|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: layout.cxx
//
// Contents: Code for the relayout tool
//
// Classes:
//
// Functions:
//
// History: 12-Feb-96 PhilipLa Created
// 21-Feb-96 SusiA Put funtions on ILayoutStorage
//
//----------------------------------------------------------------------------
#include "layouthd.cxx"
#pragma hdrstop
#include <dirfunc.hxx>
#include "laylkb.hxx"
#include "laywrap.hxx"
#include <stddef.h>
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::LayoutScript
//
// Synopsis: Construct an unprocessed script from an app provided script
//
// Arguments: [pStorageLayout] -- Pointer to storage layout array
// [nEntries] -- Number of entries in the array
// [grfInterleavedFlag] -- Specifies disposition of control
// structures
//
// Returns: Appropriate status code
//
// History: 21-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutRootStorage::LayoutScript( StorageLayout *pStorageLayout, DWORD nEntries, DWORD glfInterleavedFlag) {
SCODE sc;
if ((LONG)nEntries < 0) { return E_INVALIDARG; } if ((LONG)nEntries == 0) { return S_OK; } if ((glfInterleavedFlag != STG_LAYOUT_INTERLEAVED) && (glfInterleavedFlag != STG_LAYOUT_SEQUENTIAL ) ) { return STG_E_INVALIDFLAG; }
if (pStorageLayout == NULL) { return STG_E_INVALIDPOINTER; }
if (FAILED(sc = BeginMonitor())) { return sc; } if (FAILED(sc = ProcessLayout(pStorageLayout, nEntries, glfInterleavedFlag))) { // ignore errors from EndMonitor
EndMonitor(); return sc; }
if (FAILED(sc = EndMonitor())) { return sc; }
return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::BeginMonitor
//
// Synopsis: Begin monitoring the ILockBytes operations for recording a
// script.
//
// Arguments: None.
//
// Returns: Appropriate status code
//
// History: 21-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutRootStorage::BeginMonitor(void) { SCODE sc = S_OK; sc = _pllkb->StartLogging(); return ResultFromScode(sc);
}
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::EndMonitor
//
// Synopsis: Stop monitoring ILockBytes operations for script recording.
//
// Arguments: None.
//
// Returns: Appropriate status code
//
// History: 21-Feb-96 SusiA Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutRootStorage::EndMonitor(void) { SCODE sc = S_OK; sc = _pllkb->StopLogging(); return ResultFromScode(sc); }
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ReLayoutDocfile
//
// Synopsis: Relayout the docfile into the new name specified.
//
// Arguments: [pwcsNewName] -- Name of destination file
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
// 21-Feb-96 SusiA Made a method on ILayoutStorage
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutRootStorage::ReLayoutDocfile(OLECHAR *pwcsNewDfName) { SCODE sc;
#if (!defined(UNICODE) && (!defined(_MAC)))
WCHAR awcScriptName[MAX_PATH + 1];
UINT uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; if (!MultiByteToWideChar( uCodePage, 0, _pllkb->GetScriptName(), -1, awcScriptName, MAX_PATH + 1 )) { return STG_E_INVALIDNAME; } sc = StgLayoutDocfile(_pllkb->GetHandle(), pwcsNewDfName, awcScriptName); #else
sc = StgLayoutDocfile(_pllkb->GetHandle(), pwcsNewDfName, _pllkb->GetScriptName()); #endif //UNICODE
if (FAILED(sc)) { //Delete new file
#ifdef UNICODE
DeleteFileW(pwcsNewDfName); #elif defined( _MAC)
DeleteFile(pwcsNewDfName); #else
TCHAR atcPath[MAX_PATH + 1];
uCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
//Note: Intentionally ignore an error if it happens here. We
// want to return the error from StgLayoutDocfile, not from
// the cleanup path.
WideCharToMultiByte( uCodePage, 0, pwcsNewDfName, -1, atcPath, _MAX_PATH + 1, NULL, NULL); DeleteFileA(atcPath);
#endif // UNICODE
} else { //Delete Script File
DeleteFile(_pllkb->GetScriptName()); //Note: Intentionally ignore an error if it happens here. We
// want to return the error from StgLayoutDocfile, not from
// the cleanup path.
_pllkb->ClearScriptName(); } return sc; }
#if DBG == 1
STDMETHODIMP CLayoutRootStorage::GetScript(TCHAR **ptcsScriptFileName) { *ptcsScriptFileName = _pllkb->GetScriptName(); return S_OK; } #endif
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ReLayoutDocfileOnILockBytes
//
// Synopsis: Relayout the docfile into a generic ILockBytes implementation.
//
// Arguments: [pILockBytes] -- destination relayout ILockBytes
//
// Returns: Appropriate status code
//
// History: 09-Jun-96 SusiA Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CLayoutRootStorage::ReLayoutDocfileOnILockBytes(ILockBytes *pILockBytes) { return STG_E_UNIMPLEMENTEDFUNCTION; }
//+---------------------------------------------------------------------------
//
// Function: StgLayoutDocfile
//
// Synopsis: Given an old file and an unprocessed script, relayout the
// docfile into the new name specified.
//
// Arguments: [hOld] -- Handle of source file
// [pwcsNewDfName] -- Name of destination file
// [pwcsScriptName] -- Name of unprocessed script file
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE StgLayoutDocfile(HANDLE hOld, OLECHAR const *pwcsNewDfName, OLECHAR const *pwcsScriptName) { SCODE sc = S_OK; CMappedFile mfOld, mfNew, mfScript; MAPFILE *pvOld, *pvNew, *pvScript; ULONG ulScriptSize; ULONG csectScript, csectProcessed, csectFile; ULONG cbSectorSize; ULONG i; SECT *psProcessedScript = NULL; if (pwcsNewDfName == NULL) return STG_E_INVALIDNAME;
#ifdef _MAC
layChkTo(EH_End, mfOld.InitFromHandle(hOld, GENERIC_READ, FALSE, NULL)); #else
layChkTo(EH_End, mfOld.InitFromHandle(hOld, GENERIC_READ, TRUE, NULL)); #endif
layChkTo(EH_End, mfNew.Init(pwcsNewDfName, mfOld.GetSize(), GENERIC_READ | GENERIC_WRITE, CREATE_ALWAYS, NULL));
if ((pwcsScriptName !=NULL) && (pwcsScriptName[0] != TEXT('\0')) ) { sc = mfScript.Init(pwcsScriptName, 0, GENERIC_READ, OPEN_EXISTING, NULL); layChkTo(EH_End, sc);
if (sc == STG_S_FILEEMPTY) { pvScript = NULL; } else { pvScript = &mfScript; } } else { pvScript = NULL; }
pvOld = &mfOld; pvNew = &mfNew;
//From this point on, we may get an exception while we're poking around
// in one of the memory maps. We need to handle this case and be able
// to properly return an error and clean up if it happens.
#ifndef _MAC
__try { #endif
//Figure out how many sectors are in the file
cbSectorSize = 1 << pvOld->GetUSHORT( (ULONG) offsetof(CMSFHeaderData,_uSectorShift)); pvOld->SetSectorSize(cbSectorSize); pvNew->SetSectorSize(cbSectorSize); const ULONG cbHeader = cbSectorSize; csectFile = (mfOld.GetSize() + cbSectorSize - 1 - cbHeader) / cbSectorSize;
SECT sectRangeLocks = (OLOCKREGIONEND - cbHeader + cbSectorSize - 1) / cbSectorSize;
if (pvScript) { ulScriptSize = mfScript.GetSize(); } else { ulScriptSize = 0; }
csectProcessed = max(ulScriptSize / sizeof(SECT), csectFile); layMem(psProcessedScript = new SECT[csectProcessed]);
for (i = 0; i < csectProcessed; i++) { psProcessedScript[i] = ENDOFCHAIN; } ULONG csectControl; layChk(ProcessControl(psProcessedScript, pvOld, &csectControl)); layChk(ProcessScript(psProcessedScript, pvScript, csectFile, ulScriptSize / sizeof(SECT), csectControl, sectRangeLocks, &csectScript));
//layAssert(csectScript == csectFile);
layChk(CopyData(pvNew, pvOld, psProcessedScript, csectFile, cbSectorSize));
layChk(RemapHeader(pvNew, psProcessedScript, csectFile)); layChk(RemapDIF(pvNew, psProcessedScript, csectFile, cbSectorSize)); layChk(RemapFat(pvNew, pvOld, psProcessedScript, csectFile, cbSectorSize)); layChk(RemapDirectory(pvNew, psProcessedScript, csectFile, cbSectorSize)); Err: delete [] psProcessedScript;
#ifndef _MAC
} __except (EXCEPTION_EXECUTE_HANDLER) { sc = STG_E_WRITEFAULT; } #endif
pvOld = NULL; pvNew = NULL;
EH_End: return sc; }
//+---------------------------------------------------------------------------
//
// Function: GetDIFSect
//
// Synopsis: Return a pointer to the appropriate sector in the DIF
//
// Arguments: [pvBase] -- Pointer to base address of memory mapped file
// [iDIF] -- Index into DIF desired
// [cbSectorSize] -- Size in bytes of sector
//
// Returns: Pointer to appropriate sector
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
CFatSect * GetDIFSect(MAPFILE *pvBase, ULONG iDIF, ULONG cbSectorSize, SECT *psect) { USHORT cSectPerFat = (USHORT)(cbSectorSize / sizeof(SECT)); SECT sectDif = pvBase->GetULONG( (ULONG) offsetof(CMSFHeaderData,_sectDifStart));
for (ULONG i = 0; i < iDIF; i++) { CFatSect *pdif = pvBase->GetCFatSect((sectDif * cbSectorSize) + cbSectorSize); sectDif = pdif->GetSect(cSectPerFat - 1); pvBase->Remove(pdif); }
if (psect) { *psect = sectDif; } return pvBase->GetCFatSect((sectDif * cbSectorSize) + cbSectorSize); }
//+---------------------------------------------------------------------------
//
// Function: GetFatSect
//
// Synopsis: Return a pointer to the appropriate sector in the fat
//
// Arguments: [pvBase] -- Pointer to base address of memory mapped file
// [iFat] -- Index into fat desired
// [cbSectorSize] -- Size in bytes of sector
//
// Returns: Pointer to appropriate sector
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
CFatSect *GetFatSect(MAPFILE *pvBase, ULONG iFat, ULONG cbSectorSize, SECT *psect) { SECT sectFat; if (iFat < CSECTFAT) { //Fatsect can be found in header
sectFat = pvBase->GetULONG( (ULONG) offsetof(CMSFHeaderData,_sectFat[iFat])); } else { ULONG cFatPerDif = (cbSectorSize / sizeof(SECT)) - 1; ULONG iDIF = (iFat - CSECTFAT) / cFatPerDif; USHORT oDIF = (USHORT)((iFat - CSECTFAT) % cFatPerDif); CFatSect *pDif = GetDIFSect(pvBase, iDIF, cbSectorSize, NULL); sectFat = pDif->GetSect(oDIF);
pvBase->Remove(pDif); }
CFatSect *pbFat = pvBase->GetCFatSect( (sectFat * cbSectorSize) + cbSectorSize);
if (psect) { *psect = sectFat; } return (CFatSect *)pbFat; }
//+---------------------------------------------------------------------------
//
// Function: GetNext
//
// Synopsis: Given a sector, return the next sector in the fat chain
//
// Arguments: [pvBase] -- Pointer to base address of memory mapped file
// [sect] -- Sect desired
// [cbSectorSize] -- Sector size in bytes
//
// Returns: Appropriate SECT value
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SECT GetNext(MAPFILE *pvBase, SECT sect, ULONG cbSectorSize) { SECT newsect;
ULONG csectPerFat = cbSectorSize / sizeof(SECT); ULONG iFat = sect / csectPerFat; USHORT oFat = (USHORT)(sect % csectPerFat); CFatSect *pfs = GetFatSect(pvBase, iFat, cbSectorSize, NULL); newsect = pfs->GetSect(oFat);
pvBase->Remove(pfs);
return newsect; }
//+---------------------------------------------------------------------------
//
// Function: ProcessControl, private
//
// Synopsis: Add control structures to processed script
//
// Arguments: [psProcessed] -- Pointer to processed script
// [pvOld] -- Pointer to old file
// [pcsectControl] -- Return location for total sectors processed
//
// Returns: Appropriate status code
//
// History: 05-Mar-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE ProcessControl(SECT *psProcessed, MAPFILE *pvOld, ULONG *pcsectControl) { SECT sectCurrent = 0; CMSFHeaderData *phdr = (CMSFHeaderData *)pvOld->GetCMSFHeaderData();
ULONG csectDif, csectFat; ULONG cbSectorSize;
csectDif = phdr->_csectDif; csectFat = phdr->_csectFat; cbSectorSize = 1 << phdr->_uSectorShift;
//We want the structures in the following order:
//1) Enough fat and DIFat sectors to hold themselves and all of the
// directory sectors.
//2) All of the directory sectors
//3) Everything else - the rest of the difat, the fat, and the minifat.
//First find out how big the directory is
SECT sectDir = phdr->_sectDirStart; ULONG csectDir = 0; while (sectDir != ENDOFCHAIN) { sectDir = GetNext(pvOld, sectDir, cbSectorSize); csectDir++; }
//Now compute the number of fat sectors we need to hold the directory
// plus the fat sectors themselves.
ULONG csectFatNeeded = 0; ULONG csectDifNeeded = 0; ULONG csectNeededLast = 0; ULONG cfsSect = (cbSectorSize / sizeof(SECT));
do { csectNeededLast = csectFatNeeded; csectFatNeeded = (csectFatNeeded + csectDifNeeded + csectDir + cfsSect - 1) / cfsSect; if (csectFatNeeded > CSECTFAT) { csectDifNeeded = (csectFatNeeded - CSECTFAT + cfsSect - 2) / (cfsSect - 1); } } while (csectFatNeeded != csectNeededLast);
//Now we know how many DIF, Fat, and Directory sectors we need.
//Lay those out first.
//For those of you keeping score, the docfile will need to have exactly
// csectFatNeeded + csectDifNeeded sectors downloaded before it can
// be opened.
for (ULONG i = 0; i < csectDifNeeded; i++) { SECT sectDif; pvOld->Remove(GetDIFSect(pvOld, i, cbSectorSize, §Dif)); psProcessed[sectDif] = sectCurrent++; }
for (i = 0; i < csectFatNeeded; i++) { SECT sectFat;
pvOld->Remove(GetFatSect(pvOld, i, cbSectorSize, §Fat)); psProcessed[sectFat] = sectCurrent++; } sectDir = phdr->_sectDirStart; for (i = 0; i < csectDir; i++) { layAssert(sectDir != ENDOFCHAIN); psProcessed[sectDir] = sectCurrent++; sectDir = GetNext(pvOld, sectDir, cbSectorSize); }
//Now put down everything else
for (i = csectDifNeeded; i < csectDif; i++) { SECT sectDif;
GetDIFSect(pvOld, i, cbSectorSize, §Dif); pvOld->Remove(GetDIFSect(pvOld, i, cbSectorSize, §Dif)); psProcessed[sectDif] = sectCurrent++; } for (i = csectFatNeeded; i < csectFat; i++) { SECT sectFat; pvOld->Remove(GetFatSect(pvOld, i, cbSectorSize, §Fat)); psProcessed[sectFat] = sectCurrent++; } //Finally minifat
SECT sectMiniFat = phdr->_sectMiniFatStart; while (sectMiniFat != ENDOFCHAIN) { psProcessed[sectMiniFat] = sectCurrent++; sectMiniFat = GetNext(pvOld, sectMiniFat, cbSectorSize); } *pcsectControl = sectCurrent;
pvOld->Remove(phdr); return S_OK; }
//+---------------------------------------------------------------------------
//
// Function: ProcessScript
//
// Synopsis: Given a list of sectors in order, construct a mapping
// of old sector->new sector
//
// Arguments: [psProcessed] -- Pointer to destination buffer
// [psOriginal] -- Pointer to source script buffer
// [csectFile] -- Count of sectors in file
// [csectOriginal] -- Count of entries in original script
// [sectRangeLocks] -- sector containing docfile range locks
// [pcsectProcessed] -- Return location for number of entries
// in processed script
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE ProcessScript(SECT *psProcessed, MAPFILE *psOriginal, ULONG csectFile, ULONG csectOriginal, ULONG csectControl, SECT sectRangeLocks, ULONG *pcsectProcessed) { SCODE sc = S_OK; #if DBG == 1
ULONG csectProcessed = 0; #endif
ULONG cDuplicates = 0; ULONG cUnlisted = 0; for (ULONG i = 0; i < csectOriginal; i++) { SECT sectOld = (*psOriginal)[i];
if (sectOld >= csectFile) { //Weird. We're past the range of the file.
return STG_E_UNKNOWN; } #if DBG == 1
if (sectOld + 1> csectProcessed) { csectProcessed = sectOld + 1; } #endif
if (psProcessed[sectOld] == ENDOFCHAIN) { psProcessed[sectOld] = i - cDuplicates + csectControl; } else { cDuplicates++; } }
//Fill in holes
for (i = 0; i < csectFile; i++) { if (psProcessed[i] == ENDOFCHAIN) { SECT sectNew = csectOriginal - cDuplicates + csectControl + cUnlisted; if (sectNew == sectRangeLocks) // skip over range locks
{ sectNew++; cUnlisted++; } psProcessed[i] = sectNew; cUnlisted++; #if DBG == 1
if (sectNew + 1> csectProcessed) { csectProcessed = sectNew + 1; } #endif
} #if DBG == 1
//If we have control structures at the end of the file that are
// not in the script anywhere (which may happen particularly often
// on files produced with simple mode), we want to make sure to
// update the count on those. For retail builds, we don't really
// care about the count, so we can skip this.
else if (psProcessed[i] + 1 > csectProcessed) { csectProcessed = psProcessed[i] + 1; } #endif
} #if DBG == 1
for (i = 0; i < csectProcessed; i++) { layDebugOut((DEB_IERROR, "Script[%lu] = %lx\n", i, psProcessed[i])); } #endif
#if DBG == 1
*pcsectProcessed = csectProcessed; #else
*pcsectProcessed = csectFile; #endif
return sc; }
//+---------------------------------------------------------------------------
//
// Function: CopyData
//
// Synopsis: Given an old->new mapping, copy data from old mapping to
// new mapping
//
// Arguments: [pvNew] -- Pointer to destination mapped file
// [pvOld] -- Pointer to source mapped file
// [psScript] -- Pointer to processed script
// [csectFile] -- Count of sectors in the file
// [cbSectorSize] -- Sector size in bytes
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE CopyData(MAPFILE *pvNew, MAPFILE *pvOld, SECT *psScript, ULONG csectFile, ULONG cbSectorSize) { SCODE sc = S_OK;
#ifdef SUPPORT_FILE_MAPPING
BYTE *pbSrc, *pbDest;
pbSrc = (BYTE *)(pvOld->GetBaseAddress()); pbDest = (BYTE *)(pvNew->GetBaseAddress()); #endif
for (ULONG i = 0; i < csectFile; i++) { #ifdef SUPPORT_FILE_MAPPING
BYTE *pbSrcStart = (BYTE *)pbSrc + (i * cbSectorSize) + cbSectorSize; BYTE *pbDestStart = (BYTE *)pbDest + (psScript[i] * cbSectorSize) + cbSectorSize; if ((pbSrc != NULL) && pbDest != NULL) { CopyMemory(pbDestStart, pbSrcStart, cbSectorSize); } else #endif // SUPPORT_FILE_MAPPING
{ BYTE *pbBuffer = (BYTE *) CoTaskMemAlloc(cbSectorSize); if (!pbBuffer) { return STG_E_INSUFFICIENTMEMORY; } if (S_OK == (sc = pvOld->ReadFromFile(pbBuffer, (i * cbSectorSize) + cbSectorSize, cbSectorSize ))) { sc = pvNew->WriteToFile(pbBuffer, (psScript[i] * cbSectorSize) + cbSectorSize, cbSectorSize ); } CoTaskMemFree(pbBuffer);
if (S_OK != sc) { return sc; } }
} //Also the header.
#ifdef SUPPORT_FILE_MAPPING
if ((pbSrc != NULL) && (pbDest != NULL)) { CopyMemory(pbDest, pbSrc, sizeof(CMSFHeaderData)); } else #endif
{ BYTE *pbBuffer = (BYTE *) CoTaskMemAlloc(sizeof(CMSFHeaderData)); if (!pbBuffer) { return STG_E_INSUFFICIENTMEMORY; } if (S_OK == (sc = pvOld->ReadFromFile( pbBuffer, 0, sizeof(CMSFHeaderData) ))) { sc = pvNew->WriteToFile( pbBuffer, 0, sizeof(CMSFHeaderData) ); }
CoTaskMemFree(pbBuffer);
if (S_OK != sc) { return sc; } }
return S_OK; }
//+---------------------------------------------------------------------------
//
// Function: RemapHeader
//
// Synopsis: Remap the docfile header using a processed script
//
// Arguments: [pvNew] -- Pointer to base of memory mapped file
// [psScript] -- Pointer to processed script
// [csectFile] -- Count of sectors in file
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE RemapHeader(MAPFILE *pvNew, SECT *psScript, ULONG csectFile) {
SCODE sc = S_OK;
CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
//Directory start will never be EOC
ph->_sectDirStart = psScript[ph->_sectDirStart];
if (ph->_sectMiniFatStart != ENDOFCHAIN) ph->_sectMiniFatStart = psScript[ph->_sectMiniFatStart];
if (ph->_sectDifStart != ENDOFCHAIN) ph->_sectDifStart = psScript[ph->_sectDifStart];
for (ULONG i = 0; i < CSECTFAT; i++) { if (ph->_sectFat[i] != FREESECT) { ph->_sectFat[i] = psScript[ph->_sectFat[i]]; } }
sc = pvNew->WriteToFile(ph); pvNew->Remove(ph); return sc; }
//+---------------------------------------------------------------------------
//
// Function: RemapDIF
//
// Synopsis: Remap the DIF according to a processed script
//
// Arguments: [pvNew] -- Pointer to base of memory mapped file
// [psScript] -- Pointer to processed script
// [csectFile] -- Count of sectors in file
// [cbSectorSize] -- Sector size in bytes
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE RemapDIF(MAPFILE *pvNew, SECT *psScript, ULONG csectFile, ULONG cbSectorSize) { CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
SCODE sc = S_OK;
CFatSect *pfs = NULL; USHORT csectPerDif = (USHORT)(cbSectorSize / sizeof(SECT)); SECT sectDif = ph->_sectDifStart;
for (ULONG i = 0; i < ph->_csectDif; i++) {
pfs = pvNew->GetCFatSect((sectDif * cbSectorSize) + cbSectorSize );
for (USHORT j = 0; j < csectPerDif; j++) { SECT sectOld = pfs->GetSect(j); if ((sectOld != FREESECT) && (sectOld != ENDOFCHAIN)) { pfs->SetSect(j, psScript[sectOld]); } }
sectDif = pfs->GetNextFat(csectPerDif - 1);
sc = pvNew->WriteToFile(pfs); pvNew->Remove(pfs);
}
pvNew->Remove(ph); return sc; }
//+---------------------------------------------------------------------------
//
// Function: RemapFat
//
// Synopsis: Remap the Fat according to a processed script and the original
// file
//
// Arguments: [pvNew] -- Pointer to base of destination memory mapped file
// [pvOld] -- Pointer to base of source memory mapped file
// [psScript] -- Pointer to processed script
// [csectFile] -- Count of sectors in file
// [cbSectorSize] -- Sector size in bytes
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
// Notes: Since the processed script does not contain information
// about individual fat chains, we need the old file in order
// to construct the new fat.
//
//----------------------------------------------------------------------------
SCODE RemapFat(MAPFILE *pvNew, MAPFILE *pvOld, SECT *psScript, ULONG csectFile, ULONG cbSectorSize) { CFatSect *pfsNew; CFatSect *pfsOld;
SCODE sc = S_OK;
ULONG csectFat = pvNew->GetULONG( (ULONG) offsetof(CMSFHeaderData, _csectFat));
USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT));
for (ULONG i = 0; i < csectFat; i++) { pfsNew = GetFatSect(pvNew, i, cbSectorSize, NULL); memset(pfsNew, 0xFF, cbSectorSize);
sc = pvNew->WriteToFile(pfsNew); if (sc != S_OK) { return sc; } pvNew->Remove(pfsNew); }
for (i = 0; i < csectFat; i++) { pfsOld = GetFatSect(pvOld, i, cbSectorSize, NULL);
for (USHORT j = 0; j < csectPerFat; j++) { if (i * csectPerFat + j >= csectFile) { //Sector outside of current file size - no remapping
//is necessary, and sector has already been marked
//as free above.
break; } SECT sectOld = pfsOld->GetSect(j); SECT sectNew = psScript[i * csectPerFat + j]; ULONG iFatNew = sectNew / csectPerFat; USHORT oFatNew = (USHORT)(sectNew % csectPerFat); pfsNew = GetFatSect(pvNew, iFatNew, cbSectorSize, NULL); if (sectOld > MAXREGSECT) { pfsNew->SetSect(oFatNew, sectOld); } else { //Need to map contents.
SECT sectMap = psScript[sectOld]; pfsNew->SetSect(oFatNew, sectMap); } sc = pvNew->WriteToFile(pfsNew); pvNew->Remove(pfsNew); }
pvOld->Remove(pfsOld); } return sc; }
//+---------------------------------------------------------------------------
//
// Function: RemapDirectory
//
// Synopsis: Remap a directory based on a processed script
//
// Arguments: [pvNew] -- Pointer to base of memory mapped file
// [psScript] -- Pointer to processed script
// [csectFile] -- Count of sectors in file
// [cbSectorSize] -- Sector size in bytes
//
// Returns: Appropriate status code
//
// History: 13-Feb-96 PhilipLa Created
//
//----------------------------------------------------------------------------
SCODE RemapDirectory(MAPFILE *pvNew, SECT *psScript, ULONG csectFile, ULONG cbSectorSize) { CMSFHeaderData *ph = (CMSFHeaderData *)pvNew->GetCMSFHeaderData();
SCODE sc = S_OK;
USHORT csectPerFat = (USHORT)(cbSectorSize / sizeof(SECT)); USHORT cEntryPerSect = (USHORT)(cbSectorSize / sizeof(CDirEntry)); SECT sectDir = ph->_sectDirStart;
while (sectDir != ENDOFCHAIN) { CDirSect *pds = pvNew->GetCDirSect((sectDir * cbSectorSize) + cbSectorSize );
for (USHORT i = 0; i < cEntryPerSect; i++) { CDirEntry *pde = pds->GetEntry(i);
if (STREAMLIKE(pde->GetFlags())) { SECT sectOld = (ULONG) pde->GetStart(); #ifdef LARGE_STREAMS
ULONGLONG ulSize = pde->GetSize(cbSectorSize > 512); #else
ULONG ulSize = pde->GetSize(); #endif
swap ((char *) §Old, sizeof(SECT)); swap ((char *) &ulSize, sizeof(ulSize)); if ((ulSize >= ph->_ulMiniSectorCutoff) || (pde->GetFlags() == STGTY_ROOT)) { if ((sectOld != ENDOFCHAIN) && (sectOld != FREESECT)) { SECT sectNew = psScript[sectOld]; swap ((char *) §New, sizeof(SECT)); pde->SetStart(sectNew); } } } } sectDir = GetNext(pvNew, sectDir, cbSectorSize);
sc = pvNew->WriteToFile(pds); pvNew->Remove(pds); } pvNew->Remove(ph); return sc; }
|