⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 volume.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	{
		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 + -