⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpdisk.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				blocksToRead	-= blocksChunk;
			}
		}
	}
	
	// Read in the tail.
	if (derr.IsntError())
	{
		if (nBytes)					// 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.

			blockPGPdisk = pos/kDefaultBlockSize;

			derr = VolFile::Read(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
				kDefaultBlockSize);

			if (derr.IsntError())
			{
				SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
					kCipherOp_Decrypt);

				pgpCopyMemory(mDataBuf, buf + bufPos, nBytes);
			}
		}
	}

	return derr;
}

// WriteSync performs a write request on the mounted PGPdisk synchronously.

DualErr 
PGPdisk::WriteSync(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBytes)
{
	DualErr		derr;
	PGPUInt32	blocksChunk, blocksToWrite, bufPos;
	PGPUInt64	blockPGPdisk;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssert(Mounted());

	// The position (pos) and size (nBytes) variables are in bytes, but we
	// can only perform encryption in blocks. What we have to do is handle
	// the request in at most three separate pieces - a head, middle, and
	// end.

	bufPos = 0;

	if (pos%kDefaultBlockSize > 0)	// is there a head?
	{
		PGPUInt32 headOffset, headSize;

		// Now write the head.
		//
		// blockPGPdisk = block on PGPdisk containing the head.
		// headOffset = byte offset into blockPGPdisk where head starts
		// headSize = size of the head, in bytes

		blockPGPdisk	= pos/kDefaultBlockSize;
		headOffset		= (PGPUInt32) (pos%kDefaultBlockSize);
		headSize		= min(nBytes, kDefaultBlockSize - headOffset);

		derr = VolFile::Read(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
			kDefaultBlockSize);

		if (derr.IsntError())
		{
			SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
				kCipherOp_Decrypt);

			pgpCopyMemory(buf, mDataBuf + headOffset, headSize);

			SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
				kCipherOp_Encrypt);

			derr = VolFile::Write(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
				kDefaultBlockSize);
		}

		if (derr.IsntError())
		{
			bufPos	= headSize;
			pos		+= headSize;
			nBytes	-= headSize;
		}
	}

	// Write the middle, in 'kPGDBlocksPerOp' chunks.
	if (derr.IsntError())
	{
		blocksToWrite = nBytes/kDefaultBlockSize;

		while (derr.IsntError() && (blocksToWrite > 0))	// is there a 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 write in this iteration

			blockPGPdisk	= pos/kDefaultBlockSize;
			blocksChunk		= min(blocksToWrite, kPGDBlocksPerOp);

			SmartCipherBlocks(blockPGPdisk, blocksChunk, buf + bufPos, 
				mDataBuf, kCipherOp_Encrypt);

			derr = VolFile::Write(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
				blocksChunk*kDefaultBlockSize);

			if (derr.IsntError())
			{
				bufPos			+= blocksChunk * kDefaultBlockSize;
				nBytes			-= blocksChunk * kDefaultBlockSize;
				pos				+= blocksChunk * kDefaultBlockSize;
				blocksToWrite	-= blocksChunk;
			}
		}
	}
	
	// Write in the tail.
	if (derr.IsntError())
	{
		if (nBytes)					// 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.

			blockPGPdisk = pos/kDefaultBlockSize;

			derr = VolFile::Read(mDataBuf, blockPGPdisk*kDefaultBlockSize, 
				kDefaultBlockSize);

			if (derr.IsntError())
			{
				SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
					kCipherOp_Decrypt);

				pgpCopyMemory(buf, mDataBuf, nBytes);

				SmartCipherBlocks(blockPGPdisk, 1, mDataBuf, mDataBuf, 
					kCipherOp_Encrypt);

				derr = VolFile::Write(mDataBuf, 
					blockPGPdisk*kDefaultBlockSize, kDefaultBlockSize);
			}
		}
	}

	return derr;
}

// Read performs a read request on the mounted PGPdisk.

	DualErr 
PGPdisk::Read(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr derr;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssert(Mounted());

	DebugOut("PGPdisk: Reading PGPdisk %u at pos %u nBlocks %u", GetDrive(), 
		(PGPUInt32) (pos/kDefaultBlockSize), 
		(PGPUInt32) (nBytes/kDefaultBlockSize));

	if (upInfo)
		ReadAsync(buf, pos, nBytes, upInfo);
	else
		derr = ReadSync(buf, pos, nBytes);

	return derr;
}

// Write performs a write request on the mounted PGPdisk.

DualErr 
PGPdisk::Write(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBytes, 
	GenericCallbackInfo	*upInfo)
{
	DualErr derr;

	pgpAssertAddrValid(buf, PGPUInt8);
	pgpAssert(Mounted());

	DebugOut("PGPdisk: Writing PGPdisk %u at pos %u nBlocks %u", GetDrive(), 
		(PGPUInt32) (pos/kDefaultBlockSize), 
		(PGPUInt32) (nBytes/kDefaultBlockSize));

	if (upInfo)
		WriteAsync(buf, pos, nBytes, upInfo);
	else
		derr = WriteSync(buf, pos, nBytes);

	return derr;
}


/////////////////////////////////////////
// Class PGPdisk private member functions
/////////////////////////////////////////

// SmartCipherBlocks performs the given cipher operation using whichever
// cipher context isn't flipped.

void 
PGPdisk::SmartCipherBlocks(
	PGPUInt64	startBlockIndex, 
	PGPUInt32	nBlocks, 
	const void	*src, 
	void		*dest, 
	CipherOp	op)
{
	pgpAssertAddrValid(mContextA, CipherContext);
	pgpAssertAddrValid(mContextB, CipherContext);
			
	if (mContextA->IsFlipped())
		mContextB->CipherBlocks(startBlockIndex, nBlocks, src, dest, op);
	else
		mContextA->CipherBlocks(startBlockIndex, nBlocks, src, dest, op);
}

// ExecuteRequest executes the next 'piece' of the current request. If there
// nothing left to execute, 'doneWithRequest' is set to TRUE, otherwise FALSE.

void 
PGPdisk::ExecuteRequest(PGPBoolean *doneWithRequest)
{
	PGPUInt8	*buf;
	PGPUInt32	nBytes;
	PGPUInt64	pos;

	pgpAssertAddrValid(doneWithRequest, PGPBoolean);
	(* doneWithRequest) = FALSE;

	pgpAssert(mPGPdiskReq.isInUse);

	// Look for the next piece of the request and process it. Read requests
	// can consist of reading the header, the tail, or any number of pieces
	// in the middle. Write requests are similar except header and tail
	// processing must be done in two parts.

	switch (mPGPdiskReq.op)
	{

	case kPGDOP_Read:
		if (!mPGPdiskReq.read.readHeader)
		{
			// Read in the header block.

			pos = mPGPdiskReq.read.posHeader;

			VolFile::Read(mDataBuf, pos - pos%kDefaultBlockSize, 
				kDefaultBlockSize, &mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.read.readMiddle)
		{
			PGPUInt32 bytesToRead;

			// Read in as much of the middle as we can. Leave the rest for
			// later.

			pos			= mPGPdiskReq.read.posMiddle;
			nBytes		= mPGPdiskReq.read.nBytesMiddle;
			bytesToRead	= min(nBytes, kPGDBlocksPerOp*kDefaultBlockSize);

			VolFile::Read(mDataBuf, pos, bytesToRead, &mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.read.readTail)
		{
			// Read in the tail block.
			pos = mPGPdiskReq.read.posTail;

			VolFile::Read(mDataBuf, pos, kDefaultBlockSize, 
				&mPGPdiskReq.downInfo);
		}
		else
		{
			(* doneWithRequest) = TRUE;
		}
		break;

	case kPGDOP_Write:
		if (!mPGPdiskReq.write.readHeader)
		{
			// Read in the header block. This must be done because we can't
			// encrypt in units smaller than one block. Once we've read in
			// the header, we modify it with data from the input buffer,
			// encrypt the whole block, and write it out.

			pos = mPGPdiskReq.write.posHeader;

			VolFile::Read(mDataBuf, pos - pos%kDefaultBlockSize, 
				kDefaultBlockSize, &mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.write.wroteHeader)
		{
			// We read in the header block, now modify it with the changed
			// data from the input buffer, encrypt it, and write it out.

			buf		= mPGPdiskReq.write.bufHeader;
			pos		= mPGPdiskReq.write.posHeader;
			nBytes	= mPGPdiskReq.write.nBytesHeader;

			pgpAssertAddrValid(buf, PGPUInt8);
			pgpCopyMemory(buf, mDataBuf + pos%kDefaultBlockSize, nBytes);

			SmartCipherBlocks(pos/kDefaultBlockSize, 1, mDataBuf, mDataBuf, 
				kCipherOp_Encrypt);

			VolFile::Write(mDataBuf, pos - pos%kDefaultBlockSize, 
				kDefaultBlockSize, &mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.write.wroteMiddle)
		{
			PGPUInt32 bytesToWrite;

			// Encrypt and write out as much of the middle as we can. Leave
			// the rest for later.

			buf		= mPGPdiskReq.write.bufMiddle;
			pos		= mPGPdiskReq.write.posMiddle;
			nBytes	= mPGPdiskReq.write.nBytesMiddle;

			bytesToWrite = min(nBytes, kPGDBlocksPerOp*kDefaultBlockSize);

			SmartCipherBlocks(pos/kDefaultBlockSize, 
				bytesToWrite/kDefaultBlockSize, buf, mDataBuf, 
				kCipherOp_Encrypt);

			VolFile::Write(mDataBuf, pos, bytesToWrite, 
				&mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.write.readTail)
		{
			// Read in the tail block. This must be done because we can't
			// encrypt in units smaller than one block. Once we've read in
			// the tail, we modify it with data from the input buffer,
			// encrypt the whole block, and write it out.

			pos = mPGPdiskReq.write.posTail;

			VolFile::Read(mDataBuf, pos - pos%kDefaultBlockSize, 
				kDefaultBlockSize, &mPGPdiskReq.downInfo);
		}
		else if (!mPGPdiskReq.write.wroteTail)
		{
			// We read in the tail block, now modify it with the changed
			// data from the input buffer, encrypt it, and write it out.

			buf		= mPGPdiskReq.write.bufTail;
			pos		= mPGPdiskReq.write.posTail;
			nBytes	= mPGPdiskReq.write.nBytesTail;

			pgpAssertAddrValid(buf, PGPUInt8);
			pgpCopyMemory(buf, mDataBuf, nBytes);

			SmartCipherBlocks(pos/kDefaultBlockSize, 1, mDataBuf, mDataBuf, 
				kCipherOp_Encrypt);

			VolFile::Write(mDataBuf, pos, kDefaultBlockSize, 
				&mPGPdiskReq.downInfo);
		}
		else
		{
			(* doneWithRequest) = TRUE;
		}
		break;

	default:
		pgpAssert(FALSE);
		break;
	}
}

// PGPdiskCallback is called as a callback by the routines who executed our
// read and write requests. We extract the address of the PGPdisk object in
// question and pass the callback to it.

void 
PGPdisk::PGPdiskCallback(GenericCallbackInfo *downInfo)
{
	PGPdisk *pPGD;

	pgpAssertAddrValid(downInfo, GenericCallbackInfo);

	pPGD = (PGPdisk *) downInfo->refData[0];
	pgpAssertAddrValid(pPGD, PGPdisk);

	pPGD->PGPdiskCallbackAux();
}

// PGPdiskCallbackAux is called by the static callback function
// 'PGPdiskCallback' so we don't have to type 'pPGD' before every reference
// to an object member or method.

void 
PGPdisk::PGPdiskCallbackAux()
{
	DualErr		derr;
	PGPBoolean	doneWithRequest;
	PGPUInt8	*buf;
	PGPUInt32	nBytes;
	PGPUInt64	pos;

	pgpAssert(mPGPdiskReq.isInUse);

	derr = mPGPdiskReq.downInfo.derr;

	if (derr.IsntError())
	{
		// Before passing the request to 'ExecuteRequest' we perform some pre-
		// processing on the data manipulated by the piece of the request that
		// was just processed.

		switch (mPGPdiskReq.op)
		{

		case kPGDOP_Read:
			if (!mPGPdiskReq.read.readHeader)
			{
				// We read in the header block. Decrypt and copy just what the
				// caller needs into his buffer.

				mPGPdiskReq.read.readHeader = TRUE;

				buf		= mPGPdiskReq.read.bufHeader;
				pos		= mPGPdiskReq.read.posHeader;
				nBytes	= mPGPdiskReq.read.nBytesHeader;

				pgpAssertAddrValid(buf, PGPUInt8);

				SmartCipherBlocks(pos/kDefaultBlockSize, 1, mDataBuf, 
					mDataBuf, kCipherOp_Decrypt);

				pgpCopyMemory(mDataBuf + pos%kDefaultBlockSize, buf, nBytes);
			}
			else if (!mPGPdiskReq.read.readMiddle)
			{
				PGPUInt32 bytesRead;

				// We read in a piece of the middle. Decrypt it, copy it into
				// the output buffer, and if there is still more middle left
				// then adjust the variables.

				buf		= mPGPdiskReq.read.bufMiddle;
				pos		= mPGPdiskReq.read.posMiddle;
				nBytes	= mPGPdiskReq.read.nBytesMiddle;

				pgpAssertAddrValid(buf, PGPUInt8);

				bytesRead = min(nBytes, kPGDBlocksPerOp*kDefaultBlockSize);

				SmartCipherBlocks(pos/kDefaultBlockSize, 
					bytesRead/kDefaultBlockSize, mDataBuf, buf, 
					kCipherOp_Decrypt);

				if (nBytes - bytesRead > 0)
				{
					mPGPdiskReq.read.bufMiddle		+= bytesRead;
					mPGPdiskReq.read.posMiddle		+= bytesRead;
					mPGPdiskReq.read.nBytesMiddle	-= bytesRead;
				}
				else
				{
					mPGPdiskReq.read.readMiddle = TRUE;
				}
			}
			else if (!mPGPdiskReq.read.readTail)
			{
				// We read in the tail block. Decrypt and copy just what the
				// caller needs into his buffer.

				mPGPdiskReq.read.readTail = TRUE;

				buf		= mPGPdiskReq.read.bufTail;
				pos		= mPGPdiskReq.read.posTail;
				nBytes	= mPGPdiskReq.read.nBytesTail;

				pgpAssertAddrValid(buf, PGPUInt8);

				SmartCipherBlocks(pos/kDefaultBlockSize, 1, mDataBuf, 
					mDataBuf, kCipherOp_Decrypt);

				pgpCopyMemory(mDataBuf, buf, nBytes);
			}
			break;

		case kPGDOP_Write:
			if (!mPGPdiskReq.write.readHeader)
			{
				// No pre-processing needed here.
				mPGPdiskReq.write.readHeader = TRUE;
			}
			else if (!mPGPdiskReq.write.wroteHeader)
			{
				// No pre-processing needed here.
				mPGPdiskReq.write.wroteHeader = TRUE;
			}
			else if (!mPGPdiskReq.write.wroteMiddle)
			{
				PGPUInt32 bytesWritten;

				// We wrote out a piece of the middle. If there is still more
				// middle left to write out then adjust the variables.

				buf		= mPGPdiskReq.write.bufMiddle;
				pos		= mPGPdiskReq.write.posMiddle;
				nBytes	= mPGPdiskReq.write.nBytesMiddle;

				pgpAssertAddrValid(buf, PGPUInt8);

				bytesWritten = min(nBytes, kPGDBlocksPerOp*kDefaultBlockSize);

				if (nBytes - bytesWritten > 0)
				{
					mPGPdiskReq.write.bufMiddle		+= bytesWritten;
					mPGPdiskReq.write.posMiddle		+= bytesWritten;
					mPGPdiskReq.write.nBytesMiddle	-= bytesWritten;
				}
				else
				{
					mPGPdiskReq.write.wroteMiddle = TRUE;
				}
			}
			else if (!mPGPdiskReq.write.readTail)
			{
				// No pre-processing needed here.
				mPGPdiskReq.write.readTail = TRUE;
			}
			else if (!mPGPdiskReq.write.wroteTail)
			{
				// No pre-processing needed here.
				mPGPdiskReq.write.wroteTail = TRUE;
			}
			break;

		default:
			pgpAssert(FALSE);
			break;
		}

		// Perform further processing on this request, if needed.
		ExecuteRequest(&doneWithRequest);
	}

	// Callback if we're done or on error.
	if (doneWithRequest || derr.IsError())
	{
		ScheduleAsyncCallback(derr);
	}
}

// ScheduleAsyncCallback schedules a windows event that calls our function
// that will call the asynchronous request up.

void 
PGPdisk::ScheduleAsyncCallback(DualErr derr)
{
	static RestrictedEvent_THUNK callbackThunk;

	pgpAssertAddrValid(mPGPdiskReq.upInfo, GenericCallbackInfo);
	mPGPdiskReq.upInfo->derr = derr;

	Call_Restricted_Event(0, NULL, PEF_ALWAYS_SCHED, (PVOID) this, 
		AsyncExecuteCallback, 0, &callbackThunk);
}

// AsyncExecuteCallback was scheduled by 'ScheduleAsyncCallback' for the
// purpose of calling back up the asynchronous request we received.

VOID 
__stdcall 
PGPdisk::AsyncExecuteCallback(
	VMHANDLE		hVM, 
	THREADHANDLE	hThread, 
	PVOID			Refdata, 
	PCLIENT_STRUCT	pRegs)
{
	PGPdisk *pPGD;

	pPGD = (PGPdisk *) Refdata;
	pgpAssertAddrValid(pPGD, PGPdisk);

	pgpAssert(pPGD->mPGPdiskReq.isInUse);
	pPGD->mPGPdiskReq.isInUse = FALSE;

	pgpAssertAddrValid(pPGD->mPGPdiskReq.upInfo, GenericCallbackInfo);
	pPGD->mPGPdiskReq.upInfo->callback(pPGD->mPGPdiskReq.upInfo);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -