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.
237 lines
5.4 KiB
237 lines
5.4 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
StrucSup.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the Raw in-memory data structure manipulation
|
|
routines
|
|
|
|
Author:
|
|
|
|
David Goebel [DavidGoe] 18-Mar-91
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "RawProcs.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, RawInitializeVcb)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
RawInitializeVcb (
|
|
IN OUT PVCB Vcb,
|
|
IN PDEVICE_OBJECT TargetDeviceObject,
|
|
IN PVPB Vpb
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes and inserts a new Vcb record into the in-memory
|
|
data structure. The Vcb record "hangs" off the end of the Volume device
|
|
object and must be allocated by our caller.
|
|
|
|
Arguments:
|
|
|
|
Vcb - Supplies the address of the Vcb record being initialized.
|
|
|
|
TargetDeviceObject - Supplies the address of the target device object to
|
|
associate with the Vcb record.
|
|
|
|
Vpb - Supplies the address of the Vpb to associate with the Vcb record.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS for any errors
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// We start by first zeroing out all of the VCB, this will guarantee
|
|
// that any stale data is wiped clean
|
|
//
|
|
|
|
RtlZeroMemory( Vcb, sizeof(VCB) );
|
|
|
|
//
|
|
// Set the proper node type code and node byte size
|
|
//
|
|
|
|
Vcb->NodeTypeCode = RAW_NTC_VCB;
|
|
Vcb->NodeByteSize = sizeof(VCB);
|
|
|
|
//
|
|
// Set the Target Device Object, Vpb, and Vcb State fields
|
|
//
|
|
|
|
//
|
|
// No need to take a extra reference on the Target Device object as
|
|
// IopMountVolume already has taken a reference.
|
|
//
|
|
|
|
Vcb->TargetDeviceObject = TargetDeviceObject;
|
|
Vcb->Vpb = Vpb;
|
|
|
|
//
|
|
// Initialize the Mutex.
|
|
//
|
|
|
|
KeInitializeMutex( &Vcb->Mutex, MUTEX_LEVEL_FILESYSTEM_RAW_VCB );
|
|
|
|
//
|
|
// allocate the spare vpb for forced dismount
|
|
//
|
|
|
|
Vcb->SpareVpb = ExAllocatePoolWithTag( NonPagedPool, sizeof( VPB ), 'Raw ');
|
|
if (Vcb->SpareVpb == NULL) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// and return to our caller
|
|
//
|
|
|
|
return Status;
|
|
}
|
|
|
|
BOOLEAN
|
|
RawCheckForDismount (
|
|
PVCB Vcb,
|
|
BOOLEAN CalledFromCreate
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines if a volume is ready for deletion. It
|
|
correctly synchronizes with creates en-route to the file system.
|
|
On exit if the vcb is deleted the mutex is released
|
|
|
|
Arguments:
|
|
|
|
Vcb - Supplies the volue to examine
|
|
|
|
CalledFromCreate - Tells us if we should allow 0 or 1 in VpbRefCount
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if the volume was deleted, FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
KIRQL SavedIrql;
|
|
ULONG ReferenceCount = 0;
|
|
BOOLEAN DeleteVolume = FALSE;
|
|
|
|
//
|
|
// We must enter with the vcb mutex acquired
|
|
//
|
|
|
|
ASSERT( KeReadStateMutant( &Vcb->Mutex ) == 0 );
|
|
|
|
IoAcquireVpbSpinLock( &SavedIrql );
|
|
|
|
ReferenceCount = Vcb->Vpb->ReferenceCount;
|
|
|
|
{
|
|
PVPB Vpb;
|
|
|
|
Vpb = Vcb->Vpb;
|
|
|
|
//
|
|
// If a create is in progress on this volume, don't
|
|
// delete it.
|
|
//
|
|
|
|
if ( ReferenceCount != (ULONG)(CalledFromCreate ? 1 : 0) ) {
|
|
|
|
//
|
|
// Cleanup the vpb on a forced dismount even if we can't delete the vcb if
|
|
// we haven't already done so
|
|
//
|
|
|
|
if ((Vcb->SpareVpb != NULL) &&
|
|
FlagOn( Vcb->VcbState, VCB_STATE_FLAG_DISMOUNTED )) {
|
|
|
|
//
|
|
// Setup the spare vpb and put it on the real device
|
|
//
|
|
|
|
RtlZeroMemory( Vcb->SpareVpb, sizeof( VPB ) );
|
|
|
|
Vcb->SpareVpb->Type = IO_TYPE_VPB;
|
|
Vcb->SpareVpb->Size = sizeof( VPB );
|
|
Vcb->SpareVpb->RealDevice = Vcb->Vpb->RealDevice;
|
|
Vcb->SpareVpb->DeviceObject = NULL;
|
|
Vcb->SpareVpb->Flags = FlagOn( Vcb->Vpb->Flags, VPB_REMOVE_PENDING );
|
|
|
|
Vcb->Vpb->RealDevice->Vpb = Vcb->SpareVpb;
|
|
|
|
//
|
|
// The spare vpb now belongs to the iosubsys and we own the original one
|
|
//
|
|
|
|
Vcb->SpareVpb = NULL;
|
|
Vcb->Vpb->Flags |= VPB_PERSISTENT;
|
|
|
|
}
|
|
|
|
DeleteVolume = FALSE;
|
|
|
|
} else {
|
|
|
|
DeleteVolume = TRUE;
|
|
|
|
if ( Vpb->RealDevice->Vpb == Vpb ) {
|
|
|
|
Vpb->DeviceObject = NULL;
|
|
|
|
Vpb->Flags &= ~VPB_MOUNTED;
|
|
}
|
|
}
|
|
}
|
|
IoReleaseVpbSpinLock( SavedIrql );
|
|
|
|
if (DeleteVolume) {
|
|
|
|
(VOID)KeReleaseMutex( &Vcb->Mutex, FALSE );
|
|
|
|
//
|
|
// Free the spare vpb if we didn't use it or the original one if
|
|
// we did use it and there are no more reference counts. Otherwise i/o
|
|
// subsystem still has a ref and will free the vpb itself
|
|
//
|
|
|
|
if (Vcb->SpareVpb) {
|
|
ExFreePool( Vcb->SpareVpb );
|
|
} else if (ReferenceCount == 0) {
|
|
ExFreePool( Vcb->Vpb );
|
|
}
|
|
|
|
ObDereferenceObject( Vcb->TargetDeviceObject );
|
|
IoDeleteDevice( (PDEVICE_OBJECT)CONTAINING_RECORD( Vcb,
|
|
VOLUME_DEVICE_OBJECT,
|
|
Vcb));
|
|
}
|
|
|
|
return DeleteVolume;
|
|
}
|
|
|