ReactOS 0.4.16-dev-336-gb667d82
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 Cdfs Verification routines.
12
13
14--*/
15
16#include "cdprocs.h"
17
18//
19// The Bug check file id for this module
20//
21
22#define BugCheckFileId (CDFS_BUG_CHECK_VERFYSUP)
23
24#ifdef ALLOC_PRAGMA
25#pragma alloc_text(PAGE, CdVerifyFcbOperation)
26#pragma alloc_text(PAGE, CdVerifyVcb)
27#endif
28
29_Requires_lock_held_(_Global_critical_region_)
31CdPerformVerify (
32 _Inout_ PIRP_CONTEXT IrpContext,
35 )
36
37/*++
38
39Routine Description:
40
41 This routines performs an IoVerifyVolume operation and takes the
42 appropriate action. If the verify is successful then we send the originating
43 Irp off to an Ex Worker Thread. This routine is called from the exception handler.
44
45 No file system resources are held when this routine is called.
46
47Arguments:
48
49 Irp - The irp to send off after all is well and done.
50
51 Device - The real device needing verification.
52
53Return Value:
54
55 None.
56
57--*/
58
59{
60 PVCB Vcb;
63
64 ASSERT_IRP_CONTEXT( IrpContext );
65 ASSERT_IRP( Irp );
66
67 //
68 // Check if this Irp has a status of Verify required and if it does
69 // then call the I/O system to do a verify.
70 //
71 // Skip the IoVerifyVolume if this is a mount or verify request
72 // itself. Trying a recursive mount will cause a deadlock with
73 // the DeviceObject->DeviceLock.
74 //
75
76 if ((IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
77 ((IrpContext->MinorFunction == IRP_MN_MOUNT_VOLUME) ||
78 (IrpContext->MinorFunction == IRP_MN_VERIFY_VOLUME))) {
79
80 return CdFsdPostRequest( IrpContext, Irp );
81 }
82
83 //
84 // Extract a pointer to the Vcb from the VolumeDeviceObject.
85 // Note that since we have specifically excluded mount,
86 // requests, we know that IrpSp->DeviceObject is indeed a
87 // volume device object.
88 //
89
91
94 DeviceObject )->Vcb;
95 _SEH2_TRY {
96
97 //
98 // Send down the verify FSCTL. Note that this is sent to the
99 // currently mounted volume, which may not be this one.
100 //
101 // We will allow Raw to mount this volume if we were doing a
102 // an absolute DASD open.
103 //
104
106
107 //
108 // Acquire the Vcb so we're working with a stable VcbCondition.
109 //
110
111 CdAcquireVcbShared( IrpContext, Vcb, FALSE);
112
113 //
114 // If the verify operation completed it will return
115 // either STATUS_SUCCESS or STATUS_WRONG_VOLUME, exactly.
116 //
117 // If CdVerifyVolume encountered an error during
118 // processing, it will return that error. If we got
119 // STATUS_WRONG_VOLUME from the verify, and our volume
120 // is now mounted, commute the status to STATUS_SUCCESS.
121 //
122
123 if ((Status == STATUS_WRONG_VOLUME) &&
124 (Vcb->VcbCondition == VcbMounted)) {
125
127 }
128 else if ((STATUS_SUCCESS == Status) && (Vcb->VcbCondition != VcbMounted)) {
129
130 //
131 // If the verify succeeded, but our volume is not mounted,
132 // then some other volume is on the device.
133 //
134
136 }
137
138 //
139 // Do a quick unprotected check here. The routine will do
140 // a safe check. After here we can release the resource.
141 // Note that if the volume really went away, we will be taking
142 // the Reparse path.
143 //
144
145 //
146 // If the device might need to go away then call our dismount routine.
147 //
148
149 if (((Vcb->VcbCondition == VcbNotMounted) ||
150 (Vcb->VcbCondition == VcbInvalid) ||
151 (Vcb->VcbCondition == VcbDismountInProgress)) &&
152 (Vcb->VcbReference <= CDFS_RESIDUAL_REFERENCE)) {
153
154 CdReleaseVcb( IrpContext, Vcb);
155
156 CdAcquireCdData( IrpContext );
157 CdCheckForDismount( IrpContext, Vcb, FALSE );
158 CdReleaseCdData( IrpContext );
159 }
160 else {
161
162 CdReleaseVcb( IrpContext, Vcb);
163 }
164
165 //
166 // If this is a create and the verify succeeded then complete the
167 // request with a REPARSE status.
168 //
169
170 if ((IrpContext->MajorFunction == IRP_MJ_CREATE) &&
171 (IrpSp->FileObject->RelatedFileObject == NULL) &&
173
174 Irp->IoStatus.Information = IO_REMOUNT;
175
176 CdCompleteRequest( IrpContext, Irp, STATUS_REPARSE );
178 Irp = NULL;
179 IrpContext = NULL;
180
181 //
182 // If there is still an error to process then call the Io system
183 // for a popup.
184 //
185
186 } else if ((Irp != NULL) && !NT_SUCCESS( Status )) {
187
188 //
189 // Fill in the device object if required.
190 //
191
193
195 }
196
197 CdNormalizeAndRaiseStatus( IrpContext, Status );
198 }
199
200 //
201 // If there is still an Irp, send it off to an Ex Worker thread.
202 //
203
204 if (IrpContext != NULL) {
205
206 Status = CdFsdPostRequest( IrpContext, Irp );
207 }
208
210
211 //
212 // We had some trouble trying to perform the verify or raised
213 // an error ourselves. So we'll abort the I/O request with
214 // the error status that we get back from the execption code.
215 //
216
217 Status = CdProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
218 } _SEH2_END;
219
220 return Status;
221}
222
223
224
225_Requires_lock_held_(_Global_critical_region_)
227CdCheckForDismount (
228 _In_ PIRP_CONTEXT IrpContext,
231 )
232
233/*++
234
235Routine Description:
236
237 This routine is called to check if a volume is ready for dismount. This
238 occurs when only file system references are left on the volume.
239
240 If the dismount is not currently underway and the user reference count
241 has gone to zero then we can begin the dismount.
242
243 If the dismount is in progress and there are no references left on the
244 volume (we check the Vpb for outstanding references as well to catch
245 any create calls dispatched to the file system) then we can delete
246 the Vcb.
247
248Arguments:
249
250 Vcb - Vcb for the volume to try to dismount.
251
252 Force - Whether we will force this volume to be dismounted.
253
254Return Value:
255
256 BOOLEAN - True if the Vcb was not gone by the time this function finished,
257 False if it was deleted.
258
259 This is only a trustworthy indication to the caller if it had the vcb
260 exclusive itself.
261
262--*/
263
264{
265 BOOLEAN UnlockVcb = TRUE;
266 BOOLEAN VcbPresent = TRUE;
267 KIRQL SavedIrql;
268
269 ASSERT_IRP_CONTEXT( IrpContext );
270 ASSERT_VCB( Vcb );
271
273
274 //
275 // Acquire and lock this Vcb to check the dismount state.
276 //
277
278 CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
279
280 //
281 // Lets get rid of any pending closes for this volume.
282 //
283
284 CdFspClose( Vcb );
285
286 CdLockVcb( IrpContext, Vcb );
287
288 //
289 // If the dismount is not already underway then check if the
290 // user reference count has gone to zero or we are being forced
291 // to disconnect. If so start the teardown on the Vcb.
292 //
293
294 if (Vcb->VcbCondition != VcbDismountInProgress) {
295
296 if (Vcb->VcbUserReference <= CDFS_RESIDUAL_USER_REFERENCE || Force) {
297
298 CdUnlockVcb( IrpContext, Vcb );
299 UnlockVcb = FALSE;
300 VcbPresent = CdDismountVcb( IrpContext, Vcb );
301 }
302
303 //
304 // If the teardown is underway and there are absolutely no references
305 // remaining then delete the Vcb. References here include the
306 // references in the Vcb and Vpb.
307 //
308
309 } else if (Vcb->VcbReference == 0) {
310
311 IoAcquireVpbSpinLock( &SavedIrql );
312
313 //
314 // If there are no file objects and no reference counts in the
315 // Vpb we can delete the Vcb. Don't forget that we have the
316 // last reference in the Vpb.
317 //
318
319 if (Vcb->Vpb->ReferenceCount == 1) {
320
321 IoReleaseVpbSpinLock( SavedIrql );
322 CdUnlockVcb( IrpContext, Vcb );
323 UnlockVcb = FALSE;
324 CdDeleteVcb( IrpContext, Vcb );
325 VcbPresent = FALSE;
326
327 } else {
328
329 IoReleaseVpbSpinLock( SavedIrql );
330 }
331 }
332
333 //
334 // Unlock the Vcb if still held.
335 //
336
337 if (UnlockVcb) {
338
339 CdUnlockVcb( IrpContext, Vcb );
340 }
341
342 //
343 // Release any resources still acquired.
344 //
345
346 if (VcbPresent) {
347
348 CdReleaseVcb( IrpContext, Vcb );
349 }
350 else {
352 }
353
354 return VcbPresent;
355}
356
357
361 )
362
363/*++
364
365Routine Description:
366
367 This routine checks to see if the specified Vcb is currently mounted on
368 the device or not. If it is, it sets the verify flag on the device, if
369 not then the state is noted in the Vcb.
370
371Arguments:
372
373 Vcb - This is the volume to check.
374
375Return Value:
376
377 TRUE if the device has been marked for verify here, FALSE otherwise.
378
379--*/
380
381{
383 KIRQL SavedIrql;
384
385 IoAcquireVpbSpinLock( &SavedIrql );
386
387#ifdef _MSC_VER
388#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the vpb is allowed")
389#endif
390 if (Vcb->Vpb->RealDevice->Vpb == Vcb->Vpb) {
391
392 CdMarkRealDevForVerify( Vcb->Vpb->RealDevice);
393 Marked = TRUE;
394 }
395 else {
396
397 //
398 // Flag this to avoid the VPB spinlock in future passes.
399 //
400
402 }
403
404 IoReleaseVpbSpinLock( SavedIrql );
405
406 return Marked;
407}
408
409
410VOID
412 _In_ PIRP_CONTEXT IrpContext,
414 )
415
416/*++
417
418Routine Description:
419
420 This routine checks that the current Vcb is valid and currently mounted
421 on the device. It will raise on an error condition.
422
423 We check whether the volume needs verification and the current state
424 of the Vcb.
425
426Arguments:
427
428 Vcb - This is the volume to verify.
429
430Return Value:
431
432 None
433
434--*/
435
436{
439 ULONG MediaChangeCount = 0;
440 BOOLEAN ForceVerify = FALSE;
441 BOOLEAN DevMarkedForVerify;
442
443 PAGED_CODE();
444
445 //
446 // Fail immediately if the volume is in the progress of being dismounted
447 // or has been marked invalid.
448 //
449
450 if ((Vcb->VcbCondition == VcbInvalid) ||
451 ((Vcb->VcbCondition == VcbDismountInProgress) &&
452 (IrpContext->MajorFunction != IRP_MJ_CREATE))) {
453
454 if (FlagOn( Vcb->VcbState, VCB_STATE_DISMOUNTED )) {
455
457
458 } else {
459
460 CdRaiseStatus( IrpContext, STATUS_FILE_INVALID );
461 }
462 }
463
464 //
465 // Capture the real device verify state.
466 //
467
468 DevMarkedForVerify = CdRealDevNeedsVerify( Vcb->Vpb->RealDevice);
469
470 if (FlagOn( Vcb->VcbState, VCB_STATE_REMOVABLE_MEDIA ) && !DevMarkedForVerify) {
471
472 //
473 // If the media is removable and the verify volume flag in the
474 // device object is not set then we want to ping the device
475 // to see if it needs to be verified.
476 //
477
478 if (Vcb->VcbCondition != VcbMountInProgress) {
479
480 Status = CdPerformDevIoCtrl( IrpContext,
482 Vcb->TargetDeviceObject,
483 &MediaChangeCount,
484 sizeof(ULONG),
485 FALSE,
486 FALSE,
487 &Iosb );
488
489 if (Iosb.Information != sizeof(ULONG)) {
490
491 //
492 // Be safe about the count in case the driver didn't fill it in
493 //
494
495 MediaChangeCount = 0;
496 }
497
498 //
499 // There are four cases when we want to do a verify. These are the
500 // first three.
501 //
502 // 1. We are mounted, and the device has become empty
503 // 2. The device has returned verify required (=> DO_VERIFY_VOL flag is
504 // set, but could be due to hardware condition)
505 // 3. Media change count doesn't match the one in the Vcb
506 //
507
508 if (((Vcb->VcbCondition == VcbMounted) &&
509 CdIsRawDevice( IrpContext, Status ))
510 ||
512 ||
513 (NT_SUCCESS(Status) &&
514 (Vcb->MediaChangeCount != MediaChangeCount))) {
515
516 //
517 // If we are currently the volume on the device then it is our
518 // responsibility to set the verify flag. If we're not on the device,
519 // then we shouldn't touch the flag.
520 //
521
522 if (!FlagOn( Vcb->VcbState, VCB_STATE_VPB_NOT_ON_DEVICE) &&
523 !DevMarkedForVerify) {
524
525 DevMarkedForVerify = CdMarkDevForVerifyIfVcbMounted( Vcb);
526 }
527
528 ForceVerify = TRUE;
529
530 //
531 // NOTE that we no longer update the media change count here. We
532 // do so only when we've actually completed a verify at a particular
533 // change count value.
534 //
535 }
536 }
537
538 //
539 // This is the 4th verify case.
540 //
541 // We ALWAYS force CREATE requests on unmounted volumes through the
542 // verify path. These requests could have been in limbo between
543 // IoCheckMountedVpb and us when a verify/mount took place and caused
544 // a completely different fs/volume to be mounted. In this case the
545 // checks above may not have caught the condition, since we may already
546 // have verified (wrong volume) and decided that we have nothing to do.
547 // We want the requests to be re routed to the currently mounted volume,
548 // since they were directed at the 'drive', not our volume.
549 //
550
551 if (NT_SUCCESS( Status) && !ForceVerify && !DevMarkedForVerify &&
552 (IrpContext->MajorFunction == IRP_MJ_CREATE)) {
553
555
556 ForceVerify = (IrpSp->FileObject->RelatedFileObject == NULL) &&
557 ((Vcb->VcbCondition == VcbDismountInProgress) ||
558 (Vcb->VcbCondition == VcbNotMounted));
559
560 //
561 // Note that we don't touch the device verify flag here. It required
562 // it would have been caught and set by the first set of checks.
563 //
564 }
565 }
566
567 //
568 // Raise the verify / error if neccessary.
569 //
570
571 if (ForceVerify || DevMarkedForVerify || !NT_SUCCESS( Status)) {
572
573 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
574 Vcb->Vpb->RealDevice );
575
576 CdRaiseStatus( IrpContext, (ForceVerify || DevMarkedForVerify)
578 : Status);
579 }
580
581 //
582 // Based on the condition of the Vcb we'll either return to our
583 // caller or raise an error condition
584 //
585
586 switch (Vcb->VcbCondition) {
587
588 case VcbNotMounted:
589
590 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, Vcb->Vpb->RealDevice );
591
592 CdRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
593 break;
594
595 case VcbInvalid:
597
598 if (FlagOn( Vcb->VcbState, VCB_STATE_DISMOUNTED )) {
599
601
602 } else {
603
604 CdRaiseStatus( IrpContext, STATUS_FILE_INVALID );
605 }
606 break;
607
608 /* ReactOS Change: GCC "enumeration value not handled in switch" */
609 default: break;
610 }
611}
612
613
616 _In_opt_ PIRP_CONTEXT IrpContext,
618 )
619
620/*++
621
622Routine Description:
623
624 This routine is called to verify that the state of the Fcb is valid
625 to allow the current operation to continue. We use the state of the
626 Vcb, target device and type of operation to determine this.
627
628Arguments:
629
630 IrpContext - IrpContext for the request. If not present then we
631 were called from the fast IO path.
632
633 Fcb - Fcb to perform the request on.
634
635Return Value:
636
637 BOOLEAN - TRUE if the request can continue, FALSE otherwise.
638
639--*/
640
641{
642 PVCB Vcb = Fcb->Vcb;
643 PDEVICE_OBJECT RealDevice = Vcb->Vpb->RealDevice;
644 PIRP Irp;
645
646 PAGED_CODE();
647
648 //
649 // Check that the fileobject has not been cleaned up.
650 //
651
652 if ( ARGUMENT_PRESENT( IrpContext )) {
653
655
656 Irp = IrpContext->Irp;
658
660
662
663 //
664 // Following FAT, we allow certain operations even on cleaned up
665 // file objects. Everything else, we fail.
666 //
667
668 if ( (FlagOn(Irp->Flags, IRP_PAGING_IO)) ||
673
674 NOTHING;
675
676 } else {
677
678 CdRaiseStatus( IrpContext, STATUS_FILE_CLOSED );
679 }
680 }
681 }
682
683 //
684 // Fail immediately if the volume is in the progress of being dismounted
685 // or has been marked invalid.
686 //
687
688 if ((Vcb->VcbCondition == VcbInvalid) ||
689 (Vcb->VcbCondition == VcbDismountInProgress)) {
690
691 if (ARGUMENT_PRESENT( IrpContext )) {
692
693 if (FlagOn( Vcb->VcbState, VCB_STATE_DISMOUNTED )) {
694
696
697 } else {
698
699 CdRaiseStatus( IrpContext, STATUS_FILE_INVALID );
700 }
701 }
702
703 return FALSE;
704 }
705
706 //
707 // Always fail if the volume needs to be verified.
708 //
709
710 if (CdRealDevNeedsVerify( RealDevice)) {
711
712 if (ARGUMENT_PRESENT( IrpContext )) {
713
714 IoSetHardErrorOrVerifyDevice( IrpContext->Irp,
715 RealDevice );
716
718 }
719
720 return FALSE;
721
722 //
723 //
724 // All operations are allowed on mounted.
725 //
726
727 } else if ((Vcb->VcbCondition == VcbMounted) ||
728 (Vcb->VcbCondition == VcbMountInProgress)) {
729
730 return TRUE;
731
732 //
733 // Fail all requests for fast Io on other Vcb conditions.
734 //
735
736 } else if (!ARGUMENT_PRESENT( IrpContext )) {
737
738 return FALSE;
739
740 //
741 // The remaining case is VcbNotMounted.
742 // Mark the device to be verified and raise WRONG_VOLUME.
743 //
744
745 } else if (Vcb->VcbCondition == VcbNotMounted) {
746
747 IoSetHardErrorOrVerifyDevice( IrpContext->Irp, RealDevice );
748 CdRaiseStatus( IrpContext, STATUS_WRONG_VOLUME );
749
750// return FALSE; // unreachable code
751 }
752
753 return TRUE;
754}
755
756
757
758_Requires_lock_held_(_Global_critical_region_)
760CdDismountVcb (
761 _In_ PIRP_CONTEXT IrpContext,
763 )
764
765/*++
766
767Routine Description:
768
769 This routine is called when all of the user references to a volume are
770 gone. We will initiate all of the teardown any system resources.
771
772 If all of the references to this volume are gone at the end of this routine
773 then we will complete the teardown of this Vcb and mark the current Vpb
774 as not mounted. Otherwise we will allocated a new Vpb for this device
775 and keep the current Vpb attached to the Vcb.
776
777Arguments:
778
779 Vcb - Vcb for the volume to dismount.
780
781Return Value:
782
783 BOOLEAN - TRUE if we didn't delete the Vcb, FALSE otherwise.
784
785--*/
786
787{
788 PVPB OldVpb;
789 BOOLEAN VcbPresent = TRUE;
790 KIRQL SavedIrql;
791
792 BOOLEAN FinalReference;
793
796
797 CdLockVcb( IrpContext, Vcb );
798
799 //
800 // We should only take this path once.
801 //
802
803 NT_ASSERT( Vcb->VcbCondition != VcbDismountInProgress );
804
805 //
806 // Mark the Vcb as DismountInProgress.
807 //
808
809 Vcb->VcbCondition = VcbDismountInProgress;
810
811 if (Vcb->XASector != NULL) {
812
813 CdFreePool( &Vcb->XASector );
814 Vcb->XASector = 0;
815 Vcb->XADiskOffset = 0;
816 }
817
818 //
819 // Remove our reference to the internal Fcb's. The Fcb's will then
820 // be removed in the purge path below.
821 //
822
823 if (Vcb->RootIndexFcb != NULL) {
824
825 Vcb->RootIndexFcb->FcbReference -= 1;
826 Vcb->RootIndexFcb->FcbUserReference -= 1;
827 }
828
829 if (Vcb->PathTableFcb != NULL) {
830
831 Vcb->PathTableFcb->FcbReference -= 1;
832 Vcb->PathTableFcb->FcbUserReference -= 1;
833 }
834
835 if (Vcb->VolumeDasdFcb != NULL) {
836
837 Vcb->VolumeDasdFcb->FcbReference -= 1;
838 Vcb->VolumeDasdFcb->FcbUserReference -= 1;
839 }
840
841 CdUnlockVcb( IrpContext, Vcb );
842
843 //
844 // Purge the volume.
845 //
846
847 CdPurgeVolume( IrpContext, Vcb, TRUE );
848
849 //
850 // Empty the delayed and async close queues.
851 //
852
853 CdFspClose( Vcb );
854
855 OldVpb = Vcb->Vpb;
856
857 //
858 // Remove the mount volume reference.
859 //
860
861 CdLockVcb( IrpContext, Vcb );
862 Vcb->VcbReference -= 1;
863
864 //
865 // Acquire the Vpb spinlock to check for Vpb references.
866 //
867
868 IoAcquireVpbSpinLock( &SavedIrql );
869
870 //
871 // Remember if this is the last reference on this Vcb. We incremented
872 // the count on the Vpb earlier so we get one last crack it. If our
873 // reference has gone to zero but the vpb reference count is greater
874 // than zero then the Io system will be responsible for deleting the
875 // Vpb.
876 //
877
878 FinalReference = (BOOLEAN) ((Vcb->VcbReference == 0) &&
879 (OldVpb->ReferenceCount == 1));
880
881 //
882 // There is a reference count in the Vpb and in the Vcb. We have
883 // incremented the reference count in the Vpb to make sure that
884 // we have last crack at it. If this is a failed mount then we
885 // want to return the Vpb to the IO system to use for the next
886 // mount request.
887 //
888
889#ifdef _MSC_VER
890#pragma prefast(suppress: 28175, "this is a filesystem driver, touching the vpb is allowed")
891#endif
892 if (OldVpb->RealDevice->Vpb == OldVpb) {
893
894 //
895 // If not the final reference then swap out the Vpb. We must
896 // preserve the REMOVE_PENDING flag so that the device is
897 // not remounted in the middle of a PnP remove operation.
898 //
899
900 if (!FinalReference) {
901
902 NT_ASSERT( Vcb->SwapVpb != NULL );
903
904 Vcb->SwapVpb->Type = IO_TYPE_VPB;
905 Vcb->SwapVpb->Size = sizeof( VPB );
906
907#ifdef _MSC_VER
908#pragma prefast(push)
909#pragma prefast(disable: 28175, "this is a filesystem driver, touching the vpb is allowed")
910#endif
911 Vcb->SwapVpb->RealDevice = OldVpb->RealDevice;
912 Vcb->SwapVpb->RealDevice->Vpb = Vcb->SwapVpb;
913#ifdef _MSC_VER
914#pragma prefast(pop)
915#endif
916
917 Vcb->SwapVpb->Flags = FlagOn( OldVpb->Flags, VPB_REMOVE_PENDING );
918
919 IoReleaseVpbSpinLock( SavedIrql );
920
921 //
922 // Indicate we used up the swap.
923 //
924
925 Vcb->SwapVpb = NULL;
926
927 CdUnlockVcb( IrpContext, Vcb );
928
929 //
930 // We want to leave the Vpb for the IO system. Mark it
931 // as being not mounted. Go ahead and delete the Vcb as
932 // well.
933 //
934
935 } else {
936
937 //
938 // Make sure to remove the last reference on the Vpb.
939 //
940
941 OldVpb->ReferenceCount -= 1;
942
943 OldVpb->DeviceObject = NULL;
944 ClearFlag( Vcb->Vpb->Flags, VPB_MOUNTED );
945 ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED );
946
947 //
948 // Clear the Vpb flag so we know not to delete it.
949 //
950
951 Vcb->Vpb = NULL;
952
953 IoReleaseVpbSpinLock( SavedIrql );
954 CdUnlockVcb( IrpContext, Vcb );
955 CdDeleteVcb( IrpContext, Vcb );
956 VcbPresent = FALSE;
957 }
958
959 //
960 // Someone has already swapped in a new Vpb. If this is the final reference
961 // then the file system is responsible for deleting the Vpb.
962 //
963
964 } else if (FinalReference) {
965
966 //
967 // Make sure to remove the last reference on the Vpb.
968 //
969
970 OldVpb->ReferenceCount -= 1;
971
972 IoReleaseVpbSpinLock( SavedIrql );
973 CdUnlockVcb( IrpContext, Vcb );
974 CdDeleteVcb( IrpContext, Vcb );
975 VcbPresent = FALSE;
976
977 //
978 // The current Vpb is no longer the Vpb for the device (the IO system
979 // has already allocated a new one). We leave our reference in the
980 // Vpb and will be responsible for deleting it at a later time.
981 //
982
983 } else {
984
985 IoReleaseVpbSpinLock( SavedIrql );
986 CdUnlockVcb( IrpContext, Vcb );
987 }
988
989 //
990 // Let our caller know whether the Vcb is still present.
991 //
992
993 return VcbPresent;
994}
995
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
LONG CdExceptionFilter(_Inout_ PIRP_CONTEXT IrpContext, _In_ PEXCEPTION_POINTERS ExceptionPointer)
Definition: cddata.c:525
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
#define CDFS_RESIDUAL_REFERENCE
Definition: cddata.h:43
#define ASSERT_EXCLUSIVE_CDDATA
Definition: cddata.h:257
#define ASSERT_IRP(I)
Definition: cddata.h:250
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:248
#define ASSERT_EXCLUSIVE_VCB(V)
Definition: cddata.h:258
#define ASSERT_VCB(V)
Definition: cddata.h:241
BOOLEAN CdMarkDevForVerifyIfVcbMounted(_Inout_ PVCB Vcb)
Definition: verfysup.c:359
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define CdAcquireCdData(IC)
Definition: cdprocs.h:973
VOID CdFspClose(_In_opt_ PVCB Vcb)
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
static INLINE BOOLEAN CdOperationIsDasdOpen(_In_ PIRP_CONTEXT IrpContext)
Definition: cdprocs.h:1392
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:985
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1023
#define CdRealDevNeedsVerify(DO)
Definition: cdprocs.h:1456
#define CdReleaseCdData(IC)
Definition: cdprocs.h:976
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:982
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1028
VOID CdDeleteVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: strucsup.c:876
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:979
_Inout_ PIRP _In_ PDEVICE_OBJECT DeviceToVerify
Definition: cdprocs.h:1409
#define CdMarkRealDevForVerify(DO)
Definition: cdprocs.h:1451
#define CdNormalizeAndRaiseStatus(IC, S)
Definition: cdprocs.h:1860
NTSTATUS FASTCALL CdPerformDevIoCtrl(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT Device, _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _In_ BOOLEAN OverrideVerify, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: deviosup.c:1446
#define CdFreePool(x)
Definition: cdprocs.h:2190
#define CdIsRawDevice(IC, S)
Definition: cdprocs.h:1466
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1859
#define VCB_STATE_REMOVABLE_MEDIA
Definition: cdstruc.h:710
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:714
#define VCB_STATE_DISMOUNTED
Definition: cdstruc.h:716
@ VcbMounted
Definition: cdstruc.h:492
@ VcbMountInProgress
Definition: cdstruc.h:491
@ VcbNotMounted
Definition: cdstruc.h:490
@ VcbDismountInProgress
Definition: cdstruc.h:494
@ VcbInvalid
Definition: cdstruc.h:493
#define _Analysis_assume_lock_not_held_(lock)
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#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:33
#define Marked(f)
Definition: render.c:146
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
return Iosb
Definition: create.c:4402
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
Status
Definition: gdiplustypes.h:25
#define NOTHING
Definition: input_list.c:10
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:103
#define ARGUMENT_PRESENT(ArgumentPointer)
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
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_FILE_INVALID
Definition: ntstatus.h:388
#define BOOLEAN
Definition: pedump.c:73
#define Vcb
Definition: cdprocs.h:1415
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
Definition: cdstruc.h:498
Definition: iotypes.h:189
struct _DEVICE_OBJECT * DeviceObject
Definition: iotypes.h:194
USHORT Flags
Definition: iotypes.h:192
ULONG ReferenceCount
Definition: iotypes.h:197
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:195
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_TYPE_VPB
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_PAGING_IO
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4405
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
struct _VPB VPB
* PFILE_OBJECT
Definition: iotypes.h:1998
#define VPB_LOCKED
Definition: iotypes.h:1808
#define IO_REMOUNT
Definition: iotypes.h:544
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4404
#define NT_ASSERT
Definition: rtlfuncs.h:3327