Undocumented Corner
by George Shepherd and Scot Wingo


Listing One
ISomeInterface* pSomeInterface = NULL;
HRESULT hr;

hr = CoCreateInstance(CLSID_SomeObject, NULL, CLSCTX_ALL, 
                                 IID_ISomeInterface, *pSomeInterface);
if(SUCCEEDED(hr)) {
   pSomeInterface->Function1();
   pSomeInterface->Function2();
   pSomeInterface->Release();
}

Listing Two
interface IConnectionPoint : IUnknown {
  HRESULT GetConnectionInterface(IID *pIID) = 0;
  HRESULT GetConnectionPointContainer(IConnectionPointContainer **ppCPC) = 0;
  HRESULT Advise(IUnknown *pUnk, DWORD *pdwCookie) = 0;
  HRESULT Unadvise(DWORD dwCookie) = 0;
  HRESULT EnumConnections(IEnumConnections **ppEnum) = 0;
};

Listing Three
interface IConnectionPointContainer : IUnknown {
   HRESULT EnumConnectionPoints(IEnumConnectionPoints **ppEnum) = 0;
   HRESULT FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP) = 0;
};

Listing Four
class CCmdTarget : public CObject {
 ...
   EnableConnections();
   DECLARE_CONNECTION_MAP()
   struct XConnPtContainer {
      DWORD m_vtbl; // place-holder for IConnectionPointContainer vtable
   } m_xConnPtContainer;
   virtual BOOL GetExtraConnectionPoints(CPtrArray* pConnPoints);
   virtual LPCONNECTIONPOINT GetConnectionHook(const IID& iid);

   friend class COleConnPtContainer;
 ...
};

Listing Five
void CCmdTarget::EnableConnections() {
   // construct an COleConnPtContainer instance just to get to the vtable
   COleConnPtContainer cpc;
   // copy the vtable (and other data) to make sure it is initialized
   m_xConnPtContainer.m_vtbl = *(DWORD*)&cpc;
}

Listing Six
class COleConnPtContainer : public IConnectionPointContainer
{
public:
   STDMETHOD_(ULONG, AddRef)();
   STDMETHOD_(ULONG, Release)();
   STDMETHOD(QueryInterface)(REFIID, LPVOID*);
   STDMETHOD(EnumConnectionPoints)(LPENUMCONNECTIONPOINTS* ppEnum);
   STDMETHOD(FindConnectionPoint)(REFIID iid, LPCONNECTIONPOINT* ppCP);
};


2


