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

📄 fatparser.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		clustBias	= kFat16ClustBias;
		maxClust	= kMaxFat16Clust;
		minClust	= kMinFat16Clust;
		break;

	case kFS_FAT32:
		bitsClust	= kBitsFat32Clust;
		clustBias	= kFat32ClustBias;
		maxClust	= kMaxFat32Clust;
		minClust	= kMinFat32Clust;
		break;

	default:
		pgpAssert(FALSE);
		break;
	}

	// Then fill in the data specific to this drive.
	blockSize		= mFat.fdBlockSize;
	fatSize			= mFat.fdFatSize;
	spc				= mFat.fdSpc;		
	firstSecData	= mFat.fdFirstSecData;
	firstClustFile	= mFat.fdFirstClustFile;
	firstSecFat		= mFat.fdFirstSecFat + mFat.fdActiveFat*fatSize;

	totalClusts = TotalClusters(fatSize, bitsClust, blockSize);

	DebugOut("PGPdisk: blockSize is %u", blockSize);
	DebugOut("PGPdisk: fatSize is %u", fatSize);
	DebugOut("PGPdisk: spc is %u", spc);
	DebugOut("PGPdisk: firstSecData is %u", firstSecData);
	DebugOut("PGPdisk: firstClustFile is %u", firstClustFile);
	DebugOut("PGPdisk: firstSecFat is %u", firstSecFat);

	pgpAssert(firstSecFat < firstSecData);
	pgpAssert(firstClustFile <= totalClusts);

	// Now we will calculate the index of the first sector on disk holding our
	// file's contents.

	firstSecFile = ClusterToSector(firstClustFile, firstSecData, spc, 
		clustBias);

	pgpAssert(firstSecFile >= firstSecData);

	// Init the first file fragment structure for the file.
	if (derr.IsntError())
	{
		i = 0;
		mNumFragsInUse = 1;

		InitFileFrag(&mFragArray[i], 0, (PGPUInt64) firstSecFile*blockSize);
	}

	// 'curClust' will keep track of the index of the current cluster we are
	// looking at. 'clustSec' and 'bitOffset' keep track of the sector in the
	// FAT table where this cluster is located, and the offset (in bits) into
	// that sector where the cluster begins.

	if (derr.IsntError())
	{
		curClust = firstClustFile;

		GetClusterInfo(firstSecFat, curClust, bitsClust, blockSize, &clustSec, 
			&bitOffset);

		// Before parsing the FAT table we read the current sector into a
		// buffer. WE MUST read in the extra sector because FAT12 clusters can
		// overrun the boundary.

		derr = mHost.Read(mDataBuf, clustSec, kFPDataBufSize + 1);
	}

	if (derr.IsntError())
	{
		ParseNextClusterInfo PNCI;

		PNCI.blockSize	= blockSize;
		PNCI.clustBias	= clustBias;
		PNCI.spc		= spc;

		PNCI.bitsClust		= bitsClust;
		PNCI.bitOffset		= bitOffset;
		PNCI.clustSec		= clustSec;
		PNCI.curClust		= curClust;
		PNCI.firstSecData	= firstSecData;
		PNCI.firstSecFat	= firstSecFat;
		PNCI.i				= i;
		PNCI.nextClust		= 
			ExtractCluster(mDataBuf, bitOffset, curClust, mFsId);
		PNCI.overFlow		= 0;
		PNCI.totalClusts	= totalClusts;

		// We now construct the file fragment list by parsing the FAT table.
		// Beginning with the first cluster of the file, we iterate over all
		// remaining clusters until finished.
		//
		// As long as the cluster two numbers, it refers to a valid cluster
		// index; else it means the file has ended.

		while (derr.IsntError() && (PNCI.nextClust >= minClust) && 
			(PNCI.nextClust <= maxClust))
		{
			derr = ParseNextCluster(&PNCI);
		}

		i = PNCI.i;
	}

	// The file has been completely parsed.
	if (derr.IsntError())
	{
		mFragArray[i].fileEnd	+= (spc*blockSize) - 1;
		mFragArray[i].diskEnd	+= (spc*blockSize) - 1;

		// Does combined size of the fragments agree with the actual file size?
		if ((mFragArray[i].fileEnd < (mBytesFile - spc*blockSize)) ||
			(mFragArray[i].fileEnd > (mBytesFile + spc*blockSize)))
		{
			derr = DualErr(kPGDMinorError_CorruptFat);
		}
	}

	if (derr.IsError())
	{
		mNumFragsInUse = 0;
	}

	return derr;
}

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

void 
FatParser::ExecuteRequest(PGPBoolean *doneWithRequest)
{
	PGPUInt8	*buf;
	PGPUInt16	blockSize;
	PGPUInt32	i, nBytes, sizeChunk;
	PGPUInt64	blockVolume, pos;

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

	pgpAssert(mFatParserReq.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 (mFatParserReq.op)
	{

	case kFPOP_Read:
		blockSize = mHost.GetBlockSize();

		if (!mFatParserReq.read.readHeader)
		{
			// Read in the header block.

			pos = mFatParserReq.read.posHeader;
			i = FindFragmentIndex(pos);

			blockVolume	= CalcDiskSector(pos, &mFragArray[i], blockSize);

			mHost.Read(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.read.readMiddle)
		{
			// Read in as much of the middle as we can. Leave the rest for
			// later.

			buf		= mFatParserReq.read.bufMiddle;
			pos		= mFatParserReq.read.posMiddle;
			nBytes	= mFatParserReq.read.nBytesMiddle;
			i		= FindFragmentIndex(pos);

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);
			sizeChunk = min(nBytes/blockSize, (PGPUInt32) 
				((mFragArray[i].fileEnd - pos) / blockSize) + 1);

			mFatParserReq.read.sizeCurrentRead = sizeChunk*blockSize;

			mHost.Read(buf, blockVolume, sizeChunk, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.read.readTail)
		{
			// Read in the tail block.

			pos = mFatParserReq.read.posTail;
			i = FindFragmentIndex(pos);

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);

			mHost.Read(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else
		{
			(* doneWithRequest) = TRUE;
		}
		break;

	case kFPOP_Write:
		blockSize = mHost.GetBlockSize();

		if (!mFatParserReq.write.readHeader)
		{
			// Read in the header block. This must be done because we can't
			// write in units smaller than one block. Once we've read in
			// the header, we modify it with data from the input buffer,
			// and write it out.
			
			pos = mFatParserReq.write.posHeader;
			i = FindFragmentIndex(pos);

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);

			mHost.Read(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.write.wroteHeader)
		{
			// We read in the header block, now modify it with the changed
			// data from the input buffer and write it out.
			
			buf			= mFatParserReq.write.bufHeader;
			pos			= mFatParserReq.write.posHeader;
			nBytes		= mFatParserReq.write.nBytesHeader;
			i			= FindFragmentIndex(pos);
			blockVolume	= CalcDiskSector(pos, &mFragArray[i], blockSize);

			pgpAssertAddrValid(buf, PGPUInt8);
			pgpCopyMemory(buf, mDataBuf + pos%blockSize, nBytes);
			
			mHost.Write(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.write.wroteMiddle)
		{
			// Encrypt and write out as much of the middle as we can. Leave
			// the rest for later.

			buf			= mFatParserReq.write.bufMiddle;
			pos			= mFatParserReq.write.posMiddle;
			nBytes		= mFatParserReq.write.nBytesMiddle;
			i			= FindFragmentIndex(pos);

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);
			sizeChunk = min(nBytes/blockSize, (PGPUInt32) 
				((mFragArray[i].fileEnd - pos) / blockSize) + 1);

			mFatParserReq.write.sizeCurrentWrite = sizeChunk*blockSize;

			mHost.Write(buf, blockVolume, sizeChunk, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.write.readTail)
		{
			// Read in the tail block. This must be done because we can't
			// write in units smaller than one block. Once we've read in
			// the tail, we modify it with data from the input buffer,
			// and write it out.
			
			pos = mFatParserReq.write.posTail;
			i = FindFragmentIndex(pos);

			blockVolume = CalcDiskSector(pos, &mFragArray[i], blockSize);

			mHost.Read(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else if (!mFatParserReq.write.wroteTail)
		{
			// We read in the tail block, now modify it with the changed
			// data from the input buffer and write it out.

			buf			= mFatParserReq.write.bufTail;
			nBytes		= mFatParserReq.write.nBytesTail;
			pos			= mFatParserReq.write.posTail;
			i			= FindFragmentIndex(pos);
			blockVolume	= CalcDiskSector(pos, &mFragArray[i], blockSize);

			pgpAssertAddrValid(buf, PGPUInt8);
			pgpCopyMemory(buf, mDataBuf + pos%blockSize, nBytes);
			
			mHost.Write(mDataBuf, blockVolume, 1, &mFatParserReq.downInfo);
		}
		else
		{
			(* doneWithRequest) = TRUE;
		}
		break;

	default:
		pgpAssert(FALSE);
		break;
	}
}

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

void 
FatParser::FatParserCallback(GenericCallbackInfo *downInfo)
{
	FatParser *pFP;

	pgpAssertAddrValid(downInfo, GenericCallbackInfo);

	pFP = (FatParser *) downInfo->refData[0];
	pgpAssertAddrValid(pFP, FatParser);

	pFP->FatParserCallbackAux();
}

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

void 
FatParser::FatParserCallbackAux()
{
	DualErr		derr;
	PGPBoolean	doneWithRequest;
	PGPUInt8	*buf;
	PGPUInt16	blockSize;
	PGPUInt32	nBytes;
	PGPUInt64	pos;

	pgpAssert(mFatParserReq.isInUse);
	blockSize = mHost.GetBlockSize();	

	derr = mFatParserReq.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 (mFatParserReq.op)
		{

		case kFPOP_Read:
			if (!mFatParserReq.read.readHeader)
			{			
				// We read in the header block. Copy just what the caller needs
				// into his buffer.
				
				mFatParserReq.read.readHeader = TRUE;

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

				pgpAssertAddrValid(buf, PGPUInt8);

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

				// We read in a piece of the middle. Copy it into the output
				// buffer, and if there is still more middle left then adjust
				// the variables.
				
				buf			= mFatParserReq.read.bufMiddle;
				pos			= mFatParserReq.read.posMiddle;
				nBytes		= mFatParserReq.read.nBytesMiddle;
				bytesRead	= mFatParserReq.read.sizeCurrentRead;

				pgpAssertAddrValid(buf, PGPUInt8);

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

				mFatParserReq.read.readTail = TRUE;

				buf = mFatParserReq.read.bufTail;
				nBytes = mFatParserReq.read.nBytesTail;

				pgpAssertAddrValid(buf, PGPUInt8);

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

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

				// We wrote out a piece of the middle. Copy it into the output
				// buffer, and if there is still more middle left then adjust
				// the variables.
				
				buf				= mFatParserReq.write.bufMiddle;
				pos				= mFatParserReq.write.posMiddle;
				nBytes			= mFatParserReq.write.nBytesMiddle;
				bytesWritten	= mFatParserReq.write.sizeCurrentWrite;

				pgpAssertAddrValid(buf, PGPUInt8);

				if (nBytes - bytesWritten > 0)
				{
					mFatParserReq.write.bufMiddle		+= bytesWritten;
					mFatParserReq.write.posMiddle		+= bytesWritten;
					mFatParserReq.write.nBytesMiddle	-= bytesWritten;
				}
				else
				{
					mFatParserReq.write.wroteMiddle = TRUE;
				}
			}
			else if (!mFatParserReq.write.readTail)
			{
				// No pre-processing needed here.
				mFatParserReq.write.readTail = TRUE;
			}
			else if (!mFatParserReq.write.wroteTail)
			{
				// No pre-processing needed here.
				mFatParserReq.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 
FatParser::ScheduleAsyncCallback(DualErr derr)
{
	static RestrictedEvent_THUNK callbackThunk;

	pgpAssertAddrValid(mFatParserReq.upInfo, GenericCallbackInfo);
	mFatParserReq.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 
FatParser::AsyncExecuteCallback(
	VMHANDLE		hVM, 
	THREADHANDLE	hThread, 
	PVOID			Refdata, 
	PCLIENT_STRUCT	pRegs)
{
	FatParser *pFP;

	pFP = (FatParser *) Refdata;
	pgpAssertAddrValid(pFP, FatParser);

	pgpAssert(pFP->mFatParserReq.isInUse);
	pFP->mFatParserReq.isInUse = FALSE;

	pgpAssertAddrValid(pFP->mFatParserReq.upInfo, GenericCallbackInfo);
	pFP->mFatParserReq.upInfo->callback(pFP->mFatParserReq.upInfo);
}

⌨️ 快捷键说明

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