|
|
// Copyright 1997 Microsoft Corporation. All Rights Reserved.
#include "header.h"
#include "fsclient.h"
#include "sitemap.h"
static const UINT CSTREAM_BUF_SIZE = (4 * 1024);
CFSClient::CFSClient() { ClearMemory(this, sizeof(CFSClient)); }
CFSClient::CFSClient(CFileSystem* pFS, PCSTR pszSubFile) { ClearMemory(this, sizeof(CFSClient)); m_pFS = pFS; m_fNoDeleteFS = TRUE; OpenStream(pszSubFile); }
CFSClient::~CFSClient() { if (m_pSubFS) delete m_pSubFS; if (m_pFS && !m_fNoDeleteFS) delete m_pFS;
if (m_pbuf) lcFree(m_pbuf); }
BOOL CFSClient::Initialize(PCSTR pszCompiledFile) { CStr cszCompiledFile; PCSTR pszFilePortion = GetCompiledName(pszCompiledFile, &cszCompiledFile);
ASSERT(cszCompiledFile.IsNonEmpty()); ASSERT(!m_pFS);
m_pFS = new CFileSystem;
if (! SUCCEEDED(m_pFS->Init()) ) return FALSE;
if ( !SUCCEEDED(m_pFS->Open((PSTR)cszCompiledFile)) ) { delete m_pFS; m_pFS = NULL; return FALSE; }
if (pszFilePortion) return SUCCEEDED(OpenStream(pszFilePortion));
return TRUE; }
HRESULT CFSClient::OpenStream(PCSTR pszFile, DWORD dwAccess) { HRESULT hr; ASSERT(m_pFS); if (! m_pFS ) return E_FAIL;
m_pSubFS = new CSubFileSystem(m_pFS);
PSTR pszFileCopy = _strdup(pszFile);
ReplaceEscapes(pszFile, pszFileCopy, ESCAPE_URL);
if (! SUCCEEDED(hr = m_pSubFS->OpenSub(pszFileCopy, dwAccess)) ) { delete m_pSubFS; m_pSubFS = NULL; } free(pszFileCopy); return hr; }
void CFSClient::WriteStorageContents(PCSTR pszRootFolder, OLECHAR* wszFSName) { IStorage* pStorage; HRESULT hr; BOOL fDoRelease = FALSE;
if (! m_pFS ) return;
if (wszFSName != NULL) { IStorage* pStorage2 = m_pFS->GetITStorageDocObj(); HRESULT hr = pStorage2->OpenStorage(wszFSName, NULL, STGM_READ, NULL, 0, &pStorage); if (!SUCCEEDED(hr)) { DEBUG_ReportOleError(hr); return; } fDoRelease = TRUE; } else pStorage = m_pFS->GetITStorageDocObj();
IEnumSTATSTG* pEnum; hr = pStorage->EnumElements(0, NULL, 0, &pEnum); if (!SUCCEEDED(hr)) { DEBUG_ReportOleError(hr); return; }
STATSTG Stat;
if (GetFileAttributes(pszRootFolder) == HFILE_ERROR) { // Only ask about creating the root folder
if (!CreateFolder(pszRootFolder)) return; }
while (GetElementStat(pEnum, &Stat)) { char szFullPath[MAX_PATH]; CStr cszName(Stat.pwcsName); // convert to Multi-Byte
CoTaskMemFree(GetStatName()); if (cszName.psz[0] == '#' || cszName.psz[0] == '$') { continue; // we don't decompile system files
} if (Stat.type == STGTY_STORAGE) { strcpy(szFullPath, pszRootFolder); AddTrailingBackslash(szFullPath); strcat(szFullPath, cszName); WCHAR wszTemp[MAX_PATH]; wszTemp[0] = NULL; if (wszFSName) { lstrcpyW(wszTemp,wszFSName); lstrcatW(wszTemp, L"\\"); } lstrcatW(wszTemp, Stat.pwcsName); WriteStorageContents(szFullPath, wszTemp); } else { strcpy(szFullPath, pszRootFolder); AddTrailingBackslash(szFullPath); strcat(szFullPath, cszName);
HANDLE hf = CreateFile(szFullPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hf == INVALID_HANDLE_VALUE) continue;
CMem mem(Stat.cbSize.LowPart); ULONG cbRead; if (wszFSName) { CStr cszFsName(wszFSName); strcpy(szFullPath, cszFsName); AddTrailingBackslash(szFullPath); strcat(szFullPath, cszName); cszName = szFullPath; } hr = OpenStream(cszName); if (SUCCEEDED(hr)) { hr = Read(mem, Stat.cbSize.LowPart, &cbRead); DWORD cbWritten; if (SUCCEEDED(hr)) WriteFile(hf, mem, cbRead, &cbWritten, NULL); CloseStream(); } CloseHandle(hf); if (!SUCCEEDED(hr)) DeleteFile(szFullPath); } }
ReleaseObjPtr(pEnum); if ( fDoRelease ) ReleaseObjPtr(pStorage); }
ULONG CFSClient::GetElementStat(ULONG nNumber, STATSTG* stat, IEnumSTATSTG* pEnum) { ULONG nReturned = 0; HRESULT hr;
if (pEnum == NULL) { if (m_pEnum) { hr = m_pEnum->Next(nNumber, stat, &nReturned); } else hr = S_FALSE; } else { hr = pEnum->Next(nNumber, stat, &nReturned); } return (SUCCEEDED(hr) ? nReturned : 0); }
HRESULT CFSClient::Read(void* pDst, const ULONG cbRead, ULONG* pcbRead) { ASSERT(m_pFS); ASSERT(m_pSubFS); if (m_cbBuf) { // we've streamed it
*pcbRead = Read((PBYTE) pDst, cbRead); return S_OK; } else return m_pSubFS->ReadSub(pDst, cbRead, pcbRead); }
ULONG CFSClient::Read(PBYTE pbDest, ULONG cbBytes) { if (!m_cbBuf) ReadBuf();
if (m_pEndBuf - m_pbuf < m_cbBuf) { // adjust cbBytes for actual remaining size
if (m_pEndBuf - m_pCurBuf < (int) cbBytes) cbBytes = (ULONG)(m_pEndBuf - m_pCurBuf); } if (m_pCurBuf + cbBytes < m_pEndBuf) { memcpy(pbDest, m_pCurBuf, cbBytes); m_pCurBuf += cbBytes; return cbBytes; } PBYTE pbDst = (PBYTE) pbDest;
// If destination buffer is larger then our internal buffer, then
// recursively call until we have filled up the destination.
int cbRead = (int)(m_pEndBuf - m_pCurBuf); memcpy(pbDest, m_pCurBuf, cbRead); pbDst += cbRead; if (!m_fEndOfFile) ReadBuf(); if (m_fEndOfFile) return cbRead;
return Read(pbDst, cbBytes - cbRead) + cbRead; }
void CFSClient::ReadBuf(void) { ULONG cRead; if (!m_cbBuf) { m_cbBuf = CSTREAM_BUF_SIZE; // use constant in case we pull in read-ahead code from CStream
// +2 because we add a zero just past the buffer in case anyone expects strings
m_pbuf = (PBYTE) lcMalloc(CSTREAM_BUF_SIZE); m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cRead); m_pCurBuf = m_pbuf; m_pEndBuf = m_pbuf + cRead; m_lFilePos = cRead; m_lFileBuf = 0; return; } m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cRead); m_lFileBuf = m_lFilePos; m_lFilePos += cRead;
m_pCurBuf = m_pbuf; m_pEndBuf = m_pbuf + cRead;
if (!cRead) m_fEndOfFile = TRUE; }
HRESULT CFSClient::seek(int pos, SEEK_TYPE seek) { ASSERT(seek != SK_END); // we don't support this one
if (seek == SK_CUR) // convert to SEEK_SET equivalent
pos = m_lFileBuf + (int)(m_pCurBuf - m_pbuf) + pos;
if (pos >= m_lFileBuf && pos < m_lFilePos) { m_pCurBuf = m_pbuf + (pos - m_lFileBuf); if (m_pCurBuf >= m_pEndBuf && m_pEndBuf < m_pbuf + m_cbBuf) m_fEndOfFile = TRUE; return S_OK; } else { m_lFileBuf = m_pSubFS->SeekSub(pos, SK_SET); ULONG cread; if (FAILED(m_pSubFS->ReadSub(m_pbuf, m_cbBuf, &cread))) { m_fEndOfFile = TRUE; return STG_E_READFAULT; } m_lFilePos = m_lFileBuf + cread; m_pCurBuf = m_pbuf; m_pEndBuf = m_pbuf + cread; if (cread == 0) m_fEndOfFile = TRUE;
return S_OK; } }
void CFSClient::CloseStream(void) { if (m_pSubFS) { delete m_pSubFS; m_pSubFS = NULL; } if (m_pbuf) { lcFree(m_pbuf); m_pbuf = NULL; m_cbBuf = 0; } }
|