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