IPERSTOR.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * IPERSTOR.CPP
- * Polyline Component Chapter 19
- *
- * Implementation of the IPersistStorage interface exposed on the
- * Polyline object.
- *
- * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
- *
- * Kraig Brockschmidt, Microsoft
- * Internet : kraigb@microsoft.com
- * Compuserve: >INTERNET:kraigb@microsoft.com
- */
- #include "polyline.h"
- /*
- * CImpIPersistStorage:CImpIPersistStorage
- * CImpIPersistStorage::~CImpIPersistStorage
- *
- * Constructor Parameters:
- * pObj PCPolyline pointing to the object we live in.
- * pUnkOuter LPUNKNOWN of the controlling unknown.
- */
- CImpIPersistStorage::CImpIPersistStorage(PCPolyline pObj
- , LPUNKNOWN pUnkOuter)
- {
- m_cRef=0;
- m_pObj=pObj;
- m_pUnkOuter=pUnkOuter;
- m_psState=PSSTATE_UNINIT;
- return;
- }
- CImpIPersistStorage::~CImpIPersistStorage(void)
- {
- return;
- }
- /*
- * CImpIPersistStorage::QueryInterface
- * CImpIPersistStorage::AddRef
- * CImpIPersistStorage::Release
- */
- STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid
- , PPVOID ppv)
- {
- return m_pUnkOuter->QueryInterface(riid, ppv);
- }
- STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
- {
- ++m_cRef;
- return m_pUnkOuter->AddRef();
- }
- STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
- {
- --m_cRef;
- return m_pUnkOuter->Release();
- }
- /*
- * CImpIPersistStorage::GetClassID
- *
- * Purpose:
- * Returns the CLSID of the object represented by this interface.
- *
- * Parameters:
- * pClsID LPCLSID in which to store our CLSID.
- *
- * Return Value:
- * HRESULT NOERROR on success, error code otherwise.
- */
- STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
- {
- if (PSSTATE_UNINIT==m_psState)
- return ResultFromScode(E_UNEXPECTED);
- *pClsID=m_pObj->m_clsID;
- return NOERROR;
- }
- /*
- * CImpIPersistStorage::IsDirty
- *
- * Purpose:
- * Tells the caller if we have made changes to this object since
- * it was loaded or initialized new.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * HRESULT Contains S_OK if we ARE dirty, S_FALSE if
- * NOT dirty.
- *
- */
- STDMETHODIMP CImpIPersistStorage::IsDirty(void)
- {
- if (PSSTATE_UNINIT==m_psState)
- return ResultFromScode(E_UNEXPECTED);
- return ResultFromScode(m_pObj->m_fDirty ? S_OK : S_FALSE);
- }
- /*
- * CImpIPersistStorage::InitNew
- *
- * Purpose:
- * Provides the object with the IStorage to hold on to while the
- * object is running. Here we initialize the structure of the
- * storage and AddRef it for incremental access. This function will
- * only be called once in the object's lifetime in lieu of Load.
- *
- * Parameters:
- * pIStorage LPSTORAGE for the object.
- *
- * Return Value:
- * HRESULT NOERROR or a general error value.
- */
- STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
- {
- HRESULT hr;
- if (PSSTATE_UNINIT!=m_psState)
- return ResultFromScode(E_UNEXPECTED);
- if (NULL==pIStorage)
- return ResultFromScode(E_POINTER);
- /*
- * The rules of IPersistStorage mean we hold onto the IStorage
- * and pre-create anything we'd need in Save(...,TRUE) for
- * low-memory situations. For us this means creating our
- * "CONTENTS" stream and holding onto that IStream as
- * well as the IStorage here (requiring an AddRef call).
- */
- hr=pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
- | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
- , 0, 0, &m_pObj->m_pIStream);
- if (FAILED(hr))
- return hr;
- //We expect that the client has called WriteClassStg
- WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
- , (*m_pObj->m_pST)[IDS_USERTYPE]);
- m_pObj->m_pIStorage=pIStorage;
- pIStorage->AddRef();
- m_psState=PSSTATE_SCRIBBLE;
- //CHAPTER19MOD
- //Initialize the cache as needed.
- m_pObj->m_pDefIPersistStorage->InitNew(pIStorage);
- //End CHAPTER19MOD
- return NOERROR;
- }
- /*
- * CImpIPersistStorage::Load
- *
- * Purpose:
- * Instructs the object to load itself from a previously saved
- * IStorage that was handled by Save in another object lifetime.
- * This function will only be called once in the object's lifetime
- * in lieu of InitNew. The object should hold on to pIStorage here
- * for incremental access and low-memory saves in Save.
- *
- * Parameters:
- * pIStorage LPSTORAGE from which to load.
- *
- * Return Value:
- * HRESULT NOERROR or a general error value.
- */
- STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
- {
- POLYLINEDATA pl;
- ULONG cb;
- LPSTREAM pIStream;
- HRESULT hr;
- if (PSSTATE_UNINIT!=m_psState)
- return ResultFromScode(E_UNEXPECTED);
- if (NULL==pIStorage)
- return ResultFromScode(E_POINTER);
- //We don't check CLSID to remain compatible with other chapters.
- hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
- | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
- if (FAILED(hr))
- return ResultFromScode(STG_E_READFAULT);
- //Read all the data into the POLYLINEDATA structure.
- hr=pIStream->Read(&pl, CBPOLYLINEDATA, &cb);
- if (FAILED(hr) || CBPOLYLINEDATA!=cb)
- {
- pIStream->Release();
- return hr;
- }
- /*
- * We don't call pIStream->Release here because we may need
- * it for a low-memory save in Save. We also need to
- * hold onto a copy of pIStorage, meaning AddRef.
- */
- m_pObj->m_pIStream=pIStream;
- m_pObj->m_pIStorage=pIStorage;
- pIStorage->AddRef();
- //DataSet now internal on CPolyline
- m_pObj->DataSet(&pl, TRUE, TRUE);
- m_psState=PSSTATE_SCRIBBLE;
- //CHAPTER19MOD
- //We also need to tell the cache to load cached graphics
- m_pObj->m_pDefIPersistStorage->Load(pIStorage);
- //End CHAPTER19MOD
- return NOERROR;
- }
- /*
- * CImpIPersistStorage::Save
- *
- * Purpose:
- * Saves the data for this object to an IStorage which may
- * or may not be the same as the one previously passed to
- * Load, indicated with fSameAsLoad. After this call we may
- * not write into the storage again until SaveCompleted is
- * called, although we may still read.
- *
- * Parameters:
- * pIStorage LPSTORAGE in which to save our data.
- * fSameAsLoad BOOL indicating if this is the same pIStorage
- * that was passed to Load. If TRUE, then the
- * object should write whatever it has *without
- * *using any extra memory* as this may be a low
- * memory save attempt. That means that you must
- * not try to open or create streams. If FALSE
- * you need to regenerate your whole storage
- * structure, being sure to also release any
- * pointers held from InitNew and Load.
- *
- * Return Value:
- * HRESULT NOERROR or a general error value.
- */
- STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage
- , BOOL fSameAsLoad)
- {
- POLYLINEDATA pl;
- ULONG cb;
- LPSTREAM pIStream;
- HRESULT hr;
- //Have to come here from scribble state.
- if (PSSTATE_SCRIBBLE!=m_psState)
- return ResultFromScode(E_UNEXPECTED);
- //Must have an IStorage if we're not in SameAsLoad
- if (NULL==pIStorage && !fSameAsLoad)
- return ResultFromScode(E_POINTER);
- /*
- * If we're saving to a new storage, create a new stream.
- * If fSameAsLoad it TRUE, then we write to the
- * stream we already allocated. We should NOT depends on
- * pIStorage with fSameAsLoad is TRUE.
- */
- if (fSameAsLoad)
- {
- LARGE_INTEGER li;
- /*
- * Use pre-allocated streams to avoid failures due
- * to low-memory conditions. Be sure to reset the
- * stream pointer if you used this stream before!!
- */
- pIStream=m_pObj->m_pIStream;
- LISet32(li, 0);
- pIStream->Seek(li, STREAM_SEEK_SET, NULL);
- //This matches the Release below.
- pIStream->AddRef();
- }
- else
- {
- hr=pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
- | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE
- , 0, 0, &pIStream);
- if (FAILED(hr))
- return hr;
- //Only do this with new storages.
- WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
- , (*m_pObj->m_pST)[IDS_USERTYPE]);
- }
- //DataGet now internal on CPolyline
- m_pObj->DataGet(&pl);
- hr=pIStream->Write(&pl, CBPOLYLINEDATA, &cb);
- pIStream->Release();
- if (FAILED(hr) || CBPOLYLINEDATA!=cb)
- return ResultFromScode(STG_E_WRITEFAULT);
- m_psState=PSSTATE_ZOMBIE;
- //CHAPTER19MOD
- //We also need to tell the cache to save cached graphics
- m_pObj->m_pDefIPersistStorage->Save(pIStorage, fSameAsLoad);
- //End CHAPTER19MOD
- return NOERROR;
- }
- /*
- * CImpIPersistStorage::SaveCompleted
- *
- * Purpose:
- * Notifies the object that the storage in pIStorage has been
- * completely saved now. This is called when the user of this
- * object wants to save us in a completely new storage, and if
- * we normally hang on to the storage we have to reinitialize
- * ourselves here for this new one that is now complete.
- *
- * Parameters:
- * pIStorage LPSTORAGE of the new storage in which we live.
- *
- * Return Value:
- * HRESULT NOERROR or a general error value.
- */
- STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
- {
- HRESULT hr;
- LPSTREAM pIStream;
- //Must be called in no-scribble or hands-off state
- if (!(PSSTATE_ZOMBIE==m_psState || PSSTATE_HANDSOFF==m_psState))
- return ResultFromScode(E_UNEXPECTED);
- //If we're coming from Hands-Off, we'd better get a storage
- if (NULL==pIStorage && PSSTATE_HANDSOFF==m_psState)
- return ResultFromScode(E_UNEXPECTED);
- /*
- * If pIStorage is NULL, then we don't need to do anything
- * since we already have all the pointers we need for Save.
- * Otherwise we have to release any held pointers and
- * reinitialize them from pIStorage.
- */
- if (NULL!=pIStorage)
- {
- hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
- | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0
- , &pIStream);
- if (FAILED(hr))
- return hr;
- if (NULL!=m_pObj->m_pIStream)
- m_pObj->m_pIStream->Release();
- m_pObj->m_pIStream=pIStream;
- if (NULL!=m_pObj->m_pIStorage)
- m_pObj->m_pIStorage->Release();
- m_pObj->m_pIStorage=pIStorage;
- m_pObj->m_pIStorage->AddRef();
- }
- //Change state back to scribble.
- m_psState=PSSTATE_SCRIBBLE;
- //CHAPTER19MOD
- m_pObj->m_pDefIPersistStorage->SaveCompleted(pIStorage);
- //End CHAPTER19MOD
- return NOERROR;
- }
- /*
- * CImpIPersistStorage::HandsOffStorage
- *
- * Purpose:
- * Instructs the object that another agent is interested in having
- * total access to the storage we might be hanging on to from
- * InitNew or SaveCompleted. In this case we must release our hold
- * and await another call to SaveCompleted before we have a hold
- * again. Therefore we cannot read or write after this call until
- * SaveCompleted.
- *
- * Situations where this might happen arise in compound document
- * scenarios where this object might be in-place active but the
- * application wants to rename and commit the root storage.
- * Therefore we are asked to close our hold, let the container
- * party on the storage, then call us again later to tell us the
- * new storage we can hold.
- *
- * Parameters:
- * None
- *
- * Return Value:
- * HRESULT NOERROR or a general error value.
- */
- STDMETHODIMP CImpIPersistStorage::HandsOffStorage(void)
- {
- /*
- * Must come from scribble or no-scribble. A repeated call
- * to HandsOffStorage is an unexpected error (bug in client).
- */
- if (PSSTATE_UNINIT==m_psState || PSSTATE_HANDSOFF==m_psState)
- return ResultFromScode(E_UNEXPECTED);
- //Release held pointers
- if (NULL!=m_pObj->m_pIStream)
- {
- m_pObj->m_pIStream->Release();
- m_pObj->m_pIStream=NULL;
- }
- if (NULL!=m_pObj->m_pIStorage)
- {
- m_pObj->m_pIStorage->Release();
- m_pObj->m_pIStorage=NULL;
- }
- m_psState=PSSTATE_HANDSOFF;
- //CHAPTER19MOD
- m_pObj->m_pDefIPersistStorage->HandsOffStorage();
- //End CHAPTER19MOD
- return NOERROR;
- }