windows-nt/Source/XPSP1/NT/base/ntos/raw/strucsup.c
2020-09-26 16:20:57 +08:00

232 lines
5 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
BOOLEAN DeleteVolume = FALSE;
//
// We must enter with the vcb mutex acquired
//
ASSERT( KeReadStateMutant( &Vcb->Mutex ) == 0 );
IoAcquireVpbSpinLock( &SavedIrql );
{
PVPB Vpb;
Vpb = Vcb->Vpb;
//
// If a create is in progress on this volume, don't
// delete it.
//
if ( Vcb->Vpb->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
//
if (Vcb->SpareVpb) {
ExFreePool( Vcb->SpareVpb );
} else {
ExFreePool( Vcb->Vpb );
}
ObDereferenceObject( Vcb->TargetDeviceObject );
IoDeleteDevice( (PDEVICE_OBJECT)CONTAINING_RECORD( Vcb,
VOLUME_DEVICE_OBJECT,
Vcb));
}
return DeleteVolume;
}