|
|
#include "privcpp.h"
// Constructor
CPackage_IPersistStorage::CPackage_IPersistStorage(CPackage *pPackage) : _pPackage(pPackage) { ASSERT(_cRef == 0); ASSERT(_psState == PSSTATE_UNINIT); }
CPackage_IPersistStorage::~CPackage_IPersistStorage() { DebugMsg(DM_TRACE,"CPackage_IPersistStorage destroyed with ref count %d",_cRef); }
//////////////////////////////////
//
// IUnknown Methods...
//
HRESULT CPackage_IPersistStorage::QueryInterface(REFIID iid, void ** ppv) { return _pPackage->QueryInterface(iid,ppv); // delegate to CPackage
}
ULONG CPackage_IPersistStorage::AddRef(void) { _cRef++; // interface ref count for debug
return _pPackage->AddRef(); // delegate to CPackage
}
ULONG CPackage_IPersistStorage::Release(void) { _cRef--; // interface ref count for debug
return _pPackage->Release(); // delegate to CPackage
}
//////////////////////////////////
//
// IPersistStorage Methods...
//
HRESULT CPackage_IPersistStorage::GetClassID(LPCLSID pClassID) { DebugMsg(DM_TRACE, "pack ps - GetClassID() called."); if (_psState == PSSTATE_UNINIT) return E_UNEXPECTED; if (pClassID == NULL) return E_INVALIDARG; *pClassID = CLSID_CPackage; return S_OK; }
HRESULT CPackage_IPersistStorage::IsDirty(void) { DebugMsg(DM_TRACE, "pack ps - IsDirty() called. _fIsDirty==%d", (INT)_pPackage->_fIsDirty); if (_psState == PSSTATE_UNINIT) return E_UNEXPECTED; return (_pPackage->_fIsDirty ? S_OK : S_FALSE); }
HRESULT CPackage_IPersistStorage::InitNew(IStorage *pstg) { HRESULT hr;
DebugMsg(DM_TRACE, "pack ps - InitNew() called.");
if (_psState != PSSTATE_UNINIT) return E_UNEXPECTED;
if (!pstg) return E_POINTER;
// Create a stream to save the package and cache the pointer. By doing
// this now we ensure being able to save in low memory conditions.
//
hr = pstg->CreateStream(SZCONTENTS,STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &_pPackage->_pstm); if (SUCCEEDED(hr)) { hr = WriteFmtUserTypeStg(pstg, (CLIPFORMAT)_pPackage->_cf,SZUSERTYPE); if (SUCCEEDED(hr)) { _pPackage->_fIsDirty = TRUE; _psState = PSSTATE_SCRIBBLE; _pPackage->_pIStorage = pstg; // cache the IStorage pointer
_pPackage->_pIStorage->AddRef(); // but don't forget to addref it!
DebugMsg(DM_TRACE, " leaving InitNew()"); } else { _pPackage->_pstm->Release(); _pPackage->_pstm = NULL; } }
return hr; }
HRESULT CPackage_IPersistStorage::Load(IStorage *pstg) { HRESULT hr; LPSTREAM pstm = NULL; // package contents
CLSID clsid;
DebugMsg(DM_TRACE, "pack ps - Load() called.");
if (_psState != PSSTATE_UNINIT) { DebugMsg(DM_TRACE," wrong state!!"); return E_UNEXPECTED; } if (!pstg) { DebugMsg(DM_TRACE," bad pointer!!"); return E_POINTER; } // check to make sure this is one of our storages
hr = ReadClassStg(pstg, &clsid); if (SUCCEEDED(hr) && (clsid != CLSID_CPackage && clsid != CLSID_OldPackage) || FAILED(hr)) { DebugMsg(DM_TRACE," bad storage type!!"); return E_UNEXPECTED; } hr = pstg->OpenStream(SZCONTENTS,0, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstm); if (FAILED(hr)) { DebugMsg(DM_TRACE," couldn't open contents stream!!"); DebugMsg(DM_TRACE," hr==%Xh",hr); goto ErrRet; }
hr = _pPackage->PackageReadFromStream(pstm); if (FAILED(hr)) goto ErrRet; _pPackage->_pstm = pstm; _pPackage->_pIStorage = pstg; pstg->AddRef(); _psState = PSSTATE_SCRIBBLE; _pPackage->_fIsDirty = FALSE; _pPackage->_fLoaded = TRUE; DebugMsg(DM_TRACE, " leaving Load()"); return S_OK; ErrRet: if (pstm) pstm->Release(); return hr; }
HRESULT CPackage_IPersistStorage::Save(IStorage *pstg, BOOL fSameAsLoad) { HRESULT hr; LPSTREAM pstm=NULL;
DebugMsg(DM_TRACE, "pack ps - Save() called."); // must come here from scribble state
if ((_psState != PSSTATE_SCRIBBLE) && fSameAsLoad) { DebugMsg(DM_TRACE," bad state!!"); return E_UNEXPECTED; } // must have an IStorage if not SameAsLoad
if (!pstg && !fSameAsLoad) { DebugMsg(DM_TRACE," bad pointer!!"); return E_POINTER; } // hopefully, the container calls WriteClassStg with our CLSID before
// we get here, that way we can overwrite that and write out the old
// packager's CLSID so that the old packager can read new packages.
//
if (FAILED(WriteClassStg(pstg,CLSID_OldPackage))) { DebugMsg(DM_TRACE, " couldn't write CLSID to storage!!"); return E_FAIL; } //
// ok, we have four possible ways we could be calling Save:
// 1. we're creating a new package and saving to the same
// storage we received in InitNew
// 2. We're creating a new package and saving to a different
// storage than we received in InitNew
// 3. We were loaded by a container and we're saving to the
// same stream we received in Load
// 4. We were loaded by a container and we're saving to a
// different stream than we received in Load
//
//////////////////////////////////////////////////////////////////
//
// Same Storage as Load
//
//////////////////////////////////////////////////////////////////
if (fSameAsLoad) {
DebugMsg(DM_TRACE," Same as load."); LARGE_INTEGER li = {0,0}; pstm = _pPackage->_pstm;
// If we're not dirty, so there's nothing new to save.
if (FALSE == _pPackage->_fIsDirty) { DebugMsg(DM_TRACE, " not saving cause we're not dirty!!"); return S_OK; } // if we are dirty, set the seek pointer to the beginning and write
// the package information to the stream
hr = pstm->Seek(li, STREAM_SEEK_SET, NULL); if (FAILED(hr)) { DebugMsg(DM_TRACE, " couldn't set contents pointer!!"); return hr; } // case 1: new package
if (!_pPackage->_fLoaded) { switch(_pPackage->_panetype) { LPTSTR temp; case PEMBED: // if haven't created a temp file yet, then use the the
// file to be packaged to get our file contents from,
// otherwise we just use the temp file, because if we
// have a temp file, it contains the most recent info.
//
temp = _pPackage->_pEmbed->pszTempName; if (!_pPackage->_pEmbed->pszTempName) { DebugMsg(DM_TRACE, " case 1a:not loaded, using initFile."); _pPackage->_pEmbed->pszTempName = _pPackage->_pEmbed->fd.cFileName; } else { DebugMsg(DM_TRACE, " case 1b:not loaded, using tempfile."); } hr = _pPackage->PackageWriteToStream(pstm); // reset our temp name back, since we might have changed it
// basically, this just sets it to NULL if it was before
_pPackage->_pEmbed->pszTempName = temp; break;
case CMDLINK: // nothing screwy to do here...just write out the info
// which we already have in memory.
hr = _pPackage->PackageWriteToStream(pstm); break; } if (FAILED(hr)) return hr; } // case 3: loaded package
else { hr = _pPackage->PackageWriteToStream(pstm); } } //////////////////////////////////////////////////////////////////
//
// NEW Storage
//
//////////////////////////////////////////////////////////////////
else {
DebugMsg(DM_TRACE," NOT same as load."); hr = pstg->CreateStream(SZCONTENTS,STGM_DIRECT | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pstm); if (FAILED(hr)) { DebugMsg(DM_TRACE, " couldn't create contents stream!!"); return hr; } WriteFmtUserTypeStg(pstg, (CLIPFORMAT)_pPackage->_cf,SZUSERTYPE); // case 2:
if (!_pPackage->_fLoaded) { switch(_pPackage->_panetype) { LPTSTR temp; case PEMBED: temp = _pPackage->_pEmbed->pszTempName; if (!_pPackage->_pEmbed->pszTempName) { DebugMsg(DM_TRACE, " case 2a:not loaded, using initFile."); _pPackage->_pEmbed->pszTempName = _pPackage->_pEmbed->fd.cFileName; } else { DebugMsg(DM_TRACE, " case 2b:not loaded, using tempfile."); } hr = _pPackage->PackageWriteToStream(pstm); // reset our temp name back, since we might have changed it
// basically, this just sets it to NULL if it was before
_pPackage->_pEmbed->pszTempName = temp; break;
case CMDLINK: // nothing interesting to do here, other than write out
// the package.
hr = _pPackage->PackageWriteToStream(pstm); break; }
if (FAILED(hr)) goto ErrRet; } // case 4:
else { if (_pPackage->_panetype == PEMBED && _pPackage->_pEmbed->pszTempName ) { DebugMsg(DM_TRACE," case 4a:loaded, using tempfile."); hr = _pPackage->PackageWriteToStream(pstm); if (FAILED(hr)) goto ErrRet; } else { DebugMsg(DM_TRACE," case 4b:loaded, using stream."); ULARGE_INTEGER uli = { 0xFFFFFFFF, 0xFFFFFFFF }; LARGE_INTEGER li = {0,0}; hr = _pPackage->_pstm->Seek(li,STREAM_SEEK_SET,NULL); if (FAILED(hr)) goto ErrRet; hr = _pPackage->_pstm->CopyTo(pstm,uli,NULL,NULL); if (FAILED(hr)) goto ErrRet; } } ErrRet: UINT u = pstm->Release(); DebugMsg(DM_TRACE," new stream released. cRef==%d.",u); if (FAILED(hr)) return hr; } _psState = PSSTATE_ZOMBIE; DebugMsg(DM_TRACE, " leaving Save()"); return S_OK; }
HRESULT CPackage_IPersistStorage::SaveCompleted(IStorage *pstg) { HRESULT hr; LPSTREAM pstm; DebugMsg(DM_TRACE, "pack ps - SaveCompleted() called.");
// must be called from no-scribble or hands-off state
if (!(_psState == PSSTATE_ZOMBIE || _psState == PSSTATE_HANDSOFF)) return E_UNEXPECTED; // if we're hands-off, we'd better get a storage to re-init from
if (!pstg && _psState == PSSTATE_HANDSOFF) return E_UNEXPECTED; // if pstg is NULL then we have everything we need, otherwise we must
// release our held pointers and reinitialize.
//
if (pstg != NULL) { DebugMsg(DM_TRACE, " getting new storage."); hr = pstg->OpenStream(SZCONTENTS, 0, STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pstm); if (FAILED(hr)) return hr;
if (_pPackage->_pstm != NULL) _pPackage->_pstm->Release(); // this will be reinitialized when it's needed
if (_pPackage->_pstmFileContents != NULL) { _pPackage->_pstmFileContents->Release(); _pPackage->_pstmFileContents = NULL; } if (_pPackage->_pIStorage != NULL) _pPackage->_pIStorage->Release();
_pPackage->_pstm = pstm; _pPackage->_pIStorage = pstg; _pPackage->_pIStorage->AddRef(); } _psState = PSSTATE_SCRIBBLE; _pPackage->_fIsDirty = FALSE; DebugMsg(DM_TRACE, " leaving SaveCompleted()"); return S_OK; }
HRESULT CPackage_IPersistStorage::HandsOffStorage(void) { DebugMsg(DM_TRACE, "pack ps - HandsOffStorage() called.");
// must come from scribble or no-scribble. a repeated call to
// HandsOffStorage is an unexpected error (bug in client).
//
if (_psState == PSSTATE_UNINIT || _psState == PSSTATE_HANDSOFF) return E_UNEXPECTED; // release our held pointers
//
if (_pPackage->_pstmFileContents != NULL) { _pPackage->_pstmFileContents->Release(); _pPackage->_pstmFileContents = NULL; } if (_pPackage->_pstm != NULL) { _pPackage->_pstm->Release(); _pPackage->_pstm = NULL; } if (_pPackage->_pIStorage != NULL) { _pPackage->_pIStorage->Release(); _pPackage->_pIStorage = NULL; } _psState = PSSTATE_HANDSOFF; DebugMsg(DM_TRACE, " leaving HandsOffStorage()"); return S_OK; }
|