Click here to Skip to main content
13,256,301 members (49,454 online)
Click here to Skip to main content
Add your own
alternative version


44 bookmarked
Posted 5 Jun 2002

Sinking connection points in C++ objects

, 5 Jun 2002
Rate this:
Please Sign up or sign in to vote.
Sometimes it would be nice to be able to use a simple C++ object as a sink for Connection Point notifications. This article shows you how.

The following source was built using Visual Studio 6.0 SP5 and Visual Studio .Net. You need to have the Microsoft NetMeeting SDK installed. This is available from here or as part of recent versions of the Microsoft Platform SDK.

Sinking connection points in C++ objects.

Many COM objects provide events to their clients by means on Connection Points. A Connection Point is a generalised method of allowing clients to register a COM interface so that the object can notify them of things that they may be interested in. The problem is, sometimes you will be developing code that simply uses COM objects and doesn't implement any COM objects itself, yet you still need to be able to register a COM object to receive notifications via a Connection Point. This article shows you how you can use Connection Points and sink events from them without needing to use ATL or MFC or expose real COM objects from your application.

Registering for notifications

Suppose we want to use a COM object that provides notifications via Connection Points, the NetMeeting Conference Manager object for example. Our application will create an instance of the Conference Manager object and manipulate it via its interface, we will monitor the events it generates by registering a connection point to receive events generated by the INmManagerNotify interface. The INmManagerNotify interface is shown below:

interface INmManagerNotify : IUnknown
   typedef [unique] INmManagerNotify *LPNMMANAGERNOTIFY;

      [in] CONFN uNotify);

   HRESULT ConferenceCreated(
      [in] INmConference *pConference);

   HRESULT CallCreated(
      [in] INmCall *pCall);

We don't want to use MFC or ATL and the resulting program will be a console application using straight C++ and COM client APIs. Our problem is that our application simply uses COM, it doesn't expose any COM functionality itself and we don't want to add the complexity of being able to serve real COM objects simply so that we can consume events from a Connection Point. What we'd like to do is simply implement the methods of the notification interface and ask the Conference Manager object to call us when notifications occur without worrying about the necessary plumbing.

A reusable, self contained, notification class

The work involved to hook up a connection point is fairly straight forward and MFC and ATL could both provide some help if we were using them, but since we're not we have to do the work ourselves. Given the IUnknown of a connectable object we need to obtain a pointer to its IConnectionPointContainer interface and from that obtain a pointer to the required connection point interface. Once we have that, we simply call the Advise() member function, pass our sink interface and keep hold of the cookie that is returned as we need it to disconnect. If we wrap this work in a class we can make sure that we disconnect in the destructor. The class might look something like this:

class CNotify
   public :


      void Connect(
         IUnknown *pConnectTo,
         REFIID riid,
         IUnknown *pIUnknown);

      void Disconnect();

      bool Connected() const;

      private :

         DWORD m_dwCookie;
         IUnknown *m_pIUnknown;
         IConnectionPoint *m_pIConnectionPoint;
         IConnectionPointContainer *m_pIConnectionPointContainer;

Connecting can be as simple as calling Connect() and passing the connectable object, the IID of the connection point that we wish to connect to and our sink interface. Disconnecting is equally easy.

The class above is useful but it doesn't solve our problem. We still need to have a COM object to pass as our sink interface and we don't have one, or want to build one. However, it's relative easy to put together a template class that's derived from our CNotify class and fills in the missing functionality. The template looks something like this:

template <class NotifyInterface, const GUID *InterfaceIID> class TNotify :
   private CNotify,
   public NotifyInterface
   public :

      void Connect(IUnknown *pConnectTo)
         CNotify::Connect(pConnectTo, *InterfaceIID, this);

      using CNotify::Disconnect;
      using CNotify::Connected;

      // IUnknown methods
         return 2;

         return 1;

         HRESULT hr = S_OK;

         if (riid == IID_IUnknown)
            *ppvObj = (IUnknown *)this;
         else if (riid == *InterfaceIID)
            *ppvObj = (NotifyInterface *)this;
            hr = E_NOINTERFACE;
            *ppvObj = NULL;

         return hr;

TNotify is used as a base class for your notification sink object, it derives from the sink interface that you want to implement and provides the IUnknown methods for you. You simply have to implement the sink interface methods and then call Connect() and pass the connectable object that you wish to connect to. Your sink object might look like this:

class MyConferenceManager : private TNotify<INmManagerNotify, &IID_INmManagerNotify>
   public :

         return S_OK;

      HRESULT STDMETHODCALLTYPE ConferenceCreated(INmConference *pConference)
         return S_OK;

         return S_OK;

You need to be aware of a few things when using your sink object. The first is that the COM object that is constructed for you by the TNotify base class expects to reside on the stack, or, at least, it doesn't expect COM to manage its lifetime (notice the implementation of AddRef() and Release()). Secondly the sink object maintains references to the connectable object's interfaces, so that it can disconnect when you call Disconnect() or, if you don't, when it gets destroyed. Finally, since the sink object could make COM calls when it is destroyed you need to make sure that COM is still initialised at that point - so no calling CoUninitialize() before you destroy your sink object.

The example code

The example code is slightly more complex than that shown above. Because of all the type mapping that you tend to have to do to call COM methods from straight C++ we tend to wrap the COM objects in thin C++ wrappers. We do this with the interface that we obtain for the INmManager object and we use the same wrapper to sink the events. This leaves us with a single C++ object that exposes both the INmManager interface which translates the argument types to C++ friendly types and throws exceptions on method failures, and also exposes the INmManagerNotify interface to notify us of events that occur on the object. As you'll see, creating and using the NetMeeting Conference Manager COM object and wiring it up to receieve notification events is as simple this:

   class MyConferenceManager : public CNmConferenceManager
      public :
         // implement some or all of the INmManagerNotify methods to do 
         // stuff when the notifications happen...


   if (MyConferenceManager::IsNmInstalled())
      MyConferenceManager confManager;

      ULONG options = NM_INIT_NORMAL;
      ULONG capabilities = NMCH_ALL;

      confManager.Initialize(options, capabilities);


Since the CNmConferenceManager object implements all of the notification interface and just does nothing, i.e. it returns S_OK to all methods, our derived class can choose to simply override the notifications that it wants to handle. Creating our object initialises COM, so that COM remains initialised until our object is no more, creates the NetMeeting Conference Manager COM object and connects up the notification sink. We can then simply call methods on the object and recieve notifications back.

Revision history

  • 30th May 2002 - Initial revision.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Len Holgate
Software Developer (Senior) JetByte Limited
United Kingdom United Kingdom
Len has been programming for over 30 years, having first started with a Sinclair ZX-80. Now he runs his own consulting company, JetByte Limited and has a technical blog here.

JetByte provides contract programming and consultancy services. We can provide experience in COM, Corba, C++, Windows NT and UNIX. Our speciality is the design and implementation of systems but we are happy to work with you throughout the entire project life-cycle. We are happy to quote for fixed price work, or, if required, can work for an hourly rate.

We are based in London, England, but, thanks to the Internet, we can work 'virtually' anywhere...

Please note that many of the articles here may have updated code available on Len's blog and that the IOCP socket server framework is also available in a licensed, much improved and fully supported version, see here for details.

You may also be interested in...


Comments and Discussions

QuestionMissing template arguments? Pin
mxcl9-Aug-06 2:35
membermxcl9-Aug-06 2:35 
AnswerRe: Missing template arguments? Pin
Len Holgate9-Aug-06 12:31
memberLen Holgate9-Aug-06 12:31 
GeneralRe: Missing template arguments? Pin
mxcl10-Aug-06 0:23
membermxcl10-Aug-06 0:23 
Yes the code is great and very useful. It's helped me plenty Smile | :)
GeneralHello , Pin
belkhiri6-Apr-06 9:22
memberbelkhiri6-Apr-06 9:22 
GeneralIDispatch Pin
OlaSjöstedt30-Mar-04 3:15
memberOlaSjöstedt30-Mar-04 3:15 
GeneralRe: IDispatch Pin
OlaSjöstedt4-Apr-04 23:24
memberOlaSjöstedt4-Apr-04 23:24 
GeneralRe: IDispatch Pin
Len Holgate5-Apr-04 8:56
memberLen Holgate5-Apr-04 8:56 
GeneralRe: IDispatch Pin
OlaSjöstedt6-Apr-04 0:49
memberOlaSjöstedt6-Apr-04 0:49 
GeneralRe: IDispatch Pin
OlaSjöstedt6-Apr-04 0:51
memberOlaSjöstedt6-Apr-04 0:51 
GeneralI maybe wrong Pin
igor196025-Sep-03 12:44
memberigor196025-Sep-03 12:44 
GeneralRe: I maybe wrong Pin
Len Holgate25-Sep-03 13:16
memberLen Holgate25-Sep-03 13:16 
GeneralRe: I maybe wrong Pin
igor196025-Sep-03 13:18
memberigor196025-Sep-03 13:18 
QuestionHow about passing C++ object(SAFEARRAY) as Event parameter? Pin
i--13-Aug-03 3:01
memberi--13-Aug-03 3:01 
AnswerRe: How about passing C++ object(SAFEARRAY) as Event parameter? Pin
cadi28-Oct-03 5:09
membercadi28-Oct-03 5:09 
GeneralOut-of-proc server Pin
Sidra Ahmed18-Feb-03 21:32
sussSidra Ahmed18-Feb-03 21:32 
GeneralRe: Out-of-proc server Pin
Len Holgate19-Feb-03 9:27
memberLen Holgate19-Feb-03 9:27 
GeneralAdvice required Pin
Anonymous9-Jan-03 2:05
sussAnonymous9-Jan-03 2:05 
GeneralRe: Advice required Pin
Len Holgate9-Jan-03 11:04
memberLen Holgate9-Jan-03 11:04 
Generalit does not deal with dispinterface Pin
MaximE26-Sep-02 9:46
memberMaximE26-Sep-02 9:46 
GeneralRe: it does not deal with dispinterface Pin
Len Holgate26-Sep-02 13:48
memberLen Holgate26-Sep-02 13:48 
GeneralRe: it does not deal with dispinterface Pin
MaximE28-Sep-02 14:22
memberMaximE28-Sep-02 14:22 
GeneralTruly excellent you seem like the person to ask! Pin
Bo Carleon22-Jul-02 14:51
sussBo Carleon22-Jul-02 14:51 
GeneralRe: Truly excellent you seem like the person to ask! Pin
Len Holgate22-Jul-02 22:29
memberLen Holgate22-Jul-02 22:29 
GeneralJust a bit more help, please! Pin
J.G. Hattingh16-Jun-02 23:49
memberJ.G. Hattingh16-Jun-02 23:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.171114.1 | Last Updated 6 Jun 2002
Article Copyright 2002 by Len Holgate
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid