Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

231 lines
5.0 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. StrucSup.c
  5. Abstract:
  6. This module implements the Raw in-memory data structure manipulation
  7. routines
  8. Author:
  9. David Goebel [DavidGoe] 18-Mar-91
  10. Revision History:
  11. --*/
  12. #include "RawProcs.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, RawInitializeVcb)
  15. #endif
  16. NTSTATUS
  17. RawInitializeVcb (
  18. IN OUT PVCB Vcb,
  19. IN PDEVICE_OBJECT TargetDeviceObject,
  20. IN PVPB Vpb
  21. )
  22. /*++
  23. Routine Description:
  24. This routine initializes and inserts a new Vcb record into the in-memory
  25. data structure. The Vcb record "hangs" off the end of the Volume device
  26. object and must be allocated by our caller.
  27. Arguments:
  28. Vcb - Supplies the address of the Vcb record being initialized.
  29. TargetDeviceObject - Supplies the address of the target device object to
  30. associate with the Vcb record.
  31. Vpb - Supplies the address of the Vpb to associate with the Vcb record.
  32. Return Value:
  33. NTSTATUS for any errors
  34. --*/
  35. {
  36. NTSTATUS Status = STATUS_SUCCESS;
  37. PAGED_CODE();
  38. //
  39. // We start by first zeroing out all of the VCB, this will guarantee
  40. // that any stale data is wiped clean
  41. //
  42. RtlZeroMemory( Vcb, sizeof(VCB) );
  43. //
  44. // Set the proper node type code and node byte size
  45. //
  46. Vcb->NodeTypeCode = RAW_NTC_VCB;
  47. Vcb->NodeByteSize = sizeof(VCB);
  48. //
  49. // Set the Target Device Object, Vpb, and Vcb State fields
  50. //
  51. //
  52. // No need to take a extra reference on the Target Device object as
  53. // IopMountVolume already has taken a reference.
  54. //
  55. Vcb->TargetDeviceObject = TargetDeviceObject;
  56. Vcb->Vpb = Vpb;
  57. //
  58. // Initialize the Mutex.
  59. //
  60. KeInitializeMutex( &Vcb->Mutex, MUTEX_LEVEL_FILESYSTEM_RAW_VCB );
  61. //
  62. // allocate the spare vpb for forced dismount
  63. //
  64. Vcb->SpareVpb = ExAllocatePoolWithTag( NonPagedPool, sizeof( VPB ), 'Raw ');
  65. if (Vcb->SpareVpb == NULL) {
  66. Status = STATUS_INSUFFICIENT_RESOURCES;
  67. }
  68. //
  69. // and return to our caller
  70. //
  71. return Status;
  72. }
  73. BOOLEAN
  74. RawCheckForDismount (
  75. PVCB Vcb,
  76. BOOLEAN CalledFromCreate
  77. )
  78. /*++
  79. Routine Description:
  80. This routine determines if a volume is ready for deletion. It
  81. correctly synchronizes with creates en-route to the file system.
  82. On exit if the vcb is deleted the mutex is released
  83. Arguments:
  84. Vcb - Supplies the volue to examine
  85. CalledFromCreate - Tells us if we should allow 0 or 1 in VpbRefCount
  86. Return Value:
  87. BOOLEAN - TRUE if the volume was deleted, FALSE otherwise.
  88. --*/
  89. {
  90. KIRQL SavedIrql;
  91. BOOLEAN DeleteVolume = FALSE;
  92. //
  93. // We must enter with the vcb mutex acquired
  94. //
  95. ASSERT( KeReadStateMutant( &Vcb->Mutex ) == 0 );
  96. IoAcquireVpbSpinLock( &SavedIrql );
  97. {
  98. PVPB Vpb;
  99. Vpb = Vcb->Vpb;
  100. //
  101. // If a create is in progress on this volume, don't
  102. // delete it.
  103. //
  104. if ( Vcb->Vpb->ReferenceCount != (ULONG)(CalledFromCreate ? 1 : 0) ) {
  105. //
  106. // Cleanup the vpb on a forced dismount even if we can't delete the vcb if
  107. // we haven't already done so
  108. //
  109. if ((Vcb->SpareVpb != NULL) &&
  110. FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNTED )) {
  111. //
  112. // Setup the spare vpb and put it on the real device
  113. //
  114. RtlZeroMemory( Vcb->SpareVpb, sizeof( VPB ) );
  115. Vcb->SpareVpb->Type = IO_TYPE_VPB;
  116. Vcb->SpareVpb->Size = sizeof( VPB );
  117. Vcb->SpareVpb->RealDevice = Vcb->Vpb->RealDevice;
  118. Vcb->SpareVpb->DeviceObject = NULL;
  119. Vcb->SpareVpb->Flags = FlagOn( Vcb->Vpb->Flags, VPB_REMOVE_PENDING );
  120. Vcb->Vpb->RealDevice->Vpb = Vcb->SpareVpb;
  121. //
  122. // The spare vpb now belongs to the iosubsys and we own the original one
  123. //
  124. Vcb->SpareVpb = NULL;
  125. Vcb->Vpb->Flags |= VPB_PERSISTENT;
  126. }
  127. DeleteVolume = FALSE;
  128. } else {
  129. DeleteVolume = TRUE;
  130. if ( Vpb->RealDevice->Vpb == Vpb ) {
  131. Vpb->DeviceObject = NULL;
  132. Vpb->Flags &= ~VPB_MOUNTED;
  133. }
  134. }
  135. }
  136. IoReleaseVpbSpinLock( SavedIrql );
  137. if (DeleteVolume) {
  138. (VOID)KeReleaseMutex( &Vcb->Mutex, FALSE );
  139. //
  140. // Free the spare vpb if we didn't use it or the original one if we did use it
  141. //
  142. if (Vcb->SpareVpb) {
  143. ExFreePool( Vcb->SpareVpb );
  144. } else {
  145. ExFreePool( Vcb->Vpb );
  146. }
  147. ObDereferenceObject( Vcb->TargetDeviceObject );
  148. IoDeleteDevice( (PDEVICE_OBJECT)CONTAINING_RECORD( Vcb,
  149. VOLUME_DEVICE_OBJECT,
  150. Vcb));
  151. }
  152. return DeleteVolume;
  153. }