home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap19 / hcosmo / iperstor.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  8.7 KB  |  350 lines

  1. /*
  2.  * IPERSTOR.CPP
  3.  * Cosmo Handler Chapter 19
  4.  *
  5.  * Implementation of the IPersistStorage interface that we expose on
  6.  * the Figure 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.  
  15.  
  16. #include "hcosmo.h"
  17.  
  18.  
  19. /*
  20.  * CImpIPersistStorage:CImpIPersistStorage
  21.  * CImpIPersistStorage::~CImpIPersistStorage
  22.  *
  23.  * Constructor Parameters:
  24.  *  pObj            PCFigure pointing to the object we live in.
  25.  *  pUnkOuter       LPUNKNOWN of the controlling unknown.
  26.  */
  27.  
  28. CImpIPersistStorage::CImpIPersistStorage(PCFigure pObj
  29.     , LPUNKNOWN pUnkOuter)
  30.     {
  31.     m_cRef=0;
  32.     m_pObj=pObj;
  33.     m_pUnkOuter=pUnkOuter;
  34.     m_psState=PSSTATE_UNINIT;
  35.  
  36.     m_fConvert=FALSE;
  37.     return;
  38.     }
  39.  
  40.  
  41. CImpIPersistStorage::~CImpIPersistStorage(void)
  42.     {
  43.     return;
  44.     }
  45.  
  46.  
  47.  
  48.  
  49. /*
  50.  * CImpIPersistStorage::QueryInterface
  51.  * CImpIPersistStorage::AddRef
  52.  * CImpIPersistStorage::Release
  53.  */
  54.  
  55. STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid
  56.     , PPVOID ppv)
  57.     {
  58.     return m_pUnkOuter->QueryInterface(riid, ppv);
  59.     }
  60.  
  61. STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
  62.     {
  63.     ++m_cRef;
  64.     return m_pUnkOuter->AddRef();
  65.     }
  66.  
  67. STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
  68.     {
  69.     --m_cRef;
  70.     return m_pUnkOuter->Release();
  71.     }
  72.  
  73.  
  74.  
  75.  
  76.  
  77. /*
  78.  * CImpIPersistStorage::GetClassID
  79.  *
  80.  * Purpose:
  81.  *  Returns the CLSID of the object represented by this interface.
  82.  */
  83.  
  84. STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
  85.     {
  86.     if (PSSTATE_UNINIT==m_psState)
  87.         return ResultFromScode(E_UNEXPECTED);
  88.  
  89.     *pClsID=m_pObj->m_clsID;
  90.     return NOERROR;
  91.     }
  92.  
  93.  
  94.  
  95.  
  96. /*
  97.  * CImpIPersistStorage::IsDirty
  98.  *
  99.  * Purpose:
  100.  *  Tells the caller if we have made changes to this object since
  101.  *  it was loaded or initialized new.
  102.  */
  103.  
  104. STDMETHODIMP CImpIPersistStorage::IsDirty(void)
  105.     {
  106.     if (PSSTATE_UNINIT==m_psState)
  107.         return ResultFromScode(E_UNEXPECTED);
  108.  
  109.     /*
  110.      * Since we don't edit, we have no idea if this data is dirty.
  111.      * Delegate to the default handler in case it wants to ask the
  112.      * server.
  113.      */
  114.     return m_pObj->m_pDefIPersistStorage->IsDirty();
  115.     }
  116.  
  117.  
  118.  
  119.  
  120.  
  121. /*
  122.  * CImpIPersistStorage::InitNew
  123.  *
  124.  * Purpose:
  125.  *  Provides the object with the IStorage they hold on to while
  126.  *  they are running.  Since we don't create data in the handler,
  127.  *  there it nothing to write here.  We only need to initialize
  128.  *  out internal state.  This function is only be called once in
  129.  *  the object's lifetime in lieu of Load.
  130.  */
  131.  
  132. STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
  133.     {
  134.     if (PSSTATE_UNINIT!=m_psState)
  135.         return ResultFromScode(E_UNEXPECTED);
  136.  
  137.     if (NULL==pIStorage)
  138.         return ResultFromScode(E_POINTER);
  139.  
  140.     //Good time to initilize our data
  141.     m_pObj->m_pl.wVerMaj=VERSIONMAJOR;
  142.     m_pObj->m_pl.wVerMin=VERSIONMINOR;
  143.     m_pObj->m_pl.cPoints=0;
  144.     m_pObj->m_pl.rgbBackground=GetSysColor(COLOR_WINDOW);
  145.     m_pObj->m_pl.rgbLine=GetSysColor(COLOR_WINDOWTEXT);
  146.     m_pObj->m_pl.iLineStyle=PS_SOLID;
  147.  
  148.     //Make sure these aren't filled with trash.
  149.     memcpy(&m_pObj->m_plContent,   &m_pObj->m_pl, CBPOLYLINEDATA);
  150.     memcpy(&m_pObj->m_plThumbnail, &m_pObj->m_pl, CBPOLYLINEDATA);
  151.  
  152.     m_pObj->m_pDefIPersistStorage->InitNew(pIStorage);
  153.  
  154.     /*
  155.      * This is just for state validation in other calls.  As
  156.      * a handler we never actually 'scribble.'
  157.      */
  158.     m_psState=PSSTATE_SCRIBBLE;
  159.     return NOERROR;
  160.     }
  161.  
  162.  
  163.  
  164.  
  165.  
  166. /*
  167.  * CImpIPersistStorage::Load
  168.  *
  169.  * Purpose:
  170.  *  Instructs the object to load itself from a previously saved
  171.  *  IStorage that was handled by Save in another object lifetime.
  172.  *  This function will only be called once in the object's lifetime
  173.  *  in lieu of InitNew.
  174.  */
  175.  
  176. STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
  177.     {
  178.     POLYLINEDATA    pl;
  179.     ULONG           cb;
  180.     LPSTREAM        pIStream;
  181.     HRESULT         hr;
  182.  
  183.     if (PSSTATE_UNINIT!=m_psState)
  184.         return ResultFromScode(E_UNEXPECTED);
  185.  
  186.     if (NULL==pIStorage)
  187.         return ResultFromScode(E_POINTER);
  188.  
  189.     //This tells us if we're coming from another class storage.
  190.     m_fConvert=(NOERROR==GetConvertStg(pIStorage));
  191.  
  192.     //This is the type of storage we're really messing with in Treat As
  193.     ReadClassStg(pIStorage, &m_pObj->m_clsID);
  194.  
  195.     //Open the CONTENTS stream
  196.     hr=pIStorage->OpenStream(SZSTREAM, 0, STGM_DIRECT | STGM_READ
  197.         | STGM_SHARE_EXCLUSIVE, 0, &pIStream);
  198.  
  199.     if (FAILED(hr))
  200.         return ResultFromScode(STG_E_READFAULT);
  201.  
  202.     //Read all the data into the POLYLINEDATA structure.
  203.     hr=pIStream->Read(&pl, CBPOLYLINEDATA, &cb);
  204.     pIStream->Release();
  205.  
  206.     if (CBPOLYLINEDATA!=cb)
  207.         return ResultFromScode(STG_E_READFAULT);
  208.  
  209.     //Copy into the actual object now.
  210.     memcpy(&m_pObj->m_pl, &pl, CBPOLYLINEDATA);
  211.  
  212.     m_pObj->m_pDefIPersistStorage->Load(pIStorage);
  213.  
  214.     //As with InitNew, this is just for validating other calls
  215.     m_psState=PSSTATE_SCRIBBLE;
  216.     return NOERROR;
  217.     }
  218.  
  219.  
  220.  
  221.  
  222.  
  223. /*
  224.  * CImpIPersistStorage::Save
  225.  *
  226.  * Purpose:
  227.  *  Saves the data for this object to an IStorage.
  228.  */
  229.  
  230. STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage
  231.     , BOOL fSameAsLoad)
  232.     {
  233.     ULONG           cb;
  234.     HRESULT         hr;
  235.     LPSTREAM        pIStream;
  236.  
  237.     //Have to come here from scribble state.
  238.     if (PSSTATE_SCRIBBLE!=m_psState)
  239.         return ResultFromScode(E_UNEXPECTED);
  240.  
  241.     //Must have an IStorage if we're not in SameAsLoad
  242.     if (NULL==pIStorage && !fSameAsLoad)
  243.         return ResultFromScode(E_POINTER);
  244.  
  245.     /*
  246.      * If the server is running, don't do the save ourselves since
  247.      * we'd end up writing the storage twice with possible conflicts.
  248.      */
  249.     if (OleIsRunning(m_pObj->m_pDefIOleObject))
  250.         {
  251.         hr=m_pObj->m_pDefIPersistStorage->Save(pIStorage
  252.             , fSameAsLoad);
  253.  
  254.         if (SUCCEEDED(hr))
  255.             m_psState=PSSTATE_ZOMBIE;
  256.  
  257.         return hr;
  258.         }
  259.  
  260.     /*
  261.      * Since we don't have any data we modify in the handler,
  262.      * we have nothing to do for same-as-load cases.  The only
  263.      * case we have to handle is writing to a new storage.
  264.      */
  265.     if (!fSameAsLoad)
  266.         {
  267.         /*
  268.          * This code facilitates making copies of an object into
  269.          * a new storage during a container Save As.
  270.          */
  271.  
  272.         hr=pIStorage->CreateStream(SZSTREAM, STGM_DIRECT | STGM_CREATE
  273.             | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pIStream);
  274.  
  275.         if (FAILED(hr))
  276.             return hr;
  277.  
  278.         WriteClassStg(pIStorage, CLSID_CosmoFigure);
  279.         WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
  280.             , TEXT("Polyline Figure"));
  281.  
  282.         hr=pIStream->Write(&m_pObj->m_pl, CBPOLYLINEDATA, &cb);
  283.         pIStream->Release();
  284.  
  285.         if (FAILED(hr) || CBPOLYLINEDATA!=cb)
  286.             return ResultFromScode(STG_E_WRITEFAULT);
  287.         }
  288.  
  289.     //Clear the convert bit if it was set
  290.     if (m_fConvert)
  291.         {
  292.         WriteFmtUserTypeStg(pIStorage, m_pObj->m_cf
  293.             , TEXT("Polyline Figure"));
  294.  
  295.         SetConvertStg(pIStorage, FALSE);
  296.         m_fConvert=FALSE;
  297.         }
  298.  
  299.     m_psState=PSSTATE_ZOMBIE;
  300.     m_pObj->m_pDefIPersistStorage->Save(pIStorage, fSameAsLoad);
  301.     return NOERROR;
  302.     }
  303.  
  304.  
  305.  
  306.  
  307. /*
  308.  * CImpIPersistStorage::SaveCompleted
  309.  * CImpIPersistStorage::HandsOffStorage
  310.  *
  311.  * Purpose:
  312.  *  Pass throughs with typical management of our pointers.
  313.  */
  314.  
  315. STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
  316.     {
  317.     //Must be called in no-scribble or hands-off state
  318.     if (!(PSSTATE_ZOMBIE==m_psState || PSSTATE_HANDSOFF==m_psState))
  319.         return ResultFromScode(E_UNEXPECTED);
  320.  
  321.     //If we're coming from Hands-Off, we'd better get a storage
  322.     if (NULL==pIStorage && PSSTATE_HANDSOFF==m_psState)
  323.         return ResultFromScode(E_UNEXPECTED);
  324.  
  325.     /*
  326.      * Since this handler modifies nothing, it saves no pointers
  327.      * which it would have to release here.  Nothing to do.
  328.      */
  329.  
  330.     m_pObj->m_pDefIPersistStorage->SaveCompleted(pIStorage);
  331.     m_psState=PSSTATE_SCRIBBLE;
  332.     return NOERROR;
  333.     }
  334.  
  335.  
  336. STDMETHODIMP CImpIPersistStorage::HandsOffStorage(void)
  337.     {
  338.     if (PSSTATE_UNINIT==m_psState || PSSTATE_HANDSOFF==m_psState)
  339.         return ResultFromScode(E_UNEXPECTED);
  340.  
  341.     /*
  342.      * Since this handler modifies nothing, it saves no pointers
  343.      * which it would have to release here.  Nothing to do.
  344.      */
  345.  
  346.     m_pObj->m_pDefIPersistStorage->HandsOffStorage();
  347.     m_psState=PSSTATE_HANDSOFF;
  348.     return NOERROR;
  349.     }
  350.