ReactOS 0.4.15-dev-7842-g558ab78
verfysup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 VerfySup.c
8
9Abstract:
10
11 This module implements the Fat Verify volume and fcb/dcb support
12 routines
13
14
15--*/
16
17#include "fatprocs.h"
18
19//
20// The Bug check file id for this module
21//
22
23#define BugCheckFileId (FAT_BUG_CHECK_VERFYSUP)
24
25//
26// The Debug trace level for this module
27//
28
29#define Dbg (DEBUG_TRACE_VERFYSUP)
30
31//
32// Local procedure prototypes
33//
34
35VOID
37 IN PIRP_CONTEXT IrpContext,
38 IN PFCB Fcb
39 );
40
43 __in PIRP_CONTEXT IrpContext,
46 );
47
48_Requires_lock_held_(_Global_critical_region_)
49VOID
50FatDetermineAndMarkFcbCondition (
51 IN PIRP_CONTEXT IrpContext,
52 IN PFCB Fcb
53 );
54
55WORKER_THREAD_ROUTINE FatDeferredCleanVolume;
56
57VOID
61 );
62
63IO_COMPLETION_ROUTINE FatMarkVolumeCompletionRoutine;
64
70 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
71 );
72
73#ifdef ALLOC_PRAGMA
74#pragma alloc_text(PAGE, FatCheckDirtyBit)
75#pragma alloc_text(PAGE, FatVerifyOperationIsLegal)
76#pragma alloc_text(PAGE, FatDeferredCleanVolume)
77#pragma alloc_text(PAGE, FatMatchFileSize)
78#pragma alloc_text(PAGE, FatDetermineAndMarkFcbCondition)
79#pragma alloc_text(PAGE, FatQuickVerifyVcb)
80#pragma alloc_text(PAGE, FatPerformVerify)
81#pragma alloc_text(PAGE, FatMarkFcbCondition)
82#pragma alloc_text(PAGE, FatResetFcb)
83#pragma alloc_text(PAGE, FatVerifyVcb)
84#pragma alloc_text(PAGE, FatVerifyFcb)
85#endif
86
87
88VOID
90 IN PIRP_CONTEXT IrpContext,
91 IN PFCB Fcb,
92 IN FCB_CONDITION FcbCondition,
93 IN BOOLEAN Recursive
94 )
95
96/*++
97
98Routine Description:
99
100 This routines marks the entire Fcb/Dcb structure from Fcb down with
101 FcbCondition.
102
103Arguments:
104
105 Fcb - Supplies the Fcb/Dcb being marked
106
107 FcbCondition - Supplies the setting to use for the Fcb Condition
108
109 Recursive - Specifies whether this condition should be applied to
110 all children (see the case where we are invalidating a live volume
111 for a case where this is now desireable).
112
113Return Value:
114
115 None.
116
117--*/
118
119{
120 PAGED_CODE();
121
122 DebugTrace(+1, Dbg, "FatMarkFcbCondition, Fcb = %p\n", Fcb );
123
124 //
125 // If we are marking this Fcb something other than Good, we will need
126 // to have the Vcb exclusive.
127 //
128
129 NT_ASSERT( FcbCondition != FcbNeedsToBeVerified ? TRUE :
130 FatVcbAcquiredExclusive(IrpContext, Fcb->Vcb) );
131
132 //
133 // If this is a PagingFile it has to be good unless media underneath is
134 // removable. The "removable" check was added specifically for ReadyBoost,
135 // which opens its cache file on a removable device as a paging file and
136 // relies on the file system to validate its mapping information after a
137 // power transition.
138 //
139
142
144 return;
145 }
146
147 //
148 // Update the condition of the Fcb.
149 //
150
151 Fcb->FcbCondition = FcbCondition;
152
153 DebugTrace(0, Dbg, "MarkFcb: %wZ\n", &Fcb->FullFileName);
154
155 //
156 // This FastIo flag is based on FcbCondition, so update it now. This only
157 // applies to regular FCBs, of course.
158 //
159
160 if (Fcb->Header.NodeTypeCode == FAT_NTC_FCB) {
161
162 Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
163 }
164
165 if (FcbCondition == FcbNeedsToBeVerified) {
166 FatResetFcb( IrpContext, Fcb );
167 }
168
169 //
170 // Now if we marked NeedsVerify or Bad a directory then we also need to
171 // go and mark all of our children with the same condition.
172 //
173
174 if ( ((FcbCondition == FcbNeedsToBeVerified) ||
175 (FcbCondition == FcbBad)) &&
176 Recursive &&
177 ((Fcb->Header.NodeTypeCode == FAT_NTC_DCB) ||
178 (Fcb->Header.NodeTypeCode == FAT_NTC_ROOT_DCB)) ) {
179
180 PFCB OriginalFcb = Fcb;
181
182 while ( (Fcb = FatGetNextFcbTopDown(IrpContext, Fcb, OriginalFcb)) != NULL ) {
183
184 DebugTrace(0, Dbg, "MarkFcb: %wZ\n", &Fcb->FullFileName);
185
186 Fcb->FcbCondition = FcbCondition;
187
188 //
189 // We already know that FastIo is not possible since we are propagating
190 // a parent's bad/verify flag down the tree - IO to the children must
191 // take the long route for now.
192 //
193
194 Fcb->Header.IsFastIoPossible = FastIoIsNotPossible;
195
196 //
197 // Leave all the Fcbs in a condition to be verified.
198 //
199
200 if (FcbCondition == FcbNeedsToBeVerified) {
201 FatResetFcb( IrpContext, Fcb );
202 }
203
204 }
205 }
206
207 DebugTrace(-1, Dbg, "FatMarkFcbCondition -> VOID\n", 0);
208
209 return;
210}
211
214 IN PVCB Vcb
215 )
216
217/*++
218
219Routine Description:
220
221 This routine checks to see if the specified Vcb is currently mounted on
222 the device or not. If it is, it sets the verify flag on the device, if
223 not then the state is noted in the Vcb.
224
225Arguments:
226
227 Vcb - This is the volume to check.
228
229Return Value:
230
231 TRUE if the device has been marked for verify here, FALSE otherwise.
232
233--*/
234{
236 KIRQL SavedIrql;
237
238 IoAcquireVpbSpinLock( &SavedIrql );
239
240#ifdef _MSC_VER
241#pragma prefast( push )
242#pragma prefast( disable: 28175, "touching Vpb is ok for a filesystem" )
243#endif
244
245 if (Vcb->Vpb->RealDevice->Vpb == Vcb->Vpb) {
246
247 SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
248 Marked = TRUE;
249 }
250 else {
251
252 //
253 // Flag this to avoid the VPB spinlock in future passes.
254 //
255
257 }
258
259#ifdef _MSC_VER
260#pragma prefast( pop )
261#endif
262
263 IoReleaseVpbSpinLock( SavedIrql );
264
265 return Marked;
266}
267
268
269VOID
271 IN PIRP_CONTEXT IrpContext,
272 IN PVCB Vcb
273 )
274
275/*++
276
277Routine Description:
278
279 This routines verifies that the Vcb still denotes a valid Volume
280 If the Vcb is bad it raises an error condition.
281
282Arguments:
283
284 Vcb - Supplies the Vcb being verified
285
286Return Value:
287
288 None.
289
290--*/
291
292{
293 BOOLEAN DevMarkedForVerify;
294
295 PAGED_CODE();
296
297 DebugTrace(+1, Dbg, "FatVerifyVcb, Vcb = %p\n", Vcb );
298
299 //
300 // If the verify volume flag in the device object is set
301 // this means the media has potentially changed.
302 //
303 // Note that we only force this ping for create operations.
304 // For others we take a sporting chance. If in the end we
305 // have to physically access the disk, the right thing will happen.
306 //
307
308 DevMarkedForVerify = BooleanFlagOn(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME);
309
310 //
311 // We ALWAYS force CREATE requests on unmounted volumes through the
312 // verify path. These requests could have been in limbo between
313 // IoCheckMountedVpb and us, when a verify/mount took place and caused
314 // a completely different fs/volume to be mounted. In this case the
315 // checks above may not have caught the condition, since we may already
316 // have verified (wrong volume) and decided that we have nothing to do.
317 // We want the requests to be re routed to the currently mounted volume,
318 // since they were directed at the 'drive', not our volume. So we take
319 // the verify path for synchronisation, and the request will eventually
320 // be bounced back to IO with STATUS_REPARSE by our verify handler.
321 //
322
323 if (!DevMarkedForVerify &&
324 (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
325 (IrpContext->OriginatingIrp != NULL)) {
326
327 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( IrpContext->OriginatingIrp);
328
329 if ((IrpSp->FileObject->RelatedFileObject == NULL) &&
330 (Vcb->VcbCondition == VcbNotMounted)) {
331
332 DevMarkedForVerify = TRUE;
333 }
334 }
335
336 //
337 // Raise any error condition otherwise.
338 //
339
340 if (DevMarkedForVerify) {
341
342 DebugTrace(0, Dbg, "The Vcb needs to be verified\n", 0);
343
344 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
345 Vcb->Vpb->RealDevice );
346
348 }
349
350 //
351 // Check the operation is legal for current Vcb state.
352 //
353
354 FatQuickVerifyVcb( IrpContext, Vcb );
355
356 DebugTrace(-1, Dbg, "FatVerifyVcb -> VOID\n", 0);
357}
358
359
360_Requires_lock_held_(_Global_critical_region_)
361VOID
362FatVerifyFcb (
363 IN PIRP_CONTEXT IrpContext,
364 IN PFCB Fcb
365 )
366
367/*++
368
369Routine Description:
370
371 This routines verifies that the Fcb still denotes the same file.
372 If the Fcb is bad it raises a error condition.
373
374Arguments:
375
376 Fcb - Supplies the Fcb being verified
377
378Return Value:
379
380 None.
381
382--*/
383
384{
386
387 PAGED_CODE();
388
389 DebugTrace(+1, Dbg, "FatVerifyFcb, Vcb = %p\n", Fcb );
390
391 //
392 // Always refuse operations on dismounted volumes.
393 //
394
396
398 }
399
400 //
401 // If this is the Fcb of a deleted dirent or our parent is deleted,
402 // no-op this call with the hope that the caller will do the right thing.
403 // The only caller we really have to worry about is the AdvanceOnly
404 // callback for setting valid data length from Cc, this will happen after
405 // cleanup (and file deletion), just before the SCM is ripped down.
406 //
407
408 if (IsFileDeleted( IrpContext, Fcb ) ||
410 IsFileDeleted( IrpContext, Fcb->ParentDcb ))) {
411
412 return;
413 }
414
415 //
416 // If we are not in the process of doing a verify,
417 // first do a quick spot check on the Vcb.
418 //
419
420 if ( Fcb->Vcb->VerifyThread != KeGetCurrentThread() ) {
421
422 FatQuickVerifyVcb( IrpContext, Fcb->Vcb );
423 }
424
425 //
426 // Now based on the condition of the Fcb we'll either return
427 // immediately to the caller, raise a condition, or do some work
428 // to verify the Fcb.
429 //
430
431 switch (Fcb->FcbCondition) {
432
433 case FcbGood:
434
435 DebugTrace(0, Dbg, "The Fcb is good\n", 0);
436 break;
437
438 case FcbBad:
439
440 FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
441 break;
442
444
445 //
446 // We loop here checking our ancestors until we hit an Fcb which
447 // is either good or bad.
448 //
449
450 CurrentFcb = Fcb;
451
453
454 FatDetermineAndMarkFcbCondition(IrpContext, CurrentFcb);
455
456 //
457 // If this Fcb didn't make it, or it was the Root Dcb, exit
458 // the loop now, else continue with out parent.
459 //
460
461 if ( (CurrentFcb->FcbCondition != FcbGood) ||
463
464 break;
465 }
466
468 }
469
470 //
471 // Now we can just look at ourselves to see how we did.
472 //
473
474 if (Fcb->FcbCondition != FcbGood) {
475
476 FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
477 }
478
479 break;
480
481 default:
482
483 DebugDump("Invalid FcbCondition\n", 0, Fcb);
484
485#ifdef _MSC_VER
486#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
487#endif
488 FatBugCheck( Fcb->FcbCondition, 0, 0 );
489 }
490
491 DebugTrace(-1, Dbg, "FatVerifyFcb -> VOID\n", 0);
492
493 return;
494}
495
496
497VOID
498NTAPI
501 )
502
503/*++
504
505Routine Description:
506
507 This is the routine that performs the actual FatMarkVolumeClean call.
508 It assures that the target volume still exists as there ia a race
509 condition between queueing the ExWorker item and volumes going away.
510
511Arguments:
512
513 Parameter - Points to a clean volume packet that was allocated from pool
514
515Return Value:
516
517 None.
518
519--*/
520
521{
523 PLIST_ENTRY Links;
524 PVCB Vcb;
525 IRP_CONTEXT IrpContext;
526 BOOLEAN VcbExists = FALSE;
527
528 PAGED_CODE();
529
530 DebugTrace(+1, Dbg, "FatDeferredCleanVolume\n", 0);
531
533
534 Vcb = Packet->Vcb;
535
536 //
537 // Make us appear as a top level FSP request so that we will
538 // receive any errors from the operation.
539 //
540
542
543 //
544 // Dummy up and Irp Context so we can call our worker routines
545 //
546
547 RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT));
548
549 SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
550
551 //
552 // Acquire shared access to the global lock and make sure this volume
553 // still exists.
554 //
555
556#ifdef _MSC_VER
557#pragma prefast( push )
558#pragma prefast( disable: 28193, "this will always wait" )
559#endif
560 FatAcquireSharedGlobal( &IrpContext );
561#ifdef _MSC_VER
562#pragma prefast( pop )
563#endif
564
565 for (Links = FatData.VcbQueue.Flink;
566 Links != &FatData.VcbQueue;
567 Links = Links->Flink) {
568
569 PVCB ExistingVcb;
570
571 ExistingVcb = CONTAINING_RECORD(Links, VCB, VcbLinks);
572
573 if ( Vcb == ExistingVcb ) {
574
575 VcbExists = TRUE;
576 break;
577 }
578 }
579
580 //
581 // If the vcb is good then mark it clean. Ignore any problems.
582 //
583
584 if ( VcbExists &&
585 (Vcb->VcbCondition == VcbGood) &&
586 !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_SHUTDOWN) ) {
587
588 _SEH2_TRY {
589
590 if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
591
592 FatMarkVolume( &IrpContext, Vcb, VolumeClean );
593 }
594
595 //
596 // Check for a pathological race condition, and fix it.
597 //
598
599 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {
600
601 FatMarkVolume( &IrpContext, Vcb, VolumeDirty );
602
603 } else {
604
605 //
606 // Unlock the volume if it is removable.
607 //
608
609 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
611
612 FatToggleMediaEjectDisable( &IrpContext, Vcb, FALSE );
613 }
614 }
615
618
619 NOTHING;
620 } _SEH2_END;
621 }
622
623 //
624 // Release the global resource, unpin and repinned Bcbs and return.
625 //
626
627 FatReleaseGlobal( &IrpContext );
628
629 _SEH2_TRY {
630
631 FatUnpinRepinnedBcbs( &IrpContext );
632
635
636 NOTHING;
637 } _SEH2_END;
638
640
641 //
642 // and finally free the packet.
643 //
644
646
647 return;
648}
649
650
651
652VOID
653NTAPI
655 _In_ PKDPC Dpc,
659 )
660
661/*++
662
663Routine Description:
664
665 This routine is dispatched 5 seconds after the last disk structure was
666 modified in a specific volume, and exqueues an execuative worker thread
667 to perform the actual task of marking the volume dirty.
668
669Arguments:
670
671 DefferedContext - Contains the Vcb to process.
672
673Return Value:
674
675 None.
676
677--*/
678
679{
680 PVCB Vcb;
682
686
688
689
690 //
691 // If there is still dirty data (highly unlikely), set the timer for a
692 // second in the future.
693 //
694
695 if (CcIsThereDirtyData(Vcb->Vpb)) {
696
697 LARGE_INTEGER TwoSecondsFromNow;
698
699 TwoSecondsFromNow.QuadPart = (LONG)-2*1000*1000*10;
700
701 KeSetTimer( &Vcb->CleanVolumeTimer,
702 TwoSecondsFromNow,
703 &Vcb->CleanVolumeDpc );
704
705 return;
706 }
707
708 //
709 // If we couldn't get pool, oh well....
710 //
711
712 Packet = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(CLEAN_AND_DIRTY_VOLUME_PACKET), ' taF');
713
714 if ( Packet ) {
715
716 Packet->Vcb = Vcb;
717 Packet->Irp = NULL;
718
719 //
720 // Clear the dirty flag now since we cannot synchronize after this point.
721 //
722
724
726
727#ifdef _MSC_VER
728#pragma prefast( suppress:28159, "prefast indicates this is an obsolete API, but it is ok for fastfat to keep using it" )
729#endif
731 }
732
733 return;
734}
735
736
737_Requires_lock_held_(_Global_critical_region_)
738VOID
739FatMarkVolume (
740 IN PIRP_CONTEXT IrpContext,
741 IN PVCB Vcb,
743 )
744
745/*++
746
747Routine Description:
748
749 This routine moves the physically marked volume state between the clean
750 and dirty states. For compatibility with Win9x, we manipulate both the
751 historical DOS (on==clean in index 1 of the FAT) and NT (on==dirty in
752 the CurrentHead field of the BPB) dirty bits.
753
754Arguments:
755
756 Vcb - Supplies the Vcb being modified
757
758 VolumeState - Supplies the state the volume is transitioning to
759
760Return Value:
761
762 None.
763
764--*/
765
766{
767 PCHAR Sector;
768 PBCB Bcb = NULL;
770 PIRP Irp = NULL;
772 BOOLEAN FsInfoUpdate = FALSE;
773 ULONG FsInfoOffset = 0;
774 ULONG ThisPass;
777
778 DebugTrace(+1, Dbg, "FatMarkVolume, Vcb = %p\n", Vcb);
779
780 //
781 // We had best not be trying to scribble dirty/clean bits if the
782 // volume is write protected. The responsibility lies with the
783 // callers to make sure that operations that could cause a state
784 // change cannot happen. There are a few, though, that show it
785 // just doesn't make sense to force everyone to do the dinky
786 // check.
787 //
788
789 //
790 // If we were called for FAT12 or readonly media, return immediately.
791 //
792
793 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED) ||
794 FatIsFat12( Vcb )) {
795
796 return;
797 }
798
799 //
800 // We have two possible additional tasks to do to mark a volume
801 //
802 // Pass 0) Flip the dirty bit in the Bpb
803 // Pass 1) Rewrite the FsInfo sector for FAT32 if needed
804 //
805 // In most cases we can collapse these two either because the volume
806 // is either not FAT32 or the FsInfo sector is adjacent to the boot sector.
807 //
808
809 for (ThisPass = 0; ThisPass < 2; ThisPass++) {
810
811 //
812 // If this volume is being dirtied, or isn't FAT32, or if it is and
813 // we were able to perform the fast update, or the bpb lied to us
814 // about where the FsInfo went, we're done - no FsInfo to update in
815 // a seperate write.
816 //
817
818 if (ThisPass == 1 && (!FatIsFat32( Vcb ) ||
820 FsInfoUpdate ||
821 Vcb->Bpb.FsInfoSector == 0)) {
822
823 break;
824 }
825
826 //
827 // Bail if we get an IO error.
828 //
829
830 _SEH2_TRY {
831
832 ULONG PinLength;
834
835 //
836 // If the FAT table is 12-bit then our strategy is to pin the entire
837 // thing when any of it is modified. Here we're going to pin the
838 // first page, so in the 12-bit case we also want to pin the rest
839 // of the FAT table.
840 //
841
842 Offset.QuadPart = 0;
843
844 if (Vcb->AllocationSupport.FatIndexBitSize == 12) {
845
846 //
847 // But we only write back the first sector.
848 //
849
850 PinLength = FatReservedBytes(&Vcb->Bpb) + FatBytesPerFat(&Vcb->Bpb);
851 WriteLength = Vcb->Bpb.BytesPerSector;
852
853 } else {
854
855 WriteLength = PinLength = Vcb->Bpb.BytesPerSector;
856
857 //
858 // If this is a FAT32 volume going into the clean state,
859 // see about doing the FsInfo sector.
860 //
861
862 if (FatIsFat32( Vcb ) && VolumeState == VolumeClean) {
863
864 //
865 // If the FsInfo sector immediately follows the boot sector,
866 // we can do this in a single operation by rewriting both
867 // sectors at once.
868 //
869
870 if (Vcb->Bpb.FsInfoSector == 1) {
871
872 NT_ASSERT( ThisPass == 0 );
873
874 FsInfoUpdate = TRUE;
875 FsInfoOffset = Vcb->Bpb.BytesPerSector;
876 WriteLength = PinLength = Vcb->Bpb.BytesPerSector * 2;
877
878 } else if (ThisPass == 1) {
879
880 //
881 // We are doing an explicit write to the FsInfo sector.
882 //
883
884 FsInfoUpdate = TRUE;
885 FsInfoOffset = 0;
886
887 Offset.QuadPart = Vcb->Bpb.BytesPerSector * Vcb->Bpb.FsInfoSector;
888 }
889 }
890 }
891
892 //
893 // Call Cc directly here so that we can avoid overhead and push this
894 // right down to the disk.
895 //
896
897 CcPinRead( Vcb->VirtualVolumeFile,
898 &Offset,
899 PinLength,
900 TRUE,
901 &Bcb,
902 (PVOID *)&Sector );
903
904 DbgDoit( IrpContext->PinCount += 1 )
905
906 //
907 // Set the Bpb on Pass 0 always
908 //
909
910 if (ThisPass == 0) {
911
912 PCHAR CurrentHead;
913
914 //
915 // Before we do anything, doublecheck that this still looks like a
916 // FAT bootsector. If it doesn't, something remarkable happened
917 // and we should avoid touching the volume.
918 //
919 // THIS IS TEMPORARY (but may last a while)
920 //
921
922 if (!FatIsBootSectorFat( (PPACKED_BOOT_SECTOR) Sector )) {
923 abort = TRUE;
925 }
926
927 if (FatIsFat32( Vcb )) {
928
929 CurrentHead = (PCHAR)&((PPACKED_BOOT_SECTOR_EX) Sector)->CurrentHead;
930
931 } else {
932
933 CurrentHead = (PCHAR)&((PPACKED_BOOT_SECTOR) Sector)->CurrentHead;
934 }
935
936 if (VolumeState == VolumeClean) {
937
938 ClearFlag( *CurrentHead, FAT_BOOT_SECTOR_DIRTY );
939
940 } else {
941
942 SetFlag( *CurrentHead, FAT_BOOT_SECTOR_DIRTY );
943
944 //
945 // In addition, if this request received an error that may indicate
946 // media corruption, have autochk perform a surface test.
947 //
948
950
951 SetFlag( *CurrentHead, FAT_BOOT_SECTOR_TEST_SURFACE );
952 }
953 }
954 }
955
956 //
957 // Update the FsInfo as appropriate.
958 //
959
960 if (FsInfoUpdate) {
961
962 PFSINFO_SECTOR FsInfoSector = (PFSINFO_SECTOR) ((PCHAR)Sector + FsInfoOffset);
963
964 //
965 // We just rewrite all of the spec'd fields. Note that we don't
966 // care to synchronize with the allocation package - this will be
967 // quickly taken care of by a re-dirtying of the volume if a change
968 // is racing with us. Remember that this is all a compatibility
969 // deference for Win9x FAT32 - NT will never look at this information.
970 //
971
973 FsInfoSector->FsInfoSignature = FSINFO_SIGNATURE;
974 FsInfoSector->FreeClusterCount = Vcb->AllocationSupport.NumberOfFreeClusters;
975 FsInfoSector->NextFreeCluster = Vcb->ClusterHint;
977 }
978
979 //
980 // Initialize the event we're going to use
981 //
982
984
985 //
986 // Build the irp for the operation and also set the override flag.
987 // Note that we may be at APC level, so do this asyncrhonously and
988 // use an event for synchronization as normal request completion
989 // cannot occur at APC level.
990 //
991
993 Vcb->TargetDeviceObject,
994 (PVOID)Sector,
996 &Offset,
997 NULL );
998
999 if ( Irp == NULL ) {
1000
1002 }
1003
1004 //
1005 // Make this operation write-through. It never hurts to try to be
1006 // safer about this, even though we aren't logged.
1007 //
1008
1010
1011 //
1012 // Set up the completion routine
1013 //
1014
1017 &Event,
1018 TRUE,
1019 TRUE,
1020 TRUE );
1021
1022 //
1023 // Call the device to do the write and wait for it to finish.
1024 // Igmore any return status.
1025 //
1026
1027 Status = IoCallDriver( Vcb->TargetDeviceObject, Irp );
1028
1029 if (Status == STATUS_PENDING) {
1030
1032 }
1033
1034 try_exit: NOTHING;
1035 } _SEH2_FINALLY {
1036
1037 //
1038 // Clean up the Irp and Mdl
1039 //
1040
1041
1042 if (Irp) {
1043
1044 //
1045 // If there is an MDL (or MDLs) associated with this I/O
1046 // request, Free it (them) here. This is accomplished by
1047 // walking the MDL list hanging off of the IRP and deallocating
1048 // each MDL encountered.
1049 //
1050
1051 while (Irp->MdlAddress != NULL) {
1052
1053 PMDL NextMdl;
1054
1055 NextMdl = Irp->MdlAddress->Next;
1056
1057 MmUnlockPages( Irp->MdlAddress );
1058
1059 IoFreeMdl( Irp->MdlAddress );
1060
1061 Irp->MdlAddress = NextMdl;
1062 }
1063
1064 IoFreeIrp( Irp );
1065 }
1066
1067 if (Bcb != NULL) {
1068
1069 FatUnpinBcb( IrpContext, Bcb );
1070 }
1071 } _SEH2_END;
1072 }
1073
1074 if (!abort) {
1075
1076 //
1077 // Flip the dirty bit in the FAT
1078 //
1079
1080 if (VolumeState == VolumeDirty) {
1081
1082 FatSetFatEntry( IrpContext, Vcb, FAT_DIRTY_BIT_INDEX, FAT_DIRTY_VOLUME);
1083
1084 } else {
1085
1086 FatSetFatEntry( IrpContext, Vcb, FAT_DIRTY_BIT_INDEX, FAT_CLEAN_VOLUME);
1087 }
1088 }
1089
1090 DebugTrace(-1, Dbg, "FatMarkVolume -> VOID\n", 0);
1091
1092 return;
1093}
1094
1095
1096VOID
1097NTAPI
1100 )
1101
1102/*++
1103
1104Routine Description:
1105
1106 This is the routine that performs the actual FatMarkVolume Dirty call
1107 on a paging file Io that encounters a media error. It is responsible
1108 for completing the PagingIo Irp as soon as this is done.
1109
1110 Note: this routine (and thus FatMarkVolume()) must be resident as
1111 the paging file might be damaged at this point.
1112
1113Arguments:
1114
1115 Parameter - Points to a dirty volume packet that was allocated from pool
1116
1117Return Value:
1118
1119 None.
1120
1121--*/
1122
1123{
1125 PVCB Vcb;
1126 IRP_CONTEXT IrpContext;
1127 PIRP Irp;
1128
1129 DebugTrace(+1, Dbg, "FatFspMarkVolumeDirtyWithRecover\n", 0);
1130
1132
1133 Vcb = Packet->Vcb;
1134 Irp = Packet->Irp;
1135
1136 //
1137 // Dummy up the IrpContext so we can call our worker routines
1138 //
1139
1140 RtlZeroMemory( &IrpContext, sizeof(IRP_CONTEXT));
1141
1142 SetFlag(IrpContext.Flags, IRP_CONTEXT_FLAG_WAIT);
1143 IrpContext.OriginatingIrp = Irp;
1144
1145 //
1146 // Make us appear as a top level FSP request so that we will
1147 // receive any errors from the operation.
1148 //
1149
1151
1152 //
1153 // Try to write out the dirty bit. If something goes wrong, we
1154 // tried.
1155 //
1156
1157 _SEH2_TRY {
1158
1160
1161 FatMarkVolume( &IrpContext, Vcb, VolumeDirtyWithSurfaceTest );
1162
1164
1165 NOTHING;
1166 } _SEH2_END;
1167
1169
1170 //
1171 // Now complete the originating Irp or set the synchronous event.
1172 //
1173
1174 if (Packet->Event) {
1175 KeSetEvent( Packet->Event, 0, FALSE );
1176 } else {
1178 }
1179
1180 DebugTrace(-1, Dbg, "FatFspMarkVolumeDirtyWithRecover -> VOID\n", 0);
1181}
1182
1183
1184VOID
1186 IN PIRP_CONTEXT IrpContext,
1187 IN PVCB Vcb
1188 )
1189
1190/*++
1191
1192Routine Description:
1193
1194 This routine looks at the volume dirty bit, and depending on the state of
1195 VCB_STATE_FLAG_MOUNTED_DIRTY, the appropriate action is taken.
1196
1197Arguments:
1198
1199 Vcb - Supplies the Vcb being queried.
1200
1201Return Value:
1202
1203 None.
1204
1205--*/
1206
1207{
1208 BOOLEAN Dirty;
1209
1211 PBCB BootSectorBcb;
1212
1213 UNICODE_STRING VolumeLabel;
1214
1215 PAGED_CODE();
1216
1217 //
1218 // Look in the boot sector
1219 //
1220
1221 FatReadVolumeFile( IrpContext,
1222 Vcb,
1223 0,
1224 sizeof(PACKED_BOOT_SECTOR),
1225 &BootSectorBcb,
1226 (PVOID *)&BootSector );
1227
1228 _SEH2_TRY {
1229
1230 //
1231 // Check if the magic bit is set
1232 //
1233
1234 if (IsBpbFat32(&BootSector->PackedBpb)) {
1235 Dirty = BooleanFlagOn( ((PPACKED_BOOT_SECTOR_EX)BootSector)->CurrentHead,
1237 } else {
1238 Dirty = BooleanFlagOn( BootSector->CurrentHead, FAT_BOOT_SECTOR_DIRTY );
1239 }
1240
1241 //
1242 // Setup the VolumeLabel string
1243 //
1244
1245 VolumeLabel.Length = Vcb->Vpb->VolumeLabelLength;
1247 VolumeLabel.Buffer = &Vcb->Vpb->VolumeLabel[0];
1248
1249 if ( Dirty ) {
1250
1251 //
1252 // Do not trigger the mounted dirty bit if this is a verify
1253 // and the volume is a boot or paging device. We know that
1254 // a boot or paging device cannot leave the system, and thus
1255 // that on its mount we will have figured this out correctly.
1256 //
1257 // This logic is a reasonable change. Why?
1258 // 'cause setup cracked a non-exclusive DASD handle near the
1259 // end of setup, wrote some data, closed the handle and we
1260 // set the verify bit ... came back around and saw that other
1261 // arbitrary activity had left the volume in a temporarily dirty
1262 // state.
1263 //
1264 // Of course, the real problem is that we don't have a journal.
1265 //
1266
1267 if (!(IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
1268 IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME &&
1270
1273 "FASTFAT: WARNING! Mounting Dirty Volume %Z\n",
1274 &VolumeLabel));
1275
1277 }
1278
1279 } else {
1280
1281 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {
1282
1285 "FASTFAT: Volume %Z has been cleaned.\n",
1286 &VolumeLabel));
1287
1289
1290 } else {
1291
1292 (VOID)FsRtlBalanceReads( Vcb->TargetDeviceObject );
1293 }
1294 }
1295
1296 } _SEH2_FINALLY {
1297
1298 FatUnpinBcb( IrpContext, BootSectorBcb );
1299 } _SEH2_END;
1300}
1301
1302
1303VOID
1305 IN PIRP_CONTEXT IrpContext
1306 )
1307
1308/*++
1309
1310Routine Description:
1311
1312 This routine determines is the requested operation should be allowed to
1313 continue. It either returns to the user if the request is Okay, or
1314 raises an appropriate status.
1315
1316Arguments:
1317
1318 Irp - Supplies the Irp to check
1319
1320Return Value:
1321
1322 None.
1323
1324--*/
1325
1326{
1327 PIRP Irp;
1329
1330 PAGED_CODE();
1331
1332 Irp = IrpContext->OriginatingIrp;
1333
1334 //
1335 // If the Irp is not present, then we got here via close.
1336 //
1337 //
1338
1339 if ( Irp == NULL ) {
1340
1341 return;
1342 }
1343
1345
1346 //
1347 // If there is not a file object, we cannot continue.
1348 //
1349
1350 if ( FileObject == NULL ) {
1351
1352 return;
1353 }
1354
1355 //
1356 // If the file object has already been cleaned up, and
1357 //
1358 // A) This request is a paging io read or write, or
1359 // B) This request is a close operation, or
1360 // C) This request is a set or query info call (for Lou)
1361 // D) This is an MDL complete
1362 //
1363 // let it pass, otherwise return STATUS_FILE_CLOSED.
1364 //
1365
1366 if ( FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE) ) {
1367
1369
1370 if ( (FlagOn(Irp->Flags, IRP_PAGING_IO)) ||
1374 ( ( (IrpSp->MajorFunction == IRP_MJ_READ) ||
1377
1378 NOTHING;
1379
1380 } else {
1381
1382 FatRaiseStatus( IrpContext, STATUS_FILE_CLOSED );
1383 }
1384 }
1385
1386 return;
1387}
1388
1389
1390
1391//
1392// Internal support routine
1393//
1394
1395VOID
1397 IN PIRP_CONTEXT IrpContext,
1398 IN PFCB Fcb
1399 )
1400
1401/*++
1402
1403Routine Description:
1404
1405 This routine is called when an Fcb has been marked as needs to be verified.
1406
1407 It does the following tasks:
1408
1409 - Reset Mcb mapping information
1410 - For directories, reset dirent hints
1411 - Set allocation size to unknown
1412
1413Arguments:
1414
1415 Fcb - Supplies the Fcb to reset
1416
1417Return Value:
1418
1419 None.
1420
1421--*/
1422
1423{
1424 LOGICAL IsRealPagingFile;
1425
1426 PAGED_CODE();
1427 UNREFERENCED_PARAMETER( IrpContext );
1428
1429 //
1430 // Don't do the two following operations for the Root Dcb
1431 // of a non FAT32 volume or paging files. Paging files!?
1432 // Yes, if someone diddles a volume we try to reverify all
1433 // of the Fcbs just in case; however, there is no safe way
1434 // to chuck and retrieve the mapping pair information for
1435 // a real paging file. Lose it and die.
1436 //
1437 // An exception is made for ReadyBoost cache files, which
1438 // are created as paging files on removable devices and
1439 // require validation after a power transition.
1440 //
1441
1444
1445 IsRealPagingFile = TRUE;
1446
1447 } else {
1448
1449 IsRealPagingFile = FALSE;
1450 }
1451
1452 if ( (NodeType(Fcb) != FAT_NTC_ROOT_DCB ||
1453 FatIsFat32( Fcb->Vcb )) &&
1454 !IsRealPagingFile ) {
1455
1456 //
1457 // Reset the mcb mapping.
1458 //
1459
1460 FsRtlRemoveLargeMcbEntry( &Fcb->Mcb, 0, 0xFFFFFFFF );
1461
1462 //
1463 // Reset the allocation size to 0 or unknown
1464 //
1465
1466 if ( Fcb->FirstClusterOfFile == 0 ) {
1467
1468 Fcb->Header.AllocationSize.QuadPart = 0;
1469
1470 } else {
1471
1472 Fcb->Header.AllocationSize.QuadPart = FCB_LOOKUP_ALLOCATIONSIZE_HINT;
1473 }
1474 }
1475
1476 //
1477 // If this is a directory, reset the hints.
1478 //
1479
1480 if ( (NodeType(Fcb) == FAT_NTC_DCB) ||
1481 (NodeType(Fcb) == FAT_NTC_ROOT_DCB) ) {
1482
1483 //
1484 // Force a rescan of the directory
1485 //
1486
1487 Fcb->Specific.Dcb.UnusedDirentVbo = 0xffffffff;
1488 Fcb->Specific.Dcb.DeletedDirentHint = 0xffffffff;
1489 }
1490}
1491
1492
1493
1494BOOLEAN
1496 __in PIRP_CONTEXT IrpContext,
1498 __in PFCB Fcb
1499 )
1500{
1501
1502 UNREFERENCED_PARAMETER(IrpContext);
1503
1504 if (NodeType(Fcb) != FAT_NTC_FCB) {
1505 return TRUE;
1506 }
1507
1508
1509 if (Fcb->Header.FileSize.LowPart != Dirent->FileSize) {
1510 return FALSE;
1511 }
1512
1513
1514 return TRUE;
1515}
1516
1517//
1518// Internal support routine
1519//
1520
1521_Requires_lock_held_(_Global_critical_region_)
1522VOID
1523FatDetermineAndMarkFcbCondition (
1524 IN PIRP_CONTEXT IrpContext,
1525 IN PFCB Fcb
1526 )
1527
1528/*++
1529
1530Routine Description:
1531
1532 This routine checks a specific Fcb to see if it is different from what's
1533 on the disk. The following things are checked:
1534
1535 - File Name
1536 - File Size (if not directory)
1537 - First Cluster Of File
1538 - Dirent Attributes
1539
1540Arguments:
1541
1542 Fcb - Supplies the Fcb to examine
1543
1544Return Value:
1545
1546 None.
1547
1548--*/
1549
1550{
1552 PBCB DirentBcb;
1553 ULONG FirstClusterOfFile;
1554
1556 CHAR Buffer[16];
1557
1558 PAGED_CODE();
1559
1560 //
1561 // If this is the Root Dcb, special case it. That is, we know
1562 // by definition that it is good since it is fixed in the volume
1563 // structure.
1564 //
1565
1566 if ( NodeType(Fcb) == FAT_NTC_ROOT_DCB ) {
1567
1568 FatMarkFcbCondition( IrpContext, Fcb, FcbGood, FALSE );
1569
1570 return;
1571 }
1572
1573 // The first thing we need to do to verify ourselves is
1574 // locate the dirent on the disk.
1575 //
1576
1577 FatGetDirentFromFcbOrDcb( IrpContext,
1578 Fcb,
1579 TRUE,
1580 &Dirent,
1581 &DirentBcb );
1582 //
1583 // If we couldn't get the dirent, this fcb must be bad (case of
1584 // enclosing directory shrinking during the time it was ejected).
1585 //
1586
1587 if (DirentBcb == NULL) {
1588
1589 FatMarkFcbCondition( IrpContext, Fcb, FcbBad, FALSE );
1590
1591 return;
1592 }
1593
1594 //
1595 // We located the dirent for ourselves now make sure it
1596 // is really ours by comparing the Name and FatFlags.
1597 // Then for a file we also check the file size.
1598 //
1599 // Note that we have to unpin the Bcb before calling FatResetFcb
1600 // in order to avoid a deadlock in CcUninitializeCacheMap.
1601 //
1602
1603 _SEH2_TRY {
1604
1605 Name.MaximumLength = 16;
1606 Name.Buffer = &Buffer[0];
1607
1608 Fat8dot3ToString( IrpContext, Dirent, FALSE, &Name );
1609
1610 //
1611 // We need to calculate the first cluster 'cause FAT32 splits
1612 // this field across the dirent.
1613 //
1614
1615 FirstClusterOfFile = Dirent->FirstClusterOfFile;
1616
1617 if (FatIsFat32( Fcb->Vcb )) {
1618
1619 FirstClusterOfFile += Dirent->FirstClusterOfFileHi << 16;
1620 }
1621
1623
1624 ||
1625
1626 !FatMatchFileSize(IrpContext, Dirent, Fcb )
1627
1628 ||
1629
1630 (FirstClusterOfFile != Fcb->FirstClusterOfFile)
1631
1632 ||
1633
1634 (Dirent->Attributes != Fcb->DirentFatFlags) ) {
1635
1636 FatMarkFcbCondition( IrpContext, Fcb, FcbBad, FALSE );
1637
1638 } else {
1639
1640 //
1641 // We passed. Get the Fcb ready to use again.
1642 //
1643
1644 FatMarkFcbCondition( IrpContext, Fcb, FcbGood, FALSE );
1645 }
1646
1647 } _SEH2_FINALLY {
1648
1649 FatUnpinBcb( IrpContext, DirentBcb );
1650 } _SEH2_END;
1651
1652 return;
1653}
1654
1655
1656
1657//
1658// Internal support routine
1659//
1660
1661VOID
1663 IN PIRP_CONTEXT IrpContext,
1664 IN PVCB Vcb
1665 )
1666
1667/*++
1668
1669Routine Description:
1670
1671 This routines just checks the verify bit in the real device and the
1672 Vcb condition and raises an appropriate exception if so warented.
1673 It is called when verifying both Fcbs and Vcbs.
1674
1675Arguments:
1676
1677 Vcb - Supplies the Vcb to check the condition of.
1678
1679Return Value:
1680
1681 None.
1682
1683--*/
1684
1685{
1686 PAGED_CODE();
1687
1688 //
1689 // If the real device needs to be verified we'll set the
1690 // DeviceToVerify to be our real device and raise VerifyRequired.
1691 //
1692
1693 if (FlagOn(Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME)) {
1694
1695 DebugTrace(0, Dbg, "The Vcb needs to be verified\n", 0);
1696
1697 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
1698 Vcb->Vpb->RealDevice );
1699
1701 }
1702
1703 //
1704 // Based on the condition of the Vcb we'll either return to our
1705 // caller or raise an error condition
1706 //
1707
1708 switch (Vcb->VcbCondition) {
1709
1710 case VcbGood:
1711
1712 DebugTrace(0, Dbg, "The Vcb is good\n", 0);
1713
1714 //
1715 // Do a check here of an operation that would try to modify a
1716 // write protected media.
1717 //
1718
1719 if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED) &&
1720 ((IrpContext->MajorFunction == IRP_MJ_WRITE) ||
1721 (IrpContext->MajorFunction == IRP_MJ_SET_INFORMATION) ||
1722 (IrpContext->MajorFunction == IRP_MJ_SET_EA) ||
1723 (IrpContext->MajorFunction == IRP_MJ_FLUSH_BUFFERS) ||
1724 (IrpContext->MajorFunction == IRP_MJ_SET_VOLUME_INFORMATION) ||
1725 (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
1726 IrpContext->MinorFunction == IRP_MN_USER_FS_REQUEST &&
1727 IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp)->Parameters.FileSystemControl.FsControlCode ==
1729
1730 //
1731 // Set the real device for the pop-up info, and set the verify
1732 // bit in the device object, so that we will force a verify
1733 // in case the user put the correct media back in.
1734 //
1735
1736
1737 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
1738 Vcb->Vpb->RealDevice );
1739
1741
1743 }
1744
1745 break;
1746
1747 case VcbNotMounted:
1748
1749 DebugTrace(0, Dbg, "The Vcb is not mounted\n", 0);
1750
1751 //
1752 // Set the real device for the pop-up info, and set the verify
1753 // bit in the device object, so that we will force a verify
1754 // in case the user put the correct media back in.
1755 //
1756
1757 IoSetHardErrorOrVerifyDevice( IrpContext->OriginatingIrp,
1758 Vcb->Vpb->RealDevice );
1759
1760 FatRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
1761
1762 break;
1763
1764 case VcbBad:
1765
1766 DebugTrace(0, Dbg, "The Vcb is bad\n", 0);
1767
1768 if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DISMOUNTED )) {
1769
1771
1772 } else {
1773
1774 FatRaiseStatus( IrpContext, STATUS_FILE_INVALID );
1775 }
1776 break;
1777
1778 default:
1779
1780 DebugDump("Invalid VcbCondition\n", 0, Vcb);
1781#ifdef _MSC_VER
1782#pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1783#endif
1784 FatBugCheck( Vcb->VcbCondition, 0, 0 );
1785 }
1786}
1787
1788_Requires_lock_held_(_Global_critical_region_)
1790FatPerformVerify (
1791 _In_ PIRP_CONTEXT IrpContext,
1792 _In_ PIRP Irp,
1794 )
1795
1796/*++
1797
1798Routine Description:
1799
1800 This routines performs an IoVerifyVolume operation and takes the
1801 appropriate action. After the Verify is complete the originating
1802 Irp is sent off to an Ex Worker Thread. This routine is called
1803 from the exception handler.
1804
1805Arguments:
1806
1807 Irp - The irp to send off after all is well and done.
1808
1809 Device - The real device needing verification.
1810
1811Return Value:
1812
1813 None.
1814
1815--*/
1816
1817{
1818 PVCB Vcb;
1822 BOOLEAN AllowRawMount = FALSE;
1823 BOOLEAN VcbDeleted = FALSE;
1824
1825 PAGED_CODE();
1826
1827 //
1828 // Check if this Irp has a status of Verify required and if it does
1829 // then call the I/O system to do a verify.
1830 //
1831 // Skip the IoVerifyVolume if this is a mount or verify request
1832 // itself. Trying a recursive mount will cause a deadlock with
1833 // the DeviceObject->DeviceLock.
1834 //
1835
1836 if ( (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
1837 ((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) ||
1838 (IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME)) ) {
1839
1840 return FatFsdPostRequest( IrpContext, Irp );
1841 }
1842
1843 DebugTrace(0, Dbg, "Verify Required, DeviceObject = %p\n", Device);
1844
1845 //
1846 // Extract a pointer to the Vcb from the VolumeDeviceObject.
1847 // Note that since we have specifically excluded mount,
1848 // requests, we know that IrpSp->DeviceObject is indeed a
1849 // volume device object.
1850 //
1851
1853
1856 DeviceObject )->Vcb;
1857
1858 //
1859 // Check if the volume still thinks it needs to be verified,
1860 // if it doesn't then we can skip doing a verify because someone
1861 // else beat us to it.
1862 //
1863
1864 _SEH2_TRY {
1865
1866 //
1867 // We will allow Raw to mount this volume if we were doing a
1868 // a DASD open.
1869 //
1870
1871 if ( (IrpContext->MajorFunction == IRP_MJ_CREATE) &&
1872 (IrpSp->FileObject->FileName.Length == 0) &&
1873 (IrpSp->FileObject->RelatedFileObject == NULL) ) {
1874
1875 AllowRawMount = TRUE;
1876 }
1877
1878 //
1879 // Send down the verify. This could be going to a different
1880 // filesystem.
1881 //
1882
1883 Status = IoVerifyVolume( Device, AllowRawMount );
1884
1885 //
1886 // If the verify operation completed it will return
1887 // either STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly.
1888 //
1889 // If FatVerifyVolume encountered an error during
1890 // processing, it will return that error. If we got
1891 // STATUS_WRONG_VOLUME from the verfy, and our volume
1892 // is now mounted, commute the status to STATUS_SUCCESS.
1893 //
1894 // Acquire the Vcb so we're working with a stable Vcb condition.
1895 //
1896
1897 FatAcquireSharedVcb(IrpContext, Vcb);
1898
1899 if ( (Status == STATUS_WRONG_VOLUME) &&
1900 (Vcb->VcbCondition == VcbGood) ) {
1901
1903 }
1904 else if ((STATUS_SUCCESS == Status) && (Vcb->VcbCondition != VcbGood)) {
1905
1907 }
1908
1909 //
1910 // Do a quick unprotected check here. The routine will do
1911 // a safe check. After here we can release the resource.
1912 // Note that if the volume really went away, we will be taking
1913 // the Reparse path.
1914 //
1915
1916 if ((VcbGood != Vcb->VcbCondition) &&
1917 (0 == Vcb->OpenFileCount) ) {
1918
1919 FatReleaseVcb( IrpContext, Vcb);
1920
1921#ifdef _MSC_VER
1922#pragma prefast( push )
1923#pragma prefast( disable: 28137, "prefast wants the wait to be a constant, but that isn't possible for the way fastfat is designed" )
1924#pragma prefast( disable: 28193 )
1925#endif
1926 FatAcquireExclusiveGlobal( IrpContext );
1927#ifdef _MSC_VER
1928#pragma prefast( pop )
1929#endif
1930
1931 FatAcquireExclusiveVcb( IrpContext,
1932 Vcb );
1933
1934 VcbDeleted = FatCheckForDismount( IrpContext,
1935 Vcb,
1936 FALSE );
1937
1938 if (!VcbDeleted) {
1939
1940 FatReleaseVcb( IrpContext,
1941 Vcb );
1942 }
1943
1944 FatReleaseGlobal( IrpContext );
1945 }
1946 else {
1947
1948 FatReleaseVcb( IrpContext, Vcb);
1949 }
1950
1951 //
1952 // If the IopMount in IoVerifyVolume did something, and
1953 // this is an absolute open, force a reparse.
1954 //
1955
1956 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
1957 (FileObject->RelatedFileObject == NULL) &&
1959
1960 Irp->IoStatus.Information = IO_REMOUNT;
1961
1962 FatCompleteRequest( IrpContext, Irp, STATUS_REPARSE );
1964 Irp = NULL;
1965 }
1966
1967 if ( (Irp != NULL) && !NT_SUCCESS(Status) ) {
1968
1969 //
1970 // Fill in the device object if required.
1971 //
1972
1973 if ( IoIsErrorUserInduced( Status ) ) {
1974
1976 }
1977
1979
1980 FatNormalizeAndRaiseStatus( IrpContext, Status );
1981 }
1982
1983 //
1984 // If there is still an Irp, send it off to an Ex Worker thread.
1985 //
1986
1987 if ( Irp != NULL ) {
1988
1989 Status = FatFsdPostRequest( IrpContext, Irp );
1990 }
1991
1992 }
1994
1995 //
1996 // We had some trouble trying to perform the verify or raised
1997 // an error ourselves. So we'll abort the I/O request with
1998 // the error status that we get back from the execption code.
1999 //
2000
2001 Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
2002 } _SEH2_END;
2003
2004 return Status;
2005}
2006
2007//
2008// Local support routine
2009//
2010
2012NTAPI
2015 _In_ PIRP Irp,
2016 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2017 )
2018
2019{
2020 //
2021 // Set the event so that our call will wake up.
2022 //
2023
2024 KeSetEvent( (PKEVENT)Contxt, 0, FALSE );
2025
2028
2030}
2031
2032
#define PAGED_CODE()
ULONG WriteLength
Definition: CcPinRead_drv.c:40
NodeType
Definition: Node.h:6
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
_In_ PFCB _In_ PDIRENT_ENUM_CONTEXT _Inout_ PDIRENT Dirent
Definition: cdprocs.h:427
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFCB * CurrentFcb
Definition: cdprocs.h:801
#define try_return(S)
Definition: cdprocs.h:2179
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:714
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
struct _VCB * PVCB
Definition: fatstruc.h:557
@ VcbNotMounted
Definition: cdstruc.h:490
@ FcbGood
Definition: cdstruc.h:779
@ FcbBad
Definition: cdstruc.h:780
@ FcbNeedsToBeVerified
Definition: cdstruc.h:781
enum _FCB_CONDITION FCB_CONDITION
Definition: bufpool.h:45
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define __in
Definition: dbghelp.h:35
#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
#define Marked(f)
Definition: render.c:146
@ DPFLTR_FASTFAT_ID
Definition: dpfilter.h:61
#define NodeType(P)
Definition: nodetype.h:51
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
#define FSINFO_SIGNATURE
Definition: fat.h:207
struct _FSINFO_SECTOR * PFSINFO_SECTOR
#define FatReservedBytes(B)
Definition: fat.h:414
#define FAT_DIRTY_VOLUME
Definition: fat.h:235
#define IsBpbFat32(bpb)
Definition: fat.h:101
#define FAT_CLEAN_VOLUME
Definition: fat.h:234
#define FSINFO_SECTOR_BEGIN_SIGNATURE
Definition: fat.h:204
#define FSINFO_SECTOR_END_SIGNATURE
Definition: fat.h:205
#define FAT_BOOT_SECTOR_TEST_SURFACE
Definition: fat.h:214
#define FAT_BOOT_SECTOR_DIRTY
Definition: fat.h:213
#define FatBytesPerFat(B)
Definition: fat.h:410
#define FAT_DIRTY_BIT_INDEX
Definition: fat.h:237
#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 FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#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 IsFileDeleted(Mcb)
Definition: ext2fs.h:968
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
VOID FatUnpinRepinnedBcbs(IN PIRP_CONTEXT IrpContext)
Definition: cachesup.c:1407
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
VOID FatQuickVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:1662
VOID NTAPI FatDeferredCleanVolume(_In_ PVOID Parameter)
Definition: verfysup.c:499
NTSTATUS NTAPI FatMarkVolumeCompletionRoutine(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp, _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt)
Definition: verfysup.c:2013
VOID FatResetFcb(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb)
Definition: verfysup.c:1396
BOOLEAN FatMatchFileSize(__in PIRP_CONTEXT IrpContext, __in PDIRENT Dirent, __in PFCB Fcb)
Definition: verfysup.c:1495
VOID FatCheckDirtyBit(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:1185
VOID FatVerifyVcb(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb)
Definition: verfysup.c:270
VOID FatVerifyOperationIsLegal(IN PIRP_CONTEXT IrpContext)
Definition: verfysup.c:1304
#define Dbg
Definition: verfysup.c:29
BOOLEAN FatMarkDevForVerifyIfVcbMounted(IN PVCB Vcb)
Definition: verfysup.c:213
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
FAT_DATA FatData
Definition: fatdata.c:56
#define DbgDoit(X)
Definition: fatdata.h:336
#define DebugDump(STR, LEVEL, PTR)
Definition: fatdata.h:314
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
@ VolumeClean
Definition: fatprocs.h:1954
@ VolumeDirty
Definition: fatprocs.h:1955
@ VolumeDirtyWithSurfaceTest
Definition: fatprocs.h:1956
#define FatVcbAcquiredExclusive(IRPCONTEXT, VCB)
Definition: fatprocs.h:1495
PFCB FatGetNextFcbTopDown(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN PFCB TerminationFcb)
Definition: strucsup.c:2627
IN PVCB IN VBO IN ULONG OUT PBCB * Bcb
Definition: fatprocs.h:414
#define FatAcquireExclusiveGlobal(IRPCONTEXT)
Definition: fatprocs.h:1387
#define FatUnpinBcb(IRPCONTEXT, BCB)
Definition: fatprocs.h:546
WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover
Definition: fatprocs.h:2000
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define FatCompleteRequest(IRPCONTEXT, IRP, STATUS)
Definition: fatprocs.h:2633
#define FatReleaseGlobal(IRPCONTEXT)
Definition: fatprocs.h:1636
#define FatIsFat12(VCB)
Definition: fatprocs.h:1448
#define FatAcquireExclusiveVcb(IC, V)
Definition: fatprocs.h:1460
KDEFERRED_ROUTINE FatCleanVolumeDpc
Definition: fatprocs.h:1981
#define FatIsFastIoPossible(FCB)
Definition: fatprocs.h:2813
#define FatNormalizeAndRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2995
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2977
BOOLEAN FatIsBootSectorFat(IN PPACKED_BOOT_SECTOR BootSector)
Definition: fsctrl.c:2522
VOID Fat8dot3ToString(_In_ PIRP_CONTEXT IrpContext, _In_ PDIRENT Dirent, _In_ BOOLEAN RestoreCase, _Out_ POEM_STRING OutputString)
Definition: namesup.c:179
#define FatAcquireSharedGlobal(IRPCONTEXT)
Definition: fatprocs.h:1391
enum _FAT_VOLUME_STATE FAT_VOLUME_STATE
IN PVCB IN FAT_VOLUME_STATE VolumeState
Definition: fatprocs.h:1998
#define FatReleaseVcb(IRPCONTEXT, Vcb)
Definition: fatprocs.h:1640
#define FatIsFat32(VCB)
Definition: fatprocs.h:1446
VOID FatMarkFcbCondition(IN PIRP_CONTEXT IrpContext, IN PFCB Fcb, IN FCB_CONDITION FcbCondition, IN BOOLEAN Recursive)
#define VCB_STATE_FLAG_VOLUME_DIRTY
Definition: fatstruc.h:561
#define VCB_STATE_FLAG_SHUTDOWN
Definition: fatstruc.h:563
#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_MOUNTED_DIRTY
Definition: fatstruc.h:562
#define VCB_STATE_FLAG_WRITE_PROTECTED
Definition: fatstruc.h:570
#define FCB_LOOKUP_ALLOCATIONSIZE_HINT
Definition: fatstruc.h:1241
#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
struct _CLEAN_AND_DIRTY_VOLUME_PACKET * PCLEAN_AND_DIRTY_VOLUME_PACKET
NTSTATUS NTAPI FsRtlBalanceReads(PDEVICE_OBJECT TargetDevice)
Definition: faulttol.c:35
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define _SEH2_LEAVE
Definition: filesup.c:20
#define FSRTL_FSP_TOP_LEVEL_IRP
Definition: fsrtltypes.h:59
@ FastIoIsNotPossible
Definition: fsrtltypes.h:240
#define IoFreeMdl
Definition: fxmdl.h:89
Status
Definition: gdiplustypes.h:25
#define KeGetCurrentThread
Definition: hal.h:55
#define abort()
Definition: i386-dis.c:34
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define EXCEPTION_CONTINUE_SEARCH
Definition: excpt.h:86
#define NOTHING
Definition: input_list.c:10
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
VOID NTAPI FsRtlRemoveLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG SectorCount)
Definition: largemcb.c:905
if(dx< 0)
Definition: linetemp.h:194
BOOLEAN NTAPI CcIsThereDirtyData(IN PVPB Vpb)
Definition: logsup.c:55
#define PCHAR
Definition: match.c:90
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
#define KernelMode
Definition: asm.h:34
#define DPFLTR_INFO_LEVEL
Definition: kdtypes.h:33
#define FSCTL_MARK_VOLUME_DIRTY
Definition: nt_native.h:838
NTSYSAPI BOOLEAN NTAPI RtlEqualString(PSTRING String1, PSTRING String2, BOOLEAN CaseInSensitive)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ NotificationEvent
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoBuildAsynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:750
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
NTSTATUS NTAPI IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount)
Definition: volume.c:877
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:532
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:747
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_FILE_INVALID
Definition: ntstatus.h:388
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
BOOLEAN NTAPI CcPinRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG Flags, OUT PVOID *Bcb, OUT PVOID *Buffer)
Definition: pinsup.c:802
#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_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
LIST_ENTRY VcbQueue
Definition: fatstruc.h:49
Definition: cdstruc.h:902
struct _FCB * ParentDcb
Definition: fatstruc.h:836
union _FCB::@719 Specific
PVCB Vcb
Definition: cdstruc.h:933
CD_MCB Mcb
Definition: cdstruc.h:1016
UNICODE_STRING FullFileName
Definition: fatstruc.h:1122
FCB_CONDITION FcbCondition
Definition: fatstruc.h:850
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
FILE_NAME_NODE ShortName
Definition: fatstruc.h:1115
UCHAR DirentFatFlags
Definition: fatstruc.h:1133
union _FILE_NAME_NODE::@718 Name
OEM_STRING Oem
Definition: fatstruc.h:693
ULONG FsInfoSignature
Definition: fat.h:197
ULONG SectorEndSignature
Definition: fat.h:201
ULONG NextFreeCluster
Definition: fat.h:199
ULONG FreeClusterCount
Definition: fat.h:198
ULONG SectorBeginSignature
Definition: fat.h:195
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: ketypes.h:699
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: cdstruc.h:498
PKTHREAD VerifyThread
Definition: fatstruc.h:485
ULONG VcbState
Definition: cdstruc.h:540
BOOLEAN NTAPI KeSetTimer(IN OUT PKTIMER Timer, IN LARGE_INTEGER DueTime, IN PKDPC Dpc OPTIONAL)
Definition: timerobj.c:281
#define NTAPI
Definition: typedefs.h:36
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_MEDIA_WRITE_PROTECTED
Definition: udferr_usr.h:161
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
STRING OEM_STRING
Definition: umtypes.h:203
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ CriticalWorkQueue
Definition: extypes.h:189
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_PAGING_IO
#define IRP_MJ_SET_VOLUME_INFORMATION
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4403
#define IRP_MJ_SET_EA
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MJ_FLUSH_BUFFERS
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define IO_REMOUNT
Definition: iotypes.h:544
#define MAXIMUM_VOLUME_LABEL_LENGTH
Definition: iotypes.h:177
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
#define KdPrintEx(_x_)
Definition: kdfuncs.h:114
@ Executive
Definition: ketypes.h:415
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
#define NT_ASSERT
Definition: rtlfuncs.h:3310
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
char CHAR
Definition: xmlstorage.h:175