home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / BOCOLE.PAK / BOLECTRL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  18.7 KB  |  740 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1996 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.16  $
  6. //
  7. //  Implements the Bolero half of the OLE2 control object.
  8. //    BOleControl objects impersonate the OCX from the point of view of the 
  9. //    Bolero customer who's writing a OCX container.
  10. //----------------------------------------------------------------------------
  11. #include "BOle.h"
  12. #include "BOleCMan.h"
  13. #include "BOleCtrl.h"
  14. #include "BOleFont.h"
  15. #include "BOleDoc.h"
  16.  
  17. #if defined(WIN16)
  18. #include <olenls.h>
  19. #endif
  20.  
  21.  
  22. #define NOT_IMPLEMENTED OLERET(E_NOTIMPL);
  23.  
  24. BOOL InterfaceDisconnect(LPUNKNOWN pObj, REFIID riid, LPDWORD pdwConn);
  25. BOOL InterfaceConnect(LPUNKNOWN pObj, REFIID riid,
  26.                       LPUNKNOWN pIUnknownSink, LPDWORD pdwConn);
  27.  
  28. //**************************************************************************
  29. //
  30. // BOleControl implementation -- These functions aren't part of an inherited
  31. //                              interface, but are part of the private
  32. //                              implementation of BOleControl
  33. //
  34. //**************************************************************************
  35.  
  36. HRESULT _IFUNC BOleControl::QueryInterfaceMain(REFIID iid, LPVOID FAR *ppv)
  37. {
  38.   HRESULT hr = ResultFromScode(E_NOINTERFACE);
  39.   *ppv = NULL;
  40.  
  41.   // Self
  42.   //
  43.   if (iid == IID_BOleControl) {
  44.      (BOleControl *)*ppv = this;
  45.      BOlePart::AddRef();
  46.      return NOERROR;
  47.   }
  48.  
  49.   // interfaces
  50.   if (SUCCEEDED(hr = IOleControlSite_QueryInterface (this, iid, ppv))) {
  51.   }
  52.   else if (SUCCEEDED(hr = IPropertyNotifySink_QueryInterface (this, iid, ppv))) {
  53.   }
  54.   else if (SUCCEEDED(hr = IBControl_QueryInterface(this, iid, ppv))) {
  55.   }
  56.   else if ((iid == IID_IDispatch) && (pIAmbients)){
  57.     ((IDispatch *)*ppv) = pIAmbients;
  58.     pIAmbients->AddRef ();
  59.     return NOERROR;
  60.   }
  61.   else if ((pIEvents) && (iid == iidEvents)) {
  62.     ((IDispatch *)*ppv) = pIEvents;
  63.     pIEvents->AddRef ();
  64.     return NOERROR;
  65.   }
  66.   // base classes
  67.   else if (SUCCEEDED(hr = BOlePart::QueryInterfaceMain(iid, ppv))) {
  68.   }
  69.   return hr;
  70. };
  71.  
  72.  
  73. BOleControl::BOleControl (BOleClassManager *pF, IBUnknownMain * pO,
  74.                            BOleDocument * pOD) :
  75.   BOlePart (pF, pO, pOD),
  76.   pIEvents (NULL),         pIAmbients (NULL),
  77.   pCtrlDispatch (NULL),    pOleCtrl (NULL),
  78.   pCSite (NULL),           pNextCtrl (NULL),
  79.   pPrevCtrl (NULL),        iidEvents (IID_NULL),
  80.   ConnEvents (0),          ConnProp (0)
  81. {
  82.   CtrlInfo.cb = sizeof(CONTROLINFO);
  83.   CtrlInfo.cAccel = 0;
  84.   CtrlInfo.hAccel = 0;
  85. }
  86.  
  87. BOleControl::~BOleControl ()
  88. {
  89.   RemoveFromCtrlList ();
  90.   if (ConnEvents)
  91.     InterfaceDisconnect (pOleCtrl, iidEvents, &ConnEvents);
  92.   if (ConnProp)
  93.     InterfaceDisconnect (pOleCtrl, IID_IPropertyNotifySink, &ConnProp);
  94.  
  95.   if (pCtrlDispatch) {
  96.     pCtrlDispatch->Release();
  97.     pCtrlDispatch = NULL;
  98.   }
  99.   if (pIEvents) {
  100.     pIEvents->Release();
  101.     pIEvents = NULL;
  102.   }
  103.   if (pIAmbients) {
  104.     pIAmbients->Release();
  105.     pIAmbients = NULL;
  106.   }
  107.   if (pOleCtrl) {
  108.     pOleCtrl->Release();
  109.     pOleCtrl = NULL;
  110.   }
  111. }
  112.  
  113.  
  114.  
  115. HRESULT _IFUNC BOleControl::Init(IBSite * pIS,BOleInitInfo *pBI)
  116. {
  117.   HRESULT hr;
  118.  
  119.   hr = pIS->QueryInterface (IID_IBControlSite, &(VOID FAR*)pCSite);
  120.   if (!pCSite)
  121.      return hr;
  122.   pCSite->Release ();
  123.  
  124.   hr = BOlePart::Init (pIS, pBI);
  125.   if (FAILED (hr))
  126.      return hr;
  127.  
  128.   hr = pOleObject->QueryInterface (IID_IOleControl, &(VOID FAR*)pOleCtrl);
  129.   if (!pOleCtrl)
  130.      return hr;
  131.   AddToCtrlList ();
  132.  
  133.   /*
  134.    * Call IOleControl::GetControlInfo to retrieve the keyboard
  135.    * information for this control.  We have to reload this
  136.    * information in IOleControlSite::OnControlInfoChanged.
  137.    */
  138.   pOleCtrl->GetControlInfo (&CtrlInfo);
  139.  
  140.   /*
  141.    * Get the properties and methods IDispatch
  142.    */
  143.   pOleCtrl->QueryInterface (IID_IDispatch, &(VOID FAR*)pCtrlDispatch);
  144.  
  145.  
  146.   /*
  147.    * Connect our events IDispatch to the object.  The function
  148.    * EventIIDFromObject retrieves the events IID for us.  If 
  149.    * InterfaceConnect fails, then we'll just do without events.  If 
  150.    * we do connect to the events, then we need to initialize event 
  151.    * information.
  152.    */
  153.   ObjectEventsIID (&iidEvents);
  154.  
  155.   /*
  156.    * Connect our property notification sink to the object.
  157.    * If "new" fails then InterfaceConnect will fail and we'll
  158.    * just do without notifications.
  159.    */
  160.   IUnknown *pObj;
  161.   QueryInterface (IID_IPropertyNotifySink, &(VOID FAR*)pObj);
  162.   if (pObj)
  163.   {
  164.     InterfaceConnect (pOleCtrl, IID_IPropertyNotifySink, pObj, &ConnProp);
  165.     pObj->Release ();
  166.   }
  167.   return hr;
  168. }
  169.  
  170.  
  171. HRESULT _IFUNC BOleControl::BOleCreate (BOleInitInfo *pBI, DWORD dwRenderOpt, 
  172.                                                       LPVOID FAR *ppv)
  173. {
  174.   if (pBI->Where == BOLE_NEW)
  175.     return BOlePart::BOleCreate (pBI, dwRenderOpt, ppv);
  176.  
  177.   // else if (pBI->Where == BOLE_NEW_OCX)
  178.  
  179.   HRESULT     hr;
  180.   FORMATETC   fmtetc;
  181.   CLSID       clsidNew;
  182.   IOleObject *poleobj = NULL;
  183.   IUnknown   *punk;
  184.  
  185.   *ppv = NULL;
  186.  
  187.   // Check if this class auto-converts to another class
  188.   hr = OleGetAutoConvert (*(LPIID)pBI->whereNew.cid, &clsidNew);
  189.   if (FAILED (hr))
  190.     clsidNew = *(LPIID)pBI->whereNew.cid;
  191.  
  192.   // Create handler or inproc server for class
  193.   hr = CoCreateInstance (clsidNew, NULL, CLSCTX_INPROC, IID_IOleObject, 
  194.                                                       &(LPVOID)punk);
  195.   if (FAILED (hr))
  196.     goto error;
  197.  
  198.   *ppv = punk;
  199.   DWORD dwMiscStatus;
  200.   // Determine if IOleObject::SetClientSite should be called before
  201.   // IPersistStorage::InitNew
  202.   hr = punk->QueryInterface (IID_IOleObject, (LPVOID FAR*)&poleobj);
  203.   if (FAILED (hr))
  204.     goto error;
  205.   hr = poleobj->GetMiscStatus (DVASPECT_CONTENT, &dwMiscStatus);
  206.   if (FAILED (hr))
  207.     goto error;
  208.  
  209.   // Set client site before InitNew if the control requires it.
  210.   if (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
  211.   {
  212.     hr = poleobj->SetClientSite (this);
  213.     if (FAILED (hr))
  214.        goto error;
  215.   }
  216.  
  217.  /*
  218.  * BOleCreate do not use the IPersistStreamInit
  219.  * interfaces. A control container that wants to use this interface
  220.  * would either not cache a presentation or would cache the presentation
  221.  * itself after obtaining it using IDataObject::GetData. It will not be
  222.  * able to use the default handler to cache the presentation because
  223.  * the default handler can only save/load presentations into/from storages.
  224.  * If the controls are always shipped with the container, caching is not
  225.  * required.
  226.  */
  227.   LPPERSISTSTORAGE pPS;
  228.   // Write class into storage and call InitNew
  229.   hr = punk->QueryInterface (IID_IPersistStorage, (LPVOID FAR*)&pPS);
  230.   if (FAILED (hr))
  231.     goto error;
  232.   WriteClassStg (pStgFromInit, clsidNew);
  233.   hr = pPS->InitNew (pStgFromInit);
  234.   pPS->Release ();
  235.   if (FAILED (hr))
  236.     goto error;
  237.  
  238.   if (!(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
  239.   {
  240.     hr = poleobj->SetClientSite (this);
  241.     if (FAILED (hr))
  242.        goto error;
  243.   }
  244.   poleobj->Release ();
  245.   poleobj = NULL;
  246.  
  247.  
  248.   // No need to run the object or cache presentations if no
  249.   // caches are requested.
  250.   if ((dwRenderOpt == OLERENDER_NONE) || (dwRenderOpt == OLERENDER_ASIS))
  251.     return NOERROR;
  252.  
  253.   // If the render option is OLERENDER_DRAW, pfmtetc can be NULL. If
  254.   // pfmtetc is non-NULL, cfFormat & tymed must be 0.
  255.   if (dwRenderOpt == OLERENDER_DRAW) {
  256.     fmtetc.cfFormat = NULL;
  257.     fmtetc.tymed = TYMED_NULL;
  258.     fmtetc.ptd = NULL;
  259.     fmtetc.lindex = -1;
  260.     fmtetc.dwAspect = DVASPECT_CONTENT;
  261.   }
  262.  
  263. #if 0
  264.   OleCreate will run the object at this point using OleRun. But OleRun
  265.   calls IPersistStorage::InitNew before IOleObject::SetClientSite using
  266.   the client site and storage pointers saved in the handler. For this
  267.   reason, ControlCreate () doesn't support LocalServer controls.
  268.   (LocalServer controls currently cannot be implemented because the new 
  269.    OLE control interfaces do not have marshalling code).
  270.  
  271.   // Run object
  272.   hr = OleRun (punk);
  273.   if (FAILED (hr))
  274.      goto error;
  275. #endif
  276.  
  277.   LPOLECACHE polecache;
  278.   DWORD dwConnId;
  279.   // Cache presentation
  280.   hr = punk->QueryInterface (IID_IOleCache, (LPVOID FAR*)&polecache);
  281.   if (FAILED (hr))
  282.       return NOERROR;
  283.     //goto error;
  284.   hr =  polecache->Cache (&fmtetc, ADVF_PRIMEFIRST, &dwConnId);
  285.   polecache->Release ();
  286.   if (FAILED (hr))
  287.     goto error;
  288.  
  289.   return NOERROR;
  290.  
  291. error:
  292.   if (punk) punk->Release ();
  293.   *ppv = NULL;
  294.   if (poleobj) poleobj->Release ();
  295.   return hr;
  296.  
  297. }
  298.  
  299.  
  300. void BOleControl::AddToCtrlList ()
  301. {
  302.   // Insert "this" onto the list of control instances in this document.
  303.   // Similar to part list on doc
  304.   BOleControl *pOldFirstCtrl = pDoc->GetFirstControl ();
  305.   pDoc->SetFirstControl (this);
  306.   pNextCtrl = pOldFirstCtrl;
  307.   if (pOldFirstCtrl)
  308.     pOldFirstCtrl->pPrevCtrl = this;
  309. }
  310.  
  311. void BOleControl::RemoveFromCtrlList ()
  312. {
  313.   // Remove "this" from the list of part instances in this document.
  314.   //
  315.   if (pPrevCtrl)
  316.     pPrevCtrl->pNextCtrl = pNextCtrl;
  317.   if (pNextCtrl)
  318.     pNextCtrl->pPrevCtrl = pPrevCtrl;
  319.  
  320.   if (pDoc) {
  321.     if (this == pDoc->GetFirstControl ())
  322.       pDoc->SetFirstControl (pNextCtrl);
  323.   }
  324.   pNextCtrl = pPrevCtrl = NULLP;
  325. }
  326.  
  327. // standard control methods
  328. HRESULT _IFUNC BOleControl::Refresh ()
  329. {
  330.   return InvokeStdMethod (DISPID_REFRESH);
  331. }
  332.  
  333.  
  334. HRESULT _IFUNC BOleControl::DoClick ()
  335. {
  336.   return InvokeStdMethod (DISPID_DOCLICK);
  337. }
  338.  
  339.  
  340. HRESULT _IFUNC BOleControl::AboutBox ()
  341. {
  342.   return InvokeStdMethod (DISPID_ABOUTBOX);
  343. }
  344.  
  345.  
  346. HRESULT BOleControl::InvokeStdMethod (DISPID id)
  347. {
  348.   VARIANTARG   result;
  349.   DISPPARAMS   args;
  350.   unsigned int argError;
  351.  
  352.   VariantInit (&result);
  353.   args.rgvarg = NULLP;
  354.   args.cArgs = 0;
  355.   args.cNamedArgs = 0;
  356.   args.rgdispidNamedArgs = NULLP;
  357.   return pCtrlDispatch->Invoke (id, IID_NULL,
  358.       LOCALE_SYSTEM_DEFAULT,
  359.       DISPATCH_METHOD, &args, &result, NULLP, &argError);
  360. }
  361.  
  362.  
  363. HRESULT _IFUNC BOleControl::GetEventIID (IID *iidEv)
  364. {
  365.   *iidEv = iidEvents;
  366.   return NOERROR;
  367. }
  368.  
  369.  
  370. HRESULT _IFUNC BOleControl::GetEventTypeInfo (LPTYPEINFO *ppITypeInfo)
  371. {
  372.   HRESULT             hr;
  373.   LPTYPEINFO          pITypeInfoAll;
  374.   LPPROVIDECLASSINFO  pIProvideClassInfo;
  375.   LPTYPEATTR          pTA;
  376.  
  377.   *ppITypeInfo = NULL;  //Use this to determine success
  378.   if (!(pOleCtrl) || !(ppITypeInfo))
  379.      return ResultFromScode (S_FALSE);
  380.  
  381.   /*
  382.    * Get the object's IProvideClassInfo and call the GetClassInfo
  383.    * method therein.  This will give us back the ITypeInfo for
  384.    * the entire object.
  385.    */
  386.  
  387.   hr = pOleCtrl->QueryInterface(IID_IProvideClassInfo,
  388.                                    &(VOID FAR*)pIProvideClassInfo);
  389.   if (FAILED (hr))
  390.      return hr;
  391.  
  392.   hr = pIProvideClassInfo->GetClassInfo (&pITypeInfoAll);
  393.   pIProvideClassInfo->Release ();
  394.   if (FAILED (hr))
  395.      return hr;
  396.  
  397.  
  398.   /*
  399.    * We have the object's overall ITypeInfo in pITypeInfoAll.
  400.    * Now get the type attributes which will tell us the number of
  401.    * individual interfaces in this type library.  We then loop
  402.    * through the "implementation types" for all those interfaces
  403.    * calling GetImplTypeFlags, looking for the default source.
  404.    */
  405.   if (SUCCEEDED (pITypeInfoAll->GetTypeAttr (&pTA))) {
  406.     UINT        i;
  407.     int         iFlags;
  408.  
  409.     for (i=0; i < pTA->cImplTypes; i++) {
  410.       //Get the implementation type for this interface
  411.       if (FAILED (pITypeInfoAll->GetImplTypeFlags (i, &iFlags)))
  412.          continue;
  413.  
  414.       if ((iFlags & IMPLTYPEFLAG_FDEFAULT)
  415.                            && (iFlags & IMPLTYPEFLAG_FSOURCE))
  416.       {
  417.         HREFTYPE    hRefType=NULL;
  418.  
  419.         /*
  420.          * This is the interface we want.  Get a handle to
  421.          * the type description from which we can then get
  422.          * the ITypeInfo.
  423.          */
  424.         pITypeInfoAll->GetRefTypeOfImplType (i, &hRefType);
  425.         hr = pITypeInfoAll->GetRefTypeInfo (hRefType, ppITypeInfo);
  426.         break;
  427.       }
  428.     }
  429.     pITypeInfoAll->ReleaseTypeAttr(pTA);
  430.   }
  431.   pITypeInfoAll->Release();
  432.   return (*ppITypeInfo != NULL)? ResultFromScode (S_OK) : ResultFromScode (S_FALSE);
  433. }
  434.  
  435.  
  436. HRESULT _IFUNC BOleControl::GetCtrlDispatch (IDispatch FAR * FAR *ppDispatch)
  437. {
  438.   *ppDispatch = pCtrlDispatch;
  439.   pCtrlDispatch->AddRef ();
  440.   return S_OK;
  441. }
  442.  
  443.  
  444. /*
  445.  * ObjectEventsIID
  446.  *
  447.  * Purpose:
  448.  *  Determines the IID of the object's events interface so we
  449.  *  can ask for the right IConnectionPoint for events.
  450.  */
  451.  
  452. BOOL BOleControl::ObjectEventsIID (IID *piid)
  453. {
  454.   HRESULT     hr;
  455.   LPTYPEINFO  pITypeInfo;
  456.   LPTYPEATTR  pTA;
  457.  
  458.   *piid = IID_IDispatch;
  459.   *piid = CLSID_NULL;
  460.   if (GetEventTypeInfo (&pITypeInfo) != S_OK)
  461.     return FALSE;
  462.  
  463.   hr = pITypeInfo->GetTypeAttr (&pTA);
  464.   if (SUCCEEDED (hr)) {
  465.     *piid = pTA->guid;
  466.     pITypeInfo->ReleaseTypeAttr (pTA);
  467.   }
  468.   pITypeInfo->Release ();
  469.   return SUCCEEDED (hr);
  470. }
  471.  
  472.  
  473.  
  474. HRESULT _IFUNC BOleControl::SetEventDispatch (IDispatch *pNew)
  475. {
  476.   if (pIEvents) {
  477.     if (ConnEvents)
  478.       InterfaceDisconnect (pOleCtrl, iidEvents, &ConnEvents);
  479.     pIEvents->Release ();
  480.   }
  481.  
  482.   pIEvents = pNew;
  483.   if (pIEvents) {
  484.     pIEvents->AddRef ();
  485.     if (pOleCtrl)
  486.       InterfaceConnect (pOleCtrl, iidEvents, pIEvents, &ConnEvents);
  487.   }
  488.   return NOERROR;
  489. }
  490.  
  491.  
  492. HRESULT _IFUNC BOleControl::SetAmbientDispatch (IDispatch *pNew)
  493. {
  494.   if (pIAmbients)
  495.     pIAmbients->Release ();
  496.  
  497.   pIAmbients = pNew;
  498.   if (pIAmbients)
  499.     pIAmbients->AddRef ();
  500.   return NOERROR;
  501. }
  502.  
  503.  
  504.  
  505. HRESULT _IFUNC BOleControl::AmbientChanged (DISPID dispid)
  506. {
  507.   if (pOleCtrl)
  508.     return pOleCtrl->OnAmbientPropertyChange (dispid);
  509.   else return NOERROR;
  510. }
  511.  
  512. // function passed down by BOleControlSite
  513. HRESULT _IFUNC BOleControl::GetControlInfo (LPCONTROLINFO pCI)
  514. {
  515.   *pCI = CtrlInfo;
  516.   return S_OK;
  517. }
  518.  
  519. HRESULT _IFUNC BOleControl::OnMnemonic (LPMSG pMsg)
  520. {
  521.   return ResultFromScode (E_NOTIMPL);
  522. }
  523.  
  524.  
  525. #if 0 
  526. HRESULT _IFUNC BOleControl::OnAmbientPropertyChange (DISPID dispid)
  527. {
  528.   return ResultFromScode (E_NOTIMPL);
  529. }
  530. #endif 
  531.  
  532. HRESULT _IFUNC BOleControl::GetSizeMax (ULARGE_INTEGER FAR*)
  533. {
  534.   return ResultFromScode (E_NOTIMPL);
  535. }
  536.  
  537. HRESULT _IFUNC BOleControl::Save (LPSTREAM)
  538. {
  539.   return ResultFromScode (E_NOTIMPL);
  540. }
  541.  
  542.  
  543.  
  544. HRESULT _IFUNC BOleControl::FreezeEvents (BOOL bFreeze)
  545. {
  546.   return ResultFromScode (E_NOTIMPL);
  547. }
  548.  
  549. HRESULT _IFUNC BOleControl::GetClassInfo (LPTYPEINFO FAR* ppTI)
  550. {
  551.   return ResultFromScode (E_NOTIMPL);
  552. }
  553.  
  554. // IOleControlSite methods
  555. HRESULT _IFUNC BOleControl::OnControlInfoChanged (void)
  556. {
  557.   if (pOleCtrl)
  558.     pOleCtrl->GetControlInfo (&CtrlInfo); 
  559.   return NOERROR;
  560. }
  561.  
  562.  
  563. HRESULT _IFUNC BOleControl::LockInPlaceActive (BOOL fLock)
  564. {
  565.   NOT_IMPLEMENTED
  566. }
  567.  
  568.  
  569. HRESULT _IFUNC BOleControl::GetExtendedControl (LPDISPATCH FAR* ppDisp)
  570. {
  571.   NOT_IMPLEMENTED
  572. }
  573.  
  574.  
  575.  
  576. HRESULT _IFUNC BOleControl::TransformCoords (POINTL FAR* lpptlHimetric,
  577.                                POINTF FAR* lpptfContainer, DWORD flags)
  578. {
  579.   return pCSite->TransformCoords (lpptlHimetric,
  580.                         (TPOINTF FAR*)lpptfContainer, flags);
  581. }
  582.  
  583.  
  584.  
  585. HRESULT _IFUNC BOleControl::TranslateAccelerator (LPMSG lpMsg, DWORD )
  586. {
  587.   return pDoc->TranslateControlAccel (lpMsg);
  588. }
  589.  
  590.  
  591.  
  592. HRESULT _IFUNC BOleControl::OnFocus (BOOL fGotFocus)
  593. {
  594.   HRESULT hr = NOERROR;
  595.  
  596.   pCSite->OnControlFocus (fGotFocus);
  597.   if (fGotFocus && pOleObject)
  598.     hr = DoVerb (OLEIVERB_UIACTIVATE);
  599.   return hr;
  600. }
  601.  
  602.  
  603.  
  604. HRESULT _IFUNC BOleControl::ShowPropertyFrame (void)
  605. {
  606.   NOT_IMPLEMENTED
  607. }
  608.  
  609.  
  610.  
  611.  
  612. // IPropertyNotifySink methods
  613. HRESULT _IFUNC BOleControl::OnChanged (DISPID dispid)
  614. {
  615.   pCSite->OnPropertyChanged (dispid);
  616.   return NOERROR;
  617. }
  618.  
  619.  
  620.  
  621. HRESULT _IFUNC BOleControl::OnRequestEdit (DISPID dispid)
  622. {
  623.   return pCSite->OnPropertyRequestEdit (dispid);
  624.   // OnPropertyRequestEdit to return S_OK or S_FALSE
  625. }
  626.  
  627.  
  628.  
  629. /////////// utility routines
  630.  
  631.  
  632. /*
  633.  * InterfaceConnect
  634.  *
  635.  * Purpose:
  636.  *  Connects some sink interface of a given IID to an object.
  637.  *
  638.  * Parameters:
  639.  *  pObj            LPUNKNOWN of the object to which we connect
  640.  *  riid            REFIID of the interface of the sink
  641.  *  pIUnknownSink   LPUNKNOWN of the caller's sink interface that
  642.  *                  is actually of the type matching riid
  643.  *  pdwConn         LPDWORD in which to return the connection key
  644.  *
  645.  * Return Value:
  646.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  647.  */
  648.  
  649. BOOL InterfaceConnect(LPUNKNOWN pObj, REFIID riid,
  650.                       LPUNKNOWN pIUnknownSink, LPDWORD pdwConn)
  651. {
  652.   HRESULT                     hr;
  653.   LPCONNECTIONPOINTCONTAINER  pCPC;
  654.   LPCONNECTIONPOINT           pCP;
  655.  
  656.   if (!pObj || !pIUnknownSink || !pdwConn)
  657.     return FALSE;
  658.  
  659.   if (FAILED (pObj->QueryInterface(IID_IConnectionPointContainer,
  660.                      &(VOID FAR*)pCPC)))
  661.     return FALSE;
  662.  
  663.   hr = pCPC->FindConnectionPoint(riid, &pCP);
  664.   if (SUCCEEDED (hr)) {
  665.     hr = pCP->Advise (pIUnknownSink, pdwConn);
  666.     pCP->Release();
  667.   }
  668.   pCPC->Release();
  669.   return SUCCEEDED(hr);
  670. }
  671.  
  672.  
  673.  
  674. /*
  675.  * InterfaceDisconnect
  676.  *
  677.  * Purpose:
  678.  *  Disconnects a prior connection to an object.
  679.  *
  680.  * Parameters:
  681.  *  pObj            LPUNKNOWN of the object from which to disconnect
  682.  *  riid            REFIID of the interface of the sink
  683.  *  pdwConn         LPDWORD containing the key returned by
  684.  *                  InterfaceConnect.  This function will zero the
  685.  *                  key on diconnect.
  686.  *
  687.  * Return Value:
  688.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  689.  */
  690.  
  691. BOOL InterfaceDisconnect(LPUNKNOWN pObj, REFIID riid, LPDWORD pdwConn)
  692. {
  693.   HRESULT                     hr;
  694.   LPCONNECTIONPOINTCONTAINER  pCPC;
  695.   LPCONNECTIONPOINT           pCP;
  696.  
  697.   if (!pObj || !pdwConn)
  698.     return FALSE;
  699.  
  700.   if (*pdwConn == 0)
  701.     return FALSE;
  702.  
  703.   if (FAILED (pObj->QueryInterface (IID_IConnectionPointContainer,
  704.                      &(VOID FAR*)pCPC)))
  705.     return FALSE;
  706.  
  707.   hr = pCPC->FindConnectionPoint (riid, &pCP);
  708.   if (SUCCEEDED (hr)) {
  709.     hr = pCP->Unadvise (*pdwConn);
  710.     if (SUCCEEDED (hr))
  711.       *pdwConn = 0L;
  712.     pCP->Release ();
  713.   }
  714.   pCPC->Release();
  715.   return SUCCEEDED (hr);
  716. }
  717.  
  718.  
  719.  
  720. // BOleTranslateColor - poor man's replacement function for OleTranslateColor
  721. //     If we get an official license for OCX'es and the associated dll's,
  722. //     then we can remove this and use the real thing
  723. //
  724. //     The only thing this appears to be missing is error checking if a
  725. //     Palette index is specified and is out of range for the spec'ed palette
  726. extern "C"
  727.  
  728. HRESULT PASCAL FAR _export _loadds BOleTranslateColor (OLE_COLOR color,
  729.   HPALETTE hpal, COLORREF *pcolorref)
  730. {
  731.   long flag = 0xff000000 & color;
  732.   if (flag == 0x80000000)
  733.     *pcolorref = GetSysColor ((int) (0xff & color));
  734.   else if ((flag == 0) && (hpal))
  735.     *pcolorref = 0x02000000 | color;
  736.   else
  737.     *pcolorref = color;
  738.   return NOERROR;
  739. }
  740.