|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: layscrpt.cxx
//
// Contents: Code for the LayoutScript method
//
//
// History: 22-Apr-96 SusiA Created
//
//----------------------------------------------------------------------------
#include "layouthd.cxx"
#pragma hdrstop
#include <dirfunc.hxx>
#include "layout.hxx"
#include "laylkb.hxx"
#include "laywrap.hxx"
#define NULL_TERM L'\0'
#define BACKSLASH L'\\'
#define MAX_BUFFER 0x10000
//#define UNIT_TEST
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::FreeStmList
//
// Synopsis: Free the stream linked list
//
// Arguments: [pStmList] -- Pointer STREAMLIST node
//
//----------------------------------------------------------------------------
void CLayoutRootStorage::FreeStmList( STREAMLIST *pStmList) { STREAMLIST *ptmp = pStmList;
while (pStmList) { ptmp = pStmList->pnext;
#ifdef UNIT_TEST
wprintf(L"STGTY_STREAM %ls\n", pStmList->pwcsStmName ); #endif
CoTaskMemFree(pStmList->pwcsStmName); pStmList->pStm->Release(); delete pStmList; pStmList = ptmp;
}
}
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::FreeStgList
//
// Synopsis: Free the storage linked list
//
// Arguments: [pStgList] -- Pointer STORAGELIST node
//
//----------------------------------------------------------------------------
void CLayoutRootStorage::FreeStgList( STORAGELIST *pStgList) { STORAGELIST *ptmp;
while (pStgList) { ptmp = pStgList->pnext; #ifdef UNIT_TEST
wprintf(L"STGTY_STORAGE %ls\n", pStgList->pwcsStgName ); #endif
CoTaskMemFree(pStgList->pwcsStgName); pStgList->pStg->Release(); delete pStgList;
pStgList = ptmp; } }
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ProcessOpen
//
// Synopsis: Open the storage or stream
//
// Arguments: [pwcsElementPathName] -- full "path" name of element to open
// [dwType] STGTY_STORAGE or STGTY_STREAM
// [ppIstgStm] interface pointer to the opened Storage or Stream
// [cOffset] offset of beginning of the read
//
// Returns: Appropriate status code
//
// History: 22-Apr-96 SusiA Created
//
//----------------------------------------------------------------------------
SCODE CLayoutRootStorage::ProcessOpen(OLECHAR *pwcsElementPathName, DWORD dwType, void **ppIStgStm, LARGE_INTEGER cOffset) { SCODE sc = S_OK;
IStorage *pStgNew; IStream *pStmNew;
IStorage *pStg = this;
STORAGELIST *pStgList; STREAMLIST *pStmList;
OLECHAR *pwcsStg = pwcsElementPathName, *pwcsTemp = pwcsElementPathName; OLECHAR *pwcsBuffer;
if ( (!pwcsElementPathName) || (pwcsElementPathName[0] == NULL_TERM)) { return STG_E_PATHNOTFOUND; } // process storage path
while (1) { while ((*pwcsTemp) && (*pwcsTemp != BACKSLASH)) { pwcsTemp++; }
pwcsBuffer = (OLECHAR *) CoTaskMemAlloc ((INT)(pwcsTemp - pwcsElementPathName + 1) * sizeof(OLECHAR) ); if (!pwcsBuffer) { return STG_E_INSUFFICIENTMEMORY; } lstrcpynW (pwcsBuffer, pwcsElementPathName, (INT)(pwcsTemp - pwcsElementPathName + 1));
pwcsBuffer[pwcsTemp - pwcsElementPathName] = NULL_TERM;
if (!(*pwcsTemp)) { //we are at the end, now handle leaf Storage or stream
break; }
pStgList = _pStgList;
// see if this storage is already in the list
while (pStgList) { if (!(lstrcmpW(pwcsBuffer, pStgList->pwcsStgName ))) { break; }
pStgList = pStgList->pnext; } if (pStgList) { pStgNew = pStgList->pStg; CoTaskMemFree(pwcsBuffer); } else { sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName), NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStgNew); if (FAILED(sc)) { CoTaskMemFree(pwcsBuffer); return sc; } // add the storage to the list
pStgList = _pStgList; if (NULL == (_pStgList = new STORAGELIST)) { CoTaskMemFree(pwcsBuffer); pStgNew->Release(); return STG_E_INSUFFICIENTMEMORY; }
_pStgList->pwcsStgName = pwcsBuffer; _pStgList->pStg = pStgNew; _pStgList->pnext = pStgList;
}
pStg = pStgNew; pwcsStg = ++pwcsTemp; } //process leaf storage
if (dwType == STGTY_STORAGE) { sc = pStg->OpenStorage(pwcsBuffer+(pwcsStg-pwcsElementPathName), NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStgNew); if (FAILED(sc)) { CoTaskMemFree(pwcsBuffer); return sc; }
// add the storage to the list
pStgList = _pStgList; if (NULL == (_pStgList = new STORAGELIST)) { CoTaskMemFree(pwcsBuffer); pStgNew->Release(); return STG_E_INSUFFICIENTMEMORY; }
_pStgList->pwcsStgName = pwcsBuffer; _pStgList->pStg = pStgNew; _pStgList->pnext = pStgList;
*ppIStgStm = (void *) pStgNew; } //process leaf stream
else { sc = pStg->OpenStream(pwcsBuffer+(pwcsStg-pwcsElementPathName), NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStmNew); if (FAILED(sc)) { CoTaskMemFree(pwcsBuffer); return sc; }
pStmList = _pStmList;
if (NULL == (_pStmList = new STREAMLIST)) { CoTaskMemFree(pwcsBuffer); pStmNew->Release(); return STG_E_INSUFFICIENTMEMORY; } _pStmList->pwcsStmName = pwcsBuffer; _pStmList->pStm = pStmNew; _pStmList->fDone = FALSE; _pStmList->cOffset = cOffset; _pStmList->pnext = pStmList; *ppIStgStm = (void *) pStmNew; }
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ProcessItem
//
// Synopsis: Construct an unprocessed script from an app provided script
//
// Arguments: [pLayoutItem] -- Pointer to a StorageLayout element of the array
// [fStmDone] -- indicate whether the stream finished reading
//
// Returns: Appropriate status code
//
// History: 22-Apr-96 SusiA Created
//
//----------------------------------------------------------------------------
SCODE CLayoutRootStorage::ProcessItem( StorageLayout *pLayoutItem, BOOL *fStmDone ) { SCODE sc = S_OK;
STREAMLIST *pStmList = _pStmList; STORAGELIST *pStgList = _pStgList; IStorage *pStgNew; IStream *pStmNew;
ULARGE_INTEGER libNewPosition; ULONG cbRead;
BYTE abBuffer[MAX_BUFFER]; BYTE *pb = abBuffer; BOOL fBigBuffer = FALSE;
*fStmDone = FALSE;
if ((pLayoutItem->cOffset.QuadPart < 0) || (pLayoutItem->cBytes.QuadPart < 0)) { return STG_E_INVALIDPARAMETER; } switch (pLayoutItem->LayoutType) { case STGTY_STORAGE:
#ifdef UNIT_TEST
wprintf(L"STGTY_STORAGE %ls %lu%lu %lu%lu\n", pLayoutItem->pwcsElementName, pLayoutItem->cOffset.HighPart, pLayoutItem->cOffset.LowPart, pLayoutItem->cBytes.HighPart, pLayoutItem->cBytes.LowPart); #endif
while (pStgList) { if (!(lstrcmpW(pLayoutItem->pwcsElementName, pStgList->pwcsStgName ))) { break; }
pStgList = pStgList->pnext; } // if storage was not found in the list, open the storage
// and add it to the list
if (!pStgList) { sc = ProcessOpen(pLayoutItem->pwcsElementName, STGTY_STORAGE, (void **)&pStgNew, pLayoutItem->cOffset); if (FAILED(sc)) { // the application may try to open Storages
// that do not really exist in the compound file,
// and we will let them try.
if (sc == STG_E_FILENOTFOUND) { return S_OK; } else { return sc; } } }
break;
case STGTY_STREAM:
#ifdef UNIT_TEST
wprintf(L"STGTY_STREAM %ls %lu%lu %lu%lu\n", pLayoutItem->pwcsElementName, pLayoutItem->cOffset.HighPart, pLayoutItem->cOffset.LowPart, pLayoutItem->cBytes.HighPart, pLayoutItem->cBytes.LowPart); #endif
while (pStmList) { if (!(lstrcmpW(pLayoutItem->pwcsElementName, pStmList->pwcsStmName ))) { pStmNew = pStmList->pStm; break; } pStmList = pStmList->pnext; } // if stream was not found in the list, open the stream,
// and add it to the list
if (pStmList) { if( pStmList->fDone ) { *fStmDone = TRUE; return S_OK; } } else { sc = ProcessOpen(pLayoutItem->pwcsElementName, STGTY_STREAM, (void **)&pStmNew, pLayoutItem->cOffset); if (FAILED(sc)) { // the application may try to open Streams
// that do not really exist in the compound file,
// and we will let them try.
if (sc == STG_E_FILENOTFOUND) { return S_OK; } else { return sc; } }
pStmList = _pStmList; }
// seek to the correct position
sc = pStmNew->Seek( pStmList->cOffset, STREAM_SEEK_SET, &libNewPosition ); if (FAILED(sc)) { return sc; }
// read the stream and update the script information
if (pLayoutItem->cBytes.LowPart > MAX_BUFFER) { if (NULL == (pb = (BYTE *) CoTaskMemAlloc(pLayoutItem->cBytes.LowPart)) ) { return STG_E_INSUFFICIENTMEMORY; } fBigBuffer = TRUE; } sc = pStmNew->Read(pb, pLayoutItem->cBytes.LowPart, &cbRead);
if (fBigBuffer) { CoTaskMemFree(pb); fBigBuffer = FALSE; pb = abBuffer; } if (FAILED(sc)) { return sc; } //we have reached the end of the stream, mark it as done
if (cbRead < pLayoutItem->cBytes.LowPart) { pStmList->fDone = TRUE; } pStmList->cOffset.QuadPart += cbRead; break; default: // we just handle storages and stream types
return STG_E_INVALIDPARAMETER;
} return sc; }
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ProcessRepeatLoop
//
// Synopsis: Construct an unprocessed script from an app provided script
//
// Arguments: [pStorageLayout] -- Pointer to storage layout array
// [nEntries] -- Number of entries in the array
// [nRepeatStart] -- address of index of start of repeat loop
//
// Returns: Appropriate status code
//
// History: 22-Apr-96 SusiA Created
//
//----------------------------------------------------------------------------
SCODE CLayoutRootStorage::ProcessRepeatLoop( StorageLayout *pStorageLayout, DWORD nEntries, int * nRepeatStart) { SCODE sc = S_OK;
int i, nLoopCount = 0, nLoopTimes; BOOL fDone = FALSE, fUntilDone;
// Are we going to repeat until all streams are read to the end?
if ((nLoopTimes = (LONG) pStorageLayout[*nRepeatStart].cBytes.LowPart) != STG_TOEND) fUntilDone = FALSE; else { fUntilDone = TRUE; nLoopTimes = 1; } // finished when all streams are completely read, or we have
// looped through the specified amount of times
while ((!fDone)&&(nLoopCount < nLoopTimes)) { if (!fUntilDone) nLoopCount ++;
i = *nRepeatStart; fDone = TRUE;
// STGTY_REPEAT with 0 bytes indicates the end of this repeat block
while (!((pStorageLayout[++i].LayoutType == STGTY_REPEAT ) && (pStorageLayout[i].cBytes.QuadPart == 0)) ) { if (i >= (LONG) nEntries) { return E_INVALIDARG; } // beginning of another repeat block
if (pStorageLayout[i].LayoutType == STGTY_REPEAT ) { if ((pStorageLayout[i].pwcsElementName !=NULL) || (pStorageLayout[i].cOffset.QuadPart < 0) || (pStorageLayout[i].cBytes.QuadPart < 0) ) { return STG_E_INVALIDPARAMETER; } layChk(ProcessRepeatLoop(pStorageLayout, nEntries, &i)); } else { layChk(ProcessItem(&(pStorageLayout[i]), &fDone)); } } } *nRepeatStart = i;
Err:
return sc; }
//+---------------------------------------------------------------------------
//
// Function: CLayoutRootStorage::ProcessLayout
//
// 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: 22-Apr-96 SusiA Created
//
//----------------------------------------------------------------------------
SCODE CLayoutRootStorage::ProcessLayout( StorageLayout *pStorageLayout, DWORD nEntries, DWORD glfInterleavedFlag) {
SCODE sc = S_OK; int i; BOOL fUnused; TCHAR *patcScriptName = _pllkb->GetScriptName();
for (i = 0; i < (LONG) nEntries; i++) { if (pStorageLayout[i].LayoutType == STGTY_REPEAT ) {
if (pStorageLayout[i].cBytes.QuadPart != 0) { if ((pStorageLayout[i].pwcsElementName !=NULL) || (pStorageLayout[i].cOffset.QuadPart < 0) || (pStorageLayout[i].cBytes.QuadPart < 0) ) { return STG_E_INVALIDPARAMETER; } layChk(ProcessRepeatLoop(pStorageLayout, nEntries, &i)); } else //end repeat block with no matching beginning
{ sc = E_INVALIDARG; layChk(sc);
}
} else // (pStorageLayout[i].LayoutType == STGTY_REPEAT )
{ layChk(ProcessItem(&(pStorageLayout[i]), &fUnused)); } }
Err: if (_pStgList) { FreeStgList(_pStgList); _pStgList = NULL; } if (_pStmList) { FreeStmList(_pStmList); _pStmList = NULL; } return sc;
}
|