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, ®s);
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, ®s);
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 + -
显示快捷键?