- Update to r53061
[reactos.git] / drivers / filesystems / cdfs / finfo.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2004 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/fs/cdfs/finfo.c
24 * PURPOSE: CDROM (ISO 9660) filesystem driver
25 * PROGRAMMER: Art Yerkes
26 * Eric Kohl
27 * UPDATE HISTORY:
28 */
29
30 /* INCLUDES *****************************************************************/
31
32 #include "cdfs.h"
33
34 #define NDEBUG
35 #include <debug.h>
36
37 /* FUNCTIONS ****************************************************************/
38
39 /*
40 * FUNCTION: Retrieve the standard file information
41 */
42 static NTSTATUS
43 CdfsGetStandardInformation(PFCB Fcb,
44 PDEVICE_OBJECT DeviceObject,
45 PFILE_STANDARD_INFORMATION StandardInfo,
46 PULONG BufferLength)
47 {
48 DPRINT("CdfsGetStandardInformation() called\n");
49
50 if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
51 return STATUS_BUFFER_OVERFLOW;
52
53 /* PRECONDITION */
54 ASSERT(StandardInfo != NULL);
55 ASSERT(Fcb != NULL);
56
57 RtlZeroMemory(StandardInfo,
58 sizeof(FILE_STANDARD_INFORMATION));
59
60 if (CdfsFCBIsDirectory(Fcb))
61 {
62 StandardInfo->AllocationSize.QuadPart = 0LL;
63 StandardInfo->EndOfFile.QuadPart = 0LL;
64 StandardInfo->Directory = TRUE;
65 }
66 else
67 {
68 StandardInfo->AllocationSize = Fcb->RFCB.AllocationSize;
69 StandardInfo->EndOfFile = Fcb->RFCB.FileSize;
70 StandardInfo->Directory = FALSE;
71 }
72 StandardInfo->NumberOfLinks = 0;
73 StandardInfo->DeletePending = FALSE;
74
75 *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
76 return(STATUS_SUCCESS);
77 }
78
79
80 /*
81 * FUNCTION: Retrieve the file position information
82 */
83 static NTSTATUS
84 CdfsGetPositionInformation(PFILE_OBJECT FileObject,
85 PFILE_POSITION_INFORMATION PositionInfo,
86 PULONG BufferLength)
87 {
88 DPRINT("CdfsGetPositionInformation() called\n");
89
90 if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
91 return STATUS_BUFFER_OVERFLOW;
92
93 PositionInfo->CurrentByteOffset.QuadPart =
94 FileObject->CurrentByteOffset.QuadPart;
95
96 DPRINT("Getting position %I64x\n",
97 PositionInfo->CurrentByteOffset.QuadPart);
98
99 *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
100 return(STATUS_SUCCESS);
101 }
102
103
104 /*
105 * FUNCTION: Retrieve the basic file information
106 */
107 static NTSTATUS
108 CdfsGetBasicInformation(PFILE_OBJECT FileObject,
109 PFCB Fcb,
110 PDEVICE_OBJECT DeviceObject,
111 PFILE_BASIC_INFORMATION BasicInfo,
112 PULONG BufferLength)
113 {
114 DPRINT("CdfsGetBasicInformation() called\n");
115
116 if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
117 return STATUS_BUFFER_OVERFLOW;
118
119 CdfsDateTimeToSystemTime(Fcb,
120 &BasicInfo->CreationTime);
121 CdfsDateTimeToSystemTime(Fcb,
122 &BasicInfo->LastAccessTime);
123 CdfsDateTimeToSystemTime(Fcb,
124 &BasicInfo->LastWriteTime);
125 CdfsDateTimeToSystemTime(Fcb,
126 &BasicInfo->ChangeTime);
127
128 CdfsFileFlagsToAttributes(Fcb,
129 &BasicInfo->FileAttributes);
130
131 *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
132
133 return(STATUS_SUCCESS);
134 }
135
136
137 /*
138 * FUNCTION: Retrieve the file name information
139 */
140 static NTSTATUS
141 CdfsGetNameInformation(PFILE_OBJECT FileObject,
142 PFCB Fcb,
143 PDEVICE_OBJECT DeviceObject,
144 PFILE_NAME_INFORMATION NameInfo,
145 PULONG BufferLength)
146 {
147 ULONG NameLength;
148 ULONG BytesToCopy;
149
150 DPRINT("CdfsGetNameInformation() called\n");
151
152 ASSERT(NameInfo != NULL);
153 ASSERT(Fcb != NULL);
154
155 /* If buffer can't hold at least the file name length, bail out */
156 if (*BufferLength < (ULONG)FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
157 return STATUS_BUFFER_OVERFLOW;
158
159 /* Calculate file name length in bytes */
160 NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
161 NameInfo->FileNameLength = NameLength;
162
163 /* Calculate amount of bytes to copy not to overflow the buffer */
164 BytesToCopy = min(NameLength,
165 *BufferLength - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]));
166
167 /* Fill in the bytes */
168 RtlCopyMemory(NameInfo->FileName, Fcb->PathName, BytesToCopy);
169
170 /* Check if we could write more but are not able to */
171 if (*BufferLength < NameLength + FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]))
172 {
173 /* Return number of bytes written */
174 *BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + BytesToCopy;
175 return STATUS_BUFFER_OVERFLOW;
176 }
177
178 /* We filled up as many bytes, as needed */
179 *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + NameLength);
180
181 return STATUS_SUCCESS;
182 }
183
184
185 /*
186 * FUNCTION: Retrieve the internal file information
187 */
188 static NTSTATUS
189 CdfsGetInternalInformation(PFCB Fcb,
190 PFILE_INTERNAL_INFORMATION InternalInfo,
191 PULONG BufferLength)
192 {
193 DPRINT("CdfsGetInternalInformation() called\n");
194
195 ASSERT(InternalInfo);
196 ASSERT(Fcb);
197
198 if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
199 return(STATUS_BUFFER_OVERFLOW);
200
201 InternalInfo->IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart;
202
203 *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
204
205 return(STATUS_SUCCESS);
206 }
207
208
209 /*
210 * FUNCTION: Retrieve the file network open information
211 */
212 static NTSTATUS
213 CdfsGetNetworkOpenInformation(PFCB Fcb,
214 PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
215 PULONG BufferLength)
216 {
217 ASSERT(NetworkInfo);
218 ASSERT(Fcb);
219
220 if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
221 return(STATUS_BUFFER_OVERFLOW);
222
223 CdfsDateTimeToSystemTime(Fcb,
224 &NetworkInfo->CreationTime);
225 CdfsDateTimeToSystemTime(Fcb,
226 &NetworkInfo->LastAccessTime);
227 CdfsDateTimeToSystemTime(Fcb,
228 &NetworkInfo->LastWriteTime);
229 CdfsDateTimeToSystemTime(Fcb,
230 &NetworkInfo->ChangeTime);
231 if (CdfsFCBIsDirectory(Fcb))
232 {
233 NetworkInfo->AllocationSize.QuadPart = 0LL;
234 NetworkInfo->EndOfFile.QuadPart = 0LL;
235 }
236 else
237 {
238 NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
239 NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
240 }
241 CdfsFileFlagsToAttributes(Fcb,
242 &NetworkInfo->FileAttributes);
243
244 *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
245
246 return(STATUS_SUCCESS);
247 }
248
249
250 /*
251 * FUNCTION: Retrieve all file information
252 */
253 static NTSTATUS
254 CdfsGetAllInformation(PFILE_OBJECT FileObject,
255 PFCB Fcb,
256 PFILE_ALL_INFORMATION Info,
257 PULONG BufferLength)
258 {
259 ULONG NameLength;
260
261 ASSERT(Info);
262 ASSERT(Fcb);
263
264 NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
265 if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength)
266 return(STATUS_BUFFER_OVERFLOW);
267
268 /* Basic Information */
269 CdfsDateTimeToSystemTime(Fcb,
270 &Info->BasicInformation.CreationTime);
271 CdfsDateTimeToSystemTime(Fcb,
272 &Info->BasicInformation.LastAccessTime);
273 CdfsDateTimeToSystemTime(Fcb,
274 &Info->BasicInformation.LastWriteTime);
275 CdfsDateTimeToSystemTime(Fcb,
276 &Info->BasicInformation.ChangeTime);
277 CdfsFileFlagsToAttributes(Fcb,
278 &Info->BasicInformation.FileAttributes);
279
280 /* Standard Information */
281 if (CdfsFCBIsDirectory(Fcb))
282 {
283 Info->StandardInformation.AllocationSize.QuadPart = 0LL;
284 Info->StandardInformation.EndOfFile.QuadPart = 0LL;
285 Info->StandardInformation.Directory = TRUE;
286 }
287 else
288 {
289 Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize;
290 Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize;
291 Info->StandardInformation.Directory = FALSE;
292 }
293 Info->StandardInformation.NumberOfLinks = 0;
294 Info->StandardInformation.DeletePending = FALSE;
295
296 /* Internal Information */
297 Info->InternalInformation.IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart;
298
299 /* EA Information */
300 Info->EaInformation.EaSize = 0;
301
302 /* Access Information */
303 /* The IO-Manager adds this information */
304
305 /* Position Information */
306 Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart;
307
308 /* Mode Information */
309 /* The IO-Manager adds this information */
310
311 /* Alignment Information */
312 /* The IO-Manager adds this information */
313
314 /* Name Information */
315 Info->NameInformation.FileNameLength = NameLength;
316 RtlCopyMemory(Info->NameInformation.FileName,
317 Fcb->PathName,
318 NameLength + sizeof(WCHAR));
319
320 *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR));
321
322 return STATUS_SUCCESS;
323 }
324
325
326 /*
327 * FUNCTION: Retrieve the specified file information
328 */
329 NTSTATUS NTAPI
330 CdfsQueryInformation(PDEVICE_OBJECT DeviceObject,
331 PIRP Irp)
332 {
333 FILE_INFORMATION_CLASS FileInformationClass;
334 PIO_STACK_LOCATION Stack;
335 PFILE_OBJECT FileObject;
336 PFCB Fcb;
337 PVOID SystemBuffer;
338 ULONG BufferLength;
339
340 NTSTATUS Status = STATUS_SUCCESS;
341
342 DPRINT("CdfsQueryInformation() called\n");
343
344 Stack = IoGetCurrentIrpStackLocation(Irp);
345 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
346 FileObject = Stack->FileObject;
347 Fcb = FileObject->FsContext;
348
349 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
350 BufferLength = Stack->Parameters.QueryFile.Length;
351
352 switch (FileInformationClass)
353 {
354 case FileStandardInformation:
355 Status = CdfsGetStandardInformation(Fcb,
356 DeviceObject,
357 SystemBuffer,
358 &BufferLength);
359 break;
360
361 case FilePositionInformation:
362 Status = CdfsGetPositionInformation(FileObject,
363 SystemBuffer,
364 &BufferLength);
365 break;
366
367 case FileBasicInformation:
368 Status = CdfsGetBasicInformation(FileObject,
369 Fcb,
370 DeviceObject,
371 SystemBuffer,
372 &BufferLength);
373 break;
374
375 case FileNameInformation:
376 Status = CdfsGetNameInformation(FileObject,
377 Fcb,
378 DeviceObject,
379 SystemBuffer,
380 &BufferLength);
381 break;
382
383 case FileInternalInformation:
384 Status = CdfsGetInternalInformation(Fcb,
385 SystemBuffer,
386 &BufferLength);
387 break;
388
389 case FileNetworkOpenInformation:
390 Status = CdfsGetNetworkOpenInformation(Fcb,
391 SystemBuffer,
392 &BufferLength);
393 break;
394
395 case FileAllInformation:
396 Status = CdfsGetAllInformation(FileObject,
397 Fcb,
398 SystemBuffer,
399 &BufferLength);
400 break;
401
402 case FileAlternateNameInformation:
403 Status = STATUS_NOT_IMPLEMENTED;
404 break;
405
406 default:
407 DPRINT("Unimplemented information class %u\n", FileInformationClass);
408 Status = STATUS_INVALID_PARAMETER;
409 break;
410 }
411
412 Irp->IoStatus.Status = Status;
413 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
414 Irp->IoStatus.Information =
415 Stack->Parameters.QueryFile.Length - BufferLength;
416 else
417 Irp->IoStatus.Information = 0;
418
419 IoCompleteRequest(Irp, IO_NO_INCREMENT);
420
421 return(Status);
422 }
423
424
425 /*
426 * FUNCTION: Set the file position information
427 */
428 static NTSTATUS
429 CdfsSetPositionInformation(PFILE_OBJECT FileObject,
430 PFILE_POSITION_INFORMATION PositionInfo)
431 {
432 DPRINT ("CdfsSetPositionInformation()\n");
433
434 DPRINT ("PositionInfo %x\n", PositionInfo);
435 DPRINT ("Setting position %I64u\n", PositionInfo->CurrentByteOffset.QuadPart);
436
437 FileObject->CurrentByteOffset.QuadPart =
438 PositionInfo->CurrentByteOffset.QuadPart;
439
440 return STATUS_SUCCESS;
441 }
442
443
444 /*
445 * FUNCTION: Set the specified file information
446 */
447 NTSTATUS NTAPI
448 CdfsSetInformation(PDEVICE_OBJECT DeviceObject,
449 PIRP Irp)
450 {
451 FILE_INFORMATION_CLASS FileInformationClass;
452 PIO_STACK_LOCATION Stack;
453 PFILE_OBJECT FileObject;
454 PFCB Fcb;
455 PVOID SystemBuffer;
456
457 NTSTATUS Status = STATUS_SUCCESS;
458
459 DPRINT("CdfsSetInformation() called\n");
460
461 Stack = IoGetCurrentIrpStackLocation(Irp);
462 FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
463 FileObject = Stack->FileObject;
464 Fcb = FileObject->FsContext;
465
466 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
467
468 switch (FileInformationClass)
469 {
470 case FilePositionInformation:
471 Status = CdfsSetPositionInformation(FileObject,
472 SystemBuffer);
473 break;
474
475 case FileBasicInformation:
476 case FileRenameInformation:
477 Status = STATUS_NOT_IMPLEMENTED;
478 break;
479
480 default:
481 Status = STATUS_NOT_SUPPORTED;
482 break;
483 }
484
485 Irp->IoStatus.Status = Status;
486 Irp->IoStatus.Information = 0;
487
488 IoCompleteRequest(Irp, IO_NO_INCREMENT);
489
490 return Status;
491 }
492
493 /* EOF */