📄 cpgpdiskdrvvolumes.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// CPGPdiskDrvVolumes.cpp
//
// Contains high-level functions for working with PGPdisks.
//////////////////////////////////////////////////////////////////////////////
// $Id: CPGPdiskDrvVolumes.cpp,v 1.8 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 "PGPdiskHighLevelUtils.h"
#include "UtilityFunctions.h"
#include "CPGPdiskDrvVolumes.h"
#include "CPGPdiskDrvWinutils.h"
#include "Globals.h"
//////////////////////////////////////
// Mount and unmount utility functions
//////////////////////////////////////
// MountPGPdisk mounts the PGPdisk file specified by 'path' and returns the
// drive number it was mounted on.
DualErr
CPGPdiskDrv::MountPGPdisk(
LPCSTR path,
CipherContext *context,
PGPUInt8 drive,
PGPBoolean mountReadOnly)
{
DualErr derr;
PDCB newDcb;
PGPBoolean addedPGPdisk, createdPGPdiskObject, gotDcb, isPathLooped;
PGPdisk *pPGD;
pgpAssertStrValid(path);
pgpAssertAddrValid(context, CipherContext);
addedPGPdisk = createdPGPdiskObject = gotDcb = isPathLooped = FALSE;
// We must first check if we have space for another PGPdisk.
if (mPGPdisks.GetNumPGPdisks() >= kMaxMountedPGPdisks)
derr = DualErr(kPGDMinorError_MaxPGPdisksMounted);
// Search for any pre-existing PGPdisks corresponding to the path.
if (derr.IsntError())
{
if (mPGPdisks.FindPGPdisk(path))
derr = DualErr(kPGDMinorError_PGPdiskAlreadyMounted);
}
// Validate the PGPdisk.
if (derr.IsntError())
{
derr = ValidatePGPdisk(path);
}
// If the PGPdisk is opened by someone else with write access, fail.
if (derr.IsntError())
{
if (IsFileInUseByWriter(path))
derr = DualErr(kPGDMinorError_PGPdiskAlreadyInUse);
}
// Create a new PGPdisk object.
if (derr.IsntError())
{
if (!(pPGD = new PGPdisk()))
derr = DualErr(kPGDMinorError_OutOfMemory);
createdPGPdiskObject = derr.IsntError();
}
if (derr.IsntError())
{
derr = pPGD->mInitErr;
}
// We now get a new DCB.
if (derr.IsntError())
{
derr = mDcbs.NewDcb(&newDcb);
gotDcb = derr.IsntError();
}
// Attempt our mount.
if (derr.IsntError())
{
derr = pPGD->Mount(path, context, newDcb, drive, mountReadOnly);
}
if (derr.IsntError())
{
// Attach the object to the global list.
mPGPdisks.AddPGPdisk(pPGD);
addedPGPdisk = TRUE;
// Hook an ejection filter to the host.
if (!IsUNCPath(pPGD->GetPath()))
derr = HookEjectionFilter(pPGD->GetLocalHostDrive());
}
// Cleanup if an error occurred.
if (derr.IsError())
{
if (addedPGPdisk)
{
mPGPdisks.RemovePGPdisk(pPGD);
}
if (createdPGPdiskObject)
{
if (pPGD->Mounted())
pPGD->Unmount();
delete pPGD;
}
if (gotDcb)
{
mDcbs.DeleteDcb(newDcb);
}
}
return derr;
}
// UnmountPGPdisk unmounts the PGPdisk specified by 'drive'.
DualErr
CPGPdiskDrv::UnmountPGPdisk(PGPUInt8 drive, PGPBoolean isThisEmergency)
{
DualErr derr;
PDCB oldDcb;
PGPBoolean removedPGPdisk = FALSE;
PGPdisk *pPGD;
PGPUInt32 i = 0;
pgpAssert(IsLegalDriveNumber(drive));
// First we verify that the PGPdisk exists and is mounted.
if (IsNull(pPGD = mPGPdisks.FindPGPdisk(drive)))
derr = DualErr(kPGDMinorError_PGPdiskNotMounted);
// If IO is disabled to the drive, make this an emergency automatically.
if (derr.IsntError())
{
if (!pPGD->IsIOEnabled())
isThisEmergency = TRUE;
}
// If I/O to this drive is in process, don't unmount. This OVERRIDES
// 'isThisEmergency'.
if (derr.IsntError())
{
if (pPGD->IsUnmountPending())
derr = DualErr(kPGDMinorError_FailSilently);
else if (mIopProcessor.IsDriveBusy(drive))
derr = DualErr(kPGDMinorError_PGPdiskIsBusy);
else
pPGD->MarkUnmountPending(TRUE);
}
// If this PGPdisk has other PGPdisks mounted on it, we must perform a
// depth-first unmount of all those PGPdisks first.
while (derr.IsntError())
{
PGPdisk *pClient;
if (!(pClient = Driver->mPGPdisks.EnumPGPdisks(i++)))
break;
if (!IsUNCPath(pClient->GetPath()) &&
(pClient->GetLocalHostDrive() == drive))
{
i = 0;
derr = UnmountPGPdisk(pClient->GetDrive(), isThisEmergency);
}
}
// Check if the PGPdisk has open files.
if (derr.IsntError())
{
if (pPGD->HasOpenFiles())
derr = DualErr(kPGDMinorError_FilesOpenOnDrive);
if (isThisEmergency)
derr = DualErr::NoError;
}
// Remove the object from the global list and attempt the unmount.
if (derr.IsntError())
{
mPGPdisks.RemovePGPdisk(pPGD);
removedPGPdisk = TRUE;
oldDcb = pPGD->GetDcb();
derr = pPGD->Unmount(isThisEmergency);
}
// Delete the previously created DCB.
if (derr.IsntError())
{
mDcbs.DeleteDcb(oldDcb);
delete pPGD;
}
// Cleanup if an error occurred;
if (derr.IsError())
{
pPGD->MarkUnmountPending(FALSE);
if (removedPGPdisk && pPGD->Mounted())
mPGPdisks.AddPGPdisk(pPGD);
}
return derr;
}
// UnmountAllPGPdisks unmounts all PGPdisks in the system.
DualErr
CPGPdiskDrv::UnmountAllPGPdisks(PGPBoolean isThisEmergency)
{
DualErr derr, storedDerr;
PGPUInt8 drive;
PGPUInt32 i = 0;
PGPdisk *pPGD;
// Note how we enumerate on position 0, and increase this only when we
// find a drive we can't unmount for whatever reason. This is because
// if a drive can't be unmounted it won't be removed, and thus 'sticks'
// at position 0, 1, etc.
while (pPGD = mPGPdisks.EnumPGPdisks(i))
{
pgpAssert(pPGD->Mounted());
drive = pPGD->GetDrive();
// Now attempt the unmount.
if (derr.IsntError())
{
derr = UnmountPGPdisk(drive, isThisEmergency);
}
// Remember only the first error we see.
if (derr.IsError())
{
if (storedDerr.IsntError())
{
storedDerr = derr;
}
derr = DualErr::NoError;
i++;
}
}
return storedDerr;
}
// UnmountAllPGPdisksCallback is scheduled to unmount all PGPdisk at a safe
// time.
VOID
__stdcall
CPGPdiskDrv::UnmountAllPGPdisksCallback(
VMHANDLE hVM,
THREADHANDLE hThread,
PVOID Refdata,
PCLIENT_STRUCT pRegs)
{
DualErr derr;
PGPBoolean warnIfUnmountsFail = (PGPBoolean) Refdata;
derr = Driver->UnmountAllPGPdisks(FALSE);
if (derr.IsError() && warnIfUnmountsFail)
{
Driver->ReportError(kPGDMajorError_PGPdiskUnmountAllFailed, derr);
}
}
// UnmountAllPGPdisksSafely schedules a callback to unmount all PGPdisks at a
// safe time.
void
CPGPdiskDrv::UnmountAllPGPdisksSafely(PGPBoolean warnIfUnmountsFail)
{
static RestrictedEvent_THUNK callbackThunk;
Call_Restricted_Event(0, NULL, PEF_WAIT_NOT_CRIT,
(PVOID) warnIfUnmountsFail, UnmountAllPGPdisksCallback, 0,
&callbackThunk);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -