{"id":109198,"date":"2023-12-28T07:00:00","date_gmt":"2023-12-28T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109198"},"modified":"2023-12-29T09:08:07","modified_gmt":"2023-12-29T17:08:07","slug":"20231228-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20231228-00\/?p=109198","title":{"rendered":"On calling <CODE>Afx&shy;Connection&shy;Advise<\/CODE> with <CODE>bAddRef<\/CODE> set to <CODE>FALSE<\/CODE>"},"content":{"rendered":"<p>A customer had a question about the <code>Afx\u00adConnection\u00adAdvise<\/code> function when you set <code>bAddRef<\/code> to <code>FALSE<\/code>.<\/p>\n<p><a href=\"https:\/\/learn.microsoft.com\/cpp\/mfc\/reference\/connection-maps?view=msvc-170#afxconnectionadvise\"> According to the documentation<\/a>,<\/p>\n<blockquote class=\"q\">\n<pre>BOOL AFXAPI AfxConnectionAdvise(\r\n    LPUNKNOWN pUnkSrc,\r\n    REFIID iid,\r\n    LPUNKNOWN pUnkSink,\r\n    BOOL bRefCount,\r\n    DWORD FAR* pdwCookie);\r\n<\/pre>\n<p><i>bRefCount<\/i> <br \/>\nTRUE indicates that creating the connection should cause the reference count of <i>pUnkSink<\/i> to be incremented. FALSE indicates that the reference count should not be incremented.<\/p>\n<\/blockquote>\n<p>They are passing <code>FALSE<\/code> for <code>bAddRef<\/code> when they connect to an out-of-process COM server. What they found is that not only does this suppress the increment of the sink&#8217;s reference count, it in fact does a spurious <i>decrement<\/i> of the reference count, causing the sink to be destroyed.<\/p>\n<p>The customer looked at <a href=\"https:\/\/github.com\/mirror\/winscp\/blob\/3266c40c2d98ae659b1e8fe32a596697f8bdacf0\/libs\/mfc\/source\/ctlconn.cpp#L147\"> the source code for <code>Afx\u00adConnection\u00adAdvise<\/code><\/a> and saw that if you pass <code>FALSE<\/code> for <code>bAddRef<\/code>, then it calls <code>Release<\/code> on the sink after a successful registration.<\/p>\n<pre>BOOL AFXAPI AfxConnectionAdvise(LPUNKNOWN pUnkSrc, REFIID iid,\r\n    LPUNKNOWN pUnkSink, BOOL bRefCount, DWORD* pdwCookie)\r\n{\r\n    ASSERT_POINTER(pUnkSrc, IUnknown);\r\n    ASSERT_POINTER(pUnkSink, IUnknown);\r\n    ASSERT_POINTER(pdwCookie, DWORD);\r\n\r\n    BOOL bSuccess = FALSE;\r\n\r\n    LPCONNECTIONPOINTCONTAINER pCPC;\r\n\r\n    if (SUCCEEDED(pUnkSrc-&gt;QueryInterface(\r\n                    IID_IConnectionPointContainer,\r\n                    (LPVOID*)&amp;pCPC)))\r\n    {\r\n        ASSERT_POINTER(pCPC, IConnectionPointContainer);\r\n\r\n        LPCONNECTIONPOINT pCP;\r\n\r\n        if (SUCCEEDED(pCPC-&gt;FindConnectionPoint(iid, &amp;pCP)))\r\n        {\r\n            ASSERT_POINTER(pCP, IConnectionPoint);\r\n\r\n            if (SUCCEEDED(pCP-&gt;Advise(pUnkSink, pdwCookie)))\r\n                bSuccess = TRUE;\r\n\r\n            pCP-&gt;Release();\r\n\r\n            \/\/ The connection point just AddRef'ed us.  If we don't want to\r\n            \/\/ keep this reference count (because it would prevent us from\r\n            \/\/ being deleted; our reference count wouldn't go to zero),\r\n            \/\/ then we need to cancel the effects of the AddRef by calling\r\n            \/\/ Release.\r\n\r\n            if (bSuccess &amp;&amp; !bRefCount)\r\n                pUnkSink-&gt;Release();\r\n        }\r\n\r\n        pCPC-&gt;Release();\r\n    }\r\n\r\n    return bSuccess;\r\n}\r\n<\/pre>\n<p>It is apparent from the comment &#8220;The connection point just AddRef&#8217;ed us&#8221; that <code>Afx\u00adConnection\u00adAdvise<\/code> expects the <code>IConnectionPoint::<wbr \/>Advise<\/code> method to increment the reference count of the sink, because it is doing a bonus <code>Release<\/code> to counteract that <code>AddRef<\/code>.<\/p>\n<p>Is this a valid assumption?<\/p>\n<p>No.<\/p>\n<p>One case where <code>IConnectionPoint::<wbr \/>Advise<\/code> would not increment the reference count on the sink is the somewhat pathological case where the source knows that it will never call the event sink, so there&#8217;s no point remembering it.<\/p>\n<p>It&#8217;s like if somebody hands you a slip of paper and says, &#8220;Make sure to call this number if the antenna falls down,&#8221; but your television set doesn&#8217;t have an antenna at all. In that case, you can just throw away the slip of paper since you know you will never need it.<\/p>\n<p>Now, as I noted, this is a rather pathological case. After all, a connection point container is unlikely to advertise a connection point that does nothing.\u00b9<\/p>\n<p>The customer is encountering another case, though: Reference count aggregation through a proxy.<\/p>\n<p>When a COM object is passed to another context (in this case, to another process), the client receives a proxy object. To reduce cross-context chatter, each proxy retains a single reference to the real object on the other side, and any local reference counts are aggregated in the proxy.<\/p>\n<p>For example, suppose we have an object on the server with a single reference held by a client process.<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"An object with refcount 1 on the server. It is referenced by an object proxy in the client. The object proxy's refcount is 1. The proxy is in turn referenced by the pObject variable in the client application.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>Server<\/td>\n<td>&nbsp;<\/td>\n<td>Client<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\">pObject<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\">Object<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Object proxy<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In these diagrams, heavy arrows are those that cross process boundaries.<\/p>\n<p>If the client calls <code>pObject-&gt;AddRef()<\/code> to increment the reference count, COM merely increments the reference count of the proxy. It doesn&#8217;t send an <code>AddRef<\/code> call over the wire to the server. After the client calls <code>AddRef<\/code>, we have this:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The same the previous diagram, except that the refcount of the object proxy has been incremented from 1 to 2.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>Server<\/td>\n<td>&nbsp;<\/td>\n<td>Client<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px currentcolor;\">pObject<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\">Object<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Object proxy<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 2 <\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Notice that the reference count of the proxy has gone up to 2, but there is no change to the reference count of the original object on the server. The proxy aggregates all the references from the client, and only a single reference count is retained from the proxy to the original object. When the proxy&#8217;s reference count drops to zero, then the proxy is destroyed, and only then does the proxy send a <code>Release<\/code> to the original object.<\/p>\n<p>Okay, now we can set up our story. Suppose you register the same sink against multiple connection points in a remote process. From the point of view of the sink, those remote processes are all clients. (Of course, from the point of view of the connection points, your process is the client.)<\/p>\n<pre>ComPtr&lt;IDispatch&gt; sink = \u27e6 create a sink \u27e7;\r\nComPtr&lt;IConnectionPoint&gt; point1 = \u27e6 some remote object \u27e7;\r\nComPtr&lt;IConnectionPoint&gt; point2 = \u27e6 some remote object \u27e7;\r\n\r\nDWORD cookie1, cookie2;\r\npoint1-&gt;Advise(sink.Get(), &amp;cookie1);\r\npoint2-&gt;Advise(sink.Get(), &amp;cookie2);\r\n<\/pre>\n<p>This is what things look like before the first <code>Advise<\/code>:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"In the app process (labeled &quot;you&quot;), point1 references a point1 proxy object whose refcount is 1. The proxy object references a point1 object in the remote process (labeled &quot;them&quot; whose refcount is 1. Similar, in the app process, point2 references a point2 proxy object whos erefcount 1, and which in turn references a point2 object in the remote process with refcount 1. Finally, in the app process, sink references a sink object whose refcount is 1.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = 1<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The only reference to the sink object is the one you hold in the <code>sink<\/code> local variable.<\/p>\n<p>After the first <code>Advise<\/code>, the Point1 object now holds a reference to the Sink Object, through its own proxy on their side.<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The point1 object in the remote process now has a reference to a newly-created sink proxy object in the remote process, with refcount 1. That sink proxy object in the remote process references the app's sink object, whose refcount has gone up from 1 to 2.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\u21d3<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 2 <\/span><\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\ud83e\udc44<\/div>\n<\/td>\n<td style=\"border: solid 1px currentcolor; position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">Sink Proxy<br \/>\nrefcount = 1<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>With the second <code>Advise<\/code>, things get interesting:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The point2 object in the remote process now has a reference to the same sink proxy object in the remote process, whose refcount has gone up from 1 to 2. There is no change to the sink object in the app process, whose refcount is still 2.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = 2<\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Proxy<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 2 <\/span><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\u21d1<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>COM realizes that it already has a proxy for the sink object on their side, so instead of creating a second proxy, it just reuses the existing one. When <code>Point2<\/code> calls <code>AddRef<\/code> to retain a reference to the sink, the <code>AddRef<\/code> is cached by the proxy, and no <code>AddRef<\/code> happens on the original sink.<\/p>\n<p>What we did above was roughly equivalent to calling <code>Afx\u00adConnection\u00adAdvise<\/code> with <code>bAddRef<\/code> set to <code>TRUE<\/code>.<\/p>\n<p>Now let&#8217;s do it again with <code>bAddRef<\/code> set to <code>FALSE<\/code>.<\/p>\n<pre>ComPtr&lt;IDispatch&gt; sink = \u27e6 create a sink \u27e7;\r\nComPtr&lt;IConnectionPoint&gt; point1 = \u27e6 some remote object \u27e7;\r\nComPtr&lt;IConnectionPoint&gt; point2 = \u27e6 some remote object \u27e7;\r\n\r\nDWORD cookie1, cookie2;\r\npoint1-&gt;Advise(sink.Get(), &amp;cookie1);\r\nsink-&gt;Release(); \/\/ New!\r\n\r\npoint2-&gt;Advise(sink.Get(), &amp;cookie2);\r\nsink-&gt;Release(); \/\/ New!\r\n<\/pre>\n<p>Everything is the same through the first <code>Advise<\/code>:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The point1 object in the remote process now has a reference to a newly-created sink proxy object in the remote process, with refcount 1. That sink proxy object in the remote process references the app's sink object, whose refcount has gone up from 1 to 2.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\u21d3<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 2 <\/span><\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\ud83e\udc44<\/div>\n<\/td>\n<td style=\"border: solid 1px currentcolor; position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">Sink Proxy<br \/>\nrefcount = 1<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>But this time, since <code>bAddRef<\/code> is <code>FALSE<\/code>, the <code>Afx\u00adConnection\u00adAdvise<\/code> function tries to undo the <code>AddRef<\/code> performed by the connection point by doing a <code>sink-&gt;Release()<\/code>.<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The refcount on the sink object has dropped from 2 back to 1.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 1 <\/span><\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Proxy<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The sink object&#8217;s reference count is back down to 1, so it&#8217;s as if the sink proxy&#8217;s <code>AddRef<\/code> had never occurred.<\/p>\n<p>Now we do the second <code>Advise<\/code>:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The point2 object in the remote process now has a reference to the same sink proxy object in the remote process, whose refcount has gone up from 1 to 2. There is no change to the sink object in the app process, whose refcount is still 1.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Proxy<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 2 <\/span><\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">\u21d1<\/div>\n<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <code>AddRef<\/code> from the second connection point to the sink is cached in the proxy and is not communicated to the original sink in the server process.<\/p>\n<p>Nevertheless, <code>Afx\u00adConnection\u00adAdvise<\/code> sees that <code>bAddRef<\/code> is set to <code>FALSE<\/code>, so it performs a second <code>sink-&gt;Release()<\/code>, and bad things happen:<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" title=\"The reference count of the sink object in the app has dropped from 1 to 0.\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Object<br \/>\nrefcount = <span style=\"border: solid 1px currentcolor; position: relative;\"> <span style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/span> 0 <\/span><\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Proxy<br \/>\nrefcount = 2<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d1<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Oh no, the sink object&#8217;s reference count has dropped to zero! This destructs the sink, leaving the <code>sink<\/code> variable and the sink proxy with pointers to freed memory.<\/p>\n<table style=\"border-collapse: separate; text-align: center;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\" colspan=\"3\">You<\/td>\n<td style=\"width: 1em;\">\u00a0<\/td>\n<td style=\"border: solid 1px currentcolor; border-bottom: none;\">Them<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point1<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point1 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d3<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>sink<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: dashed 1px currentcolor; position: relative;\">\n<div style=\"position: absolute; top: 0; left: 0; background: currentcolor; opacity: 15%; width: 100%; height: 100%;\">\u00a0<\/div>\n<div style=\"width: 100%; height: 100%;\">(freed memory)<\/div>\n<\/td>\n<td>\ud83e\udc44<\/td>\n<td style=\"border: solid 1px currentcolor;\">Sink Proxy<br \/>\nrefcount = 2<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>\u21d1<\/td>\n<\/tr>\n<tr>\n<td style=\"border: solid 1px currentcolor;\"><code>point2<\/code><\/td>\n<td>\u21d2<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Proxy<br \/>\nrefcount = 1<\/td>\n<td>\ud83e\udc46<\/td>\n<td style=\"border: solid 1px currentcolor;\">Point2 Object<br \/>\nrefcount = 1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The original authors of <code>Afx\u00adConnection\u00adAdvise<\/code> made an invalid assumption, namely that a successful <code>Advise<\/code> necessarily increments the reference count on the sink. In the case of remote connection points, the reference counts of those remote connection points are aggregated on the remote side, and only a single reference count is maintained on the server side. The <code>Release()<\/code> call thinks it is counteracting the <code>AddRef()<\/code> on the client side, but really it&#8217;s counteracting a nonexistent <code>AddRef()<\/code> on the server side.<\/p>\n<p>You break the COM rules at your own peril.<\/p>\n<p>Moral of the story: This is a design flaw in <code>Afx\u00adConnection\u00adAdvise<\/code>. Do not call it with <code>bAddRef<\/code> set to <code>FALSE<\/code>. Instead of playing games with COM reference counts trying to simulate a weak reference, use a proper weak reference to the sink.<\/p>\n<p>\u00b9 And it may end up not being a valid implementation anyway, because the connection point is expected to produce those clients in response to <code>IConnectionPoint::<wbr \/>Enum\u00adConnections<\/code>, so it is obligated to retain references to them even though it has no use for them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Playing fast and loose, and eventually you get burnt.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-109198","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Playing fast and loose, and eventually you get burnt.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109198","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=109198"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109198\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=109198"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109198"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109198"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}