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

📄 cvolumeimpdrvnt.cpp

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

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

#include "pgpClassesConfig.h"

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

#include "CDevice.h"
#include "CEvent.h"
#include "CUnicodeString.h"
#include "FsctlCodes.h"

#include "pgpDiskBase.h"
#include "DriverAPI.h"

#include "CDeviceCache.h"
#include "CDriverSubsystemsDrvNT.h"
#include "CVolumeImpDrvNT.h"
#include "DriverMain.h"

_USING_PGP

_UNNAMED_BEGIN

// Constants

const WCHAR		*kMountPointDeviceName		= L"MountPointManager";
const PGPUInt32	IO_REPARSE_TAG_MOUNT_POINT	= 0xA0000003;

// Types

struct REPARSE_GUID_DATA_BUFFER
{
	PGPUInt32	ReparseTag;
	PGPUInt16	ReparseDataLength;
	PGPUInt16	Reserved;
	GUID		ReparseGuid;

	struct
	{
		PGPByte	DataBuffer[1];

	} GenericReparseBuffer;
};

_UNNAMED_END

// Class CVolumeImpDrvNT member functions

#if	(_WIN32_WINNT >= 0x0500)

CVolumeImpDrvNT::CVolumeImpDrvNT() : mPDevice(NULL), mVHFileObject(NULL),
	mVolumeHandle(NULL), mDirFileObject(NULL), mDirHandle(NULL)
{
	Status() = mAsciiDeviceName.Status();

	if (Status().IsntError())
		Status() = mVHDevice.Status();

	if (Status().IsntError())
		Status() = mMountMgr.Status();

	if (Status().IsntError())
		Status() = mDirDevice.Status();
}

#else	// !(_WIN32_WINNT < 0x0500)

CVolumeImpDrvNT::CVolumeImpDrvNT() : mPDevice(NULL), mVHFileObject(NULL),
	mVolumeHandle(NULL)
{
	Status() = mAsciiDeviceName.Status();

	if (Status().IsntError())
		Status() = mVHDevice.Status();
}

#endif	// (_WIN32_WINNT < 0x0500)

CVolumeImpDrvNT::~CVolumeImpDrvNT()
{
	if (IsMounted())
	{
		if (IsAttachedToVolume())
			DetachVolume();
		else
			Unmount(TRUE);
	}
}

PGPBoolean
CVolumeImpDrvNT::HasOpenFiles()
{
	pgpAssert(IsMounted());

	CComboError	error;

	if (IsLockedForIO() || IsLockedForFormat())
		return TRUE;

	// If lock fails, then the volume has open files.
	error = LockForIO();  // NETABUG has open files?

	if (error.IsntError())
		UnlockVolume();

	return error.IsError();
}

CComboError
CVolumeImpDrvNT::AttachVolume(const char *root, const char *deviceName)
{
	pgpAssert(!IsMounted());

	CComboError	error;
	error = mRoot.Assign(root);

	if (error.IsntError())
	{
		if (IsntNull(deviceName))
			error = mAsciiDeviceName.Assign(deviceName);
	}

	if (error.IsntError())
		error = FillInBlockInfo();

	if (error.IsntError())
	{
		mIsAttachedToVolume = TRUE;

		mVolState = kVolStateMounted;
		mLockState = kLockStateNone;
	}

	return error;
}

void
CVolumeImpDrvNT::DetachVolume()
{
	pgpAssert(IsMounted());
	pgpAssert(IsAttachedToVolume());

	if (IsLockedForIO() || IsLockedForFormat())
		UnlockVolume();

	mIsAttachedToVolume = FALSE;

	mVolState = kVolStateUnmounted;
	mLockState = kLockStateNone;
}

CComboError
CVolumeImpDrvNT::Mount(
	const char	*deviceName,
	const char	*root,
	PGPUInt64	totalBlocks,
	PGPUInt32	blockSize,
	const void	*ioHandlerFunc,
	void		*refPtr,
	PGPBoolean	readOnly)
{
	pgpAssert(IsUnmounted());
	pgpAssertStrValid(deviceName);
	pgpAssertStrValid(root);
	pgpAssertAddrValid(ioHandlerFunc, VoidAlign);

	CComboError	error;

	// Prepare strings.
	CUnicodeString	fullDevName;
	CUnicodeString	fullLinkName;

	error = MakeDeviceStrings(deviceName, root, fullDevName, fullLinkName);

	if (error.IsntError())
		error = mAsciiDeviceName.Assign(deviceName);

	if (error.IsntError())
		error = mRoot.Assign(root);

	if (error.IsntError())
	{
		mVolState			= kVolStateMounted;
		mLockState			= kLockStateNone;
		mIsAttachedToVolume = FALSE;

		mTotalBlocks = totalBlocks;
		mBlockSize = blockSize;

		// Is device for this device name in cache?
		if (CDriverSubsystemsDrvNT::DeviceCache().DoesEntryExist(deviceName))
		{
			// It's in cache, get it.
			error = CDriverSubsystemsDrvNT::DeviceCache().GetEntryDevice(
				deviceName, mPDevice);

			if (readOnly)
				mPDevice->Get()->Characteristics |= FILE_READ_ONLY_DEVICE;
			else
				mPDevice->Get()->Characteristics &= ~FILE_READ_ONLY_DEVICE;

			mPDevice->UpdateRefPtr(refPtr);
		}
		else
		{
			// Not in cache, create new entry.
			error = CDriverSubsystemsDrvNT::DeviceCache().CreateEntry(
				deviceName);
			mPDevice = new CDevice;

			if (IsNull(mPDevice))
				error.err = kPGPError_OutOfMemory;

			if (error.IsntError())
			{
				error = mPDevice->Status();

				if (error.IsntError())
				{
					PGPUInt32	attribs	= 0;

					if (CVolume::kUseRemovableFlag)
						attribs |= FILE_REMOVABLE_MEDIA;

					if (readOnly)
						attribs |= FILE_READ_ONLY_DEVICE;

					error = mPDevice->Create(
						DriverMain::GetDriverObjectInitParam(), fullDevName,
						FILE_DEVICE_DISK, attribs, FALSE,
						static_cast<IrpDispatchFunc>(ioHandlerFunc), refPtr);
				}

				if (error.IsntError())
				{
					error = CDriverSubsystemsDrvNT::DeviceCache().
						SetEntryDevice(deviceName, mPDevice);

					if (error.IsError())
						mPDevice->Delete();
				}

				if (error.IsError())
				{
					delete mPDevice;
					mPDevice = NULL;
				}
			}
		}
	}

#if	(_WIN32_WINNT >= 0x0500)

	// Win2k, announce arrival and create mount point.
	if (error.IsntError())
		error = OpenMountMgr();

	if (error.IsntError())
	{
		error = AnnounceWin2kArrival(fullDevName);

		if (error.IsntError())
		{
			CUnicodeString	curLink;
			CUnicodeString	volId;

			error = GetVolumeStrings(deviceName, volId, curLink);

			if (error.IsntError())
			{
				if (!curLink.IsEmpty() && (fullLinkName != curLink))
					error = DeleteMountPoint(volId, fullDevName, curLink);
			}

			if (error.IsntError())
			{
				if (fullLinkName != curLink)
				{
					error = CreateMountPoint(volId, fullDevName, 
						fullLinkName);
				}
			}
		}

		CloseMountMgr();
	}

#else	// !(_WIN32_WINNT >= 0x0500)

	// NT4, create symbolic link.
	if (error.IsntError())
		error = mPDevice->Link(fullLinkName);

#endif	// (_WIN32_WINNT >= 0x0500)

	if (error.IsError())
	{
		if (IsntNull(mPDevice))
		{
			mPDevice->UpdateRefPtr(NULL);
			mPDevice = NULL;	// no need to delete, it's cached
		}

		mAsciiDeviceName.Empty();
		mRoot.Empty();

		mVolState = kVolStateUnmounted;
		mLockState = kLockStateNone;
	}

	return error;
}

CComboError
CVolumeImpDrvNT::Unmount(PGPBoolean isForced)
{
	pgpAssert(IsMounted());
	pgpAssert(!IsAttachedToVolume());

	CComboError	error;

	// Prepare strings.
	CUnicodeString	fullDevName;
	CUnicodeString	fullLinkName;

	error = MakeDeviceStrings(DeviceName(), Root(), fullDevName,
		fullLinkName);

	// Dismount the volume.
	if (error.IsntError() && !IsLockedForFormat() && !IsLockedForIO())
	{
		error = LockForIO(); 

		if (error.IsError() && isForced)
			error = OpenVolumeHandle(); // NETABUG forced unmount failure/crash?
	}

	// Dismount the volume.
	if (error.IsntError())
	{
		error = mVHDevice.SendFsctlRequest(IRP_MN_USER_FS_REQUEST,
			FSCTL_DISMOUNT_VOLUME);

		if (isForced)
			error = CComboError();
	}

#if	(_WIN32_WINNT >= 0x0500)

	// Win2k, delete the mount point.
	if (error.IsntError())
		error = OpenMountMgr();

	if (error.IsntError())
	{
		CUnicodeString	curLink;
		CUnicodeString	volId;

		error = GetVolumeStrings(DeviceName(), volId, curLink);

		if (error.IsntError())
			error = DeleteMountPoint(volId, fullDevName, fullLinkName);

		if (error.IsntError())
		{
			// Make sure cached link name is empty.
			CUnicodeString	empty;
			error = empty.Status();

			CDriverSubsystemsDrvNT::DeviceCache().SetEntryCurLink(
				DeviceName(), empty);
		}

		if (isForced)
			error = CComboError();

		CloseMountMgr();
	}

#else	// !(_WIN32_WINNT >= 0x0500)

	// NT4, delete the symbolic link.
	if (error.IsntError())
		error = mPDevice->Unlink();

#endif	// (_WIN32_WINNT >= 0x0500)

	if (IsLockedForIO() || IsLockedForFormat())
		UnlockVolume();

	if (IsVolumeHandleOpened())
		CloseVolumeHandle();

	if (error.IsntError())
	{
		mPDevice->UpdateRefPtr(NULL);
		mPDevice = NULL;	// no need to delete, it's cached

		mAsciiDeviceName.Empty();
		mRoot.Empty();

		mVolState = kVolStateUnmounted;
		mLockState = kLockStateNone;
	}

	return error;
}

CComboError
CVolumeImpDrvNT::LockForIO()
{
	pgpAssert(IsMounted());
	pgpAssert(!IsLockedForIO() && !IsLockedForFormat());

	CComboError	error;
	error = OpenVolumeHandle(); // NETABUG has open files?

	if (error.IsntError())
	{
		error = mVHDevice.SendFsctlRequest(IRP_MN_USER_FS_REQUEST,
			FSCTL_LOCK_VOLUME);
	}

	if (error.IsntError())
		mLockState = kLockStateIO;

	if (error.IsError())
	{
		if (IsVolumeHandleOpened())
			CloseVolumeHandle();
	}

	return error;
}

CComboError
CVolumeImpDrvNT::LockForFormat()
{
	pgpAssert(IsMounted());
	pgpAssert(!IsLockedForIO() && !IsLockedForFormat());

	CComboError	error;
	error = OpenVolumeHandle();

	if (error.IsntError())
	{
		error = mVHDevice.SendFsctlRequest(IRP_MN_USER_FS_REQUEST,
			FSCTL_LOCK_VOLUME);
	}

	if (error.IsntError())
		mLockState = kLockStateFormat;

	if (error.IsError())
	{
		if (IsVolumeHandleOpened())
			CloseVolumeHandle();
	}

	return error;
}

CComboError
CVolumeImpDrvNT::UnlockVolume()
{
	pgpAssert(IsMounted());
	pgpAssert(IsVolumeHandleOpened());
	pgpAssert(IsLockedForIO() || IsLockedForFormat());

	CComboError	error;

	if (IsLockedForFormat())
	{
		error = mVHDevice.SendFsctlRequest(IRP_MN_USER_FS_REQUEST,
			FSCTL_DISMOUNT_VOLUME);
	}

	if (error.IsntError())
	{
		error = mVHDevice.SendFsctlRequest(IRP_MN_USER_FS_REQUEST,
			FSCTL_UNLOCK_VOLUME);
	}

	if (error.IsntError())
	{
		mLockState = kLockStateNone;
		CloseVolumeHandle();
	}

	return error;
}

CComboError
CVolumeImpDrvNT::Read(void *buf, PGPUInt64 pos, PGPUInt32 nBlocks) const
{
	pgpAssert(IsMounted());
	pgpAssert(IsVolumeHandleOpened());
	pgpAssert(IsLockedForIO() || IsLockedForFormat());
	pgpAssertAddrValid(buf, VoidAlign);

	CComboError		error;
	IO_STATUS_BLOCK	ioStatus;
	LARGE_INTEGER	bigPos;

	bigPos.QuadPart = pos * BlockSize();

	error.err = ZwReadFile(mVolumeHandle, NULL, NULL, NULL, &ioStatus, buf,
		nBlocks * BlockSize(), &bigPos, NULL);

	if (error.HaveNonPGPError())
		error.pgpErr = kPGPError_VolumeOpFailed;

	return error;
}

CComboError
CVolumeImpDrvNT::Write(const void *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
	pgpAssert(IsMounted());
	pgpAssert(IsVolumeHandleOpened());
	pgpAssert(IsLockedForIO() || IsLockedForFormat());
	pgpAssertAddrValid(buf, VoidAlign);

	CComboError		error;

⌨️ 快捷键说明

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