An introduction to COM connection points

Last time, we saw how to enumerate all the Internet Explorer and Explorer Windows and see what they are viewing. But that program printed static information. It didn't track the changes to the windows if the user clicked to another Web page or navigated to a different folder.

In order to hook that up, we need to understand the connection point model and the way events are expressed in dispatch interfaces. First, let's look at the connection point model. These topics confused me when I first met them (in part because I didn't do a good job of mentally separating them into two topics and instead treated it as one big topic), so I'm going to spend a few days trying to explain how it works, and then later this week, we'll actually hook things up. (And actually hooking it up is a lot easier than explaining it.)

Today, the connection point model.

Suppose you have a widget which can have multiple clients. The clients can communicate with the widget by invoking methods on the widget, like IWidget::Set­Color. but how does the widget communicate with its clients? Well, since this is COM, the first thing you need is an interface, say, IWidget­Client. The idea is that each client implements IWidget­Client, and when the widget needs to, say, notify each client that the color changed, it can invoke IWidget­Client::On­Color­Changed on each one. Each client can register with the widget for notifications.

The COM interface for standardizing the registration mechanism is IConnection­Point. A connection point acts as a middle-man between the widget and all its clients: Whenever the widget needs to notify all its clients, it tells the connection point to do it.

Widget Connection
Client A
Client B
Client C

A client registers with a connection point by calling IConnection­Point::Advise, and it unregisters by calling IConnection­Point::Unadvise.

Okay, that's great, but how do clients find the connection point so they can register with it?

The widget exposes an interface known as IConnection­Point­Container which provides access to an object's connection points. The client can call the IConnection­Point­Container::Find­Connection­Point method to get access to a specific connection point.

Here's how the pieces fit together:

// error checking elided for expository purposes

void IUnknown_FindConnectionPoint(IUnknown *punk,
                                  REFIID riid,
                                  IConnectionPoint **ppcp)
 // get the IConnectionPointContainer interface
 CComQIPtr<IConnectionPointContainer> spcpc(punk);

 // Locate the connection point
 spcpc->FindConnectionPoint(riid,  ppcp);

class CClient : public IWidgetClient
 IWidget *m_pWidget;
 DWORD m_dwCookie;

 // Find the IWidgetClient connection point
 CComPtr<IConnectionPoint> spcp;
                              IID_IWidgetClient, &spcp);

 // register with it
 spcp->Advise(this, &m_dwCookie);

 // Find the IWidgetClient connection point
 CComPtr<IConnectionPoint> spcp;
                              IID_IWidgetClient, &spcp);

 // unregister from it

After registering as a widget client, the CClient object will receive method calls on its IWidget­Client until it unregisters.

Now the widget and clients have two-way communication. If the clients want to initiate the communuication, it can call a method on IWidget. If the widget wants to initiate the communication, it can call a method on IWidget­Client.

Note that we've created a giant circular reference. The widget has a reference to its connection point (so it can tell it to fire a notification to all its clients), and the connection point has a reference to the widget client (so it can forward the notification along), and the widget client has a reference to the widget in its m_pWidget member. In order to break this cycle, you have to remember to explicitly call Unregister­Widget­Client when you are no longer interested in receiving widget notifications.

Note that even though the arrows in the diagram above flow from left to right (from widget to clients), that doesn't mean that the information flow is strictly left-to-right. You can pass information in the other direction via return values or output parameters.

For example, there might be a method on the IWidget­Client interface called Get­Color:

interface IWidgetClient : IUnknown
 HRESULT GetColor([out] COLORREF *pclr);

Since there can be multiple clients, the widget needs to have some sort of rule for deciding which client gets to choose the color. It might decide to ask each client in turn for a color, until one of them returns S_OK, and that client's color is used and no further clients are notified.

Or maybe there's a method called On­Save:

interface IWidgetClient : IUnknown
 HRESULT OnSave([in] IPropertyStorage *pps);

The convention here might be that all clients will be notified of the Save operation and they can write any additional information to the IProperty­Storage while handing the notification.

Those are just examples. Feel free to make up your own. The point is that just because the arrows go from the widget to the clients doesn't mean that information can't flow back the other way.

Most of the time, you have the simple case where a widget will expose a single connection point. In that case, the generality of the IConnection­Point­Container may seem unnecessary. But it allows you to add new connection points later. For example, you might have multiple client interfaces for different types of clients. You could have IWidget­Color­Client for clients that are interested only in color changes, and IWidget­Network­Client for clients that are interested only in monitoring the widget's network activity.

Or maybe you didn't plan on having multiple connection points originally, but in the second version of your product, you want to add additional methods to IWidget­Client, so you need to create IWidget­Client2, which means that you also need a new connection point for it.

Next time, a look at the special case where the client interface is a dispatch interface.

Comments (16)
  1. ChuckOp says:

    This showed up on my Favorites bar as "An introduction to COM connection points (new)" and I thought, "this is anything but new!  Maybe a dormant form of the Y2K issue, where everything from the 1990's is new."  I'm teasing of course.

  2. skSdnW says:

    The generality of IConnection­Point­Container also means that it is possible to write a generic helper function, and the shell already has one; shlwapi!ConnectToConnectionPoint (And some undocumented? IDispacth? IConnectionPoint helpers)

  3. SI says:

    There's also ATLAdvise / AtlUnadvise which presumably does that internally.

  4. CarlD says:

    Ah, good old Connection Points.  I made extensive use of these (and Monikers) back in the Windows 95/NT4 days on a desktop video product that was all built out of COM components (although we refused to deal with IDispatch interfaces – anyone wanting to play in our pool had to use a real language to write their components).  I recall writing something like ConnectToConnectionPoint way back then as well.

  5. ipoverscsi says:

    @CarlD: I've read the Component Object Model Specification v0.9 from cover to cover, and besides the actual low-level marshaling stuff, the only other part I never got was Monikers.  Oh, I know that they're supposed to be names to COM objects, but I never really groked what you were supposed to do with them.  Since you're the first person I've heard of who actually implemented them, care to share what you did with them?

  6. CarlD says:

    Oh, Monikers are cool!  In the video product, for example, I supported Monikers for just about everything, from a clip on the hard drives, to the master controller for the whole system.  The great thing about monikers (which is also a bad thing, depending on your POV) is that you can hide an arbitrarily object binding operation behind a moniker – the client just call CoGetObject and is blissfully unaware of what needs to go on behind the scenes to instantiate that object.  They were fun stuff, for sure!

  7. CarlD says:

    arrg!  s/arbitrarily object binding/arbitrarily complex object binding/

  8. CarlD says:

    Oh, and as far as what you're supposed to DO with Monikers: Their reason for being is OLE linking (not embedding).  It gives you a way to store a string (the Moniker) that refers to (a part of) another thing, like a range of cells in an Excel spreadsheet, or a clip on a hard drive (in a particular slot of a particular chassis of a particular FX machine connected to a particular network interface,…) and then use that string to retrieve a reference to the original object at a later time, without your program needing to know how to navigate through layers of containers to find the object.

  9. Klimax says:


    In the code CComPtr<IConnectionPoint> spcp;

    IUnknown_FindConnectionPoint(m_pWidget,ID_IWidgetClient, &spcp);

    How does one avoid/filter out debug assert on operator & of CComPtr?

    (I am doing same thing in my code, but with RSS Platform andI'd like to avoid hundreds of debug asserts, when it iterates over items in feeds.)

  10. Ens says:


    Sounds like you're re-using spcp.  Don't do that!  That's a memory leak!  That's why CComPtr complains about the & operator when spcp is non-NULL.  In Raymond's code it should not assert (CComPtr has a constructor which auto-nulls itself).

    If you must do that, call spcp.Release() beforehand.  But that starts to defeat the point of smart pointers.

  11. Medinoc says:

    @Klimax: You just posted the code of operator*, not operator&.

  12. Klimax says:


    There is no reuse. Debug_Assert(resp. ATLEnsure) complains on *null* pointer. (It's freshly constructed object)

    That code is identical to the one in article. (Checked that again)

    Code of ATL member function:

    T& operator*() const



     return *p;


  13. Klimax says:

    How can one tell I am in a hurry…

    T** operator&() throw()



           return &p;


    This should be right.

  14. CarlD says:

    @Ian – I completely agree.  One of the best technical introductions ever, and an indispensable book if you're diving deep into COM.

  15. Ian Boyd says:

    Speaking of COM connection points, it's time to plug Don Box's book Essential COM. It is probably the best technical introduction to any topic ever.

    In the 35 pages of the first chapter, Don Box explains the fundamental problem of trying to re-use classes. And through a series of simple steps of solving the problems: he invents COM before your very eyes. Once you realize the *why* of COM, the remaining 300 pages are obvious, and just detail Microsoft's implementation. That includes `IUnknown`, `IDispatch`, ProgIDs, ClassIDs, and yes even Connection Points.

  16. alexander says:

    and my first thought was we travelled back to the 90s for serial communicatiob ;)

Comments are closed.

Skip to main content