📄 volume.cpp
字号:
{
if (LockedForReadWrite())
UnlockVolume();
}
return derr;
}
// LockVolumeForReadWrite locks the mounted volume for direct read/write
// access.
DualErr
Volume::LockVolumeForReadWrite()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(!LockedForReadWrite() && !LockedForFormat());
derr = OpenVolumeHandle();
if (derr.IsntError())
{
derr = SendUserFSCTLRequest(FSCTL_LOCK_VOLUME);
}
if (derr.IsntError())
{
mLockState = kLock_ReadWrite;
}
if (derr.IsError())
{
if (VolumeHandleOpened())
CloseVolumeHandle();
}
return derr;
}
// LockVolumeForFormat locks the mounted volume for formatting.
DualErr
Volume::LockVolumeForFormat()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(!LockedForReadWrite() && !LockedForFormat());
derr = OpenVolumeHandle();
if (derr.IsntError())
{
derr = SendUserFSCTLRequest(FSCTL_LOCK_VOLUME);
}
if (derr.IsntError())
{
mLockState = kLock_Format;
}
if (derr.IsError())
{
if (VolumeHandleOpened())
CloseVolumeHandle();
}
return derr;
}
// UnlockVolume removes any outstanding locks on the volume;
DualErr
Volume::UnlockVolume()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(LockedForReadWrite() || LockedForFormat());
derr = SendUserFSCTLRequest(FSCTL_UNLOCK_VOLUME);
pgpAssert(derr.IsntError());
if (derr.IsntError())
{
mLockState = kLock_None;
CloseVolumeHandle();
}
return derr;
}
// Read reads 'nBlocks' sectors from the logical mounted volume from sector
// position 'pos'.
DualErr
Volume::Read(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
DualErr derr;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
KIrp pIrp;
LARGE_INTEGER liPos;
NTSTATUS status;
PGPBoolean openedVolHandle = FALSE;
pgpAssertAddrValid(buf, PGPUInt8);
pgpAssert(Mounted());
// Open handle to the volume.
if (!VolumeHandleOpened())
{
derr = OpenVolumeHandle();
openedVolHandle = derr.IsntError();
}
if (derr.IsntError())
{
// Initialize the event.
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Build the request.
liPos.QuadPart = pos * GetBlockSize();
pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, mVHDeviceObject,
buf, nBlocks * GetBlockSize(), &liPos, &event, &ioStatus);
if (IsNull((PIRP) pIrp))
derr = DualErr(kPGDMinorError_IoBuildSynchFsdRequestFailed);
}
// Send the request.
if (derr.IsntError())
{
pIrp.NextStackLocation()->FileObject = mVHFileObject;
status = IoCallDriver(mVHDeviceObject, pIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoCallDriverFailed, status);
}
// Close volume handle.
if (openedVolHandle)
CloseVolumeHandle();
return derr;
}
// Write reads 'nBlocks' sectors from the logical mounted volume from sector
// position 'pos'.
DualErr
Volume::Write(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
DualErr derr;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
KIrp pIrp;
LARGE_INTEGER liPos;
NTSTATUS status;
PGPBoolean openedVolHandle = FALSE;
pgpAssertAddrValid(buf, PGPUInt8);
pgpAssert(Mounted());
// Open handle to the volume.
if (!VolumeHandleOpened())
{
derr = OpenVolumeHandle();
openedVolHandle = derr.IsntError();
}
if (derr.IsntError())
{
// Initialize the event.
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Build the request.
liPos.QuadPart = pos * GetBlockSize();
pIrp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, mVHDeviceObject,
buf, nBlocks * GetBlockSize(), &liPos, &event, &ioStatus);
if (IsNull((PIRP) pIrp))
derr = DualErr(kPGDMinorError_IoBuildIOCTLRequestFailed);
}
// Send the request.
if (derr.IsntError())
{
pIrp.NextStackLocation()->FileObject = mVHFileObject;
status = IoCallDriver(mVHDeviceObject, pIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoCallDriverFailed, status);
}
// Close volume handle.
if (openedVolHandle)
CloseVolumeHandle();
return derr;
}
////////////////////////////////////////
// Class Volume private member functions
////////////////////////////////////////
// VolumeHandleOpened returns TRUE if a handle to the volume has been opened,
// FALSE otherwise.
PGPBoolean
Volume::VolumeHandleOpened()
{
return (IsntNull(mVolumeHandle));
}
// GetDriveGeometry gets the geometry of the specified drive.
DualErr
Volume::GetDriveGeometry()
{
DualErr derr;
PGPBoolean openedVolHandle;
pgpAssert(Mounted());
if (!VolumeHandleOpened())
{
derr = OpenVolumeHandle();
openedVolHandle = derr.IsntError();
}
// Send down the request.
if (derr.IsntError())
{
derr = SendIOCTLRequest(IRP_MJ_DEVICE_CONTROL, 0,
IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &mGeometry,
sizeof(mGeometry));
}
if (openedVolHandle)
CloseVolumeHandle();
return derr;
}
// OpenVolumeHandle opens a handle to the actual volume and references the
// associated file object.
DualErr
Volume::OpenVolumeHandle()
{
DualErr derr;
IO_STATUS_BLOCK ioStatus;
KUstring drivePath;
NTSTATUS status;
PGPBoolean openedVol, reffedFileObj;
openedVol = reffedFileObj = FALSE;
pgpAssert(!VolumeHandleOpened());
// Get path to volume.
derr = MakePathToDrive(mDrive, &drivePath);
// Get handle to volume;
if (derr.IsntError())
{
OBJECT_ATTRIBUTES objectAttributes;
InitializeObjectAttributes(&objectAttributes, drivePath,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwCreateFile(&mVolumeHandle,
SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
&objectAttributes, &ioStatus, NULL, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_ZwCreateFileFailed, status);
openedVol = derr.IsntError();
}
// Get file object from this handle.
if (derr.IsntError())
{
status = ObReferenceObjectByHandle(mVolumeHandle, FILE_READ_DATA,
NULL, KernelMode, (void **) &mVHFileObject, NULL);
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_ObRefObjByHandleFailed, status);
reffedFileObj = derr.IsntError();
}
// Initialize variables on success.
if (derr.IsntError())
{
mVHDeviceObject = IoGetRelatedDeviceObject(mVHFileObject);
}
// Cleaup on error.
if (derr.IsError())
{
if (reffedFileObj)
{
ObDereferenceObject(mVHFileObject);
mVHFileObject = NULL;
mVHDeviceObject = NULL;
}
if (openedVol)
{
ZwClose(mVolumeHandle);
mVolumeHandle = NULL;
}
}
return derr;
}
// CloseVolumeHandle closes a handle opened with OpenVolumeHandle.
void
Volume::CloseVolumeHandle()
{
pgpAssert(VolumeHandleOpened());
// Dereference file object pointer taken before.
ObDereferenceObject(mVHFileObject);
mVHFileObject = NULL;
mVHDeviceObject = NULL;
// Close volume handle.
ZwClose(mVolumeHandle);
mVolumeHandle = NULL;
}
// SendIOCTLRequest sends an IOCTL request to the mounted volume.
DualErr
Volume::SendIOCTLRequest(
PGPUInt8 majorFunc,
PGPUInt8 minorFunc,
PGPUInt32 ioctlCode,
PVOID inBuf,
PGPUInt32 sizeInBuf,
PVOID outBuf,
PGPUInt32 sizeOutBuf)
{
DualErr derr;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
KIrp pIrp;
NTSTATUS status;
pgpAssert(Mounted());
pgpAssert(VolumeHandleOpened());
// Initialize the event.
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Build the request.
pIrp = IoBuildDeviceIoControlRequest(ioctlCode, mVHDeviceObject, inBuf,
sizeInBuf, outBuf, sizeOutBuf, FALSE, &event, &ioStatus);
if (IsNull((PIRP) pIrp))
derr = DualErr(kPGDMinorError_IoBuildIOCTLRequestFailed);
// Call down the request.
if (derr.IsntError())
{
pIrp.MajorFunction(NEXT) = majorFunc;
pIrp.MinorFunction(NEXT) = minorFunc;
pIrp.NextStackLocation()->FileObject = mVHFileObject;
pIrp.IoctlCode(NEXT) = ioctlCode;
status = IoCallDriver(mVHDeviceObject, pIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
}
if (!NT_SUCCESS(status))
derr = DualErr(kPGDMinorError_IoCallDriverFailed, status);
}
return derr;
}
// SendUserFSCTLRequest is a wrapper around SendIOCTLRequest.
DualErr
Volume::SendUserFSCTLRequest(PGPUInt32 fsctlCode)
{
pgpAssert(Mounted());
pgpAssert(VolumeHandleOpened());
return SendIOCTLRequest(IRP_MJ_FILE_SYSTEM_CONTROL,
IRP_MN_USER_FS_REQUEST, fsctlCode);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -