<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Cluebat-man to the rescue : ATL</title><link>http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx</link><description>Tags: ATL</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Practical ATL: Solving the race condition in CAtlExeModuleT</title><link>http://msmvps.com/blogs/vandooren/archive/2009/04/15/solving-the-race-condition-in-catlexemodulet.aspx</link><pubDate>Wed, 15 Apr 2009 12:40:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1687784</guid><dc:creator>vanDooren</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1687784</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1687784</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/04/15/solving-the-race-condition-in-catlexemodulet.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;When I was spelunking through the ATL header for my previous articles (the class object plumbing) I discovered that there is a serious race condition in the server lifetime management.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I contacted the Microsoft C++ folks, and someone from the libraries group told me that this problem has already been fixed in the next release of Visual C++.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;But since the issue still exists in all current ATL projects, I decided to write something about it and publish the fix which will circumvent the problem in the recent versions of ATL (7.0 and upwards if I am correct).&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The problem&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The module lock count of an ATL COM server is managed in the CAtlExeModuleT&amp;lt;T&amp;gt; class. It is this lock count that keeps the server alive as long as it is nonzero.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The CAtlExeModuleT&amp;lt;T&amp;gt; class manages its reference count via the&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CComGlobalsThreadModel class increment and decrement methods. CComGlobalsThreadModel is a typedef for CComMultiThreadModel so these methods map to InterlockedIncrement and InterlockedDecrement&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The last module lock is released if&lt;br /&gt;- the class object itself has no more external connections (IExternalConnection), and&lt;br /&gt;- there are no more object instances.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As soon as the final module lock is released (module refcount is 0), the shutdown of the server is initiated, which will happen through either a WM_QUIT message or a win32 event object. In both cases there is a time window between the triggering of the shutdown, and the actual call to CoRevokeClassObject. This time window can be several seconds.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This time window causes a race condition between the server (which is already dying at that point) trying to revoke the class object, and a hypothetical client, requesting an interface pointer to the class object. Depending on how the race turns out, the client might end up with an S_OK HRESULT from CoGetClassObject, and an invalid interface pointer. This will cause a critical problem in the client, and may cause an application&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;crash.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The solution&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The proper way to manage the server lifetime is to use CoAddRefServerProcess and CoReleaseRefServerProcess to manage the module lockcount. Those functions will (according to MSDN http://msdn.microsoft.com/en-us/library/aa910552.aspx) suspend all class objects when the reference count drops to 0, in an atomic operation.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In that case, the server starts dying AFTER all class objects are suspended. Any incoming client request for the class object will spawn a new server process after the dying server has finished revoking its class objects.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The fix&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The code for fixing this is simple. I simply created a new class that inherits from CAtlExeModuleT&amp;lt;T&amp;gt; and then overrides the Lock and Unlock methods.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;template&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; &amp;lt;&lt;span style="color:blue;"&gt;typename&lt;/span&gt; T&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;class&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CAtlExeModuleT_NoRace : &lt;span style="color:blue;"&gt;public&lt;/span&gt; CAtlExeModuleT&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;public&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;typedef&lt;/span&gt; CAtlExeModuleT&amp;lt;T&amp;gt; base;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;#if&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; _ATL_VER &amp;lt; 0x0A00&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;LONG Lock(&lt;span style="color:blue;"&gt;void&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CoAddRefServerProcess();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; base::Lock();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;LONG Unlock(&lt;span style="color:blue;"&gt;void&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CoReleaseServerProcess();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; base::Unlock();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;#else&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;//removed compiler messages&lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;#endif&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I use CoxxxxServerProcess functions to explicitly manage the class object registration, and then I delegate to the base class which maintains its own reference count.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The reason I do that is that the base::Unlock function is the one which triggers the module shutdown, and I don&amp;rsquo;t want to mess with that. And Unlock works only when paired with Lock, so the only thing I really need to do is to call the CoxxxxServerProcess routines to prevent possible activation requests. The rest is still done by CAtlExeModuleT&amp;lt;T&amp;gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I put a compiler condition around my implementation of the new Lock and Unlock methods, because they are only needed for current versions of ATL. The next version of ATL won&amp;rsquo;t have this problem, so it would be dangerous to meddle with the reference counting, especially since I cannot predict what side effects this may have.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The conditional compilation allows you to safely upgrade the project to the next version of ATL. The compiler messages which show up in the compiler output inform you that it is no longer needed to inherit from CAtlExeModuleT_NoRace as shown below:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;class&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CStuff_ServerModule : &lt;span style="color:blue;"&gt;public&lt;/span&gt; CAtlExeModuleT&lt;span style="background:silver;mso-highlight:silver;"&gt;_NoRace&lt;/span&gt;&amp;lt; CStuff_ServerModule &amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;public&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; :&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;DECLARE_LIBID(LIBID_Stuff_ServerLib)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;DECLARE_REGISTRY_APPID_RESOURCEID(IDR_STUFF_SERVER, &lt;span style="color:#a31515;"&gt;&amp;quot;{597B5DFF-DACE-42B0-9E49-54A09C10B2BB}&amp;quot;&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The only thing you have to do to use my new module class is to include the header and change CAtlExeModuleT to CAtlExeModuleT_NoRace.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And if you upgrade the project to VC10, then you can simply change it back as indicated by the compiler output messages that are printed out when the compiler parses my class.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Conclusion&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I was surprised that this bug was still in the ATL headers after all these years. When I contacted the VC++ team I was half expecting them to tell me that I had missed something. This issue is what caused CoAddRefServerProcess to be created after all, over a decade ago, so a COM programmer implementing lifetime management should be aware of it.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;However, the modular and hierarchical nature of ATL made it easy to fix this problem, so I guess that is a plus for ATL. And mistakes happen. It is always a bit painful if it happens in widely used libraries, but I too have had my share of whoopsies over the years. It is sad but it happens.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The header file with the fix is attached to this blog post under the MIT license.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1687784" width="1" height="1"&gt;</description><enclosure url="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.01.68.77.84/AtlExeModuleT_5F00_NoRace.zip" length="1536" type="application/x-zip-compressed" /><category domain="http://msmvps.com/blogs/vandooren/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item><item><title>Practial ATL: Implementing a non-standard class object</title><link>http://msmvps.com/blogs/vandooren/archive/2009/02/20/practial-atl-implementing-a-non-standard-class-object.aspx</link><pubDate>Fri, 20 Feb 2009 21:03:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1673035</guid><dc:creator>vanDooren</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1673035</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1673035</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/02/20/practial-atl-implementing-a-non-standard-class-object.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In my previous article in this series, I explained how class objects are associated with COM objects, and how it all fits together.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Armed with that knowledge, I can now demonstrate how to provide a custom class object that will allow us to support parameterized construction.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;If you haven&amp;rsquo;t already read my previous article on class objects, please do so first because I am going to assume you did &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The non-standard class object interface: IStuffCreator&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;A class object can have any interface you want, just like the COM object we have created earlier. It is just another COM object after all. My custom interface looks like this:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;[&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;object&lt;/span&gt;,&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;uuid&lt;/span&gt;(6DD69CDB-3128-432b-B335-773A287E6F06),&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;oleautomation&lt;/span&gt;,&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;helpstring&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;IStuffCreator Interface&amp;quot;&lt;/span&gt;),&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;pointer_default&lt;/span&gt;(&lt;span style="color:blue;"&gt;unique&lt;/span&gt;)&lt;br /&gt;]&lt;br /&gt;&lt;span style="color:blue;"&gt;interface&lt;/span&gt; IStuffCreator : IUnknown {&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;id&lt;/span&gt;(1), &lt;span style="color:blue;"&gt;helpstring&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;method MakeMeAStuff&amp;quot;&lt;/span&gt;)]&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HRESULT MakeMeAStuff(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;in&lt;/span&gt;] BSTR name,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;in&lt;/span&gt;] REFIID riid,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;out&lt;/span&gt;, &lt;span style="color:blue;"&gt;iid_is&lt;/span&gt;(riid)] IUnknown** ppStuff);&lt;br /&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The bits between the square brackets are the attributes that are applied to this interface. &amp;lsquo;Object&amp;rsquo; specifies that it is a COM interface. The uuid specifies the GUID that identifies the interface. &amp;lsquo;oleautomation&amp;rsquo; specifies that the arguments being used are all automation compatible. The meaning of&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&amp;lsquo;helpstring&amp;rsquo; is pretty obvious, and pointer_default specifies the assumptions that the marshaller can make about pointers.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you want to know the details about it, then have a look in MSDN for MIDL attributes.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The interface itself is very simple. Instead of deriving from IDispatch like the IStuff interface, this interface derives from IUnknown. Deriving from IDispatch would only complicate matters without any benefit.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The interface has only one method, which is responsible for handing out new stuffs. &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The parameter that will be used for constructing the CStuff instance itself is the &amp;lsquo;name&amp;rsquo; parameter. If the CStuff would need multiple parameters, they would have to be part of the parameter list so that they can be used at the time of construction. The riid and ppStuff parameters have the same meaning as those of CoCreateInstance.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The declaration of CStuffCreator&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If we want to implement this interface, we add a new C++ class with the name &amp;lsquo;CStuffCreator&amp;rsquo; to our project, and implement our IStuffCreator interface&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;class&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CStuffCreator:&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; IStuffCreator,&lt;br /&gt;&lt;span style="color:blue;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;public&lt;/span&gt; CComObjectRootEx&amp;lt;CComGlobalsThreadModel&amp;gt;&lt;br /&gt;{&lt;br /&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CStuffCreator(&lt;span style="color:blue;"&gt;void&lt;/span&gt;){}&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;virtual&lt;/span&gt; ~CStuffCreator(&lt;span style="color:blue;"&gt;void&lt;/span&gt;){}&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;BEGIN_COM_MAP(CStuffCreator)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;COM_INTERFACE_ENTRY(IStuffCreator)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;END_COM_MAP()&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;//IStuffCreator methods&lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;HRESULT STDMETHODCALLTYPE MakeMeAStuff(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;BSTR name,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;REFIID riid,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IUnknown **ppStuff);&lt;br /&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// helper method&lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; SetVoid(&lt;span style="color:blue;"&gt;void&lt;/span&gt;* pv);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;_ATL_CREATORFUNC* m_pfnCreateInstance;&lt;br /&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As you can see, it is pretty simple. The CComObjectRootEx base class helps with reference counting, and is the same that is used by the other COM objects in our project.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;We add IStuffCreator to the interface map using the ATL macros, and then we simply declare the single &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;MakeMeAStuff&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; method that we need to implement.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The SetVoid method and the function pointer are part of the default C++ interface for class objects in ATL, and are explained in my previous article.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The implementation&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The implementation of CStuffCreator is even simpler than the declaration:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;HRESULT STDMETHODCALLTYPE CStuffCreator::MakeMeAStuff( &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;BSTR name,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;REFIID riid,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;IUnknown **ppStuff)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IUnknown&amp;gt; newStuff;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;HRESULT hr = m_pfnCreateInstance(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;NULL, &lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IUnknown), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)&amp;amp;newStuff);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; newStuff-&amp;gt;QueryInterface(riid, (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)ppStuff);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;void&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CStuffCreator::SetVoid(&lt;span style="color:blue;"&gt;void&lt;/span&gt;* pv)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Ignore the &amp;lsquo;name&amp;rsquo; parameter for now. That will be used when we are going to initialize the new instance. The bare functionality of our class object is to use the function pointer to create a new instance. I could have done this in 1 step instead of 2 (the QueryInterface isn&amp;rsquo;t necessary at this point) but this way I can slide in some additional functionality later on.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And you can see now that the class object will receive the creator function pointer via the &amp;lsquo;SetVoid&amp;rsquo; method. This mechanism was explained in my previous article.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Parameterized construction&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The point of using a non-standard class object in this demonstration was to be able to create objects that need some sort of initialization before the client has access to them. Normally, ATL supports only default constructors using, because IClassFactory is a generic interface.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;For parameterized constructors, we are going to have to do something special.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;There are essentially 2 ways we can do this. The first is to change CStuff to have a parameterized constructor. But ATL can&amp;rsquo;t handle that, and it would mean we have to abandon the incredible convenience of being able to use the ATL::Creator&amp;lt;T&amp;gt; class, ATL::CComObject class, and other helper classes that take the pain out of COM.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Don Box wrote an article about parameterized construction, many years ago, and this was the approach he took. Of course, ATL was much simpler in those days, and abandoning it was perhaps less of an inconvenience.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The approach I am taking is much simpler: I cheat!&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;That&amp;rsquo;s right. I cheat. I am &lt;i style="mso-bidi-font-style:normal;"&gt;not&lt;/i&gt; going to implement parameterized constructors. I am going to fake it. But from the client&amp;rsquo;s point of view, it&amp;rsquo;s going to look exactly the same, so he won&amp;rsquo;t mind. And from the server&amp;rsquo;s point of view, it will be much simpler to implement, so everybody wins.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The second approach to implementing parameterized construction is to implement an internal interface on CStuff, which will be used for initializing it. The new CStuff instance will not be accessible to anyone until the first interface pointer is handed out by the class object. And we are the ones implementing the class interface, so we can make sure that the new instance is initialized properly before it is released into the wild.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The initialization interface&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The interface for initializing a CStuff is pretty simple (I left out the header for clarity):&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;interface&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; IStuffInit : IUnknown {&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;id&lt;/span&gt;(1), &lt;span style="color:blue;"&gt;helpstring&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;method InitStuffInstance&amp;quot;&lt;/span&gt;)]&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HRESULT InitStuffInstance(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;in&lt;/span&gt;] BSTR Name);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Our CStuff instances are supposed to have a name, so that&amp;rsquo;s what needs to be in the init interface. If they would also need an address, a hat, and a pair of pants, we would have to put those in the parameter list of the InitStuffInstance method as well.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Implementing the initialization interface&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Implementing the interface in CStuff is easy I highlighted the changes that have to be made to the declaration.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;// CStuff&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;class&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; ATL_NO_VTABLE CStuff :&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; CComObjectRootEx&amp;lt;CComMultiThreadModel&amp;gt;,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; CComCoClass&amp;lt;CStuff, &amp;amp;CLSID_Stuff&amp;gt;,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; IDispatchImpl&amp;lt;IStuff, &amp;amp;IID_IStuff, &amp;amp;LIBID_Stuff_ServerLib, &lt;span style="color:green;"&gt;/*wMajor =*/&lt;/span&gt; 1, &lt;span style="color:green;"&gt;/*wMinor =*/&lt;/span&gt; 0&amp;gt;,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;color:blue;mso-highlight:silver;"&gt;public&lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt; IStuffInit&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;private&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;CComBSTR m_Name;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;public&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;background:silver;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;mso-highlight:silver;"&gt;DECLARE_CLASSFACTORY_EX(CStuffCreator)&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;// removed irrelevant stuff&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;BEGIN_COM_MAP(CStuff)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;COM_INTERFACE_ENTRY(IStuff)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;COM_INTERFACE_ENTRY(IDispatch)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;COM_INTERFACE_ENTRY(IStuffInit)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;END_COM_MAP()&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:green;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;// removed irrelevant stuff&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; &lt;span style="color:green;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;HRESULT STDMETHODCALLTYPE InitStuffInstance(BSTR Name);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;First we add IStuffInit to the inheritance list, we add it to the COM map, and then we add the declaration for InitStuffInstance.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Of course, the name has to be part of the objects state, so we add a CComBSTR variable to hold it.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And finally, we use the DECLARE_CLASSFACTORY_EX macro to change the class object for CStuff from CComClassFactory to CStuffCreator.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The actual implementation of the interface consists of the simple code&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;STDMETHODIMP CStuff::InitStuffInstance(BSTR Name)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;m_Name = Name;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; S_OK;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Note the ease with which CComBSTR allows us to perform simple string operations.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Initializing the new CStuff object&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Now that there is a dedicated function to handle the initialization, the changes to CStuffCreator are trivial:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;HRESULT STDMETHODCALLTYPE CStuffCreator::MakeMeAStuff( &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;BSTR name,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;REFIID riid,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;IUnknown **ppStuff)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IStuffInit&amp;gt; newStuff;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;HRESULT hr = m_pfnCreateInstance(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;NULL,&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IStuffInit), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)&amp;amp;newStuff);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;hr = newStuff-&amp;gt;InitStuffInstance(name);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; newStuff-&amp;gt;QueryInterface(riid, (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)ppStuff);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;What about double initialization&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;By now you might be wondering: But what if the client application retrieves this interface and performs another initialization?&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;However, this will not be possible.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;It&amp;rsquo;s true that I put the interface in our IDL file, and that I implemented it in the CStuff object. But I did not put that interface in the library declaration, nor did I put it in the interface list of the coclass.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So for all practical purposes, this interface is not accessible to the client application. If you are really paranoid, you could argue that an attacker might know the interface GUID, and guess the interface definition, and with some trial and error make it work.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Even then, the fix is quite simple. You can add a boolean to your class that indicates if the object was initialized or not. Set it to false in the constructor, and then the InitStuffInstance can either perform initialization if it is false and set it to true, or return E_FAIL if it is already true.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;You don&amp;rsquo;t even have to care about race conditions, because there aren&amp;rsquo;t any. Only the class object can perform the real initialization. And since no one else has an interface pointer yet, there can&amp;rsquo;t be a race.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The client side&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Creating a new CStuff has changed a little bit, because now we can&amp;rsquo;t use CoCreateInstance anymore. So construction is now done in 2 stages:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IStuffCreator&amp;gt; stuffClass;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = CoGetClassObject(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(Stuff), CLSCTX_ALL, NULL,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IStuffCreator), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)&amp;amp;stuffClass);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;//make a new stuff&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComBSTR stuffName = L&lt;span style="color:#a31515;"&gt;&amp;quot;Kato&amp;quot;&lt;/span&gt;;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IStuff&amp;gt; newStuffUnk;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = stuffClass-&amp;gt;MakeMeAStuff(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;stuffName.m_str,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(GUID*)&amp;amp;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IStuff),&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(IUnknown**)&amp;amp;newStuffUnk);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;It&amp;rsquo;s still very simple though. First we get the class object, and then we use the IStuffCreator interface to create the new CStuff.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Server lifetime management&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Everything works, hip hip hurray&amp;hellip; until you destroy the first CStuff instance, and then try to create another one. That is where it all goes pear shaped.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The problem is that we haven&amp;rsquo;t taken care of managing the lifetime of the server (the exe). The key issue here is the module lock reference count.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Each COM module (exe or dll) has a global reference count to keep track of how many objects are &amp;lsquo;alive&amp;rsquo;. COM objects exist physically inside a DLL or EXE. So the EXE has to stay alive as long as there are living objects inside. Conversely, as soon as there are no living objects anymore, the EXE should shut down.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;What happens in our example is that CStuff raises the module ref count when it is created. And when the CStuff instance destroys itself, it lowers the module ref count. If you remember correctly, the class object itself uses CComObjectNoLock as its COM core. This means that its existence does not influence the module lifetime.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So when the CStuff instance destroys itself and lowers the module ref count, the ref count reaches 0 and the server EXE shuts down.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The client is unaware of this and tries to use the class object again. It still thinks it has a valid interface pointer, but the underlying class object is long gone and there will be a critical error in the client application.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;You might say &amp;lsquo;well duh, then don&amp;rsquo;t use CComObjectNoLock, doofus&amp;rsquo; but that has the opposite effect. The COM runtime will always have the interface pointer that was used for registering the class object with CoRegisterClassObject. This means that the class object would not destroy as long as the server lives. And the server would keep living as long as the class object was around. This is clearly not the answer.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;IExternalConnection to the rescue&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The key to solving this problem is a rarely used standard interface. IExternalConnection is an interface that can be used by an object to track how many external connections there are to itself. This is basically an alternative to the standard object reference count.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;There are 2 methods in this interface:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;STDMETHODIMP_(DWORD) AddConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;DWORD extconn, DWORD dwReserved); &lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;STDMETHODIMP_(DWORD) ReleaseConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;DWORD extconn,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;DWORD dwReserved,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;BOOL bLastUnlockReleases);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If a client requests any class object, the COM runtime will retrieve it. But before the interface pointer is released to the client, it will request some interfaces itself for housekeeping purposes. One of those interfaces is IExternalConnection.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If a client requests an interface pointer to a class object, the marshaller will call AddConnection when it hands out the pointer, and ReleaseConnection when the pointer is destroyed.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So all we have to do is to make sure that a call to AddConnection will increment the module lock count, and a call to ReleaseConnection releases the module lock count.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Implementing IExternalConnection&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you look in MSDN, you won&amp;rsquo;t find it. It is undocumented, but the ATL headers contain an implementation for IExternalConnection. It&amp;rsquo;s called IExternalConnectionImpl&amp;lt;T&amp;gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;To use it, we only have to change CStuffCreator so that it inherits from it, and add it to the COM interface map.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;class&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CStuffCreator:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; IStuffCreator,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;color:blue;mso-highlight:silver;"&gt;public&lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt; IExternalConnectionImpl&amp;lt;CStuffCreator&amp;gt;,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt; CComObjectRootEx&amp;lt;CComGlobalsThreadModel&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;public&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;//removed irrelevant stuff&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;BEGIN_COM_MAP(CStuffCreator)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;COM_INTERFACE_ENTRY(IStuffCreator)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;COM_INTERFACE_ENTRY(IExternalConnection)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;END_COM_MAP()&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;//IExeternalConnectionImpl&amp;lt;T&amp;gt; extension&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="background:silver;color:blue;mso-highlight:silver;"&gt;void&lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt; STDMETHODCALLTYPE OnReleaseConnection(&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;background:silver;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;mso-highlight:silver;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; bThisIsLastUnlock, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; bLastUnlockReleases);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;background:silver;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;mso-highlight:silver;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; STDMETHODCALLTYPE OnAddConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;background:silver;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;mso-highlight:silver;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; bThisIsFirstLock);&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;//removed irrelevant stuff&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;That is really all there is to it. The default implementation does not modify the module lock count. But it has 2 extension points that we can override. So that&amp;rsquo;s what we do to make sure the module lock count is managed properly.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;void&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; STDMETHODCALLTYPE CStuffCreator::OnAddConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; bThisIsFirstLock)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;_pAtlModule-&amp;gt;Lock();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;void&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; STDMETHODCALLTYPE CStuffCreator::OnReleaseConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; bThisIsLastUnlock, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; bLastUnlockReleases)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;_pAtlModule-&amp;gt;Unlock();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;IExternalConnectionImpl&amp;lt;CStuffCreator&amp;gt;::OnReleaseConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;bThisIsLastUnlock,&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;bLastUnlockReleases);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The only special thing that still needs mentioning is that OnReleaseConnection delegates back to the default implementation in IExternalConnectionImpl. It does this because there is something that needs to be done when the last external connection is closed.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; OnReleaseConnection(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; bThisIsLastUnlock, &lt;span style="color:blue;"&gt;bool&lt;/span&gt; bLastUnlockReleases)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (bThisIsLastUnlock &amp;amp;&amp;amp; bLastUnlockReleases)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CoDisconnectObject(&lt;span style="color:blue;"&gt;static_cast&lt;/span&gt;&amp;lt;T*&amp;gt;(&lt;span style="color:blue;"&gt;this&lt;/span&gt;)-&amp;gt;GetUnknown(), 0);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If the last connection closes, the class object needs to call CoDisConnectObject to destroy its marshalling stub. Now I could copy paste this code into my implementation of OnReleaseConnection, but it is simpler to just delegate back to the base class for stuff that needs doing anyway.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The result&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Now that we have provided this implementation of IExternalConnection, the server EXE will stay alive until all CStuff instances are gone, and noone is using the class object anymore. Only then will the EXE terminate. &lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="color:black;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;CComClassFactory revisited&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="color:black;"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;If you look at the interface implemented by CComClassFactory, you&amp;rsquo;ll notice that IExternalConnection is missing. And yet, server lifetime of CComClassFactory is managed correctly.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="color:black;"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The reason for this is that the COM runtime treats IClassFactory class objects differently from other class objects. It will check if the class object supports IClassFactory. And if it does, it calls IClassFactory::LockServer to indicate that someone is using the class object. And it unlocks the class object when the class object reference is released again.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="color:black;"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;In a way, it uses the IClassFactory in almost the same way as it would use IExternalConnection. And in a way it is too bad that this functionality was included in IClassFactory directly, instead of making IClassFactory inherit from IExternalConnection. The reasons for this are lost in the mists of time. But whatever the reasons, this is why IClassFactory doesn&amp;rsquo;t need IExternalConnection. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Conclusion&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As you can see, implementing a non standard class object is not so hard. As long as you have a basic understanding of the underlying COM principles, ATL takes care of all the dirty work.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And by using these techniques, we can implement COM objects that need initialization before they can safely be used by the client. The source code for this article is available under the MIT license as usual.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And again I&amp;rsquo;d like to add a thank you for Microsoft&amp;rsquo;s Tim Springfield and Amit Mohindra&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1673035" width="1" height="1"&gt;</description><enclosure url="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.01.67.30.35/Stuff_5F00_V2.zip" length="24747" type="application/x-zip-compressed" /><category domain="http://msmvps.com/blogs/vandooren/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item><item><title>Practical ATL: Understanding the class object</title><link>http://msmvps.com/blogs/vandooren/archive/2009/02/10/practical-atl-understanding-the-class-object.aspx</link><pubDate>Tue, 10 Feb 2009 07:46:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1671098</guid><dc:creator>vanDooren</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1671098</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1671098</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/02/10/practical-atl-understanding-the-class-object.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;In my previous article in this series, I explained how to create a simple COM server and implement a method that returns an enumerator object.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;It was all done very easily, but the ATL wizards hide some of the things that you really ought to know for my next article. For starters: where is the class object?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The class object is the COM object responsible for creating new instances of the CStuff COM object that I demonstrated in a previous article. But we didn&amp;rsquo;t have to write any code for it, nor is it even visible&amp;hellip; so what&amp;rsquo;s up with that?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Some more on class objects&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The class object of a COM server is the object that is actually responsible handing out instances of the COM object. The class object is a COM object itself, but only 1 instance of it normally exists in a module (DLL or EXE) per defined COM object type.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;For example, the &amp;lsquo;Stuff&amp;rsquo; COM object that I implemented in my previous article uses the standard class factory with IClassFactory as the interface for handing out new CStuff instances.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The most important method in IClassFactory is &amp;lsquo;CreateInstance&amp;rsquo; which simply creates a new instance of the COM object and then passes an interface pointer back to the caller.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Normally, this process is invisible to the client application, because &amp;lsquo;CoCreateInstance&amp;rsquo; uses IClassFactory behind the scenes so that the client doesn&amp;rsquo;t have to bother with it.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;First it calls &amp;lsquo;CoGetClassObject&amp;rsquo; to get the class object for the requested COM object, and then it uses the IClassFactory interface of that class object to create a new instance. That instance is then passed to the caller, as an interface pointer of the type that was requested in the call to &amp;lsquo;CoCreateInstance&amp;rsquo;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;I think it is safe to say that &amp;lsquo;IClassFactory&amp;rsquo; (or one of its relatives) is the interface on the class object of 99.99% of all COM objects that have a class object.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;The default class factory&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;By default, CStuff uses CComClassFactory as its default class object. But looking at the declaration of CStuff, it is not immediately apparent how it does this.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;CStuff derives from CCoClass&amp;lt;T&amp;gt;, which has the macro DECLARE_CLASSFACTORY in its implementation.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;For EXE servers, this macro expands to DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory), which in turn expands to &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;typedef&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; ATL::CComCreator&amp;lt; ATL::CComObjectNoLock&amp;lt; ATL::CComClassFactory &amp;gt; &amp;gt; _ClassFactoryCreatorClass;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;DLL servers use CComObjectCached instead of CComObjectNoLock, but I don&amp;rsquo;t cover DLL servers in this article.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;As you can remember from the first article that featured CStuff, the C++ COM classes are missing the IUnknown core by default, because the implementation of that core depends on how we want to the object to behave.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;This means we have to shove our class into a COM object to make it whole. For class objects, the CComObjectNoLock is most appropriate, because the lifetime of the object should not contribute to the lifetime of the server executable. Otherwise there would be a deadlock.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The server would start, and create the class object. And then the server would continue to live until the class object was destroyed. But since the COM runtime will always have a reference to the class object, the reference count would never reach zero, the class object would never be destroyed, and the server would never be able to shut down.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;And finally, this class definition is shoved into a creator object which will help us by creating a properly initialized instance of the class object itself via its static CreateInstance function.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Associating the COM object C++ class with the class factory&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;So the COM object C++ class has a typedef that identifies the class object type. But how does the executable use this fact?.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;This is where things get a little hairy, and possibly start to make ominous squishy sounds &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;After the class declaration of CStuff, there is the innocuous line &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;OBJECT_ENTRY_AUTO(&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(Stuff), CStuff)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The OBJECT_ENTRY_AUTO is a macro that expands to this:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;#define&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; OBJECT_ENTRY_AUTO(clsid, &lt;span style="color:blue;"&gt;class&lt;/span&gt;) \&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__declspec&lt;/span&gt;(&lt;span style="color:blue;"&gt;selectany&lt;/span&gt;) ATL::_ATL_OBJMAP_ENTRY __objMap_##&lt;span style="color:blue;"&gt;class&lt;/span&gt; = {&amp;amp;clsid, &lt;span style="color:blue;"&gt;class&lt;/span&gt;::UpdateRegistry, &lt;b style="mso-bidi-font-weight:normal;"&gt;&lt;span style="background:silver;color:blue;mso-highlight:silver;"&gt;class&lt;/span&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;::_ClassFactoryCreatorClass::CreateInstance&lt;/span&gt;&lt;/b&gt;&lt;span style="background:silver;mso-highlight:silver;"&gt;, &lt;b style="mso-bidi-font-weight:normal;"&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt;::_CreatorClass::CreateInstance&lt;/b&gt;&lt;/span&gt;, NULL, 0, &lt;span style="color:blue;"&gt;class&lt;/span&gt;::GetObjectDescription, &lt;span style="color:blue;"&gt;class&lt;/span&gt;::GetCategoryMap, &lt;span style="color:blue;"&gt;class&lt;/span&gt;::ObjectMain }; \&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;extern&lt;/span&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;C&amp;quot;&lt;/span&gt; &lt;span style="color:blue;"&gt;__declspec&lt;/span&gt;(&lt;span style="color:blue;"&gt;allocate&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;ATL$__m&amp;quot;&lt;/span&gt;)) &lt;span style="color:blue;"&gt;__declspec&lt;/span&gt;(&lt;span style="color:blue;"&gt;selectany&lt;/span&gt;) ATL::_ATL_OBJMAP_ENTRY* &lt;span style="color:blue;"&gt;const&lt;/span&gt; __pobjMap_##&lt;span style="color:blue;"&gt;class&lt;/span&gt; = &amp;amp;__objMap_##&lt;span style="color:blue;"&gt;class&lt;/span&gt;; \&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;OBJECT_ENTRY_PRAGMA(&lt;span style="color:blue;"&gt;class&lt;/span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Don&amp;rsquo;t worry if the sight of this code makes you nauseous. That&amp;rsquo;s normal. I highlighted the important parts&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;What it does is simple. It&amp;rsquo;s just how it does it that is ugly. It creates a map entry for the ATL innards of our server executable. In this map entry, it associates the static method for creating the class object with the static method for creating an object instance.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Creating the class object&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Now that the class object and the COM object are associated with each other, the next bit of code in the ATL headers is where the magic happens:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;_ATL_OBJMAP_ENTRY* pEntry;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (m_pObjMap != NULL)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pEntry = m_pObjMap;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;while&lt;/span&gt; (pEntry-&amp;gt;pclsid != NULL &amp;amp;&amp;amp; hr == S_OK)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = pEntry-&amp;gt;RegisterClassObject(dwClsContext, dwFlags);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pEntry++;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;When the ATL module initializes, it will iterate over all elements in the object map and register each one. And this registration process entails the following:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IUnknown* p = NULL;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (pfnGetClassObject == NULL)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; S_OK;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HRESULT hRes = pfnGetClassObject(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;pfnCreateInstance,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IUnknown),&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(LPVOID*) &amp;amp;p);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (SUCCEEDED(hRes))&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hRes = CoRegisterClassObject(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;*pclsid, p, dwClsContext, dwFlags, &amp;amp;dwRegister);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt; (p != NULL)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;p-&amp;gt;Release();&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hRes;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;If you do a bit of spelunking in the headers, you&amp;rsquo;ll see that pfnGetClassObject is a function pointer that maps to _ClassFactoryCreatorClass::CreateInstance. So this code simply creates a new class object and registers it.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Again, this is specific to EXE servers. In DLL servers, the class object is created on demand in the DllGetClassObject function, which is called by CoGetClassObject if the COM server is a DLL.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Creating CStuff instances&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;If you look at the _ClassFactoryCreatorClass::CreateInstance, you&amp;rsquo;ll see that its first parameter is a void *. And the value that is passed in this parameter by the ATL module is the address of the static method for creating new object instances.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;_ClassFactoryCreatorClass::CreateInstance simply creates a new class object &amp;lsquo;p&amp;rsquo;, and then calls &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;p-&amp;gt;SetVoid(pv);&lt;/span&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt; to pass the aforementioned function pointer to the class object.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;And the SetVoid method is no more complicated then this:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;void&lt;/span&gt; SetVoid(&lt;span style="color:blue;"&gt;void&lt;/span&gt;* pv)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;m_pfnCreateInstance = (_ATL_CREATORFUNC*)pv;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;_ATL_CREATORFUNC* m_pfnCreateInstance;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;I guess the original developer hadn&amp;rsquo;t had his morning coffee yet when he came up with this name. It manages to be 100% factually correct, while being 100% opaque at the same time. But it does the job.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;When the class object has to create a new instance, it simply does the following:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, &lt;span style="color:blue;"&gt;void&lt;/span&gt;** ppvObj)&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// snip irrelevant code&lt;/span&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hRes = m_pfnCreateInstance(pUnkOuter, riid, ppvObj);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:green;"&gt;// snip irrelevant code&lt;/span&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hRes;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Providing a new class factory&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Now that you understand how the class object plumbing is hooked up, it is easy to see how you can implement your own class object.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Remember how DECLARE_CLASSFACTORY_EX maps a class object to the _ClassFactoryCreatorClass typedef?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In C++, a typedef in a derived class can override a typedef in a base class. So even though the CCoClass&amp;lt;T&amp;gt; base class says that the _ClassFactoryCreatorClass maps to &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;ATL::CComCreator&amp;lt; ATL::CComObjectNoLock&amp;lt; ATL::CComClassFactory &amp;gt; &amp;gt;,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;We can override this by simply putting &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;DECLARE_CLASSFACTORY_EX(CStuffCreator) &lt;/span&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;In the declaration for CStuff. That&amp;rsquo;s really all there is to it. The macro magic takes care of the rest.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;"&gt;&lt;span style="font-family:Arial;"&gt;Conclusion&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;If changing the class object for a COM server is as trivial as adding a single line to your COM server C++ class, then why did I just write 4 pages of stuff?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;I wrote all this because if I tell someone to use a macro to do something non-trivial, I want him or her to understand what is going on. There are already far too many programmers on this planet who do things without understanding what it is they do, or how it works. And I am not going to add some more by glossing over the details.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Of course, judging by the number of visitors on this corner of the internet that I call &amp;lsquo;home&amp;rsquo;, I stand little risk of doing so no matter how crappy I would write &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;This article was originally part of my article on implementing a custom class object. But after I spent more than 3 pages on the previous explanation, I thought it would be best to put it in a separate article. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;A big thank-you goes to Jim Springfield of the Architects team within the developers division (I think) of Microsoft for taking the time to review this article for correctness, and to Amit Mohindra for helping my questions and articles reach the right people.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;And you can find the demo project attached to this article under the MIT license.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1671098" width="1" height="1"&gt;</description><enclosure url="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.01.67.10.98/Stuff_5F00_V2.zip" length="24747" type="application/x-zip-compressed" /><category domain="http://msmvps.com/blogs/vandooren/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item><item><title>Practical ATL: recognizing marshalling problems</title><link>http://msmvps.com/blogs/vandooren/archive/2009/01/27/practical-atl-recognizing-marshalling-problems.aspx</link><pubDate>Tue, 27 Jan 2009 11:30:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1666343</guid><dc:creator>vanDooren</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1666343</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1666343</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/01/27/practical-atl-recognizing-marshalling-problems.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Before I publish my next article, I should explain something else about the black magic aspect of ATL / COM: Marshalling.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The Stuff server we made in the previous article is an out-of-proc server. This means that the arguments being passed to / from a stuff instance have to be somehow moved back and forth between different process contexts (or different threading apartments).&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In the case of IStuff, we don&amp;rsquo;t really have to bother, because IStuff derives from IDispatch. And in that case, there is a marshaller (aptly named Universal Marshaller) that can be used to do all this for you.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If IStuff wouldn&amp;rsquo;t derive from IDispatch, then we would need to provide our own proxy &amp;ndash; stub interface that knows how to marshal the interface. With ATL, this is not difficult. You&amp;rsquo;ll notice that the Stuff solution of my previous article had a &amp;lsquo;Stuff_ServerPS&amp;rsquo; project that I didn&amp;rsquo;t mention before.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;That solution will build the proxy stub dll that will perform the marshaling. It is disabled by default, so you have to enable it in the build configuration before it is built. Also remember to rebuild the proxy, every time the IDL files of your project change.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So for the remainder of this article I will show what can happen if there is a marshalling problem. &lt;b style="mso-bidi-font-weight:normal;"&gt;Don&amp;rsquo;t worry if it all seems ugly, gory, and incomprehensible. Normally you won&amp;rsquo;t have to deal with issues like this. But if you should ever do, you should at least recognize the signs that you have a marshaling problem&lt;/b&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Confused? It&amp;rsquo;s the marshaller&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you find yourself in a situation where very weird things happen, suspect a marshalling problem.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you get the error code E_NOINTERFACE when you know for sure that your object implements it properly, suspect a marshalling problem.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you get a crash while using an interface pointer that was properly created without getting a HRESULT that indicated a problem,&amp;hellip; that&amp;rsquo;s right: you can bet it&amp;rsquo;s a marshaling problem.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Example&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The article I am currently writing discusses implementing a non standard class object, for the purpose of parameterized construction of the Stuff object. Never mind for the moment about what any of that means.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;For all practical purposes: it just means that I defined the following interface via copy / paste / edit:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;[&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;object&lt;/span&gt;,&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;local&lt;/span&gt;,&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;uuid&lt;/span&gt;(6DD69CDB-3128-432b-B335-773A287E6F06),&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;dual&lt;/span&gt;,&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;helpstring&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;IStuffCreator Interface&amp;quot;&lt;/span&gt;),&lt;br /&gt;&lt;span style="mso-tab-count:1;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;pointer_default&lt;/span&gt;(&lt;span style="color:blue;"&gt;unique&lt;/span&gt;)&lt;br /&gt;]&lt;br /&gt;&lt;span style="color:blue;"&gt;interface&lt;/span&gt; IStuffCreator : IUnknown {&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;id&lt;/span&gt;(1), &lt;span style="color:blue;"&gt;helpstring&lt;/span&gt;(&lt;span style="color:#a31515;"&gt;&amp;quot;method MakeMeAStuff&amp;quot;&lt;/span&gt;)]&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;HRESULT MakeMeAStuff(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;in&lt;/span&gt;] BSTR name,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;in&lt;/span&gt;] REFIID riid,&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color:blue;"&gt;out&lt;/span&gt;] &lt;span style="color:blue;"&gt;void&lt;/span&gt; ** ppStuff);&lt;br /&gt;};&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;There were 4 things wrong with this interface (showing just why you shouldn&amp;rsquo;t define IDL interfaces in a hurry). This has to be some sort of record.&lt;/span&gt;&lt;/p&gt;
&lt;ol style="margin-top:0cm;"&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;lsquo;local&amp;rsquo; shouldn&amp;rsquo;t be there.&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;lsquo;dual&amp;rsquo; shouldn&amp;rsquo;t be there.&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;lsquo;void&amp;rsquo; should be &amp;lsquo;IUnknown&amp;rsquo;&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;lsquo;ppStuff&amp;rsquo; should be attributed with riid_is(riid).&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So let&amp;rsquo;s have a look at the result of these different issues.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Issue 1: local&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;lsquo;local&amp;rsquo; simply shouldn&amp;rsquo;t be there. &amp;lsquo;local&amp;rsquo; is a MIDL attribute that &amp;ndash;when use in an interface header- causes MIDL not to generate stubs for that interface.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The effect on our interface is that the IStuff specific methods are not forwarded to the remote server.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;You might wonder: why does it exist. The answer is: in case you want to write custom marshalling code, or in case the calls never have to be remoted. In that case you can have a local interface and a remote interface. And usage and marshalling could be optimized.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;IUnknown is such an interface. But it has custom stub code to deal with things like remoting&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;The result of using &amp;lsquo;local&amp;rsquo; on my IStuffCreator interface is that trying to call GetEnum on the returned IStuff interface pointer will result in a debug assertion: &lt;i style="mso-bidi-font-style:normal;"&gt;Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.&lt;/i&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And if you have this problem with COM, it is usually indeed an indication that you have a calling convention mismatch. In this case, it is a side effect of the fact that we are trying to execute a method that isn&amp;rsquo;t remoted.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Issue 2: dual&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This one shouldn&amp;rsquo;t be here either. Dual indicates that the interface implements IDispatch, and this could have an effect on marshalling.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In this case, it worked just fine. Perhaps it is because of the fact that I use my object as a class object, or perhaps because my interface itself uses only arguments that are automation compatible, or perhaps because the stars are aligned in the proper configuration.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I don&amp;rsquo;t know. And anything you don&amp;rsquo;t know for certain will hurt you when dealing with DCOM. It has to be correct.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Issue 3: void&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This one is interesting.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If I want to pass an interface pointer, it has to be passed as an IUnknown**, instead of a void**. This is because Universal Marshaller has no idea on how to marshal something which has only contextual meaning, nor does the IDL compiler know what you mean with it.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;With this I mean that my server knows it will be an interface pointer, and my client will know it is an interface pointer, but the stuff in the middle doesn&amp;rsquo;t. It sees just a memory address.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I used void** because that is what QueryInterface itself uses. And what&amp;rsquo;s good enough for QI should be good enough for me. Except QI has custom code for marshalling its arguments across, which I don&amp;rsquo;t. So QI can use void** because both the proxy and the stub know what is going on.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So what happens when you use void**?&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I request the class object like this:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = CoGetClassObject(&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(Stuff),&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CLSCTX_ALL,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;NULL,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IStuffCreator),&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;(&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)&amp;amp;stuffClass);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And the resulting hr is 0x80020008: Bad variable type. There is absolutely nothing wrong with this line of code. But because there is something in the interface itself that confuses the marshaller, it tells me to sod off when I want that specific interface.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Credit where it is due: I figured this one out thanks to someone whose name I can&amp;rsquo;t figure out &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:Times New Roman;"&gt;. But his blog post is &lt;a href="http://www.ajitatif.com/CategoryView,category,ATL.aspx" title="http://www.ajitatif.com/CategoryView,category,ATL.aspx"&gt;here&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Issue 4: iid_is(riid)&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This one is also a good one.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The iid_is informs the marshaller that riid points to the identifier which identifies the interface that is being marshaled.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This way, the marshaller knows how to marshal the interface that was specified with riid. Without that part, it would only marshal the IUnknown part of the interface, and not the IStuff specific part.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As a result, you can use the IUnknown part of the interface without a problem, but if you use the IStuff specific part, you will get an access violation, stack corruption or other interesting phenomenon.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Conclusion&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;A couple of things can be concluded at this point.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;First of all: Marshaling problems are hard to debug, because the problems occur outside of your source code.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you use any interfaces that don&amp;rsquo;t derive from IDispatch, then you have to enable the &amp;lsquo;xxxPS&amp;rsquo; project in your solution so that the ProxyStub dll will be built and registered. And of course, this dll has to be part of your install procedure. Without this stub, you could get access violations, or you get an E_NOINTERFACE error if the marshaler doesn&amp;#39;t know one of those interface exist.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As I have shown, you need to be careful and pay attention when you manually define COM interfaces. If you don&amp;rsquo;t, then you can have all sorts of hard to diagnose problems.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And if you ever find yourself in a situation where nothing makes sense, then suspect marshalling issues and have a long hard look at your IDL files.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1666343" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item><item><title>Practical ATL: Implementing an enumerator object</title><link>http://msmvps.com/blogs/vandooren/archive/2009/01/21/practical-atl-implementing-an-enumerator-object.aspx</link><pubDate>Wed, 21 Jan 2009 19:55:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1664320</guid><dc:creator>vanDooren</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1664320</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1664320</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/01/21/practical-atl-implementing-an-enumerator-object.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This is my first article about practical ATL examples, which I already mentioned here.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In this example I will create an ATL Server which implements 1 custom interface: IStuff. Hardly an inspiring name, but I couldn&amp;rsquo;t think of anything better before I had my first coffee.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This interface will have 1 method which will return an enumerator to the caller. Specifically, this enumerator will implement IEnumString.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Enumerators are part of the interface of many real-life COM servers, but creating your own is an arduous task. ATL makes this much easier, but an example makes things so much easier still.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Since client code will have to deal with this enumerator (and to have a demo app) I will also create a client application that creates an instance of the server, consumes the IStuff interface and then enumerate the items contained in the returned enumerator.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Before we get started&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you don&amp;rsquo;t own a copy of &amp;lsquo;ATL Internals, Second Edition&amp;rsquo; yet, I strongly advise you to buy it. It is worth the money, and apart from leading you through all the interesting and gory stuff, it also starts by explaining the actual process of creating an ATL server through the IDE, as well as implementing methods, properties and events.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I am only going to cover that aspect very lightly. It should be detailed enough for anyone who has done C++ development using VS:&lt;/span&gt;&lt;/p&gt;
&lt;ol style="margin-top:0cm;"&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Create a new ATL Server project with project name &amp;lsquo;Stuff_Server&amp;rsquo; and a solution name &amp;lsquo;Stuff&amp;rsquo;.&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Choose the EXE project type and click &amp;lsquo;finish&amp;rsquo;&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Add a new class to the project, and specify ATL Simple Object. Use &amp;lsquo;Stuff&amp;rsquo; as the name of the object.&lt;/span&gt;&lt;/li&gt;
&lt;li style="margin:0cm 0cm 12pt;mso-list:l0 level1 lfo1;tab-stops:list 36.0pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Switch to classview, and add a new method to the IStuff interface with the prototype &amp;lsquo;HRESULT GetEnum(IUnknown ** ppEnum).&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;ppEnum should be marked as an &amp;lsquo;out&amp;rsquo; parameter.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Build the project, and you should be ready for the actual work. The ATL wizards will have implemented all the IDL and DCOM stuff for you, and you only have to implement the functionality.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Finally, I always end by changing the project configuration to use static CRT and ATL runtimes instead of dynamic runtimes. This makes it infinitely more easy to distribute the resulting executables without having to bother with registration and installation of the runtime dlls and their manifests.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Creating the server&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Now that the ATL wizards have generated the function skeleton for us, it is time to do something with it:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;STDMETHODIMP CStuff::GetEnum(IUnknown** ppEnum)&lt;br /&gt;{&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;The enumerator&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Before we can do anything else, we have to think about the actual enumerator for a bit. In our case we implement IEnumString. This is an interface for enumerating string (who&amp;rsquo;d have thought, eh?).&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Enum interfaces all look alike, and ATL helpfully has a stock implementation for generic enumerators that allows you to specify the Interface, GUID, datatype and data type copy traits as template parameters. In order to facilitate coding, we make a typedef for this class:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;typedef&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CComEnum&amp;lt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IEnumString,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&amp;amp;IID_IEnumString,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;LPOLESTR,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_Copy&amp;lt;LPOLESTR&amp;gt; &amp;gt; CComEnumStringAbstract;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This will specialize the enumerator for our purposes. The use of the first 3 parameters is obvious. Don&amp;rsquo;t worry about the _Copy parameter. I will cover that later.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The enumerator itself is a normal COM object, so it needs lifetime management, interface managements, and all other things you really don&amp;rsquo;t want to care about for something so simple. At this point, &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;CComEnumStringAbstract&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; will still be an abstract class because it can&amp;rsquo;t decide how to do these things for you.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In order to make our enumerator a full fledged COM object, we have to shove it into a bare COM object. This is very easy:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;typedef&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; CComObject&amp;lt;CComEnumStringAbstract&amp;gt; CComEnumString;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And that is all there is to creating an enumerator! Anyone who has ever implemented one manually will agree that this is infinitely more convenient&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Implementing GetEnum&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The implementation for GetEnum is also fairly easy (comments removed for clarity)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;STDMETHODIMP CStuff::GetEnum(IUnknown** ppEnum)&lt;br /&gt;{&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CComEnumString * thEnumObj&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;= NULL;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;HRESULT hr = CComEnumString::CreateInstance(&amp;amp;thEnumObj);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;br /&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;CComEnumString&amp;gt; thEnum(thEnumObj);&lt;br /&gt;&lt;span style="color:green;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;LPOLESTR strings[] = {L&lt;span style="color:#a31515;"&gt;&amp;quot;One&amp;quot;&lt;/span&gt;, L&lt;span style="color:#a31515;"&gt;&amp;quot;Two&amp;quot;&lt;/span&gt;, L&lt;span style="color:#a31515;"&gt;&amp;quot;Three&amp;quot;&lt;/span&gt;, NULL};&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;hr = thEnum-&amp;gt;Init(&amp;amp;strings[0], &amp;amp;strings[3], NULL, AtlFlagCopy);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;hr = thEnum-&amp;gt;QueryInterface( &lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IUnknown), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)ppEnum);&lt;br /&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;First we create a new &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;CComEnumString&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; object. It is worth noting that the object returned by &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;CreateInstance&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; has a refcount of 0. Before we do anything with it we should AddRef it, but instead of doing that manually, I do it via assignment to the CComPtr. smart pointer. That way the object also gets released automatically at the end.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Then we have to make sure the enumerator has some data to enumerate. We do this by populating an array, and then telling the enumerator to copy the data out of it into its own internal buffer. This is done via the &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;AtlFlagCopy&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; flag.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;It might seem weird if you come from a C background, but the &amp;lsquo;End&amp;rsquo; pointer has to point to the first position beyond the last element. This is normal with collections in C++. That is also why I populate the array with a NULL pointer at the end; So that there is something in the array after the last &amp;lsquo;real&amp;rsquo; element. This way there is no buffer overflow.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Using &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;AtlFlagCopy&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; has the overhead of having to copy the data, but otoh the enumerator does not have to care about the lifetime of the array. We could also use new[] to create a new array and then use the &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;AtlFlagTakeOwnership&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; flag to indicate that it is up to the enumerator to call delete[] and clean up. But in this example we can&amp;rsquo;t do that (read below).&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;When the enumerator is initialized, we return an IUnknown interface pointer to the caller. Since this will have increased the enumerator ref count, the enumerator object will keep on living when the CComPtr goes out of scope and releases its own reference to the enumerator.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;There. That is all there is to it on the server side. No vast amounts of copy pasted boilerplate code, but just a couple of lines of powerful ATL incantations &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;_Copy&amp;lt;LPOLESTR&amp;gt; revisited&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If an enumerator has to copy data to a client, or if it has to copy data into its internal buffers in the &amp;lsquo;Init&amp;rsquo; function, it has to know how to do this.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;It&amp;rsquo;s all good and well to do a simple memcpy of an ULONG or a double, but for strings (LPOLESTR) and interface pointers (IUnknown) this won&amp;rsquo;t work. There&amp;rsquo;s ref counting and memory ownership to deal with.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Of course, the template class, not knowing about this, can&amp;rsquo;t anticipate what you want, so instead it needs a policy class to delegate to. That is where the _Copy&amp;lt;&amp;gt; template class comes in. It has 3 methods: Init, Destroy, and Copy. Those methods perform the actual operations needed to copy an instance of T to another instance of T, to initialize a new one, and to destroy one.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;There are several stock specializations for _Copy&amp;lt;&amp;gt;, one of which works for LPOLESTR. So rather than copying the LPOLESTR pointer itself, it calls CoTaskMemAlloc to create a buffer for the copy of the string, and then copies over the data.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you look at my example more closely, you will also see why I cannot simply new up an array of string literals and pass those to the Init function with the &lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;AtlFlagTakeOwnership&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; flag.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;LPOLESTR is superficially identical to wchar_t*. So using a string literal instead of an LPOLESTR (which is what I do in my example) will work without a hitch. But if I&amp;rsquo;d new up an array and tell the enumerator to manage it, that is when it would all go pear shaped.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Because the enumerator would not only call delete[] on the array, but it would also call _Copy::Destroy for each of the items. And trying to free up a string literal with CoTaskMemFree will result in a hard to diagnose crash.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Installing the server&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;On a development station this is done automatically by Visual Studio. But if you need to do this on another PC, you just execute the server from the command line with the /RegServer argument.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Creating the Client&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Creating the client application is fairly simple, but I wanted to show how to do it anyway, because then I could demonstrate that the COM server works as intended.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I create a simple win32 console application so that I only had to care about the actual functionality.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Importing the server type library&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In the olden days or yore, working with COM servers in a C++ project was a bit tedious. You had to include the IDL files in your project and compile them, then include the resulting header files, add the .c files to your project for the GUID definitions&amp;hellip; Not rocket science by any means, but still&amp;hellip; a bit messy and ugly.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Now, I have &lt;i style="mso-bidi-font-style:normal;"&gt;very&lt;/i&gt; few kind words for Visual Basic, but to give credit where it is due: Visual Basic is (in large part) responsible for the existence of tlb files.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Visual Basic programmers wanted to use COM too, and the people who made Visual Basic wanted to prevent the application programmers to have anything to do with IDL. They wanted Visual Basic to take care of all that mess behind the scenes.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And thus the type library (tlb) was born.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The type library contains the same stuff as the IDL files, but in a machine readable, programming language independent format.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;To use a COM server, you need to do nothing more than add the following line to the StdAfx.h header file of the client program:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;#import&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; &lt;span style="color:#a31515;"&gt;&amp;quot;Stuff_Server.tlb&amp;quot;&lt;/span&gt; no_namespace&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;You also need to make sure that the compiler knows where to find Stuff_Server.tlb. This is easily done by adding the following line to the &amp;lsquo;Additional include directories&amp;rsquo; setting:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;..\Stuff_Server\$(ConfigurationName)&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you then compile StdAfx.cpp, the compiler will pull in the type library and generate the appropriate headers which are then automatically included.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The no_namespace attribute tells the compiler that it shouldn&amp;rsquo;t put the declarations in a specific namespace.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style="margin:12pt 0cm 3pt;"&gt;&lt;span style="font-size:medium;font-family:Arial;"&gt;Using the COM server&lt;/span&gt;&lt;/h3&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The client application code itself is fairly trivial:&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;int&lt;/span&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt; _tmain(&lt;span style="color:blue;"&gt;int&lt;/span&gt; argc, _TCHAR* argv[])&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;HRESULT hr = CoInitialize(NULL);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(SUCCEEDED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IStuff&amp;gt; stuff;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = CoCreateInstance(&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(Stuff), NULL, CLSCTX_ALL,&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IStuff), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**)&amp;amp;stuff );&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IUnknown&amp;gt; thEnumUnk;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = stuff-&amp;gt;GetEnum((IUnknown **)&amp;amp;thEnumUnk);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(FAILED(hr))&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; hr;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CComPtr&amp;lt;IEnumString&amp;gt; thEnum;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;thEnumUnk-&amp;gt;QueryInterface(&lt;span style="color:blue;"&gt;__uuidof&lt;/span&gt;(IEnumString), (&lt;span style="color:blue;"&gt;void&lt;/span&gt;**) &amp;amp;thEnum);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;do&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;LPOLESTR str;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;hr = thEnum-&amp;gt;Next(1, &amp;amp;str, NULL);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;if&lt;/span&gt;(hr == S_OK )&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;wprintf(L&lt;span style="color:#a31515;"&gt;&amp;quot;%s\n&amp;quot;&lt;/span&gt;, str);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CoTaskMemFree(str);&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;span style="color:blue;"&gt;while&lt;/span&gt; (hr == S_OK );&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;CoUninitialize();&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 0pt;mso-layout-grid-align:none;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;&lt;span style="mso-spacerun:yes;"&gt;&amp;nbsp; &lt;/span&gt;&lt;span style="color:blue;"&gt;return&lt;/span&gt; 0;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:10pt;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;First I initialize the COM runtime and then create a new instance of the Stuff object. I request IStuff as the initial interface. I also use the &lt;/span&gt;&lt;span style="font-size:10pt;color:blue;font-family:&amp;#39;Courier New&amp;#39;;mso-no-proof:yes;"&gt;__uuidof&lt;/span&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt; keyword to get the GUID for an interface / object instead of using the CLSID_ and IID_ parameters. In my opinion, it is more convenient.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The COM smart pointer takes care of the reference counting for me. This is most convenient, because then I am certain that it will get released properly without me having to worry about it.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Btw, this is also the reason that all the code is placed into a separate scope block after the call to CoInitialize. The smart pointers clean up their interface pointers when they go out of scope. If CoUninitialize would have been called before that, it would lead to weird problems / crashes.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;"&gt;&lt;span style="font-family:Times New Roman;"&gt;Via the IStuff interface I request an enumerator object. This gets returned as an IUnknow interface, so I have to get the IEnumString interface via the IUnknown::QueryInterface method. So that&amp;rsquo;s 3 interfaces already, and I still don&amp;rsquo;t have to care about reference counting &lt;/span&gt;&lt;span style="font-family:Wingdings;mso-ascii-font-family:&amp;#39;Times New Roman&amp;#39;;mso-hansi-font-family:&amp;#39;Times New Roman&amp;#39;;mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;&lt;span style="mso-char-type:symbol;mso-symbol-font-family:Wingdings;"&gt;J&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;After that I use the &amp;lsquo;Next&amp;rsquo; method of the IEnumString interface to retrieve the items contained in the enumerator. This the only place where I have to perform a manual cleanup action.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The IEnumString interface does not work with BSTRs, it works with LPOLESTRs. While these are code compatible because they are the same type of data, their semantics are not. The _Copy&amp;lt;LPOLESTR&amp;gt; mentioned earlier allocates data for the string using CoTaskMemAlloc. It has to be freed by CoTaskMemFree.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;CComBSTR would use SysAllocString and SysFreeString. And while the code would compile and execute perfectly, there would be an crash as soon as the CComBSTR would try to free the string it got from the call to &amp;lsquo;Next&amp;rsquo;.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Conclusion&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;As you can see, implementing COM servers and clients can be really easy with the proper use of ATL. And you&amp;rsquo;ve also seen that implementing an enumerator object is made really easy.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The code demo code is up for download with this article under the MIT license. Have fun.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I will probably write some more ATL / COM stuff soon. Stay tuned for more DCOM archaeology from the mists of time ;-)&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1664320" width="1" height="1"&gt;</description><enclosure url="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.01.66.43.20/Stuff_5F00_V1.zip" length="25052" type="application/x-zip-compressed" /><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item><item><title>Getting started with ATL</title><link>http://msmvps.com/blogs/vandooren/archive/2009/01/20/getting-started-with-atl.aspx</link><pubDate>Tue, 20 Jan 2009 10:53:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1663592</guid><dc:creator>vanDooren</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/rsscomments.aspx?PostID=1663592</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/vandooren/commentapi.aspx?PostID=1663592</wfw:comment><comments>http://msmvps.com/blogs/vandooren/archive/2009/01/20/getting-started-with-atl.aspx#comments</comments><description>&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;I am currently working on some projects where I have to program a DCOM server. There are several reasons why it has to be DCOM and C++, instead of e.g. .NET remoting and C#.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The biggest pain (imo) about DCOM is that the technology stems from an era when the internet was no ubiquitous, and there were no huge forums filled with experts, or blogs by programming gurus and sites like codeproject.com There were newsgroups, but those were generally only used for specific problems.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;There is a vast amount of concise information about everything you can do with the .NET framework. For DCOM there is &amp;hellip; a big dark void.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Granted, there are several resources out there. But if you look on sites like codeproject, you will find that most of the articles about DCOM and ATL are written before 2003. Most of the information out there will not cover the improvements that have been made to ATL (or DCOM) since the last 5 years.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;And when looking into the more obscure corners of DCOM, there are some things that noone really likes to talk about because the documented semantics are so vague, and if you look into things like custom IMoniker implementation&amp;hellip; well&amp;hellip; that is a story for another day.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Understanding DCOM&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;The most important thing with DCOM is that you understand the basics really well. I guess this is true for most things, but unlike other things like .NET, DCOM does not cut you any slack, and does not provide you with tons of helpful diagnostic information.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;When I started with DCOM a couple of years ago, I first read &amp;lsquo;Essential COM&amp;rsquo; by Don Box. This is really the most excellent book on COM ever.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Of course, this information becomes vitally important in the real world when you have to debug a problem, because no tool is going to tell you anything useful with DCOM related crashes.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;Understanding ATL&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;In the real world (unless maintaining legacy code) you use ATL to write COM clients or servers. Personally, I don&amp;rsquo;t like books that just tell me how to use technology XYZ. I like to understand the &amp;lsquo;why&amp;rsquo; and &amp;lsquo;how&amp;rsquo; too.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;This is where I have to give big thanks to &amp;lsquo;ATL Internals, Second Edition&amp;rsquo;. It is one of the very few books on ATL that were written for VS2005, and it is still valid for VS2008. It is also an extremely well written book.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;If you are starting with ATL (or if you want to know &lt;i style="mso-bidi-font-style:normal;"&gt;how&lt;/i&gt; it works) buy this book. This book is very, very good, and will teach you a lot.&lt;/span&gt;&lt;/p&gt;
&lt;h2 style="margin:12pt 0cm 3pt;"&gt;&lt;em&gt;&lt;span style="font-size:large;font-family:Arial;"&gt;What happens next?&lt;/span&gt;&lt;/em&gt;&lt;/h2&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Over the next weeks / months I will probably write a couple of articles describing how to do specific things with ATL. One article that is nearly finished is about implementing and using IEnumString using ATL.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Not rocket science by any measure, but ATL is severely lacking in the area of easy-to-find, up-to-date and to-the-point examples. So I figured that there is still value in writing about the ancient art of circles and lollipops, even if many developers probably think COM and ATL are no longer worth bothering with.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;Oh and I released some &lt;a href="http://msmvps.com/blogs/vandooren/archive/2007/04/08/the-ancient-art-of-circles-and-lollipops-part-2.aspx" title="http://msmvps.com/blogs/vandooren/archive/2007/04/08/the-ancient-art-of-circles-and-lollipops-part-2.aspx"&gt;win32 DCOM demo projects some time ago&lt;/a&gt;. They were interesting for me because making them taught me a lot about the raw DCOM stuff that you normally don&amp;rsquo;t see with ATL. But I&amp;rsquo;ve always found that it is always useful to know what makes the motor hum.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin:0cm 0cm 12pt;" class="MsoNormal"&gt;&lt;span style="font-size:small;font-family:Times New Roman;"&gt;So while they are not terribly useful for practical purposes, they are well documented and they might be useful if you are working your way through &amp;lsquo;Essential COM&amp;rsquo;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1663592" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/vandooren/archive/tags/C_2B002B00_/default.aspx">C++</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/Windows+Platform/default.aspx">Windows Platform</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/cplusplus/default.aspx">cplusplus</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/ATL/default.aspx">ATL</category><category domain="http://msmvps.com/blogs/vandooren/archive/tags/DCOM/default.aspx">DCOM</category></item></channel></rss>