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