cpgpdiskimp.cpp
来自「PGP8.0源码 请认真阅读您的文件包然后写出其具体功能」· C++ 代码 · 共 571 行
CPP
571 行
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CPGPdiskImp.cpp,v 1.11 2002/09/26 01:32:11 wjb Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include "CString.h"
#include "UDebug.h"
#include "UMath.h"
#include "CCipherContext.h"
#include "DriverAPI.h"
#include "pgpClientErrors.h"
#include "CDiskInactivity.h"
#include "CDriverSubsystems.h"
#include "CPGPdiskImp.h"
_USING_PGP
// Class CPGPdiskImp member functions
CPGPdiskImp::~CPGPdiskImp()
{
if (IsMounted())
Unmount(TRUE);
}
CPGPdiskImp::CPGPdiskImp() : mTimeoutActive(FALSE), mHasTimedOut(FALSE)
{
Status() = mVolume.Status();
if (Status().IsntError())
Status() = mCipherContextMutex.Status();
}
void
CPGPdiskImp::FlipContexts()
{
mCipherContextMutex.Enter();
mCipherContext.FlipKeyBytes();
mCipherContextMutex.Leave();
}
CComboError
CPGPdiskImp::ValidateContexts()
{
CComboError error;
mCipherContextMutex.Enter();
error = mCipherContext.Validate();
mCipherContextMutex.Leave();
return error;
}
CComboError
CPGPdiskImp::SetInactivityTimeout(PGPUInt32 seconds)
{
pgpAssert(IsMounted());
CComboError error;
if (mTimeoutActive)
{
error = CDriverSubsystems::DiskInactivity().DestroyInactivityTimer(
mTimeoutId);
if (error.IsntError())
{
mTimeoutActive = FALSE;
mHasTimedOut = FALSE;
}
}
if (error.IsntError())
{
if (seconds > 0)
{
error = CDriverSubsystems::DiskInactivity().CreateInactivityTimer(
seconds, TRUE, InactivityTimerCallback,
reinterpret_cast<ULONG>(this), mTimeoutId);
if (error.IsntError())
mTimeoutActive = TRUE;
}
}
return error;
}
void
CPGPdiskImp::ResetTimedOut()
{
mHasTimedOut = FALSE;
}
CComboError
CPGPdiskImp::Mount(
const char *path,
const char *root,
const char *deviceName,
PGPdiskEncryptionAlgorithm algorithm,
const void *exportedContext,
PGPUInt32 sizeContext,
PGPUInt64 firstDataBlock,
PGPUInt64 numDataBlocks,
const void *ioHandlerFunc,
void *refPtr,
PGPUInt32 procId,
PGPBoolean readOnly)
{
pgpAssertStrValid(path);
pgpAssertStrValid(root);
pgpAssertStrValid(deviceName);
pgpAssertAddrValid(exportedContext, VoidAlign);
pgpAssert(sizeContext > 0);
pgpAssertAddrValid(ioHandlerFunc, VoidAlign);
CComboError error;
mIsReadOnly = readOnly;
mFirstDataBlock = firstDataBlock;
mNumDataBlocks = numDataBlocks;
// Open the PGPdisk file.
PGPUInt16 flags = CFile::kNoBufferingFlag;
if (IsReadOnly())
flags |= CFile::kReadOnlyFlag;
error = mFile.Open(path, flags);
if (error.IsntError())
{
// Read in blocksize of host drive.
error = CalcBlockSizeOfHost(path, mHostBlockSize);
if (error.IsntError())
{
// Create buffer of appropriate size, aligned properly.
mBufferObject = new CArray<PGPByte>(BlocksPerOp *
mHostBlockSize + PFLConstants::kPlatformPageSize);
if (IsNull(mBufferObject))
error.pgpErr = kPGPError_OutOfMemory;
if (error.IsntError())
error = mBufferObject->Status();
if (error.IsntError())
{
// Use only page-aligned portion of buffer.
PGPUInt32 baseAddress = reinterpret_cast<PGPUInt32>(
mBufferObject->Get());
mBuffer = reinterpret_cast<PGPByte *>(
UMath::RoundUpToMultiple<PGPUInt32>(baseAddress,
PFLConstants::kPlatformPageSize));
// Initliaze the cipher context.
error = mCipherContext.Init(algorithm);
if (error.IsntError())
{
// Import the cipher context data.
mCipherContext.Import(exportedContext, sizeContext);
// Create the PGPdisk I/O thread.
if (IsNull(mIoThread = new CThread))
error.pgpErr = kPGPError_OutOfMemory;
if (error.IsntError())
{
// Start the PGPdisk I/O thread.
error = mIoThread->StartThread(MaxQueuedIoReqs);
// Call down to base classe for pre-mount tasks.
if (error.IsntError())
error = PerformPremountTasks();
if (error.IsntError())
{
// Create the PGPdisk volume.
error = mVolume.Mount(deviceName, root,
mNumDataBlocks, kPGPdiskBlockSize,
ioHandlerFunc, refPtr, IsReadOnly());
if (error.IsError())
mIoThread->KillThread();
}
if (error.IsError())
{
delete mIoThread;
mIoThread = NULL;
}
}
if (error.IsError())
mCipherContext.Cleanup();
}
if (error.IsError())
{
delete mBufferObject;
mBufferObject = NULL;
mBuffer = NULL;
}
}
}
if (error.IsError())
mFile.Close();
}
return error;
}
CComboError
CPGPdiskImp::Unmount(PGPBoolean isForced)
{
CComboError error;
pgpAssert(IsMounted());
// Fail if the PGPdisk has open files.
if (mVolume.HasOpenFiles())
error.pgpErr = kPGPClientError_FilesOpenOnDisk; // NETABUG has open files?
if (isForced)
error = CComboError();
// Destroy any active inactivity timeouts.
if (error.IsntError())
error = SetInactivityTimeout(0);
// Destroy the PGPdisk volume.
if (error.IsntError())
error = mVolume.Unmount(isForced);
if (error.IsntError())
{
// Kill the IO thread.
mIoThread->KillThread();
delete mIoThread;
mIoThread = NULL;
// Destroy the cipher context.
mCipherContext.Cleanup();
// Delete the data buffer.
delete mBufferObject;
mBufferObject = NULL;
mBuffer = NULL;
// Close the PGPdisk file.
mFile.Close();
}
return error;
}
CComboError
CPGPdiskImp::Read(void *buf, PGPUInt64 posInBlocks, PGPUInt32 nBlocks) const
{
pgpAssertAddrValid(buf, PGPByte);
pgpAssert(IsMounted());
CComboError error;
UDebug::DebugOut("PGPdisk: Reading PGPdisk %s at pos %u nBlocks "
"%u\n", Root(), static_cast<PGPUInt32>(posInBlocks), nBlocks);
// Moved around actual decrypt calls because of fsecure hang -wjb
// mCipherContextMutex.Enter();
// We must handle the case where the PGPdisk block size is less than the
// block size of the underlying volume by breaking up the request.
PGPUInt64 posInBytes = posInBlocks * kPGPdiskBlockSize;
PGPUInt32 nBytes = nBlocks * kPGPdiskBlockSize;
PGPUInt32 bufPos = 0;
if (posInBytes % mHostBlockSize > 0) // is there a head?
{
// Now read in the head.
//
// blockPGPdisk = block on PGPdisk containing the head
// headOffset = byte offset into block where head starts
// headSize = size of the head, in bytes
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
PGPUInt32 headOffset = static_cast<PGPUInt32>(posInBytes %
mHostBlockSize);
PGPUInt32 headSize = pgpMin(nBytes, mHostBlockSize -
headOffset);
error = mFile.Read(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
if (error.IsntError())
{
// Decrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.DecryptCFB(
posInBytes / kPGPdiskBlockSize,
headSize / kPGPdiskBlockSize, mBuffer + headOffset, buf);
mCipherContextMutex.Leave();
}
if (error.IsntError())
{
bufPos = headSize;
posInBytes += headSize;
nBytes -= headSize;
}
}
// Read the middle in chunks.
if (error.IsntError())
{
PGPUInt32 blocksToRead = nBytes / mHostBlockSize;
while (error.IsntError() && (blocksToRead > 0)) // is middle?
{
// Determine exactly how many blocks to read this iteration.
//
// blockPGPdisk = block on the PGPdisk where this read begins
// blocksChunk = the most blocks we can read in this iteration
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
PGPUInt32 blocksChunk = pgpMin(blocksToRead, BlocksPerOp);
error = mFile.Read(mBuffer, blockPGPdisk * mHostBlockSize,
blocksChunk * mHostBlockSize);
if (error.IsntError())
{
// Decrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.DecryptCFB(
posInBytes / kPGPdiskBlockSize,
(blocksChunk * mHostBlockSize) / kPGPdiskBlockSize,
mBuffer, static_cast<PGPByte *>(buf) + bufPos);
mCipherContextMutex.Leave();
}
if (error.IsntError())
{
bufPos += blocksChunk * mHostBlockSize;
nBytes -= blocksChunk * mHostBlockSize;
posInBytes += blocksChunk * mHostBlockSize;
blocksToRead -= blocksChunk;
}
}
}
// Read in the tail.
if (error.IsntError())
{
if (nBytes > 0) // is there a tail?
{
// This read is very simple because we know the tail begins on a
// block boundary.
//
// blockPGPdisk = the block in the PGPdisk containing the tail.
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
error = mFile.Read(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
if (error.IsntError())
{
// Decrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.DecryptCFB(
posInBytes / kPGPdiskBlockSize,
nBytes / kPGPdiskBlockSize, mBuffer,
static_cast<PGPByte *>(buf) + bufPos);
mCipherContextMutex.Leave();
}
}
}
// Moved around actual decrypt calls because of fsecure hang -wjb
// mCipherContextMutex.Leave();
return error;
}
CComboError
CPGPdiskImp::Write(const void *buf, PGPUInt64 posInBlocks, PGPUInt32 nBlocks)
{
pgpAssertAddrValid(buf, PGPByte);
pgpAssert(IsMounted());
CComboError error;
UDebug::DebugOut("PGPdisk: Writing PGPdisk %s at pos %u nBlocks "
"%u\n", Root(), static_cast<PGPUInt32>(posInBlocks), nBlocks);
// Moved around actual decrypt calls because of fsecure hang -wjb
// mCipherContextMutex.Enter();
// We must handle the case where the PGPdisk block size is less than the
// block size of the underlying volume by breaking up the request.
PGPUInt64 posInBytes = posInBlocks * kPGPdiskBlockSize;
PGPUInt32 nBytes = nBlocks * kPGPdiskBlockSize;
PGPUInt32 bufPos = 0;
if (posInBytes % mHostBlockSize > 0) // is there a head?
{
// Now write out the head.
//
// blockPGPdisk = block on PGPdisk containing the head
// headOffset = byte offset into block where head starts
// headSize = size of the head, in bytes
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
PGPUInt32 headOffset = static_cast<PGPUInt32>(posInBytes %
mHostBlockSize);
PGPUInt32 headSize = pgpMin(nBytes, mHostBlockSize -
headOffset);
// Must read in existing head first.
error = mFile.Read(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
if (error.IsntError())
{
// Encrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.DecryptCFB(
posInBytes / kPGPdiskBlockSize,
headSize / kPGPdiskBlockSize, buf, mBuffer + headOffset);
mCipherContextMutex.Leave();
}
if (error.IsntError())
{
// Write out the modified header.
error = mFile.Write(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
}
if (error.IsntError())
{
bufPos = headSize;
posInBytes += headSize;
nBytes -= headSize;
}
}
// Write the middle in chunks.
if (error.IsntError())
{
PGPUInt32 blocksToWrite = nBytes / mHostBlockSize;
while (error.IsntError() && (blocksToWrite > 0)) // is middle?
{
// Determine exactly how many blocks to write this iteration.
//
// blockPGPdisk = block on the PGPdisk where this write begins
// blocksChunk = the most blocks we can read in this iteration
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
PGPUInt32 blocksChunk = pgpMin(blocksToWrite, BlocksPerOp);
// Encrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.EncryptCFB(
posInBytes / kPGPdiskBlockSize,
(blocksChunk * mHostBlockSize) / kPGPdiskBlockSize,
static_cast<const PGPByte *>(buf) + bufPos, mBuffer);
mCipherContextMutex.Leave();
if (error.IsntError())
{
// Write out the blocks.
error = mFile.Write(mBuffer, blockPGPdisk * mHostBlockSize,
blocksChunk * mHostBlockSize);
}
if (error.IsntError())
{
bufPos += blocksChunk * mHostBlockSize;
nBytes -= blocksChunk * mHostBlockSize;
posInBytes += blocksChunk * mHostBlockSize;
blocksToWrite -= blocksChunk;
}
}
}
// Write out the tail.
if (error.IsntError())
{
if (nBytes > 0) // is there a tail?
{
// This read is very simple because we know the tail begins on a
// block boundary.
//
// blockPGPdisk = the block in the PGPdisk containing the tail.
PGPUInt64 blockPGPdisk = (posInBytes + mFirstDataBlock *
kPGPdiskBlockSize) / mHostBlockSize;
// Must read in existing tail first.
error = mFile.Read(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
if (error.IsntError())
{
// Encrypt the blocks.
mCipherContextMutex.Enter();
error = mCipherContext.DecryptCFB(
posInBytes / kPGPdiskBlockSize,
nBytes / kPGPdiskBlockSize,
static_cast<const PGPByte *>(buf) + bufPos, mBuffer);
mCipherContextMutex.Leave();
}
if (error.IsntError())
{
// Write out the modified tail.
error = mFile.Write(mBuffer, blockPGPdisk * mHostBlockSize,
mHostBlockSize);
}
}
}
// Moved around actual decrypt calls because of fsecure hang -wjb
// mCipherContextMutex.Leave();
return error;
}
void
CPGPdiskImp::InactivityTimerCallback(ULONG userVal)
{
CPGPdiskImp *pImp = reinterpret_cast<CPGPdiskImp *>(userVal);
pgpAssertAddrValid(pImp, CPGPdiskImp);
pImp->mHasTimedOut = TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?