📄 cpgpdiskdrvwinutils.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// CPGPdiskDrvWinutils.cpp
//
// Contains utility functions for making interrupt calls to Windows/DOS.
//////////////////////////////////////////////////////////////////////////////
// $Id: CPGPdiskDrvWinutils.cpp,v 1.9 1999/02/13 04:24:34 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#include <vtoolscp.h>
#include "Required.h"
#include "UtilityFunctions.h"
#include "CPGPdiskDrv.h"
#include "CPGPdiskDrvWinutils.h"
////////////
// Constants
////////////
// The following are file attribute flags returned by R0_GetFileAttributes.
const PGPUInt16 _A_NORMAL = 0x0000; // normal file
const PGPUInt16 _A_RDONLY = 0x0001; // read-only
const PGPUInt16 _A_HIDDEN = 0x0002; // hidden
const PGPUInt16 _A_SYSTEM = 0x0004; // system
const PGPUInt16 _A_ARCH = 0x0020; // special OS file (?)
// The following are from the DDK.
#define LOCKP_ALLOW_WRITES 0x01 // Bit 0 set - allow writes
#define LOCKP_FAIL_WRITES 0x00 // Bit 0 clear - fail writes
#define LOCKP_FAIL_MEM_MAPPING 0x02 // Bit 1 set - fail memory mappings
#define LOCKP_ALLOW_MEM_MAPPING 0x00 // Bit 1 clear - allow memory mappings
#define LOCKP_USER_MASK 0x03 // Mask for user lock flags
#define LOCKP_LOCK_FOR_FORMAT 0x04 // Level 0 lock for format
//////////////////////////////////////
// Functions for performing interrupts
//////////////////////////////////////
// DoWinInt simulates a DOS interrupt.
PGPBoolean
CPGPdiskDrv::DoWinInt(PGPUInt8 interrupt, ALLREGS *pAllRegs)
{
pgpAssertAddrValid(pAllRegs, ALLREGS);
// Execute the interrupt.
Exec_VxD_Int(interrupt, pAllRegs);
return (pAllRegs->RFLAGS & 0x0001 ? FALSE : TRUE);
}
//////////////////////////
// Drive locking functions
//////////////////////////
// GetLockLevel returns the level of the lock on the given drive.
LockLevel
CPGPdiskDrv::GetLockLevel(PGPUInt8 drive)
{
PGPInt32 pLockType;
PGPUInt32 pLockFlags, pLockOwner;
pgpAssert(drive < kMaxDrives);
IFSMgr_GetLockState(drive, (PGPUInt32 *) &pLockType, &pLockFlags,
&pLockOwner);
switch (pLockType)
{
case -1:
return kLock_None;
case 0:
return (pLockFlags & LOCKP_LOCK_FOR_FORMAT ? kLock_L0MR : kLock_L0);
case 1:
return kLock_L1;
case 2:
return kLock_L2;
case 3:
return kLock_L3;
default:
pgpAssert(FALSE);
return kLock_None;
}
}
// AcquireLogicalVolLock gets a lock of the specified level on the specified
// drive, increasing or decreasing the lock level as needed. It doesn't
// handle L0 locks.
DualErr
CPGPdiskDrv::AcquireLogicalVolLock(
PGPUInt8 drive,
LockLevel lock,
PGPUInt8 permissions)
{
ALLREGS allRegs;
DualErr derr;
LockLevel curLock;
pgpAssert(lock != kLock_L0);
pgpAssert(IsLegalDriveNumber(drive));
// Make sure we aren't trying to alter a level-0 lock.
curLock = GetLockLevel(drive);
if (curLock == kLock_L0)
derr = DualErr(kPGDMinorError_LockVolumeFailed);
DebugOut("PGPdisk: Want lock %d on drive %u curlock %d", lock, drive,
curLock);
// Since there is a special call to acquire a L1 lock, we do this first
// before anything else.
if (derr.IsntError())
{
if ((curLock == kLock_None) && (lock != kLock_None))
{
curLock = kLock_L1;
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = 0x0100 + drive + 1; // first get L1 lock
allRegs.RECX = 0x084A; // (Lock Volume)
allRegs.REDX = permissions; // locking permissions
allRegs.RFLAGS = 0x0001; // carry cleared if error
mLockInProgress = TRUE;
mDriveBeingLocked = drive;
if (!DoWinInt(0x21, &allRegs))
derr = DualErr(kPGDMinorError_LockVolumeFailed, allRegs.REAX);
mLockInProgress = FALSE;
}
}
// Now we calculate how many lock levels we need to go up or down.
if (derr.IsntError())
{
PGPUInt8 locksUp = 0;
PGPUInt8 locksDown = 0;
if (curLock != lock)
{
switch (curLock)
{
case kLock_L1:
switch (lock)
{
case kLock_None:
locksDown = 1;
break;
case kLock_L2:
locksUp = 1;
break;
case kLock_L3:
locksUp = 2;
break;
default:
pgpAssert(FALSE);
break;
}
break;
case kLock_L2:
switch (lock)
{
case kLock_None:
locksDown = 2;
break;
case kLock_L1:
locksDown = 1;
break;
case kLock_L3:
locksUp = 1;
break;
default:
pgpAssert(FALSE);
break;
}
break;
case kLock_L3:
switch (lock)
{
case kLock_None:
locksDown = 3;
break;
case kLock_L1:
locksDown = 2;
break;
case kLock_L2:
locksDown = 1;
break;
default:
pgpAssert(FALSE);
break;
}
break;
default:
pgpAssert(FALSE);
break;
}
}
// If we need to get locks, we do that here.
while (derr.IsntError() && (locksUp != 0))
{
PGPUInt16 lockValue;
locksUp--;
if (curLock == kLock_L1)
{
curLock = kLock_L2;
lockValue = 2;
}
else
{
curLock = kLock_L3;
lockValue = 3;
}
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = (lockValue << 8) + drive + 1; // get next lock
allRegs.RECX = 0x084A; // (Lock Volume)
allRegs.REDX = 0; // > L1s expect zero here
allRegs.RFLAGS = 0x0001; // carry cleared if error
mLockInProgress = TRUE;
mDriveBeingLocked = drive;
if (!DoWinInt(0x21, &allRegs))
derr = DualErr(kPGDMinorError_LockVolumeFailed, allRegs.REAX);
mLockInProgress = FALSE;
}
// If we need to release locks, we do that here.
while (derr.IsntError() && (locksDown !=0))
{
locksDown--;
if (curLock == kLock_L3)
curLock = kLock_L2;
else if (curLock == kLock_L2)
curLock = kLock_L1;
else if (curLock == kLock_L1)
curLock = kLock_None;
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = drive + 1; // decrement lock level
allRegs.RECX = 0x086A; // code 6A (Unlock Volume)
allRegs.RFLAGS = 0x0001; // carry flag cleared on err
if (!DoWinInt(0x21, &allRegs))
{
derr = DualErr(kPGDMinorError_UnlockVolumeFailed,
allRegs.REAX);
}
}
}
DebugOut("PGPdisk: Lock on drive %u is now %d", drive,
GetLockLevel(drive));
return derr;
}
// GetFormatLockOnDrive locks the specified drive for formatting.
DualErr
CPGPdiskDrv::GetFormatLockOnDrive(PGPUInt8 drive)
{
ALLREGS allRegs;
DualErr derr;
PGPUInt32 locksTaken = 0;
pgpAssert(IsLegalDriveNumber(drive));
// Make sure we aren't already locked;
if (GetLockLevel(drive) != kLock_None)
derr = DualErr(kPGDMinorError_LockVolumeFailed);
// First get a 'normal' level-0 lock.
if (derr.IsntError())
{
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = 0x0000 + drive + 1; // L0 lock
allRegs.RECX = 0x084A; // (Lock Volume)
allRegs.REDX = 0; // must be 0
allRegs.RFLAGS = 0x0001; // carry set if error
mLockInProgress = TRUE;
mDriveBeingLocked = drive;
if (!DoWinInt(0x21, &allRegs))
derr = DualErr(kPGDMinorError_LockVolumeFailed, allRegs.REAX);
else
locksTaken++;
mLockInProgress = FALSE;
}
// Now get a 'more restrictive' level-0 lock.
if (derr.IsntError())
{
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = 0x0000 + drive + 1; // L0 lock
allRegs.RECX = 0x084A; // (Lock Volume)
allRegs.REDX = 4; // must be 4
allRegs.RFLAGS = 0x0001; // carry set if error
mLockInProgress = TRUE;
mDriveBeingLocked = drive;
if (!DoWinInt(0x21, &allRegs))
derr = DualErr(kPGDMinorError_LockVolumeFailed, allRegs.REAX);
else
locksTaken++;
mLockInProgress = FALSE;
}
// Undo what we did on error.
if (derr.IsError())
{
while (locksTaken-- > 0)
{
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = drive + 1; // decrement lock level
allRegs.RECX = 0x086A; // code 6A (Unlock Volume)
allRegs.RFLAGS = 0x0001; // carry flag set on error
DoWinInt(0x21, &allRegs);
}
}
return derr;
}
// ReleaseFormatLockOnDrive release a formatting lock on the specified drive.
DualErr
CPGPdiskDrv::ReleaseFormatLockOnDrive(PGPUInt8 drive)
{
ALLREGS allRegs;
DualErr derr;
PGPUInt32 locksTaken = 2;
pgpAssert(IsLegalDriveNumber(drive));
// Make sure we are already locked;
if (GetLockLevel(drive) != kLock_L0MR)
derr = DualErr(kPGDMinorError_UnlockVolumeFailed);
// Release locks.
while (derr.IsntError() && (locksTaken-- > 0))
{
allRegs.REAX = 0x440D; // function 440D
allRegs.REBX = drive + 1; // decrement lock level
allRegs.RECX = 0x086A; // code 6A (Unlock Volume)
allRegs.RFLAGS = 0x0001; // carry flag set on error
if (!DoWinInt(0x21, &allRegs))
derr = DualErr(kPGDMinorError_UnlockVolumeFailed, allRegs.REAX);
}
return derr;
}
/////////////////////////
// File utility functions
/////////////////////////
// IsFileInUseByReader returns TRUE if someone has opened the specified file
// with read access, FALSE otherwise.
PGPBoolean
CPGPdiskDrv::IsFileInUseByReader(LPCSTR path)
{
File existingFile;
DualErr derr;
pgpAssertStrValid(path);
derr = existingFile.Open(path,
kOF_ReadOnly | kOF_DenyRead | kOF_MustExist);
if (existingFile.Opened())
{
existingFile.Close();
}
return derr.IsError();
}
// IsFileInUseByWriter returns TRUE if someone has opened the specified file
// with write access, FALSE otherwise.
PGPBoolean
CPGPdiskDrv::IsFileInUseByWriter(LPCSTR path)
{
File existingFile;
DualErr derr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -