cvolumeimpdrv98.cpp

来自「PGP8.0源码 请认真阅读您的文件包然后写出其具体功能」· C++ 代码 · 共 874 行 · 第 1/2 页

CPP
874
字号
/*____________________________________________________________________________
		Copyright (C) 2002 PGP Corporation
        All rights reserved.

        $Id: CVolumeImpDrv98.cpp,v 1.9 2002/08/06 20:09:31 dallen Exp $
____________________________________________________________________________*/

#include "pgpClassesConfig.h"
#include "pgpDiskBase.h"

#include "UDebug.h"
#include "UMath.h"
#include "UString.h"

#include "UFileSys.h"

#include "CDriverSubsystemsDrv98.h"
#include "CIop.h"
#include "CIosInterface.h"
#include "CVolumeImpDrv98.h"

_USING_PGP


_UNNAMED_BEGIN

// Constants

const char	*kDcbVendorId	= "PGP     ";
const char	*kDcbProductId	= "PGPdisk         ";
const char	*kDcbRevLevel	= "0001";

_UNNAMED_END


// Class CVolumeImpDrv98 member functions

CVolumeImpDrv98::CVolumeImpDrv98()
{
	Status() = mDeviceName.Status();
}

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

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

	CComboError	error;

	char		*pathBuf;
	CString		path;
	PGPBoolean	hasOpenFiles;

	LockLevel	oldLock;
	error = GetLockLevel(oldLock);

	if (error.IsntError())
		error = path.Status();

	if (error.IsntError())
		error = path.GetBuffer(kPGPdiskMaxPathLength, pathBuf);

	if (error.IsntError())
	{
		error = SetLockLevel(LockLevel3);

		if (error.IsntError())
		{
			PGPUInt8	drive	= UString::LetterToNumber(mRoot[0]);
			VxdIntRegs	regs;

			regs.eax	= 0x440D;			// function 440D
			regs.ebx	= drive + 1;		// drive to enumerate on
			regs.ecx	= 0x086D;			// minor code 6D (Enum Open Files)
			regs.edx	= reinterpret_cast<PGPUInt32>(pathBuf);	// file path
			regs.esi	= 0;				// index to 0 to get first file
			regs.edi	= 0;				// enumerate all files (0)
			regs.flags	= 0x0001;			// carry flag set on error

			Exec_VxD_Int(0x21, &regs);
			hasOpenFiles = ((regs.flags & 0x0001) ? FALSE : TRUE);

			SetLockLevel(oldLock);
		}

		path.ReleaseBuffer();
	}

	if (error.IsError())
		return TRUE;
	else
		return hasOpenFiles;
}

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

	CComboError	error;

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

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

	if (error.IsntError())
		error = mDcb.GetDcbOfDrive(UString::LetterToNumber(root[0]));

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

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

		mVolState = kVolStateMounted;
		mLockState = kLockStateNone;
	}

	return error;
}

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

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

	mIsAttachedToVolume = FALSE;

	mVolState = kVolStateUnmounted;
	mLockState = kLockStateNone;
}

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

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

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

	// Need to create a new Dcb.
	if (error.IsntError())
		error = mDcb.Create();

	if (error.IsntError())
	{
		PGPUInt8	drive	= UString::LetterToNumber(root[0]);

		InitDcb(drive, totalBlocks, blockSize, readOnly);

		// Tell system to send us requests for this Dcb.
		if (!CDriverSubsystemsDrv98::IosInterface().IspInsertCalldown(mDcb,
			DispatchIop, 0, mDcb.DemandFlags()))
		{
			error.pgpErr = kPGPError_VolumeOpFailed;
		}

		if (error.IsntError())
		{
			// Associate the Dcb with a drive letter.
			if (!CDriverSubsystemsDrv98::IosInterface().IspAssociateDcb(
				mDcb, drive, NULL))
			{
				error.pgpErr = kPGPError_VolumeOpFailed;
			}
		}

		// Initialize variables on success.
		if (error.IsntError())
		{
			mVolState			= kVolStateMounted;
			mLockState			= kLockStateNone;
			mIsAttachedToVolume = FALSE;

			mDispatchFunc = static_cast<IopDispatchFunc>(iopDispatchFunc);
			mRefPtr = refPtr;

			mTotalBlocks = totalBlocks;
			mBlockSize = blockSize;
		}
	}

	return error;
}

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

	CComboError	error;

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

	PGPUInt8	drive	= UString::LetterToNumber(mRoot[0]);

	// Flush the volume.
	if (error.IsntError())
	{
		_VolFlush(drive, NULL);

		// Get a lock on the drive.
		if (!isForced)	// hang on BS open file warning
			error = LockForIO();
	}

	if (error.IsntError())
	{
		// this fixes DriveSpace problems
		NotifyVolumeRemoval(drive);

		// Disassociate the Dcb with its drive letter.
		if (!CDriverSubsystemsDrv98::IosInterface().IspDisassociateDcb(
			drive))
		{
			error.pgpErr = kPGPError_VolumeOpFailed;
		}

		if (error.IsntError())
		{
			mRoot.Empty();
			mDeviceName.Empty();

			mVolState = kVolStateUnmounted;
			mLockState = kLockStateNone;
		}

		if (error.IsError() && !isForced)
			UnlockVolume();
	}

	return error;
}

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

	CComboError	error;
	error = SetLockLevel(LockLevel3);

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

	return error;
}

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

	CComboError	error;
	error = AcquireFormatLock();

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

	return error;
}

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

	CComboError	error;

	if (IsLockedForIO())
		error = SetLockLevel(LockLevelNone);
	else
		error = ReleaseFormatLock();

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

	return error;
}

CComboError
CVolumeImpDrv98::Read(void *buf, PGPUInt64 pos, PGPUInt32 nBlocks) const
{
	CComboError	error;

	error = DiskAccess(IOR_READ, buf, pos, nBlocks);

	return error;
}

CComboError
CVolumeImpDrv98::Write(const void *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
	CComboError	error;

	error = DiskAccess(IOR_WRITE, const_cast<void *>(buf), pos, nBlocks);

	return error;
}

CComboError
CVolumeImpDrv98::GetLockLevel(LockLevel& lockLevel) const
{
	pgpAssert(IsMounted());

	CComboError	error;
	PGPUInt32	lockFlags, lockOwner, lockType;

	if (IFSMgr_GetLockState(UString::LetterToNumber(mRoot[0]), &lockType,
		&lockFlags, &lockOwner) != 0)
	{
		error.pgpErr = kPGPError_VolumeOpFailed;
	}

	if (error.IsntError())
	{
		switch (lockType)
		{
		case -1:
			lockLevel = LockLevelNone;
			break;
		case 0:
			lockLevel = (lockFlags & LOCKP_LOCK_FOR_FORMAT ? LockLevel0MR :
				LockLevel0);
			break;
		case 1:
			lockLevel = LockLevel1;
			break;
		case 2:
			lockLevel = LockLevel2;
			break;
		case 3:
			lockLevel = LockLevel3;
			break;
		default:
			pgpAssert(FALSE);
			break;
		}
	}

	return error;
}

CComboError
CVolumeImpDrv98::SetLockLevel(LockLevel lockLevel, PGPUInt8 permissions)
{
	pgpAssert(IsMounted());

	CComboError	error;
	LockLevel	curLock;
	PGPUInt8	drive	= UString::LetterToNumber(mRoot[0]);

	// Don't take format locks.
	if ((lockLevel == LockLevel0) || (lockLevel == LockLevel0MR))
		error.pgpErr = kPGPError_BadParams;

	// Make sure we aren't trying to alter a level-0 lock.
	if (error.IsntError())
		error = GetLockLevel(curLock);

	if (error.IsntError())
	{
		UDebug::DebugOut("PGPdisk: Want lock %d on drive %u curlock %d",
			lockLevel, drive, curLock);

		if ((curLock == LockLevel0) || (lockLevel == LockLevel0MR))
			error.pgpErr = kPGPError_VolumeOpFailed;
	}

	// Since there is a special call to acquire a L1 lock, we do this first
	// before anything else.

	if (error.IsntError())
	{
		VxdIntRegs 	regs;

		if ((curLock == LockLevelNone) && (lockLevel != LockLevelNone))
		{
			curLock = LockLevel1;

			regs.eax	= 0x440D;				// function 440D
			regs.ebx	= 0x0100 + drive + 1;	// first get L1 lock
			regs.ecx	= 0x084A;				// (Lock Volume)
			regs.edx	= permissions;			// locking permissions
			regs.flags	= 0x0001;				// carry set if error

			Exec_VxD_Int(0x21, &regs);

			if (regs.flags & 0x0001)
			{
				error.pgpErr = kPGPError_VolumeOpFailed;
				error.err = regs.eax;
			}
		}

		// Now we calculate how many lock levels we need to go up or down.
		if (error.IsntError())
		{

⌨️ 快捷键说明

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