xref: /reactos/drivers/filesystems/cdfs/fileinfo.c (revision 40462c92)
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7     FileInfo.c
8 
9 Abstract:
10 
11     This module implements the File Information routines for Cdfs called by
12     the Fsd/Fsp dispatch drivers.
13 
14 
15 --*/
16 
17 #include "cdprocs.h"
18 
19 //
20 //  The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId                   (CDFS_BUG_CHECK_FILEINFO)
24 
25 //
26 //  Local support routines
27 //
28 
29 VOID
30 CdQueryBasicInfo (
31     _In_ PIRP_CONTEXT IrpContext,
32     _In_ PFCB Fcb,
33     _Out_ PFILE_BASIC_INFORMATION Buffer,
34     _Inout_ PULONG Length
35     );
36 
37 VOID
38 CdQueryStandardInfo (
39     _In_ PIRP_CONTEXT IrpContext,
40     _In_ PFCB Fcb,
41     _Out_ PFILE_STANDARD_INFORMATION Buffer,
42     _Inout_ PULONG Length
43     );
44 
45 VOID
46 CdQueryInternalInfo (
47     _In_ PIRP_CONTEXT IrpContext,
48     _In_ PFCB Fcb,
49     _Out_ PFILE_INTERNAL_INFORMATION Buffer,
50     _Inout_ PULONG Length
51     );
52 
53 VOID
54 CdQueryEaInfo (
55     _In_ PIRP_CONTEXT IrpContext,
56     _In_ PFCB Fcb,
57     _Out_ PFILE_EA_INFORMATION Buffer,
58     _Inout_ PULONG Length
59     );
60 
61 VOID
62 CdQueryPositionInfo (
63     _In_ PIRP_CONTEXT IrpContext,
64     _In_ PFILE_OBJECT FileObject,
65     _Out_ PFILE_POSITION_INFORMATION Buffer,
66     _Inout_ PULONG Length
67     );
68 
69 NTSTATUS
70 CdQueryNameInfo (
71     _In_ PIRP_CONTEXT IrpContext,
72     _In_ PFILE_OBJECT FileObject,
73     _Out_ PFILE_NAME_INFORMATION Buffer,
74     _Inout_ PULONG Length
75     );
76 
77 _Requires_lock_held_(_Global_critical_region_)
78 NTSTATUS
79 CdQueryAlternateNameInfo (
80     _In_ PIRP_CONTEXT IrpContext,
81     _In_ PFCB Fcb,
82     _In_ PCCB Ccb,
83     _Out_ PFILE_NAME_INFORMATION Buffer,
84     _Inout_ PULONG Length
85     );
86 
87 VOID
88 CdQueryNetworkInfo (
89     _In_ PIRP_CONTEXT IrpContext,
90     _In_ PFCB Fcb,
91     _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
92     _Inout_ PULONG Length
93     );
94 
95 #ifdef ALLOC_PRAGMA
96 #pragma alloc_text(PAGE, CdCommonQueryInfo)
97 #pragma alloc_text(PAGE, CdCommonSetInfo)
98 #pragma alloc_text(PAGE, CdFastQueryBasicInfo)
99 #pragma alloc_text(PAGE, CdFastQueryStdInfo)
100 #pragma alloc_text(PAGE, CdFastQueryNetworkInfo)
101 #pragma alloc_text(PAGE, CdQueryAlternateNameInfo)
102 #pragma alloc_text(PAGE, CdQueryBasicInfo)
103 #pragma alloc_text(PAGE, CdQueryEaInfo)
104 #pragma alloc_text(PAGE, CdQueryInternalInfo)
105 #pragma alloc_text(PAGE, CdQueryNameInfo)
106 #pragma alloc_text(PAGE, CdQueryNetworkInfo)
107 #pragma alloc_text(PAGE, CdQueryPositionInfo)
108 #pragma alloc_text(PAGE, CdQueryStandardInfo)
109 #endif
110 
111 
112 _Requires_lock_held_(_Global_critical_region_)
113 NTSTATUS
114 CdCommonQueryInfo (
115     _Inout_ PIRP_CONTEXT IrpContext,
116     _Inout_ PIRP Irp
117     )
118 
119 /*++
120 
121 Routine Description:
122 
123     This is the common routine for query file information called by both the
124     fsd and fsp threads.
125 
126 Arguments:
127 
128     Irp - Supplies the Irp to process.
129 
130 Return Value:
131 
132     NTSTATUS - The return status for this operation.
133 
134 --*/
135 
136 {
137     NTSTATUS Status = STATUS_SUCCESS;
138     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
139 
140     ULONG Length;
141     FILE_INFORMATION_CLASS FileInformationClass;
142     PFILE_ALL_INFORMATION Buffer;
143 
144     TYPE_OF_OPEN TypeOfOpen;
145     PFCB Fcb;
146     PCCB Ccb;
147 
148     BOOLEAN ReleaseFcb = FALSE;
149 
150     PAGED_CODE();
151 
152     //
153     //  Reference our input parameters to make things easier
154     //
155 
156     Length = IrpSp->Parameters.QueryFile.Length;
157     FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
158     Buffer = Irp->AssociatedIrp.SystemBuffer;
159 
160     //
161     //  Decode the file object
162     //
163 
164     TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
165 
166     //
167     //  Use a try-finally to facilitate cleanup.
168     //
169 
170     _SEH2_TRY {
171 
172         //
173         //  We only support query on file and directory handles.
174         //
175 
176         switch (TypeOfOpen) {
177 
178         case UserDirectoryOpen :
179         case UserFileOpen :
180 
181             //
182             //  Acquire shared access to this file.  NOTE that this could be
183             //  a recursive acquire,  if we already preacquired in
184             //  CdAcquireForCreateSection().
185             //
186 
187             CdAcquireFileShared( IrpContext, Fcb );
188             ReleaseFcb = TRUE;
189 
190             //
191             //  Make sure we have the correct sizes for a directory.
192             //
193 
194             if (!FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED )) {
195 
196                 NT_ASSERT( TypeOfOpen == UserDirectoryOpen );
197                 CdVerifyOrCreateDirStreamFile( IrpContext, Fcb);
198             }
199 
200             //
201             //  Make sure the Fcb is in a usable condition.  This will raise
202             //  an error condition if the volume is unusable
203             //
204 
205             CdVerifyFcbOperation( IrpContext, Fcb );
206 
207             //
208             //  Based on the information class we'll do different
209             //  actions.  Each of hte procedures that we're calling fills
210             //  up the output buffer, if possible.  They will raise the
211             //  status STATUS_BUFFER_OVERFLOW for an insufficient buffer.
212             //  This is considered a somewhat unusual case and is handled
213             //  more cleanly with the exception mechanism rather than
214             //  testing a return status value for each call.
215             //
216 
217             switch (FileInformationClass) {
218 
219             case FileAllInformation:
220 
221                 //
222                 //  We don't allow this operation on a file opened by file Id.
223                 //
224 
225                 if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
226 
227                     Status = STATUS_INVALID_PARAMETER;
228                     break;
229                 }
230 
231                 //
232                 //  In this case go ahead and call the individual routines to
233                 //  fill in the buffer.  Only the name routine will
234                 //  pointer to the output buffer and then call the
235                 //  individual routines to fill in the buffer.
236                 //
237 
238                 Length -= (sizeof( FILE_ACCESS_INFORMATION ) +
239                            sizeof( FILE_MODE_INFORMATION ) +
240                            sizeof( FILE_ALIGNMENT_INFORMATION ));
241 
242                 CdQueryBasicInfo( IrpContext, Fcb, &Buffer->BasicInformation, &Length );
243                 CdQueryStandardInfo( IrpContext, Fcb, &Buffer->StandardInformation, &Length );
244                 CdQueryInternalInfo( IrpContext, Fcb, &Buffer->InternalInformation, &Length );
245                 CdQueryEaInfo( IrpContext, Fcb, &Buffer->EaInformation, &Length );
246                 CdQueryPositionInfo( IrpContext, IrpSp->FileObject, &Buffer->PositionInformation, &Length );
247                 Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, &Buffer->NameInformation, &Length );
248 
249                 break;
250 
251             case FileBasicInformation:
252 
253                 CdQueryBasicInfo( IrpContext, Fcb, (PFILE_BASIC_INFORMATION) Buffer, &Length );
254                 break;
255 
256             case FileStandardInformation:
257 
258                 CdQueryStandardInfo( IrpContext, Fcb, (PFILE_STANDARD_INFORMATION) Buffer, &Length );
259                 break;
260 
261             case FileInternalInformation:
262 
263                 CdQueryInternalInfo( IrpContext, Fcb, (PFILE_INTERNAL_INFORMATION) Buffer, &Length );
264                 break;
265 
266             case FileEaInformation:
267 
268                 CdQueryEaInfo( IrpContext, Fcb, (PFILE_EA_INFORMATION) Buffer, &Length );
269                 break;
270 
271             case FilePositionInformation:
272 
273                 CdQueryPositionInfo( IrpContext, IrpSp->FileObject, (PFILE_POSITION_INFORMATION) Buffer, &Length );
274                 break;
275 
276             case FileNameInformation:
277 
278                 //
279                 //  We don't allow this operation on a file opened by file Id.
280                 //
281 
282                 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
283 
284                     Status = CdQueryNameInfo( IrpContext, IrpSp->FileObject, (PFILE_NAME_INFORMATION) Buffer, &Length );
285 
286                 } else {
287 
288                     Status = STATUS_INVALID_PARAMETER;
289                 }
290 
291                 break;
292 
293             case FileAlternateNameInformation:
294 
295                 if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_BY_ID )) {
296 
297                     Status = CdQueryAlternateNameInfo( IrpContext, Fcb, Ccb, (PFILE_NAME_INFORMATION) Buffer, &Length );
298 
299                 } else {
300 
301                     Status = STATUS_INVALID_PARAMETER;
302                 }
303 
304                 break;
305 
306             case FileNetworkOpenInformation:
307 
308                 CdQueryNetworkInfo( IrpContext, Fcb, (PFILE_NETWORK_OPEN_INFORMATION) Buffer, &Length );
309                 break;
310 
311             default :
312 
313                 Status = STATUS_INVALID_PARAMETER;
314             }
315 
316             break;
317 
318         default :
319 
320             Status = STATUS_INVALID_PARAMETER;
321         }
322 
323         //
324         //  Set the information field to the number of bytes actually filled in
325         //  and then complete the request
326         //
327 
328         Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
329 
330     } _SEH2_FINALLY {
331 
332         //
333         //  Release the file.
334         //
335 
336         if (ReleaseFcb) {
337 
338             CdReleaseFile( IrpContext, Fcb );
339         }
340     } _SEH2_END;
341 
342     //
343     //  Complete the request if we didn't raise.
344     //
345 
346     CdCompleteRequest( IrpContext, Irp, Status );
347 
348     return Status;
349 }
350 
351 
352 _Requires_lock_held_(_Global_critical_region_)
353 NTSTATUS
354 CdCommonSetInfo (
355     _Inout_ PIRP_CONTEXT IrpContext,
356     _Inout_ PIRP Irp
357     )
358 
359 /*++
360 
361 Routine Description:
362 
363     This is the common routine for set file information called by both the
364     fsd and fsp threads.  We only support operations which set the file position.
365 
366 Arguments:
367 
368     Irp - Supplies the Irp to process.
369 
370 Return Value:
371 
372     NTSTATUS - The return status for this operation.
373 
374 --*/
375 
376 {
377     NTSTATUS Status = STATUS_INVALID_PARAMETER;
378 
379     TYPE_OF_OPEN TypeOfOpen;
380     PFCB Fcb;
381     PCCB Ccb;
382 
383     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
384 
385     PFILE_POSITION_INFORMATION Buffer;
386 
387     PAGED_CODE();
388 
389     //
390     //  Decode the file object
391     //
392 
393     TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb );
394 
395     //
396     //  We only support a SetPositionInformation on a user file.
397     //
398 
399     if ((TypeOfOpen != UserFileOpen) ||
400         (IrpSp->Parameters.QueryFile.FileInformationClass != FilePositionInformation)) {
401 
402         CdCompleteRequest( IrpContext, Irp, Status );
403         return Status;
404     }
405 
406     //
407     //  Acquire shared access to this file.
408     //
409 
410     CdAcquireFileShared( IrpContext, Fcb );
411 
412     _SEH2_TRY {
413 
414         //
415         //  Make sure the Fcb is in a usable condition.  This
416         //  will raise an error condition if the fcb is unusable
417         //
418 
419         CdVerifyFcbOperation( IrpContext, Fcb );
420 
421         Buffer = Irp->AssociatedIrp.SystemBuffer;
422 
423         //
424         //  Check if the file does not use intermediate buffering.  If it
425         //  does not use intermediate buffering then the new position we're
426         //  supplied must be aligned properly for the device
427         //
428 
429         if (FlagOn( IrpSp->FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING ) &&
430             ((Buffer->CurrentByteOffset.LowPart & Fcb->Vcb->BlockMask) != 0)) {
431 
432             try_return( NOTHING );
433         }
434 
435         //
436         //  The input parameter is fine so set the current byte offset and
437         //  complete the request
438         //
439 
440         //
441         //  Lock the Fcb to provide synchronization.
442         //
443 
444         CdLockFcb( IrpContext, Fcb );
445         IrpSp->FileObject->CurrentByteOffset = Buffer->CurrentByteOffset;
446         CdUnlockFcb( IrpContext, Fcb );
447 
448         Status = STATUS_SUCCESS;
449 
450     try_exit: NOTHING;
451     } _SEH2_FINALLY {
452 
453         CdReleaseFile( IrpContext, Fcb );
454     } _SEH2_END;
455 
456     //
457     //  Complete the request if there was no raise.
458     //
459 
460     CdCompleteRequest( IrpContext, Irp, Status );
461     return Status;
462 }
463 
464 
465 _Function_class_(FAST_IO_QUERY_BASIC_INFO)
466 _IRQL_requires_same_
467 _Success_(return != FALSE)
468 BOOLEAN
469 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
470 CdFastQueryBasicInfo (
471     _In_ PFILE_OBJECT FileObject,
472     _In_ BOOLEAN Wait,
473     _Out_ PFILE_BASIC_INFORMATION Buffer,
474     _Out_ PIO_STATUS_BLOCK IoStatus,
475     _In_ PDEVICE_OBJECT DeviceObject
476     )
477 
478 /*++
479 
480 Routine Description:
481 
482     This routine is for the fast query call for basic file information.
483 
484 Arguments:
485 
486     FileObject - Supplies the file object used in this operation
487 
488     Wait - Indicates if we are allowed to wait for the information
489 
490     Buffer - Supplies the output buffer to receive the basic information
491 
492     IoStatus - Receives the final status of the operation
493 
494 Return Value:
495 
496     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
497         needs to take the long route.
498 
499 --*/
500 
501 {
502     BOOLEAN Result = FALSE;
503     TYPE_OF_OPEN TypeOfOpen;
504 
505     PFCB Fcb;
506 
507     PAGED_CODE();
508 
509     UNREFERENCED_PARAMETER( DeviceObject );
510 
511     ASSERT_FILE_OBJECT( FileObject );
512 
513     FsRtlEnterFileSystem();
514 
515     //
516     //  Decode the file object to find the type of open and the data
517     //  structures.
518     //
519 
520     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
521 
522     //
523     //  We only support this request on user file or directory objects.
524     //
525 
526     if ((TypeOfOpen != UserFileOpen) &&
527         ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
528 
529         FsRtlExitFileSystem();
530         return FALSE;
531     }
532 
533     //
534     //  Acquire the file shared to access the Fcb.
535     //
536 
537     if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
538 
539         FsRtlExitFileSystem();
540         return FALSE;
541     }
542 
543     //
544     //  Use a try-finally to facilitate cleanup.
545     //
546 
547     _SEH2_TRY {
548 
549         //
550         //  Only deal with 'good' Fcb's.
551         //
552 
553         if (CdVerifyFcbOperation( NULL, Fcb )) {
554 
555             //
556             //  Fill in the input buffer from the Fcb fields.
557             //
558 
559             Buffer->CreationTime.QuadPart =
560             Buffer->LastWriteTime.QuadPart =
561             Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
562 
563             Buffer->LastAccessTime.QuadPart = 0;
564 
565             Buffer->FileAttributes = Fcb->FileAttributes;
566 
567             //
568             //  Update the IoStatus block with the size of this data.
569             //
570 
571             IoStatus->Status = STATUS_SUCCESS;
572             IoStatus->Information = sizeof( FILE_BASIC_INFORMATION );
573 
574             Result = TRUE;
575         }
576 
577     } _SEH2_FINALLY {
578 
579         ExReleaseResourceLite( Fcb->Resource );
580 
581         FsRtlExitFileSystem();
582     } _SEH2_END;
583 
584     return Result;
585 }
586 
587 
588 _Function_class_(FAST_IO_QUERY_STANDARD_INFO)
589 _IRQL_requires_same_
590 _Success_(return != FALSE)
591 BOOLEAN
592 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
593 CdFastQueryStdInfo (
594     _In_ PFILE_OBJECT FileObject,
595     _In_ BOOLEAN Wait,
596     _Out_ PFILE_STANDARD_INFORMATION Buffer,
597     _Out_ PIO_STATUS_BLOCK IoStatus,
598     _In_ PDEVICE_OBJECT DeviceObject
599     )
600 
601 /*++
602 
603 Routine Description:
604 
605     This routine is for the fast query call for standard file information.
606 
607 Arguments:
608 
609     FileObject - Supplies the file object used in this operation
610 
611     Wait - Indicates if we are allowed to wait for the information
612 
613     Buffer - Supplies the output buffer to receive the basic information
614 
615     IoStatus - Receives the final status of the operation
616 
617 Return Value:
618 
619     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
620         needs to take the long route.
621 
622 --*/
623 
624 {
625     BOOLEAN Result = FALSE;
626     TYPE_OF_OPEN TypeOfOpen;
627 
628     PFCB Fcb;
629 
630     PAGED_CODE();
631 
632     UNREFERENCED_PARAMETER( DeviceObject );
633 
634     ASSERT_FILE_OBJECT( FileObject );
635 
636     FsRtlEnterFileSystem();
637 
638     //
639     //  Decode the file object to find the type of open and the data
640     //  structures.
641     //
642 
643     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
644 
645     //
646     //  We only support this request on initialized user file or directory objects.
647     //
648 
649     if ((TypeOfOpen != UserFileOpen) &&
650         ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED ))) {
651 
652         FsRtlExitFileSystem();
653         return FALSE;
654     }
655 
656     //
657     //  Acquire the file shared to access the Fcb.
658     //
659 
660     if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
661 
662         FsRtlExitFileSystem();
663         return FALSE;
664     }
665 
666     //
667     //  Use a try-finally to facilitate cleanup.
668     //
669 
670     _SEH2_TRY {
671 
672         //
673         //  Only deal with 'good' Fcb's.
674         //
675 
676         if (CdVerifyFcbOperation( NULL, Fcb )) {
677 
678             //
679             //  Check whether this is a directory.
680             //
681 
682             if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
683 
684                 Buffer->AllocationSize.QuadPart =
685                 Buffer->EndOfFile.QuadPart = 0;
686 
687                 Buffer->Directory = TRUE;
688 
689             } else {
690 
691                 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
692                 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
693 
694                 Buffer->Directory = FALSE;
695             }
696 
697             Buffer->NumberOfLinks = 1;
698             Buffer->DeletePending = FALSE;
699 
700             //
701             //  Update the IoStatus block with the size of this data.
702             //
703 
704             IoStatus->Status = STATUS_SUCCESS;
705             IoStatus->Information = sizeof( FILE_STANDARD_INFORMATION );
706 
707             Result = TRUE;
708         }
709 
710     } _SEH2_FINALLY {
711 
712         ExReleaseResourceLite( Fcb->Resource );
713 
714         FsRtlExitFileSystem();
715     } _SEH2_END;
716 
717     return Result;
718 }
719 
720 
721 _Function_class_(FAST_IO_QUERY_NETWORK_OPEN_INFO)
722 _IRQL_requires_same_
723 _Success_(return != FALSE)
724 BOOLEAN
725 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
726 CdFastQueryNetworkInfo (
727     _In_ PFILE_OBJECT FileObject,
728     _In_ BOOLEAN Wait,
729     _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
730     _Out_ PIO_STATUS_BLOCK IoStatus,
731     _In_ PDEVICE_OBJECT DeviceObject
732     )
733 
734 /*++
735 
736 Routine Description:
737 
738     This routine is for the fast query call for network file information.
739 
740 Arguments:
741 
742     FileObject - Supplies the file object used in this operation
743 
744     Wait - Indicates if we are allowed to wait for the information
745 
746     Buffer - Supplies the output buffer to receive the basic information
747 
748     IoStatus - Receives the final status of the operation
749 
750 Return Value:
751 
752     BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
753         needs to take the long route.
754 
755 --*/
756 
757 {
758     BOOLEAN Result = FALSE;
759     TYPE_OF_OPEN TypeOfOpen;
760 
761     PFCB Fcb;
762 
763     PAGED_CODE();
764 
765     UNREFERENCED_PARAMETER( DeviceObject );
766 
767     ASSERT_FILE_OBJECT( FileObject );
768 
769     FsRtlEnterFileSystem();
770 
771     //
772     //  Decode the file object to find the type of open and the data
773     //  structures.
774     //
775 
776     TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb );
777 
778     //
779     //  We only support this request on user file or directory objects.
780     //
781 
782     if ((TypeOfOpen != UserFileOpen) &&
783         ((TypeOfOpen != UserDirectoryOpen) || !FlagOn( Fcb->FcbState, FCB_STATE_INITIALIZED))) {
784 
785         FsRtlExitFileSystem();
786         return FALSE;
787     }
788 
789     //
790     //  Acquire the file shared to access the Fcb.
791     //
792 
793     if (!ExAcquireResourceSharedLite( Fcb->Resource, Wait )) {
794 
795         FsRtlExitFileSystem();
796         return FALSE;
797     }
798 
799     //
800     //  Use a try-finally to facilitate cleanup.
801     //
802 
803     _SEH2_TRY {
804 
805         //
806         //  Only deal with 'good' Fcb's.
807         //
808 
809         if (CdVerifyFcbOperation( NULL, Fcb )) {
810 
811             //
812             //  Fill in the input buffer from the Fcb fields.
813             //
814 
815             Buffer->CreationTime.QuadPart =
816             Buffer->LastWriteTime.QuadPart =
817             Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
818 
819             Buffer->LastAccessTime.QuadPart = 0;
820 
821             Buffer->FileAttributes = Fcb->FileAttributes;
822 
823             //
824             //  Check whether this is a directory.
825             //
826 
827             if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
828 
829                 Buffer->AllocationSize.QuadPart =
830                 Buffer->EndOfFile.QuadPart = 0;
831 
832             } else {
833 
834                 Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
835                 Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
836             }
837 
838             //
839             //  Update the IoStatus block with the size of this data.
840             //
841 
842             IoStatus->Status = STATUS_SUCCESS;
843             IoStatus->Information = sizeof( FILE_NETWORK_OPEN_INFORMATION );
844 
845             Result = TRUE;
846         }
847 
848     } _SEH2_FINALLY {
849 
850         ExReleaseResourceLite( Fcb->Resource );
851 
852         FsRtlExitFileSystem();
853     } _SEH2_END;
854 
855     return Result;
856 }
857 
858 
859 //
860 //  Local support routine
861 //
862 
863 VOID
864 CdQueryBasicInfo (
865     _In_ PIRP_CONTEXT IrpContext,
866     _In_ PFCB Fcb,
867     _Out_ PFILE_BASIC_INFORMATION Buffer,
868     _Inout_ PULONG Length
869     )
870 
871 /*++
872 
873  Description:
874 
875     This routine performs the query basic information function for Cdfs
876 
877 Arguments:
878 
879     Fcb - Supplies the Fcb being queried, it has been verified
880 
881     Buffer - Supplies a pointer to the buffer where the information is to
882         be returned
883 
884     Length - Supplies the length of the buffer in bytes, and receives the
885         remaining bytes free in the buffer upon return.
886 
887 Return Value:
888 
889     None
890 
891 --*/
892 
893 {
894     PAGED_CODE();
895 
896     UNREFERENCED_PARAMETER( IrpContext );
897 
898     //
899     //  We only support creation, last modify and last write times on Cdfs.
900     //
901 
902     RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
903 
904     Buffer->LastWriteTime.QuadPart =
905     Buffer->CreationTime.QuadPart =
906     Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
907 
908     Buffer->LastAccessTime.QuadPart = 0;
909 
910     Buffer->FileAttributes = Fcb->FileAttributes;
911 
912     //
913     //  Update the length and status output variables
914     //
915 
916     *Length -= sizeof( FILE_BASIC_INFORMATION );
917 
918     return;
919 }
920 
921 
922 //
923 //  Local support routine
924 //
925 
926 VOID
927 CdQueryStandardInfo (
928     _In_ PIRP_CONTEXT IrpContext,
929     _In_ PFCB Fcb,
930     _Out_ PFILE_STANDARD_INFORMATION Buffer,
931     _Inout_ PULONG Length
932     )
933 /*++
934 
935 Routine Description:
936 
937     This routine performs the query standard information function for cdfs.
938 
939 Arguments:
940 
941     Fcb - Supplies the Fcb being queried, it has been verified
942 
943     Buffer - Supplies a pointer to the buffer where the information is to
944         be returned
945 
946     Length - Supplies the length of the buffer in bytes, and receives the
947         remaining bytes free in the buffer upon return.
948 
949 Return Value:
950 
951     None
952 
953 --*/
954 
955 {
956     PAGED_CODE();
957 
958     UNREFERENCED_PARAMETER( IrpContext );
959 
960     //
961     //  There is only one link and delete is never pending on a Cdrom file.
962     //
963 
964     Buffer->NumberOfLinks = 1;
965     Buffer->DeletePending = FALSE;
966 
967     //
968     //  We get the sizes from the header.  Return a size of zero
969     //  for all directories.
970     //
971 
972     if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
973 
974         Buffer->AllocationSize.QuadPart =
975         Buffer->EndOfFile.QuadPart = 0;
976 
977         Buffer->Directory = TRUE;
978 
979     } else {
980 
981         Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
982         Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
983 
984         Buffer->Directory = FALSE;
985     }
986 
987     //
988     //  Update the length and status output variables
989     //
990 
991     *Length -= sizeof( FILE_STANDARD_INFORMATION );
992 
993     return;
994 }
995 
996 
997 //
998 //  Local support routine
999 //
1000 
1001 VOID
1002 CdQueryInternalInfo (
1003     _In_ PIRP_CONTEXT IrpContext,
1004     _In_ PFCB Fcb,
1005     _Out_ PFILE_INTERNAL_INFORMATION Buffer,
1006     _Inout_ PULONG Length
1007     )
1008 
1009 /*++
1010 
1011 Routine Description:
1012 
1013     This routine performs the query internal information function for cdfs.
1014 
1015 Arguments:
1016 
1017     Fcb - Supplies the Fcb being queried, it has been verified
1018 
1019     Buffer - Supplies a pointer to the buffer where the information is to
1020         be returned
1021 
1022     Length - Supplies the length of the buffer in bytes, and receives the
1023         remaining bytes free in the buffer upon return.
1024 
1025 Return Value:
1026 
1027     None
1028 
1029 --*/
1030 
1031 {
1032     PAGED_CODE();
1033 
1034     UNREFERENCED_PARAMETER( IrpContext );
1035 
1036     //
1037     //  Index number is the file Id number in the Fcb.
1038     //
1039 
1040     Buffer->IndexNumber = Fcb->FileId;
1041     *Length -= sizeof( FILE_INTERNAL_INFORMATION );
1042 
1043     return;
1044 }
1045 
1046 
1047 //
1048 //  Local support routine
1049 //
1050 
1051 VOID
1052 CdQueryEaInfo (
1053     _In_ PIRP_CONTEXT IrpContext,
1054     _In_ PFCB Fcb,
1055     _Out_ PFILE_EA_INFORMATION Buffer,
1056     _Inout_ PULONG Length
1057     )
1058 
1059 /*++
1060 
1061 Routine Description:
1062 
1063     This routine performs the query Ea information function for cdfs.
1064 
1065 Arguments:
1066 
1067     Fcb - Supplies the Fcb being queried, it has been verified
1068 
1069     Buffer - Supplies a pointer to the buffer where the information is to
1070         be returned
1071 
1072     Length - Supplies the length of the buffer in bytes, and receives the
1073         remaining bytes free in the buffer upon return.
1074 
1075 Return Value:
1076 
1077     None
1078 
1079 --*/
1080 
1081 {
1082     PAGED_CODE();
1083 
1084     UNREFERENCED_PARAMETER( IrpContext );
1085     UNREFERENCED_PARAMETER( Fcb );
1086 
1087     //
1088     //  No Ea's on Cdfs volumes.
1089     //
1090 
1091     Buffer->EaSize = 0;
1092     *Length -= sizeof( FILE_EA_INFORMATION );
1093 
1094     return;
1095 }
1096 
1097 
1098 //
1099 //  Local support routine
1100 //
1101 
1102 VOID
1103 CdQueryPositionInfo (
1104     _In_ PIRP_CONTEXT IrpContext,
1105     _In_ PFILE_OBJECT FileObject,
1106     _Out_ PFILE_POSITION_INFORMATION Buffer,
1107     _Inout_ PULONG Length
1108     )
1109 
1110 /*++
1111 
1112 Routine Description:
1113 
1114     This routine performs the query position information function for cdfs.
1115 
1116 Arguments:
1117 
1118     FileObject - Supplies the File object being queried
1119 
1120     Buffer - Supplies a pointer to the buffer where the information is to
1121         be returned
1122 
1123     Length - Supplies the length of the buffer in bytes, and receives the
1124         remaining bytes free in the buffer upon return.
1125 
1126 Return Value:
1127 
1128     None
1129 
1130 --*/
1131 
1132 {
1133     PAGED_CODE();
1134 
1135     UNREFERENCED_PARAMETER( IrpContext );
1136 
1137     //
1138     //  Get the current position found in the file object.
1139     //
1140 
1141     Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
1142 
1143     //
1144     //  Update the length and status output variables
1145     //
1146 
1147     *Length -= sizeof( FILE_POSITION_INFORMATION );
1148 
1149     return;
1150 }
1151 
1152 
1153 //
1154 //  Local support routine
1155 //
1156 
1157 NTSTATUS
1158 CdQueryNameInfo (
1159     _In_ PIRP_CONTEXT IrpContext,
1160     _In_ PFILE_OBJECT FileObject,
1161     _Out_ PFILE_NAME_INFORMATION Buffer,
1162     _Inout_ PULONG Length
1163     )
1164 
1165 /*++
1166 
1167 Routine Description:
1168 
1169     This routine performs the query name information function for cdfs.
1170 
1171 Arguments:
1172 
1173     FileObject - Supplies the file object containing the name.
1174 
1175     Buffer - Supplies a pointer to the buffer where the information is to
1176         be returned
1177 
1178     Length - Supplies the length of the buffer in bytes, and receives the
1179         remaining bytes free in the buffer upon return.
1180 
1181 Return Value:
1182 
1183     NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied.
1184 
1185 --*/
1186 
1187 {
1188     NTSTATUS Status = STATUS_SUCCESS;
1189     ULONG LengthToCopy;
1190 
1191     PAGED_CODE();
1192 
1193     UNREFERENCED_PARAMETER( IrpContext );
1194 
1195     NT_ASSERT(*Length >= sizeof(ULONG));
1196 
1197     //
1198     //  Simply copy the name in the file object to the user's buffer.
1199     //
1200 
1201     //
1202     //  Place the size of the filename in the user's buffer and reduce the remaining
1203     //  size to match.
1204     //
1205 
1206     Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length;
1207     *Length -= sizeof(ULONG);
1208 
1209     if (LengthToCopy > *Length) {
1210 
1211         LengthToCopy = *Length;
1212         Status = STATUS_BUFFER_OVERFLOW;
1213     }
1214 
1215     RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy );
1216 
1217     //
1218     //  Reduce the available bytes by the amount stored into this buffer.  In the overflow
1219     //  case, this simply drops to zero.  The returned filenamelength will indicate to the
1220     //  caller how much space is required.
1221     //
1222 
1223     *Length -= LengthToCopy;
1224 
1225     return Status;
1226 }
1227 
1228 
1229 //
1230 //  Local support routine
1231 //
1232 
1233 _Requires_lock_held_(_Global_critical_region_)
1234 NTSTATUS
1235 CdQueryAlternateNameInfo (
1236     _In_ PIRP_CONTEXT IrpContext,
1237     _In_ PFCB Fcb,
1238     _In_ PCCB Ccb,
1239     _Out_ PFILE_NAME_INFORMATION Buffer,
1240     _Inout_ PULONG Length
1241     )
1242 
1243 /*++
1244 
1245 Routine Description:
1246 
1247     This routine performs the query alternate name information function.
1248     We lookup the dirent for this file and then check if there is a
1249     short name.
1250 
1251 Arguments:
1252 
1253     Fcb - Supplies the Fcb being queried, it has been verified.
1254 
1255     Ccb - Ccb for this open handle.
1256 
1257     Buffer - Supplies a pointer to the buffer where the information is to
1258         be returned.
1259 
1260     Length - Supplies the length of the buffer in bytes, and receives the
1261         remaining bytes free in the buffer upon return.
1262 
1263 Return Value:
1264 
1265     NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer,
1266                STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name,
1267                STATUS_BUFFER_OVERFLOW otherwise.
1268 
1269 --*/
1270 
1271 {
1272     NTSTATUS Status = STATUS_SUCCESS;
1273 
1274     DIRENT_ENUM_CONTEXT DirContext = {0};
1275     DIRENT Dirent = {0};
1276 
1277     PUNICODE_STRING NameToUse;
1278     ULONG DirentOffset;
1279 
1280     COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
1281     FILE_ENUM_CONTEXT FileContext;
1282 
1283     PFCB ParentFcb = NULL;
1284     BOOLEAN ReleaseParentFcb = FALSE;
1285 
1286     BOOLEAN CleanupFileLookup = FALSE;
1287     BOOLEAN CleanupDirectoryLookup = FALSE;
1288 
1289     WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ];
1290     USHORT ShortNameLength;
1291 
1292     PAGED_CODE();
1293 
1294     //
1295     //  Initialize the buffer length to zero.
1296     //
1297 
1298     Buffer->FileNameLength = 0;
1299 
1300     //
1301     //  If this is the root or this file was opened using a version number then
1302     //  there is no short name.
1303     //
1304 
1305     if ((Fcb == Fcb->Vcb->RootIndexFcb) ||
1306         FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) {
1307 
1308         return STATUS_OBJECT_NAME_NOT_FOUND;
1309     }
1310 
1311     //
1312     //  Use a try-finally to cleanup the structures.
1313     //
1314 
1315     _SEH2_TRY {
1316 
1317         ParentFcb = Fcb->ParentFcb;
1318         CdAcquireFileShared( IrpContext, ParentFcb );
1319         ReleaseParentFcb = TRUE;
1320 
1321         CdVerifyOrCreateDirStreamFile( IrpContext, ParentFcb);
1322 
1323         if (CdFidIsDirectory( Fcb->FileId)) {
1324 
1325             //
1326             //  Fcb is for a directory, so we need to dig the dirent from the parent.  In
1327             //  order to do this we need to get the name of the directory from its pathtable
1328             //  entry and then search in the parent for a matching dirent.
1329             //
1330             //  This could be optimized somewhat.
1331             //
1332 
1333             CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
1334             CdInitializeFileContext( IrpContext, &FileContext );
1335 
1336             CleanupDirectoryLookup = TRUE;
1337 
1338             CdLookupPathEntry( IrpContext,
1339                                CdQueryFidPathTableOffset( Fcb->FileId ),
1340                                Fcb->Ordinal,
1341                                FALSE,
1342                                &CompoundPathEntry );
1343 
1344             CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE );
1345 
1346             if (!CdFindDirectory( IrpContext,
1347                                   ParentFcb,
1348                                   &CompoundPathEntry.PathEntry.CdCaseDirName,
1349                                   TRUE,
1350                                   &FileContext )) {
1351 
1352                 //
1353                 //  If we failed to find the child directory by name in the parent
1354                 //  something is quite wrong with this disc.
1355                 //
1356 
1357                 CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
1358             }
1359 
1360             NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName;
1361             DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset;
1362 
1363         } else {
1364 
1365             //
1366             //  Initialize the search dirent structures.
1367             //
1368 
1369             CdInitializeDirContext( IrpContext, &DirContext );
1370             CdInitializeDirent( IrpContext, &Dirent );
1371 
1372             CleanupFileLookup = TRUE;
1373 
1374             CdLookupDirent( IrpContext,
1375                             ParentFcb,
1376                             CdQueryFidDirentOffset( Fcb->FileId ),
1377                             &DirContext );
1378 
1379             CdUpdateDirentFromRawDirent( IrpContext,
1380                                          ParentFcb,
1381                                          &DirContext,
1382                                          &Dirent );
1383 
1384             //
1385             //  Now update the dirent name.
1386             //
1387 
1388             CdUpdateDirentName( IrpContext, &Dirent, TRUE );
1389 
1390             NameToUse = &Dirent.CdCaseFileName.FileName;
1391             DirentOffset = Dirent.DirentOffset;
1392         }
1393 
1394         //
1395         //  If the name is 8.3 then fail this request.
1396         //
1397 
1398         if (CdIs8dot3Name( IrpContext,
1399                            *NameToUse )) {
1400 
1401 
1402             try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
1403         }
1404 
1405         CdGenerate8dot3Name( IrpContext,
1406                              NameToUse,
1407                              DirentOffset,
1408                              ShortNameBuffer,
1409                              &ShortNameLength );
1410 
1411         //
1412         //  We now have the short name.  We have left it in Unicode form so copy it directly.
1413         //
1414 
1415         Buffer->FileNameLength = ShortNameLength;
1416 
1417         if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {
1418 
1419             Buffer->FileNameLength = *Length - sizeof( ULONG );
1420             Status = STATUS_BUFFER_OVERFLOW;
1421         }
1422 
1423         RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength );
1424 
1425     try_exit:  NOTHING;
1426     } _SEH2_FINALLY {
1427 
1428         if (CleanupFileLookup) {
1429 
1430             CdCleanupDirContext( IrpContext, &DirContext );
1431             CdCleanupDirent( IrpContext, &Dirent );/* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
1432 
1433         } else if (CleanupDirectoryLookup) {
1434 
1435             CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
1436             CdCleanupFileContext( IrpContext, &FileContext );
1437         }
1438 
1439         if (ReleaseParentFcb) {
1440 
1441             CdReleaseFile( IrpContext, ParentFcb );
1442         }
1443     } _SEH2_END;
1444 
1445     //
1446     //  Reduce the available bytes by the amount stored into this buffer.
1447     //
1448 
1449     if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
1450 
1451         *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
1452     }
1453 
1454     return Status;
1455 }
1456 
1457 
1458 //
1459 //  Local support routine
1460 //
1461 
1462 VOID
1463 CdQueryNetworkInfo (
1464     _In_ PIRP_CONTEXT IrpContext,
1465     _In_ PFCB Fcb,
1466     _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1467     _Inout_ PULONG Length
1468     )
1469 
1470 /*++
1471 
1472  Description:
1473 
1474     This routine performs the query network open information function for Cdfs
1475 
1476 Arguments:
1477 
1478     Fcb - Supplies the Fcb being queried, it has been verified
1479 
1480     Buffer - Supplies a pointer to the buffer where the information is to
1481         be returned
1482 
1483     Length - Supplies the length of the buffer in bytes, and receives the
1484         remaining bytes free in the buffer upon return.
1485 
1486 Return Value:
1487 
1488     None
1489 
1490 --*/
1491 
1492 {
1493     PAGED_CODE();
1494 
1495     UNREFERENCED_PARAMETER( IrpContext );
1496 
1497     //
1498     //  We only support creation, last modify and last write times on Cdfs.
1499     //
1500 
1501     Buffer->LastWriteTime.QuadPart =
1502     Buffer->CreationTime.QuadPart =
1503     Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
1504 
1505     Buffer->LastAccessTime.QuadPart = 0;
1506 
1507     Buffer->FileAttributes = Fcb->FileAttributes;
1508 
1509     //
1510     //  We get the sizes from the header.  Return a size of zero
1511     //  for all directories.
1512     //
1513 
1514     if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
1515 
1516         Buffer->AllocationSize.QuadPart =
1517         Buffer->EndOfFile.QuadPart = 0;
1518 
1519     } else {
1520 
1521         Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
1522         Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
1523     }
1524 
1525     //
1526     //  Update the length and status output variables
1527     //
1528 
1529     *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );
1530 
1531     return;
1532 }
1533 
1534