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 / chap21 / cosmo / ioleobj.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  18.8 KB  |  826 lines

  1. /*
  2.  * IOLEOBJ.CPP
  3.  * Cosmo Chapter 21
  4.  *
  5.  * Implementation of the IOleObject interface for Polyline.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "cosmo.h"
  16.  
  17.  
  18. /*
  19.  * CImpIOleObject::CImpIOleObject
  20.  * CImpIOleObject::~CImpIOleObject
  21.  *
  22.  * Parameters (Constructor):
  23.  *  pObj            PCFigure of the object we're in.
  24.  *  pUnkOuter       LPUNKNOWN to which we delegate.
  25.  */
  26.  
  27. CImpIOleObject::CImpIOleObject(PCFigure pObj, LPUNKNOWN pUnkOuter)
  28.     {
  29.     m_cRef=0;
  30.     m_pObj=pObj;
  31.     m_pUnkOuter=pUnkOuter;
  32.     return;
  33.     }
  34.  
  35. CImpIOleObject::~CImpIOleObject(void)
  36.     {
  37.     return;
  38.     }
  39.  
  40.  
  41.  
  42. /*
  43.  * CImpIOleObject::QueryInterface
  44.  * CImpIOleObject::AddRef
  45.  * CImpIOleObject::Release
  46.  */
  47.  
  48. STDMETHODIMP CImpIOleObject::QueryInterface(REFIID riid, PPVOID ppv)
  49.     {
  50.     return m_pUnkOuter->QueryInterface(riid, ppv);
  51.     }
  52.  
  53. STDMETHODIMP_(ULONG) CImpIOleObject::AddRef(void)
  54.     {
  55.     ++m_cRef;
  56.     return m_pUnkOuter->AddRef();
  57.     }
  58.  
  59. STDMETHODIMP_(ULONG) CImpIOleObject::Release(void)
  60.     {
  61.     --m_cRef;
  62.     return m_pUnkOuter->Release();
  63.     }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. /*
  70.  * CImpIOleObject::SetClientSite
  71.  *
  72.  * Purpose:
  73.  *  Provides the object with a pointer to the IOleClient site
  74.  *  representing the container in which this object resides.
  75.  *
  76.  * Parameters:
  77.  *  pIOleClientSite LPOLECLIENTSITE to the container's interface.
  78.  *
  79.  * Return Value:
  80.  *  HRESULT         NOERROR
  81.  */
  82.  
  83. STDMETHODIMP CImpIOleObject::SetClientSite
  84.     (LPOLECLIENTSITE pIOleClientSite)
  85.     {
  86.     if (NULL!=m_pObj->m_pIOleClientSite)
  87.         m_pObj->m_pIOleClientSite->Release();
  88.  
  89.     m_pObj->m_pIOleClientSite=pIOleClientSite;
  90.     m_pObj->m_pIOleClientSite->AddRef();
  91.     return NOERROR;
  92.     }
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CImpIOleObject::GetClientSite
  100.  *
  101.  * Purpose:
  102.  *  Asks the object for the client site provided in SetClientSite.
  103.  *  If you have not seen SetClientSite yet, return a NULL in
  104.  *  ppIOleClientSite.
  105.  *
  106.  * Parameters:
  107.  *  ppSite          LPOLECLIENTSITE * in which to store the
  108.  *                  pointer.
  109.  *
  110.  * Return Value:
  111.  *  HRESULT         NOERROR
  112.  */
  113.  
  114. STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE
  115.     *ppSite)
  116.     {
  117.     //Be sure to AddRef the new pointer you are giving away.
  118.     *ppSite=m_pObj->m_pIOleClientSite;
  119.     m_pObj->m_pIOleClientSite->AddRef();
  120.  
  121.     return NOERROR;
  122.     }
  123.  
  124.  
  125.  
  126.  
  127.  
  128. /*
  129.  * CImpIOleObject::SetHostNames
  130.  *
  131.  * Purpose:
  132.  *  Provides the object with names of the container application and
  133.  *  the object in the container to use in object user interface.
  134.  *
  135.  * Parameters:
  136.  *  pszApp          LPCOLESTR of the container application.
  137.  *  pszObj          LPCOLESTR of some name useful in window titles.
  138.  *
  139.  * Return Value:
  140.  *  HRESULT         NOERROR
  141.  */
  142.  
  143. STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR pszApp
  144.     , LPCOLESTR pszObj)
  145.     {
  146.     m_pObj->m_fEmbedded=TRUE;
  147.    #ifdef WIN32ANSI
  148.     char        szApp[80], szObj[80];
  149.  
  150.     szApp[0]=0;
  151.     szObj[0]=0;
  152.  
  153.     if (NULL!=pszApp)
  154.         {
  155.         WideCharToMultiByte(CP_ACP, 0, pszApp, -1, szApp, 80
  156.             , NULL, NULL);
  157.         }
  158.  
  159.     if (NULL!=pszObj)
  160.         {
  161.         WideCharToMultiByte(CP_ACP, 0, pszObj, -1, szObj, 80
  162.             , NULL, NULL);
  163.         }
  164.  
  165.     m_pObj->m_pFR->UpdateEmbeddingUI(TRUE, m_pObj->m_pDoc
  166.         , szApp, szObj);
  167.    #else
  168.     m_pObj->m_pFR->UpdateEmbeddingUI(TRUE, m_pObj->m_pDoc
  169.         , pszApp, pszObj);
  170.    #endif
  171.     return NOERROR;
  172.     }
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. /*
  180.  * CImpIOleObject::Close
  181.  *
  182.  * Purpose:
  183.  *  Forces the object to close down its user interface and unload.
  184.  *
  185.  * Parameters:
  186.  *  dwSaveOption    DWORD describing the circumstances under which
  187.  *                  the object is being saved and closed.
  188.  *
  189.  * Return Value:
  190.  *  HRESULT         NOERROR or a general error value.
  191.  */
  192.  
  193. STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption)
  194.     {
  195.     HWND        hWnd;
  196.     BOOL        fSave=FALSE;
  197.  
  198.     hWnd=m_pObj->m_pDoc->Window();
  199.  
  200.     //If object is dirty and we're asked to save, save it and close.
  201.     if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->FIsDirty())
  202.         fSave=TRUE;
  203.  
  204.     /*
  205.      * If asked to prompt, only do so if dirty, then if we get a
  206.      * YES, save as usual and close.  On NO, just close.  On
  207.      * CANCEL return OLE_E_PROMPTSAVECANCELLED.
  208.      */
  209.     if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->FIsDirty())
  210.         {
  211.         UINT        uRet;
  212.  
  213.         uRet=MessageBox(hWnd, (*m_pObj->m_pST)[IDS_CLOSECAPTION]
  214.             , (*m_pObj->m_pST)[IDS_CLOSEPROMPT], MB_YESNOCANCEL);
  215.  
  216.         if (IDCANCEL==uRet)
  217.             return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
  218.  
  219.         if (IDYES==uRet)
  220.             fSave=TRUE;
  221.         }
  222.  
  223.     if (fSave)
  224.         {
  225.         m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT);
  226.         m_pObj->SendAdvise(OBJECTCODE_SAVED);
  227.         }
  228.  
  229.     //We get directly here on OLECLOSE_NOSAVE.
  230.     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  231.     return NOERROR;
  232.     }
  233.  
  234.  
  235.  
  236.  
  237.  
  238. /*
  239.  * CImpIOleObject::SetMoniker
  240.  *
  241.  * Purpose:
  242.  *  Informs the object of its moniker or its container's moniker
  243.  *  depending on dwWhich.
  244.  *
  245.  * Parameters:
  246.  *  dwWhich         DWORD describing whether the moniker is the
  247.  *                  object's or the container's.
  248.  *  pmk             LPMONIKER with the name.
  249.  *
  250.  * Return Value:
  251.  *  HRESULT         NOERROR or a general error value.
  252.  */
  253.  
  254. STDMETHODIMP CImpIOleObject::SetMoniker(DWORD dwWhich
  255.     , LPMONIKER pmk)
  256.     {
  257.     //CHAPTER21MOD
  258.     LPMONIKER       pmkFull;
  259.     HRESULT         hr=ResultFromScode(E_FAIL);
  260.  
  261.     /*
  262.      * For an embedded object we might be living in a container that
  263.      * has given us away as a link.  This is our indication to
  264.      * register the full moniker for this object that we obtain from
  265.      * IOleClientSite::GetMoniker(OLEWHICHMK_FULL).
  266.      */
  267.  
  268.     if (NULL!=m_pObj->m_pIOleClientSite)
  269.         {
  270.         hr=m_pObj->m_pIOleClientSite->GetMoniker
  271.             (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  272.             , &pmkFull);
  273.         }
  274.  
  275.     if (SUCCEEDED(hr))
  276.         {
  277.         /*
  278.          * If this moniker is already running then we don't
  279.          * need to revoke and re-register the same thing again.
  280.          */
  281.         if (NOERROR==pmkFull->IsRunning(NULL, NULL, NULL))
  282.             {
  283.             pmkFull->Release();
  284.             return NOERROR;
  285.             }
  286.  
  287.         //This will revoke the old one if m_dwRegROT is nonzero.
  288.         INOLE_RegisterAsRunning(m_pObj, pmkFull
  289.             , 0, &m_pObj->m_dwRegROT);
  290.  
  291.         //Inform clients of the new moniker
  292.         if (NULL!=m_pObj->m_pIOleAdviseHolder)
  293.             m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
  294.  
  295.         pmkFull->Release();
  296.         }
  297.  
  298.     return hr;
  299.     //End CHAPTER21MOD
  300.     }
  301.  
  302.  
  303.  
  304.  
  305.  
  306. /*
  307.  * CImpIOleObject::GetMoniker
  308.  *
  309.  * Purpose:
  310.  *  Asks the object for a moniker that can later be used to
  311.  *  reconnect to it.
  312.  *
  313.  * Parameters:
  314.  *  dwAssign        DWORD determining how to assign the moniker to
  315.  *                  to the object.
  316.  *  dwWhich         DWORD describing which moniker the caller wants.
  317.  *  ppmk            LPMONIKER * into which to store the moniker.
  318.  *
  319.  * Return Value:
  320.  *  HRESULT         NOERROR or a general error value.
  321.  */
  322.  
  323. STDMETHODIMP CImpIOleObject::GetMoniker(DWORD dwAssign
  324.     , DWORD dwWhich, LPMONIKER *ppmk)
  325.     {
  326.     //CHAPTER21MOD
  327.     HRESULT         hr=ResultFromScode(E_FAIL);
  328.  
  329.     *ppmk=NULL;
  330.  
  331.     /*
  332.      * When we support linking we either return our file moniker if
  333.      * we're linked, or out full moniker from the container if we're
  334.      * embedded.
  335.      */
  336.  
  337.     if (NULL!=m_pObj->m_pMoniker)
  338.         {
  339.         *ppmk=m_pObj->m_pMoniker;       //Document file moniker
  340.         m_pObj->m_pMoniker->AddRef();
  341.         }
  342.     else
  343.         {
  344.         //Get the full container:object moniker if we're embedded
  345.         if (NULL!=m_pObj->m_pIOleClientSite)
  346.             {
  347.             hr=m_pObj->m_pIOleClientSite->GetMoniker
  348.                 (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  349.                 , ppmk);
  350.             }
  351.         }
  352.  
  353.     return (NULL!=*ppmk) ? NOERROR : hr;
  354.     //End CHAPTER21MOD
  355.     }
  356.  
  357.  
  358.  
  359.  
  360.  
  361. /*
  362.  * CImpIOleObject::InitFromData
  363.  *
  364.  * Purpose:
  365.  *  Initializes the object from the contents of a data object.
  366.  *
  367.  * Parameters:
  368.  *  pIDataObject    LPDATAOBJECT containing the data.
  369.  *  fCreation       BOOL indicating if this is part of a new
  370.  *                  creation. If FALSE, the container is trying
  371.  *                  to paste here.
  372.  *  dwReserved      DWORD reserved.
  373.  *
  374.  * Return Value:
  375.  *  HRESULT         NOERROR or a general error value.
  376.  */
  377.  
  378. STDMETHODIMP CImpIOleObject::InitFromData(LPDATAOBJECT pIDataObject
  379.     , BOOL fCreation, DWORD dwReserved)
  380.     {
  381.     BOOL    fRet;
  382.  
  383.     /*
  384.      * If we get a data object here, try to paste from it.  If
  385.      * you've written clipboard code already, this is a snap.
  386.      * We don't really care about fCreation or not since pasting
  387.      * in us blasts away whatever is already here.
  388.      */
  389.     fRet=m_pObj->m_pDoc->PasteFromData(pIDataObject);
  390.     return fRet ? NOERROR : ResultFromScode(E_FAIL);
  391.     }
  392.  
  393.  
  394.  
  395.  
  396.  
  397. /*
  398.  * CImpIOleObject::GetClipboardData
  399.  *
  400.  * Purpose:
  401.  *  Returns an IDataObject pointer to the caller representing what
  402.  *  would be on the clipboard if the server did an Edit/Copy using
  403.  *  OleSetClipboard.
  404.  *
  405.  * Parameters:
  406.  *  dwReserved      DWORD reserved.
  407.  *  ppIDataObj      LPDATAOBJECT * into which to store the
  408.  *                  pointer.
  409.  *
  410.  * Return Value:
  411.  *  HRESULT         NOERROR or a general error value.
  412.  */
  413.  
  414. STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD dwReserved
  415.     , LPDATAOBJECT *ppIDataObj)
  416.     {
  417.     /*
  418.      * Again, if you have a function to create a data object for the
  419.      * clipboard, this is a simple implementation.  The one we have
  420.      * does all the compound document formats already.
  421.      */
  422.     *ppIDataObj=m_pObj->m_pDoc->TransferObjectCreate(FALSE);
  423.     return (NULL!=*ppIDataObj) ? NOERROR : ResultFromScode(E_FAIL);
  424.     }
  425.  
  426.  
  427.  
  428.  
  429.  
  430. /*
  431.  * CImpIOleObject::DoVerb
  432.  *
  433.  * Purpose:
  434.  *  Executes an object-defined action.
  435.  *
  436.  * Parameters:
  437.  *  iVerb           LONG index of the verb to execute.
  438.  *  pMSG            LPMSG describing the event causing the
  439.  *                  activation.
  440.  *  pActiveSite     LPOLECLIENTSITE to the site involved.
  441.  *  lIndex          LONG the piece on which execution is happening.
  442.  *  hWndParent      HWND of window in which the object can play
  443.  *                  in-place.
  444.  *  pRectPos        LPRECT of the object in hWndParent where the
  445.  *                  object can play in-place if desired.
  446.  *
  447.  * Return Value:
  448.  *  HRESULT         NOERROR or a general error value.
  449.  */
  450.  
  451. STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG pMSG
  452.     , LPOLECLIENTSITE pActiveSite, LONG lIndex, HWND hWndParent
  453.     , LPCRECT pRectPos)
  454.     {
  455.     HWND            hWnd, hWndT;
  456.  
  457.     //Find the upper most window
  458.     hWndT=GetParent(m_pObj->m_pDoc->Window());
  459.  
  460.     while (NULL!=hWndT)
  461.         {
  462.         hWnd=hWndT;
  463.         hWndT=GetParent(hWndT);
  464.         }
  465.  
  466.     switch (iVerb)
  467.         {
  468.         case OLEIVERB_HIDE:
  469.             ShowWindow(hWnd, SW_HIDE);
  470.             m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
  471.             break;
  472.  
  473.         case OLEIVERB_PRIMARY:
  474.         case OLEIVERB_OPEN:
  475.         case OLEIVERB_SHOW:
  476.             ShowWindow(hWnd, SW_SHOW);
  477.             SetForegroundWindow(hWnd);
  478.             SetFocus(hWnd);
  479.  
  480.             m_pObj->SendAdvise(OBJECTCODE_SHOWOBJECT);
  481.             m_pObj->SendAdvise(OBJECTCODE_SHOWWINDOW);
  482.             break;
  483.  
  484.         default:
  485.             return ResultFromScode(OLEOBJ_S_INVALIDVERB);
  486.         }
  487.  
  488.     return NOERROR;
  489.     }
  490.  
  491.  
  492.  
  493.  
  494.  
  495. /*
  496.  * CImpIOleObject::EnumVerbs
  497.  *
  498.  * Purpose:
  499.  *  Creates an enumerator that knows the object's verbs.  If you
  500.  *  need to change the verb list dynamically, then you'll need to
  501.  *  implement this, otherwise you can return OLE_S_USEREG.
  502.  *
  503.  * Parameters:
  504.  *  ppEnum          LPENUMOLEVERB * into which to return the
  505.  *                  enum.
  506.  *
  507.  * Return Value:
  508.  *  HRESULT         NOERROR or a general error value.
  509.  */
  510.  
  511. STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum)
  512.     {
  513.     //Trivial implementation if you fill the regDB.
  514.     return ResultFromScode(OLE_S_USEREG);
  515.     }
  516.  
  517.  
  518.  
  519.  
  520.  
  521. /*
  522.  * CImpIOleObject::Update
  523.  *
  524.  * Purpose:
  525.  *  Insures that the object is up to date.  This is mostly used for
  526.  *  caching but you must make sure that you recursively call all
  527.  *  nested objects you contain as well.
  528.  *
  529.  * Parameters:
  530.  *  None
  531.  *
  532.  * Return Value:
  533.  *  HRESULT         NOERROR or a general error value.
  534.  */
  535.  
  536. STDMETHODIMP CImpIOleObject::Update(void)
  537.     {
  538.     //We're always updated since we don't contain.
  539.     return NOERROR;
  540.     }
  541.  
  542.  
  543.  
  544.  
  545.  
  546. /*
  547.  * CImpIOleObject::IsUpToDate
  548.  *
  549.  * Purpose:
  550.  *  Returns if the object is currently up to date, which involves
  551.  *  asking all contained object inside this object if they are up
  552.  *  to date as well.
  553.  *
  554.  * Parameters:
  555.  *  None
  556.  *
  557.  * Return Value:
  558.  *  HRESULT         NOERROR if successful, S_FALSE if dirty.
  559.  */
  560.  
  561. STDMETHODIMP CImpIOleObject::IsUpToDate(void)
  562.     {
  563.     //We're always updated since we don't contain.
  564.     return NOERROR;
  565.     }
  566.  
  567.  
  568.  
  569.  
  570.  
  571. /*
  572.  * CImpIOleObject::GetUserClassID
  573.  *
  574.  * Purpose:
  575.  *  Used for linked objects, this returns the class ID of what end
  576.  *  users think they are editing.
  577.  *
  578.  * Parameters:
  579.  *  pClsID          LPCLSID in which to store the CLSID.
  580.  *
  581.  * Return Value:
  582.  *  HRESULT         NOERROR or a general error value.
  583.  */
  584.  
  585. STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID)
  586.     {
  587.     /*
  588.      * If you are not registered to handle data other than yourself,
  589.      * then you can just return your class ID here.  If you are
  590.      * registered as usable from Treat-As dialogs, then you need
  591.      * to return the CLSID of what you are really editing.
  592.      */
  593.  
  594.     *pClsID=m_pObj->m_clsID;
  595.     return NOERROR;
  596.     }
  597.  
  598.  
  599.  
  600.  
  601.  
  602. /*
  603.  * CImpIOleObject::GetUserType
  604.  *
  605.  * Purpose:
  606.  *  Determines the user-presentable name of the object.
  607.  *
  608.  * Parameters:
  609.  *  dwForm          DWORD describing which form of the string is
  610.  *                  desired.
  611.  *  pszType         LPOLESTR * into which to return the pointer to
  612.  *                  the type string.
  613.  *
  614.  * Return Value:
  615.  *  HRESULT         NOERROR or a general error value.
  616.  */
  617.  
  618. STDMETHODIMP CImpIOleObject::GetUserType(DWORD dwForm
  619.     , LPOLESTR *ppszType)
  620.     {
  621.     return ResultFromScode(OLE_S_USEREG);
  622.     }
  623.  
  624.  
  625.  
  626.  
  627.  
  628. /*
  629.  * CImpIOleObject::SetExtent
  630.  *
  631.  * Purpose:
  632.  *  Sets the size of the object in HIMETRIC units.
  633.  *
  634.  * Parameters:
  635.  *  dwAspect        DWORD of the aspect affected.
  636.  *  pszl            LPSIZEL containing the new size.
  637.  *
  638.  * Return Value:
  639.  *  HRESULT         NOERROR or a general error value.
  640.  */
  641.  
  642. STDMETHODIMP CImpIOleObject::SetExtent(DWORD dwAspect, LPSIZEL pszl)
  643.     {
  644.     RECT            rc;
  645.     SIZEL           szl;
  646.  
  647.     if (!(DVASPECT_CONTENT & dwAspect))
  648.         return ResultFromScode(E_FAIL);
  649.  
  650.     XformSizeInHimetricToPixels(NULL, pszl, &szl);
  651.  
  652.     //This resizes the window to match the container's size.
  653.     SetRect(&rc, 0, 0, (int)szl.cx, (int)szl.cy);
  654.     m_pObj->m_pPL->SizeSet(&rc, TRUE);
  655.  
  656.     return NOERROR;
  657.     }
  658.  
  659.  
  660.  
  661.  
  662.  
  663. /*
  664.  * CImpIOleObject::GetExtent
  665.  *
  666.  * Purpose:
  667.  *  Retrieves the size of the object in HIMETRIC units.
  668.  *
  669.  * Parameters:
  670.  *  dwAspect        DWORD of the aspect requested
  671.  *  pszl            LPSIZEL into which to store the size.
  672.  *
  673.  * Return Value:
  674.  *  HRESULT         NOERROR or a general error value.
  675.  */
  676.  
  677. STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl)
  678.     {
  679.     RECT            rc;
  680.     SIZEL           szl;
  681.  
  682.     if (!(DVASPECT_CONTENT & dwAspect))
  683.         return ResultFromScode(E_FAIL);
  684.  
  685.     m_pObj->m_pPL->RectGet(&rc);
  686.     szl.cx=rc.right-rc.left;
  687.     szl.cy=rc.bottom-rc.top;
  688.  
  689.     XformSizeInPixelsToHimetric(NULL, &szl, pszl);
  690.     return NOERROR;
  691.     }
  692.  
  693.  
  694.  
  695.  
  696.  
  697. /*
  698.  * CImpIOleObject::Advise
  699.  *
  700.  * Purpose:
  701.  *  Provides an IAdviseSink to the object for notifications.
  702.  *
  703.  * Parameters:
  704.  *  pIAdviseSink    LPADVISESINK to notify.
  705.  *  pdwConn         LPDWORD into which to store a connection key.
  706.  *
  707.  * Return Value:
  708.  *  HRESULT         NOERROR or a general error value.
  709.  */
  710.  
  711. STDMETHODIMP CImpIOleObject::Advise(LPADVISESINK pIAdviseSink
  712.     , LPDWORD pdwConn)
  713.     {
  714.     if (NULL==m_pObj->m_pIOleAdviseHolder)
  715.         {
  716.         HRESULT     hr;
  717.  
  718.         hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
  719.  
  720.         if (FAILED(hr))
  721.             return hr;
  722.         }
  723.  
  724.     return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink
  725.         , pdwConn);
  726.     }
  727.  
  728.  
  729.  
  730.  
  731.  
  732. /*
  733.  * CImpIOleObject::Unadvise
  734.  *
  735.  * Purpose:
  736.  *  Terminates a previous advise connection from Advise.
  737.  *
  738.  * Parameters:
  739.  *  dwConn          DWORD connection key from Advise.
  740.  *
  741.  * Return Value:
  742.  *  HRESULT         NOERROR or a general error value.
  743.  */
  744.  
  745. STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn)
  746.     {
  747.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  748.         return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
  749.  
  750.     return ResultFromScode(E_FAIL);
  751.     }
  752.  
  753.  
  754.  
  755.  
  756.  
  757. /*
  758.  * CImpIOleObject::EnumAdvise
  759.  *
  760.  * Purpose:
  761.  *  Creates and returns a enumeration of the advises on this object.
  762.  *
  763.  * Parameters:
  764.  *  ppEnum          LPENUMSTATDATA * in which to return the
  765.  *                  enumerator.
  766.  *
  767.  * Return Value:
  768.  *  HRESULT         NOERROR or a general error value.
  769.  */
  770.  
  771. STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum)
  772.     {
  773.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  774.         return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
  775.  
  776.     return ResultFromScode(E_FAIL);
  777.     }
  778.  
  779.  
  780.  
  781.  
  782.  
  783. /*
  784.  * CImpIOleObject::GetMiscStatus
  785.  *
  786.  * Purpose:
  787.  *  Returns a set of miscellaneous status flags for the object.
  788.  *
  789.  * Parameters:
  790.  *  dwAspect        DWORD of the aspect in question.
  791.  *  pdwStatus       LPDWORD in which to store the flags.
  792.  *
  793.  * Return Value:
  794.  *  HRESULT         NOERROR or a general error value.
  795.  */
  796.  
  797. STDMETHODIMP CImpIOleObject::GetMiscStatus(DWORD dwAspect
  798.     , LPDWORD pdwStatus)
  799.     {
  800.     return ResultFromScode(OLE_S_USEREG);
  801.     }
  802.  
  803.  
  804.  
  805.  
  806.  
  807. /*
  808.  * CImpIOleObject::SetColorScheme
  809.  *
  810.  * Purpose:
  811.  *  Provides the object with the color palette as recommended by
  812.  *  the container application that also knows the palettes of other
  813.  *  objects.  The object here is not required to use these colors.
  814.  *
  815.  * Parameters:
  816.  *  pLP             LPLOGPALETTE providing the colors.
  817.  *
  818.  * Return Value:
  819.  *  HRESULT         NOERROR or a general error value.
  820.  */
  821.  
  822. STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE pLP)
  823.     {
  824.     return ResultFromScode(E_NOTIMPL);
  825.     }
  826.