ReactOS 0.4.15-dev-7834-g00c4b3d
fsctrl.c
Go to the documentation of this file.
1/*++
2
3
4Copyright (c) 1989-2000 Microsoft Corporation
5
6Module Name:
7
8 FsCtrl.c
9
10Abstract:
11
12 This module implements the File System Control routines for Fat called
13 by the dispatch driver.
14
15
16--*/
17
18#include "fatprocs.h"
19
20//
21// The Bug check file id for this module
22//
23
24#define BugCheckFileId (FAT_BUG_CHECK_FSCTRL)
25
26//
27// The local debug trace level
28//
29
30#define Dbg (DEBUG_TRACE_FSCTRL)
31
32//
33// Local procedure prototypes
34//
35
36_Requires_lock_held_(_Global_critical_region_)
38FatMountVolume (
39 IN PIRP_CONTEXT IrpContext,
41 IN PVPB Vpb,
43 );
44
45_Requires_lock_held_(_Global_critical_region_)
47FatVerifyVolume (
48 IN PIRP_CONTEXT IrpContext,
49 IN PIRP Irp
50 );
51
54 IN PIRP_CONTEXT IrpContext,
56 );
57
58_Requires_lock_held_(_Global_critical_region_)
60FatUserFsCtrl (
61 IN PIRP_CONTEXT IrpContext,
62 IN PIRP Irp
63 );
64
65_Requires_lock_held_(_Global_critical_region_)
67FatOplockRequest (
68 _In_ PIRP_CONTEXT IrpContext,
70 );
71
72_Requires_lock_held_(_Global_critical_region_)
74FatLockVolume (
75 IN PIRP_CONTEXT IrpContext,
76 IN PIRP Irp
77 );
78
81 IN PIRP_CONTEXT IrpContext,
82 IN PIRP Irp
83 );
84
85_Requires_lock_held_(_Global_critical_region_)
87FatDismountVolume (
88 IN PIRP_CONTEXT IrpContext,
89 IN PIRP Irp
90 );
91
92_Requires_lock_held_(_Global_critical_region_)
94FatDirtyVolume (
95 IN PIRP_CONTEXT IrpContext,
96 IN PIRP Irp
97 );
98
101 IN PIRP_CONTEXT IrpContext,
102 IN PIRP Irp
103 );
104
107 IN PIRP_CONTEXT IrpContext,
108 IN PIRP Irp
109 );
110
113 IN PIRP_CONTEXT IrpContext,
114 IN PIRP Irp
115 );
116
117_Requires_lock_held_(_Global_critical_region_)
119FatInvalidateVolumes (
120 IN PIRP Irp
121 );
122
123_Requires_lock_held_(_Global_critical_region_)
124VOID
125FatScanForDismountedVcb (
126 IN PIRP_CONTEXT IrpContext
127 );
128
131 IN PIRP_CONTEXT IrpContext,
132 IN PVCB Vcb,
134 IN LBO Lbo,
135 IN ULONG NumberOfBytesToRead,
136 IN BOOLEAN ReturnOnError
137 );
138
139_Requires_lock_held_(_Global_critical_region_)
141FatQueryRetrievalPointers (
142 IN PIRP_CONTEXT IrpContext,
143 IN PIRP Irp
144 );
145
148 IN PIRP_CONTEXT IrpContext,
149 IN PIRP Irp
150 );
151
154 IN PIRP_CONTEXT IrpContext,
155 IN PIRP Irp
156 );
157
160 IN PIRP_CONTEXT IrpContext,
161 IN PIRP Irp
162 );
163
164_Requires_lock_held_(_Global_critical_region_)
166FatGetBootAreaInfo (
167 _In_ PIRP_CONTEXT IrpContext,
169 );
170
171_Requires_lock_held_(_Global_critical_region_)
173FatGetRetrievalPointerBase (
174 _In_ PIRP_CONTEXT IrpContext,
176 );
177
178_Requires_lock_held_(_Global_critical_region_)
180FatMarkHandle(
181 _In_ PIRP_CONTEXT IrpContext,
183 );
184
187 __in PIRP_CONTEXT IrpContext,
189 );
190
191_Requires_lock_held_(_Global_critical_region_)
193FatSetPurgeFailureMode (
194 _In_ PIRP_CONTEXT IrpContext,
196 );
197
198//
199// Local support routine prototypes
200//
201
202_Requires_lock_held_(_Global_critical_region_)
204FatGetVolumeBitmap (
205 IN PIRP_CONTEXT IrpContext,
206 IN PIRP Irp
207 );
208
209_Requires_lock_held_(_Global_critical_region_)
211FatGetRetrievalPointers (
212 IN PIRP_CONTEXT IrpContext,
213 IN PIRP Irp
214 );
215
216_Requires_lock_held_(_Global_critical_region_)
217VOID
218FatMoveFileNeedsWriteThrough (
219 _In_ PIRP_CONTEXT IrpContext,
221 _In_ ULONG OldWriteThroughFlags
222 );
223
224_Requires_lock_held_(_Global_critical_region_)
226FatMoveFile (
227 IN PIRP_CONTEXT IrpContext,
228 IN PIRP Irp
229 );
230
231VOID
233 PIRP_CONTEXT IrpContext,
236 ULONG TargetCluster,
237 ULONG BytesToReallocate,
238 PULONG FirstSpliceSourceCluster,
239 PULONG FirstSpliceTargetCluster,
240 PULONG SecondSpliceSourceCluster,
241 PULONG SecondSpliceTargetCluster,
242 PLARGE_MCB SourceMcb
243);
244
245_Requires_lock_held_(_Global_critical_region_)
246VOID
247FatComputeMoveFileParameter (
248 IN PIRP_CONTEXT IrpContext,
253 OUT PULONG BytesToReallocate,
254 OUT PULONG BytesToWrite,
255 OUT PLARGE_INTEGER SourceLbo
256);
257
260 IN PIRP_CONTEXT IrpContext,
261 IN PVPB Vpb,
263 IN ULONG Size,
264 OUT PBOOLEAN LabelFound
265);
266
267VOID
269 IN PIRP_CONTEXT IrpContext,
270 IN PVCB Vcb,
273 );
274
275#ifdef ALLOC_PRAGMA
276#pragma alloc_text(PAGE, FatAddMcbEntry)
277#pragma alloc_text(PAGE, FatAllowExtendedDasdIo)
278#pragma alloc_text(PAGE, FatCommonFileSystemControl)
279#pragma alloc_text(PAGE, FatComputeMoveFileParameter)
280#pragma alloc_text(PAGE, FatComputeMoveFileSplicePoints)
281#pragma alloc_text(PAGE, FatDirtyVolume)
282#pragma alloc_text(PAGE, FatFsdFileSystemControl)
283#pragma alloc_text(PAGE, FatGetRetrievalPointerBase)
284#pragma alloc_text(PAGE, FatGetBootAreaInfo)
285#pragma alloc_text(PAGE, FatMarkHandle)
286#pragma alloc_text(PAGE, FatGetRetrievalPointers)
287#pragma alloc_text(PAGE, FatGetStatistics)
288#pragma alloc_text(PAGE, FatGetVolumeBitmap)
289#pragma alloc_text(PAGE, FatIsMediaWriteProtected)
290#pragma alloc_text(PAGE, FatIsPathnameValid)
291#pragma alloc_text(PAGE, FatIsVolumeDirty)
292#pragma alloc_text(PAGE, FatIsVolumeMounted)
293#pragma alloc_text(PAGE, FatLockVolume)
294#pragma alloc_text(PAGE, FatLookupLastMcbEntry)
295#pragma alloc_text(PAGE, FatGetNextMcbEntry)
296#pragma alloc_text(PAGE, FatMountVolume)
297#pragma alloc_text(PAGE, FatMoveFileNeedsWriteThrough)
298#pragma alloc_text(PAGE, FatMoveFile)
299#pragma alloc_text(PAGE, FatOplockRequest)
300#pragma alloc_text(PAGE, FatPerformVerifyDiskRead)
301#pragma alloc_text(PAGE, FatQueryBpb)
302#pragma alloc_text(PAGE, FatQueryRetrievalPointers)
303#pragma alloc_text(PAGE, FatRemoveMcbEntry)
304#pragma alloc_text(PAGE, FatScanForDismountedVcb)
305#pragma alloc_text(PAGE, FatFlushAndCleanVolume)
306#pragma alloc_text(PAGE, FatSearchBufferForLabel)
307#pragma alloc_text(PAGE, FatSetPurgeFailureMode)
308#pragma alloc_text(PAGE, FatUnlockVolume)
309#pragma alloc_text(PAGE, FatUserFsCtrl)
310#pragma alloc_text(PAGE, FatVerifyLookupFatEntry)
311#pragma alloc_text(PAGE, FatVerifyVolume)
312#endif
313
314#if DBG
315
316BOOLEAN FatMoveFileDebug = 0;
317
318#endif
319
320//
321// These wrappers go around the MCB package; we scale the LBO's passed
322// in (which can be bigger than 32 bits on fat32) by the volume's sector
323// size.
324//
325// Note we now use the real large mcb package. This means these shims
326// now also convert the -1 unused LBN number to the 0 of the original
327// mcb package.
328//
329
330#define MCB_SCALE_LOG2 (Vcb->AllocationSupport.LogOfBytesPerSector)
331#define MCB_SCALE (1 << MCB_SCALE_LOG2)
332#define MCB_SCALE_MODULO (MCB_SCALE - 1)
333
335FatNonSparseMcb(
336 _In_ PVCB Vcb,
338 _Out_ PVBO Vbo,
340 )
341{
342 LBO Lbo;
343 ULONG Index = 0;
344 LONGLONG llVbo = 0;
345
347
348 while (FsRtlGetNextLargeMcbEntry(Mcb, Index, &llVbo, &Lbo, ByteCount)) {
349 *Vbo = (VBO)llVbo;
350 if (((ULONG)Lbo) == -1) {
351 return FALSE;
352 }
353
354 Index++;
355 }
356
357 *Vbo = (VBO)llVbo;
358
359 return TRUE;
360}
361
362
365 IN PVCB Vcb,
367 IN VBO Vbo,
368 IN LBO Lbo,
370 )
371
372{
374#if DBG
375 VBO SparseVbo;
376 LONGLONG SparseByteCount;
377#endif
378
379 PAGED_CODE();
380
381 if (SectorCount) {
382
383 //
384 // Round up sectors, but be careful as SectorCount approaches 4Gb.
385 // Note that for x>0, (x+m-1)/m = ((x-1)/m)+(m/m) = ((x-1)/m)+1
386 //
387
388 SectorCount--;
390 SectorCount++;
391 }
392
395
396 NT_ASSERT( SectorCount != 0 );
397
398 if (Mcb != &Vcb->DirtyFatMcb) {
399 NT_ASSERT( FatNonSparseMcb( Vcb, Mcb, &SparseVbo, &SparseByteCount ) ||
400 ((SparseVbo == Vbo) && (SparseByteCount == SectorCount )) );
401 }
402
404 ((LONGLONG) Vbo),
405 ((LONGLONG) Lbo),
406 ((LONGLONG) SectorCount) );
407
408 if (Mcb != &Vcb->DirtyFatMcb) {
409 NT_ASSERT( FatNonSparseMcb( Vcb, Mcb, &SparseVbo, &SparseByteCount ) ||
410 ((SparseVbo == Vbo) && (SparseByteCount == SectorCount )) );
411 }
412
413 return Result;
414}
415
416
419 IN PVCB Vcb,
421 IN VBO Vbo,
422 OUT PLBO Lbo,
425 )
426{
427 BOOLEAN Results;
428 LONGLONG LiLbo;
429 LONGLONG LiSectorCount;
431
432 LiLbo = 0;
433 LiSectorCount = 0;
434
436
437 Results = FsRtlLookupLargeMcbEntry( Mcb,
438 (Vbo >> MCB_SCALE_LOG2),
439 &LiLbo,
440 ARGUMENT_PRESENT(ByteCount) ? &LiSectorCount : NULL,
441 NULL,
442 NULL,
443 Index );
444
445 if ((ULONG) LiLbo != -1) {
446
447 *Lbo = (((LBO) LiLbo) << MCB_SCALE_LOG2);
448
449 if (Results) {
450
451 *Lbo += Remainder;
452 }
453
454 } else {
455
456 *Lbo = 0;
457 }
458
460
461 *ByteCount = (ULONG) LiSectorCount;
462
463 if (*ByteCount) {
464
466
467 //
468 // If ByteCount overflows, then this is likely the case of
469 // a file of max-supported size (4GiB - 1), allocated in a
470 // single continuous run.
471 //
472
473 if (*ByteCount == 0) {
474
475 *ByteCount = 0xFFFFFFFF;
476 }
477
478 if (Results) {
479
481 }
482 }
483
484 }
485
486 return Results;
487}
488
489//
490// NOTE: Vbo/Lbn undefined if MCB is empty & return code false.
491//
492
495 IN PVCB Vcb,
497 OUT PVBO Vbo,
498 OUT PLBO Lbo,
500 )
501
502{
503 BOOLEAN Results;
504 LONGLONG LiVbo;
505 LONGLONG LiLbo;
506 ULONG LocalIndex;
507
508 PAGED_CODE();
509
510 LiVbo = LiLbo = 0;
511 LocalIndex = 0;
512
514 &LiVbo,
515 &LiLbo,
516 &LocalIndex );
517
518 *Vbo = ((VBO) LiVbo) << MCB_SCALE_LOG2;
519
520 if (((ULONG) LiLbo) != -1) {
521
522 *Lbo = ((LBO) LiLbo) << MCB_SCALE_LOG2;
523
524 *Lbo += (MCB_SCALE - 1);
525 *Vbo += (MCB_SCALE - 1);
526
527 } else {
528
529 *Lbo = 0;
530 }
531
532 if (Index) {
533 *Index = LocalIndex;
534 }
535
536 return Results;
537}
538
539
542 IN PVCB Vcb,
545 OUT PVBO Vbo,
546 OUT PLBO Lbo,
548 )
549
550{
551 BOOLEAN Results;
552 LONGLONG LiVbo;
553 LONGLONG LiLbo;
554 LONGLONG LiSectorCount;
555
556 PAGED_CODE();
557
558 LiVbo = LiLbo = 0;
559
561 RunIndex,
562 &LiVbo,
563 &LiLbo,
564 &LiSectorCount );
565
566 if (Results) {
567
568 *Vbo = ((VBO) LiVbo) << MCB_SCALE_LOG2;
569
570 if (((ULONG) LiLbo) != -1) {
571
572 *Lbo = ((LBO) LiLbo) << MCB_SCALE_LOG2;
573
574 } else {
575
576 *Lbo = 0;
577 }
578
579 *ByteCount = ((ULONG) LiSectorCount) << MCB_SCALE_LOG2;
580
581 if ((*ByteCount == 0) && (LiSectorCount != 0)) {
582
583 //
584 // If 'ByteCount' overflows, then this is likely a file of
585 // max supported size (2^32 - 1) in one contiguous run.
586 //
587
588 NT_ASSERT( RunIndex == 0 );
589
590 *ByteCount = 0xFFFFFFFF;
591 }
592 }
593
594 return Results;
595}
596
597
598VOID
600 IN PVCB Vcb,
602 IN VBO Vbo,
604 )
605{
606 PAGED_CODE();
607
608 if ((SectorCount) && (SectorCount != 0xFFFFFFFF)) {
609
610 SectorCount--;
612 SectorCount++;
613 }
614
616
617#if DBG
618 _SEH2_TRY {
619#endif
620
622 (LONGLONG) Vbo,
624
625#if DBG
626 } _SEH2_EXCEPT(FatBugCheckExceptionFilter( _SEH2_GetExceptionInformation() )) {
627
628 NOTHING;
629 } _SEH2_END;
630#endif
631
632}
633
634
638NTAPI
639FatFsdFileSystemControl (
640 _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
642 )
643
644/*++
645
646Routine Description:
647
648 This routine implements the FSD part of FileSystem control operations
649
650Arguments:
651
652 VolumeDeviceObject - Supplies the volume device object where the
653 file exists
654
655 Irp - Supplies the Irp being processed
656
657Return Value:
658
659 NTSTATUS - The FSD status for the IRP
660
661--*/
662
663{
666 PIRP_CONTEXT IrpContext = NULL;
667
669
670 PAGED_CODE();
671 UNREFERENCED_PARAMETER( VolumeDeviceObject );
672
673 DebugTrace(+1, Dbg,"FatFsdFileSystemControl\n", 0);
674
675 //
676 // Call the common FileSystem Control routine, with blocking allowed if
677 // synchronous. This opeation needs to special case the mount
678 // and verify suboperations because we know they are allowed to block.
679 // We identify these suboperations by looking at the file object field
680 // and seeing if its null.
681 //
682
684
685 Wait = TRUE;
686
687 } else {
688
689 Wait = CanFsdWait( Irp );
690 }
691
693
695
696 _SEH2_TRY {
697
699
701
702 //
703 // We need to made a special check here for the InvalidateVolumes
704 // FSCTL as that comes in with a FileSystem device object instead
705 // of a volume device object.
706 //
707
711 (IrpSp->Parameters.FileSystemControl.FsControlCode ==
713
714 Status = FatInvalidateVolumes( Irp );
715
716 } else {
717
718 IrpContext = FatCreateIrpContext( Irp, Wait );
719
720 Status = FatCommonFileSystemControl( IrpContext, Irp );
721 }
722
724
725 //
726 // We had some trouble trying to perform the requested
727 // operation, so we'll abort the I/O request with
728 // the error status that we get back from the
729 // execption code
730 //
731
732 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
733 } _SEH2_END;
734
735 if (TopLevel) { IoSetTopLevelIrp( NULL ); }
736
738
739 //
740 // And return to our caller
741 //
742
743 DebugTrace(-1, Dbg, "FatFsdFileSystemControl -> %08lx\n", Status);
744
745 return Status;
746}
747
748
749_Requires_lock_held_(_Global_critical_region_)
751FatCommonFileSystemControl (
752 IN PIRP_CONTEXT IrpContext,
753 IN PIRP Irp
754 )
755
756/*++
757
758Routine Description:
759
760 This is the common routine for doing FileSystem control operations called
761 by both the fsd and fsp threads
762
763Arguments:
764
765 Irp - Supplies the Irp to process
766
767Return Value:
768
769 NTSTATUS - The return status for the operation
770
771--*/
772
773{
776
777 PAGED_CODE();
778
779 //
780 // Get a pointer to the current Irp stack location
781 //
782
784
785 DebugTrace(+1, Dbg,"FatCommonFileSystemControl\n", 0);
786 DebugTrace( 0, Dbg,"Irp = %p\n", Irp);
787 DebugTrace( 0, Dbg,"MinorFunction = %08lx\n", IrpSp->MinorFunction);
788
789 //
790 // We know this is a file system control so we'll case on the
791 // minor function, and call a internal worker routine to complete
792 // the irp.
793 //
794
795 switch (IrpSp->MinorFunction) {
796
798
799 Status = FatUserFsCtrl( IrpContext, Irp );
800 break;
801
803
804 Status = FatMountVolume( IrpContext,
805 IrpSp->Parameters.MountVolume.DeviceObject,
806 IrpSp->Parameters.MountVolume.Vpb,
808
809 //
810 // Complete the request.
811 //
812 // We do this here because FatMountVolume can be called recursively,
813 // but the Irp is only to be completed once.
814 //
815 // NOTE: I don't think this is true anymore (danlo 3/15/1999). Probably
816 // an artifact of the old doublespace attempt.
817 //
818
819 FatCompleteRequest( IrpContext, Irp, Status );
820 break;
821
823
824 Status = FatVerifyVolume( IrpContext, Irp );
825 break;
826
827 default:
828
829 DebugTrace( 0, Dbg, "Invalid FS Control Minor Function %08lx\n", IrpSp->MinorFunction);
830
833 break;
834 }
835
836 DebugTrace(-1, Dbg, "FatCommonFileSystemControl -> %08lx\n", Status);
837
838 return Status;
839}
840
841
842//
843// Local Support Routine
844//
845
846_Requires_lock_held_(_Global_critical_region_)
848FatMountVolume (
849 IN PIRP_CONTEXT IrpContext,
851 IN PVPB Vpb,
853 )
854
855/*++
856
857Routine Description:
858
859 This routine performs the mount volume operation. It is responsible for
860 either completing of enqueuing the input Irp.
861
862 Its job is to verify that the volume denoted in the IRP is a Fat volume,
863 and create the VCB and root DCB structures. The algorithm it uses is
864 essentially as follows:
865
866 1. Create a new Vcb Structure, and initialize it enough to do cached
867 volume file I/O.
868
869 2. Read the disk and check if it is a Fat volume.
870
871 3. If it is not a Fat volume then free the cached volume file, delete
872 the VCB, and complete the IRP with STATUS_UNRECOGNIZED_VOLUME
873
874 4. Check if the volume was previously mounted and if it was then do a
875 remount operation. This involves reinitializing the cached volume
876 file, checking the dirty bit, resetting up the allocation support,
877 deleting the VCB, hooking in the old VCB, and completing the IRP.
878
879 5. Otherwise create a root DCB, create Fsp threads as necessary, and
880 complete the IRP.
881
882Arguments:
883
884 TargetDeviceObject - This is where we send all of our requests.
885
886 Vpb - This gives us additional information needed to complete the mount.
887
888Return Value:
889
890 NTSTATUS - The return status for the operation
891
892--*/
893
894{
895 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp );
897
898 PBCB BootBcb;
900
901 PBCB DirentBcb;
904
905 BOOLEAN MountNewVolume = FALSE;
906 BOOLEAN WeClearedVerifyRequiredBit = FALSE;
907 BOOLEAN DoARemount = FALSE;
908
909 PVCB OldVcb = NULL;
910 PVPB OldVpb = NULL;
911
912 PDEVICE_OBJECT RealDevice = NULL;
914 PVCB Vcb = NULL;
915 PFILE_OBJECT RootDirectoryFile = NULL;
916
917 PLIST_ENTRY Links;
918
919 IO_STATUS_BLOCK Iosb = {0};
920 ULONG ChangeCount = 0;
921
922 DISK_GEOMETRY Geometry;
923
924 PARTITION_INFORMATION_EX PartitionInformation;
925 NTSTATUS StatusPartInfo;
926
927#if (NTDDI_VERSION > NTDDI_WIN8)
928 GUID VolumeGuid = {0};
929#endif
930
931
932 PAGED_CODE();
933
934 DebugTrace(+1, Dbg, "FatMountVolume\n", 0);
935 DebugTrace( 0, Dbg, "TargetDeviceObject = %p\n", TargetDeviceObject);
936 DebugTrace( 0, Dbg, "Vpb = %p\n", Vpb);
937
938 NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
940
941 //
942 // Only send down IOCTL_DISK_CHECK_VERIFY if it is removable media.
943 //
944
945 if (FlagOn(TargetDeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
946
947 //
948 // Verify that there is a disk here and pick up the change count.
949 //
950
951 Status = FatPerformDevIoCtrl( IrpContext,
954 NULL,
955 0,
956 &ChangeCount,
957 sizeof(ULONG),
958 FALSE,
959 TRUE,
960 &Iosb );
961
962 if (!NT_SUCCESS( Status )) {
963
964 //
965 // If we will allow a raw mount then avoid sending the popup.
966 //
967 // Only send this on "true" disk devices to handle the accidental
968 // legacy of FAT. No other FS will throw a harderror on empty
969 // drives.
970 //
971 // Cmd should really handle this per 9x.
972 //
973
975 Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK) {
976
977 FatNormalizeAndRaiseStatus( IrpContext, Status );
978 }
979
980 return Status;
981 }
982
983 }
984
985 if (Iosb.Information != sizeof(ULONG)) {
986
987 //
988 // Be safe about the count in case the driver didn't fill it in
989 //
990
991 ChangeCount = 0;
992 }
993
994 //
995 // If this is a CD class device, then check to see if there is a
996 // 'data track' or not. This is to avoid issuing paging reads which will
997 // fail later in the mount process (e.g. CD-DA or blank CD media)
998 //
999
1000 if ((TargetDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) &&
1001 !FatScanForDataTrack( IrpContext, TargetDeviceObject)) {
1002
1004 }
1005
1006 //
1007 // Ping the volume with a partition query and pick up the partition
1008 // type. We'll check this later to avoid some scurrilous volumes.
1009 //
1010
1011 StatusPartInfo = FatPerformDevIoCtrl( IrpContext,
1014 NULL,
1015 0,
1016 &PartitionInformation,
1018 FALSE,
1019 TRUE,
1020 &Iosb );
1021
1022 //
1023 // Make sure we can wait.
1024 //
1025
1026 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
1027
1028 //
1029 // Do a quick check to see if there any Vcb's which can be removed.
1030 //
1031
1032 FatScanForDismountedVcb( IrpContext );
1033
1034 //
1035 // Initialize the Bcbs and our final state so that the termination
1036 // handlers will know what to free or unpin
1037 //
1038
1039 BootBcb = NULL;
1040 DirentBcb = NULL;
1041
1042 Vcb = NULL;
1043 VolDo = NULL;
1044 MountNewVolume = FALSE;
1045
1046 _SEH2_TRY {
1047
1048 //
1049 // Synchronize with FatCheckForDismount(), which modifies the vpb.
1050 //
1051
1052#ifdef _MSC_VER
1053#pragma prefast( push )
1054#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
1055#pragma prefast( disable: 28193, "this will always wait" )
1056#endif
1057
1058 (VOID)FatAcquireExclusiveGlobal( IrpContext );
1059
1060#ifdef _MSC_VER
1061#pragma prefast( pop )
1062#endif
1063
1064 //
1065 // Create a new volume device object. This will have the Vcb
1066 // hanging off of its end, and set its alignment requirement
1067 // from the device we talk to.
1068 //
1069
1071 sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
1072 NULL,
1074 0,
1075 FALSE,
1076 (PDEVICE_OBJECT *)&VolDo))) {
1077
1078 try_return( Status );
1079 }
1080
1081 //
1082 // Our alignment requirement is the larger of the processor alignment requirement
1083 // already in the volume device object and that in the TargetDeviceObject
1084 //
1085
1086 if (TargetDeviceObject->AlignmentRequirement > VolDo->DeviceObject.AlignmentRequirement) {
1087
1088 VolDo->DeviceObject.AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
1089 }
1090
1091 //
1092 // Initialize the overflow queue for the volume
1093 //
1094
1095 VolDo->OverflowQueueCount = 0;
1096 InitializeListHead( &VolDo->OverflowQueue );
1097
1098 VolDo->PostedRequestCount = 0;
1099 KeInitializeSpinLock( &VolDo->OverflowQueueSpinLock );
1100
1101 //
1102 // We must initialize the stack size in our device object before
1103 // the following reads, because the I/O system has not done it yet.
1104 // This must be done before we clear the device initializing flag
1105 // otherwise a filter could attach and copy the wrong stack size into
1106 // it's device object.
1107 //
1108
1109 VolDo->DeviceObject.StackSize = (CCHAR)(TargetDeviceObject->StackSize + 1);
1110
1111 //
1112 // We must also set the sector size correctly in our device object
1113 // before clearing the device initializing flag.
1114 //
1115
1116 Status = FatPerformDevIoCtrl( IrpContext,
1119 NULL,
1120 0,
1121 &Geometry,
1122 sizeof( DISK_GEOMETRY ),
1123 FALSE,
1124 TRUE,
1125 NULL );
1126
1127 if (!NT_SUCCESS( Status )) {
1128
1129 try_return( Status );
1130 }
1131
1132#ifdef _MSC_VER
1133#pragma prefast( suppress: 28175, "this is a filesystem driver, touching SectorSize is fine" )
1134#endif
1135 VolDo->DeviceObject.SectorSize = (USHORT)Geometry.BytesPerSector;
1136
1137 //
1138 // Indicate that this device object is now completely initialized
1139 //
1140
1141 ClearFlag(VolDo->DeviceObject.Flags, DO_DEVICE_INITIALIZING);
1142
1143 //
1144 // Now Before we can initialize the Vcb we need to set up the device
1145 // object field in the Vpb to point to our new volume device object.
1146 // This is needed when we create the virtual volume file's file object
1147 // in initialize vcb.
1148 //
1149
1150 Vpb->DeviceObject = (PDEVICE_OBJECT)VolDo;
1151
1152 //
1153 // If the real device needs verification, temporarily clear the
1154 // field.
1155 //
1156
1157 RealDevice = Vpb->RealDevice;
1158
1159 if ( FlagOn(RealDevice->Flags, DO_VERIFY_VOLUME) ) {
1160
1161 ClearFlag(RealDevice->Flags, DO_VERIFY_VOLUME);
1162
1163 WeClearedVerifyRequiredBit = TRUE;
1164 }
1165
1166 //
1167 // Initialize the new vcb
1168 //
1169
1170 FatInitializeVcb( IrpContext,
1171 &VolDo->Vcb,
1173 Vpb,
1175 //
1176 // Get a reference to the Vcb hanging off the end of the device object
1177 //
1178
1179 Vcb = &VolDo->Vcb;
1180
1181 //
1182 // Read in the boot sector, and have the read be the minumum size
1183 // needed. We know we can wait.
1184 //
1185
1186 //
1187 // We need to commute errors on CD so that CDFS will get its crack. Audio
1188 // and even data media may not be universally readable on sector zero.
1189 //
1190
1191 _SEH2_TRY {
1192
1193 FatReadVolumeFile( IrpContext,
1194 Vcb,
1195 0, // Starting Byte
1196 sizeof(PACKED_BOOT_SECTOR),
1197 &BootBcb,
1198 (PVOID *)&BootSector );
1199
1200 } _SEH2_EXCEPT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
1202
1203 NOTHING;
1204 } _SEH2_END;
1205
1206 //
1207 // Call a routine to check the boot sector to see if it is fat
1208 //
1209
1210 if (BootBcb == NULL || !FatIsBootSectorFat( BootSector)) {
1211
1212 DebugTrace(0, Dbg, "Not a Fat Volume\n", 0);
1213
1214 //
1215 // Complete the request and return to our caller
1216 //
1217
1219 }
1220
1221#if (NTDDI_VERSION > NTDDI_WIN8)
1222 //
1223 // Initialize the volume guid.
1224 //
1225
1226 if (NT_SUCCESS( IoVolumeDeviceToGuid( Vcb->TargetDeviceObject, &VolumeGuid ))) {
1227
1228
1229 //
1230 // Stash a copy away in the VCB.
1231 //
1232
1233 RtlCopyMemory( &Vcb->VolumeGuid, &VolumeGuid, sizeof(GUID));
1234
1235 }
1236
1237
1238 //
1239 // Stash away a copy of the volume GUID path in our VCB.
1240 //
1241
1242 if (Vcb->VolumeGuidPath.Buffer) {
1243 ExFreePool( Vcb->VolumeGuidPath.Buffer );
1244 Vcb->VolumeGuidPath.Buffer = NULL;
1245 Vcb->VolumeGuidPath.Length = Vcb->VolumeGuidPath.MaximumLength = 0;
1246 }
1247
1248 IoVolumeDeviceToGuidPath( Vcb->TargetDeviceObject, &Vcb->VolumeGuidPath );
1249#endif
1250
1251 //
1252 // Unpack the BPB. We used to do some sanity checking of the FATs at
1253 // this point, but authoring errors on third-party devices prevent
1254 // us from continuing to safeguard ourselves. We can only hope the
1255 // boot sector check is good enough.
1256 //
1257 // (read: digital cameras)
1258 //
1259 // Win9x does the same.
1260 //
1261
1262 FatUnpackBios( &Vcb->Bpb, &BootSector->PackedBpb );
1263
1264 //
1265 // Check if we have an OS/2 Boot Manager partition and treat it as an
1266 // unknown file system. We'll check the partition type in from the
1267 // partition table and we ensure that it has less than 0x80 sectors,
1268 // which is just a heuristic that will capture all real OS/2 BM partitions
1269 // and avoid the chance we'll discover partitions which erroneously
1270 // (but to this point, harmlessly) put down the OS/2 BM type.
1271 //
1272 // Note that this is only conceivable on good old MBR media.
1273 //
1274 // The OS/2 Boot Manager boot format mimics a FAT16 partition in sector
1275 // zero but does is not a real FAT16 file system. For example, the boot
1276 // sector indicates it has 2 FATs but only really has one, with the boot
1277 // manager code overlaying the second FAT. If we then set clean bits in
1278 // FAT[0] we'll corrupt that code.
1279 //
1280
1281 if (NT_SUCCESS( StatusPartInfo ) &&
1282 (PartitionInformation.PartitionStyle == PARTITION_STYLE_MBR &&
1283 PartitionInformation.Mbr.PartitionType == PARTITION_OS2BOOTMGR) &&
1284 (Vcb->Bpb.Sectors != 0 &&
1285 Vcb->Bpb.Sectors < 0x80)) {
1286
1287 DebugTrace( 0, Dbg, "OS/2 Boot Manager volume detected, volume not mounted. \n", 0 );
1288
1289 //
1290 // Complete the request and return to our caller
1291 //
1292
1294 }
1295
1296 //
1297 // Verify that the sector size recorded in the Bpb matches what the
1298 // device currently reports it's sector size to be.
1299 //
1300
1301 if ( !NT_SUCCESS( Status) ||
1302 (Geometry.BytesPerSector != Vcb->Bpb.BytesPerSector)) {
1303
1305 }
1306
1307 //
1308 // This is a fat volume, so extract the bpb, serial number. The
1309 // label we'll get later after we've created the root dcb.
1310 //
1311 // Note that the way data caching is done, we set neither the
1312 // direct I/O or Buffered I/O bit in the device object flags.
1313 //
1314
1315 if (Vcb->Bpb.Sectors != 0) { Vcb->Bpb.LargeSectors = 0; }
1316
1317 if (IsBpbFat32(&BootSector->PackedBpb)) {
1318
1319 CopyUchar4( &Vpb->SerialNumber, ((PPACKED_BOOT_SECTOR_EX)BootSector)->Id );
1320
1321 } else {
1322
1323 CopyUchar4( &Vpb->SerialNumber, BootSector->Id );
1324
1325 //
1326 // Allocate space for the stashed boot sector chunk. This only has meaning on
1327 // FAT12/16 volumes since this only is kept for the FSCTL_QUERY_FAT_BPB and it and
1328 // its users are a bit wierd, thinking that a BPB exists wholly in the first 0x24
1329 // bytes.
1330 //
1331
1332 Vcb->First0x24BytesOfBootSector =
1334 0x24,
1336
1337 //
1338 // Stash a copy of the first 0x24 bytes
1339 //
1340
1341 RtlCopyMemory( Vcb->First0x24BytesOfBootSector,
1342 BootSector,
1343 0x24 );
1344 }
1345
1346 //
1347 // Now unpin the boot sector, so when we set up allocation eveything
1348 // works.
1349 //
1350
1351 FatUnpinBcb( IrpContext, BootBcb );
1352
1353 //
1354 // Compute a number of fields for Vcb.AllocationSupport
1355 //
1356
1357 FatSetupAllocationSupport( IrpContext, Vcb );
1358
1359 //
1360 // Sanity check the FsInfo information for FAT32 volumes. Silently deal
1361 // with messed up information by effectively disabling FsInfo updates.
1362 //
1363
1364 if (FatIsFat32( Vcb )) {
1365
1366 if (Vcb->Bpb.FsInfoSector >= Vcb->Bpb.ReservedSectors) {
1367
1368 Vcb->Bpb.FsInfoSector = 0;
1369 }
1370 }
1371
1372
1373 //
1374 // Create a root Dcb so we can read in the volume label. If this is FAT32, we can
1375 // discover corruption in the FAT chain.
1376 //
1377 // NOTE: this exception handler presumes that this is the only spot where we can
1378 // discover corruption in the mount process. If this ever changes, this handler
1379 // MUST be expanded. The reason we have this guy here is because we have to rip
1380 // the structures down now (in the finally below) and can't wait for the outer
1381 // exception handling to do it for us, at which point everything will have vanished.
1382 //
1383
1384 _SEH2_TRY {
1385
1386 FatCreateRootDcb( IrpContext, Vcb );
1387
1390
1391 //
1392 // The volume needs to be dirtied, do it now. Note that at this point we have built
1393 // enough of the Vcb to pull this off.
1394 //
1395
1396 FatCheckDirtyBit( IrpContext,
1397 Vcb );
1398
1399 //
1400 // Set the dirty bit if it is not set already
1401 //
1402
1403 if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
1404
1406 FatMarkVolume( IrpContext, Vcb, VolumeDirty );
1408 }
1409
1410 //
1411 // Now keep bailing out ...
1412 //
1413
1415 } _SEH2_END;
1416
1417 FatLocateVolumeLabel( IrpContext,
1418 Vcb,
1419 &Dirent,
1420 &DirentBcb,
1421 (PVBO)&ByteOffset );
1422
1423 if (Dirent != NULL) {
1424
1425 UCHAR OemBuffer[11];
1428
1429 OemString.Buffer = (PCHAR)&OemBuffer[0];
1430 OemString.MaximumLength = 11;
1431
1432 RtlCopyMemory( OemString.Buffer, Dirent->FileName, 11 );
1433
1434 //
1435 // Translate the first character from 0x5 to 0xe5.
1436 //
1437
1438 if (OemString.Buffer[0] == FAT_DIRENT_REALLY_0E5) {
1439
1440 OemString.Buffer[0] = 0xe5;
1441 }
1442
1443 //
1444 // Compute the length of the volume name
1445 //
1446
1447 for ( OemString.Length = 11;
1448 OemString.Length > 0;
1449 OemString.Length -= 1) {
1450
1451 if ( (OemString.Buffer[OemString.Length-1] != 0x00) &&
1452 (OemString.Buffer[OemString.Length-1] != 0x20) ) { break; }
1453 }
1454
1456 UnicodeString.Buffer = &Vcb->Vpb->VolumeLabel[0];
1457
1459 &OemString,
1460 FALSE );
1461
1462 if ( !NT_SUCCESS( Status ) ) {
1463
1464 try_return( Status );
1465 }
1466
1467 Vpb->VolumeLabelLength = UnicodeString.Length;
1468
1469 } else {
1470
1471 Vpb->VolumeLabelLength = 0;
1472 }
1473
1474 //
1475 // Use the change count we noted initially *before* doing any work.
1476 // If something came along in the midst of this operation, we'll
1477 // verify and discover the problem.
1478 //
1479
1480 Vcb->ChangeCount = ChangeCount;
1481
1482 //
1483 // Now scan the list of previously mounted volumes and compare
1484 // serial numbers and volume labels off not currently mounted
1485 // volumes to see if we have a match.
1486 //
1487
1488 for (Links = FatData.VcbQueue.Flink;
1489 Links != &FatData.VcbQueue;
1490 Links = Links->Flink) {
1491
1492 OldVcb = CONTAINING_RECORD( Links, VCB, VcbLinks );
1493 OldVpb = OldVcb->Vpb;
1494
1495 //
1496 // Skip over ourselves since we're already in the VcbQueue
1497 //
1498
1499 if (OldVpb == Vpb) { continue; }
1500
1501 //
1502 // Check for a match:
1503 //
1504 // Serial Number, VolumeLabel and Bpb must all be the same.
1505 // Also the volume must have failed a verify before (ie.
1506 // VolumeNotMounted), and it must be in the same physical
1507 // drive than it was mounted in before.
1508 //
1509
1510 if ( (OldVpb->SerialNumber == Vpb->SerialNumber) &&
1511 (OldVcb->VcbCondition == VcbNotMounted) &&
1512 (OldVpb->RealDevice == RealDevice) &&
1513 (OldVpb->VolumeLabelLength == Vpb->VolumeLabelLength) &&
1514 (RtlEqualMemory(&OldVpb->VolumeLabel[0],
1515 &Vpb->VolumeLabel[0],
1516 Vpb->VolumeLabelLength)) &&
1517 (RtlEqualMemory(&OldVcb->Bpb,
1518 &Vcb->Bpb,
1519 IsBpbFat32(&Vcb->Bpb) ?
1520 sizeof(BIOS_PARAMETER_BLOCK) :
1522 LargeSectorsPerFat) ))) {
1523
1524 DoARemount = TRUE;
1525
1526 break;
1527 }
1528 }
1529
1530 if ( DoARemount ) {
1531
1532 PVPB *IrpVpb;
1533
1534 DebugTrace(0, Dbg, "Doing a remount\n", 0);
1535 DebugTrace(0, Dbg, "Vcb = %p\n", Vcb);
1536 DebugTrace(0, Dbg, "Vpb = %p\n", Vpb);
1537 DebugTrace(0, Dbg, "OldVcb = %p\n", OldVcb);
1538 DebugTrace(0, Dbg, "OldVpb = %p\n", OldVpb);
1539
1540 //
1541 // Swap target device objects between the VCBs. That way
1542 // the old VCB will start using the new target device object,
1543 // and the new VCB will be torn down and deference the old
1544 // target device object.
1545 //
1546
1547 Vcb->TargetDeviceObject = OldVcb->TargetDeviceObject;
1549
1550 //
1551 // This is a remount, so link the old vpb in place
1552 // of the new vpb.
1553 //
1554
1556
1557 FatSetVcbCondition( OldVcb, VcbGood);
1558 OldVpb->RealDevice = Vpb->RealDevice;
1560
1561#ifdef _MSC_VER
1562#pragma prefast( suppress: 28175, "touching Vpb is ok for a filesystem" )
1563#endif
1564 OldVpb->RealDevice->Vpb = OldVpb;
1565
1566 //
1567 // Use the new changecount.
1568 //
1569
1570 OldVcb->ChangeCount = Vcb->ChangeCount;
1571
1572 //
1573 // If the new VPB is the VPB referenced in the original Irp, set
1574 // that reference back to the old VPB.
1575 //
1576
1577 IrpVpb = &IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp)->Parameters.MountVolume.Vpb;
1578
1579 if (*IrpVpb == Vpb) {
1580
1581 *IrpVpb = OldVpb;
1582 }
1583
1584 //
1585 // We do not want to touch this VPB again. It will get cleaned up when
1586 // the new VCB is cleaned up.
1587 //
1588
1589 NT_ASSERT( Vcb->Vpb == Vpb );
1590
1591 Vpb = NULL;
1594
1595 //
1596 // Reinitialize the volume file cache and allocation support.
1597 //
1598
1599 {
1601
1603 FileSizes.FileSize.QuadPart = ( 0x40000 + 0x1000 );
1605
1606 DebugTrace(0, Dbg, "Truncate and reinitialize the volume file\n", 0);
1607
1609 &FileSizes,
1610 TRUE,
1612 Vcb );
1613
1614 //
1615 // Redo the allocation support
1616 //
1617
1618 FatSetupAllocationSupport( IrpContext, OldVcb );
1619
1620 //
1621 // Get the state of the dirty bit.
1622 //
1623
1624 FatCheckDirtyBit( IrpContext, OldVcb );
1625
1626 //
1627 // Check for write protected media.
1628 //
1629
1631
1633
1634 } else {
1635
1637 }
1638 }
1639
1640 //
1641 // Complete the request and return to our caller
1642 //
1643
1645 }
1646
1647 DebugTrace(0, Dbg, "Mount a new volume\n", 0);
1648
1649 //
1650 // This is a new mount
1651 //
1652 // Create a blank ea data file fcb, just not for Fat32.
1653 //
1654
1655 if (!FatIsFat32(Vcb)) {
1656
1657 DIRENT TempDirent;
1658 PFCB EaFcb;
1659
1660 RtlZeroMemory( &TempDirent, sizeof(DIRENT) );
1661 RtlCopyMemory( &TempDirent.FileName[0], "EA DATA SF", 11 );
1662
1663 EaFcb = FatCreateFcb( IrpContext,
1664 Vcb,
1665 Vcb->RootDcb,
1666 0,
1667 0,
1668 &TempDirent,
1669 NULL,
1670 NULL,
1671 FALSE,
1672 TRUE );
1673
1674 //
1675 // Deny anybody who trys to open the file.
1676 //
1677
1679
1680 Vcb->EaFcb = EaFcb;
1681 }
1682
1683 //
1684 // Get the state of the dirty bit.
1685 //
1686
1687 FatCheckDirtyBit( IrpContext, Vcb );
1688
1689
1690 //
1691 // Check for write protected media.
1692 //
1693
1695
1697
1698 } else {
1699
1701 }
1702
1703
1704 //
1705 // Lock volume in drive if we just mounted the boot drive.
1706 //
1707
1708 if (FlagOn(RealDevice->Flags, DO_SYSTEM_BOOT_PARTITION)) {
1709
1711
1712 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA)) {
1713
1714 FatToggleMediaEjectDisable( IrpContext, Vcb, TRUE );
1715 }
1716 }
1717
1718
1719 //
1720 // Indicate to our termination handler that we have mounted
1721 // a new volume.
1722 //
1723
1724 MountNewVolume = TRUE;
1725
1726 //
1727 // Complete the request
1728 //
1729
1731
1732 //
1733 // Ref the root dir stream object so we can send mount notification.
1734 //
1735
1736 RootDirectoryFile = Vcb->RootDcb->Specific.Dcb.DirectoryFile;
1737 ObReferenceObject( RootDirectoryFile );
1738
1739 //
1740 // Remove the extra reference to this target DO made on behalf of us
1741 // by the IO system. In the remount case, we permit regular Vcb
1742 // deletion to do this work.
1743 //
1744
1746
1747
1748 try_exit: NOTHING;
1749
1750 } _SEH2_FINALLY {
1751
1752 DebugUnwind( FatMountVolume );
1753
1754 FatUnpinBcb( IrpContext, BootBcb );
1755 FatUnpinBcb( IrpContext, DirentBcb );
1756
1757 //
1758 // Check if a volume was mounted. If not then we need to
1759 // mark the Vpb not mounted again.
1760 //
1761
1762 if ( !MountNewVolume ) {
1763
1764 if ( Vcb != NULL ) {
1765
1766 //
1767 // A VCB was created and initialized. We need to try to tear it down.
1768 //
1769
1770 FatCheckForDismount( IrpContext,
1771 Vcb,
1772 TRUE );
1773
1774 IrpContext->Vcb = NULL;
1775
1776 } else if (VolDo != NULL) {
1777
1778 //
1779 // The VCB was never initialized, so we need to delete the
1780 // device right here.
1781 //
1782
1783 IoDeleteDevice( &VolDo->DeviceObject );
1784 }
1785
1786 //
1787 // See if a remount failed.
1788 //
1789
1790 if (DoARemount && _SEH2_AbnormalTermination()) {
1791
1792 //
1793 // The remount failed. Try to tear down the old VCB as well.
1794 //
1795
1796 FatCheckForDismount( IrpContext,
1797 OldVcb,
1798 TRUE );
1799 }
1800 }
1801
1802 if ( WeClearedVerifyRequiredBit == TRUE ) {
1803
1804 SetFlag(RealDevice->Flags, DO_VERIFY_VOLUME);
1805 }
1806
1807 FatReleaseGlobal( IrpContext );
1808
1809 DebugTrace(-1, Dbg, "FatMountVolume -> %08lx\n", Status);
1810 } _SEH2_END;
1811
1812 //
1813 // Now send mount notification. Note that since this is outside of any
1814 // synchronization since the synchronous delivery of this may go to
1815 // folks that provoke re-entrance to the FS.
1816 //
1817
1818 if (RootDirectoryFile != NULL) {
1819
1820#if (NTDDI_VERSION >= NTDDI_WIN8)
1822
1823 CcSetAdditionalCacheAttributesEx( RootDirectoryFile, CC_ENABLE_DISK_IO_ACCOUNTING );
1824 }
1825#endif
1826
1827 FsRtlNotifyVolumeEvent( RootDirectoryFile, FSRTL_VOLUME_MOUNT );
1828 ObDereferenceObject( RootDirectoryFile );
1829 }
1830
1831 return Status;
1832}
1833
1834
1835//
1836// Local Support Routine
1837//
1838
1839_Requires_lock_held_(_Global_critical_region_)
1841FatVerifyVolume (
1842 IN PIRP_CONTEXT IrpContext,
1843 IN PIRP Irp
1844 )
1845
1846/*++
1847
1848Routine Description:
1849
1850 This routine performs the verify volume operation by checking the volume
1851 label and serial number physically on the media with the the Vcb
1852 currently claiming to have the volume mounted. It is responsible for
1853 either completing or enqueuing the input Irp.
1854
1855 Regardless of whether the verify operation succeeds, the following
1856 operations are performed:
1857
1858 - Set Vcb->VirtualEaFile back to its initial state.
1859 - Purge all cached data (flushing first if verify succeeds)
1860 - Mark all Fcbs as needing verification
1861
1862 If the volumes verifies correctly we also must:
1863
1864 - Check the volume dirty bit.
1865 - Reinitialize the allocation support
1866 - Flush any dirty data
1867
1868 If the volume verify fails, it may never be mounted again. If it is
1869 mounted again, it will happen as a remount operation. In preparation
1870 for that, and to leave the volume in a state that can be "lazy deleted"
1871 the following operations are performed:
1872
1873 - Set the Vcb condition to VcbNotMounted
1874 - Uninitialize the volume file cachemap
1875 - Tear down the allocation support
1876
1877 In the case of an abnormal termination we haven't determined the state
1878 of the volume, so we set the Device Object as needing verification again.
1879
1880Arguments:
1881
1882 Irp - Supplies the Irp to process
1883
1884Return Value:
1885
1886 NTSTATUS - If the verify operation completes, it will return either
1887 STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly. If an IO or
1888 other error is encountered, that status will be returned.
1889
1890--*/
1891
1892{
1894
1896
1899
1901
1903 PVCB Vcb;
1904 PVPB Vpb;
1905
1907 BOOLEAN ClearVerify = FALSE;
1908 BOOLEAN ReleaseEntireVolume = FALSE;
1909 BOOLEAN VerifyAlreadyDone = FALSE;
1910
1911 DISK_GEOMETRY DiskGeometry;
1912
1913 LBO RootDirectoryLbo;
1914 ULONG RootDirectorySize;
1915 BOOLEAN LabelFound;
1916
1917 ULONG ChangeCount = 0;
1918 IO_STATUS_BLOCK Iosb = {0};
1919
1920 PAGED_CODE();
1921
1922 //
1923 // Get the current Irp stack location
1924 //
1925
1927
1928 DebugTrace(+1, Dbg, "FatVerifyVolume\n", 0);
1929 DebugTrace( 0, Dbg, "DeviceObject = %p\n", IrpSp->Parameters.VerifyVolume.DeviceObject);
1930 DebugTrace( 0, Dbg, "Vpb = %p\n", IrpSp->Parameters.VerifyVolume.Vpb);
1931
1932 //
1933 // Save some references to make our life a little easier. Note the Vcb for the purposes
1934 // of exception handling.
1935 //
1936
1937 VolDo = (PVOLUME_DEVICE_OBJECT)IrpSp->Parameters.VerifyVolume.DeviceObject;
1938
1939 Vpb = IrpSp->Parameters.VerifyVolume.Vpb;
1940 IrpContext->Vcb = Vcb = &VolDo->Vcb;
1941
1942 //
1943 // If we cannot wait then enqueue the irp to the fsp and
1944 // return the status to our caller.
1945 //
1946
1947 if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
1948
1949 DebugTrace(0, Dbg, "Cannot wait for verify.\n", 0);
1950
1951 Status = FatFsdPostRequest( IrpContext, Irp );
1952
1953 DebugTrace(-1, Dbg, "FatVerifyVolume -> %08lx\n", Status );
1954 return Status;
1955 }
1956
1957 //
1958 // We are serialized at this point allowing only one thread to
1959 // actually perform the verify operation. Any others will just
1960 // wait and then no-op when checking if the volume still needs
1961 // verification.
1962 //
1963
1964#ifdef _MSC_VER
1965#pragma prefast( push )
1966#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
1967#pragma prefast( disable: 28193, "this will always wait" )
1968#endif
1969
1970 (VOID)FatAcquireExclusiveGlobal( IrpContext );
1971
1972#ifdef _MSC_VER
1973#pragma prefast( pop )
1974#endif
1975
1976 (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
1977
1978 _SEH2_TRY {
1979
1980 BOOLEAN AllowRawMount = BooleanFlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT );
1981
1982 //
1983 // Mark ourselves as verifying this volume so that recursive I/Os
1984 // will be able to complete.
1985 //
1986
1987 NT_ASSERT( Vcb->VerifyThread == NULL );
1988 Vcb->VerifyThread = KeGetCurrentThread();
1989
1990 //
1991 // Check if the real device still needs to be verified. If it doesn't
1992 // then obviously someone beat us here and already did the work
1993 // so complete the verify irp with success. Otherwise reenable
1994 // the real device and get to work.
1995 //
1996
1997 if (!FlagOn(Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) {
1998
1999 DebugTrace(0, Dbg, "RealDevice has already been verified\n", 0);
2000
2001 VerifyAlreadyDone = TRUE;
2003 }
2004
2005 //
2006 // Ping the volume with a partition query to make Jeff happy.
2007 //
2008
2009 {
2010 PARTITION_INFORMATION_EX PartitionInformation;
2011
2012 (VOID) FatPerformDevIoCtrl( IrpContext,
2014 Vcb->TargetDeviceObject,
2015 NULL,
2016 0,
2017 &PartitionInformation,
2019 FALSE,
2020 TRUE,
2021 &Iosb );
2022 }
2023
2024 //
2025 // Only send down IOCTL_DISK_CHECK_VERIFY if it is removable media.
2026 //
2027
2028 if (FlagOn(Vcb->TargetDeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
2029
2030 //
2031 // Verify that there is a disk here and pick up the change count.
2032 //
2033
2034 Status = FatPerformDevIoCtrl( IrpContext,
2036 Vcb->TargetDeviceObject,
2037 NULL,
2038 0,
2039 &ChangeCount,
2040 sizeof(ULONG),
2041 FALSE,
2042 TRUE,
2043 &Iosb );
2044
2045 if (!NT_SUCCESS( Status )) {
2046
2047 //
2048 // If we will allow a raw mount then return WRONG_VOLUME to
2049 // allow the volume to be mounted by raw.
2050 //
2051
2052 if (AllowRawMount) {
2053
2055 }
2056
2057 FatNormalizeAndRaiseStatus( IrpContext, Status );
2058 }
2059
2060 }
2061
2062 if (Iosb.Information != sizeof(ULONG)) {
2063
2064 //
2065 // Be safe about the count in case the driver didn't fill it in
2066 //
2067
2068 ChangeCount = 0;
2069 }
2070
2071 //
2072 // Whatever happens we will have verified this volume at this change
2073 // count, so record that fact.
2074 //
2075
2076 Vcb->ChangeCount = ChangeCount;
2077
2078 //
2079 // If this is a CD class device, then check to see if there is a
2080 // 'data track' or not. This is to avoid issuing paging reads which will
2081 // fail later in the mount process (e.g. CD-DA or blank CD media)
2082 //
2083
2084 if ((Vcb->TargetDeviceObject->DeviceType == FILE_DEVICE_CD_ROM) &&
2085 !FatScanForDataTrack( IrpContext, Vcb->TargetDeviceObject)) {
2086
2088 }
2089
2090 //
2091 // Some devices can change sector sizes on the fly. Obviously, it
2092 // isn't the same volume if that happens.
2093 //
2094
2095 Status = FatPerformDevIoCtrl( IrpContext,
2097 Vcb->TargetDeviceObject,
2098 NULL,
2099 0,
2100 &DiskGeometry,
2101 sizeof( DISK_GEOMETRY ),
2102 FALSE,
2103 TRUE,
2104 NULL );
2105
2106 if (!NT_SUCCESS( Status )) {
2107
2108 //
2109 // If we will allow a raw mount then return WRONG_VOLUME to
2110 // allow the volume to be mounted by raw.
2111 //
2112
2113 if (AllowRawMount) {
2114
2116 }
2117
2118 FatNormalizeAndRaiseStatus( IrpContext, Status );
2119 }
2120
2121 //
2122 // Read in the boot sector
2123 //
2124
2125 SectorSize = (ULONG)Vcb->Bpb.BytesPerSector;
2126
2127 if (SectorSize != DiskGeometry.BytesPerSector) {
2128
2130 }
2131
2132 BootSector = FsRtlAllocatePoolWithTag(NonPagedPoolNxCacheAligned,
2135
2136 //
2137 // If this verify is on behalf of a DASD open, allow a RAW mount.
2138 //
2139
2140 if (!FatPerformVerifyDiskRead( IrpContext,
2141 Vcb,
2142 BootSector,
2143 0,
2144 SectorSize,
2145 AllowRawMount )) {
2146
2148 }
2149
2150 //
2151 // Call a routine to check the boot sector to see if it is fat.
2152 // If it is not fat then mark the vcb as not mounted tell our
2153 // caller its the wrong volume
2154 //
2155
2157
2158 DebugTrace(0, Dbg, "Not a Fat Volume\n", 0);
2159
2161 }
2162
2163 //
2164 // This is a fat volume, so extract serial number and see if it is
2165 // ours.
2166 //
2167
2168 {
2170
2171 if (IsBpbFat32(&BootSector->PackedBpb)) {
2173 } else {
2175 }
2176
2177 if (SerialNumber != Vpb->SerialNumber) {
2178
2179 DebugTrace(0, Dbg, "Not our serial number\n", 0);
2180
2182 }
2183 }
2184
2185 //
2186 // Make sure the Bpbs are not different. We have to zero out our
2187 // stack version of the Bpb since unpacking leaves holes.
2188 //
2189
2190 RtlZeroMemory( &Bpb, sizeof(BIOS_PARAMETER_BLOCK) );
2191
2192 FatUnpackBios( &Bpb, &BootSector->PackedBpb );
2193 if (Bpb.Sectors != 0) { Bpb.LargeSectors = 0; }
2194
2195 if ( !RtlEqualMemory( &Bpb,
2196 &Vcb->Bpb,
2197 IsBpbFat32(&Bpb) ?
2198 sizeof(BIOS_PARAMETER_BLOCK) :
2200 LargeSectorsPerFat) )) {
2201
2202 DebugTrace(0, Dbg, "Bpb is different\n", 0);
2203
2205 }
2206
2207 //
2208 // Check the volume label. We do this by trying to locate the
2209 // volume label, making two strings one for the saved volume label
2210 // and the other for the new volume label and then we compare the
2211 // two labels.
2212 //
2213
2214 if (FatRootDirectorySize(&Bpb) > 0) {
2215
2216 RootDirectorySize = FatRootDirectorySize(&Bpb);
2217
2218 } else {
2219
2220 RootDirectorySize = FatBytesPerCluster(&Bpb);
2221 }
2222
2223 RootDirectory = FsRtlAllocatePoolWithTag( NonPagedPoolNxCacheAligned,
2224 (ULONG) ROUND_TO_PAGES( RootDirectorySize ),
2226
2227 if (!IsBpbFat32(&BootSector->PackedBpb)) {
2228
2229 //
2230 // The Fat12/16 case is simple -- read the root directory in and
2231 // search it.
2232 //
2233
2234 RootDirectoryLbo = FatRootDirectoryLbo(&Bpb);
2235
2236 if (!FatPerformVerifyDiskRead( IrpContext,
2237 Vcb,
2239 RootDirectoryLbo,
2240 RootDirectorySize,
2241 AllowRawMount )) {
2242
2244 }
2245
2246 Status = FatSearchBufferForLabel(IrpContext, Vpb,
2247 RootDirectory, RootDirectorySize,
2248 &LabelFound);
2249
2250 if (!NT_SUCCESS(Status)) {
2251
2252 try_return( Status );
2253 }
2254
2255 if (!LabelFound && Vpb->VolumeLabelLength > 0) {
2256
2258 }
2259
2260 } else {
2261
2262 ULONG RootDirectoryCluster;
2263
2264 RootDirectoryCluster = Bpb.RootDirFirstCluster;
2265
2266 while (RootDirectoryCluster != FAT_CLUSTER_LAST) {
2267
2268 RootDirectoryLbo = FatGetLboFromIndex(Vcb, RootDirectoryCluster);
2269
2270 if (!FatPerformVerifyDiskRead( IrpContext,
2271 Vcb,
2273 RootDirectoryLbo,
2274 RootDirectorySize,
2275 AllowRawMount )) {
2276
2278 }
2279
2280 Status = FatSearchBufferForLabel(IrpContext, Vpb,
2281 RootDirectory, RootDirectorySize,
2282 &LabelFound);
2283
2284 if (!NT_SUCCESS(Status)) {
2285
2286 try_return( Status );
2287 }
2288
2289 if (LabelFound) {
2290
2291 //
2292 // Found a matching label.
2293 //
2294
2295 break;
2296 }
2297
2298 //
2299 // Set ourselves up for the next loop iteration.
2300 //
2301
2302 FatVerifyLookupFatEntry( IrpContext, Vcb,
2303 RootDirectoryCluster,
2304 &RootDirectoryCluster );
2305
2306 switch (FatInterpretClusterType(Vcb, RootDirectoryCluster)) {
2307
2309 case FatClusterReserved:
2310 case FatClusterBad:
2311
2312 //
2313 // Bail all the way out if we have a bad root.
2314 //
2315
2317 break;
2318
2319 default:
2320
2321 break;
2322 }
2323
2324 }
2325
2326 if (RootDirectoryCluster == FAT_CLUSTER_LAST &&
2327 Vpb->VolumeLabelLength > 0) {
2328
2329 //
2330 // Should have found a label, didn't find any.
2331 //
2332
2334 }
2335 }
2336
2337
2338 try_exit: NOTHING;
2339
2340 //
2341 // Note that we have previously acquired the Vcb to serialize
2342 // the EA file stuff the marking all the Fcbs as NeedToBeVerified.
2343 //
2344 // Put the Ea file back in a initial state.
2345 //
2346
2347 FatCloseEaFile( IrpContext, Vcb, (BOOLEAN)(Status == STATUS_SUCCESS) );
2348
2349 //
2350 // Mark all Fcbs as needing verification, but only if we really have
2351 // to do it.
2352 //
2353
2354 if (!VerifyAlreadyDone) {
2355
2356 FatAcquireExclusiveVolume( IrpContext, Vcb );
2357 ReleaseEntireVolume = TRUE;
2358
2359 FatMarkFcbCondition( IrpContext, Vcb->RootDcb, FcbNeedsToBeVerified, TRUE );
2360 }
2361
2362 //
2363 // If the verify didn't succeed, get the volume ready for a
2364 // remount or eventual deletion.
2365 //
2366
2367 if (Vcb->VcbCondition == VcbNotMounted) {
2368
2369 //
2370 // If the volume was already in an unmounted state, just bail
2371 // and make sure we return STATUS_WRONG_VOLUME.
2372 //
2373
2375
2376 } else if ( Status == STATUS_WRONG_VOLUME ) {
2377
2378 //
2379 // Grab everything so we can safely transition the volume state without
2380 // having a thread stumble into the torn-down allocation engine.
2381 //
2382
2383 if (!ReleaseEntireVolume) {
2384 FatAcquireExclusiveVolume( IrpContext, Vcb );
2385 ReleaseEntireVolume = TRUE;
2386 }
2387
2388 //
2389 // Get rid of any cached data, without flushing
2390 //
2391
2392 FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, NoFlush );
2393
2394 //
2395 // Uninitialize the volume file cache map. Note that we cannot
2396 // do a "FatSyncUninit" because of deadlock problems. However,
2397 // since this FileObject is referenced by us, and thus included
2398 // in the Vpb residual count, it is OK to do a normal CcUninit.
2399 //
2400
2401 CcUninitializeCacheMap( Vcb->VirtualVolumeFile,
2402 &FatLargeZero,
2403 NULL );
2404
2405 FatTearDownAllocationSupport( IrpContext, Vcb );
2406
2408
2409 ClearVerify = TRUE;
2410
2411 } else if (!VerifyAlreadyDone) {
2412
2413 //
2414 // Grab everything so we can safely transition the volume state without
2415 // having a thread stumble into the torn-down allocation engine.
2416 //
2417
2418 if (!ReleaseEntireVolume) {
2419 FatAcquireExclusiveVolume( IrpContext, Vcb );
2420 ReleaseEntireVolume = TRUE;
2421 }
2422
2423 //
2424 // Get rid of any cached data, flushing first.
2425 //
2426 // Future work (and for bonus points, around the other flush points)
2427 // could address the possibility that the dirent filesize hasn't been
2428 // updated yet, causing us to fail the re-verification of a file in
2429 // DetermineAndMark. This is pretty subtle and very very uncommon.
2430 //
2431
2432 FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
2433
2434 //
2435 // Flush and Purge the volume file.
2436 //
2437
2438 (VOID)FatFlushFat( IrpContext, Vcb );
2439 CcPurgeCacheSection( &Vcb->SectionObjectPointers, NULL, 0, FALSE );
2440
2441 //
2442 // Redo the allocation support with newly paged stuff.
2443 //
2444
2445 FatTearDownAllocationSupport( IrpContext, Vcb );
2446 FatSetupAllocationSupport( IrpContext, Vcb );
2447
2448 FatCheckDirtyBit( IrpContext, Vcb );
2449
2450 //
2451 // Check for write protected media.
2452 //
2453
2454 if (FatIsMediaWriteProtected(IrpContext, Vcb->TargetDeviceObject)) {
2455
2457
2458 } else {
2459
2461 }
2462
2463 ClearVerify = TRUE;
2464 }
2465
2466 if (ClearVerify) {
2467
2468 //
2469 // Mark the device as no longer needing verification.
2470 //
2471
2472 ClearFlag( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
2473 }
2474
2475 } _SEH2_FINALLY {
2476
2477 DebugUnwind( FatVerifyVolume );
2478
2479 //
2480 // Free any buffer we may have allocated
2481 //
2482
2483 if ( BootSector != NULL ) { ExFreePool( BootSector ); }
2484 if ( RootDirectory != NULL ) { ExFreePool( RootDirectory ); }
2485
2486 //
2487 // Show that we are done with this volume.
2488 //
2489
2490 NT_ASSERT( Vcb->VerifyThread == KeGetCurrentThread() );
2491 Vcb->VerifyThread = NULL;
2492
2493 if (ReleaseEntireVolume) {
2494
2495 FatReleaseVolume( IrpContext, Vcb );
2496 }
2497
2498 FatReleaseVcb( IrpContext, Vcb );
2499 FatReleaseGlobal( IrpContext );
2500
2501 //
2502 // If this was not an abnormal termination, complete the irp.
2503 //
2504
2506
2507 FatCompleteRequest( IrpContext, Irp, Status );
2508 }
2509
2510 DebugTrace(-1, Dbg, "FatVerifyVolume -> %08lx\n", Status);
2511 } _SEH2_END;
2512
2513 return Status;
2514}
2515
2516
2517//
2518// Local Support Routine
2519//
2520
2521BOOLEAN
2524 )
2525
2526/*++
2527
2528Routine Description:
2529
2530 This routine checks if the boot sector is for a fat file volume.
2531
2532Arguments:
2533
2534 BootSector - Supplies the packed boot sector to check
2535
2536Return Value:
2537
2538 BOOLEAN - TRUE if the volume is Fat and FALSE otherwise.
2539
2540--*/
2541
2542{
2544 BIOS_PARAMETER_BLOCK Bpb = {0};
2545
2546 DebugTrace(+1, Dbg, "FatIsBootSectorFat, BootSector = %p\n", BootSector);
2547
2548 //
2549 // The result is true unless we decide that it should be false
2550 //
2551
2552 Result = TRUE;
2553
2554 //
2555 // Unpack the bios and then test everything
2556 //
2557
2558 FatUnpackBios( &Bpb, &BootSector->PackedBpb );
2559 if (Bpb.Sectors != 0) { Bpb.LargeSectors = 0; }
2560
2561 if ((BootSector->Jump[0] != 0xe9) &&
2562 (BootSector->Jump[0] != 0xeb) &&
2563 (BootSector->Jump[0] != 0x49)) {
2564
2565 Result = FALSE;
2566
2567 //
2568 // Enforce some sanity on the sector size (easy check)
2569 //
2570
2571 } else if ((Bpb.BytesPerSector != 128) &&
2572 (Bpb.BytesPerSector != 256) &&
2573 (Bpb.BytesPerSector != 512) &&
2574 (Bpb.BytesPerSector != 1024) &&
2575 (Bpb.BytesPerSector != 2048) &&
2576 (Bpb.BytesPerSector != 4096)) {
2577
2578 Result = FALSE;
2579
2580 //
2581 // Likewise on the clustering.
2582 //
2583
2584 } else if ((Bpb.SectorsPerCluster != 1) &&
2585 (Bpb.SectorsPerCluster != 2) &&
2586 (Bpb.SectorsPerCluster != 4) &&
2587 (Bpb.SectorsPerCluster != 8) &&
2588 (Bpb.SectorsPerCluster != 16) &&
2589 (Bpb.SectorsPerCluster != 32) &&
2590 (Bpb.SectorsPerCluster != 64) &&
2591 (Bpb.SectorsPerCluster != 128)) {
2592
2593 Result = FALSE;
2594
2595 //
2596 // Likewise on the reserved sectors (must reflect at least the boot sector!)
2597 //
2598
2599 } else if (Bpb.ReservedSectors == 0) {
2600
2601 Result = FALSE;
2602
2603 //
2604 // No FATs? Wrong ...
2605 //
2606
2607 } else if (Bpb.Fats == 0) {
2608
2609 Result = FALSE;
2610
2611 //
2612 // Prior to DOS 3.2 might contains value in both of Sectors and
2613 // Sectors Large.
2614 //
2615
2616 } else if ((Bpb.Sectors == 0) && (Bpb.LargeSectors == 0)) {
2617
2618 Result = FALSE;
2619
2620 //
2621 // Check that FAT32 (SectorsPerFat == 0) claims some FAT space and
2622 // is of a version we recognize, currently Version 0.0.
2623 //
2624
2625 } else if (Bpb.SectorsPerFat == 0 && ( Bpb.LargeSectorsPerFat == 0 ||
2626 Bpb.FsVersion != 0 )) {
2627
2628 Result = FALSE;
2629
2630 } else if ((Bpb.Media != 0xf0) &&
2631 (Bpb.Media != 0xf8) &&
2632 (Bpb.Media != 0xf9) &&
2633 (Bpb.Media != 0xfb) &&
2634 (Bpb.Media != 0xfc) &&
2635 (Bpb.Media != 0xfd) &&
2636 (Bpb.Media != 0xfe) &&
2637 (Bpb.Media != 0xff) &&
2638 (!FatData.FujitsuFMR || ((Bpb.Media != 0x00) &&
2639 (Bpb.Media != 0x01) &&
2640 (Bpb.Media != 0xfa)))) {
2641
2642 Result = FALSE;
2643
2644 //
2645 // If this isn't FAT32, then there better be a claimed root directory
2646 // size here ...
2647 //
2648
2649 } else if (Bpb.SectorsPerFat != 0 && Bpb.RootEntries == 0) {
2650
2651 Result = FALSE;
2652
2653 //
2654 // If this is FAT32 (i.e., extended BPB), look for and refuse to mount
2655 // mirror-disabled volumes. If we did, we would need to only write to
2656 // the FAT# indicated in the ActiveFat field. The only user of this is
2657 // the FAT->FAT32 converter after the first pass of protected mode work
2658 // (booting into realmode) and NT should absolutely not be attempting
2659 // to mount such an in-transition volume.
2660 //
2661
2662 } else if (Bpb.SectorsPerFat == 0 && Bpb.MirrorDisabled) {
2663
2664 Result = FALSE;
2665 }
2666
2667 DebugTrace(-1, Dbg, "FatIsBootSectorFat -> %08lx\n", Result);
2668
2669 return Result;
2670}
2671
2672
2673//
2674// Local Support Routine
2675//
2676
2677BOOLEAN
2679 IN PIRP_CONTEXT IrpContext,
2681 )
2682
2683/*++
2684
2685Routine Description:
2686
2687 This routine determines if the target media is write protected.
2688
2689Arguments:
2690
2691 TargetDeviceObject - The target of the query
2692
2693Return Value:
2694
2695 NTSTATUS - The return status for the operation
2696
2697--*/
2698
2699{
2700 PIRP Irp;
2701 KEVENT Event;
2704
2705 PAGED_CODE();
2706 UNREFERENCED_PARAMETER( IrpContext );
2707
2708 //
2709 // Query the partition table
2710 //
2711
2713
2714 //
2715 // See if the media is write protected. On success or any kind
2716 // of error (possibly illegal device function), assume it is
2717 // writeable, and only complain if he tells us he is write protected.
2718 //
2719
2722 NULL,
2723 0,
2724 NULL,
2725 0,
2726 FALSE,
2727 &Event,
2728 &Iosb );
2729
2730 //
2731 // Just return FALSE in the unlikely event we couldn't allocate an Irp.
2732 //
2733
2734 if ( Irp == NULL ) {
2735
2736 return FALSE;
2737 }
2738
2740
2742
2743 if ( Status == STATUS_PENDING ) {
2744
2746 Executive,
2747 KernelMode,
2748 FALSE,
2750
2751 Status = Iosb.Status;
2752 }
2753
2755}
2756
2757
2758//
2759// Local Support Routine
2760//
2761
2762_Requires_lock_held_(_Global_critical_region_)
2764FatUserFsCtrl (
2765 IN PIRP_CONTEXT IrpContext,
2766 IN PIRP Irp
2767 )
2768
2769/*++
2770
2771Routine Description:
2772
2773 This is the common routine for implementing the user's requests made
2774 through NtFsControlFile.
2775
2776Arguments:
2777
2778 Irp - Supplies the Irp being processed
2779
2780Return Value:
2781
2782 NTSTATUS - The return status for the operation
2783
2784--*/
2785
2786{
2789
2791
2792 PAGED_CODE();
2793
2794 //
2795 // Save some references to make our life a little easier
2796 //
2797
2798 FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
2799
2800 DebugTrace(+1, Dbg,"FatUserFsCtrl...\n", 0);
2801 DebugTrace( 0, Dbg,"FsControlCode = %08lx\n", FsControlCode);
2802
2803 //
2804 // Some of these Fs Controls use METHOD_NEITHER buffering. If the previous mode
2805 // of the caller was userspace and this is a METHOD_NEITHER, we have the choice
2806 // of realy buffering the request through so we can possibly post, or making the
2807 // request synchronous. Since the former was not done by design, do the latter.
2808 //
2809
2810 if (Irp->RequestorMode != KernelMode && (FsControlCode & 3) == METHOD_NEITHER) {
2811
2812 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
2813 }
2814
2815 //
2816 // Case on the control code.
2817 //
2818
2819 switch ( FsControlCode ) {
2820
2829#if (NTDDI_VERSION >= NTDDI_WIN7)
2830 case FSCTL_REQUEST_OPLOCK:
2831#endif
2832 Status = FatOplockRequest( IrpContext, Irp );
2833 break;
2834
2835 case FSCTL_LOCK_VOLUME:
2836
2837 Status = FatLockVolume( IrpContext, Irp );
2838 break;
2839
2841
2842 Status = FatUnlockVolume( IrpContext, Irp );
2843 break;
2844
2846
2847 Status = FatDismountVolume( IrpContext, Irp );
2848 break;
2849
2851
2852 Status = FatDirtyVolume( IrpContext, Irp );
2853 break;
2854
2856
2857 Status = FatIsVolumeDirty( IrpContext, Irp );
2858 break;
2859
2861
2862 Status = FatIsVolumeMounted( IrpContext, Irp );
2863 break;
2864
2866 Status = FatIsPathnameValid( IrpContext, Irp );
2867 break;
2868
2870 Status = FatQueryRetrievalPointers( IrpContext, Irp );
2871 break;
2872
2874 Status = FatQueryBpb( IrpContext, Irp );
2875 break;
2876
2878 Status = FatGetStatistics( IrpContext, Irp );
2879 break;
2880
2881#if (NTDDI_VERSION >= NTDDI_WIN7)
2883 Status = FatGetRetrievalPointerBase( IrpContext, Irp );
2884 break;
2885
2886 case FSCTL_GET_BOOT_AREA_INFO:
2887 Status = FatGetBootAreaInfo( IrpContext, Irp );
2888 break;
2889#endif
2890
2892 Status = FatGetVolumeBitmap( IrpContext, Irp );
2893 break;
2894
2896 Status = FatGetRetrievalPointers( IrpContext, Irp );
2897 break;
2898
2899 case FSCTL_MOVE_FILE:
2900 Status = FatMoveFile( IrpContext, Irp );
2901 break;
2902
2904 Status = FatAllowExtendedDasdIo( IrpContext, Irp );
2905 break;
2906
2907 case FSCTL_MARK_HANDLE:
2908 Status = FatMarkHandle( IrpContext, Irp );
2909 break;
2910
2911#if (NTDDI_VERSION >= NTDDI_WIN8)
2912
2913 case FSCTL_SET_PURGE_FAILURE_MODE:
2914 Status = FatSetPurgeFailureMode( IrpContext, Irp );
2915 break;
2916
2917#endif
2918
2919
2920#if (NTDDI_VERSION >= NTDDI_WIN7)
2922 Status = FatSetZeroOnDeallocate( IrpContext, Irp );
2923 break;
2924#endif
2925
2926 default :
2927
2928 DebugTrace(0, Dbg, "Invalid control code -> %08lx\n", FsControlCode );
2929
2932 break;
2933 }
2934
2935 DebugTrace(-1, Dbg, "FatUserFsCtrl -> %08lx\n", Status );
2936 return Status;
2937}
2938
2939
2940
2941//
2942// Local support routine
2943//
2944
2945_Requires_lock_held_(_Global_critical_region_)
2947FatOplockRequest (
2948 _In_ PIRP_CONTEXT IrpContext,
2949 _In_ PIRP Irp
2950 )
2951
2952/*++
2953
2954Routine Description:
2955
2956 This is the common routine to handle oplock requests made via the
2957 NtFsControlFile call.
2958
2959Arguments:
2960
2961 Irp - Supplies the Irp being processed
2962
2963Return Value:
2964
2965 NTSTATUS - The return status for the operation
2966
2967--*/
2968
2969{
2972 PFCB Fcb;
2973 PVCB Vcb;
2974 PCCB Ccb;
2975
2976 ULONG OplockCount = 0;
2977
2979
2980 BOOLEAN AcquiredVcb = FALSE;
2981 BOOLEAN AcquiredFcb = FALSE;
2982
2983#if (NTDDI_VERSION >= NTDDI_WIN7)
2984 PREQUEST_OPLOCK_INPUT_BUFFER InputBuffer = NULL;
2987#endif
2988
2990
2991 PAGED_CODE();
2992
2993 //
2994 // Save some references to make our life a little easier
2995 //
2996
2997 FsControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
2998
3000
3001 DebugTrace(+1, Dbg, "FatOplockRequest...\n", 0);
3002 DebugTrace( 0, Dbg, "FsControlCode = %08lx\n", FsControlCode);
3003
3004 //
3005 // We permit oplock requests on files and directories.
3006 //
3007
3008 if ((TypeOfOpen != UserFileOpen)
3010 &&
3012#endif
3013 ) {
3014
3016 DebugTrace(-1, Dbg, "FatOplockRequest -> STATUS_INVALID_PARAMETER\n", 0);
3018 }
3019
3020#if (NTDDI_VERSION >= NTDDI_WIN7)
3021
3022 //
3023 // Get the input & output buffer lengths and pointers.
3024 //
3025
3026 if (FsControlCode == FSCTL_REQUEST_OPLOCK) {
3027
3028 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
3029 InputBuffer = (PREQUEST_OPLOCK_INPUT_BUFFER) Irp->AssociatedIrp.SystemBuffer;
3030
3031 OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
3032
3033 //
3034 // Check for a minimum length on the input and ouput buffers.
3035 //
3036
3037 if ((InputBufferLength < sizeof( REQUEST_OPLOCK_INPUT_BUFFER )) ||
3038 (OutputBufferLength < sizeof( REQUEST_OPLOCK_OUTPUT_BUFFER ))) {
3039
3041 DebugTrace(-1, Dbg, "FatOplockRequest -> STATUS_BUFFER_TOO_SMALL\n", 0);
3043 }
3044 }
3045
3046 //
3047 // If the oplock request is on a directory it must be for a Read or Read-Handle
3048 // oplock only.
3049 //
3050
3051 if ((TypeOfOpen == UserDirectoryOpen) &&
3052 ((FsControlCode != FSCTL_REQUEST_OPLOCK) ||
3053 !FsRtlOplockIsSharedRequest( Irp ))) {
3054
3056 DebugTrace(-1, Dbg, "FatOplockRequest -> STATUS_INVALID_PARAMETER\n", 0);
3058 }
3059
3060#endif
3061
3062 //
3063 // Make this a waitable Irpcontext so we don't fail to acquire
3064 // the resources.
3065 //
3066
3067 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
3068
3069 //
3070 // Use a try finally to free the Fcb/Vcb
3071 //
3072
3073 _SEH2_TRY {
3074
3075 //
3076 // We grab the Fcb exclusively for oplock requests, shared for oplock
3077 // break acknowledgement.
3078 //
3079
3085 ||
3086 ((FsControlCode == FSCTL_REQUEST_OPLOCK) && FlagOn( InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_REQUEST ))
3087#endif
3088 ) {
3089
3090 FatAcquireSharedVcb( IrpContext, Fcb->Vcb );
3091 AcquiredVcb = TRUE;
3092 FatAcquireExclusiveFcb( IrpContext, Fcb );
3093 AcquiredFcb = TRUE;
3094
3095#if (NTDDI_VERSION >= NTDDI_WIN7)
3096 if (FsRtlOplockIsSharedRequest( Irp )) {
3097#else
3099#endif
3100
3101 //
3102 // Byte-range locks are only valid on files.
3103 //
3104
3105 if (TypeOfOpen == UserFileOpen) {
3106
3107 //
3108 // Set OplockCount to nonzero if FsRtl denies access
3109 // based on current byte-range lock state.
3110 //
3111
3112#if (NTDDI_VERSION >= NTDDI_WIN8)
3113 OplockCount = (ULONG) !FsRtlCheckLockForOplockRequest( &Fcb->Specific.Fcb.FileLock, &Fcb->Header.AllocationSize );
3114#elif (NTDDI_VERSION >= NTDDI_WIN7)
3115 OplockCount = (ULONG) FsRtlAreThereCurrentOrInProgressFileLocks( &Fcb->Specific.Fcb.FileLock );
3116#else
3117 OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks( &Fcb->Specific.Fcb.FileLock );
3118#endif
3119
3120 }
3121
3122 } else {
3123
3124 OplockCount = Fcb->UncleanCount;
3125 }
3126
3132 ||
3133 ((FsControlCode == FSCTL_REQUEST_OPLOCK) && FlagOn( InputBuffer->Flags, REQUEST_OPLOCK_INPUT_FLAG_ACK ))
3134#endif
3135 ) {
3136
3137 FatAcquireSharedFcb( IrpContext, Fcb );
3138 AcquiredFcb = TRUE;
3139#if (NTDDI_VERSION >= NTDDI_WIN7)
3140 } else if (FsControlCode == FSCTL_REQUEST_OPLOCK) {
3141
3142 //
3143 // The caller didn't provide either REQUEST_OPLOCK_INPUT_FLAG_REQUEST or
3144 // REQUEST_OPLOCK_INPUT_FLAG_ACK on the input buffer.
3145 //
3146
3148
3149 } else {
3150#else
3151 } else {
3152#endif
3153
3154#ifdef _MSC_VER
3155#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
3156#endif
3157 FatBugCheck( FsControlCode, 0, 0 );
3158 }
3159
3160 //
3161 // Fail batch, filter, and handle oplock requests if the file is marked
3162 // for delete.
3163 //
3164
3168 ||
3169 ((FsControlCode == FSCTL_REQUEST_OPLOCK) && FlagOn( InputBuffer->RequestedOplockLevel, OPLOCK_LEVEL_CACHE_HANDLE ))
3170#endif
3171 ) &&
3173
3175 }
3176
3177 //
3178 // Call the FsRtl routine to grant/acknowledge oplock.
3179 //
3180
3182 Irp,
3183 OplockCount );
3184
3185 //
3186 // Once we call FsRtlOplockFsctrl, we no longer own the IRP and we should not complete it.
3187 //
3188
3189 Irp = NULL;
3190
3191 //
3192 // Set the flag indicating if Fast I/O is possible
3193 //
3194
3195 Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
3196
3197 } _SEH2_FINALLY {
3198
3199 DebugUnwind( FatOplockRequest );
3200
3201 //
3202 // Release all of our resources
3203 //
3204
3205 if (AcquiredVcb) {
3206
3207 FatReleaseVcb( IrpContext, Fcb->Vcb );
3208 }
3209
3210 if (AcquiredFcb) {
3211
3212 FatReleaseFcb( IrpContext, Fcb );
3213 }
3214
3215 DebugTrace(-1, Dbg, "FatOplockRequest -> %08lx\n", Status );
3216 } _SEH2_END;
3217
3218 FatCompleteRequest( IrpContext, Irp, Status );
3219
3220 return Status;
3221}
3222
3223
3224//
3225// Local Support Routine
3226//
3227
3228_Requires_lock_held_(_Global_critical_region_)
3230FatLockVolume (
3231 IN PIRP_CONTEXT IrpContext,
3232 IN PIRP Irp
3233 )
3234
3235/*++
3236
3237Routine Description:
3238
3239 This routine performs the lock volume operation. It is responsible for
3240 either completing of enqueuing the input Irp.
3241
3242Arguments:
3243
3244 Irp - Supplies the Irp to process
3245
3246Return Value:
3247
3248 NTSTATUS - The return status for the operation
3249
3250--*/
3251
3252{
3254
3256
3257 PVCB Vcb;
3258 PFCB Fcb;
3259 PCCB Ccb;
3260
3261 PAGED_CODE();
3262
3264
3265 DebugTrace(+1, Dbg, "FatLockVolume...\n", 0);
3266
3267 //
3268 // Decode the file object, the only type of opens we accept are
3269 // user volume opens.
3270 //
3271
3273
3275
3276 DebugTrace(-1, Dbg, "FatLockVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3278 }
3279
3281
3283
3284 DebugTrace(-1, Dbg, "FatLockVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3286 }
3287
3288 //
3289 // Send our notification so that folks that like to hold handles on
3290 // volumes can get out of the way.
3291 //
3292
3294
3295 //
3296 // Acquire exclusive access to the Vcb and enqueue the Irp if we
3297 // didn't get access.
3298 //
3299
3300 if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {
3301
3302 DebugTrace( 0, Dbg, "Cannot acquire Vcb\n", 0);
3303
3304 Status = FatFsdPostRequest( IrpContext, Irp );
3305
3306 DebugTrace(-1, Dbg, "FatUnlockVolume -> %08lx\n", Status);
3307 return Status;
3308 }
3309
3310 _SEH2_TRY {
3311
3312 Status = FatLockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
3313
3314 } _SEH2_FINALLY {
3315
3316 //
3317 // Since we drop and release the vcb while trying to punch the volume
3318 // down, it may be the case that we decide the operation should not
3319 // continue if the user raced a CloeseHandle() with us (and it finished
3320 // the cleanup) while we were waiting for our closes to finish.
3321 //
3322 // In this case, we will have been raised out of the acquire logic with
3323 // STATUS_FILE_CLOSED, and the volume will not be held.
3324 //
3325
3327
3328 FatReleaseVcb( IrpContext, Vcb );
3329 }
3330
3332
3333 //
3334 // The volume lock will be failing.
3335 //
3336
3338 }
3339 } _SEH2_END;
3340
3341 FatCompleteRequest( IrpContext, Irp, Status );
3342
3343 DebugTrace(-1, Dbg, "FatLockVolume -> %08lx\n", Status);
3344
3345 return Status;
3346}
3347
3348
3349//
3350// Local Support Routine
3351//
3352
3355 IN PIRP_CONTEXT IrpContext,
3356 IN PIRP Irp
3357 )
3358
3359/*++
3360
3361Routine Description:
3362
3363 This routine performs the unlock volume operation. It is responsible for
3364 either completing of enqueuing the input Irp.
3365
3366Arguments:
3367
3368 Irp - Supplies the Irp to process
3369
3370Return Value:
3371
3372 NTSTATUS - The return status for the operation
3373
3374--*/
3375
3376{
3378
3380
3381 PVCB Vcb;
3382 PFCB Fcb;
3383 PCCB Ccb;
3384
3385 PAGED_CODE();
3386
3388
3389 DebugTrace(+1, Dbg, "FatUnlockVolume...\n", 0);
3390
3391 //
3392 // Decode the file object, the only type of opens we accept are
3393 // user volume opens.
3394 //
3395
3397
3399
3400 DebugTrace(-1, Dbg, "FatUnlockVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3402 }
3403
3405
3407
3408 DebugTrace(-1, Dbg, "FatUnlockVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3410 }
3411
3413
3414 //
3415 // Send notification that the volume is avaliable.
3416 //
3417
3418 if (NT_SUCCESS( Status )) {
3419
3421 }
3422
3423 FatCompleteRequest( IrpContext, Irp, Status );
3424
3425 DebugTrace(-1, Dbg, "FatUnlockVolume -> %08lx\n", Status);
3426
3427 return Status;
3428}
3429
3430
3431_Requires_lock_held_(_Global_critical_region_)
3433FatLockVolumeInternal (
3434 IN PIRP_CONTEXT IrpContext,
3435 IN PVCB Vcb,
3437 )
3438
3439/*++
3440
3441Routine Description:
3442
3443 This routine performs the actual lock volume operation. It will be called
3444 by anyone wishing to try to protect the volume for a long duration. PNP
3445 operations are such a user.
3446
3447 The volume must be held exclusive by the caller.
3448
3449Arguments:
3450
3451 Vcb - The volume being locked.
3452
3453 FileObject - File corresponding to the handle locking the volume. If this
3454 is not specified, a system lock is assumed.
3455
3456Return Value:
3457
3458 NTSTATUS - The return status for the operation
3459
3460--*/
3461
3462{
3464 KIRQL SavedIrql;
3465 ULONG RemainingUserReferences = (FileObject? 1: 0);
3466
3469 //
3470 // Go synchronous for the rest of the lock operation. It may be
3471 // reasonable to try to revisit this in the future, but for now
3472 // the purge below expects to be able to wait.
3473 //
3474 // We know it is OK to leave the flag up given how we're used at
3475 // the moment.
3476 //
3477
3478 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
3479
3480 //
3481 // If there are any open handles, this will fail.
3482 //
3483
3484 if (!FatIsHandleCountZero( IrpContext, Vcb )) {
3485
3486 return STATUS_ACCESS_DENIED;
3487 }
3488
3489 //
3490 // Force Mm to get rid of its referenced file objects.
3491 //
3492
3493 FatFlushFat( IrpContext, Vcb );
3494
3495 FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
3496
3497 FatCloseEaFile( IrpContext, Vcb, TRUE );
3498
3499 //
3500 // Now back out of our synchronization and wait for the lazy writer
3501 // to finish off any lazy closes that could have been outstanding.
3502 //
3503 // Since we flushed, we know that the lazy writer will issue all
3504 // possible lazy closes in the next tick - if we hadn't, an otherwise
3505 // unopened file with a large amount of dirty data could have hung
3506 // around for a while as the data trickled out to the disk.
3507 //
3508 // This is even more important now since we send notification to
3509 // alert other folks that this style of check is about to happen so
3510 // that they can close their handles. We don't want to enter a fast
3511 // race with the lazy writer tearing down his references to the file.
3512 //
3513
3514 FatReleaseVcb( IrpContext, Vcb );
3515
3517
3518 FatAcquireExclusiveVcb( IrpContext, Vcb );
3519
3520 if (!NT_SUCCESS( Status )) {
3521
3522 return Status;
3523 }
3524
3525 //
3526 // The act of closing and purging may have touched pages in various
3527 // parent DCBs. We handle this by purging a second time.
3528 //
3529
3530 FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, Flush );
3531
3532 FatReleaseVcb( IrpContext, Vcb );
3533
3535
3536 FatAcquireExclusiveVcb( IrpContext, Vcb );
3537
3538 if (!NT_SUCCESS( Status )) {
3539
3540 return Status;
3541 }
3542
3543 //
3544 // Now rundown the delayed closes one last time. We appear to be able
3545 // to have additional collisions.
3546 //
3547
3548 FatFspClose( Vcb );
3549
3550 //
3551 // Check if the Vcb is already locked, or if the open file count
3552 // is greater than 1 (which implies that someone else also is
3553 // currently using the volume, or a file on the volume), and that the
3554 // VPB reference count only includes our residual and the handle (as
3555 // appropriate).
3556 //
3557 // We used to only check for the vpb refcount. This is unreliable since
3558 // the vpb refcount is dropped immediately before final close, meaning
3559 // that even though we had a good refcount, the close was inflight and
3560 // subsequent operations could get confused. Especially if the PNP path
3561 // was the lock caller, we delete the VCB with an outstanding opencount!
3562 //
3563
3564 IoAcquireVpbSpinLock( &SavedIrql );
3565
3566 if (!FlagOn(Vcb->Vpb->Flags, VPB_LOCKED) &&
3567 (Vcb->Vpb->ReferenceCount <= 2 + RemainingUserReferences) &&
3568 (Vcb->OpenFileCount == (CLONG)( FileObject? 1: 0 ))) {
3569
3571 SetFlag(Vcb->VcbState, VCB_STATE_FLAG_LOCKED);
3572 Vcb->FileObjectWithVcbLocked = FileObject;
3573
3574 } else {
3575
3577 }
3578
3579 IoReleaseVpbSpinLock( SavedIrql );
3580
3581 //
3582 // If we successully locked the volume, see if it is clean now.
3583 //
3584
3585 if (NT_SUCCESS( Status ) &&
3586 FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY ) &&
3587 !FlagOn( Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY ) &&
3588 !CcIsThereDirtyData(Vcb->Vpb)) {
3589
3590 FatMarkVolume( IrpContext, Vcb, VolumeClean );
3592 }
3593
3594 NT_ASSERT( !NT_SUCCESS(Status) || (Vcb->OpenFileCount == (CLONG)( FileObject? 1: 0 )));
3595
3596 return Status;
3597}
3598
3599
3602 IN PIRP_CONTEXT IrpContext,
3603 IN PVCB Vcb,
3605 )
3606
3607/*++
3608
3609Routine Description:
3610
3611 This routine performs the actual unlock volume operation.
3612
3613 The volume must be held exclusive by the caller.
3614
3615Arguments:
3616
3617 Vcb - The volume being locked.
3618
3619 FileObject - File corresponding to the handle locking the volume. If this
3620 is not specified, a system lock is assumed.
3621
3622Return Value:
3623
3624 NTSTATUS - The return status for the operation
3625
3626 Attempting to remove a system lock that did not exist is OK.
3627
3628--*/
3629
3630{
3631 KIRQL SavedIrql;
3633
3634 UNREFERENCED_PARAMETER( IrpContext );
3635
3636 IoAcquireVpbSpinLock( &SavedIrql );
3637
3638 if (FlagOn(Vcb->Vpb->Flags, VPB_LOCKED) && FileObject == Vcb->FileObjectWithVcbLocked) {
3639
3640 //
3641 // This one locked it, unlock the volume
3642 //
3643
3645 ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_LOCKED );
3646 Vcb->FileObjectWithVcbLocked = NULL;
3647
3649 }
3650
3651 IoReleaseVpbSpinLock( SavedIrql );
3652
3653 return Status;
3654}
3655
3656
3657//
3658// Local Support Routine
3659//
3660
3661_Requires_lock_held_(_Global_critical_region_)
3663FatDismountVolume (
3664 IN PIRP_CONTEXT IrpContext,
3665 IN PIRP Irp
3666 )
3667
3668/*++
3669
3670Routine Description:
3671
3672 This routine performs the dismount volume operation. It is responsible for
3673 either completing of enqueuing the input Irp.
3674
3675Arguments:
3676
3677 Irp - Supplies the Irp to process
3678
3679Return Value:
3680
3681 NTSTATUS - The return status for the operation
3682
3683--*/
3684
3685{
3688 BOOLEAN VcbHeld = FALSE;
3689 KIRQL SavedIrql;
3690
3691 PVCB Vcb;
3692 PFCB Fcb;
3693 PCCB Ccb;
3694
3696
3697 DebugTrace(+1, Dbg, "FatDismountVolume...\n", 0);
3698
3699 //
3700 // Decode the file object, the only type of opens we accept are
3701 // user volume opens on media that is not boot/paging and is not
3702 // already dismounted ... (but we need to check that stuff while
3703 // synchronized)
3704 //
3705
3707
3709 goto fn_return;
3710 }
3711
3713
3715
3716 DebugTrace(-1, Dbg, "FatDismountVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3718 }
3719
3720 //
3721 // Make some unsynchronized checks to see if this operation is possible.
3722 // We will repeat the appropriate ones inside synchronization, but it is
3723 // good to avoid bogus notifications.
3724 //
3725
3726 if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE )) {
3727
3729 goto fn_return;
3730 }
3731
3732 if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DISMOUNTED )) {
3733
3735 goto fn_return;
3736 }
3737
3738 //
3739 // A bit of historical comment is in order.
3740 //
3741 // In all versions prior to NT5, we only permitted dismount if the volume had
3742 // previously been locked. Now we must permit a forced dismount, meaning that
3743 // we grab ahold of the whole kit-n-kaboodle - regardless of activity, open
3744 // handles, etc. - to flush and invalidate the volume.
3745 //
3746 // Previously, dismount assumed that lock had come along earlier and done some
3747 // of the work that we are now going to do - i.e., flush, tear down the eas. All
3748 // we had to do here is flush the device out and kill off as many of the orphan
3749 // fcbs as possible. This now changes.
3750 //
3751 // In fact, everything is a forced dismount now. This changes one interesting
3752 // aspect, which is that it used to be the case that the handle used to dismount
3753 // could come back, read, and induce a verify/remount. This is just not possible
3754 // now. The point of forced dismount is that very shortly someone will come along
3755 // and be destructive to the possibility of using the media further - format, eject,
3756 // etc. By using this path, callers are expected to tolerate the consequences.
3757 //
3758 // Note that the volume can still be successfully unlocked by this handle.
3759 //
3760
3761 //
3762 // Send notification.
3763 //
3764
3766
3767 //
3768 // Force ourselves to wait and grab everything.
3769 //
3770
3771 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
3772
3773#ifdef _MSC_VER
3774#pragma prefast( push )
3775#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
3776#pragma prefast( disable: 28193, "this will always wait" )
3777#endif
3778
3779 (VOID)FatAcquireExclusiveGlobal( IrpContext );
3780
3781#ifdef _MSC_VER
3782#pragma prefast( pop )
3783#endif
3784
3785 _SEH2_TRY {
3786
3787 //
3788 // Guess what? This can raise if a cleanup on the fileobject we
3789 // got races in ahead of us.
3790 //
3791
3792 FatAcquireExclusiveVolume( IrpContext, Vcb );
3793 VcbHeld = TRUE;
3794
3795 if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DISMOUNTED )) {
3796
3798 }
3799
3800 FatFlushAndCleanVolume( IrpContext, Irp, Vcb, FlushAndInvalidate );
3801
3802 //
3803 // We defer the physical dismount until this handle is closed, per symmetric
3804 // implemntation in the other FS. This permits a dismounter to issue IOCTL
3805 // through this handle and perform device manipulation without racing with
3806 // creates attempting to mount the volume again.
3807 //
3808 // Raise a flag to tell the cleanup path to complete the dismount.
3809 //
3810
3812
3813 //
3814 // Indicate that the volume was dismounted so that we may return the
3815 // correct error code when operations are attempted via open handles.
3816 //
3817
3819
3821
3822 //
3823 // Set a flag in the VPB to let others know that direct volume access is allowed.
3824 //
3825
3826 IoAcquireVpbSpinLock( &SavedIrql );
3827 SetFlag( Vcb->Vpb->Flags, VPB_DIRECT_WRITES_ALLOWED );
3828 IoReleaseVpbSpinLock( SavedIrql );
3829
3831
3832 try_exit: NOTHING;
3833
3834 } _SEH2_FINALLY {
3835
3836#if (NTDDI_VERSION >= NTDDI_WIN8)
3837
3838 FsRtlDismountComplete( Vcb->TargetDeviceObject, Status );
3839
3840#endif
3841
3842 if (VcbHeld) {
3843
3844 FatReleaseVolume( IrpContext, Vcb );
3845 }
3846
3847 FatReleaseGlobal( IrpContext );
3848
3849 //
3850 // I do not believe it is possible to raise, but for completeness
3851 // notice and send notification of failure. We absolutely
3852 // cannot have raised in CheckForDismount.
3853 //
3854 // We decline to call an attempt to dismount a dismounted volume
3855 // a failure to do so.
3856 //
3857
3860
3862 }
3863 } _SEH2_END;
3864
3865 fn_return:
3866
3867 FatCompleteRequest( IrpContext, Irp, Status );
3868 DebugTrace(-1, Dbg, "FatDismountVolume -> %08lx\n", Status);
3869 return Status;
3870}
3871
3872
3873//
3874// Local Support Routine
3875//
3876
3877_Requires_lock_held_(_Global_critical_region_)
3879FatDirtyVolume (
3880 IN PIRP_CONTEXT IrpContext,
3881 IN PIRP Irp
3882 )
3883
3884/*++
3885
3886Routine Description:
3887
3888 This routine marks the volume as dirty.
3889
3890Arguments:
3891
3892 Irp - Supplies the Irp to process
3893
3894Return Value:
3895
3896 NTSTATUS - The return status for the operation
3897
3898--*/
3899
3900{
3902
3903 PVCB Vcb;
3904 PFCB Fcb;
3905 PCCB Ccb;
3906
3907 PAGED_CODE();
3908
3910
3911 DebugTrace(+1, Dbg, "FatDirtyVolume...\n", 0);
3912
3913 //
3914 // Decode the file object, the only type of opens we accept are
3915 // user volume opens.
3916 //
3917
3919
3921
3922 DebugTrace(-1, Dbg, "FatDirtyVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3924 }
3925
3927
3929
3930 DebugTrace(-1, Dbg, "FatDirtyVolume -> %08lx\n", STATUS_INVALID_PARAMETER);
3932 }
3933
3934
3935 //
3936 // Disable popups, we will just return any error.
3937 //
3938
3939 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS);
3940
3941 //
3942 // Verify the Vcb. We want to make sure we don't dirty some
3943 // random chunk of media that happens to be in the drive now.
3944 //
3945
3946 FatVerifyVcb( IrpContext, Vcb );
3947
3949
3950 FatMarkVolume( IrpContext, Vcb, VolumeDirty );
3951
3952 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
3953
3954 DebugTrace(-1, Dbg, "FatDirtyVolume -> STATUS_SUCCESS\n", 0);
3955
3956 return STATUS_SUCCESS;
3957}
3958
3959
3960//
3961// Local Support Routine
3962//
3963
3966 IN PIRP_CONTEXT IrpContext,
3967 IN PIRP Irp
3968 )
3969
3970/*++
3971
3972Routine Description:
3973
3974 This routine determines if a volume is currently dirty.
3975
3976Arguments:
3977
3978 Irp - Supplies the Irp to process
3979
3980Return Value:
3981
3982 NTSTATUS - The return status for the operation
3983
3984--*/
3985
3986{
3988
3990 PVCB Vcb;
3991 PFCB Fcb;
3992 PCCB Ccb;
3993
3995
3996 PAGED_CODE();
3997
3998 //
3999 // Get the current stack location and extract the output
4000 // buffer information.
4001 //
4002
4004
4005 //
4006 // Get a pointer to the output buffer. Look at the system buffer field in the
4007 // irp first. Then the Irp Mdl.
4008 //
4009
4010 if (Irp->AssociatedIrp.SystemBuffer != NULL) {
4011
4012 VolumeState = Irp->AssociatedIrp.SystemBuffer;
4013
4014 } else if (Irp->MdlAddress != NULL) {
4015
4016 VolumeState = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, LowPagePriority | MdlMappingNoExecute );
4017
4018 if (VolumeState == NULL) {
4019
4022 }
4023
4024 } else {
4025
4028 }
4029
4030 //
4031 // Make sure the output buffer is large enough and then initialize
4032 // the answer to be that the volume isn't dirty.
4033 //
4034
4035 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {
4036
4039 }
4040
4041 *VolumeState = 0;
4042
4043 //
4044 // Decode the file object
4045 //
4046
4048
4049 if (TypeOfOpen != UserVolumeOpen) {
4050
4053 }
4054
4055 if (Vcb->VcbCondition != VcbGood) {
4056
4059 }
4060
4061 //
4062 // Disable PopUps, we want to return any error.
4063 //
4064
4065 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS);
4066
4067 //
4068 // Verify the Vcb. We want to make double sure that this volume
4069 // is around so that we know our information is good.
4070 //
4071
4072 FatVerifyVcb( IrpContext, Vcb );
4073
4074 //
4075 // Now set the returned information. We can avoid probing the disk since
4076 // we know our internal state is in sync.
4077 //
4078
4079 if ( FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY) ) {
4080
4082 }
4083
4084 Irp->IoStatus.Information = sizeof( ULONG );
4085
4086 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
4087 return STATUS_SUCCESS;
4088}
4089
4090
4091//
4092// Local Support Routine
4093//
4094
4097 IN PIRP_CONTEXT IrpContext,
4098 IN PIRP Irp
4099 )
4100
4101/*++
4102
4103Routine Description:
4104
4105 This routine determines if a volume is currently mounted.
4106
4107Arguments:
4108
4109 Irp - Supplies the Irp to process
4110
4111Return Value:
4112
4113 NTSTATUS - The return status for the operation
4114
4115--*/
4116
4117{
4119
4121
4122 PVCB Vcb = NULL;
4123 PFCB Fcb;
4124 PCCB Ccb;
4125
4126 PAGED_CODE();
4127
4129
4131
4132 DebugTrace(+1, Dbg, "FatIsVolumeMounted...\n", 0);
4133
4134 //
4135 // Decode the file object.
4136 //
4137
4139
4140 NT_ASSERT( Vcb != NULL );
4142
4143 //
4144 // Disable PopUps, we want to return any error.
4145 //
4146
4147 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS);
4148
4149 //
4150 // Verify the Vcb.
4151 //
4152
4153 FatVerifyVcb( IrpContext, Vcb );
4154
4155 FatCompleteRequest( IrpContext, Irp, Status );
4156
4157 DebugTrace(-1, Dbg, "FatIsVolumeMounted -> %08lx\n", Status);
4158
4159 return Status;
4160}
4161
4162
4163//
4164// Local Support Routine
4165//
4166
4169 IN PIRP_CONTEXT IrpContext,
4170 IN PIRP Irp
4171 )
4172
4173/*++
4174
4175Routine Description:
4176
4177 This routine determines if a pathname is a-priori illegal by inspecting
4178 the the characters used. It is required to be correct on a FALSE return.
4179
4180 N.B.: current implementation is intentioanlly a no-op. This may change
4181 in the future. A careful reader of the previous implementation of this
4182 FSCTL in FAT would discover that it violated the requirement stated above
4183 and could return FALSE for a valid (createable) pathname.
4184
4185Arguments:
4186
4187 Irp - Supplies the Irp to process
4188
4189Return Value:
4190
4191 NTSTATUS - The return status for the operation
4192
4193--*/
4194
4195{
4196 PAGED_CODE();
4197
4198 DebugTrace(+1, Dbg, "FatIsPathnameValid...\n", 0);
4199
4200 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
4201
4202 DebugTrace(-1, Dbg, "FatIsPathnameValid -> %08lx\n", STATUS_SUCCESS);
4203
4204 return STATUS_SUCCESS;
4205}
4206
4207
4208//
4209// Local Support Routine
4210//
4211
4214 IN PIRP_CONTEXT IrpContext,
4215 IN PIRP Irp
4216 )
4217
4218/*++
4219
4220Routine Description:
4221
4222 This routine simply returns the first 0x24 bytes of sector 0.
4223
4224Arguments:
4225
4226 Irp - Supplies the Irp to process
4227
4228Return Value:
4229
4230 NTSTATUS - The return status for the operation
4231
4232--*/
4233
4234{
4236
4237 PVCB Vcb;
4238
4240
4241 PAGED_CODE();
4242
4244
4245 DebugTrace(+1, Dbg, "FatQueryBpb...\n", 0);
4246
4247 //
4248 // Get the Vcb. If we didn't keep the information needed for this call,
4249 // we had a reason ...
4250 //
4251
4253
4254 if (Vcb->First0x24BytesOfBootSector == NULL) {
4255
4257 DebugTrace(-1, Dbg, "FatQueryBpb -> %08lx\n", STATUS_INVALID_DEVICE_REQUEST );
4259 }
4260
4261 //
4262 // Extract the buffer
4263 //
4264
4265 BpbBuffer = (PFSCTL_QUERY_FAT_BPB_BUFFER)Irp->AssociatedIrp.SystemBuffer;
4266
4267 //
4268 // Make sure the buffer is big enough.
4269 //
4270
4271 if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < 0x24) {
4272
4274 DebugTrace(-1, Dbg, "FatQueryBpb -> %08lx\n", STATUS_BUFFER_TOO_SMALL );
4276 }
4277
4278 //
4279 // Fill in the output buffer
4280 //
4281
4283 Vcb->First0x24BytesOfBootSector,
4284 0x24 );
4285
4286 Irp->IoStatus.Information = 0x24;
4287
4288 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
4289 DebugTrace(-1, Dbg, "FatQueryBpb -> %08lx\n", STATUS_SUCCESS);
4290 return STATUS_SUCCESS;
4291}
4292
4293
4294//
4295// Local Support Routine
4296//
4297
4298_Requires_lock_held_(_Global_critical_region_)
4300FatInvalidateVolumes (
4301 IN PIRP Irp
4302 )
4303
4304/*++
4305
4306Routine Description:
4307
4308 This routine searches for all the volumes mounted on the same real device
4309 of the current DASD handle, and marks them all bad. The only operation
4310 that can be done on such handles is cleanup and close.
4311
4312Arguments:
4313
4314 Irp - Supplies the Irp to process
4315
4316Return Value:
4317
4318 NTSTATUS - The return status for the operation
4319
4320--*/
4321
4322{
4324 IRP_CONTEXT IrpContext;
4326
4327 LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
4328
4329 HANDLE Handle;
4330
4331 PLIST_ENTRY Links;
4332
4333 PFILE_OBJECT FileToMarkBad;
4334 PDEVICE_OBJECT DeviceToMarkBad;
4335
4337
4338 DebugTrace(+1, Dbg, "FatInvalidateVolumes...\n", 0);
4339
4340 //
4341 // Check for the correct security access.
4342 // The caller must have the SeTcbPrivilege.
4343 //
4344
4345 if (!SeSinglePrivilegeCheck(TcbPrivilege, Irp->RequestorMode)) {
4346
4348
4349 DebugTrace(-1, Dbg, "FatInvalidateVolumes -> %08lx\n", STATUS_PRIVILEGE_NOT_HELD);
4351 }
4352
4353 //
4354 // Try to get a pointer to the device object from the handle passed in.
4355 //
4356
4357#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
4358 if (IoIs32bitProcess( Irp )) {
4359
4360 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(UINT32)) {
4361
4363
4364 DebugTrace(-1, Dbg, "FatInvalidateVolumes -> %08lx\n", STATUS_INVALID_PARAMETER);
4366 }
4367
4368 Handle = (HANDLE) LongToHandle( (*(PUINT32)Irp->AssociatedIrp.SystemBuffer) );
4369 } else {
4370#endif
4371 if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof(HANDLE)) {
4372
4374
4375 DebugTrace(-1, Dbg, "FatInvalidateVolumes -> %08lx\n", STATUS_INVALID_PARAMETER);
4377 }
4378
4379 Handle = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
4380#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
4381 }
4382#endif
4383
4384
4386 0,
4388 KernelMode,
4389#ifndef __REACTOS__
4390 &FileToMarkBad,
4391#else
4392 (PVOID *)&FileToMarkBad,
4393#endif
4394 NULL );
4395
4396 if (!NT_SUCCESS(Status)) {
4397
4399
4400 DebugTrace(-1, Dbg, "FatInvalidateVolumes -> %08lx\n", Status);
4401 return Status;
4402
4403 } else {
4404
4405 //
4406 // We only needed the pointer, not a reference.
4407 //
4408
4409 ObDereferenceObject( FileToMarkBad );
4410
4411 //
4412 // Grab the DeviceObject from the FileObject.
4413 //
4414
4415 DeviceToMarkBad = FileToMarkBad->DeviceObject;
4416 }
4417
4418 RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT) );
4419
4420 SetFlag( IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT );
4421 IrpContext.MajorFunction = IrpSp->MajorFunction;
4422 IrpContext.MinorFunction = IrpSp->MinorFunction;
4423
4424#ifdef _MSC_VER
4425#pragma prefast( push )
4426#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
4427#pragma prefast( disable: 28193, "this will always wait" )
4428#endif
4429
4430 FatAcquireExclusiveGlobal( &IrpContext );
4431
4432#ifdef _MSC_VER
4433#pragma prefast( pop )
4434#endif
4435
4436 //
4437 // First acquire the FatData resource shared, then walk through all the
4438 // mounted VCBs looking for candidates to mark BAD.
4439 //
4440 // On volumes we mark bad, check for dismount possibility (which is
4441 // why we have to get the next link early).
4442 //
4443
4444 Links = FatData.VcbQueue.Flink;
4445
4446 while (Links != &FatData.VcbQueue) {
4447
4448 PVCB ExistingVcb;
4449
4450 ExistingVcb = CONTAINING_RECORD(Links, VCB, VcbLinks);
4451
4452 Links = Links->Flink;
4453
4454 //
4455 // If we get a match, mark the volume Bad, and also check to
4456 // see if the volume should go away.
4457 //
4458
4459 if (ExistingVcb->Vpb->RealDevice == DeviceToMarkBad) {
4460
4461 BOOLEAN VcbDeleted = FALSE;
4462
4463 //
4464 // Here we acquire the Vcb exclusive and try to purge
4465 // all the open files. The idea is to have as little as
4466 // possible stale data visible and to hasten the volume
4467 // going away.
4468 //
4469
4470 (VOID)FatAcquireExclusiveVcb( &IrpContext, ExistingVcb );
4471
4472#ifdef _MSC_VER
4473#pragma prefast( push )
4474#pragma prefast( disable: 28175, "touching Vpb is ok for a filesystem" )
4475#endif
4476
4477 if (ExistingVcb->Vpb == DeviceToMarkBad->Vpb) {
4478
4479 KIRQL OldIrql;
4480
4482
4483 if (FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_MOUNTED )) {
4484
4485 PVPB NewVpb;
4486
4487 NewVpb = ExistingVcb->SwapVpb;
4488 ExistingVcb->SwapVpb = NULL;
4490
4491 RtlZeroMemory( NewVpb, sizeof( VPB ) );
4492 NewVpb->Type = IO_TYPE_VPB;
4493 NewVpb->Size = sizeof( VPB );
4494 NewVpb->RealDevice = DeviceToMarkBad;
4495 NewVpb->Flags = FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING );
4496
4497 DeviceToMarkBad->Vpb = NewVpb;
4498 }
4499
4500 NT_ASSERT( DeviceToMarkBad->Vpb->DeviceObject == NULL );
4501
4502#ifdef _MSC_VER
4503#pragma prefast( pop )
4504#endif
4505
4507 }
4508
4509 FatSetVcbCondition( ExistingVcb, VcbBad );
4510
4511 //
4512 // Process the root directory, if it is present.
4513 //
4514
4515 if (ExistingVcb->RootDcb != NULL) {
4516
4517 //
4518 // In order to safely mark all FCBs bad, we must acquire everything.
4519 //
4520
4521 FatAcquireExclusiveVolume(&IrpContext, ExistingVcb);
4522 FatMarkFcbCondition( &IrpContext, ExistingVcb->RootDcb, FcbBad, TRUE );
4523 FatReleaseVolume(&IrpContext, ExistingVcb);
4524
4525 //
4526 // Purging the file objects on this volume could result in the memory manager
4527 // dereferencing it's file pointer which could be the last reference and
4528 // trigger object deletion and VCB deletion. Protect against that here by
4529 // temporarily biasing the file count, and later checking for dismount.
4530 //
4531
4532 ExistingVcb->OpenFileCount += 1;
4533
4534 FatPurgeReferencedFileObjects( &IrpContext,
4535 ExistingVcb->RootDcb,
4536 NoFlush );
4537
4538 ExistingVcb->OpenFileCount -= 1;
4539
4540 VcbDeleted = FatCheckForDismount( &IrpContext, ExistingVcb, FALSE );
4541 }
4542
4543 //
4544 // Only release the VCB if it did not go away.
4545 //
4546
4547 if (!VcbDeleted) {
4548
4549 FatReleaseVcb( &IrpContext, ExistingVcb );
4550 }
4551 }
4552 }
4553
4554 FatReleaseGlobal( &IrpContext );
4555
4557
4558 DebugTrace(-1, Dbg, "FatInvalidateVolumes -> STATUS_SUCCESS\n", 0);
4559
4560 return STATUS_SUCCESS;
4561}
4562
4563
4564//
4565// Local Support routine
4566//
4567
4568BOOLEAN
4570 IN PIRP_CONTEXT IrpContext,
4571 IN PVCB Vcb,
4572 IN PVOID Buffer,
4573 IN LBO Lbo,
4574 IN ULONG NumberOfBytesToRead,
4575 IN BOOLEAN ReturnOnError
4576 )
4577
4578/*++
4579
4580Routine Description:
4581
4582 This routine is used to read in a range of bytes from the disk. It
4583 bypasses all of the caching and regular I/O logic, and builds and issues
4584 the requests itself. It does this operation overriding the verify
4585 volume flag in the device object.
4586
4587Arguments:
4588
4589 Vcb - Supplies the target device object for this operation.
4590
4591 Buffer - Supplies the buffer that will recieve the results of this operation
4592
4593 Lbo - Supplies the byte offset of where to start reading
4594
4595 NumberOfBytesToRead - Supplies the number of bytes to read, this must
4596 be in multiple of bytes units acceptable to the disk driver.
4597
4598 ReturnOnError - Indicates that we should return on an error, instead
4599 of raising.
4600
4601Return Value:
4602
4603 BOOLEAN - TRUE if the operation succeded, FALSE otherwise.
4604
4605--*/
4606
4607{
4608 KEVENT Event;
4609 PIRP Irp;
4613
4614 PAGED_CODE();
4615
4616 DebugTrace(0, Dbg, "FatPerformVerifyDiskRead, Lbo = %08lx\n", Lbo );
4617
4618 //
4619 // Initialize the event we're going to use
4620 //
4621
4623
4624 //
4625 // Build the irp for the operation and also set the overrride flag
4626 //
4627
4628 ByteOffset.QuadPart = Lbo;
4629
4631 Vcb->TargetDeviceObject,
4632 Buffer,
4633 NumberOfBytesToRead,
4634 &ByteOffset,
4635 &Event,
4636 &Iosb );
4637
4638 if ( Irp == NULL ) {
4639
4641 }
4642
4644
4645 //
4646 // Call the device to do the read and wait for it to finish.
4647 //
4648
4649 Status = IoCallDriver( Vcb->TargetDeviceObject, Irp );
4650
4651 if (Status == STATUS_PENDING) {
4652
4654
4655 Status = Iosb.Status;
4656 }
4657
4659
4660 //
4661 // Special case this error code because this probably means we used
4662 // the wrong sector size and we want to reject STATUS_WRONG_VOLUME.
4663 //
4664
4666
4667 return FALSE;
4668 }
4669
4670 //
4671 // If it doesn't succeed then either return or raise the error.
4672 //
4673
4674 if (!NT_SUCCESS(Status)) {
4675
4676 if (ReturnOnError) {
4677
4678 return FALSE;
4679
4680 } else {
4681
4682 FatNormalizeAndRaiseStatus( IrpContext, Status );
4683 }
4684 }
4685
4686 //
4687 // And return to our caller
4688 //
4689
4690 return TRUE;
4691}
4692
4693
4694//
4695// Local Support Routine
4696//
4697
4698_Requires_lock_held_(_Global_critical_region_)
4700FatQueryRetrievalPointers (
4701 IN PIRP_CONTEXT IrpContext,
4702 IN PIRP Irp
4703 )
4704
4705/*++
4706
4707Routine Description:
4708
4709 This routine performs the query retrieval pointers operation.
4710 It returns the retrieval pointers for the specified input
4711 file from the start of the file to the request map size specified
4712 in the input buffer.
4713
4714Arguments:
4715
4716 Irp - Supplies the Irp to process
4717
4718Return Value:
4719
4720 NTSTATUS - The return status for the operation
4721
4722--*/
4723
4724{
4726
4728
4729 PVCB Vcb;
4730 PFCB Fcb;
4731 PCCB Ccb;
4732
4733 PLARGE_INTEGER RequestedMapSize;
4734 PLARGE_INTEGER *MappingPairs;
4735
4736 ULONG Index;
4737 ULONG i;
4739 LBO Lbo;
4740 ULONG Vbo;
4741 ULONG MapSize;
4743
4744 PAGED_CODE();
4745
4746 //
4747 // Get the current stack location
4748 //
4749
4751
4752 //
4753 // Make this a synchronous IRP because we need access to the input buffer and
4754 // this Irp is marked METHOD_NEITHER.
4755 //
4756
4757 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
4758
4759 //
4760 // Decode the file object and ensure that it is the paging file
4761 //
4762 // Only Kernel mode clients may query retrieval pointer information about
4763 // a file. Ensure that this is the case for this caller.
4764 //
4765
4767
4768 if (Irp->RequestorMode != KernelMode ||
4769 Fcb == NULL ||
4771
4774 }
4775
4776 //
4777 // Extract the input and output buffer information. The input contains
4778 // the requested size of the mappings in terms of VBO. The output
4779 // parameter will receive a pointer to nonpaged pool where the mapping
4780 // pairs are stored.
4781 //
4782
4783 NT_ASSERT( IrpSp->Parameters.FileSystemControl.InputBufferLength == sizeof(LARGE_INTEGER) );
4784 NT_ASSERT( IrpSp->Parameters.FileSystemControl.OutputBufferLength == sizeof(PVOID) );
4785
4786 RequestedMapSize = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
4787 MappingPairs = Irp->UserBuffer;
4788
4789 //
4790 // Acquire exclusive access to the Fcb
4791 //
4792
4793 FatAcquireExclusiveFcb( IrpContext, Fcb );
4794
4795 _SEH2_TRY {
4796
4797 //
4798 // Verify the Fcb is still OK
4799 //
4800
4801 FatVerifyFcb( IrpContext, Fcb );
4802
4803 //
4804 // Check if the mapping the caller requested is too large
4805 //
4806
4807 if ((*RequestedMapSize).QuadPart > Fcb->Header.FileSize.QuadPart) {
4808
4810 }
4811
4812 //
4813 // Now get the index for the mcb entry that will contain the
4814 // callers request and allocate enough pool to hold the
4815 // output mapping pairs. Mapping should always be present, but handle
4816 // the case where it isn't.
4817 //
4818
4820 &Fcb->Mcb,
4821 RequestedMapSize->LowPart - 1,
4822 &Lbo,
4823 NULL,
4824 &Index );
4825
4826 if (!Result) {
4827
4830 }
4831
4832 *MappingPairs = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
4833 (Index + 2) * (2 * sizeof(LARGE_INTEGER)),
4835
4836 //
4837 // Now copy over the mapping pairs from the mcb
4838 // to the output buffer. We store in [sector count, lbo]
4839 // mapping pairs and end with a zero sector count.
4840 //
4841
4842 MapSize = RequestedMapSize->LowPart;
4843
4844 for (i = 0; i <= Index; i += 1) {
4845
4847
4848 if (SectorCount > MapSize) {
4849 SectorCount = MapSize;
4850 }
4851
4852 (*MappingPairs)[ i*2 + 0 ].QuadPart = SectorCount;
4853 (*MappingPairs)[ i*2 + 1 ].QuadPart = Lbo;
4854
4855 MapSize -= SectorCount;
4856 }
4857
4858 (*MappingPairs)[ i*2 + 0 ].QuadPart = 0;
4859
4861 }
4863
4864 DebugUnwind( FatQueryRetrievalPointers );
4865
4866 //
4867 // Release all of our resources
4868 //
4869
4870 FatReleaseFcb( IrpContext, Fcb );
4871
4872 //
4873 // If this is an abnormal termination then undo our work, otherwise
4874 // complete the irp
4875 //
4876
4878
4879 FatCompleteRequest( IrpContext, Irp, Status );
4880 }
4881 } _SEH2_END;
4882
4883 return Status;
4884}
4885
4886
4887//
4888// Local Support Routine
4889//
4890
4893 IN PIRP_CONTEXT IrpContext,
4894 IN PIRP Irp
4895 )
4896
4897/*++
4898
4899Routine Description:
4900
4901 This routine returns the filesystem performance counters from the
4902 appropriate VCB.
4903
4904Arguments:
4905
4906 Irp - Supplies the Irp to process
4907
4908Return Value:
4909
4910 NTSTATUS - The return status for the operation
4911
4912--*/
4913
4914{
4917 PVCB Vcb;
4918
4921 ULONG StatsSize;
4923
4924 PAGED_CODE();
4925
4927
4928 DebugTrace(+1, Dbg, "FatGetStatistics...\n", 0);
4929
4930 //
4931 // Extract the buffer
4932 //
4933
4934 BufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
4935
4936 //
4937 // Get a pointer to the output buffer.
4938 //
4939
4940 Buffer = Irp->AssociatedIrp.SystemBuffer;
4941
4942 //
4943 // Make sure the buffer is big enough for at least the common part.
4944 //
4945
4946 if (BufferLength < sizeof(FILESYSTEM_STATISTICS)) {
4947
4949
4950 DebugTrace(-1, Dbg, "FatGetStatistics -> %08lx\n", STATUS_BUFFER_TOO_SMALL );
4951
4953 }
4954
4955 //
4956 // Now see how many bytes we can copy.
4957 //
4958
4959 StatsSize = sizeof(FILE_SYSTEM_STATISTICS) * FatData.NumberProcessors;
4960
4961 if (BufferLength < StatsSize) {
4962
4965
4966 } else {
4967
4968 BytesToCopy = StatsSize;
4970 }
4971
4972 //
4973 // Get the Vcb.
4974 //
4975
4977
4978 //
4979 // Fill in the output buffer
4980 //
4981
4982 RtlCopyMemory( Buffer, Vcb->Statistics, BytesToCopy );
4983
4984 Irp->IoStatus.Information = BytesToCopy;
4985
4986 FatCompleteRequest( IrpContext, Irp, Status );
4987
4988 DebugTrace(-1, Dbg, "FatGetStatistics -> %08lx\n", Status);
4989
4990 return Status;
4991}
4992
4993//
4994// Local Support Routine
4995//
4996
4997_Requires_lock_held_(_Global_critical_region_)
4999FatGetVolumeBitmap(
5000 IN PIRP_CONTEXT IrpContext,
5001 IN PIRP Irp
5002 )
5003
5004/*++
5005
5006Routine Description:
5007
5008 This routine returns the volume allocation bitmap.
5009
5010 Input = the STARTING_LCN_INPUT_BUFFER data structure is passed in
5011 through the input buffer.
5012 Output = the VOLUME_BITMAP_BUFFER data structure is returned through
5013 the output buffer.
5014
5015 We return as much as the user buffer allows starting the specified input
5016 LCN (trucated to a byte). If there is no input buffer, we start at zero.
5017
5018Arguments:
5019
5020 Irp - Supplies the Irp being processed.
5021
5022Return Value:
5023
5024 NTSTATUS - The return status for the operation.
5025
5026--*/
5027{
5030
5031 PVCB Vcb;
5032 PFCB Fcb;
5033 PCCB Ccb;
5034
5036 ULONG TotalClusters;
5037 ULONG DesiredClusters;
5038 ULONG StartingCluster;
5039 ULONG EndingCluster;
5042 LARGE_INTEGER StartingLcn;
5044
5045 PAGED_CODE();
5046
5047 //
5048 // Get the current Irp stack location and save some references.
5049 //
5050
5052
5053 DebugTrace(+1, Dbg, "FatGetVolumeBitmap, FsControlCode = %08lx\n",
5054 IrpSp->Parameters.FileSystemControl.FsControlCode);
5055
5056 //
5057 // Make this a synchronous IRP because we need access to the input buffer and
5058 // this Irp is marked METHOD_NEITHER.
5059 //
5060
5061 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
5062
5063 //
5064 // Extract and decode the file object and check for type of open.
5065 //
5066
5068
5071 }
5072
5074
5076
5077 DebugTrace(-1, Dbg, "FatGetVolumeBitmap -> %08lx\n", STATUS_INVALID_PARAMETER);
5079 }
5080
5081 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
5082 OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
5083
5085
5086 //
5087 // Check for a minimum length on the input and output buffers.
5088 //
5089
5092
5095 }
5096
5097 //
5098 // Check if a starting cluster was specified.
5099 //
5100
5101 TotalClusters = Vcb->AllocationSupport.NumberOfClusters;
5102
5103 //
5104 // Check for valid buffers
5105 //
5106
5107 _SEH2_TRY {
5108
5109 if (Irp->RequestorMode != KernelMode) {
5110
5111 ProbeForRead( IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5113 sizeof(UCHAR) );
5114
5116 }
5117
5118 StartingLcn = ((PSTARTING_LCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingLcn;
5119
5121
5123
5124 FatRaiseStatus( IrpContext,
5127 } _SEH2_END;
5128
5129 if (StartingLcn.HighPart || StartingLcn.LowPart >= TotalClusters) {
5130
5133
5134 } else {
5135
5136 StartingCluster = StartingLcn.LowPart & ~7;
5137 }
5138
5139 (VOID)FatAcquireExclusiveVcb( IrpContext, Vcb );
5140
5141 //
5142 // Only return what will fit in the user buffer.
5143 //
5144
5146 DesiredClusters = TotalClusters - StartingCluster;
5147
5148 if (OutputBufferLength < (DesiredClusters + 7) / 8) {
5149
5152
5153 } else {
5154
5155 BytesToCopy = (DesiredClusters + 7) / 8;
5157 }
5158
5159 //
5160 // Use try/finally for cleanup.
5161 //
5162
5163 _SEH2_TRY {
5164
5165 _SEH2_TRY {
5166
5167 //
5168 // Verify the Vcb is still OK
5169 //
5170
5171 FatQuickVerifyVcb( IrpContext, Vcb );
5172
5173 //
5174 // Fill in the fixed part of the output buffer
5175 //
5176
5177 OutputBuffer->StartingLcn.QuadPart = StartingCluster;
5178 OutputBuffer->BitmapSize.QuadPart = DesiredClusters;
5179
5180 if (Vcb->NumberOfWindows == 1) {
5181
5182 //
5183 // Just copy the volume bitmap into the user buffer.
5184 //
5185
5186 NT_ASSERT( Vcb->FreeClusterBitMap.Buffer != NULL );
5187
5188 RtlCopyMemory( &OutputBuffer->Buffer[0],
5189 (PUCHAR)Vcb->FreeClusterBitMap.Buffer + StartingCluster/8,
5190 BytesToCopy );
5191 } else {
5192
5193 //
5194 // Call out to analyze the FAT. We must bias by two to account for
5195 // the zero base of this API and FAT's physical reality of starting
5196 // the file heap at cluster 2.
5197 //
5198 // Note that the end index is inclusive - we need to subtract one to
5199 // calculcate it.
5200 //
5201 // I.e.: StartingCluster 0 for one byte of bitmap means a start cluster
5202 // of 2 and end cluster of 9, a run of eight clusters.
5203 //
5204
5205 EndingCluster = StartingCluster + (BytesToCopy * 8);
5206
5207 //
5208 // Make sure we do not read past the end of the entries.
5209 //
5210
5211 if (EndingCluster > TotalClusters) {
5212
5213 EndingCluster = TotalClusters;
5214 }
5215
5216 FatExamineFatEntries( IrpContext,
5217 Vcb,
5218 StartingCluster + 2,
5219 EndingCluster + 2 - 1,
5220 FALSE,
5221 NULL,
5222 (PULONG)&OutputBuffer->Buffer[0] );
5223 }
5224
5226
5228
5229 FatRaiseStatus( IrpContext,
5232 } _SEH2_END;
5233
5234 } _SEH2_FINALLY {
5235
5236 FatReleaseVcb( IrpContext, Vcb );
5237 } _SEH2_END;
5238
5239 Irp->IoStatus.Information = FIELD_OFFSET(VOLUME_BITMAP_BUFFER, Buffer) +
5241
5242 FatCompleteRequest( IrpContext, Irp, Status );
5243
5244 DebugTrace(-1, Dbg, "FatGetVolumeBitmap -> VOID\n", 0);
5245
5246 return Status;
5247}
5248
5249
5250//
5251// Local Support Routine
5252//
5253
5254_Requires_lock_held_(_Global_critical_region_)
5256FatGetRetrievalPointers (
5257 IN PIRP_CONTEXT IrpContext,
5258 IN PIRP Irp
5259 )
5260
5261/*++
5262
5263Routine Description:
5264
5265 This routine scans the MCB and builds an extent list. The first run in
5266 the output extent list will start at the begining of the contiguous
5267 run specified by the input parameter.
5268
5269 Input = STARTING_VCN_INPUT_BUFFER;
5270 Output = RETRIEVAL_POINTERS_BUFFER.
5271
5272Arguments:
5273
5274 Irp - Supplies the Irp being processed.
5275
5276Return Value:
5277
5278 NTSTATUS - The return status for the operation.
5279
5280--*/
5281{
5284
5285 PVCB Vcb;
5286 PFCB FcbOrDcb;
5287 PCCB Ccb;
5288 PLARGE_MCB McbToUse = NULL;
5290
5291 ULONG Index;
5292 ULONG ClusterShift = 0;
5295
5296 ULONG Run;
5297 ULONG RunCount;
5298 ULONG StartingRun;
5299 LARGE_INTEGER StartingVcn;
5300
5303
5304 VBO LastVbo;
5305 LBO LastLbo;
5306 ULONG LastIndex;
5307
5309
5310 PAGED_CODE();
5311
5312 //
5313 // Get the current Irp stack location and save some references.
5314 //
5315
5317
5318 DebugTrace(+1, Dbg, "FatGetRetrievalPointers, FsControlCode = %08lx\n",
5319 IrpSp->Parameters.FileSystemControl.FsControlCode);
5320
5321 //
5322 // Make this a synchronous IRP because we need access to the input buffer and
5323 // this Irp is marked METHOD_NEITHER.
5324 //
5325
5326 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
5327
5328 //
5329 // Extract and decode the file object and check for type of open.
5330 //
5331
5333
5335
5338 }
5339
5340 //
5341 // Get the input and output buffer lengths and pointers.
5342 // Initialize some variables.
5343 //
5344
5345 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
5346 OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
5347
5349
5350 //
5351 // Check for a minimum length on the input and ouput buffers.
5352 //
5353
5356
5359 }
5360
5361 //
5362 // Acquire the Fcb and enqueue the Irp if we didn't get access. Go for
5363 // shared on read-only media so we can allow prototype XIP to get
5364 // recursive, as well as recognizing this is safe anyway.
5365 //
5367
5369
5370 (VOID)FatAcquireSharedFcb( IrpContext, FcbOrDcb );
5371
5372 } else {
5373
5374 (VOID)FatAcquireExclusiveFcb( IrpContext, FcbOrDcb );
5375 }
5376 } else if ((TypeOfOpen == UserVolumeOpen )) {
5377
5379
5381
5382 DebugTrace(-1, Dbg, "FatMoveFile -> 0x%x\n", STATUS_ACCESS_DENIED);
5383 return STATUS_ACCESS_DENIED;
5384 }
5385
5386 (VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
5387 }
5388
5389 _SEH2_TRY {
5390
5391 //
5392 // Verify the Fcb is still OK, or if it is a volume handle, the VCB.
5393 //
5394
5396
5397 FatVerifyFcb( IrpContext, FcbOrDcb );
5398
5399 //
5400 // If we haven't yet set the correct AllocationSize, do so.
5401 //
5402
5403 if (FcbOrDcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {
5404
5405 FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
5406
5407 //
5408 // If this is a non-root directory, we have a bit more to
5409 // do since it has not gone through FatOpenDirectoryFile().
5410 //
5411
5412 if (NodeType(FcbOrDcb) == FAT_NTC_DCB ||
5414
5415 FcbOrDcb->Header.FileSize.LowPart =
5416 FcbOrDcb->Header.AllocationSize.LowPart;
5417 }
5418 }
5419
5420
5421 ClusterShift = Vcb->AllocationSupport.LogOfBytesPerCluster;
5422
5423#ifdef _MSC_VER
5424#pragma prefast( suppress:28931, "calculate it anyway, in case someone adds code that uses this in the future" )
5425#endif
5426 ClusterSize = 1 << ClusterShift;
5427
5428 AllocationSize = FcbOrDcb->Header.AllocationSize.LowPart;
5429 McbToUse = &FcbOrDcb->Mcb;
5430
5431 } else if ((TypeOfOpen == UserVolumeOpen )) {
5432
5433 FatQuickVerifyVcb( IrpContext, Vcb );
5434
5436
5437 //
5438 // If the bad cluster mcb isn't populated, something is wrong. (It should have been
5439 // populated during mount when we scanned the FAT.
5440 //
5441
5443 }
5444
5445 ClusterShift = Vcb->AllocationSupport.LogOfBytesPerCluster;
5446 ClusterSize = 1 << ClusterShift;
5447
5448 if (!FatLookupLastMcbEntry(Vcb, &Vcb->BadBlockMcb, &LastVbo, &LastLbo, &LastIndex)) {
5449 AllocationSize = 0;
5450 } else {
5451
5452 //
5453 // Round the allocation size to a multiple of of the cluster size.
5454 //
5455
5456 AllocationSize = (LastVbo + ((LONGLONG)ClusterSize-1)) & ~((LONGLONG)ClusterSize-1);
5457 }
5458
5459 McbToUse = &Vcb->BadBlockMcb;
5460
5461 }
5462
5463 //
5464 // Check if a starting cluster was specified.
5465 //
5466
5467 _SEH2_TRY {
5468
5469 if (Irp->RequestorMode != KernelMode) {
5470
5471 ProbeForRead( IrpSp->Parameters.FileSystemControl.Type3InputBuffer,
5473 sizeof(UCHAR) );
5474
5476 }
5477
5478 StartingVcn = ((PSTARTING_VCN_INPUT_BUFFER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer)->StartingVcn;
5479
5481
5483
5484 FatRaiseStatus( IrpContext,
5487 } _SEH2_END;
5488
5489 if (StartingVcn.HighPart ||
5490 StartingVcn.LowPart >= (AllocationSize >> ClusterShift)) {
5491
5493
5494 } else {
5495
5496 //
5497 // If we don't find the run, something is very wrong.
5498 //
5499
5500 LBO Lbo;
5501
5502 if (!FatLookupMcbEntry( Vcb, McbToUse,
5503 StartingVcn.LowPart << ClusterShift,
5504 &Lbo,
5505 NULL,
5506 &StartingRun)) {
5507
5508#ifdef _MSC_VER
5509#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
5510#endif
5511 FatBugCheck( (ULONG_PTR)FcbOrDcb, (ULONG_PTR)McbToUse, StartingVcn.LowPart );
5512 }
5513 }
5514
5515 //
5516 // Now go fill in the ouput buffer with run information
5517 //
5518
5519 RunCount = FsRtlNumberOfRunsInLargeMcb( McbToUse );
5520
5521 for (Index = 0, Run = StartingRun; Run < RunCount; Index++, Run++) {
5522
5523 ULONG Vcn;
5524 LBO Lbo;
5525 ULONG ByteLength;
5526
5527 //
5528 // Check for an exhausted output buffer.
5529 //
5530
5532
5533
5534 //
5535 // We've run out of space, so we won't be storing as many runs to the
5536 // user's buffer as we had originally planned. We need to return the
5537 // number of runs that we did have room for.
5538 //
5539
5540 _SEH2_TRY {
5541
5542 OutputBuffer->ExtentCount = Index;
5543
5545
5547
5548 FatRaiseStatus( IrpContext,
5551 } _SEH2_END;
5552
5553 Irp->IoStatus.Information = FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[Index]);
5555 }
5556
5557 //
5558 // Get the extent. If it's not there or malformed, something is very wrong.
5559 //
5560
5561 if (!FatGetNextMcbEntry(Vcb, McbToUse, Run, (PVBO)&Vcn, &Lbo, &ByteLength)) {
5562
5563#ifdef _MSC_VER
5564#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
5565#endif
5566 FatBugCheck( (ULONG_PTR)FcbOrDcb, (ULONG_PTR)McbToUse, Run );
5567 }
5568
5569 //
5570 // Fill in the next array element.
5571 //
5572
5573 _SEH2_TRY {
5574
5575 OutputBuffer->Extents[Index].NextVcn.QuadPart = ((LONGLONG)Vcn + ByteLength) >> ClusterShift;
5576 OutputBuffer->Extents[Index].Lcn.QuadPart = FatGetIndexFromLbo( Vcb, Lbo ) - 2;
5577
5578 //
5579 // If this is the first run, fill in the starting Vcn
5580 //
5581
5582 if (Index == 0) {
5583 OutputBuffer->ExtentCount = RunCount - StartingRun;
5584 OutputBuffer->StartingVcn.QuadPart = Vcn >> ClusterShift;
5585 }
5586
5588
5590
5591 FatRaiseStatus( IrpContext,
5594 } _SEH2_END;
5595 }
5596
5597 //
5598 // We successfully retrieved extent info to the end of the allocation.
5599 //
5600
5601 Irp->IoStatus.Information = FIELD_OFFSET(RETRIEVAL_POINTERS_BUFFER, Extents[Index]);
5603
5604 try_exit: NOTHING;
5605
5606 } _SEH2_FINALLY {
5607
5608 DebugUnwind( FatGetRetrievalPointers );
5609
5610 //
5611 // Release resources
5612 //
5613
5615
5616 FatReleaseFcb( IrpContext, FcbOrDcb );
5617 } else if ((TypeOfOpen == UserVolumeOpen )) {
5618
5619 FatReleaseVcb(IrpContext, Vcb);
5620 }
5621
5622 //
5623 // If nothing raised then complete the irp.
5624 //
5625
5627
5628 FatCompleteRequest( IrpContext, Irp, Status );
5629 }
5630
5631 DebugTrace(-1, Dbg, "FatGetRetrievalPointers -> VOID\n", 0);
5632 } _SEH2_END;
5633
5634 return Status;
5635}
5636
5637
5638//
5639// Local Support Routine
5640//
5641
5642_Requires_lock_held_(_Global_critical_region_)
5643VOID
5644FatMoveFileNeedsWriteThrough (
5645 _In_ PIRP_CONTEXT IrpContext,
5647 _In_ ULONG OldWriteThroughFlags
5648 )
5649{
5650 PAGED_CODE();
5651
5652 if (NodeType(FcbOrDcb) == FAT_NTC_FCB) {
5653
5654
5655 if (FcbOrDcb->Header.ValidDataLength.QuadPart == 0) {
5656
5657
5658 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH );
5659 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH );
5660
5661 } else {
5662
5664 IrpContext->Flags |= OldWriteThroughFlags;
5665
5666 }
5667 }
5668}
5669
5670_Requires_lock_held_(_Global_critical_region_)
5672FatMoveFile (
5673 IN PIRP_CONTEXT IrpContext,
5674 IN PIRP Irp
5675 )
5676
5677/*++
5678
5679Routine Description:
5680
5681 Routine moves a file to the requested Starting Lcn from Starting Vcn for the length
5682 of cluster count. These values are passed in through the the input buffer as a
5683 MOVE_DATA structure.
5684
5685 The call must be made with a DASD handle. The file to move is passed in as a
5686 parameter.
5687
5688Arguments:
5689
5690 Irp - Supplies the Irp being processed.
5691
5692Return Value:
5693
5694 NTSTATUS - The return status for the operation.
5695
5696--*/
5697
5698{
5701
5704 PVCB Vcb;
5705 PFCB FcbOrDcb;
5706 PCCB Ccb;
5707
5710
5711 ULONG ClusterShift;
5712 ULONG MaxClusters;
5713
5715
5716 LBO TargetLbo;
5717 ULONG TargetCluster;
5718 LARGE_INTEGER LargeSourceLbo;
5719 LARGE_INTEGER LargeTargetLbo;
5720
5722 ULONG BytesToWrite;
5723 ULONG BytesToReallocate;
5724
5725 ULONG FirstSpliceSourceCluster;
5726 ULONG FirstSpliceTargetCluster;
5727 ULONG SecondSpliceSourceCluster;
5728 ULONG SecondSpliceTargetCluster;
5729
5730 LARGE_MCB SourceMcb;
5731 LARGE_MCB TargetMcb;
5732
5733 KEVENT StackEvent;
5734
5735 PVOID Buffer = NULL;
5737
5738 BOOLEAN SourceMcbInitialized = FALSE;
5739 BOOLEAN TargetMcbInitialized = FALSE;
5740
5741 BOOLEAN FcbAcquired = FALSE;
5742 BOOLEAN EventArmed = FALSE;
5743 BOOLEAN DiskSpaceAllocated = FALSE;
5744
5746 PBCB DirentBcb = NULL;
5747
5748 ULONG OldWriteThroughFlags = (IrpContext->Flags & (IRP_CONTEXT_FLAG_WRITE_THROUGH|IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH));
5749
5750#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
5751 MOVE_FILE_DATA LocalMoveFileData;
5752 PMOVE_FILE_DATA32 MoveFileData32;
5753#endif
5754
5755 ULONG LocalAbnormalTermination = 0;
5756
5757 PAGED_CODE();
5758
5759 //
5760 // Get the current Irp stack location and save some references.
5761 //
5762
5764
5765 DebugTrace(+1, Dbg, "FatMoveFile, FsControlCode = %08lx\n",
5766 IrpSp->Parameters.FileSystemControl.FsControlCode);
5767
5768 //
5769 // Force WAIT to true. We have a handle in the input buffer which can only
5770 // be referenced within the originating process.
5771 //
5772
5773 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
5774
5775 //
5776 // Extract and decode the file object and check for type of open.
5777 //
5778
5780
5782
5783 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
5785 }
5786
5788
5790
5791 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
5793 }
5794
5795 InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
5796 InputBuffer = (PMOVE_FILE_DATA)Irp->AssociatedIrp.SystemBuffer;
5797
5798 //
5799 // Do a quick check on the input buffer.
5800 //
5801
5802#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
5803 if (IoIs32bitProcess( Irp )) {
5804
5805 if (InputBuffer == NULL || InputBufferLength < sizeof(MOVE_FILE_DATA32)) {
5806
5809 }
5810
5811 MoveFileData32 = (PMOVE_FILE_DATA32) InputBuffer;
5812
5813 LocalMoveFileData.FileHandle = (HANDLE) LongToHandle( MoveFileData32->FileHandle );
5814 LocalMoveFileData.StartingVcn = MoveFileData32->StartingVcn;
5815 LocalMoveFileData.StartingLcn = MoveFileData32->StartingLcn;
5816 LocalMoveFileData.ClusterCount = MoveFileData32->ClusterCount;
5817
5818 InputBuffer = &LocalMoveFileData;
5819
5820 } else {
5821#endif
5822 if (InputBuffer == NULL || InputBufferLength < sizeof(MOVE_FILE_DATA)) {
5823
5826 }
5827#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
5828 }
5829#endif
5830
5831 MaxClusters = Vcb->AllocationSupport.NumberOfClusters;
5832 TargetCluster = InputBuffer->StartingLcn.LowPart + 2;
5833
5834 if (InputBuffer->StartingVcn.HighPart ||
5835 InputBuffer->StartingLcn.HighPart ||
5836 (TargetCluster < 2) ||
5837 (TargetCluster + InputBuffer->ClusterCount < TargetCluster) ||
5838 (TargetCluster + InputBuffer->ClusterCount > MaxClusters + 2) ||
5839 (InputBuffer->StartingVcn.LowPart >= MaxClusters) ||
5840 InputBuffer->ClusterCount == 0
5841 ) {
5842
5844
5845 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
5847 }
5848
5849 //
5850 // Try to get a pointer to the file object from the handle passed in.
5851 //
5852
5854 0,
5856 Irp->RequestorMode,
5857#ifndef __REACTOS__
5858 &FileObject,
5859#else
5860 (PVOID *)&FileObject,
5861#endif
5862 NULL );
5863
5864 if (!NT_SUCCESS(Status)) {
5865
5866 FatCompleteRequest( IrpContext, Irp, Status );
5867
5868 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", Status);
5869 return Status;
5870 }
5871
5872 //
5873 // There are three basic ways this could be an invalid attempt, so
5874 // we need to
5875 //
5876 // - check that this file object is opened on the same volume as the
5877 // DASD handle used to call this routine.
5878 //
5879 // - extract and decode the file object and check for type of open.
5880 //
5881 // - if this is a directory, verify that it's not the root and that
5882 // we are not trying to move the first cluster. We cannot move the
5883 // first cluster because sub-directories have this cluster number
5884 // in them and there is no safe way to simultaneously update them
5885 // all.
5886 //
5887 // We'll allow movefile on the root dir if its fat32, since the root dir
5888 // is a real chained file there.
5889 //
5890
5891 if (FileObject->Vpb != Vcb->Vpb) {
5892
5895
5896 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
5898 }
5899
5901
5902 if ((TypeOfOpen != UserFileOpen &&
5904
5907 (InputBuffer->StartingVcn.QuadPart == 0)))) {
5908
5911
5912 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_INVALID_PARAMETER);
5914 }
5915
5916 //
5917 // If the VDL of the file is zero, it has no valid data in it anyway.
5918 // So it should be safe to avoid flushing the FAT entries and let them be
5919 // lazily written out.
5920 //
5921 // This is done so that bitlocker's cover file doesn't cause
5922 // unnecessary FAT table I/O when it's moved around.
5923 // (See Win8 bug 106505)
5924 //
5925
5926 //
5927 // If this is a file, and the VDL is zero, clear write through.
5928 //
5929
5930 FatMoveFileNeedsWriteThrough(IrpContext, FcbOrDcb, OldWriteThroughFlags);
5931
5932
5933 //
5934 // Indicate we're getting to parents of this fcb by their child, and that
5935 // this is a sufficient assertion of our ability to by synchronized
5936 // with respect to the parent directory going away.
5937 //
5938 // The defrag path is an example of one which arrives at an Fcb by
5939 // a means which would be unreasonable to duplicate in the assertion
5940 // code. See FatOpenDirectoryFile.
5941 //
5942
5943 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_PARENT_BY_CHILD );
5944
5945 ClusterShift = Vcb->AllocationSupport.LogOfBytesPerCluster;
5946
5947 _SEH2_TRY {
5948
5949 //
5950 // Initialize our state variables and the event.
5951 //
5952
5953 FileOffset = InputBuffer->StartingVcn.LowPart << ClusterShift;
5954
5955 ByteCount = InputBuffer->ClusterCount << ClusterShift;
5956
5957 TargetLbo = FatGetLboFromIndex( Vcb, TargetCluster );
5958 LargeTargetLbo.QuadPart = TargetLbo;
5959
5960 Buffer = NULL;
5961
5962 //
5963 // Do a quick check on parameters here
5964 //
5965
5967
5969 }
5970
5971 KeInitializeEvent( &StackEvent, NotificationEvent, FALSE );
5972
5973 //
5974 // Initialize two MCBs we will be using
5975 //
5976
5977 FsRtlInitializeLargeMcb( &SourceMcb, PagedPool );
5978 SourceMcbInitialized = TRUE;
5979
5980 FsRtlInitializeLargeMcb( &TargetMcb, PagedPool );
5981 TargetMcbInitialized = TRUE;
5982
5983 //
5984 // Ok, now if this is a directory open we need to switch to the internal
5985 // stream fileobject since it is set up for caching. The top-level
5986 // fileobject has no section object pointers in order prevent folks from
5987 // mapping it.
5988 //
5989
5991
5992 PFILE_OBJECT DirStreamFileObject;
5993
5994 //
5995 // Open the stream fileobject if neccesary. We must acquire the Fcb
5996 // now to synchronize with other operations (such as dismount ripping
5997 // apart the allocator).
5998 //
5999
6000 (VOID)FatAcquireExclusiveFcb( IrpContext, FcbOrDcb );
6001 FcbAcquired = TRUE;
6002
6003 FatVerifyFcb( IrpContext, FcbOrDcb );
6004
6005 FatOpenDirectoryFile( IrpContext, FcbOrDcb );
6006 DirStreamFileObject = FcbOrDcb->Specific.Dcb.DirectoryFile;
6007
6008 //
6009 // Transfer our reference to the internal stream and proceed. Note that
6010 // if we dereferenced first, the user could sneak a teardown through since
6011 // we'd have no references.
6012 //
6013
6014 ObReferenceObject( DirStreamFileObject );
6016 FileObject = DirStreamFileObject;
6017
6018 //
6019 // We've referenced the DirStreamFileObject, so it should be ok to drop
6020 // the Dcb now.
6021 //
6022
6023 FatReleaseFcb( IrpContext, FcbOrDcb );
6024 FcbAcquired = FALSE;
6025 }
6026
6027 //
6028 // Determine the size of the buffer we will use to move data.
6029 //
6030
6032
6033 if (BufferSize < (ULONG)(1 << ClusterShift)) {
6034
6035 BufferSize = (1 << ClusterShift);
6036 }
6037
6038 while (ByteCount) {
6039
6040 VBO TempVbo;
6041 LBO TempLbo;
6042 ULONG TempByteCount;
6043
6044 //
6045 // We must throttle our writes.
6046 //
6047
6049 BufferSize,
6050 TRUE,
6051 FALSE );
6052
6053 //
6054 // Aqcuire file resource exclusive to freeze FileSize and block
6055 // user non-cached I/O. Verify the integrity of the fcb - the
6056 // media may have changed (or been dismounted) on us.
6057 //
6058
6059 if (FcbAcquired == FALSE) {
6060
6061 (VOID)FatAcquireExclusiveFcb( IrpContext, FcbOrDcb );
6062 FcbAcquired = TRUE;
6063
6064 FatVerifyFcb( IrpContext, FcbOrDcb );
6065 }
6066
6067 //
6068 // Check if the handle indicates we're allowed to move the file.
6069 //
6070 // FCB_STATE_DENY_DEFRAG indicates that someone blocked move file on this FCB.
6071 // CCB_FLAG_DENY_DEFRAG indicates that this handle was the one that blocked move file, and hence
6072 // it still gets to move the file around.
6073 //
6074
6076 DebugTrace(-1, Dbg, "FatMoveFile -> %08lx\n", STATUS_ACCESS_DENIED);
6078 }
6079
6080 //
6081 // Allocate our buffer, if we need to.
6082 //
6083
6084 if (Buffer == NULL) {
6085
6086 Buffer = FsRtlAllocatePoolWithTag( NonPagedPoolNx,
6087 BufferSize,
6089 }
6090
6091 //
6092 // Analyzes the range of file allocation we are moving
6093 // and determines the actual amount of allocation to be
6094 // moved and how much needs to be written. In addition
6095 // it guarantees that the Mcb in the file is large enough
6096 // so that later MCB operations cannot fail.
6097 //
6098
6099 FatComputeMoveFileParameter( IrpContext,
6100 FcbOrDcb,
6101 BufferSize,
6102 FileOffset,
6103 &ByteCount,
6104 &BytesToReallocate,
6105 &BytesToWrite,
6106 &LargeSourceLbo );
6107
6108 //
6109 // If ByteCount comes back zero, break here.
6110 //
6111
6112 if (ByteCount == 0) {
6113 break;
6114 }
6115
6116 //
6117 // At this point (before actually doing anything with the disk
6118 // meta data), calculate the FAT splice clusters and build an
6119 // MCB describing the space to be deallocated.
6120 //
6121
6123 FcbOrDcb,
6124 FileOffset,
6125 TargetCluster,
6126 BytesToReallocate,
6127 &FirstSpliceSourceCluster,
6128 &FirstSpliceTargetCluster,
6129 &SecondSpliceSourceCluster,
6130 &SecondSpliceTargetCluster,
6131 &SourceMcb );
6132
6133 //
6134 // Now attempt to allocate the new disk storage using the
6135 // Target Lcn as a hint.
6136 //
6137
6138 TempByteCount = BytesToReallocate;
6139 FatAllocateDiskSpace( IrpContext,
6140 Vcb,
6141 TargetCluster,
6142 &TempByteCount,
6143 TRUE,
6144 &TargetMcb );
6145
6146 DiskSpaceAllocated = TRUE;
6147
6148 //
6149 // If we didn't get EXACTLY what we wanted, return immediately.
6150 //
6151
6152 if ((FsRtlNumberOfRunsInLargeMcb( &TargetMcb ) != 1) ||
6153 !FatGetNextMcbEntry( Vcb, &TargetMcb, 0, &TempVbo, &TempLbo, &TempByteCount ) ||
6154 (FatGetIndexFromLbo( Vcb, TempLbo) != TargetCluster ) ||
6155 (TempByteCount != BytesToReallocate)) {
6156
6157 //
6158 // It would be nice if we could be more specific, but such is life.
6159 //
6161 }
6162
6163#if DBG
6164 //
6165 // We are going to attempt a move, note it.
6166 //
6167
6168 if (FatMoveFileDebug) {
6169 DbgPrint("0x%p: Vcn 0x%lx, Lcn 0x%lx, Count 0x%lx.\n",
6171 FileOffset >> ClusterShift,
6172 TargetCluster,
6173 BytesToReallocate >> ClusterShift );
6174 }
6175#endif
6176
6177 //
6178 // Now attempt to commit the new allocation to disk. If this
6179 // raises, the allocation will be deallocated.
6180 //
6181 // If the VDL of the file is zero, it has no valid data in it anyway.
6182 // So it should be safe to avoid flushing the FAT entries and let them be
6183 // lazily written out.
6184 //
6185 // This is done so that bitlocker's cover file doesn't cause
6186 // unnecessary FAT table I/O when it's moved around.
6187 // (See Win8 bug 106505)
6188 //
6189
6190 if ((FcbOrDcb->Header.ValidDataLength.QuadPart != 0) || (NodeType(FcbOrDcb) != FAT_NTC_FCB)) {
6191
6192 FatFlushFatEntries( IrpContext,
6193 Vcb,
6194 TargetCluster,
6195 BytesToReallocate >> ClusterShift );
6196 }
6197
6198 //
6199 // Aqcuire both resources exclusive now, guaranteeing that NOBODY
6200 // is in either the read or write paths.
6201 //
6202
6203 ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
6204
6205 //
6206 // This is the first part of some tricky synchronization.
6207 //
6208 // Set the Event pointer in the FCB. Any paging I/O will block on
6209 // this event (if set in FCB) after acquiring the PagingIo resource.
6210 //
6211 // This is how I keep ALL I/O out of this path without holding the
6212 // PagingIo resource exclusive for an extended time.
6213 //
6214
6215 FcbOrDcb->MoveFileEvent = &StackEvent;
6216 EventArmed = TRUE;
6217
6218 ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
6219
6220 //
6221 // Now write out the data, but only if we have to. We don't have
6222 // to copy any file data if the range being reallocated is wholly
6223 // beyond valid data length.
6224 //
6225
6226 if (BytesToWrite) {
6227
6228 PIRP IoIrp;
6229 KEVENT IoEvent;
6231
6232 KeInitializeEvent( &IoEvent,
6234 FALSE );
6235
6236 NT_ASSERT( LargeTargetLbo.QuadPart >= Vcb->AllocationSupport.FileAreaLbo );
6237
6238 //
6239 // Read in the data that is being moved.
6240 //
6241
6243 Vcb->TargetDeviceObject,
6244 Buffer,
6245 BytesToWrite,
6246 &LargeSourceLbo,
6247 &IoEvent,
6248 &Iosb );
6249
6250 if (IoIrp == NULL) {
6251
6252 FatRaiseStatus( IrpContext,
6254 }
6255
6256 Status = IoCallDriver( Vcb->TargetDeviceObject, IoIrp );
6257
6258 if (Status == STATUS_PENDING) {
6259
6260 (VOID)KeWaitForSingleObject( &IoEvent,
6261 Executive,
6262 KernelMode,
6263 FALSE,
6265
6266 Status = Iosb.Status;
6267 }
6268
6269 if (!NT_SUCCESS( Status )) {
6270
6271 FatNormalizeAndRaiseStatus( IrpContext,
6272 Status );
6273 }
6274
6275 //
6276 // Write the data to its new location.
6277 //
6278
6279 KeClearEvent( &IoEvent );
6280
6282 Vcb->TargetDeviceObject,
6283 Buffer,
6284 BytesToWrite,
6285 &LargeTargetLbo,
6286 &IoEvent,
6287 &Iosb );
6288
6289 if (IoIrp == NULL) {
6290
6291 FatRaiseStatus( IrpContext,
6293 }
6294
6295 //
6296 // Set a flag indicating that we want to write through any
6297 // cache on the controller. This eliminates the need for
6298 // an explicit flush-device after the write.
6299 //
6300
6302
6303 Status = IoCallDriver( Vcb->TargetDeviceObject, IoIrp );
6304
6305 if (Status == STATUS_PENDING) {
6306
6307 (VOID)KeWaitForSingleObject( &IoEvent,
6308 Executive,
6309 KernelMode,
6310 FALSE,
6312
6313 Status = Iosb.Status;
6314 }
6315
6316 if (!NT_SUCCESS( Status )) {
6317
6318 FatNormalizeAndRaiseStatus( IrpContext,
6319 Status );
6320 }
6321 }
6322
6323 //
6324 // Now that the file data has been moved successfully, we'll go
6325 // to fix up the links in the FAT table and perhaps change the
6326 // entry in the parent directory.
6327 //
6328 // First we'll do the second splice and commit it. At that point,
6329 // while the volume is in an inconsistent state, the file is
6330 // still OK.
6331 //
6332
6333 FatSetFatEntry( IrpContext,
6334 Vcb,
6335 SecondSpliceSourceCluster,
6336 (FAT_ENTRY)SecondSpliceTargetCluster );
6337
6338 if ((FcbOrDcb->Header.ValidDataLength.QuadPart != 0) || (NodeType(FcbOrDcb) != FAT_NTC_FCB)) {
6339
6340 FatFlushFatEntries( IrpContext, Vcb, SecondSpliceSourceCluster, 1 );
6341 }
6342
6343 //
6344 // Now do the first splice OR update the dirent in the parent
6345 // and flush the respective object. After this flush the file
6346 // now points to the new allocation.
6347 //
6348
6349 if (FirstSpliceSourceCluster == 0) {
6350
6352
6353 //
6354 // We are moving the first cluster of the file, so we need
6355 // to update our parent directory.
6356 //
6357
6358 FatGetDirentFromFcbOrDcb( IrpContext,
6359 FcbOrDcb,
6360 FALSE,
6361 &Dirent,
6362 &DirentBcb );
6363
6364 Dirent->FirstClusterOfFile = (USHORT)FirstSpliceTargetCluster;
6365
6366 if (FatIsFat32(Vcb)) {
6367
6368 Dirent->FirstClusterOfFileHi =
6369 (USHORT)(FirstSpliceTargetCluster >> 16);
6370
6371 }
6372
6373 FatSetDirtyBcb( IrpContext, DirentBcb, Vcb, TRUE );
6374
6375 FatUnpinBcb( IrpContext, DirentBcb );
6376 DirentBcb = NULL;
6377
6378 FatFlushDirentForFile( IrpContext, FcbOrDcb );
6379
6380 FcbOrDcb->FirstClusterOfFile = FirstSpliceTargetCluster;
6381
6382 } else {
6383
6384 FatSetFatEntry( IrpContext,
6385 Vcb,
6386 FirstSpliceSourceCluster,
6387 (FAT_ENTRY)FirstSpliceTargetCluster );
6388
6389 if ((FcbOrDcb->Header.ValidDataLength.QuadPart != 0) || (NodeType(FcbOrDcb) != FAT_NTC_FCB)) {
6390
6391 FatFlushFatEntries( IrpContext, Vcb, FirstSpliceSourceCluster, 1 );
6392 }
6393 }
6394
6395 //
6396 // This was successfully committed. We no longer want to free
6397 // this allocation on error.
6398 //
6399
6400 DiskSpaceAllocated = FALSE;
6401
6402 //
6403 // Check if we need to turn off write through for this file.
6404 //
6405
6406 FatMoveFileNeedsWriteThrough(IrpContext, FcbOrDcb, OldWriteThroughFlags);
6407
6408 //
6409 // Now we just have to free the orphaned space. We don't have
6410 // to commit this right now as the integrity of the file doesn't
6411 // depend on it.
6412 //
6413
6414 FatDeallocateDiskSpace( IrpContext, Vcb, &SourceMcb, FALSE );
6415
6416 FatUnpinRepinnedBcbs( IrpContext );
6417
6418 Status = FatHijackIrpAndFlushDevice( IrpContext,
6419 Irp,
6420 Vcb->TargetDeviceObject );
6421
6422 if (!NT_SUCCESS(Status)) {
6423 FatNormalizeAndRaiseStatus( IrpContext, Status );
6424 }
6425
6426 //
6427 // Finally we must replace the old MCB extent information with
6428 // the new. If this fails from pool allocation, we fix it in
6429 // the finally clause by resetting the file's Mcb.
6430 //
6431
6433 FileOffset,
6434 BytesToReallocate );
6435
6437 FileOffset,
6438 TargetLbo,
6439 BytesToReallocate );
6440
6441 //
6442 // Now this is the second part of the tricky synchronization.
6443 //
6444 // We drop the paging I/O here and signal the notification
6445 // event which allows all waiters (present or future) to proceed.
6446 // Then we block again on the PagingIo exclusive. When
6447 // we have it, we again know that there can be nobody in the
6448 // read/write path and thus nobody touching the event, so we
6449 // NULL the pointer to it and then drop the PagingIo resource.
6450 //
6451 // This combined with our synchronization before the write above
6452 // guarantees that while we were moving the allocation, there
6453 // was no other I/O to this file and because we do not hold
6454 // the paging resource across a flush, we are not exposed to
6455 // a deadlock.
6456 //
6457
6458 KeSetEvent( &StackEvent, 0, FALSE );
6459
6460 ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
6461
6463 EventArmed = FALSE;
6464
6465 ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
6466
6467 //
6468 // Release the resources and let anyone else access the file before
6469 // looping back.
6470 //
6471
6472 FatReleaseFcb( IrpContext, FcbOrDcb );
6473 FcbAcquired = FALSE;
6474
6475 //
6476 // Advance the state variables.
6477 //
6478
6479 TargetCluster += BytesToReallocate >> ClusterShift;
6480
6481 FileOffset += BytesToReallocate;
6482 TargetLbo += BytesToReallocate;
6483 ByteCount -= BytesToReallocate;
6484
6485 LargeTargetLbo.QuadPart += BytesToReallocate;
6486
6487 //
6488 // Clear the two Mcbs
6489 //
6490
6491 FatRemoveMcbEntry( Vcb, &SourceMcb, 0, 0xFFFFFFFF );
6492 FatRemoveMcbEntry( Vcb, &TargetMcb, 0, 0xFFFFFFFF );
6493
6494 //
6495 // Make the event blockable again.
6496 //
6497
6498 KeClearEvent( &StackEvent );
6499 }
6500
6502
6503 try_exit: NOTHING;
6504
6505 } _SEH2_FINALLY {
6506
6507 DebugUnwind( FatMoveFile );
6508
6509 LocalAbnormalTermination |= _SEH2_AbnormalTermination();
6510
6511 ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_PARENT_BY_CHILD );
6512
6513 //
6514 // Free the data buffer, if it was allocated.
6515 //
6516
6517 if (Buffer != NULL) {
6518
6519 ExFreePool( Buffer );
6520 }
6521
6522 //
6523 // Use a nested try-finally for cleanup if our unpinrepinned
6524 // encounters write-through errors. This may even be a re-raise.
6525 //
6526
6527 _SEH2_TRY {
6528
6529 //
6530 // If we have some new allocation hanging around, remove it. The
6531 // pages needed to do this are guaranteed to be resident because
6532 // we have already repinned them.
6533 //
6534
6535 if (DiskSpaceAllocated) {
6536 FatDeallocateDiskSpace( IrpContext, Vcb, &TargetMcb, FALSE );
6537 FatUnpinRepinnedBcbs( IrpContext );
6538 }
6539
6540 } _SEH2_FINALLY {
6541
6542 LocalAbnormalTermination |= _SEH2_AbnormalTermination();
6543
6544 //
6545 // Check on the directory Bcb
6546 //
6547
6548 if (DirentBcb != NULL) {
6549 FatUnpinBcb( IrpContext, DirentBcb );
6550 }
6551
6552 //
6553 // Uninitialize our MCBs
6554 //
6555
6556 if (SourceMcbInitialized) {
6557 FsRtlUninitializeLargeMcb( &SourceMcb );
6558 }
6559
6560 if (TargetMcbInitialized) {
6561 FsRtlUninitializeLargeMcb( &TargetMcb );
6562 }
6563
6564 //
6565 // If this is an abnormal termination then presumably something
6566 // bad happened. Set the Allocation size to unknown and clear
6567 // the Mcb, but only if we still own the Fcb.
6568 //
6569 // It is important to make sure we use a 64bit form of -1. This is
6570 // what will convince the fastIO path that it cannot extend the file
6571 // in the cache until we have picked up the mapping pairs again.
6572 //
6573 // Also, we have to do this while owning PagingIo or we can tear the
6574 // Mcb down in the midst of the noncached IO path looking up extents
6575 // (after we drop it and let them all in).
6576 //
6577
6578 if (LocalAbnormalTermination && FcbAcquired) {
6579
6580 if (FcbOrDcb->FirstClusterOfFile == 0) {
6581
6582 FcbOrDcb->Header.AllocationSize.QuadPart = 0;
6583
6584 } else {
6585
6586 FcbOrDcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
6587 }
6588
6589 FatRemoveMcbEntry( Vcb, &FcbOrDcb->Mcb, 0, 0xFFFFFFFF );
6590 }
6591
6592 //
6593 // If we broke out of the loop with the Event armed, defuse it
6594 // in the same way we do it after a write.
6595 //
6596
6597 if (EventArmed) {
6598 KeSetEvent( &StackEvent, 0, FALSE );
6599 ExAcquireResourceExclusiveLite( FcbOrDcb->Header.PagingIoResource, TRUE );
6601 ExReleaseResourceLite( FcbOrDcb->Header.PagingIoResource );
6602 }
6603
6604 //
6605 // Finally release the main file resource.
6606 //
6607
6608 if (FcbAcquired) {
6609
6610 FatReleaseFcb( IrpContext, FcbOrDcb );
6611 }
6612
6613 //
6614 // Now dereference the fileobject. If the user was a wacko they could have
6615 // tried to nail us by closing the handle right after they threw this move
6616 // down, so we had to keep the fileobject referenced across the entire
6617 // operation.
6618 //
6619
6621
6622 } _SEH2_END;
6623 } _SEH2_END;
6624
6625 //
6626 // Complete the irp if we terminated normally.
6627 //
6628
6629 FatCompleteRequest( IrpContext, Irp, Status );
6630
6631 return Status;
6632}
6633
6634
6635//
6636// Local Support Routine
6637//
6638
6639_Requires_lock_held_(_Global_critical_region_)
6640VOID
6641FatComputeMoveFileParameter (
6642 IN PIRP_CONTEXT IrpContext,
6647 OUT PULONG BytesToReallocate,
6648 OUT PULONG BytesToWrite,
6649 OUT PLARGE_INTEGER SourceLbo
6650)
6651
6652/*++
6653
6654Routine Description:
6655
6656 This is a helper routine for FatMoveFile that analyses the range of
6657 file allocation we are moving and determines the actual amount
6658 of allocation to be moved and how much needs to be written.
6659
6660Arguments:
6661
6662 FcbOrDcb - Supplies the file and its various sizes.
6663
6664 BufferSize - Supplies the size of the buffer we are using to store the data
6665 being moved.
6666
6667 FileOffset - Supplies the beginning Vbo of the reallocation zone.
6668
6669 ByteCount - Supplies the request length to reallocate. This will
6670 be bounded by allocation size on return.
6671
6672 BytesToReallocate - Receives ByteCount bounded by the file allocation size
6673 and buffer size.
6674
6675 BytesToWrite - Receives BytesToReallocate bounded by ValidDataLength.
6676
6677 SourceLbo - Receives the logical byte offset of the source data on the volume.
6678
6679Return Value:
6680
6681 VOID
6682
6683--*/
6684
6685{
6687
6689 ULONG ValidDataLength;
6690 ULONG ClusterAlignedVDL;
6691 LBO RunLbo;
6692 ULONG RunByteCount;
6694 BOOLEAN RunAllocated;
6695 BOOLEAN RunEndOnMax;
6696
6697 PAGED_CODE();
6698
6699 //
6700 // If we haven't yet set the correct AllocationSize, do so.
6701 //
6702
6703 if (FcbOrDcb->Header.AllocationSize.QuadPart == FCB_LOOKUP_ALLOCATIONSIZE_HINT) {
6704
6705 FatLookupFileAllocationSize( IrpContext, FcbOrDcb );
6706
6707 //
6708 // If this is a non-root directory, we have a bit more to
6709 // do since it has not gone through FatOpenDirectoryFile().
6710 //
6711
6712 if (NodeType(FcbOrDcb) == FAT_NTC_DCB ||
6714
6715 FcbOrDcb->Header.FileSize.LowPart =
6716 FcbOrDcb->Header.AllocationSize.LowPart;
6717 }
6718 }
6719
6720 //
6721 // Get the number of bytes left to write and ensure that it does
6722 // not extend beyond allocation size. We return here if FileOffset
6723 // is beyond AllocationSize which can happn on a truncation.
6724 //
6725
6726 AllocationSize = FcbOrDcb->Header.AllocationSize.LowPart;
6727 ValidDataLength = FcbOrDcb->Header.ValidDataLength.LowPart;
6728
6730
6731 if (FileOffset >= AllocationSize) {
6732 *ByteCount = 0;
6733 *BytesToReallocate = 0;
6734 *BytesToWrite = 0;
6735
6736 return;
6737 }
6738
6740 }
6741
6742 //
6743 // If there is more than our max, then reduce the byte count for this
6744 // pass to our maximum. We must also align the file offset to a
6745 // buffer size byte boundary.
6746 //
6747
6748 if ((FileOffset & (BufferSize - 1)) + *ByteCount > BufferSize) {
6749
6750 *BytesToReallocate = BufferSize - (FileOffset & (BufferSize - 1));
6751
6752 } else {
6753
6754 *BytesToReallocate = *ByteCount;
6755 }
6756
6757 //
6758 // Find where this data exists on the volume.
6759 //
6760
6761 FatLookupFileAllocation( IrpContext,
6762 FcbOrDcb,
6763 FileOffset,
6764 &RunLbo,
6765 &RunByteCount,
6766 &RunAllocated,
6767 &RunEndOnMax,
6768 &RunIndex );
6769
6770 NT_ASSERT( RunAllocated );
6771
6772 //
6773 // Limit this run to the contiguous length.
6774 //
6775
6776 if (RunByteCount < *BytesToReallocate) {
6777
6778 *BytesToReallocate = RunByteCount;
6779 }
6780
6781 //
6782 // Set the starting offset of the source.
6783 //
6784
6785 SourceLbo->QuadPart = RunLbo;
6786
6787 //
6788 // We may be able to skip some (or all) of the write
6789 // if allocation size is significantly greater than valid data length.
6790 //
6791
6792 ClusterSize = 1 << FcbOrDcb->Vcb->AllocationSupport.LogOfBytesPerCluster;
6793
6795
6796 ClusterAlignedVDL = (ValidDataLength + (ClusterSize - 1)) & ~(ClusterSize - 1);
6797
6798 if ((NodeType(FcbOrDcb) == FAT_NTC_FCB) &&
6799 (FileOffset + *BytesToReallocate > ClusterAlignedVDL)) {
6800
6801 if (FileOffset > ClusterAlignedVDL) {
6802
6803 *BytesToWrite = 0;
6804
6805 } else {
6806
6807 *BytesToWrite = ClusterAlignedVDL - FileOffset;
6808 }
6809
6810 } else {
6811
6812 *BytesToWrite = *BytesToReallocate;
6813 }
6814}
6815
6816
6817//
6818// Local Support Routine
6819//
6820
6821VOID
6823 IN PIRP_CONTEXT IrpContext,
6826 IN ULONG TargetCluster,
6827 IN ULONG BytesToReallocate,
6828 OUT PULONG FirstSpliceSourceCluster,
6829 OUT PULONG FirstSpliceTargetCluster,
6830 OUT PULONG SecondSpliceSourceCluster,
6831 OUT PULONG SecondSpliceTargetCluster,
6832 IN OUT PLARGE_MCB SourceMcb
6833)
6834
6835/*++
6836
6837Routine Description:
6838
6839 This is a helper routine for FatMoveFile that analyzes the range of
6840 file allocation we are moving and generates the splice points in the
6841 FAT table.
6842
6843Arguments:
6844
6845 FcbOrDcb - Supplies the file and thus Mcb.
6846
6847 FileOffset - Supplies the beginning Vbo of the reallocation zone.
6848
6849 TargetCluster - Supplies the beginning cluster of the reallocation target.
6850
6851 BytesToReallocate - Suppies the length of the reallocation zone.
6852
6853 FirstSpliceSourceCluster - Receives the last cluster in previous allocation
6854 or zero if we are reallocating from VBO 0.
6855
6856 FirstSpliceTargetCluster - Receives the target cluster (i.e. new allocation)
6857
6858 SecondSpliceSourceCluster - Receives the final target cluster.
6859
6860 SecondSpliceTargetCluster - Receives the first cluster of the remaining
6861 source allocation or FAT_CLUSTER_LAST if the reallocation zone
6862 extends to the end of the file.
6863
6864 SourceMcb - This supplies an MCB that will be filled in with run
6865 information describing the file allocation being replaced. The Mcb
6866 must be initialized by the caller.
6867
6868Return Value:
6869
6870 VOID
6871
6872--*/
6873
6874{
6875 VBO SourceVbo;
6876 LBO SourceLbo;
6877 ULONG SourceIndex;
6878 ULONG SourceBytesInRun;
6879 ULONG SourceBytesRemaining;
6880
6881 ULONG SourceMcbVbo = 0;
6882 ULONG SourceMcbBytesInRun = 0;
6883
6884 PVCB Vcb;
6886
6887 PAGED_CODE();
6888
6889 Vcb = FcbOrDcb->Vcb;
6890
6891 //
6892 // Get information on the final cluster in the previous allocation and
6893 // prepare to enumerate it in the follow loop.
6894 //
6895
6896 if (FileOffset == 0) {
6897
6898 SourceIndex = 0;
6899 *FirstSpliceSourceCluster = 0;
6901 0,
6902 &SourceVbo,
6903 &SourceLbo,
6904 &SourceBytesInRun );
6905
6906 } else {
6907
6909 FileOffset-1,
6910 &SourceLbo,
6911 &SourceBytesInRun,
6912 &SourceIndex);
6913
6914 *FirstSpliceSourceCluster = FatGetIndexFromLbo( Vcb, SourceLbo );
6915
6916 if ((Result) && (SourceBytesInRun == 1)) {
6917
6918 SourceIndex += 1;
6920 SourceIndex,
6921 &SourceVbo,
6922 &SourceLbo,
6923 &SourceBytesInRun);
6924
6925 } else {
6926
6927 SourceVbo = FileOffset;
6928 SourceLbo += 1;
6929 SourceBytesInRun -= 1;
6930 }
6931 }
6932
6933 //
6934 // Run should always be present, but don't bugcheck in the case where it's not.
6935 //
6936
6937 if (!Result) {
6938
6939 NT_ASSERT( FALSE);
6941 }
6942
6943 //
6944 // At this point the variables:
6945 //
6946 // - SourceIndex - SourceLbo - SourceBytesInRun -
6947 //
6948 // all correctly decribe the allocation to be removed. In the loop
6949 // below we will start here and continue enumerating the Mcb runs
6950 // until we are finished with the allocation to be relocated.
6951 //
6952
6953 *FirstSpliceTargetCluster = TargetCluster;
6954
6955 *SecondSpliceSourceCluster =
6956 *FirstSpliceTargetCluster +
6957 (BytesToReallocate >> Vcb->AllocationSupport.LogOfBytesPerCluster) - 1;
6958
6959 for (SourceBytesRemaining = BytesToReallocate, SourceMcbVbo = 0;
6960
6961 SourceBytesRemaining > 0;
6962
6963 SourceIndex += 1,
6964 SourceBytesRemaining -= SourceMcbBytesInRun,
6965 SourceMcbVbo += SourceMcbBytesInRun) {
6966
6967 if (SourceMcbVbo != 0) {
6968#ifdef _MSC_VER
6969#pragma prefast( suppress:28931, "needed for debug build" )
6970#endif
6972 SourceIndex,
6973 &SourceVbo,
6974 &SourceLbo,
6975 &SourceBytesInRun );
6976 NT_ASSERT( Result);
6977 }
6978
6979 NT_ASSERT( SourceVbo == SourceMcbVbo + FileOffset );
6980
6981 SourceMcbBytesInRun =
6982 SourceBytesInRun < SourceBytesRemaining ?
6983 SourceBytesInRun : SourceBytesRemaining;
6984
6985 FatAddMcbEntry( Vcb, SourceMcb,
6986 SourceMcbVbo,
6987 SourceLbo,
6988 SourceMcbBytesInRun );
6989 }
6990
6991 //
6992 // Now compute the cluster of the target of the second
6993 // splice. If the final run in the above loop was
6994 // more than we needed, then we can just do arithmetic,
6995 // otherwise we have to look up the next run.
6996 //
6997
6998 if (SourceMcbBytesInRun < SourceBytesInRun) {
6999
7000 *SecondSpliceTargetCluster =
7001 FatGetIndexFromLbo( Vcb, SourceLbo + SourceMcbBytesInRun );
7002
7003 } else {
7004
7006 SourceIndex,
7007 &SourceVbo,
7008 &SourceLbo,
7009 &SourceBytesInRun )) {
7010
7011 *SecondSpliceTargetCluster = FatGetIndexFromLbo( Vcb, SourceLbo );
7012
7013 } else {
7014
7015 *SecondSpliceTargetCluster = FAT_CLUSTER_LAST;
7016 }
7017 }
7018}
7019
7020
7023 IN PIRP_CONTEXT IrpContext,
7024 IN PIRP Irp
7025 )
7026/*++
7027
7028Routine Description:
7029
7030 This routine marks the CCB to indicate that the handle
7031 may be used to read past the end of the volume file. The
7032 handle must be a dasd handle.
7033
7034Arguments:
7035
7036 Irp - Supplies the Irp being processed.
7037
7038Return Value:
7039
7040 NTSTATUS - The return status for the operation.
7041
7042--*/
7043{
7045 PVCB Vcb;
7046 PFCB Fcb;
7047 PCCB Ccb;
7048
7049 PAGED_CODE();
7050
7051 //
7052 // Get the current Irp stack location and save some references.
7053 //
7054
7056
7057 //
7058 // Extract and decode the file object and check for type of open.
7059 //
7060
7062
7065 }
7066
7068
7070
7071 DebugTrace(-1, Dbg, "FatAllowExtendedDasdIo -> %08lx\n", STATUS_INVALID_PARAMETER);
7073 }
7074
7076
7077 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
7078 return STATUS_SUCCESS;
7079}
7080
7081#if (NTDDI_VERSION >= NTDDI_WIN7)
7082
7083_Requires_lock_held_(_Global_critical_region_)
7085FatGetRetrievalPointerBase (
7086 _In_ PIRP_CONTEXT IrpContext,
7087 _In_ PIRP Irp
7088 )
7089/*++
7090
7091Routine Description:
7092
7093 This routine retrieves the sector offset to the first allocation unit.
7094
7095Arguments:
7096
7097 IrpContext - Supplies the Irp Context.
7098 Irp - Supplies the Irp being processed.
7099
7100Return Value:
7101
7102 NTSTATUS - The return status for the operation.
7103
7104--*/
7105{
7107 PVCB Vcb = NULL;
7108 PFCB Fcb = NULL;
7109 PCCB Ccb = NULL;
7110 ULONG BufferLength = 0;
7111 PRETRIEVAL_POINTER_BASE RetrievalPointerBase = NULL;
7112
7113 PAGED_CODE();
7114
7116
7117 //
7118 // Force WAIT to true.
7119 //
7120
7121 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
7122
7123 //
7124 // Extract and decode the file object and check for type of open.
7125 //
7126
7128
7131 }
7132
7133 //
7134 // Extract the buffer
7135 //
7136
7137 RetrievalPointerBase = Irp->AssociatedIrp.SystemBuffer;
7138 BufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
7139
7140 //
7141 // Verify the handle has manage volume access.
7142 //
7143
7145
7148 }
7149
7150 //
7151 // Validate the output buffer is the right size.
7152 //
7153 // Note that the default size of BOOT_AREA_INFO has enough room for 2 boot sectors, so we're fine.
7154 //
7155
7156 if (BufferLength < sizeof(RETRIEVAL_POINTER_BASE)) {
7157
7160 }
7161
7162 //
7163 // Fill out the offset to the file area.
7164 //
7165
7166 RtlZeroMemory( RetrievalPointerBase, BufferLength );
7167
7168 try {
7169
7170 FatAcquireSharedVcb(IrpContext, Vcb);
7171 FatQuickVerifyVcb(IrpContext, Vcb);
7172
7173 RetrievalPointerBase->FileAreaOffset.QuadPart = Vcb->AllocationSupport.FileAreaLbo >> Vcb->AllocationSupport.LogOfBytesPerSector;
7174 Irp->IoStatus.Information = sizeof( RETRIEVAL_POINTER_BASE );
7175
7176 } finally {
7177
7178 FatReleaseVcb(IrpContext, Vcb);
7179
7180 }
7181
7182 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
7183
7184 return STATUS_SUCCESS;
7185
7186}
7187
7188
7189_Requires_lock_held_(_Global_critical_region_)
7191FatGetBootAreaInfo (
7192 _In_ PIRP_CONTEXT IrpContext,
7193 _In_ PIRP Irp
7194 )
7195/*++
7196
7197Routine Description:
7198
7199 This routine retrieves information about the boot areas of the filesystem.
7200
7201Arguments:
7202
7203 IrpContext - Supplies the Irp Context.
7204 Irp - Supplies the Irp being processed.
7205
7206Return Value:
7207
7208 NTSTATUS - The return status for the operation.
7209
7210--*/
7211{
7213 PVCB Vcb = NULL;
7214 PFCB Fcb = NULL;
7215 PCCB Ccb = NULL;
7216 ULONG BufferLength = 0;
7217 PBOOT_AREA_INFO BootAreaInfo = NULL;
7218
7219 PAGED_CODE();
7220
7222
7223 //
7224 // Force WAIT to true.
7225 //
7226
7227 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
7228
7229 //
7230 // Extract and decode the file object and check for type of open.
7231 //
7232
7234
7237 }
7238
7239 //
7240 // Extract the buffer
7241 //
7242
7243 BootAreaInfo = Irp->AssociatedIrp.SystemBuffer;
7244 BufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
7245
7246 //
7247 // Verify the handle has manage volume access.
7248 //
7249
7251
7254 }
7255
7256 //
7257 // Validate the output buffer is the right size.
7258 //
7259 // Note that the default size of BOOT_AREA_INFO has enough room for 2 boot sectors, so we're fine.
7260 //
7261
7262 if (BufferLength < sizeof(BOOT_AREA_INFO)) {
7263
7266 }
7267
7268 //
7269 // Fill out our boot areas.
7270 //
7271
7272 RtlZeroMemory( BootAreaInfo, BufferLength );
7273
7274 try {
7275
7276 FatAcquireSharedVcb(IrpContext, Vcb);
7277 FatQuickVerifyVcb(IrpContext, Vcb);
7278
7279 if (FatIsFat32( Vcb )) {
7280
7281 BootAreaInfo->BootSectorCount = 2;
7282 BootAreaInfo->BootSectors[0].Offset.QuadPart = 0;
7283 BootAreaInfo->BootSectors[1].Offset.QuadPart = 6;
7284 } else {
7285
7286 BootAreaInfo->BootSectorCount = 1;
7287 BootAreaInfo->BootSectors[0].Offset.QuadPart = 0;
7288 }
7289
7290 Irp->IoStatus.Information = sizeof( BOOT_AREA_INFO );
7291
7292 } finally {
7293
7294 FatReleaseVcb(IrpContext, Vcb);
7295 }
7296
7297 FatCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
7298 return STATUS_SUCCESS;
7299}
7300
7301#endif
7302
7303
7304_Requires_lock_held_(_Global_critical_region_)
7306FatMarkHandle (
7307 _In_ PIRP_CONTEXT IrpContext,
7308 _In_ PIRP Irp
7309 )
7310/*++
7311
7312Routine Description:
7313
7314 This routine is used to attach special properties to a user handle.
7315
7316Arguments:
7317
7318 IrpContext - Supplies the Irp Context.
7319 Irp - Supplies the Irp being processed.
7320
7321Return Value:
7322
7323 NTSTATUS - The return status for the operation.
7324
7325--*/
7326{
7329 PVCB Vcb = NULL;
7330 PFCB Fcb = NULL;
7331 PCCB Ccb = NULL;
7332 PFCB DasdFcb = NULL;
7333 PCCB DasdCcb = NULL;
7335 PMARK_HANDLE_INFO HandleInfo = NULL;
7336 PFILE_OBJECT DasdFileObject = NULL;
7337 BOOLEAN ReleaseFcb = FALSE;
7338
7339#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
7340 MARK_HANDLE_INFO LocalMarkHandleInfo = {0};
7341#endif
7342
7343 PAGED_CODE();
7344
7346
7347 //
7348 // Always make this a synchronous IRP.
7349 //
7350
7351 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
7352
7353 //
7354 // Extract and decode the file object and check for type of open.
7355 //
7356
7358
7359 //
7360 // We currently support this call for files and directories only.
7361 //
7362
7363 if ((TypeOfOpen != UserFileOpen) &&
7365
7368 }
7369
7370#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
7371
7372 //
7373 // Win32/64 thunking code
7374 //
7375
7376 if (IoIs32bitProcess( Irp )) {
7377
7378 PMARK_HANDLE_INFO32 MarkHandle32;
7379
7380 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof( MARK_HANDLE_INFO32 )) {
7381
7384 }
7385
7386 MarkHandle32 = (PMARK_HANDLE_INFO32) Irp->AssociatedIrp.SystemBuffer;
7387 LocalMarkHandleInfo.HandleInfo = MarkHandle32->HandleInfo;
7388 LocalMarkHandleInfo.UsnSourceInfo = MarkHandle32->UsnSourceInfo;
7389 LocalMarkHandleInfo.VolumeHandle = (HANDLE)(ULONG_PTR)(LONG) MarkHandle32->VolumeHandle;
7390
7391 HandleInfo = &LocalMarkHandleInfo;
7392
7393 } else {
7394
7395#endif
7396
7397 //
7398 // Get the input buffer pointer and check its length.
7399 //
7400
7401 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof( MARK_HANDLE_INFO )) {
7402
7405 }
7406
7407 HandleInfo = (PMARK_HANDLE_INFO) Irp->AssociatedIrp.SystemBuffer;
7408
7409#if defined(_WIN64) && defined(BUILD_WOW64_ENABLED)
7410 }
7411#endif
7412
7413 //
7414 // Check that only legal bits are being set.
7415 // We currently only support two bits: protect clusters and unprotect clusters.
7416 //
7417 // Note that we don't actually support the USN journal, but we must ignore the flags in order
7418 // to preserve compatibility.
7419 //
7420
7421 if (FlagOn( HandleInfo->HandleInfo,
7422 ~(MARK_HANDLE_PROTECT_CLUSTERS)) ||
7423 (FlagOn( HandleInfo->HandleInfo,
7424 0 ) &&
7426 FlagOn(HandleInfo->UsnSourceInfo,
7427 ~(USN_SOURCE_DATA_MANAGEMENT |
7428 USN_SOURCE_AUXILIARY_DATA |
7429 USN_SOURCE_REPLICATION_MANAGEMENT) ) ) {
7430
7433 }
7434
7435 //
7436 // Check that the user has a valid volume handle or the manage volume
7437 // privilege or is a kernel mode caller
7438 //
7439 // NOTE: the kernel mode check is only valid because the rdr doesn't support this
7440 // FSCTL.
7441 //
7442
7443 if ((Irp->RequestorMode != KernelMode) &&
7446 ( FlagOn( HandleInfo->HandleInfo, MARK_HANDLE_PROTECT_CLUSTERS ) || (HandleInfo->UsnSourceInfo != 0) )) {
7447
7448 if (HandleInfo->VolumeHandle == 0) {
7450 return STATUS_ACCESS_DENIED;
7451 }
7452
7453 Status = ObReferenceObjectByHandle( HandleInfo->VolumeHandle,
7454 0,
7456 UserMode,
7457#ifndef __REACTOS__
7458 &DasdFileObject,
7459#else
7460 (PVOID *)&DasdFileObject,
7461#endif
7462 NULL );
7463
7464 if (!NT_SUCCESS(Status)) {
7465
7466 FatCompleteRequest( IrpContext, Irp, Status );
7467 return Status;
7468 }
7469
7470 //
7471 // Check that this file object is opened on the same volume as the
7472 // handle used to call this routine.
7473 //
7474
7475 if (DasdFileObject->Vpb != Vcb->Vpb) {
7476
7477 ObDereferenceObject( DasdFileObject );
7478
7481 }
7482
7483 //
7484 // Now decode this FileObject and verify it is a volume handle.
7485 // We don't care to raise on dismounts here because
7486 // we check for that further down anyway. So send FALSE.
7487 //
7488
7489#ifdef _MSC_VER
7490#pragma prefast( suppress:28931, "convenient for debugging" )
7491#endif
7492 TypeOfOpen = FatDecodeFileObject( DasdFileObject, &Vcb, &DasdFcb, &DasdCcb ) ;
7493
7494 ObDereferenceObject( DasdFileObject );
7495
7496 if ((DasdCcb == NULL) || !FlagOn( DasdCcb->Flags, CCB_FLAG_MANAGE_VOLUME_ACCESS )) {
7497
7499 return STATUS_ACCESS_DENIED;
7500 }
7501
7502 }
7503
7504 _SEH2_TRY {
7505
7506 FatAcquireExclusiveFcb(IrpContext, Fcb);
7507 ReleaseFcb = TRUE;
7508
7509 FatVerifyFcb( IrpContext, Fcb );
7510
7511 if (HandleInfo->HandleInfo & MARK_HANDLE_PROTECT_CLUSTERS) {
7512
7514
7515 //
7516 // It's already set, bail out.
7517 //
7518
7520 }
7521
7524
7525 }
7526
7527 try_exit: NOTHING;
7528
7529 } _SEH2_FINALLY {
7530
7531 if (ReleaseFcb) {
7532
7533 FatReleaseFcb(IrpContext, Fcb);
7534 }
7535
7536 } _SEH2_END;
7537
7538 FatCompleteRequest( IrpContext, Irp, Status );
7539 return Status;
7540}
7541
7542
7543_Requires_lock_held_(_Global_critical_region_)
7544VOID
7545FatFlushAndCleanVolume(
7546 IN PIRP_CONTEXT IrpContext,
7547 IN PIRP Irp,
7548 IN PVCB Vcb,
7550 )
7551/*++
7552
7553Routine Description:
7554
7555 This routine flushes and otherwise preparse a volume to be eligible
7556 for deletion. The dismount and PNP paths share the need for this
7557 common work.
7558
7559 The Vcb will always be valid on return from this function. It is the
7560 caller's responsibility to attempt the dismount/deletion, and to setup
7561 allocation support again if the volume will be brought back from the
7562 brink.
7563
7564Arguments:
7565
7566 Irp - Irp for the overlying request
7567
7568 Vcb - the volume being operated on
7569
7570 FlushType - specifies the kind of flushing desired
7571
7572Return Value:
7573
7574 NTSTATUS - The return status for the operation.
7575
7576--*/
7577{
7578 PAGED_CODE();
7579
7580 //
7581 // The volume must be held exclusive.
7582 //
7583
7584 NT_ASSERT( FatVcbAcquiredExclusive( IrpContext, Vcb ));
7585
7586 //
7587 // There is no fail, flush everything. If invalidating, it is important
7588 // that we invalidate as we flush (eventually, w/ paging io held) so that we
7589 // error out the maximum number of late writes.
7590 //
7591
7592 if (FlushType != NoFlush) {
7593
7594 (VOID) FatFlushVolume( IrpContext, Vcb, FlushType );
7595 }
7596
7597 FatCloseEaFile( IrpContext, Vcb, FALSE );
7598
7599 //
7600 // Now, tell the device to flush its buffers.
7601 //
7602
7603 if (FlushType != NoFlush) {
7604
7605 (VOID)FatHijackIrpAndFlushDevice( IrpContext, Irp, Vcb->TargetDeviceObject );
7606 }
7607
7608 //
7609 // Now purge everything in sight. We're trying to provoke as many closes as
7610 // soon as possible, this volume may be on its way out.
7611 //
7612
7614
7615 CcPurgeCacheSection( &Vcb->SectionObjectPointers,
7616 NULL,
7617 0,
7618 FALSE );
7619
7620 (VOID) FatPurgeReferencedFileObjects( IrpContext, Vcb->RootDcb, NoFlush );
7621 }
7622
7623 //
7624 // If the volume was dirty and we were allowed to flush, do the processing that
7625 // the delayed callback would have done.
7626 //
7627
7628 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {
7629
7630 //
7631 // Cancel any pending clean volumes.
7632 //
7633
7634 (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
7635 (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );
7636
7637
7638 if (FlushType != NoFlush) {
7639
7640 //
7641 // The volume is now clean, note it.
7642 //
7643
7644 if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
7645
7646 FatMarkVolume( IrpContext, Vcb, VolumeClean );
7648 }
7649
7650 //
7651 // Unlock the volume if it is removable.
7652 //
7653
7654 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
7656
7657 FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
7658 }
7659 }
7660 }
7661
7662}
7663
7664#if (NTDDI_VERSION >= NTDDI_WIN8)
7665
7666
7667_Requires_lock_held_(_Global_critical_region_)
7669FatSetPurgeFailureMode (
7670 _In_ PIRP_CONTEXT IrpContext,
7671 _In_ PIRP Irp
7672 )
7673/*++
7674
7675 This routine is used to enable or disable the purge failure mode
7676 on a file. When in this mode the file system will propagate purge
7677 failures encountered during coherency purges. Normally these are
7678 ignored for application compatibilty purposes. Since the normal
7679 behavior can lead to cache incoherency there needs to be a way to
7680 force error propagation, particulary when a filter has mapped a
7681 section for the purposes of scanning the file in the background.
7682
7683 The purge failure mode is a reference count because it is set
7684 per mapped section and there may be multiple sections backed by
7685 the file.
7686
7687Arguments:
7688
7689 IrpContext - Supplies the Irp Context.
7690 Irp - Supplies the Irp being processed.
7691
7692Return Value:
7693
7694 NTSTATUS - The return status for the operation.
7695
7696--*/
7697{
7701 PVCB Vcb;
7702 PFCB Fcb;
7703 PCCB Ccb;
7704 PSET_PURGE_FAILURE_MODE_INPUT SetPurgeInput;
7705 BOOLEAN FcbAcquired = FALSE;
7706
7707 PAGED_CODE();
7708
7710
7711 //
7712 // Force WAIT to true.
7713 //
7714
7715 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
7716
7717 //
7718 // This has to be a kernel only call. Can't let a user request
7719 // change the purge failure mode count
7720 //
7721
7722 if (Irp->RequestorMode != KernelMode) {
7723
7726 }
7727
7728 //
7729 // Extract and decode the file object and check for type of open.
7730 //
7731
7733
7735
7738 }
7739
7740 if (TypeOfOpen != UserFileOpen) {
7741
7744 }
7745
7746 //
7747 // Get the input buffer pointer and check its length.
7748 //
7749
7750 if (IrpSp->Parameters.FileSystemControl.InputBufferLength < sizeof( SET_PURGE_FAILURE_MODE_INPUT )) {
7751
7754 }
7755
7756 SetPurgeInput = (PSET_PURGE_FAILURE_MODE_INPUT) Irp->AssociatedIrp.SystemBuffer;
7757
7758 if (!FlagOn( SetPurgeInput->Flags, SET_PURGE_FAILURE_MODE_ENABLED | SET_PURGE_FAILURE_MODE_DISABLED )) {
7759
7762 }
7763
7764 try {
7765
7766 //
7767 // Acquire the FCB exclusively to synchronize with coherency flush
7768 // and purge.
7769 //
7770
7771 FatAcquireExclusiveFcb( IrpContext, Fcb );
7772 FcbAcquired = TRUE;
7773
7774 FatVerifyFcb( IrpContext, Fcb );
7775
7776 if (FlagOn( SetPurgeInput->Flags, SET_PURGE_FAILURE_MODE_ENABLED )) {
7777
7779
7781 }
7782
7784
7785 } else {
7786
7787 ASSERT( FlagOn( SetPurgeInput->Flags, SET_PURGE_FAILURE_MODE_DISABLED ));
7788
7789 if (Fcb->PurgeFailureModeEnableCount == 0) {
7790
7792 }
7793
7795 }
7796
7797 try_exit: NOTHING;
7798
7799 } finally {
7800
7801 if (FcbAcquired) {
7802 FatReleaseFcb( IrpContext, Fcb );
7803 }
7804 }
7805
7806 //
7807 // Complete the irp if we terminated normally.
7808 //
7809
7810 FatCompleteRequest( IrpContext, Irp, Status );
7811
7812 return Status;
7813}
7814
7815#endif
7816
7817
7820 IN PIRP_CONTEXT IrpContext,
7821 IN PVPB Vpb,
7822 IN PVOID Buffer,
7823 IN ULONG Size,
7824 OUT PBOOLEAN LabelFound
7825 )
7826/*++
7827
7828Routine Description:
7829
7830 Search a buffer (taken from the root directory) for a volume label
7831 matching the label in the
7832
7833Arguments:
7834
7835 IrpContext - Supplies our irp context
7836 Vpb - Vpb supplying the volume label
7837 Buffer - Supplies the buffer we'll search
7838 Size - The size of the buffer in bytes.
7839 LabelFound - Returns whether a label was found.
7840
7841Return Value:
7842
7843 There are four interesting cases:
7844
7845 1) Some random error occurred - that error returned as status, LabelFound
7846 is indeterminate.
7847
7848 2) No label was found - STATUS_SUCCESS returned, LabelFound is FALSE.
7849
7850 3) A matching label was found - STATUS_SUCCESS returned, LabelFound is TRUE.
7851
7852 4) A non-matching label found - STATUS_WRONG_VOLUME returned, LabelFound
7853 is indeterminate.
7854
7855--*/
7856
7857{
7859 WCHAR UnicodeBuffer[11];
7860
7862 PDIRENT TerminationDirent;
7863 ULONG VolumeLabelLength;
7864 UCHAR OemBuffer[11];
7867
7868 PAGED_CODE();
7869
7870 UNREFERENCED_PARAMETER( IrpContext );
7871
7872 Dirent = Buffer;
7873
7874 TerminationDirent = Dirent + Size / sizeof(DIRENT);
7875
7876 while ( Dirent < TerminationDirent ) {
7877
7878 if ( Dirent->FileName[0] == FAT_DIRENT_NEVER_USED ) {
7879
7880 Dirent = TerminationDirent;
7881 break;
7882 }
7883
7884 //
7885 // If the entry is the non-deleted volume label break from the loop.
7886 //
7887 // Note that all out parameters are already correctly set.
7888 //
7889
7890 if (((Dirent->Attributes & ~FAT_DIRENT_ATTR_ARCHIVE) ==
7892 (Dirent->FileName[0] != FAT_DIRENT_DELETED)) {
7893
7894 break;
7895 }
7896
7897 Dirent += 1;
7898 }
7899
7900 if (Dirent >= TerminationDirent) {
7901
7902 //
7903 // We've run out of buffer.
7904 //
7905
7906 *LabelFound = FALSE;
7907 return STATUS_SUCCESS;
7908 }
7909
7910
7911 OemString.Buffer = (PCHAR)&OemBuffer[0];
7912 OemString.MaximumLength = 11;
7913
7914 RtlCopyMemory( OemString.Buffer, Dirent->FileName, 11 );
7915
7916 //
7917 // Translate the first character from 0x5 to 0xe5.
7918 //
7919
7920 if (OemString.Buffer[0] == FAT_DIRENT_REALLY_0E5) {
7921
7922 OemString.Buffer[0] = 0xe5;
7923 }
7924
7925 //
7926 // Compute the length of the volume name
7927 //
7928
7929 for ( OemString.Length = 11;
7930 OemString.Length > 0;
7931 OemString.Length -= 1) {
7932
7933 if ( (OemString.Buffer[OemString.Length-1] != 0x00) &&
7934 (OemString.Buffer[OemString.Length-1] != 0x20) ) { break; }
7935 }
7936
7937 UnicodeString.MaximumLength = sizeof( UnicodeBuffer );
7938 UnicodeString.Buffer = &UnicodeBuffer[0];
7939
7941 &OemString,
7942 FALSE );
7943
7944 if ( !NT_SUCCESS( Status ) ) {
7945
7946 return Status;
7947 }
7948
7949 VolumeLabelLength = UnicodeString.Length;
7950
7951 if ( (VolumeLabelLength != (ULONG)Vpb->VolumeLabelLength) ||
7952 (!RtlEqualMemory(&UnicodeBuffer[0],
7953 &Vpb->VolumeLabel[0],
7954 VolumeLabelLength)) ) {
7955
7956 return STATUS_WRONG_VOLUME;
7957 }
7958
7959 //
7960 // We found a matching label.
7961 //
7962
7963 *LabelFound = TRUE;
7964 return STATUS_SUCCESS;
7965}
7966
7967
7968VOID
7970 IN PIRP_CONTEXT IrpContext,
7971 IN PVCB Vcb,
7974 )
7975{
7976 ULONG PageEntryOffset;
7977 ULONG OffsetIntoVolumeFile;
7978 PVOID Buffer;
7979
7980 PAGED_CODE();
7981
7982 NT_ASSERT(Vcb->AllocationSupport.FatIndexBitSize == 32);
7983
7984 FatVerifyIndexIsValid( IrpContext, Vcb, FatIndex);
7985
7986 Buffer = FsRtlAllocatePoolWithTag( NonPagedPoolNxCacheAligned,
7987 PAGE_SIZE,
7989
7990 OffsetIntoVolumeFile = FatReservedBytes(&Vcb->Bpb) + FatIndex * sizeof(ULONG);
7991 PageEntryOffset = (OffsetIntoVolumeFile % PAGE_SIZE) / sizeof(ULONG);
7992
7993 _SEH2_TRY {
7994
7995 FatPerformVerifyDiskRead( IrpContext,
7996 Vcb,
7997 Buffer,
7998 OffsetIntoVolumeFile & ~(PAGE_SIZE - 1),
7999 PAGE_SIZE,
8000 TRUE );
8001
8002 *FatEntry = ((PULONG)(Buffer))[PageEntryOffset];
8003
8004 } _SEH2_FINALLY {
8005
8006 ExFreePool( Buffer );
8007 } _SEH2_END;
8008}
8009
8010//
8011// Local support routine
8012//
8013
8014_Requires_lock_held_(_Global_critical_region_)
8015VOID
8016FatScanForDismountedVcb (
8017 IN PIRP_CONTEXT IrpContext
8018 )
8019
8020/*++
8021
8022Routine Description:
8023
8024 This routine walks through the list of Vcb's looking for any which may
8025 now be deleted. They may have been left on the list because there were
8026 outstanding references.
8027
8028Arguments:
8029
8030Return Value:
8031
8032 None
8033
8034--*/
8035
8036{
8037 PVCB Vcb;
8038 PLIST_ENTRY Links;
8039 BOOLEAN VcbDeleted;
8040
8041
8042 PAGED_CODE();
8043
8044 //
8045 // Walk through all of the Vcb's attached to the global data.
8046 //
8047
8048 NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
8049
8050#ifdef _MSC_VER
8051#pragma prefast( push )
8052#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
8053#pragma prefast( disable: 28193, "this will always wait" )
8054#endif
8055
8056 FatAcquireExclusiveGlobal( IrpContext );
8057
8058#ifdef _MSC_VER
8059#pragma prefast( pop )
8060#endif
8061
8062 Links = FatData.VcbQueue.Flink;
8063
8064 while (Links != &FatData.VcbQueue) {
8065
8066 Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks );
8067
8068 //
8069 // Move to the next link now since the current Vcb may be deleted.
8070 //
8071
8072 Links = Links->Flink;
8073
8074 //
8075 // Try to acquire the VCB for exclusive access. If we cannot, just skip
8076 // it for now.
8077 //
8078
8079#ifdef _MSC_VER
8080#pragma prefast( push )
8081#pragma prefast( disable:28103,"prefast cannot work out that Vcb->Resource will be released below." )
8082#pragma prefast( disable:28109,"prefast cannot work out the Vcb is not already held" );
8083#endif
8084
8085 if (!ExAcquireResourceExclusiveLite( &(Vcb->Resource), FALSE )) {
8086
8087 continue;
8088 }
8089
8090#ifdef _MSC_VER
8091#pragma prefast( pop )
8092#endif
8093 //
8094 // Check if this Vcb can go away.
8095 //
8096
8097 VcbDeleted = FatCheckForDismount( IrpContext,
8098 Vcb,
8099 FALSE );
8100
8101 //
8102 // If the VCB was not deleted, release it.
8103 //
8104
8105 if (!VcbDeleted) {
8106
8107 ExReleaseResourceLite( &(Vcb->Resource) );
8108 }
8109 }
8110
8111 FatReleaseGlobal( IrpContext);
8112
8113 return;
8114}
8115
8116#if (NTDDI_VERSION >= NTDDI_WIN7)
8118//
8119// FatSetZeroOnDeallocate is used when we need to stomp over the contents with zeros when a file is deleted.
8120//
8121
8124 __in PIRP_CONTEXT IrpContext,
8125 __in PIRP Irp
8126 )
8127{
8129
8130 PVCB Vcb;
8131 PFCB FcbOrDcb;
8132 PCCB Ccb;
8133
8135
8137
8138 BOOLEAN ReleaseFcb = FALSE;
8139
8140 PAGED_CODE();
8141
8142 //
8143 // This call should always be synchronous.
8144 //
8145
8146 SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
8147
8149
8150 if ((TypeOfOpen != UserFileOpen) ||
8151 (!IrpSp->FileObject->WriteAccess) ) {
8152
8154 return STATUS_ACCESS_DENIED;
8155 }
8156
8157 //
8158 // Readonly mount should be just that: read only.
8159 //
8160
8161 if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED)) {
8162
8165 }
8166
8167 //
8168 // Acquire main then paging to exclude everyone from this FCB.
8169 //
8170
8171 FatAcquireExclusiveFcb(IrpContext, FcbOrDcb);
8172 ReleaseFcb = TRUE;
8173
8174 _SEH2_TRY {
8175
8177
8178 } _SEH2_FINALLY {
8179
8180 if (ReleaseFcb) {
8181 FatReleaseFcb(IrpContext, FcbOrDcb);
8182 }
8183
8184 } _SEH2_END;
8185
8186 FatCompleteRequest( IrpContext, Irp, Status );
8187 return Status;
8188}
8189#endif
8190
#define PAGED_CODE()
DWORD Id
static CC_FILE_SIZES FileSizes
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
unsigned int UINT32
#define VOID
Definition: acefi.h:82
LONG NTSTATUS
Definition: precomp.h:26
WCHAR RootDirectory[MAX_PATH]
Definition: format.c:74
DWORD ClusterSize
Definition: format.c:67
#define LongToHandle(h)
Definition: basetsd.h:82
unsigned int * PUINT32
Definition: basetsd.h:125
#define PARTITION_OS2BOOTMGR
Definition: disk.h:94
#define CC_ENABLE_DISK_IO_ACCOUNTING
Definition: btrfs_drv.h:1845
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
#define CanFsdWait(I)
Definition: cdprocs.h:2001
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
#define CopyUchar4(Dst, Src)
Definition: cdprocs.h:1701
@ UserDirectoryOpen
Definition: cdprocs.h:576
@ UserFileOpen
Definition: cdprocs.h:577
@ UserVolumeOpen
Definition: cdprocs.h:575
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_leave(S)
Definition: cdprocs.h:2180
enum _TYPE_OF_OPEN TYPE_OF_OPEN
#define try_return(S)
Definition: cdprocs.h:2179
#define IOCTL_DISK_CHECK_VERIFY
Definition: cdrw_usr.h:175
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
#define IOCTL_DISK_IS_WRITABLE
Definition: cdrw_usr.h:172
#define CCB_FLAG_ALLOW_EXTENDED_DASD_IO
Definition: cdstruc.h:1108
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:714
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:769
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS
Definition: cdstruc.h:1222
@ VcbNotMounted
Definition: cdstruc.h:490
@ FcbBad
Definition: cdstruc.h:780
@ FcbNeedsToBeVerified
Definition: cdstruc.h:781
Definition: bufpool.h:45
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define __in
Definition: dbghelp.h:35
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
BOOLEAN NTAPI KeRemoveQueueDpc(IN PKDPC Dpc)
Definition: dpc.c:878
#define NodeType(P)
Definition: nodetype.h:51
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
return Iosb
Definition: create.c:4402
LONGLONG LBO
Definition: fat.h:34
#define FatGetIndexFromLbo(VCB, LBO)
Definition: fat.h:566
LBO * PLBO
Definition: fat.h:36
#define FAT_DIRENT_ATTR_ARCHIVE
Definition: fat.h:373
#define FatUnpackBios(Bios, Pbios)
Definition: fat.h:136
#define FatRootDirectoryLbo(B)
Definition: fat.h:445
VBO * PVBO
Definition: fat.h:39
#define FAT_DIRENT_ATTR_VOLUME_ID
Definition: fat.h:371
#define FatVerifyIndexIsValid(IC, V, I)
Definition: fat.h:532
#define FatReservedBytes(B)
Definition: fat.h:414
#define FAT_DIRENT_REALLY_0E5
Definition: fat.h:335
#define IsBpbFat32(bpb)
Definition: fat.h:101
ULONG32 VBO
Definition: fat.h:38
#define FAT_CLUSTER_LAST
Definition: fat.h:258
#define FAT_DIRENT_DELETED
Definition: fat.h:337
#define FatBytesPerCluster(B)
Definition: fat.h:408
#define FAT_DIRENT_NEVER_USED
Definition: fat.h:334
#define FatGetLboFromIndex(VCB, FAT_INDEX)
Definition: fat.h:559
#define FatRootDirectorySize(B)
Definition: fat.h:427
#define TAG_OUTPUT_MAPPINGPAIRS
Definition: nodetype.h:179
#define TAG_DEFRAG_BUFFER
Definition: nodetype.h:188
#define FAT_NTC_ROOT_DCB
Definition: nodetype.h:31
#define FAT_NTC_FCB
Definition: nodetype.h:29
#define FAT_NTC_DCB
Definition: nodetype.h:30
#define TAG_STASHED_BPB
Definition: nodetype.h:170
#define TAG_VERIFY_BOOTSECTOR
Definition: nodetype.h:176
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define TAG_VERIFY_ROOTDIR
Definition: nodetype.h:177
#define TAG_ENTRY_LOOKUP_BUFFER
Definition: nodetype.h:181
#define ULONG_PTR
Definition: config.h:101
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
struct _DEVICE_OBJECT * PDEVICE_OBJECT
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define DO_SYSTEM_BOOT_PARTITION
Definition: env_spec_w32.h:400
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define KeInitializeSpinLock(sl)
Definition: env_spec_w32.h:604
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1088
#define FSCTL_GET_RETRIEVAL_POINTER_BASE
Definition: ext2fs.h:1132
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID FatExamineFatEntries(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG StartIndex OPTIONAL, IN ULONG EndIndex OPTIONAL, IN BOOLEAN SetupWindows, IN PFAT_WINDOW SwitchToWindow OPTIONAL, IN PULONG BitMapBuffer OPTIONAL)
Definition: allocsup.c:4720
CLUSTER_TYPE FatInterpretClusterType(IN PVCB Vcb, IN FAT_ENTRY Entry)
Definition: allocsup.c:3473
VOID FatTearDownAllocationSupport(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: allocsup.c:549
VOID FatSetupAllocationSupport(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: allocsup.c:359
VOID FatCloseEaFile(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN FlushFirst)
Definition: cachesup.c:1079
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
VOID FatInitializeCacheMap(_In_ PFILE_OBJECT FileObject, _In_ PCC_FILE_SIZES FileSizes, _In_ BOOLEAN PinAccess, _In_ PCACHE_MANAGER_CALLBACKS Callbacks, _In_ PVOID LazyWriteContext)
Definition: cachesup.c:62
VOID FatReadVolumeFile(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN VBO StartingVbo, IN ULONG ByteCount, OUT PBCB *Bcb, OUT PVOID *Buffer)
Definition: cachesup.c:102
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
NTSTATUS FatPerformDevIoCtrl(IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
Definition: deviosup.c:3621
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3357
NTSTATUS FatIsPathnameValid(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:4168
NTSTATUS FatAllowExtendedDasdIo(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:7022
NTSTATUS FatGetStatistics(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:4892
NTSTATUS FatQueryBpb(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:4213
NTSTATUS FatUnlockVolumeInternal(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject OPTIONAL)
Definition: fsctrl.c:3601
VOID FatVerifyLookupFatEntry(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG FatIndex, IN OUT PULONG FatEntry)
Definition: fsctrl.c:7969
NTSTATUS FatUnlockVolume(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:3354
VOID FatComputeMoveFileSplicePoints(IN PIRP_CONTEXT IrpContext, IN PFCB FcbOrDcb, IN ULONG FileOffset, IN ULONG TargetCluster, IN ULONG BytesToReallocate, OUT PULONG FirstSpliceSourceCluster, OUT PULONG FirstSpliceTargetCluster, OUT PULONG SecondSpliceSourceCluster, OUT PULONG SecondSpliceTargetCluster, IN OUT PLARGE_MCB SourceMcb)
Definition: fsctrl.c:6822
BOOLEAN FatLookupMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount OPTIONAL, OUT PULONG Index OPTIONAL)
Definition: fsctrl.c:418
BOOLEAN FatPerformVerifyDiskRead(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PVOID Buffer, IN LBO Lbo, IN ULONG NumberOfBytesToRead, IN BOOLEAN ReturnOnError)
Definition: fsctrl.c:4569
NTSTATUS FatIsVolumeMounted(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:4096
#define MCB_SCALE
NTSTATUS FatSetZeroOnDeallocate(__in PIRP_CONTEXT IrpContext, __in PIRP Irp)
Definition: fsctrl.c:8123
BOOLEAN FatGetNextMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PVBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount)
Definition: fsctrl.c:541
#define MCB_SCALE_MODULO
VOID FatRemoveMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, IN ULONG SectorCount)
Definition: fsctrl.c:599
#define MCB_SCALE_LOG2
BOOLEAN FatAddMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, IN LBO Lbo, IN ULONG SectorCount)
Definition: fsctrl.c:364
NTSTATUS FatIsVolumeDirty(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: fsctrl.c:3965
BOOLEAN FatLookupLastMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, OUT PVBO Vbo, OUT PLBO Lbo, OUT PULONG Index)
Definition: fsctrl.c:494
BOOLEAN FatIsBootSectorFat(IN PPACKED_BOOT_SECTOR BootSector)
Definition: fsctrl.c:2522
#define Dbg
Definition: fsctrl.c:30
NTSTATUS FatSearchBufferForLabel(IN PIRP_CONTEXT IrpContext, IN PVPB Vpb, IN PVOID Buffer, IN ULONG Size, OUT PBOOLEAN LabelFound)
Definition: fsctrl.c:7819
BOOLEAN FatIsMediaWriteProtected(IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: fsctrl.c:2678
LOGICAL FatDiskAccountingEnabled
Definition: fatdata.c:129
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
LARGE_INTEGER FatMaxLarge
Definition: fatdata.c:63
BOOLEAN FatIsIrpTopLevel(IN PIRP Irp)
Definition: fatdata.c:817
LARGE_INTEGER FatLargeZero
Definition: fatdata.c:62
FAT_DATA FatData
Definition: fatdata.c:56
#define FatNull
Definition: fatdata.h:321
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define DebugUnwind(X)
Definition: fatdata.h:315
#define FAT_DEFAULT_DEFRAG_CHUNK_IN_BYTES
Definition: fatdata.h:116
#define DIRENT
Definition: fatfs.h:187
VOID FatQuickVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:1662
@ VolumeClean
Definition: fatprocs.h:1954
@ VolumeDirty
Definition: fatprocs.h:1955
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1495
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1674
#define FatAcquireExclusiveGlobal(IRPCONTEXT)
Definition: fatprocs.h:1387
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define FatAcquireExclusiveVolume(IRPCONTEXT, VCB)
Definition: fatprocs.h:1409
TYPE_OF_OPEN FatDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Outptr_ PVCB *Vcb, _Outptr_ PFCB *FcbOrDcb, _Outptr_ PCCB *Ccb)
Definition: filobsup.c:176
IN PFCB IN PCCB IN TYPE_OF_OPEN IN BOOLEAN IN BOOLEAN TopLevel
Definition: fatprocs.h:2417
#define FatReleaseVolume(IRPCONTEXT, VCB)
Definition: fatprocs.h:1418
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
IN PFCB IN VBO OUT PLBO Lbo
Definition: fatprocs.h:308
VOID FatFlushFatEntries(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN ULONG Cluster, IN ULONG Count)
Definition: flush.c:1191
#define FatReleaseFcb(IRPCONTEXT, Fcb)
Definition: fatprocs.h:1644
#define FatReleaseGlobal(IRPCONTEXT)
Definition: fatprocs.h:1636
NTSTATUS FatFlushFat(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: flush.c:801
PFCB FatCreateFcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PDCB ParentDcb, IN ULONG LfnOffsetWithinDirectory, IN ULONG DirentOffsetWithinDirectory, IN PDIRENT Dirent, IN PUNICODE_STRING Lfn OPTIONAL, IN PUNICODE_STRING OrigLfn OPTIONAL, IN BOOLEAN IsPagingFile, IN BOOLEAN SingleResource)
Definition: strucsup.c:1252
#define FatSetVcbCondition(V, X)
Definition: fatprocs.h:1438
#define FatDeviceIsFatFsdo(D)
Definition: fatprocs.h:3095
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB IN PDEVICE_OBJECT FsDeviceObject
Definition: fatprocs.h:1677
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
IN PFCB IN FAT_FLUSH_TYPE FlushType
Definition: fatprocs.h:1082
VOID FatCheckDirtyBit(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:1185
enum _FAT_FLUSH_TYPE FAT_FLUSH_TYPE
IN PFCB FcbOrDcb
Definition: fatprocs.h:306
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1675
VOID FatFlushDirentForFile(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: flush.c:1264
BOOLEAN FatIsHandleCountZero(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: strucsup.c:3614
#define FatIsFastIoPossible(FCB)
Definition: fatprocs.h:2813
IN PFCB IN VBO Vbo
Definition: fatprocs.h:307
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2995
VOID FatVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:270
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2977
@ FlushWithoutPurge
Definition: fatprocs.h:1056
@ Flush
Definition: fatprocs.h:1054
@ FlushAndInvalidate
Definition: fatprocs.h:1055
@ NoFlush
Definition: fatprocs.h:1053
IN PVCB IN ULONG FatIndex
Definition: fatprocs.h:383
#define FatGetFcbOplock(F)
Definition: fatprocs.h:1656
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:731
IN PFCB IN PFILE_OBJECT FileObject IN ULONG AllocationSize
Definition: fatprocs.h:322
IN PVCB IN ULONG IN FAT_ENTRY FatEntry
Definition: fatprocs.h:385
IN PVCB IN FAT_VOLUME_STATE VolumeState
Definition: fatprocs.h:1998
BOOLEAN FatScanForDataTrack(IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: strucsup.c:3828
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
NTSTATUS FatHijackIrpAndFlushDevice(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN PDEVICE_OBJECT TargetDeviceObject)
Definition: flush.c:1101
IN PVCB IN ULONG IN OUT PULONG IN BOOLEAN OUT PLARGE_MCB Mcb
Definition: fatprocs.h:348
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
VOID FatMarkFcbCondition(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN FCB_CONDITION FcbCondition, IN BOOLEAN Recursive)
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define VCB_STATE_FLAG_VOLUME_DIRTY
Definition: fatstruc.h:561
#define VCB_STATE_FLAG_LOCKED
Definition: fatstruc.h:559
#define CCB_FLAG_MANAGE_VOLUME_ACCESS
Definition: fatstruc.h:1338
#define IRP_CONTEXT_FLAG_PARENT_BY_CHILD
Definition: fatstruc.h:1582
#define VCB_STATE_FLAG_REMOVABLE_MEDIA
Definition: fatstruc.h:560
#define VCB_STATE_FLAG_BOOT_OR_PAGING_FILE
Definition: fatstruc.h:567
#define VCB_STATE_FLAG_BAD_BLOCKS_POPULATED
Definition: fatstruc.h:576
#define FCB_STATE_DENY_DEFRAG
Definition: fatstruc.h:1217
#define FCB_STATE_ZERO_ON_DEALLOCATION
Definition: fatstruc.h:1224
#define VCB_STATE_FLAG_MOUNTED_DIRTY
Definition: fatstruc.h:562
#define VCB_STATE_FLAG_MOUNT_IN_PROGRESS
Definition: fatstruc.h:578
@ FatClusterBad
Definition: fatstruc.h:1749
@ FatClusterReserved
Definition: fatstruc.h:1748
@ FatClusterAvailable
Definition: fatstruc.h:1747
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:570
#define FCB_STATE_DELETE_ON_CLOSE
Definition: fatstruc.h:1193
#define FCB_STATE_SYSTEM_FILE
Definition: fatstruc.h:1199
#define FCB_LOOKUP_ALLOCATIONSIZE_HINT
Definition: fatstruc.h:1241
#define VCB_STATE_FLAG_VPB_MUST_BE_FREED
Definition: fatstruc.h:574
#define VCB_STATE_FLAG_VOLUME_DISMOUNTED
Definition: fatstruc.h:572
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
@ VcbBad
Definition: fatstruc.h:225
@ VcbGood
Definition: fatstruc.h:223
#define CCB_FLAG_DENY_DEFRAG
Definition: fatstruc.h:1352
struct _FILE_SYSTEM_STATISTICS FILE_SYSTEM_STATISTICS
#define IRP_CONTEXT_FLAG_DISABLE_WRITE_THROUGH
Definition: fatstruc.h:1565
#define CCB_FLAG_COMPLETE_DISMOUNT
Definition: fatstruc.h:1331
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG FsControlCode
Definition: fltkernel.h:1370
#define FsRtlEnterFileSystem
_Must_inspect_result_ _In_ ULONG RunIndex
Definition: fsrtlfuncs.h:538
#define FsRtlExitFileSystem
#define FsRtlAreThereCurrentFileLocks(FL)
Definition: fsrtlfuncs.h:1584
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
ULONG Handle
Definition: gdb_input.c:15
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define NOTHING
Definition: input_list.c:10
POBJECT_TYPE IoFileObjectType
Definition: iomgr.c:36
#define NTDDI_VERSION
Definition: k32.h:33
#define RtlEqualMemory(a, b, c)
Definition: kdvm.h:18
VOID NTAPI FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG SectorCount)
Definition: largemcb.c:905
BOOLEAN NTAPI FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG Lbn, IN LONGLONG SectorCount)
Definition: largemcb.c:288
BOOLEAN NTAPI FsRtlLookupLastLargeMcbEntryAndIndex(IN PLARGE_MCB OpaqueMcb, OUT PLONGLONG LargeVbn, OUT PLONGLONG LargeLbn, OUT PULONG Index)
Definition: largemcb.c:671
VOID NTAPI FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:1096
VOID NTAPI FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, IN POOL_TYPE PoolType)
Definition: largemcb.c:451
BOOLEAN NTAPI FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, OUT PLONGLONG Lbn OPTIONAL, OUT PLONGLONG SectorCountFromLbn OPTIONAL, OUT PLONGLONG StartingLbn OPTIONAL, OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, OUT PULONG Index OPTIONAL)
Definition: largemcb.c:560
ULONG NTAPI FsRtlNumberOfRunsInLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:765
BOOLEAN NTAPI FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount)
Definition: largemcb.c:392
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity(VOID)
Definition: lazyrite.c:30
if(dx< 0)
Definition: linetemp.h:194
BOOLEAN NTAPI CcIsThereDirtyData(IN PVPB Vpb)
Definition: logsup.c:55
#define PCHAR
Definition: match.c:90
#define ASSERT(a)
Definition: mode.c:44
@ LowPagePriority
Definition: imports.h:55
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define SE_TCB_PRIVILEGE
Definition: security.c:661
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Inout_
Definition: ms_sal.h:378
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3168
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define FSCTL_QUERY_RETRIEVAL_POINTERS
Definition: nt_native.h:840
#define METHOD_NEITHER
Definition: nt_native.h:597
#define FSCTL_OPLOCK_BREAK_NOTIFY
Definition: nt_native.h:831
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_OPLOCK_BREAK_ACKNOWLEDGE
Definition: nt_native.h:829
#define FSCTL_REQUEST_OPLOCK_LEVEL_1
Definition: nt_native.h:826
#define FSCTL_REQUEST_FILTER_OPLOCK
Definition: nt_native.h:849
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
#define FSCTL_INVALIDATE_VOLUMES
Definition: nt_native.h:847
#define FSCTL_IS_PATHNAME_VALID
Definition: nt_native.h:837
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
#define FSCTL_REQUEST_BATCH_OPLOCK
Definition: nt_native.h:828
#define FSCTL_QUERY_FAT_BPB
Definition: nt_native.h:848
#define FSCTL_FILESYSTEM_GET_STATISTICS
Definition: nt_native.h:850
#define FSCTL_OPBATCH_ACK_CLOSE_PENDING
Definition: nt_native.h:830
#define FSCTL_OPLOCK_BREAK_ACK_NO_2
Definition: nt_native.h:846
#define FSCTL_IS_VOLUME_MOUNTED
Definition: nt_native.h:836
#define FSCTL_REQUEST_OPLOCK_LEVEL_2
Definition: nt_native.h:827
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382
#define ARGUMENT_PRESENT(ArgumentPointer)
@ NotificationEvent
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
#define FSRTL_VOLUME_LOCK
Definition: ntifs_ex.h:441
#define FSRTL_VOLUME_DISMOUNT_FAILED
Definition: ntifs_ex.h:440
#define FSRTL_VOLUME_DISMOUNT
Definition: ntifs_ex.h:439
#define VOLUME_IS_DIRTY
Definition: ntifs_ex.h:330
#define FSRTL_VOLUME_MOUNT
Definition: ntifs_ex.h:444
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
#define FSRTL_VOLUME_LOCK_FAILED
Definition: ntifs_ex.h:442
BOOLEAN NTAPI CcCanIWrite(IN PFILE_OBJECT FileObject, IN ULONG BytesToWrite, IN BOOLEAN Wait, IN UCHAR Retrying)
Definition: copysup.c:214
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
BOOLEAN NTAPI ExIsResourceAcquiredExclusiveLite(IN PERESOURCE Resource)
Definition: resource.c:1624
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
NTSTATUS NTAPI FsRtlNotifyVolumeEvent(IN PFILE_OBJECT FileObject, IN ULONG EventCode)
Definition: pnp.c:38
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
BOOLEAN NTAPI SeSinglePrivilegeCheck(_In_ LUID PrivilegeValue, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a single privilege is present in the context of the calling thread.
Definition: priv.c:744
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NOT_LOCKED
Definition: ntstatus.h:279
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:494
NTSTATUS NTAPI FsRtlOplockFsctrl(IN POPLOCK Oplock, IN PIRP Irp, IN ULONG OpenCount)
Definition: oplock.c:1430
ULONG SectorCount
Definition: part_xbox.c:31
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define Vcb
Definition: cdprocs.h:1415
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:114
struct VOLUME_BITMAP_BUFFER * PVOLUME_BITMAP_BUFFER
#define FSCTL_IS_VOLUME_DIRTY
Definition: winioctl.h:714
struct RETRIEVAL_POINTERS_BUFFER * PRETRIEVAL_POINTERS_BUFFER
struct STARTING_VCN_INPUT_BUFFER * PSTARTING_VCN_INPUT_BUFFER
#define FSCTL_GET_RETRIEVAL_POINTERS
Definition: winioctl.h:95
struct STARTING_LCN_INPUT_BUFFER * PSTARTING_LCN_INPUT_BUFFER
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
#define FSCTL_GET_VOLUME_BITMAP
Definition: winioctl.h:94
struct MOVE_FILE_DATA * PMOVE_FILE_DATA
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
#define FSCTL_MOVE_FILE
Definition: winioctl.h:96
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define FSCTL_MARK_HANDLE
Definition: winioctl.h:154
#define FSCTL_SET_ZERO_ON_DEALLOCATION
Definition: winioctl.h:180
#define FSCTL_ALLOW_EXTENDED_DASD_IO
Definition: winioctl.h:124
ULONG SerialNumber
Definition: rxce.c:117
NTSTATUS NTAPI RtlOemStringToCountedUnicodeString(IN OUT PUNICODE_STRING UniDest, IN PCOEM_STRING OemSource, IN BOOLEAN AllocateDestinationString)
Definition: unicode.c:1473
#define NTDDI_WIN8
Definition: sdkddkver.h:113
#define NTDDI_WIN7
Definition: sdkddkver.h:112
#define STATUS_END_OF_FILE
Definition: shellext.h:67
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
USHORT ReservedSectors
Definition: fat.h:106
USHORT BytesPerSector
Definition: fat.h:104
USHORT FsVersion
Definition: fat.h:126
USHORT Sectors
Definition: fat.h:109
ULONG MirrorDisabled
Definition: fat.h:122
ULONG32 LargeSectors
Definition: fat.h:115
ULONG32 LargeSectorsPerFat
Definition: fat.h:116
ULONG32 RootDirFirstCluster
Definition: fat.h:127
USHORT RootEntries
Definition: fat.h:108
UCHAR SectorsPerCluster
Definition: fat.h:105
USHORT SectorsPerFat
Definition: fat.h:111
Definition: fsck.fat.h:192
LARGE_INTEGER StartingLcn
Definition: winioctl.h:591
LARGE_INTEGER StartingVcn
Definition: winioctl.h:590
HANDLE FileHandle
Definition: winioctl.h:589
DWORD ClusterCount
Definition: winioctl.h:592
Definition: cdstruc.h:1067
ULONG Flags
Definition: cdstruc.h:1080
LARGE_INTEGER FileSize
Definition: cctypes.h:16
LARGE_INTEGER ValidDataLength
Definition: cctypes.h:17
LARGE_INTEGER AllocationSize
Definition: cctypes.h:15
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
PCHAR FileName
Definition: cdstruc.h:1648
ULONG BytesPerSector
Definition: ntdddisk.h:409
ULONG NumberProcessors
Definition: fatstruc.h:81
CACHE_MANAGER_CALLBACKS CacheManagerNoOpCallbacks
Definition: fatstruc.h:160
PDRIVER_OBJECT DriverObject
Definition: fatstruc.h:55
BOOLEAN FujitsuFMR
Definition: fatstruc.h:95
LIST_ENTRY VcbQueue
Definition: fatstruc.h:49
ERESOURCE Resource
Definition: fatstruc.h:68
Definition: cdstruc.h:902
union _FCB::@719 Specific
ULONG Flags
Definition: ntfs.h:536
PVCB Vcb
Definition: cdstruc.h:933
CD_MCB Mcb
Definition: cdstruc.h:1016
struct _FCB::@719::@722 Fcb
CLONG UncleanCount
Definition: fatstruc.h:873
ULONG FirstClusterOfFile
Definition: fatstruc.h:818
FSRTL_ADVANCED_FCB_HEADER Header
Definition: cdstruc.h:925
ULONG FcbState
Definition: cdstruc.h:971
struct _FCB::@719::@721 Dcb
PKEVENT MoveFileEvent
Definition: fatstruc.h:1175
CLONG PurgeFailureModeEnableCount
Definition: fatstruc.h:896
UCHAR First0x24BytesOfBootSector[0x24]
Definition: iotypes.h:6234
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PARTITION_STYLE PartitionStyle
Definition: imports.h:220
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
Definition: cdstruc.h:498
struct _FCB * RootDcb
Definition: fatstruc.h:285
struct _VCB::@717 AllocationSupport
ULONG ChangeCount
Definition: fatstruc.h:520
PVPB Vpb
Definition: cdstruc.h:511
PVPB SwapVpb
Definition: cdstruc.h:667
VCB_CONDITION VcbCondition
Definition: cdstruc.h:541
CLONG OpenFileCount
Definition: fatstruc.h:312
PFILE_OBJECT VirtualVolumeFile
Definition: fatstruc.h:421
ULONG VcbState
Definition: cdstruc.h:540
PDEVICE_OBJECT TargetDeviceObject
Definition: cdstruc.h:517
BIOS_PARAMETER_BLOCK Bpb
Definition: fatstruc.h:336
Definition: iotypes.h:189
WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH/sizeof(WCHAR)]
Definition: iotypes.h:198
CSHORT Type
Definition: iotypes.h:190
USHORT VolumeLabelLength
Definition: iotypes.h:193
CSHORT Size
Definition: iotypes.h:191
USHORT Flags
Definition: iotypes.h:192
ULONG SerialNumber
Definition: iotypes.h:196
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
Definition: bidi.c:434
BOOLEAN NTAPI KeCancelTimer(IN OUT PKTIMER Timer)
Definition: timerobj.c:206
else
Definition: tritemp.h:161
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
PVOID HANDLE
Definition: typedefs.h:73
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char CCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_FILE_IS_A_DIRECTORY
Definition: udferr_usr.h:164
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNRECOGNIZED_VOLUME
Definition: udferr_usr.h:173
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
ULONG CLONG
Definition: umtypes.h:126
STRING OEM_STRING
Definition: umtypes.h:203
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
struct tagRun Run
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_ ULONG SectorSize
Definition: halfuncs.h:291
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
struct _FSCTL_QUERY_FAT_BPB_BUFFER * PFSCTL_QUERY_FAT_BPB_BUFFER
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_TYPE_VPB
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define SL_ALLOW_RAW_MOUNT
Definition: iotypes.h:1841
struct _VPB VPB
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_DIRECT_WRITES_ALLOWED
Definition: iotypes.h:1812
#define VPB_LOCKED
Definition: iotypes.h:1808
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4408
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
@ Executive
Definition: ketypes.h:415
#define ROUND_TO_PAGES(Size)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define NT_ASSERT
Definition: rtlfuncs.h:3310
_In_ LARGE_INTEGER _Out_opt_ PLARGE_INTEGER Remainder
Definition: rtlfuncs.h:3045
*BytesInOemString PCHAR OemString
Definition: rtlfuncs.h:1560
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180