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

📄 cpgpdiskimpdrvnt.cpp

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
		Copyright (C) 2002 PGP Corporation
        All rights reserved.

        $Id: CPGPdiskImpDrvNT.cpp,v 1.11 2002/09/26 01:32:11 wjb Exp $
____________________________________________________________________________*/

#include "pgpClassesConfig.h"
#include <devioctl.h>

#if	(_WIN32_WINNT >= 0x0500)
#include <mountdev.h>
#endif	// _WIN32_WINNT >= 0x5000

#include "CString.h"
#include "UDebug.h"

#include "CDevice.h"
#include "CUnicodeString.h"

#include "DriverAPI.h"

#include "CDeviceCache.h"
#include "CDriverSubsystemsDrvNT.h"
#include "CPGPdiskImpDrvNT.h"
#include "UConstantNamesDrvNT.h"
#include "UMessageLog.h"

_USING_PGP

_UNNAMED_BEGIN

// Constants
enum {kStandardBlockSize = 512};

_UNNAMED_END


// Class CPGPdiskImpDrvNT member functions

CComboError 
CPGPdiskImpDrvNT::Mount(
	const char	*path, 
	const char	*root, 
	const char	*deviceName, 
	PGPdiskEncryptionAlgorithm	algorithm, 
	const void	*exportedContext, 
	PGPUInt32	sizeContext, 
	PGPUInt64	firstDataBlock, 
	PGPUInt64	numDataBlocks, 
	const void	*ioHandlerFunc, 
	void		*refPtr, 
	PGPUInt32	procId, 
	PGPBoolean	isReadOnly)
{
	CComboError	error;

	// Initialize security tokens.
	error = mTokenForMountUnmount.AssignProcessId(procId);

	if (error.IsntError())
	{
		error = mTokenForIo.AssignProcessId(procId);

		if (error.IsntError())
		{
			// Assume security token of the user's original process ID.
			mTokenForMountUnmount.ImpersonateToken();

			error = CPGPdiskImp::Mount(path, root, deviceName, algorithm, 
				exportedContext, sizeContext, firstDataBlock, numDataBlocks, 
				ioHandlerFunc, refPtr, procId, isReadOnly);

			mTokenForMountUnmount.RevertToSelf();

			if (error.IsError())
				mTokenForIo.UnassignProcessId();
		}

		if (error.IsError())
			mTokenForMountUnmount.UnassignProcessId();
	}

	return error;
}

CComboError 
CPGPdiskImpDrvNT::Unmount(PGPBoolean isForced)
{
	CComboError	error;

	// Assume security token of the user's original process ID.
	mTokenForMountUnmount.ImpersonateToken();  // NETABUG security 
	error = CPGPdiskImp::Unmount(isForced);
	mTokenForMountUnmount.RevertToSelf();   // NETABUG security 

	// Uninitialize the previously initialize security tokens.
	if (error.IsntError())
	{
		mTokenForMountUnmount.UnassignProcessId();
		mTokenForIo.UnassignProcessId();
	}

	return error;
}

CComboError 
CPGPdiskImpDrvNT::CalcBlockSizeOfHost(
	const char	*path, 
	PGPUInt32&	hostBlockSize) const
{
	pgpAssertStrValid(path);

	CComboError	error;

	// Determine block size.
	CString	hostRoot;
	CVolume	host;

	error = hostRoot.Status();

	if (error.IsntError())
		hostRoot.Format("%c:\\", path[0]);

	if (error.IsntError())
	{
		error = host.AttachVolume(hostRoot);

		if (error.IsntError())
		{
			hostBlockSize = host.BlockSize();
			host.DetachVolume();
		}

		// Network path if error.
		if (error.IsError())
		{
			error = CComboError();
			hostBlockSize = kStandardBlockSize;
		}
	}

	return error;
}

void 
CPGPdiskImpDrvNT::CalcNTFakeDriveLayout(
	DRIVE_LAYOUT_INFORMATION	*pDLI) const
{
	pgpAssertAddrValid(pDLI, DRIVE_LAYOUT_INFORMATION);

	pDLI->PartitionCount = 1;
	pDLI->Signature = 0;

	CalcNTFakePartitionInfo(&pDLI->PartitionEntry[0]);
}

void 
CPGPdiskImpDrvNT::CalcNTFakeGeometry(DISK_GEOMETRY *pGeom) const
{
	pgpAssertAddrValid(pGeom, DISK_GEOMETRY);

	pGeom->Cylinders.QuadPart	= TotalBlocks();
	pGeom->MediaType			= (CVolume::kUseRemovableFlag ? 
		RemovableMedia : FixedMedia);
	pGeom->TracksPerCylinder	= 1;
	pGeom->SectorsPerTrack		= 1;
	pGeom->BytesPerSector		= kPGPdiskBlockSize;
}

void 
CPGPdiskImpDrvNT::CalcNTFakePartitionInfo(
	PARTITION_INFORMATION	*pPI) const
{
	pgpAssertAddrValid(pPI, PARTITION_INFORMATION);

	pPI->StartingOffset.QuadPart	= kPGPdiskBlockSize;
	pPI->PartitionLength.QuadPart	= TotalBlocks() * kPGPdiskBlockSize;
	pPI->HiddenSectors				= 0;
	pPI->PartitionNumber			= 1;
	pPI->PartitionType				= PARTITION_ENTRY_UNUSED; // like I know
	pPI->BootIndicator				= FALSE;
	pPI->RecognizedPartition		= TRUE;
	pPI->RewritePartition			= FALSE;
}

NTSTATUS 
CPGPdiskImpDrvNT::ProcessIrpMjRead(CIrp& irp)
{
	pgpAssert(irp.MajorFunction() == IRP_MJ_READ);

	CComboError	error;
	void		*buf;

	// Extract parameters. Note that 0 IS a valid length!
	PGPUInt64	posInBlocks	= irp.ReadPos() / kPGPdiskBlockSize;

	PGPUInt32	nBlocks	= static_cast<PGPUInt32>(
		irp.ReadLength() / kPGPdiskBlockSize);

	if (nBlocks > 0)
	{
		// Extract the buffer.
	#if	(_WIN32_WINNT >= 0x0500)

		buf = MmGetSystemAddressForMdlSafe(irp.MdlAddress(), 
			NormalPagePriority);

		if (IsNull(buf))
			error.pgpErr = kPGPError_MemoryOpFailed;

	#else	// _WIN32_WINNT < 0x5000

		buf = MmGetSystemAddressForMdl(irp.MdlAddress());
		pgpAssertAddrValid(buf, VoidAlign);

	#endif	// _WIN32_WINNT >= 0x5000					
	}

	if (error.IsntError())
		error = Read(buf, posInBlocks, nBlocks);

	if (error.IsntError())
	{
		irp.Information() = irp.ReadLength();
		return STATUS_SUCCESS;
	}
	else
	{
		irp.Information() = 0;
		return STATUS_DEVICE_DATA_ERROR;
	}
}

NTSTATUS 
CPGPdiskImpDrvNT::ProcessIrpMjWrite(CIrp& irp)
{
	pgpAssert(irp.MajorFunction() == IRP_MJ_WRITE);

	CComboError	error;
	void		*buf;

	if (IsReadOnly())
		return STATUS_MEDIA_WRITE_PROTECTED;
	
	// Extract parameters. Note that 0 IS a valid length!
	PGPUInt64	posInBlocks	= irp.WritePos() / kPGPdiskBlockSize;

	PGPUInt32	nBlocks	= static_cast<PGPUInt32>(
		irp.WriteLength() / kPGPdiskBlockSize);

	if (nBlocks > 0)
	{
		// Extract the buffer.
	#if	(_WIN32_WINNT >= 0x0500)

		buf = MmGetSystemAddressForMdlSafe(irp.MdlAddress(), 
			NormalPagePriority);

		if (IsNull(buf))
			error.pgpErr = kPGPError_MemoryOpFailed;

	#else	// _WIN32_WINNT < 0x5000

		buf = MmGetSystemAddressForMdl(irp.MdlAddress());
		pgpAssertAddrValid(buf, VoidAlign);

	#endif	// _WIN32_WINNT >= 0x5000					
	}

	if (error.IsntError())
		error = Write(buf, posInBlocks, nBlocks);

	if (error.IsntError())
	{
		irp.Information() = irp.WriteLength();
		return STATUS_SUCCESS;
	}
	else
	{
		irp.Information() = 0;
		return STATUS_DEVICE_DATA_ERROR;
	}
}

void 
CPGPdiskImpDrvNT::ProcessIrpCallbackAux(
	CIrp&		irp, 
	PGPBoolean&	wasIrpCompleted)
{
	CComboError	error;
	PGPUInt8	majorFunc	= irp.MajorFunction();
	PGPUInt32	irpAddress	= reinterpret_cast<PGPUInt32>(
		static_cast<PIRP>(irp));

	UDebug::DebugOut("PGPdisk: Processing an %s address %X.", 
		UConstantNamesDrvNT::NameIrpMajorFunction(majorFunc), irpAddress);

	// Assume appropriate security context for file access.
	if (!mTokenForIo.IsTokenSet())
		mTokenForIo.ImpersonateToken();

	// Process the IRP according to function.
	switch (majorFunc)
	{
	case IRP_MJ_READ:
 		error.err = ProcessIrpMjRead(irp);
		break;

	case IRP_MJ_WRITE:
		error.err = ProcessIrpMjWrite(irp);
		break;

	default:
		pgpAssert(FALSE);

		irp.Information() = 0;
		error.err = STATUS_NOT_IMPLEMENTED;
		break;
	}

	if (error.HaveNonPGPError())
		irp.Complete(error.err, IO_DISK_INCREMENT);
	else
		irp.Complete(error.err);

	wasIrpCompleted = TRUE;

	UDebug::DebugOut("PGPdisk: Completed an %s address %X status %X.", 
		UConstantNamesDrvNT::NameIrpMajorFunction(majorFunc), 
		irpAddress, static_cast<PGPUInt32>(error.err));
}

void 
_cdecl 
CPGPdiskImpDrvNT::ProcessIrpCallback(void *refPtr)
{
	CIrp		irp(static_cast<PIRP>(refPtr));
	PGPBoolean	wasIrpCompleted	= FALSE;

	__try 
	{
		CPGPdiskImpDrvNT	*pImp	= static_cast<CPGPdiskImpDrvNT *>(
			irp.DriverContext1());
		pgpAssertAddrValid(pImp, CPGPdiskImpDrvNT);

		pImp->ProcessIrpCallbackAux(irp, wasIrpCompleted);
	}
	__except(EXCEPTION_EXECUTE_HANDLER) 
	{
		UDebug::DebugOut("PGPdisk: Exception in CPGPdiskImpDrvNT::"
			"ProcessIrpCallback.");
		UMessageLog::Output("Exception caught");

		// We don't exit with uncompleted IRPs.
		if (!wasIrpCompleted)
		{
			irp.Information() = 0;
			irp.Complete(STATUS_DEVICE_DATA_ERROR);

			wasIrpCompleted = TRUE;
		}
	}
}

CComboError 
CPGPdiskImpDrvNT::QueueIrpToIoThread(CIrp& irp)
{
	CComboError	error;

	irp.DriverContext1() = static_cast<PVOID>(this);
	error = mIoThread->PerformAsyncCallback(ProcessIrpCallback, irp.Get());
	
	return error;
}

// Added by wjb for Windows XP. 
// These are selected snippets from the XP DDK
#ifndef IOCTL_DISK_GET_LENGTH_INFO

#define FTTYPE  ((ULONG)'f')
#define IOCTL_VOLUME_BASE   ((ULONG) 'V')

#define IOCTL_DISK_GET_LENGTH_INFO          CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DISK_GET_PARTITION_INFO_EX    CTL_CODE(IOCTL_DISK_BASE, 0x0012, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_STORAGE_GET_HOTPLUG_INFO		CTL_CODE(IOCTL_STORAGE_BASE, 0x0305, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FT_BALANCED_READ_MODE				CTL_CODE(FTTYPE, 6, METHOD_NEITHER,  FILE_ANY_ACCESS)
#define IOCTL_VOLUME_GET_GPT_ATTRIBUTES		CTL_CODE(IOCTL_VOLUME_BASE, 14, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_VOLUME_ONLINE					CTL_CODE(IOCTL_VOLUME_BASE, 2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_MOUNTDEV_QUERY_STABLE_GUID	CTL_CODE(MOUNTDEVCONTROLTYPE, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_STORAGE_GET_DEVICE_NUMBER		CTL_CODE(IOCTL_STORAGE_BASE, 0x0420, METHOD_BUFFERED, FILE_ANY_ACCESS)

#endif // IOCTL_DISK_GET_LENGTH_INFO

#ifndef GET_LENGTH_INFORMATION
//
// The structure GET_LENGTH_INFORMATION is used with the ioctl
// IOCTL_DISK_GET_LENGTH_INFO to obtain the length, in bytes, of the
// disk, partition, or volume.
//

typedef struct _GET_LENGTH_INFORMATION {
    LARGE_INTEGER   Length;
} GET_LENGTH_INFORMATION, *PGET_LENGTH_INFORMATION;

//
// There are currently two ways a disk can be partitioned. With a traditional
// AT-style master boot record (PARTITION_STYLE_MBR) and with a new, GPT
// partition table (PARTITION_STYLE_GPT). RAW is for an unrecognizable
// partition style. There are a very limited number of things you can
// do with a RAW partititon.
//

typedef enum _PARTITION_STYLE {
    PARTITION_STYLE_MBR,
    PARTITION_STYLE_GPT,
    PARTITION_STYLE_RAW
} PARTITION_STYLE;

//
// The following structure defines information in an MBR partition that is not
// common to both GPT and MBR partitions.
//

typedef struct _PARTITION_INFORMATION_MBR {
    UCHAR PartitionType;
    BOOLEAN BootIndicator;
    BOOLEAN RecognizedPartition;
    ULONG HiddenSectors;
} PARTITION_INFORMATION_MBR, *PPARTITION_INFORMATION_MBR;

//
// The following structure defines information in a GPT partition that is
// not common to both GPT and MBR partitions.
//

typedef struct _PARTITION_INFORMATION_GPT {
    GUID PartitionType;                 // Partition type. See table 16-3.
    GUID PartitionId;                   // Unique GUID for this partition.
    _int64 Attributes;                 // See table 16-4.
    WCHAR Name [36];                    // Partition Name in Unicode.
} PARTITION_INFORMATION_GPT, *PPARTITION_INFORMATION_GPT;

//
// The PARTITION_INFORMATION_EX structure is used with the
// IOCTL_DISK_GET_DRIVE_LAYOUT_EX, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
// IOCTL_DISK_GET_PARTITION_INFO_EX and IOCTL_DISK_GET_PARTITION_INFO_EX calls.
//

typedef struct _PARTITION_INFORMATION_EX {
    PARTITION_STYLE PartitionStyle;
    LARGE_INTEGER StartingOffset;
    LARGE_INTEGER PartitionLength;
    ULONG PartitionNumber;
    BOOLEAN RewritePartition;
    union {
        PARTITION_INFORMATION_MBR Mbr;
        PARTITION_INFORMATION_GPT Gpt;
    };
} PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX;

//
// IOCTL_STORAGE_GET_HOTPLUG_INFO
//

typedef struct _STORAGE_HOTPLUG_INFO {
    ULONG Size; // version
    BOOLEAN MediaRemovable; // ie. zip, jaz, cdrom, mo, etc. vs hdd
    BOOLEAN MediaHotplug;   // ie. does the device succeed a lock even though its not lockable media?
    BOOLEAN DeviceHotplug;  // ie. 1394, USB, etc.
    BOOLEAN WriteCacheEnableOverride; // This field should not be relied upon because it is no longer used
} STORAGE_HOTPLUG_INFO, *PSTORAGE_HOTPLUG_INFO;

//
// Output structure for IOCTL_VOLUME_GET_GPT_ATTRIBUTES.
//

typedef struct _VOLUME_GET_GPT_ATTRIBUTES_INFORMATION {
    ULONGLONG   GptAttributes;
} VOLUME_GET_GPT_ATTRIBUTES_INFORMATION, *PVOLUME_GET_GPT_ATTRIBUTES_INFORMATION;

//
// Output structure for IOCTL_MOUNTDEV_QUERY_STABLE_GUID.
//

typedef struct _MOUNTDEV_STABLE_GUID {
    GUID    StableGuid;
} MOUNTDEV_STABLE_GUID, *PMOUNTDEV_STABLE_GUID;

#endif // GET_LENGTH_INFORMATION
// End wjb

NTSTATUS 
CPGPdiskImpDrvNT::ProcessExtIrpMjDeviceControl(CIrp& irp)
{
	pgpAssert(irp.MajorFunction() == IRP_MJ_DEVICE_CONTROL);

	CComboError	error;

	UDebug::DebugOut("PGPdisk: Seen an %s IRP.", 
		UConstantNamesDrvNT::NameIoctlCode(irp.IoctlCode()));

	irp.Information() = 0;

	// Perform the IOCTL.
	switch (irp.IoctlCode())
	{
	case IOCTL_DISK_IS_WRITABLE:
		// check if disk is read-only
		if (IsReadOnly())
			error.err = STATUS_MEDIA_WRITE_PROTECTED;
		else
			error.err = STATUS_SUCCESS;
		break;
	
	case IOCTL_DISK_GET_DRIVE_GEOMETRY:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -