xref: /reactos/drivers/filesystems/cdfs/fileinfo.c (revision 279107d5)
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     Buffer->LastWriteTime.QuadPart =
903     Buffer->CreationTime.QuadPart =
904     Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
905 
906     Buffer->LastAccessTime.QuadPart = 0;
907 
908     Buffer->FileAttributes = Fcb->FileAttributes;
909 
910     //
911     //  Update the length and status output variables
912     //
913 
914     *Length -= sizeof( FILE_BASIC_INFORMATION );
915 
916     return;
917 }
918 
919 
920 //
921 //  Local support routine
922 //
923 
924 VOID
925 CdQueryStandardInfo (
926     _In_ PIRP_CONTEXT IrpContext,
927     _In_ PFCB Fcb,
928     _Out_ PFILE_STANDARD_INFORMATION Buffer,
929     _Inout_ PULONG Length
930     )
931 /*++
932 
933 Routine Description:
934 
935     This routine performs the query standard information function for cdfs.
936 
937 Arguments:
938 
939     Fcb - Supplies the Fcb being queried, it has been verified
940 
941     Buffer - Supplies a pointer to the buffer where the information is to
942         be returned
943 
944     Length - Supplies the length of the buffer in bytes, and receives the
945         remaining bytes free in the buffer upon return.
946 
947 Return Value:
948 
949     None
950 
951 --*/
952 
953 {
954     PAGED_CODE();
955 
956     UNREFERENCED_PARAMETER( IrpContext );
957 
958     //
959     //  There is only one link and delete is never pending on a Cdrom file.
960     //
961 
962     Buffer->NumberOfLinks = 1;
963     Buffer->DeletePending = FALSE;
964 
965     //
966     //  We get the sizes from the header.  Return a size of zero
967     //  for all directories.
968     //
969 
970     if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
971 
972         Buffer->AllocationSize.QuadPart =
973         Buffer->EndOfFile.QuadPart = 0;
974 
975         Buffer->Directory = TRUE;
976 
977     } else {
978 
979         Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
980         Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
981 
982         Buffer->Directory = FALSE;
983     }
984 
985     //
986     //  Update the length and status output variables
987     //
988 
989     *Length -= sizeof( FILE_STANDARD_INFORMATION );
990 
991     return;
992 }
993 
994 
995 //
996 //  Local support routine
997 //
998 
999 VOID
1000 CdQueryInternalInfo (
1001     _In_ PIRP_CONTEXT IrpContext,
1002     _In_ PFCB Fcb,
1003     _Out_ PFILE_INTERNAL_INFORMATION Buffer,
1004     _Inout_ PULONG Length
1005     )
1006 
1007 /*++
1008 
1009 Routine Description:
1010 
1011     This routine performs the query internal information function for cdfs.
1012 
1013 Arguments:
1014 
1015     Fcb - Supplies the Fcb being queried, it has been verified
1016 
1017     Buffer - Supplies a pointer to the buffer where the information is to
1018         be returned
1019 
1020     Length - Supplies the length of the buffer in bytes, and receives the
1021         remaining bytes free in the buffer upon return.
1022 
1023 Return Value:
1024 
1025     None
1026 
1027 --*/
1028 
1029 {
1030     PAGED_CODE();
1031 
1032     UNREFERENCED_PARAMETER( IrpContext );
1033 
1034     //
1035     //  Index number is the file Id number in the Fcb.
1036     //
1037 
1038     Buffer->IndexNumber = Fcb->FileId;
1039     *Length -= sizeof( FILE_INTERNAL_INFORMATION );
1040 
1041     return;
1042 }
1043 
1044 
1045 //
1046 //  Local support routine
1047 //
1048 
1049 VOID
1050 CdQueryEaInfo (
1051     _In_ PIRP_CONTEXT IrpContext,
1052     _In_ PFCB Fcb,
1053     _Out_ PFILE_EA_INFORMATION Buffer,
1054     _Inout_ PULONG Length
1055     )
1056 
1057 /*++
1058 
1059 Routine Description:
1060 
1061     This routine performs the query Ea information function for cdfs.
1062 
1063 Arguments:
1064 
1065     Fcb - Supplies the Fcb being queried, it has been verified
1066 
1067     Buffer - Supplies a pointer to the buffer where the information is to
1068         be returned
1069 
1070     Length - Supplies the length of the buffer in bytes, and receives the
1071         remaining bytes free in the buffer upon return.
1072 
1073 Return Value:
1074 
1075     None
1076 
1077 --*/
1078 
1079 {
1080     PAGED_CODE();
1081 
1082     UNREFERENCED_PARAMETER( IrpContext );
1083     UNREFERENCED_PARAMETER( Fcb );
1084 
1085     //
1086     //  No Ea's on Cdfs volumes.
1087     //
1088 
1089     Buffer->EaSize = 0;
1090     *Length -= sizeof( FILE_EA_INFORMATION );
1091 
1092     return;
1093 }
1094 
1095 
1096 //
1097 //  Local support routine
1098 //
1099 
1100 VOID
1101 CdQueryPositionInfo (
1102     _In_ PIRP_CONTEXT IrpContext,
1103     _In_ PFILE_OBJECT FileObject,
1104     _Out_ PFILE_POSITION_INFORMATION Buffer,
1105     _Inout_ PULONG Length
1106     )
1107 
1108 /*++
1109 
1110 Routine Description:
1111 
1112     This routine performs the query position information function for cdfs.
1113 
1114 Arguments:
1115 
1116     FileObject - Supplies the File object being queried
1117 
1118     Buffer - Supplies a pointer to the buffer where the information is to
1119         be returned
1120 
1121     Length - Supplies the length of the buffer in bytes, and receives the
1122         remaining bytes free in the buffer upon return.
1123 
1124 Return Value:
1125 
1126     None
1127 
1128 --*/
1129 
1130 {
1131     PAGED_CODE();
1132 
1133     UNREFERENCED_PARAMETER( IrpContext );
1134 
1135     //
1136     //  Get the current position found in the file object.
1137     //
1138 
1139     Buffer->CurrentByteOffset = FileObject->CurrentByteOffset;
1140 
1141     //
1142     //  Update the length and status output variables
1143     //
1144 
1145     *Length -= sizeof( FILE_POSITION_INFORMATION );
1146 
1147     return;
1148 }
1149 
1150 
1151 //
1152 //  Local support routine
1153 //
1154 
1155 NTSTATUS
1156 CdQueryNameInfo (
1157     _In_ PIRP_CONTEXT IrpContext,
1158     _In_ PFILE_OBJECT FileObject,
1159     _Out_ PFILE_NAME_INFORMATION Buffer,
1160     _Inout_ PULONG Length
1161     )
1162 
1163 /*++
1164 
1165 Routine Description:
1166 
1167     This routine performs the query name information function for cdfs.
1168 
1169 Arguments:
1170 
1171     FileObject - Supplies the file object containing the name.
1172 
1173     Buffer - Supplies a pointer to the buffer where the information is to
1174         be returned
1175 
1176     Length - Supplies the length of the buffer in bytes, and receives the
1177         remaining bytes free in the buffer upon return.
1178 
1179 Return Value:
1180 
1181     NTSTATUS - STATUS_BUFFER_OVERFLOW if the entire name can't be copied.
1182 
1183 --*/
1184 
1185 {
1186     NTSTATUS Status = STATUS_SUCCESS;
1187     ULONG LengthToCopy;
1188 
1189     PAGED_CODE();
1190 
1191     UNREFERENCED_PARAMETER( IrpContext );
1192 
1193     NT_ASSERT(*Length >= sizeof(ULONG));
1194 
1195     //
1196     //  Simply copy the name in the file object to the user's buffer.
1197     //
1198 
1199     //
1200     //  Place the size of the filename in the user's buffer and reduce the remaining
1201     //  size to match.
1202     //
1203 
1204     Buffer->FileNameLength = LengthToCopy = FileObject->FileName.Length;
1205     *Length -= sizeof(ULONG);
1206 
1207     if (LengthToCopy > *Length) {
1208 
1209         LengthToCopy = *Length;
1210         Status = STATUS_BUFFER_OVERFLOW;
1211     }
1212 
1213     RtlCopyMemory( Buffer->FileName, FileObject->FileName.Buffer, LengthToCopy );
1214 
1215     //
1216     //  Reduce the available bytes by the amount stored into this buffer.  In the overflow
1217     //  case, this simply drops to zero.  The returned filenamelength will indicate to the
1218     //  caller how much space is required.
1219     //
1220 
1221     *Length -= LengthToCopy;
1222 
1223     return Status;
1224 }
1225 
1226 
1227 //
1228 //  Local support routine
1229 //
1230 
1231 _Requires_lock_held_(_Global_critical_region_)
1232 NTSTATUS
1233 CdQueryAlternateNameInfo (
1234     _In_ PIRP_CONTEXT IrpContext,
1235     _In_ PFCB Fcb,
1236     _In_ PCCB Ccb,
1237     _Out_ PFILE_NAME_INFORMATION Buffer,
1238     _Inout_ PULONG Length
1239     )
1240 
1241 /*++
1242 
1243 Routine Description:
1244 
1245     This routine performs the query alternate name information function.
1246     We lookup the dirent for this file and then check if there is a
1247     short name.
1248 
1249 Arguments:
1250 
1251     Fcb - Supplies the Fcb being queried, it has been verified.
1252 
1253     Ccb - Ccb for this open handle.
1254 
1255     Buffer - Supplies a pointer to the buffer where the information is to
1256         be returned.
1257 
1258     Length - Supplies the length of the buffer in bytes, and receives the
1259         remaining bytes free in the buffer upon return.
1260 
1261 Return Value:
1262 
1263     NTSTATUS - STATUS_SUCCESS if the whole name would fit into the user buffer,
1264                STATUS_OBJECT_NAME_NOT_FOUND if we can't return the name,
1265                STATUS_BUFFER_OVERFLOW otherwise.
1266 
1267 --*/
1268 
1269 {
1270     NTSTATUS Status = STATUS_SUCCESS;
1271 
1272     DIRENT_ENUM_CONTEXT DirContext = {0};
1273     DIRENT Dirent = {0};
1274 
1275     PUNICODE_STRING NameToUse;
1276     ULONG DirentOffset;
1277 
1278     COMPOUND_PATH_ENTRY CompoundPathEntry = {{0}};/* ReactOS Change: GCC "missing braces around initializer" */
1279     FILE_ENUM_CONTEXT FileContext;
1280 
1281     PFCB ParentFcb = NULL;
1282     BOOLEAN ReleaseParentFcb = FALSE;
1283 
1284     BOOLEAN CleanupFileLookup = FALSE;
1285     BOOLEAN CleanupDirectoryLookup = FALSE;
1286 
1287     WCHAR ShortNameBuffer[ BYTE_COUNT_8_DOT_3 / 2 ];
1288     USHORT ShortNameLength;
1289 
1290     PAGED_CODE();
1291 
1292     //
1293     //  Initialize the buffer length to zero.
1294     //
1295 
1296     Buffer->FileNameLength = 0;
1297 
1298     //
1299     //  If this is the root or this file was opened using a version number then
1300     //  there is no short name.
1301     //
1302 
1303     if ((Fcb == Fcb->Vcb->RootIndexFcb) ||
1304         FlagOn( Ccb->Flags, CCB_FLAG_OPEN_WITH_VERSION)) {
1305 
1306         return STATUS_OBJECT_NAME_NOT_FOUND;
1307     }
1308 
1309     //
1310     //  Use a try-finally to cleanup the structures.
1311     //
1312 
1313     _SEH2_TRY {
1314 
1315         ParentFcb = Fcb->ParentFcb;
1316         CdAcquireFileShared( IrpContext, ParentFcb );
1317         ReleaseParentFcb = TRUE;
1318 
1319         CdVerifyOrCreateDirStreamFile( IrpContext, ParentFcb);
1320 
1321         if (CdFidIsDirectory( Fcb->FileId)) {
1322 
1323             //
1324             //  Fcb is for a directory, so we need to dig the dirent from the parent.  In
1325             //  order to do this we need to get the name of the directory from its pathtable
1326             //  entry and then search in the parent for a matching dirent.
1327             //
1328             //  This could be optimized somewhat.
1329             //
1330 
1331             CdInitializeCompoundPathEntry( IrpContext, &CompoundPathEntry );
1332             CdInitializeFileContext( IrpContext, &FileContext );
1333 
1334             CleanupDirectoryLookup = TRUE;
1335 
1336             CdLookupPathEntry( IrpContext,
1337                                CdQueryFidPathTableOffset( Fcb->FileId ),
1338                                Fcb->Ordinal,
1339                                FALSE,
1340                                &CompoundPathEntry );
1341 
1342             CdUpdatePathEntryName( IrpContext, &CompoundPathEntry.PathEntry, TRUE );
1343 
1344             if (!CdFindDirectory( IrpContext,
1345                                   ParentFcb,
1346                                   &CompoundPathEntry.PathEntry.CdCaseDirName,
1347                                   TRUE,
1348                                   &FileContext )) {
1349 
1350                 //
1351                 //  If we failed to find the child directory by name in the parent
1352                 //  something is quite wrong with this disc.
1353                 //
1354 
1355                 CdRaiseStatus( IrpContext, STATUS_DISK_CORRUPT_ERROR );
1356             }
1357 
1358             NameToUse = &FileContext.InitialDirent->Dirent.CdCaseFileName.FileName;
1359             DirentOffset = FileContext.InitialDirent->Dirent.DirentOffset;
1360 
1361         } else {
1362 
1363             //
1364             //  Initialize the search dirent structures.
1365             //
1366 
1367             CdInitializeDirContext( IrpContext, &DirContext );
1368             CdInitializeDirent( IrpContext, &Dirent );
1369 
1370             CleanupFileLookup = TRUE;
1371 
1372             CdLookupDirent( IrpContext,
1373                             ParentFcb,
1374                             CdQueryFidDirentOffset( Fcb->FileId ),
1375                             &DirContext );
1376 
1377             CdUpdateDirentFromRawDirent( IrpContext,
1378                                          ParentFcb,
1379                                          &DirContext,
1380                                          &Dirent );
1381 
1382             //
1383             //  Now update the dirent name.
1384             //
1385 
1386             CdUpdateDirentName( IrpContext, &Dirent, TRUE );
1387 
1388             NameToUse = &Dirent.CdCaseFileName.FileName;
1389             DirentOffset = Dirent.DirentOffset;
1390         }
1391 
1392         //
1393         //  If the name is 8.3 then fail this request.
1394         //
1395 
1396         if (CdIs8dot3Name( IrpContext,
1397                            *NameToUse )) {
1398 
1399 
1400             try_return( Status = STATUS_OBJECT_NAME_NOT_FOUND );
1401         }
1402 
1403         CdGenerate8dot3Name( IrpContext,
1404                              NameToUse,
1405                              DirentOffset,
1406                              ShortNameBuffer,
1407                              &ShortNameLength );
1408 
1409         //
1410         //  We now have the short name.  We have left it in Unicode form so copy it directly.
1411         //
1412 
1413         Buffer->FileNameLength = ShortNameLength;
1414 
1415         if (Buffer->FileNameLength + sizeof( ULONG ) > *Length) {
1416 
1417             Buffer->FileNameLength = *Length - sizeof( ULONG );
1418             Status = STATUS_BUFFER_OVERFLOW;
1419         }
1420 
1421         RtlCopyMemory( Buffer->FileName, ShortNameBuffer, Buffer->FileNameLength );
1422 
1423     try_exit:  NOTHING;
1424     } _SEH2_FINALLY {
1425 
1426         if (CleanupFileLookup) {
1427 
1428             CdCleanupDirContext( IrpContext, &DirContext );
1429             CdCleanupDirent( IrpContext, &Dirent );/* ReactOS Change: GCC "passing argument 1 from incompatible pointer type" */
1430 
1431         } else if (CleanupDirectoryLookup) {
1432 
1433             CdCleanupCompoundPathEntry( IrpContext, &CompoundPathEntry );
1434             CdCleanupFileContext( IrpContext, &FileContext );
1435         }
1436 
1437         if (ReleaseParentFcb) {
1438 
1439             CdReleaseFile( IrpContext, ParentFcb );
1440         }
1441     } _SEH2_END;
1442 
1443     //
1444     //  Reduce the available bytes by the amount stored into this buffer.
1445     //
1446 
1447     if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
1448 
1449         *Length -= sizeof( ULONG ) + Buffer->FileNameLength;
1450     }
1451 
1452     return Status;
1453 }
1454 
1455 
1456 //
1457 //  Local support routine
1458 //
1459 
1460 VOID
1461 CdQueryNetworkInfo (
1462     _In_ PIRP_CONTEXT IrpContext,
1463     _In_ PFCB Fcb,
1464     _Out_ PFILE_NETWORK_OPEN_INFORMATION Buffer,
1465     _Inout_ PULONG Length
1466     )
1467 
1468 /*++
1469 
1470  Description:
1471 
1472     This routine performs the query network open information function for Cdfs
1473 
1474 Arguments:
1475 
1476     Fcb - Supplies the Fcb being queried, it has been verified
1477 
1478     Buffer - Supplies a pointer to the buffer where the information is to
1479         be returned
1480 
1481     Length - Supplies the length of the buffer in bytes, and receives the
1482         remaining bytes free in the buffer upon return.
1483 
1484 Return Value:
1485 
1486     None
1487 
1488 --*/
1489 
1490 {
1491     PAGED_CODE();
1492 
1493     UNREFERENCED_PARAMETER( IrpContext );
1494 
1495     //
1496     //  We only support creation, last modify and last write times on Cdfs.
1497     //
1498 
1499     Buffer->LastWriteTime.QuadPart =
1500     Buffer->CreationTime.QuadPart =
1501     Buffer->ChangeTime.QuadPart = Fcb->CreationTime;
1502 
1503     Buffer->LastAccessTime.QuadPart = 0;
1504 
1505     Buffer->FileAttributes = Fcb->FileAttributes;
1506 
1507     //
1508     //  We get the sizes from the header.  Return a size of zero
1509     //  for all directories.
1510     //
1511 
1512     if (FlagOn( Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY )) {
1513 
1514         Buffer->AllocationSize.QuadPart =
1515         Buffer->EndOfFile.QuadPart = 0;
1516 
1517     } else {
1518 
1519         Buffer->AllocationSize.QuadPart = Fcb->AllocationSize.QuadPart;
1520         Buffer->EndOfFile.QuadPart = Fcb->FileSize.QuadPart;
1521     }
1522 
1523     //
1524     //  Update the length and status output variables
1525     //
1526 
1527     *Length -= sizeof( FILE_NETWORK_OPEN_INFORMATION );
1528 
1529     return;
1530 }
1531 
1532