📄 volume.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// Volume.cpp
//
// Implementation of class Volume.
//////////////////////////////////////////////////////////////////////////////
// $Id: Volume.cpp,v 1.4 1999/03/31 23:51:08 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#define __w64
#include <vdw.h>
#include "Required.h"
#include "UtilityFunctions.h"
#include "CPGPdiskDriver.h"
#include "Globals.h"
#include "KernelModeUtils.h"
#include "PGPdiskRequestQueue.h"
#include "Volume.h"
///////////////////////////////////////
// Class Volume public member functions
///////////////////////////////////////
// The Class Volume constructor.
Volume::Volume()
{
mDevExtInfo = (PGPUInt32) this;
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = kInvalidDrive;
mAttachedToLocalVol = FALSE;
mDeviceObject = NULL;
mVHDeviceObject = NULL;
mVHFileObject = NULL;
mVolumeHandle = NULL;
}
// The Volume destructor unmounted the volume if was mounted by us.
Volume::~Volume()
{
DualErr derr;
if (Mounted())
{
if (AttachedToLocalVolume())
{
DetachLocalVolume();
}
else
{
derr = Unmount();
pgpAssert(derr.IsntError());
}
}
}
// Mounted returns TRUE if the volume is mounted, FALSE if not.
PGPBoolean
Volume::Mounted()
{
return (mMountState == kVol_Mounted);
}
// Unmounted returns TRUE if the volume is unmounted, FALSE if not.
PGPBoolean
Volume::Unmounted()
{
return (mMountState == kVol_Unmounted);
}
// HasOpenFiles returns TRUE if the volume has open files, FALSE otherwise.
PGPBoolean
Volume::HasOpenFiles()
{
DualErr derr;
pgpAssert(Mounted());
// If lock fails, then the volume has open files.
derr = LockVolumeForReadWrite();
if (LockedForReadWrite())
UnlockVolume();
return derr.IsError();
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// read/write access, FALSE otherwise.
PGPBoolean
Volume::LockedForReadWrite()
{
return (Mounted() && (mLockState == kLock_ReadWrite));
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// format access, FALSE otherwise.
PGPBoolean
Volume::LockedForFormat()
{
return (Mounted() && (mLockState == kLock_Format));
}
// AttachedToLocalVolume returns TRUE if the Volume object is attached to a
// local volume, FALSE if not.
PGPBoolean
Volume::AttachedToLocalVolume()
{
return mAttachedToLocalVol;
}
// GetDrive returns the drive number of the volume.
PGPUInt8
Volume::GetDrive()
{
pgpAssert(Mounted());
return mDrive;
}
// GetBlockSize returns the block size of the volume.
PGPUInt16
Volume::GetBlockSize()
{
DualErr derr;
pgpAssert(Mounted());
derr = GetDriveGeometry();
if (derr.IsntError())
return (PGPUInt16) mGeometry.BytesPerSector;
else
return kDefaultBlockSize;
}
// GetTotalBlocks returns the total number of blocks on the volume.
PGPUInt64
Volume::GetTotalBlocks()
{
DualErr derr;
pgpAssert(Mounted());
derr = GetDriveGeometry();
if (derr.IsntError())
{
return (mGeometry.Cylinders.QuadPart * mGeometry.TracksPerCylinder *
mGeometry.SectorsPerTrack);
}
else
{
return 0;
}
}
// GetDeviceObject returns the device object associated with the volume.
PDEVICE_OBJECT
Volume::GetDeviceObject()
{
pgpAssert(Mounted());
return mDeviceObject;
}
// AttachLocalVolume initializes this Volume object for access to an already
// mounted volume on the local computer.
DualErr
Volume::AttachLocalVolume(PGPUInt8 drive)
{
DualErr derr;
pgpAssert(IsLegalDriveNumber(drive));
pgpAssert(!Mounted());
pgpAssert(!AttachedToLocalVolume());
if (LockedForReadWrite() || LockedForFormat())
UnlockVolume();
mMountState = kVol_Mounted;
mLockState = kLock_None;
mDrive = drive;
mAttachedToLocalVol = TRUE;
return derr;
}
// DetachLocalVolume marks this Volume object as no longer being associated
// with a local volume.
void
Volume::DetachLocalVolume()
{
pgpAssert(Mounted());
pgpAssert(AttachedToLocalVolume());
if (VolumeHandleOpened())
CloseVolumeHandle();
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = kInvalidDrive;
mAttachedToLocalVol = FALSE;
}
// Mount creates a device and links it to the specified drive letter.
DualErr
Volume::Mount(LPCSTR deviceName, PGPUInt8 drive, PGPBoolean mountReadOnly)
{
DualErr derr;
KUstring uniDeviceName, drivePath;
NTSTATUS status;
PGPBoolean createdDevice, foundDrive;
PGPUInt8 i;
pgpAssertStrValid(deviceName);
pgpAssert(Unmounted());
pgpAssert(!AttachedToLocalVolume());
createdDevice = foundDrive = FALSE;
// If preferred drive letter is specified, is it available?
if (IsLegalDriveNumber(drive))
{
derr = MakePathToDrive(drive, &drivePath);
if (derr.IsntError())
{
foundDrive = !IsValidDeviceName(drivePath);
}
}
// Find a drive letter we can use.
if (derr.IsntError() && !foundDrive)
{
for (i = 2; i < kMaxDrives; i++)
{
derr = MakePathToDrive(i, &drivePath);
if (derr.IsntError())
{
if (!IsValidDeviceName(drivePath))
{
foundDrive = TRUE;
drive = i;
break;
}
}
if (derr.IsError())
break;
}
}
// Die if no free drive found.
if (derr.IsntError())
{
if (!foundDrive)
derr = DualErr(kPGDMinorError_NoDriveLettersFree);
}
// Prepare device name.
if (derr.IsntError())
{
derr = AssignToUni(&uniDeviceName, deviceName);
}
// Prepend device prefix.
if (derr.IsntError())
{
derr = PrependToUni(&uniDeviceName, kNTDevicePathPrefix);
}
// Append driver letter.
if (derr.IsntError())
{
char driveLet[2];
driveLet[0] = DriveNumToLet(drive);
driveLet[1] = '\0';
derr = AppendToUni(&uniDeviceName, driveLet);
}
// Create a new device object.
if (derr.IsntError())
{
PGPUInt32 attribs = FILE_VIRTUAL_VOLUME;
if (mountReadOnly)
attribs |= FILE_READ_ONLY_DEVICE;
status = IoCreateDevice(Interface->mPGPdiskDriver->DriverObject(),
0, uniDeviceName, FILE_DEVICE_DISK, attribs, FALSE,
&mDeviceObject);
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoCreateDeviceFailed, status);
createdDevice = derr.IsntError();
}
// Assign the link name.
if (derr.IsntError())
{
derr = AssignToUni(&mLinkName, drivePath);
}
// Create the link.
if (derr.IsntError())
{
mDeviceObject->Flags |= DO_DIRECT_IO;
mDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
mDeviceObject->DeviceExtension = (void *) mDevExtInfo;
status = IoCreateSymbolicLink(mLinkName, uniDeviceName);
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoCreateSymbolicLinkFailed, status);
}
// Initialize variables on success.
if (derr.IsntError())
{
mMountState = kVol_Mounted;
mLockState = kLock_None;
mDrive = drive;
mAttachedToLocalVol = FALSE;
}
// Cleanup on error.
if (derr.IsError())
{
if (createdDevice)
{
IoDeleteDevice(mDeviceObject);
mDeviceObject = NULL;
}
}
return derr;
}
// Unmount unmounts a mounted Volume.
DualErr
Volume::Unmount(PGPBoolean isThisEmergency)
{
DualErr derr;
NTSTATUS status;
pgpAssert(Mounted());
pgpAssert(!AttachedToLocalVolume());
if (LockedForReadWrite() || LockedForFormat())
UnlockVolume();
// Lock the volume.
derr = LockVolumeForReadWrite();
// Dismount the volume.
if (derr.IsntError())
{
derr = SendUserFSCTLRequest(FSCTL_DISMOUNT_VOLUME);
}
if (isThisEmergency)
derr = DualErr::NoError;
// Delete the symbolic link.
if (derr.IsntError())
{
status = IoDeleteSymbolicLink(mLinkName);
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoDeleteSymbolicLinkFailed, status);
if (isThisEmergency)
derr = DualErr::NoError;
}
// Delete the device object and finish up.
if (derr.IsntError())
{
if (!isThisEmergency || (isThisEmergency && LockedForReadWrite()))
UnlockVolume();
mDeviceObject->DeviceExtension = NULL;
IoDeleteDevice(mDeviceObject);
mDeviceObject = NULL;
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = kInvalidDrive;
}
if (derr.IsError())
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -