cvolumeimpdrv98.cpp
来自「PGP8.0源码 请认真阅读您的文件包然后写出其具体功能」· C++ 代码 · 共 874 行 · 第 1/2 页
CPP
874 行
PGPUInt8 locksUp = 0;
PGPUInt8 locksDown = 0;
if (curLock != lockLevel)
{
switch (curLock)
{
case LockLevel1:
switch (lockLevel)
{
case LockLevelNone:
locksDown = 1;
break;
case LockLevel2:
locksUp = 1;
break;
case LockLevel3:
locksUp = 2;
break;
default:
pgpAssert(FALSE);
break;
}
break;
case LockLevel2:
switch (lockLevel)
{
case LockLevelNone:
locksDown = 2;
break;
case LockLevel1:
locksDown = 1;
break;
case LockLevel3:
locksUp = 1;
break;
default:
pgpAssert(FALSE);
break;
}
break;
case LockLevel3:
switch (lockLevel)
{
case LockLevelNone:
locksDown = 3;
break;
case LockLevel1:
locksDown = 2;
break;
case LockLevel2:
locksDown = 1;
break;
default:
pgpAssert(FALSE);
break;
}
break;
default:
pgpAssert(FALSE);
break;
}
}
// If we need to get locks, we do that here.
while (error.IsntError() && (locksUp != 0))
{
PGPUInt16 lockValue;
locksUp--;
if (curLock == LockLevel1)
{
curLock = LockLevel2;
lockValue = 2;
}
else
{
curLock = LockLevel3;
lockValue = 3;
}
regs.eax = 0x440D; // function 440D
regs.ebx = (lockValue << 8) + drive + 1; // get lock
regs.ecx = 0x084A; // code 4A (Lock Volume)
regs.edx = 0; // > L1s expect zero here
regs.flags = 0x0001; // carry set if error
Exec_VxD_Int(0x21, ®s);
if (regs.flags & 0x0001)
{
error.pgpErr = kPGPError_VolumeOpFailed;
error.err = regs.eax;
}
}
// If we need to release locks, we do that here.
while (error.IsntError() && (locksDown !=0))
{
locksDown--;
if (curLock == LockLevel3)
curLock = LockLevel2;
else if (curLock == LockLevel2)
curLock = LockLevel1;
else if (curLock == LockLevel1)
curLock = LockLevelNone;
regs.eax = 0x440D; // function 440D
regs.ebx = drive + 1; // decrement lock level
regs.ecx = 0x086A; // code 6A (Unlock Volume)
regs.flags = 0x0001; // carry set if error
Exec_VxD_Int(0x21, ®s);
if (regs.flags & 0x0001)
{
error.pgpErr = kPGPError_VolumeOpFailed;
error.err = regs.eax;
}
}
}
}
UDebug::DebugOut("PGPdisk: Lock on drive %u is now %d", drive, lockLevel);
return error;
}
CComboError
CVolumeImpDrv98::AcquireFormatLock()
{
pgpAssert(IsMounted());
CComboError error;
// Make sure we aren't already locked;
LockLevel lockLevel;
error = GetLockLevel(lockLevel);
if (error.IsntError())
{
if (lockLevel != LockLevelNone)
error.pgpErr = kPGPError_VolumeOpFailed;
}
// First get a 'normal' level-0 lock.
if (error.IsntError())
{
PGPUInt8 drive = UString::LetterToNumber(mRoot[0]);
PGPUInt32 locksTaken = 0;
VxdIntRegs regs;
regs.eax = 0x440D; // function 440D
regs.ebx = 0x0000 + drive + 1; // L0 lock
regs.ecx = 0x084A; // (Lock Volume)
regs.edx = 0; // must be 0
regs.flags = 0x0001; // carry set if error
Exec_VxD_Int(0x21, ®s);
if (regs.flags & 0x0001)
{
error.pgpErr = kPGPError_VolumeOpFailed;
error.err = regs.eax;
}
else
{
locksTaken++;
}
// Now get a 'more restrictive' level-0 lock.
if (error.IsntError())
{
regs.eax = 0x440D; // function 440D
regs.ebx = 0x0000 + drive + 1; // L0 lock
regs.ecx = 0x084A; // (Lock Volume)
regs.edx = 4; // must be 4
regs.flags = 0x0001; // carry set if error
Exec_VxD_Int(0x21, ®s);
if (regs.flags & 0x0001)
{
error.pgpErr = kPGPError_VolumeOpFailed;
error.err = regs.eax;
}
else
{
locksTaken++;
}
}
// Undo what we did on error.
if (error.IsError())
{
while (locksTaken-- > 0)
{
regs.eax = 0x440D; // function 440D
regs.ebx = drive + 1; // decrement lock level
regs.ecx = 0x086A; // code 6A (Unlock Volume)
regs.flags = 0x0001; // carry flag set on error
Exec_VxD_Int(0x21, ®s);
}
}
}
return error;
}
CComboError
CVolumeImpDrv98::ReleaseFormatLock()
{
pgpAssert(IsLockedForFormat());
CComboError error;
// Make sure we aren't already locked;
LockLevel lockLevel;
error = GetLockLevel(lockLevel);
if (error.IsntError())
{
if (lockLevel != LockLevel0MR)
error.pgpErr = kPGPError_VolumeOpFailed;
}
// Release locks.
PGPUInt8 drive = UString::LetterToNumber(mRoot[0]);
PGPUInt32 locksTaken = 2;
while (error.IsntError() && (locksTaken-- > 0))
{
VxdIntRegs regs;
regs.eax = 0x440D; // function 440D
regs.ebx = drive + 1; // decrement lock level
regs.ecx = 0x086A; // code 6A (Unlock Volume)
regs.flags = 0x0001; // carry flag set on error
Exec_VxD_Int(0x21, ®s);
if (regs.flags & 0x0001)
{
error.pgpErr = kPGPError_VolumeOpFailed;
error.err = regs.eax;
}
}
return error;
}
CComboError
CVolumeImpDrv98::FillInBlockInfo()
{
CComboError error;
if (error.IsntError())
{
mBlockSize = static_cast<PGPUInt32>(mDcb.CalcBlockSizeFromShift());
mTotalBlocks = mDcb.SectorCount();
}
return error;
}
void
CVolumeImpDrv98::InitDcb(
PGPUInt8 drive,
PGPUInt64 totalBlocks,
PGPUInt32 blockSize,
PGPBoolean readOnly)
{
PGPUInt32 secsPerTrack, tracksPerCyl;
PGPUInt64 cylinders;
UFileSys::CalcFakeFatGeom(blockSize, tracksPerCyl, cylinders,
secsPerTrack);
mDcb.PhysicalDcb() = static_cast<PDCB>(mDcb);
mDcb.Drive() = drive;
mDcb.TsdFlags() = DCB_TSD_NO_USER_INT13 | DCB_TSD_BAD_MBR;
mDcb.DeviceFlags() = DCB_DEV_LOGICAL;
mDcb.BlockShift() = UMath::SimpleLog2(blockSize);
mDcb.PartitionType() = FileSys::kBigFat16PartId;
mDcb.DeviceType() = DCB_type_disk;
mDcb.UserDrive() = 0xffff;
mDcb.MaxTransferLength() = FileSys::kMaxHeads*FileSys::kMaxSpt*
FileSys::kMaxCyls;
mDcb.SectorCount() = totalBlocks;
mDcb.BlockSize() = blockSize;
mDcb.Heads() = tracksPerCyl;
mDcb.Cylinders() = static_cast<PGPUInt32>(cylinders);
mDcb.Spt() = secsPerTrack;
mDcb.PortSpecific() = reinterpret_cast<PGPUInt32>(this);
mDcb.BusType() = DCB_BUS_ESDI;
mDcb.BddDeviceSubtype() = BDT_Fixed_Disk;
mDcb.BddFlags() = BDF_VERSION_002;
mDcb.BddSectorCount() = totalBlocks;
mDcb.BddBlockSize() = blockSize;
mDcb.BddHeads() = tracksPerCyl;
mDcb.BddCylinders() = static_cast<PGPUInt32>(cylinders);
mDcb.BddSpt() = secsPerTrack;
strncpy(mDcb.VendorId(), kDcbVendorId, strlen(kDcbVendorId));
strncpy(mDcb.ProductId(), kDcbProductId, strlen(kDcbProductId));
strncpy(mDcb.RevLevel(), kDcbRevLevel, strlen(kDcbRevLevel));
if (CVolume::kUseRemovableFlag)
{
mDcb.DeviceFlags() |= DCB_DEV_REMOVABLE;
mDcb.BddFlags() |= BDF_Removable;
}
if (!readOnly)
{
mDcb.DeviceFlags() |= DCB_DEV_WRITEABLE;
mDcb.BddFlags() |= BDF_Writeable;
}
}
CComboError
CVolumeImpDrv98::DiskAccess(
PGPUInt16 func,
void *buf,
PGPUInt64 pos,
PGPUInt32 nBlocks) const
{
pgpAssert(IsMounted());
pgpAssert((func == IOR_READ) || (func == IOR_WRITE));
pgpAssertAddrValid(buf, VoidAlign);
CComboError error;
// Make sure we check that the VRP field in the DCB exists; the system
// has a habit of nullifying it when an I/O error occurs.
PVRP pVrp = mDcb.Vrp();
if (IsNull(pVrp))
error.pgpErr = kPGPError_VolumeOpFailed;
if (error.IsntError())
{
CIop iop;
// Create our IOP/IOR.
error = iop.Create(pVrp, ISP_M_FL_INTERRUPT_TIME);
if (error.IsntError())
{
// Fill in the IOP/IOR.
iop.Func() = func; // IOR_READ or IOR_WRITE
iop.Flags() |= IORF_HIGH_PRIORITY // high priority
| IORF_LOGICAL_START_SECTOR // in partition
| IORF_SYNC_COMMAND; // synchronous
iop.StartAddress() = pos;
iop.TransferCount() = nBlocks;
iop.Buffer() = buf;
iop.ReqVolHandle() = pVrp;
iop.Drive() = UString::LetterToNumber(mRoot[0]);
// Ask the system to massage the IOP.
if (!iop.DoIlbCriteria())
{
UDebug::DebugOut("PGPdisk: IlbIoCriteria in "
"CVolumeImpDrv98::DiskAccess failed!");
}
UDebug::DebugOut("PGPdisk: Before volume access IOR %X func %u "
"pos %u nBlocks %u drive %u", &iop.Ior(), func,
UMath::GetLowDWord(pos), nBlocks,
UString::LetterToNumber(mRoot[0]));
// Call down the IOP.
iop.SendCommand(mDcb);
UDebug::DebugOut("PGPdisk: After volume access IOR %X",
&iop.Ior());
if (iop.IsStatusError())
{
if (func == IOR_READ)
{
error.pgpErr = kPGPError_ReadFailed;
error.err = iop.GetErrorAsWin32();
}
else
{
error.pgpErr = kPGPError_WriteFailed;
error.err = iop.GetErrorAsWin32();
}
}
iop.Destroy();
}
}
return error;
}
void
CVolumeImpDrv98::DispatchIopAux(CIop& iop)
{
mDispatchFunc(iop, mRefPtr);
}
void
CVolumeImpDrv98::DispatchIopStub(PIOP pIop)
{
CIop iop(pIop);
CDcb dcb(reinterpret_cast<PDCB>(iop.OriginalDcb()));
CVolumeImpDrv98 *pImp = reinterpret_cast<CVolumeImpDrv98 *>(
dcb.PortSpecific());
pgpAssertAddrValid(pImp, CVolumeImpDrv98);
pImp->DispatchIopAux(iop);
}
void
CVolumeImpDrv98::DispatchIop(PIOP pIop)
{
// Get around a MSVC5 compiler bug (involving the stack and IOS).
DispatchIopStub(pIop);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?