IPERSTOR.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * IPERSTOR.CPP
  3.  * Polyline Component Chapter 19
  4.  *
  5.  * Implementation of the IPersistStorage interface exposed on the
  6.  * Polyline object.
  7.  *
  8.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Microsoft
  11.  * Internet  :  kraigb@microsoft.com
  12.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  13.  */
  14. #include "polyline.h"
  15. /*
  16.  * CImpIPersistStorage:CImpIPersistStorage
  17.  * CImpIPersistStorage::~CImpIPersistStorage
  18.  *
  19.  * Constructor Parameters:
  20.  *  pObj            PCPolyline pointing to the object we live in.
  21.  *  pUnkOuter       LPUNKNOWN of the controlling unknown.
  22.  */
  23. CImpIPersistStorage::CImpIPersistStorage(PCPolyline pObj
  24.     , LPUNKNOWN pUnkOuter)
  25.     {
  26.     m_cRef=0;
  27.     m_pObj=pObj;
  28.     m_pUnkOuter=pUnkOuter;
  29.     m_psState=PSSTATE_UNINIT;
  30.     return;
  31.     }
  32. CImpIPersistStorage::~CImpIPersistStorage(void)
  33.     {
  34.     return;
  35.     }
  36. /*
  37.  * CImpIPersistStorage::QueryInterface
  38.  * CImpIPersistStorage::AddRef
  39.  * CImpIPersistStorage::Release
  40.  */
  41. STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid
  42.     , PPVOID ppv)
  43.     {
  44.     return m_pUnkOuter->QueryInterface(riid, ppv);
  45.     }
  46. STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
  47.     {
  48.     ++m_cRef;
  49.     return m_pUnkOuter->AddRef();
  50.     }
  51. STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
  52.     {
  53.     --m_cRef;
  54.     return m_pUnkOuter->Release();
  55.     }
  56. /*
  57.  * CImpIPersistStorage::GetClassID
  58.  *
  59.  * Purpose:
  60.  *  Returns the CLSID of the object represented by this interface.
  61.  *
  62.  * Parameters:
  63.  *  pClsID          LPCLSID in which to store our CLSID.
  64.  *
  65.  * Return Value:
  66.  *  HRESULT         NOERROR on success, error code otherwise.
  67.  */
  68. STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
  69.     {
  70.     if (PSSTATE_UNINIT==m_psState)
  71.         return ResultFromScode(E_UNEXPECTED);
  72.     *pClsID=m_pObj->m_clsID;
  73.     return NOERROR;
  74.     }
  75. /*
  76.  * CImpIPersistStorage::IsDirty
  77.  *
  78.  * Purpose:
  79.  *  Tells the caller if we have made changes to this object since
  80.  *  it was loaded or initialized new.
  81.  *
  82.  * Parameters:
  83.  *  None
  84.  *
  85.  * Return Value:
  86.  *  HRESULT         Contains S_OK if we ARE dirty, S_FALSE if
  87.  *                  NOT dirty.
  88.  *
  89.  */
  90. STDMETHODIMP CImpIPersistStorage::IsDirty(void)
  91.     {
  92.     if (PSSTATE_UNINIT==m_psState)
  93.         return ResultFromScode(E_UNEXPECTED);
  94.     return ResultFromScode(m_pObj->m_fDirty ? S_OK : S_FALSE);
  95.     }
  96. /*
  97.  * CImpIPersistStorage::InitNew
  98.  *
  99.  * Purpose:
  100.  *  Provides the object with the IStorage to hold on to while the
  101.  *  object is running.  Here we initialize the structure of the
  102.  *  storage and AddRef it for incremental access. This function will
  103.  *  only be called once in the object's lifetime in lieu of Load.
  104.  *
  105.  * Parameters:
  106.  *  pIStorage       LPSTORAGE for the object.
  107.  *
  108.  * Return Value:
  109.  *  HRESULT         NOERROR or a general error value.
  110.  */
  111. STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
  112.     {
  113.     HRESULT     hr;
  114.     if (PSSTATE_UNINIT!=m_psState)
  115.         return ResultFromScode(E_UNEXPECTED);
  116.     if (NULL==pIStorage)
  117.         return ResultFromScode(E_POINTER);
  118.     /*
  119.      * The rules of IPersistStorage mean we hold onto the IStorage
  120.      * and pre-create anything we'd need in Save(...,TRUE) for
  121.      * low-memory situations.  For us this means creating our
  122.      * "CONTENTS" stream and holding onto that IStream as
  123.      * well as the IStorage here (requiring an AddRef call).
  124.      */
  125.     hr=pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
  126.         | STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE
  127.         , 0, 0, &m_pObj->m_pIStream);
  128.     if (FAILED(hr))
  129.         return hr;
  130.     //We expect that the client has called WriteClassStg
  131.     WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
  132.         , (*m_pObj->m_pST)[IDS_USERTYPE]);
  133.     m_pObj->m_pIStorage=pIStorage;
  134.     pIStorage->AddRef();
  135.     m_psState=PSSTATE_SCRIBBLE;
  136.     //CHAPTER19MOD
  137.     //Initialize the cache as needed.
  138.     m_pObj->m_pDefIPersistStorage->InitNew(pIStorage);
  139.     //End CHAPTER19MOD
  140.     return NOERROR;
  141.     }
  142. /*
  143.  * CImpIPersistStorage::Load
  144.  *
  145.  * Purpose:
  146.  *  Instructs the object to load itself from a previously saved
  147.  *  IStorage that was handled by Save in another object lifetime.
  148.  *  This function will only be called once in the object's lifetime
  149.  *  in lieu of InitNew. The object should hold on to pIStorage here
  150.  *  for incremental access and low-memory saves in Save.
  151.  *
  152.  * Parameters:
  153.  *  pIStorage       LPSTORAGE from which to load.
  154.  *
  155.  * Return Value:
  156.  *  HRESULT         NOERROR or a general error value.
  157.  */
  158. STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
  159.     {
  160.     POLYLINEDATA    pl;
  161.     ULONG           cb;
  162.     LPSTREAM        pIStream;
  163.     HRESULT         hr;
  164.     if (PSSTATE_UNINIT!=m_psState)
  165.         return ResultFromScode(E_UNEXPECTED);
  166.     if (NULL==pIStorage)
  167.         return ResultFromScode(E_POINTER);
  168.     //We don't check CLSID to remain compatible with other chapters.
  169.     hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
  170.         | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  171.     if (FAILED(hr))
  172.         return ResultFromScode(STG_E_READFAULT);
  173.     //Read all the data into the POLYLINEDATA structure.
  174.     hr=pIStream->Read(&pl, CBPOLYLINEDATA, &cb);
  175.     if (FAILED(hr) || CBPOLYLINEDATA!=cb)
  176.         {
  177.         pIStream->Release();
  178.         return hr;
  179.         }
  180.     /*
  181.      * We don't call pIStream->Release here because we may need
  182.      * it for a low-memory save in Save.  We also need to
  183.      * hold onto a copy of pIStorage, meaning AddRef.
  184.      */
  185.     m_pObj->m_pIStream=pIStream;
  186.     m_pObj->m_pIStorage=pIStorage;
  187.     pIStorage->AddRef();
  188.     //DataSet now internal on CPolyline
  189.     m_pObj->DataSet(&pl, TRUE, TRUE);
  190.     m_psState=PSSTATE_SCRIBBLE;
  191.     //CHAPTER19MOD
  192.     //We also need to tell the cache to load cached graphics
  193.     m_pObj->m_pDefIPersistStorage->Load(pIStorage);
  194.     //End CHAPTER19MOD
  195.     return NOERROR;
  196.     }
  197. /*
  198.  * CImpIPersistStorage::Save
  199.  *
  200.  * Purpose:
  201.  *  Saves the data for this object to an IStorage which may
  202.  *  or may not be the same as the one previously passed to
  203.  *  Load, indicated with fSameAsLoad.  After this call we may
  204.  *  not write into the storage again until SaveCompleted is
  205.  *  called, although we may still read.
  206.  *
  207.  * Parameters:
  208.  *  pIStorage       LPSTORAGE in which to save our data.
  209.  *  fSameAsLoad     BOOL indicating if this is the same pIStorage
  210.  *                  that was passed to Load.  If TRUE, then the
  211.  *                  object should write whatever it has *without
  212.  *                  *using any extra memory* as this may be a low
  213.  *                  memory save attempt.  That means that you must
  214.  *                  not try to open or create streams.  If FALSE
  215.  *                  you need to regenerate your whole storage
  216.  *                  structure, being sure to also release any
  217.  *                  pointers held from InitNew and Load.
  218.  *
  219.  * Return Value:
  220.  *  HRESULT         NOERROR or a general error value.
  221.  */
  222. STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage
  223.     , BOOL fSameAsLoad)
  224.     {
  225.     POLYLINEDATA    pl;
  226.     ULONG           cb;
  227.     LPSTREAM        pIStream;
  228.     HRESULT         hr;
  229.     //Have to come here from scribble state.
  230.     if (PSSTATE_SCRIBBLE!=m_psState)
  231.         return ResultFromScode(E_UNEXPECTED);
  232.     //Must have an IStorage if we're not in SameAsLoad
  233.     if (NULL==pIStorage && !fSameAsLoad)
  234.         return ResultFromScode(E_POINTER);
  235.     /*
  236.      * If we're saving to a new storage, create a new stream.
  237.      * If fSameAsLoad it TRUE, then we write to the
  238.      * stream we already allocated.  We should NOT depends on
  239.      * pIStorage with fSameAsLoad is TRUE.
  240.      */
  241.     if (fSameAsLoad)
  242.         {
  243.         LARGE_INTEGER   li;
  244.         /*
  245.          * Use pre-allocated streams to avoid failures due
  246.          * to low-memory conditions.  Be sure to reset the
  247.          * stream pointer if you used this stream before!!
  248.          */
  249.         pIStream=m_pObj->m_pIStream;
  250.         LISet32(li, 0);
  251.         pIStream->Seek(li, STREAM_SEEK_SET, NULL);
  252.         //This matches the Release below.
  253.         pIStream->AddRef();
  254.         }
  255.     else
  256.         {
  257.         hr=pIStorage->CreateStream(SZSTREAM, STGM_DIRECT
  258.             | STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE
  259.             , 0, 0, &pIStream);
  260.         if (FAILED(hr))
  261.             return hr;
  262.         //Only do this with new storages.
  263.         WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
  264.             , (*m_pObj->m_pST)[IDS_USERTYPE]);
  265.         }
  266.     //DataGet now internal on CPolyline
  267.     m_pObj->DataGet(&pl);
  268.     hr=pIStream->Write(&pl, CBPOLYLINEDATA, &cb);
  269.     pIStream->Release();
  270.     if (FAILED(hr) || CBPOLYLINEDATA!=cb)
  271.         return ResultFromScode(STG_E_WRITEFAULT);
  272.     m_psState=PSSTATE_ZOMBIE;
  273.     //CHAPTER19MOD
  274.     //We also need to tell the cache to save cached graphics
  275.     m_pObj->m_pDefIPersistStorage->Save(pIStorage, fSameAsLoad);
  276.     //End CHAPTER19MOD
  277.     return NOERROR;
  278.     }
  279. /*
  280.  * CImpIPersistStorage::SaveCompleted
  281.  *
  282.  * Purpose:
  283.  *  Notifies the object that the storage in pIStorage has been
  284.  *  completely saved now.  This is called when the user of this
  285.  *  object wants to save us in a completely new storage, and if
  286.  *  we normally hang on to the storage we have to reinitialize
  287.  *  ourselves here for this new one that is now complete.
  288.  *
  289.  * Parameters:
  290.  *  pIStorage       LPSTORAGE of the new storage in which we live.
  291.  *
  292.  * Return Value:
  293.  *  HRESULT         NOERROR or a general error value.
  294.  */
  295. STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
  296.     {
  297.     HRESULT     hr;
  298.     LPSTREAM    pIStream;
  299.     //Must be called in no-scribble or hands-off state
  300.     if (!(PSSTATE_ZOMBIE==m_psState || PSSTATE_HANDSOFF==m_psState))
  301.         return ResultFromScode(E_UNEXPECTED);
  302.     //If we're coming from Hands-Off, we'd better get a storage
  303.     if (NULL==pIStorage && PSSTATE_HANDSOFF==m_psState)
  304.         return ResultFromScode(E_UNEXPECTED);
  305.     /*
  306.      * If pIStorage is NULL, then we don't need to do anything
  307.      * since we already have all the pointers we need for Save.
  308.      * Otherwise we have to release any held pointers and
  309.      * reinitialize them from pIStorage.
  310.      */
  311.     if (NULL!=pIStorage)
  312.         {
  313.         hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT
  314.             | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0
  315.             , &pIStream);
  316.         if (FAILED(hr))
  317.             return hr;
  318.         if (NULL!=m_pObj->m_pIStream)
  319.             m_pObj->m_pIStream->Release();
  320.         m_pObj->m_pIStream=pIStream;
  321.         if (NULL!=m_pObj->m_pIStorage)
  322.             m_pObj->m_pIStorage->Release();
  323.         m_pObj->m_pIStorage=pIStorage;
  324.         m_pObj->m_pIStorage->AddRef();
  325.         }
  326.     //Change state back to scribble.
  327.     m_psState=PSSTATE_SCRIBBLE;
  328.     //CHAPTER19MOD
  329.     m_pObj->m_pDefIPersistStorage->SaveCompleted(pIStorage);
  330.     //End CHAPTER19MOD
  331.     return NOERROR;
  332.     }
  333. /*
  334.  * CImpIPersistStorage::HandsOffStorage
  335.  *
  336.  * Purpose:
  337.  *  Instructs the object that another agent is interested in having
  338.  *  total access to the storage we might be hanging on to from
  339.  *  InitNew or SaveCompleted.  In this case we must release our hold
  340.  *  and await another call to SaveCompleted before we have a hold
  341.  *  again.  Therefore we cannot read or write after this call until
  342.  *  SaveCompleted.
  343.  *
  344.  *  Situations where this might happen arise in compound document
  345.  *  scenarios where this object might be in-place active but the
  346.  *  application wants to rename and commit the root storage.
  347.  *  Therefore we are asked to close our hold, let the container
  348.  *  party on the storage, then call us again later to tell us the
  349.  *  new storage we can hold.
  350.  *
  351.  * Parameters:
  352.  *  None
  353.  *
  354.  * Return Value:
  355.  *  HRESULT         NOERROR or a general error value.
  356.  */
  357. STDMETHODIMP CImpIPersistStorage::HandsOffStorage(void)
  358.     {
  359.     /*
  360.      * Must come from scribble or no-scribble.  A repeated call
  361.      * to HandsOffStorage is an unexpected error (bug in client).
  362.      */
  363.     if (PSSTATE_UNINIT==m_psState || PSSTATE_HANDSOFF==m_psState)
  364.         return ResultFromScode(E_UNEXPECTED);
  365.     //Release held pointers
  366.     if (NULL!=m_pObj->m_pIStream)
  367.         {
  368.         m_pObj->m_pIStream->Release();
  369.         m_pObj->m_pIStream=NULL;
  370.         }
  371.     if (NULL!=m_pObj->m_pIStorage)
  372.         {
  373.         m_pObj->m_pIStorage->Release();
  374.         m_pObj->m_pIStorage=NULL;
  375.         }
  376.     m_psState=PSSTATE_HANDSOFF;
  377.     //CHAPTER19MOD
  378.     m_pObj->m_pDefIPersistStorage->HandsOffStorage();
  379.     //End CHAPTER19MOD
  380.     return NOERROR;
  381.     }