ReactOS  0.4.13-dev-482-ge57f103
verfysup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  VerfySup.c
8 
9 Abstract:
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_)
31 CdPerformVerify (
32  _Inout_ PIRP_CONTEXT IrpContext,
35  )
36 
37 /*++
38 
39 Routine 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 
47 Arguments:
48 
49  Irp - The irp to send off after all is well and done.
50 
51  Device - The real device needing verification.
52 
53 Return 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 
192  if (IoIsErrorUserInduced( Status ) ) {
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_)
226 BOOLEAN
227 CdCheckForDismount (
228  _In_ PIRP_CONTEXT IrpContext,
229  _Inout_ PVCB Vcb,
231  )
232 
233 /*++
234 
235 Routine 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 
248 Arguments:
249 
250  Vcb - Vcb for the volume to try to dismount.
251 
252  Force - Whether we will force this volume to be dismounted.
253 
254 Return 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 {
351  _Analysis_assume_lock_not_held_(Vcb->VcbResource);
352  }
353 
354  return VcbPresent;
355 }
356 
357 
358 BOOLEAN
361  )
362 
363 /*++
364 
365 Routine 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 
371 Arguments:
372 
373  Vcb - This is the volume to check.
374 
375 Return Value:
376 
377  TRUE if the device has been marked for verify here, FALSE otherwise.
378 
379 --*/
380 
381 {
382  BOOLEAN Marked = FALSE;
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 
410 VOID
412  _In_ PIRP_CONTEXT IrpContext,
414  )
415 
416 /*++
417 
418 Routine 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 
426 Arguments:
427 
428  Vcb - This is the volume to verify.
429 
430 Return 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 
614 BOOLEAN
616  _In_opt_ PIRP_CONTEXT IrpContext,
617  _In_ PFCB Fcb
618  )
619 
620 /*++
621 
622 Routine 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 
628 Arguments:
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 
635 Return 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 
659  if ( FileObject && FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE)) {
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)) ||
671  ( (IrpSp->MajorFunction == IRP_MJ_READ) &&
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 
717  CdRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED );
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_)
759 BOOLEAN
760 CdDismountVcb (
761  _In_ PIRP_CONTEXT IrpContext,
763  )
764 
765 /*++
766 
767 Routine 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 
777 Arguments:
778 
779  Vcb - Vcb for the volume to dismount.
780 
781 Return 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 
#define ASSERT_EXCLUSIVE_CDDATA
Definition: cddata.h:258
#define TRUE
Definition: types.h:120
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define CdAcquireVcbShared(IC, V, I)
Definition: cdprocs.h:987
static INLINE BOOLEAN CdOperationIsDasdOpen(_In_ PIRP_CONTEXT IrpContext)
Definition: cdprocs.h:1402
USHORT Flags
Definition: iotypes.h:169
#define ASSERT_VCB(V)
Definition: cddata.h:241
_In_ PIRP Irp
Definition: csq.h:116
#define CDFS_RESIDUAL_USER_REFERENCE
Definition: cddata.h:44
Definition: cdstruc.h:908
#define IOCTL_CDROM_CHECK_VERIFY
Definition: ntddcdrm.h:34
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
LONG NTSTATUS
Definition: precomp.h:26
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
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1209
Definition: cdstruc.h:504
#define STATUS_FILE_INVALID
Definition: ntstatus.h:374
#define STATUS_WRONG_VOLUME
Definition: udferr_usr.h:140
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define PAGED_CODE()
Definition: video.h:57
#define _In_opt_
Definition: no_sal2.h:213
VOID CdFspClose(_In_opt_ PVCB Vcb)
#define Marked(f)
Definition: render.c:146
_SEH2_TRY
Definition: create.c:4250
#define IRP_MN_COMPLETE
Definition: iotypes.h:4063
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4048
#define CdIsRawDevice(IC, S)
Definition: cdprocs.h:1476
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
#define CdMarkRealDevForVerify(DO)
Definition: cdprocs.h:1461
#define CdRealDevNeedsVerify(DO)
Definition: cdprocs.h:1466
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
ULONG ReferenceCount
Definition: iotypes.h:174
#define VPB_LOCKED
Definition: iotypes.h:1764
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
struct _DEVICE_OBJECT * DeviceObject
Definition: iotypes.h:171
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define CdAcquireVcbExclusive(IC, V, I)
Definition: cdprocs.h:984
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4047
return Iosb
Definition: create.c:4426
#define CdReleaseVcb(IC, V)
Definition: cdprocs.h:990
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1033
#define ARGUMENT_PRESENT(ArgumentPointer)
#define IRP_MJ_FILE_SYSTEM_CONTROL
struct _DEVICE_OBJECT * RealDevice
Definition: iotypes.h:172
#define Vcb
Definition: cdprocs.h:1425
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2866
#define _Inout_
Definition: no_sal2.h:244
#define CDFS_RESIDUAL_REFERENCE
Definition: cddata.h:43
BOOLEAN CdMarkDevForVerifyIfVcbMounted(_Inout_ PVCB Vcb)
Definition: verfysup.c:359
* PFILE_OBJECT
Definition: iotypes.h:1954
BOOLEAN CdVerifyFcbOperation(_In_opt_ PIRP_CONTEXT IrpContext, _In_ PFCB Fcb)
Definition: verfysup.c:615
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1028
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define CdAcquireCdData(IC)
Definition: cdprocs.h:978
#define IO_TYPE_VPB
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
struct _VPB VPB
Status
Definition: gdiplustypes.h:24
#define ASSERT_IRP(I)
Definition: cddata.h:251
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_SEH2_END
Definition: create.c:4424
#define CdFreePool(x)
Definition: cdprocs.h:2200
#define VCB_STATE_REMOVABLE_MEDIA
Definition: cdstruc.h:716
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1746
LONG CdExceptionFilter(_Inout_ PIRP_CONTEXT IrpContext, _In_ PEXCEPTION_POINTERS ExceptionPointer)
Definition: cddata.c:525
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define STATUS_REPARSE
Definition: ntstatus.h:83
#define CdReleaseCdData(IC)
Definition: cdprocs.h:981
#define IRP_PAGING_IO
#define IRP_MJ_READ
Definition: rdpdr.c:46
Definition: iotypes.h:166
#define BOOLEAN
Definition: pedump.c:73
#define ASSERT_EXCLUSIVE_VCB(V)
Definition: cddata.h:259
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:733
VOID CdDeleteVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: strucsup.c:876
unsigned int ULONG
Definition: retypes.h:1
PVCB Vcb
Definition: cdstruc.h:939
#define CdNormalizeAndRaiseStatus(IC, S)
Definition: cdprocs.h:1870
#define _Analysis_assume_lock_not_held_(lock)
Definition: no_sal2.h:683
VOID NTAPI IoSetHardErrorOrVerifyDevice(IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:316
#define VCB_STATE_VPB_NOT_ON_DEVICE
Definition: cdstruc.h:720
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
_Requires_lock_held_(_Global_critical_region_)
Definition: verfysup.c:29
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define IO_REMOUNT
Definition: iotypes.h:511
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2777
#define VPB_MOUNTED
Definition: iotypes.h:1763
NTSTATUS NTAPI IoVerifyVolume(IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN AllowRawMount)
Definition: volume.c:882
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1220
_Inout_ PIRP _In_ PDEVICE_OBJECT DeviceToVerify
Definition: cdprocs.h:1417
#define VCB_STATE_DISMOUNTED
Definition: cdstruc.h:722
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1425
#define NT_ASSERT
Definition: rtlfuncs.h:3312
#define STATUS_FILE_CLOSED
Definition: ntstatus.h:518
VOID CdVerifyVcb(_In_ PIRP_CONTEXT IrpContext, _Inout_ PVCB Vcb)
Definition: verfysup.c:411