📄 fatparser.cpp
字号:
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 + -