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 / interfac / iperstor.cpp < prev    next >
C/C++ Source or Header  |  1996-05-21  |  8KB  |  327 lines

  1. /*
  2.  * IPERSTOR.CPP
  3.  *
  4.  * Template IPersistStorage interface implementation.
  5.  *
  6.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  7.  *
  8.  * Kraig Brockschmidt, Microsoft
  9.  * Internet  :  kraigb@microsoft.com
  10.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  11.  */
  12.  
  13.  
  14. #include "iperstor.h"
  15.  
  16.  
  17. /*
  18.  * CImpIPersistStorage:CImpIPersistStorage
  19.  * CImpIPersistStorage::~CImpIPersistStorage
  20.  *
  21.  * Constructor Parameters:
  22.  *  pObj            LPVOID pointing to the object we live in.
  23.  *  pUnkOuter       LPUNKNOWN of the controlling unknown.
  24.  */
  25.  
  26. CImpIPersistStorage::CImpIPersistStorage(LPVOID pObj
  27.     , LPUNKNOWN pUnkOuter)
  28.     {
  29.     m_cRef=0;
  30.     m_pObj=pObj;
  31.     m_pUnkOuter=pUnkOuter;
  32.     m_psState=PSSTATE_UNINIT;
  33.     return;
  34.     }
  35.  
  36. CImpIPersistStorage::~CImpIPersistStorage(void)
  37.     {
  38.     return;
  39.     }
  40.  
  41.  
  42.  
  43. /*
  44.  * CImpIPersistStorage::QueryInterface
  45.  * CImpIPersistStorage::AddRef
  46.  * CImpIPersistStorage::Release
  47.  *
  48.  * Purpose:
  49.  *  Delegating IUnknown members for CImpIPersistStorage.
  50.  */
  51.  
  52. STDMETHODIMP CImpIPersistStorage::QueryInterface(REFIID riid
  53.     , LPVOID *ppv)
  54.     {
  55.     return m_pUnkOuter->QueryInterface(riid, ppv);
  56.     }
  57.  
  58. STDMETHODIMP_(ULONG) CImpIPersistStorage::AddRef(void)
  59.     {
  60.     ++m_cRef;
  61.     return m_pUnkOuter->AddRef();
  62.     }
  63.  
  64. STDMETHODIMP_(ULONG) CImpIPersistStorage::Release(void)
  65.     {
  66.     --m_cRef;
  67.     return m_pUnkOuter->Release();
  68.     }
  69.  
  70.  
  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.  * Parameters:
  84.  *  pClsID          LPCLSID in which to store our CLSID.
  85.  */
  86.  
  87. STDMETHODIMP CImpIPersistStorage::GetClassID(LPCLSID pClsID)
  88.     {
  89.     if (PSSTATE_UNINIT==m_psState)
  90.         return ResultFromScode(E_UNEXPECTED);
  91.  
  92.     return NOERROR;
  93.     }
  94.  
  95.  
  96.  
  97.  
  98.  
  99. /*
  100.  * CImpIPersistStorage::IsDirty
  101.  *
  102.  * Purpose:
  103.  *  Tells the caller if we have made changes to this object since
  104.  *  it was loaded or initialized new.
  105.  *
  106.  * Parameters:
  107.  *  None
  108.  *
  109.  * Return Value:
  110.  *  HRESULT         Contains S_OK if we ARE dirty, S_FALSE if
  111.  *                  NOT dirty.
  112.  */
  113.  
  114. STDMETHODIMP CImpIPersistStorage::IsDirty(void)
  115.     {
  116.     if (PSSTATE_UNINIT==m_psState)
  117.         return ResultFromScode(E_UNEXPECTED);
  118.  
  119.     return ResultFromScode(S_FALSE);
  120.     }
  121.  
  122.  
  123.  
  124.  
  125.  
  126. /*
  127.  * CImpIPersistStorage::InitNew
  128.  *
  129.  * Purpose:
  130.  *  Provides the object with the IStorage to hold on to while the
  131.  *  object is running.  Here we initialize the structure of the
  132.  *  storage and AddRef it for incremental access. This function will
  133.  *  only be called once in the object's lifetime in lieu of Load.
  134.  *
  135.  * Parameters:
  136.  *  pIStorage       LPSTORAGE for the object.
  137.  */
  138.  
  139. STDMETHODIMP CImpIPersistStorage::InitNew(LPSTORAGE pIStorage)
  140.     {
  141.     if (PSSTATE_UNINIT!=m_psState)
  142.         return ResultFromScode(E_UNEXPECTED);
  143.  
  144.     m_psState=PSSTATE_SCRIBBLE;
  145.  
  146.     //Hold on to pIStorage for Save(..., TRUE)
  147.     return NOERROR;
  148.     }
  149.  
  150.  
  151.  
  152.  
  153.  
  154. /*
  155.  * CImpIPersistStorage::Load
  156.  *
  157.  * Purpose:
  158.  *  Instructs the object to load itself from a previously saved
  159.  *  IStorage that was handled by Save in another object lifetime.
  160.  *  This function will only be called once in the object's lifetime
  161.  *  in lieu of InitNew. The object should hold on to pIStorage here
  162.  *  for incremental access and low-memory saves in Save.
  163.  *
  164.  * Parameters:
  165.  *  pIStorage       LPSTORAGE from which to load.
  166.  */
  167.  
  168. STDMETHODIMP CImpIPersistStorage::Load(LPSTORAGE pIStorage)
  169.     {
  170.     if (PSSTATE_UNINIT!=m_psState)
  171.         return ResultFromScode(E_UNEXPECTED);
  172.  
  173.     m_psState=PSSTATE_SCRIBBLE;
  174.  
  175.     //Hold on to pIStorage for Save(..., TRUE)
  176.     return NOERROR;
  177.     }
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * CImpIPersistStorage::Save
  188.  *
  189.  * Purpose:
  190.  *  Saves the data for this object to an IStorage which may
  191.  *  or may not be the same as the one previously passed to
  192.  *  Load, indicated with fSameAsLoad.  After this call we may
  193.  *  not write into the storage again until SaveCompleted is
  194.  *  called, although we may still read.
  195.  *
  196.  * Parameters:
  197.  *  pIStorage       LPSTORAGE in which to save our data.
  198.  *  fSameAsLoad     BOOL indicating if this is the same pIStorage
  199.  *                  that was passed to Load.  If TRUE, then the
  200.  *                  object should write whatever it has *without
  201.  *                  *using any extra memory* as this may be a low
  202.  *                  memory save attempt.  That means that you must
  203.  *                  not try to open or create streams.  If FALSE
  204.  *                  you need to regenerate your whole storage
  205.  *                  structure, being sure to also release any
  206.  *                  pointers held from InitNew and Load.
  207.  */
  208.  
  209. STDMETHODIMP CImpIPersistStorage::Save(LPSTORAGE pIStorage
  210.     , BOOL fSameAsLoad)
  211.     {
  212.     //Have to come here from scribble state.
  213.     if (PSSTATE_SCRIBBLE!=m_psState)
  214.         return ResultFromScode(E_UNEXPECTED);
  215.  
  216.     /*
  217.      * Save your data to your open storages and streams if
  218.      * fSameAsLoad is FALSE, otherwise save to the new pIStorage
  219.      * but don't change your held pointers--you only do that in
  220.      * SaveCompleted if given a different pIStorage.
  221.      *
  222.      * Also, do not call pIStorage->Commit.  That's the caller's
  223.      * responsibility.
  224.      */
  225.  
  226.     m_psState=PSSTATE_ZOMBIE;
  227.  
  228.     //Clear your dirty flag.
  229.     return NOERROR;
  230.     }
  231.  
  232.  
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239. /*
  240.  * CImpIPersistStorage::SaveCompleted
  241.  *
  242.  * Purpose:
  243.  *  Notifies the object that the storage in pIStorage has been
  244.  *  completely saved now.  This is called when the user of this
  245.  *  object wants to save us in a completely new storage, and if
  246.  *  we normally hang on to the storage we have to reinitialize
  247.  *  ourselves here for this new one that is now complete.
  248.  *
  249.  * Parameters:
  250.  *  pIStorage       LPSTORAGE of the new storage in which we live.
  251.  */
  252.  
  253. STDMETHODIMP CImpIPersistStorage::SaveCompleted(LPSTORAGE pIStorage)
  254.     {
  255.     //Must be called in no-scribble or hands-off state
  256.     if (PSSTATE_ZOMBIE!=m_psState || PSSTATE_HANDSOFF!=m_psState)
  257.         return ResultFromScode(E_UNEXPECTED);
  258.  
  259.     //If we're coming from Hands-Off, we'd better get a storage
  260.     if (NULL==pIStorage && PSSTATE_HANDSOFF==m_psState)
  261.         return ResultFromScode(E_UNEXPECTED);
  262.  
  263.     /*
  264.      * If in Hands-Off state and pIStorage is non-NULL, then
  265.      * reopen storages and streams and hold the pointers,
  266.      * returning to scribble state.
  267.      *
  268.      * If in no-scribble state and pIStorage is non-NULL, then
  269.      * release currently held pointers and reopen pointers
  270.      * in pIStorage.
  271.      *
  272.      * If in no-scribble state and pIStorage is NULL, do not
  273.      * change your held pointers.
  274.      */
  275.  
  276.     //Return to scribble if there are no errors
  277.     m_psState=PSSTATE_SCRIBBLE;
  278.     return NOERROR;
  279.     }
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288. /*
  289.  * CImpIPersistStorage::HandsOffStorage
  290.  *
  291.  * Purpose:
  292.  *  Instructs the object that another agent is interested in having
  293.  *  total access to the storage we might be hanging on to from
  294.  *  InitNew or SaveCompleted.  In this case we must release our hold
  295.  *  and await another call to SaveCompleted before we have a hold
  296.  *  again.  Therefore we cannot read or write after this call until
  297.  *  SaveCompleted.
  298.  *
  299.  *  Situations where this might happen arise in compound document
  300.  *  scenarios where this object might be in-place active but the
  301.  *  application wants to rename and commit the root storage.
  302.  *  Therefore we are asked to close our hold, let the container
  303.  *  party on the storage, then call us again later to tell us the
  304.  *  new storage we can hold.
  305.  *
  306.  * Parameters:
  307.  *  None
  308.  */
  309.  
  310. STDMETHODIMP CImpIPersistStorage::HandsOffStorage(void)
  311.     {
  312.     /*
  313.      * Must come from scribble or no-scribble.  A repeated call
  314.      * to HandsOffStorage is an unexpected error (bug in client).
  315.      */
  316.     if (PSSTATE_UNINIT==m_psState || PSSTATE_HANDSOFF==m_psState)
  317.         return ResultFromScode(E_UNEXPECTED);
  318.  
  319.  
  320.     /*
  321.      * Release all held pointers regardless.
  322.      */
  323.  
  324.     m_psState=PSSTATE_HANDSOFF;
  325.     return NOERROR;
  326.     }
  327.