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 / chap23 / polyline / ioleobj.cpp < prev    next >
C/C++ Source or Header  |  1996-05-22  |  17KB  |  673 lines

  1. /*
  2.  * IOLEOBJ.CPP
  3.  * Polyline Component Chapter 23
  4.  *
  5.  * Implementation of the IOleObject interface for Polyline.  Some of
  6.  * these just pass through to the default handler which does default
  7.  * implementations.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15.  
  16.  
  17. #include "polyline.h"
  18.  
  19.  
  20. /*
  21.  * CImpIOleObject::CImpIOleObject
  22.  * CImpIOleObject::~CImpIOleObject
  23.  *
  24.  * Parameters (Constructor):
  25.  *  pObj            PCPolyline of the object we're in.
  26.  *  pUnkOuter       LPUNKNOWN to which we delegate.
  27.  */
  28.  
  29. CImpIOleObject::CImpIOleObject(PCPolyline pObj
  30.     , LPUNKNOWN pUnkOuter)
  31.     {
  32.     m_cRef=0;
  33.     m_pObj=pObj;
  34.     m_pUnkOuter=pUnkOuter;
  35.     return;
  36.     }
  37.  
  38. CImpIOleObject::~CImpIOleObject(void)
  39.     {
  40.     return;
  41.     }
  42.  
  43.  
  44.  
  45. /*
  46.  * CImpIOleObject::QueryInterface
  47.  * CImpIOleObject::AddRef
  48.  * CImpIOleObject::Release
  49.  *
  50.  * Purpose:
  51.  *  IUnknown members for CImpIOleObject object.
  52.  */
  53.  
  54. STDMETHODIMP CImpIOleObject::QueryInterface(REFIID riid, PPVOID ppv)
  55.     {
  56.     return m_pUnkOuter->QueryInterface(riid, ppv);
  57.     }
  58.  
  59.  
  60. STDMETHODIMP_(ULONG) CImpIOleObject::AddRef(void)
  61.     {
  62.     ++m_cRef;
  63.     return m_pUnkOuter->AddRef();
  64.     }
  65.  
  66. STDMETHODIMP_(ULONG) CImpIOleObject::Release(void)
  67.     {
  68.     --m_cRef;
  69.     return m_pUnkOuter->Release();
  70.     }
  71.  
  72.  
  73.  
  74.  
  75.  
  76. /*
  77.  * CImpIOleObject::SetClientSite
  78.  * CImpIOleObject::GetClientSite
  79.  *
  80.  * Purpose:
  81.  *  Manages the IOleClientSite pointer of our container.
  82.  */
  83.  
  84. STDMETHODIMP CImpIOleObject::SetClientSite
  85.     (LPOLECLIENTSITE pIOleClientSite)
  86.     {
  87.     if (NULL!=m_pObj->m_pIOleClientSite)
  88.         m_pObj->m_pIOleClientSite->Release();
  89.  
  90.     m_pObj->m_pIOleClientSite=pIOleClientSite;
  91.  
  92.     if (NULL!=m_pObj->m_pIOleClientSite)
  93.         {
  94.         HRESULT         hr;
  95.         LPMONIKER       pmk;
  96.         LPOLECONTAINER  pIOleCont;
  97.  
  98.         m_pObj->m_pIOleClientSite->AddRef();
  99.  
  100.         /*
  101.          * Within IRunnableObject::Run we're supposed to register
  102.          * ourselves as running...however, the moniker has to come
  103.          * from the container's IOleClientSite::GetMoniker.  But
  104.          * Run is called before SetClientSite here, so we have to
  105.          * register now that we do have the client site as well
  106.          * as lock the container.
  107.          */
  108.  
  109.         hr=m_pObj->m_pIOleClientSite->GetMoniker
  110.             (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, &pmk);
  111.  
  112.         if (SUCCEEDED(hr))
  113.             {
  114.             INOLE_RegisterAsRunning(this, pmk, 0
  115.                 , &m_pObj->m_dwRegROT);
  116.             pmk->Release();
  117.             }
  118.  
  119.         hr=m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont);
  120.  
  121.         if (SUCCEEDED(hr))
  122.             {
  123.             m_pObj->m_fLockContainer=TRUE;
  124.             pIOleCont->LockContainer(TRUE);
  125.             pIOleCont->Release();
  126.             }
  127.         }
  128.  
  129.     return NOERROR;
  130.     }
  131.  
  132. STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE *ppSite)
  133.     {
  134.     //Be sure to AddRef the new pointer you are giving away.
  135.     *ppSite=m_pObj->m_pIOleClientSite;
  136.     m_pObj->m_pIOleClientSite->AddRef();
  137.  
  138.     return NOERROR;
  139.     }
  140.  
  141.  
  142.  
  143.  
  144.  
  145. /*
  146.  * CImpIOleObject::SetHostNames
  147.  *
  148.  * Purpose:
  149.  *  Provides the object with names of the container application and
  150.  *  the object in the container to use in object user interface.
  151.  *
  152.  * Parameters:
  153.  *  pszApp          LPCOLESTR of the container application.
  154.  *  pszObj          LPCOLESTR of some name that is useful in window
  155.  *                  titles.
  156.  *
  157.  * Return Value:
  158.  *  HRESULT         NOERROR
  159.  */
  160.  
  161. STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR pszApp
  162.     , LPCOLESTR pszObj)
  163.     {
  164.     if (NULL!=m_pObj->m_hDlg)
  165.         {
  166.         TCHAR       szTemp[128];
  167.  
  168.        #ifdef WIN32ANSI
  169.         char        szObj[80];
  170.         WideCharToMultiByte(CP_ACP, 0, pszObj, -1, szObj, 80
  171.             , NULL, NULL);
  172.         wsprintf(szTemp, SZPOLYFRAMETITLE, szObj);
  173.        #else
  174.         wsprintf(szTemp, SZPOLYFRAMETITLE, pszObj);
  175.        #endif
  176.         SetWindowText(m_pObj->m_hDlg, szTemp);
  177.         }
  178.  
  179.     return NOERROR;
  180.     }
  181.  
  182.  
  183.  
  184.  
  185.  
  186. /*
  187.  * CImpIOleObject::Close
  188.  *
  189.  * Purpose:
  190.  *  Forces the object to close down its user interface and unload.
  191.  *
  192.  * Parameters:
  193.  *  dwSaveOption    DWORD describing the circumstances under which
  194.  *                  the object is being saved and closed.
  195.  *
  196.  * Return Value:
  197.  *  HRESULT         NOERROR or a general error value.
  198.  */
  199.  
  200. STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption)
  201.     {
  202.     HWND        hWnd;
  203.     BOOL        fSave=FALSE;
  204.  
  205.     hWnd=m_pObj->m_hDlg;
  206.  
  207.     //If object is dirty and we're asked to save, save it and close.
  208.     if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->m_fDirty)
  209.         fSave=TRUE;
  210.  
  211.     /*
  212.      * If asked to prompt, only do so if dirty, then if we get a
  213.      * YES, save as usual and close.  On NO, just close.  On
  214.      * CANCEL return OLE_E_PROMPTSAVECANCELLED.
  215.      */
  216.     if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->m_fDirty)
  217.         {
  218.         TCHAR       szTitle[20];
  219.         TCHAR       szTemp[80];
  220.         UINT        uRet;
  221.  
  222.         lstrcpy(szTitle, m_pObj->String(IDS_CLOSECAPTION));
  223.         lstrcpy(szTemp, m_pObj->String(IDS_CLOSEPROMPT));
  224.  
  225.         uRet=MessageBox(hWnd, szTemp, szTitle, MB_YESNOCANCEL);
  226.  
  227.         if (IDCANCEL==uRet)
  228.             return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
  229.  
  230.         if (IDYES==uRet)
  231.             fSave=TRUE;
  232.         }
  233.  
  234.     if (fSave)
  235.         {
  236.         m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT);
  237.         m_pObj->SendAdvise(OBJECTCODE_SAVED);
  238.         }
  239.  
  240.     //We get directly here on OLECLOSE_NOSAVE.
  241.     if (m_pObj->m_fLockContainer)
  242.         {
  243.         //Match LockContainer call from SetClientSite
  244.         LPOLECONTAINER  pIOleCont;
  245.  
  246.         if (SUCCEEDED(m_pObj->m_pIOleClientSite
  247.             ->GetContainer(&pIOleCont)))
  248.             {
  249.             pIOleCont->LockContainer(FALSE);
  250.             pIOleCont->Release();
  251.             }
  252.         }
  253.  
  254.     if (NULL!=hWnd)
  255.         {
  256.         //This hides the window and sends the appropriate notify.
  257.         DoVerb(OLEIVERB_HIDE, NULL, NULL, -1, NULL, NULL);
  258.  
  259.         m_pObj->SendAdvise(OBJECTCODE_CLOSED);
  260.         PostMessage(hWnd, POLYM_CLOSE, 0, 0L);
  261.         }
  262.  
  263.     return NOERROR;
  264.     }
  265.  
  266.  
  267.  
  268.  
  269. /*
  270.  * CImpIOleObject::DoVerb
  271.  *
  272.  * Purpose:
  273.  *  Executes an object-defined action.
  274.  *
  275.  * Parameters:
  276.  *  iVerb           LONG index of the verb to execute.
  277.  *  pMSG            LPMSG describing the event causing the
  278.  *                  activation.
  279.  *  pActiveSite     LPOLECLIENTSITE to the site involved.
  280.  *  lIndex          LONG the piece on which execution is happening.
  281.  *  hWndParent      HWND of the window in which the object can play
  282.  *                  in-place.
  283.  *  pRectPos        LPRECT of the object in hWndParent where the
  284.  *                  object can play in-place if desired.
  285.  *
  286.  * Return Value:
  287.  *  HRESULT         NOERROR or a general error value.
  288.  */
  289.  
  290. STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG pMSG
  291.     , LPOLECLIENTSITE pActiveSite, LONG lIndex, HWND hWndParent
  292.     , LPCRECT pRectPos)
  293.     {
  294.     HRESULT     hr;
  295.  
  296.     switch (iVerb)
  297.         {
  298.         case OLEIVERB_HIDE:
  299.             //CHAPTER23MOD
  300.             if (NULL!=m_pObj->m_pIOleIPSite)
  301.                 {
  302.                 if (NULL!=m_pObj->m_pHW)
  303.                     ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
  304.                 }
  305.             else
  306.                 {
  307.                 if (NULL!=m_pObj->m_hDlg)
  308.                     ShowWindow(m_pObj->m_hDlg, SW_HIDE);
  309.                 }
  310.  
  311.             m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
  312.             m_pObj->m_fAllowInPlace=TRUE;
  313.             //End CHAPTER23MOD
  314.  
  315.             break;
  316.  
  317.         //CHAPTER23MOD
  318.         case OLEIVERB_PRIMARY:
  319.         case OLEIVERB_SHOW:
  320.             if (NULL!=m_pObj->m_pIOleIPSite)
  321.                 {
  322.                 if (NULL!=m_pObj->m_pHW)
  323.                     ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
  324.  
  325.                 return NOERROR; //Already active
  326.                 }
  327.  
  328.             if (m_pObj->m_fAllowInPlace)
  329.                 {
  330.                 if (SUCCEEDED(m_pObj->InPlaceActivate(pActiveSite
  331.                     , TRUE)))
  332.                     return NOERROR;
  333.                 }
  334.             //FALL THROUGH
  335.         //End CHAPTER23MOD
  336.  
  337.         case OLEIVERB_OPEN:
  338.             //CHAPTER23MOD
  339.             if (NULL!=m_pObj->m_pIOleIPSite)
  340.                 {
  341.                 m_pObj->InPlaceDeactivate();
  342.                 m_pObj->m_fAllowInPlace=FALSE;
  343.                 }
  344.             //End CHAPTER23MOD
  345.  
  346.             /*
  347.              * If we're not running, make sure we are.  In any
  348.              * case, make the dialog visible and insure it has
  349.              * the right parent now.
  350.              */
  351.             hr=NOERROR;
  352.             if (NULL==m_pObj->m_hDlg)
  353.                 hr=m_pObj->m_pImpIRunnableObject->Run(NULL);
  354.  
  355.             if (FAILED(hr) || NULL==m_pObj->m_hDlg)
  356.                 return ResultFromScode(E_OUTOFMEMORY);
  357.  
  358.             ShowWindow(m_pObj->m_hDlg, SW_SHOW);
  359.             SetFocus(m_pObj->m_hDlg);
  360.             m_pObj->SendAdvise(OBJECTCODE_SHOWOBJECT);
  361.             m_pObj->SendAdvise(OBJECTCODE_SHOWWINDOW);
  362.  
  363.             break;
  364.  
  365.         //CHAPTER23MOD
  366.         case OLEIVERB_INPLACEACTIVATE:
  367.             if (NULL!=m_pObj->m_pHW)
  368.                 {
  369.                 HWND    hWndHW=m_pObj->m_pHW->Window();
  370.  
  371.                 ShowWindow(hWndHW, SW_SHOW);
  372.                 SetFocus(hWndHW);
  373.  
  374.                 return NOERROR;
  375.                 }
  376.  
  377.             /*
  378.              * Only inside-out supporting containers will use
  379.              * this verb.
  380.              */
  381.             m_pObj->m_fContainerKnowsInsideOut=TRUE;
  382.             m_pObj->InPlaceActivate(pActiveSite, FALSE);
  383.             break;
  384.  
  385.         case OLEIVERB_UIACTIVATE:
  386.             m_pObj->InPlaceActivate(pActiveSite, TRUE);
  387.             break;
  388.         //End CHAPTER23MOD
  389.  
  390.         default:
  391.             return ResultFromScode(OLEOBJ_S_INVALIDVERB);
  392.         }
  393.  
  394.     return NOERROR;
  395.     }
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402. /*
  403.  * CImpIOleObject::GetUserClassID
  404.  *
  405.  * Purpose:
  406.  *  Used for linked objects, this returns the class ID of what end
  407.  *  users think they are editing.
  408.  *
  409.  * Parameters:
  410.  *  pClsID          LPCLSID in which to store the CLSID.
  411.  *
  412.  * Return Value:
  413.  *  HRESULT         NOERROR or a general error value.
  414.  */
  415.  
  416. STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID)
  417.     {
  418.     /*
  419.      * If you are not registered to handle data other than yourself,
  420.      * then you can just return your class ID here.  If you are
  421.      * registered as usable from Treat-As dialogs, then you need to
  422.      * return the CLSID of what you are really editing.
  423.      */
  424.  
  425.     *pClsID=CLSID_Polyline19;
  426.     return NOERROR;
  427.     }
  428.  
  429.  
  430.  
  431.  
  432.  
  433. /*
  434.  * CImpIOleObject::SetExtent
  435.  *
  436.  * Purpose:
  437.  *  Sets the size of the object in HIMETRIC units.  Since we're in
  438.  *  a dialog, the size of the object in us is fixed, so we ignore
  439.  *  this call.
  440.  *
  441.  * Parameters:
  442.  *  dwAspect        DWORD of the aspect affected.
  443.  *  pszl            LPSIZEL containing the new size.
  444.  *
  445.  * Return Value:
  446.  *  HRESULT         NOERROR or a general error value.
  447.  */
  448.  
  449. STDMETHODIMP CImpIOleObject::SetExtent(DWORD dwAspect
  450.     , LPSIZEL pszl)
  451.     {
  452.     //Ignored:  no size change in the dialog.
  453.     return NOERROR;
  454.     }
  455.  
  456.  
  457.  
  458.  
  459.  
  460. /*
  461.  * CImpIOleObject::GetExtent
  462.  *
  463.  * Purpose:
  464.  *  Retrieves the size of the object in HIMETRIC units.
  465.  *
  466.  * Parameters:
  467.  *  dwAspect        DWORD of the aspect requested
  468.  *  pszl            LPSIZEL into which to store the size.
  469.  *
  470.  * Return Value:
  471.  *  HRESULT         NOERROR or a general error value.
  472.  */
  473.  
  474. STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl)
  475.     {
  476.     //Delegate directly to IViewObject2::GetExtent
  477.     return m_pObj->m_pImpIViewObject->GetExtent(dwAspect, -1
  478.         , NULL, pszl);
  479.     }
  480.  
  481.  
  482.  
  483.  
  484.  
  485. /*
  486.  * CImpIOleObject::Advise
  487.  * CImpIOleObject::Unadvise
  488.  * CImpIOleObject::EnumAdvise
  489.  *
  490.  * Purpose:
  491.  *  Advisory connection functions.
  492.  */
  493.  
  494. STDMETHODIMP CImpIOleObject::Advise(LPADVISESINK pIAdviseSink
  495.     , LPDWORD pdwConn)
  496.     {
  497.     if (NULL==m_pObj->m_pIOleAdviseHolder)
  498.         {
  499.         HRESULT     hr;
  500.  
  501.         hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
  502.  
  503.         if (FAILED(hr))
  504.             return hr;
  505.         }
  506.  
  507.     return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink
  508.         , pdwConn);
  509.     }
  510.  
  511.  
  512. STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn)
  513.     {
  514.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  515.         return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
  516.  
  517.     return ResultFromScode(E_FAIL);
  518.     }
  519.  
  520.  
  521. STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum)
  522.     {
  523.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  524.         return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
  525.  
  526.     return ResultFromScode(E_FAIL);
  527.     }
  528.  
  529.  
  530.  
  531. /*
  532.  * CImpIOleObject::SetMoniker
  533.  *
  534.  * Purpose:
  535.  *  Informs the object of its moniker or its container's moniker
  536.  *  depending on dwWhich.
  537.  *
  538.  * Parameters:
  539.  *  dwWhich         DWORD describing whether the moniker is the
  540.  *                  object's or the container's.
  541.  *  pmk             LPMONIKER with the name.
  542.  *
  543.  * Return Value:
  544.  *  HRESULT         NOERROR or a general error value.
  545.  */
  546.  
  547. STDMETHODIMP CImpIOleObject::SetMoniker(DWORD dwWhich
  548.     , LPMONIKER pmk)
  549.     {
  550.     LPMONIKER       pmkFull;
  551.     HRESULT         hr=ResultFromScode(E_FAIL);
  552.  
  553.     if (NULL!=m_pObj->m_pIOleClientSite)
  554.         {
  555.         hr=m_pObj->m_pIOleClientSite->GetMoniker
  556.             (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  557.             , &pmkFull);
  558.         }
  559.  
  560.     if (SUCCEEDED(hr))
  561.         {
  562.         if (NOERROR==pmkFull->IsRunning(NULL, NULL, NULL))
  563.             {
  564.             pmkFull->Release();
  565.             return NOERROR;
  566.             }
  567.  
  568.         //This will revoke the old one if m_dwRegROT is nonzero.
  569.         INOLE_RegisterAsRunning(m_pObj, pmkFull, 0
  570.             , &m_pObj->m_dwRegROT);
  571.  
  572.         //Inform clients of the new moniker
  573.         if (NULL!=m_pObj->m_pIOleAdviseHolder)
  574.             m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
  575.  
  576.         pmkFull->Release();
  577.         }
  578.  
  579.     return hr;
  580.     }
  581.  
  582.  
  583.  
  584. /*
  585.  * CImpIOleObject::GetMoniker
  586.  *
  587.  * Purpose:
  588.  *  Asks the object for a moniker that can later be used to
  589.  *  reconnect to it.
  590.  *
  591.  * Parameters:
  592.  *  dwAssign        DWORD determining how to assign the moniker to
  593.  *                  to the object.
  594.  *  dwWhich         DWORD describing which moniker the caller wants.
  595.  *  ppmk            LPMONIKER * into which to store the moniker.
  596.  *
  597.  * Return Value:
  598.  *  HRESULT         NOERROR or a general error value.
  599.  */
  600.  
  601. STDMETHODIMP CImpIOleObject::GetMoniker(DWORD dwAssign
  602.     , DWORD dwWhich, LPMONIKER *ppmk)
  603.     {
  604.     HRESULT         hr=ResultFromScode(E_FAIL);
  605.  
  606.     *ppmk=NULL;
  607.  
  608.     /*
  609.      * Since we only support embedded objects, our moniker
  610.      * is always the full moniker from the contianer.
  611.      */
  612.  
  613.     if (NULL!=m_pObj->m_pIOleClientSite)
  614.         {
  615.         hr=m_pObj->m_pIOleClientSite->GetMoniker
  616.             (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, ppmk);
  617.         }
  618.  
  619.     return (NULL!=*ppmk) ? NOERROR : hr;
  620.     }
  621.  
  622.  
  623.  
  624. //Methods not implemented or trivial
  625. STDMETHODIMP CImpIOleObject::InitFromData(LPDATAOBJECT pIDataObject
  626.     , BOOL fCreation, DWORD dw)
  627.     {
  628.     return ResultFromScode(E_NOTIMPL);
  629.     }
  630.  
  631. STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD dwReserved
  632.     , LPDATAOBJECT *ppIDataObj)
  633.     {
  634.     return ResultFromScode(E_NOTIMPL);
  635.     }
  636.  
  637. STDMETHODIMP CImpIOleObject::Update(void)
  638.     {
  639.     return NOERROR;
  640.     }
  641.  
  642. STDMETHODIMP CImpIOleObject::IsUpToDate(void)
  643.     {
  644.     return NOERROR;
  645.     }
  646.  
  647. STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE pLP)
  648.     {
  649.     return ResultFromScode(E_NOTIMPL);
  650.     }
  651.  
  652.  
  653.  
  654. //Methods implemented using registry helper functions in OLE.
  655.  
  656. STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum)
  657.     {
  658.     return OleRegEnumVerbs(m_pObj->m_clsID, ppEnum);
  659.     }
  660.  
  661. STDMETHODIMP CImpIOleObject::GetUserType(DWORD dwForm
  662.     , LPOLESTR *ppszType)
  663.     {
  664.     return OleRegGetUserType(m_pObj->m_clsID, dwForm, ppszType);
  665.     }
  666.  
  667. STDMETHODIMP CImpIOleObject::GetMiscStatus(DWORD dwAspect
  668.     , LPDWORD pdwStatus)
  669.     {
  670.     return OleRegGetMiscStatus(m_pObj->m_clsID, dwAspect
  671.         , pdwStatus);
  672.     }
  673.