<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.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>The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx</link><description>Almost anything is possible.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96807</link><pubDate>Fri, 26 Mar 2004 14:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96807</guid><dc:creator>Reuben Harris</dc:creator><description>&lt;br&gt;I once saw a whole family of COM objects whose clients were forced to clean up via something like :&lt;br&gt;&lt;br&gt; while (pObj-&amp;gt;Release() &amp;gt; 0) {&lt;br&gt; }&lt;br&gt;&lt;br&gt;I.e. you had to keep calling Release() until the refcount dropped to zero, at which point you could be sure they'd destroyed themselves.&lt;br&gt; &lt;br&gt;Unless you did that (cos their reference counting was broken) apps leaked horribly and machines eventually died.&lt;br&gt;&lt;br&gt;Did I mention that this was on ultra-mission-critical City finance systems?!&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96826</link><pubDate>Fri, 26 Mar 2004 15:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96826</guid><dc:creator>foo</dc:creator><description>Once again, these problems wouldn't be there if Microsoft Windows had enforced correct behaviour to begin with.&lt;br&gt;&lt;br&gt;That, and &amp;lt;big-name program&amp;gt; is most likely Office 95.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96833</link><pubDate>Fri, 26 Mar 2004 15:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96833</guid><dc:creator>Matt</dc:creator><description>Every time I hear an accusation such as &amp;quot;don't upgrade to MS update X because it introduces an incompatibility with program Y,&amp;quot; I wish MS would publish details on why program Y was to blame.  And links to MS public docs that spell out the rules that Y is violating.&lt;br&gt;&lt;br&gt;Not only would this shut up the conspiraicy theorists, it just might shame the vendor of program Y into not doing these problems.&lt;br&gt;&lt;br&gt;Of course, politics would let that happen.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96907</link><pubDate>Fri, 26 Mar 2004 17:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96907</guid><dc:creator>Jonathan</dc:creator><description>FYI, IShellView is derived from IOleWindow, not IOleView. :-)</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96922</link><pubDate>Fri, 26 Mar 2004 17:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96922</guid><dc:creator>senkwe</dc:creator><description>Somebody care to explain the &amp;quot;Requiring A Secret Knock&amp;quot; example?</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96946</link><pubDate>Fri, 26 Mar 2004 18:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96946</guid><dc:creator>BarryTannenbaum</dc:creator><description>re: calling Release until it returns 0&lt;br&gt;&lt;br&gt;Don't forget that returning the reference count from AddRef and Release is *optional*.  Attempting to write code to debug COM object reference counting errors is a nightmare because of this.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96951</link><pubDate>Fri, 26 Mar 2004 18:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96951</guid><dc:creator>Peter Evans</dc:creator><description>The &amp;quot;Requiring A Secret Knock&amp;quot; example has to deal with failing to have the Class constructor's CreateInstance function invoked by CoCreateInstance allow itself to be assigned to an IUnknown pointer on creation.  Yet this is perfectly legal since all objects derive from IUnknown.&lt;br&gt;&lt;br&gt;Its like the class constructor has this psuedo c++ code.  NOTE: iid is a guid so equivalence is usually done differently.&lt;br&gt;&lt;br&gt;CreateInstance(...) {&lt;br&gt;switch (iid) {&lt;br&gt;case: IID_IShellFolder&lt;br&gt;{ //instatiate IShellFolder and return interface IShellFolder &lt;br&gt;... }&lt;br&gt;case: IID_IUnknown&lt;br&gt;{ ...; return E_NOINTERFACE}&lt;br&gt;...&lt;br&gt;}&lt;br&gt;instead of &lt;br&gt;CreateInstance(...) {&lt;br&gt;switch (iid) {&lt;br&gt;case: IID_IShellFolder&lt;br&gt;{ //instatiate IShellFolder and return interface IShellFolder &lt;br&gt;... }&lt;br&gt;case: IID_IUnknown&lt;br&gt;{ //instatiate IShellFolder and return interface IUnknown&lt;br&gt;}&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96958</link><pubDate>Fri, 26 Mar 2004 18:23:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96958</guid><dc:creator>Peter Evans</dc:creator><description>Forgetting to respond to your own interface&lt;br&gt;QI==Are you you? NO!&lt;br&gt;&lt;br&gt;&amp;quot;FOO: Once again, these problems wouldn't be there if Microsoft Windows had enforced correct behaviour to begin with. &lt;br&gt;&lt;br&gt;That, and &amp;lt;big-name program&amp;gt; is most likely Office 95. &amp;quot;&lt;br&gt;&lt;br&gt;ooh! Great IDEA! Microsoft Windows the new stack machine enforcement agency regime (SMEAR).  No CPU should be allowed to run without it. :)  &lt;br&gt;&lt;br&gt;With any software its a wonder dynamic binding works at all.  I suppose we could all live in the realm of CNF and distributive protocol MATHEMATICS where if it doesn't conform to safety and liveness properties or discrete mathematics the implementation shouldn't exist or execute even if it does.  Have a dull deterministic day foo.&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#96965</link><pubDate>Fri, 26 Mar 2004 18:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:96965</guid><dc:creator>Simon Cooke [exMSFT]</dc:creator><description>Barry: Returning the value from Release is not optional; however, its value is binary - either the object has been completely released, or it's in use.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97014</link><pubDate>Fri, 26 Mar 2004 19:39:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97014</guid><dc:creator>senkwe</dc:creator><description>Peter, thanks for the response. If I understand you correctly &amp;quot;Requiring A Secret Knock&amp;quot; is a re-wording of &amp;quot;Forgetting to respond to IUnknown&amp;quot;? At least that's how I saw it and hence my confusion. &lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97026</link><pubDate>Fri, 26 Mar 2004 19:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97026</guid><dc:creator>Barry Tannenbaum</dc:creator><description>You're right Simon, I wrote in haste.&lt;br&gt;&lt;br&gt;However, it still would have been *way* easier if AddRef and Release were required to return the reference count.&lt;br&gt;&lt;br&gt;Of course, that raises the question of whether this is the reference count for the interface or the object, which is probably why it's undefined.  But it's still a pain.  Trying to divine the reference count from the outside is error-prone, to say the least.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97076</link><pubDate>Fri, 26 Mar 2004 21:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97076</guid><dc:creator>Tony Cox</dc:creator><description>More to the point, trying to divine the reference count from outside is almost certainly an error. What would you do with the reference count if you knew it?&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97080</link><pubDate>Fri, 26 Mar 2004 21:11:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97080</guid><dc:creator>Tony Cox</dc:creator><description>Follow up:&lt;br&gt;&lt;br&gt;Specifically, think about the multi-threaded case. The reference count might change between AddRef/Release returning, and your thread executing the next instruction. So the value has no meaning that you can safely act upon. (What would you want to do with it anyway?)</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97180</link><pubDate>Sat, 27 Mar 2004 00:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97180</guid><dc:creator>Skywing</dc:creator><description>He stated that he would be using it *to debug* COM objects.  I think this is a legitimate use of the return value; even MSDN itself agrees ( &lt;a target="_new" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_q2z_59np.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/com/htm/cmi_q2z_59np.asp&lt;/a&gt; ):&lt;br&gt;&amp;quot;Return Value&lt;br&gt;Returns the resulting value of the reference count, which is used for diagnostic/testing purposes only.&amp;quot;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97253</link><pubDate>Sat, 27 Mar 2004 04:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97253</guid><dc:creator>Pavel Lebedinsky</dc:creator><description>I suspect that the reason why AddRef is not required to return exact reference count is to allow implementations to simply return the result of InterlockedIncrement.&lt;br&gt;&lt;br&gt;On old CPUs (and OSes), return value of InterlockedIncement was not guaranteed to be exact. The only thing you could depend on was the sign of the return value (&lt;a target="_new" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/interlockedincrement.asp"&gt;http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/interlockedincrement.asp&lt;/a&gt;).</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97268</link><pubDate>Sat, 27 Mar 2004 05:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97268</guid><dc:creator>Raymond Chen</dc:creator><description>In the presence of proxies, the return value also loses its meaning, since it is the reference count of the proxy, not of the underlying object.&lt;br&gt;&lt;br&gt;foo: How do you recommend that Microosft enforce correct behavior? Since an IID is just a GUID, you cannot prove just by looking at an IID whether it is derived from another IID. You also cannot prove that an object implements all the methods correctly. I've seen objects that break the rules but but only when you ask them for a *specific* interface:&lt;br&gt;&lt;br&gt;IUnknown::QueryInterface() {&lt;br&gt;if (riid == IID_BadInterface)&lt;br&gt;{ return S_OK; /*error*/ }&lt;br&gt;else { ... /* correct implementation */ }&lt;br&gt;}&lt;br&gt;&lt;br&gt;The only way to detect this ahead of time is to attempt to QueryInterface all 2^128 IIDs in the hopes of finding the bad one. And it's possible that the bad QI is written like this:&lt;br&gt;&lt;br&gt;IUnknown::QueryInterface() {&lt;br&gt;if (... complex condition ...)&lt;br&gt;{ return S_OK; /*error*/ }&lt;br&gt;else { ... /* correct implementation */ }&lt;br&gt;}&lt;br&gt;&lt;br&gt;how can you test externally for this error? &amp;quot;complex condition&amp;quot; could be anything.</description></item><item><title>re: enforced correct behaviour</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#97275</link><pubDate>Sat, 27 Mar 2004 05:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:97275</guid><dc:creator>Michael Entin</dc:creator><description>Judging by earlier topic on the different ways companies defraud WHQL certification process, enforcing correct COM behavior does not seem possible.&lt;br&gt;&lt;br&gt;The best solution is good libraries, like ATL. I've seen dozens of such bugs in pre-ATL code, but don't remember any in ATL-based code.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#100438</link><pubDate>Sat, 27 Mar 2004 21:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100438</guid><dc:creator>Raymond Chen</dc:creator><description>The solution to the &amp;quot;Secret Knock&amp;quot; is to write your class factory like this: &lt;br&gt;&lt;br&gt;CreateInstance(...) { &lt;br&gt;CObject *p = new CObject(...); &lt;br&gt;if (p) { &lt;br&gt;p-&amp;gt;QueryInterface(...); &lt;br&gt;p-&amp;gt;Release(); &lt;br&gt;} &lt;br&gt;} &lt;br&gt;&lt;br&gt;If you switch on the iid in your CreateInstance, then when you add a new interface to your CObject, you will also have to update the CreateInstance to support it - something you can easily forget to do.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#100496</link><pubDate>Sun, 28 Mar 2004 00:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100496</guid><dc:creator>JCAB</dc:creator><description>Raymond: &amp;quot;How do you recommend that Microosft enforce correct behavior?&amp;quot;&lt;br&gt;&lt;br&gt;Designing the interface so that it's a lot harder to make mistakes, of course. Implementing CoQueryInterface as a free API function that takes care of all the trivial cases would do just nicely.&lt;br&gt;&lt;br&gt;Same goes for CreateInstance(). There's no reason for CoCreateInstance() not to handle the interface itself.&lt;br&gt;&lt;br&gt;Well... yes, there's a reason: CreateInstance() could decide not to create the object at all if the interface is not supported. But, if a COM class was required to publish its list of supported interfaces together with CreateInstance(), that wouldn't be needed either. Besides, that would help a free CoQueryInterface function to properly handle hierarchies itself.&lt;br&gt;&lt;br&gt;JCAB&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#100575</link><pubDate>Sun, 28 Mar 2004 06:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100575</guid><dc:creator>Raymond Chen</dc:creator><description>The problem with the proposed CoQueryInterface is that it would prevent people from implementing tear-offs, dynamic interfaces, object pseudo-interfaces, and other clever games inside QI. But the worst part would be that everybody would have to register their interfaces so CoQI can know about everybody's interface hierarchies. Today you can run guidgen and ta-da, you have a new interface. No registration necessary. Just start using it.&lt;br&gt;&lt;br&gt;The new world of the CLR has basically done what you suggested - interface management is no longer done by the object itself. Instead, you tell the CLR what your objects and interfaces derive from and it implements QI for you.  (Well, okay, the CLR QI doesn't support tear-offs or dynamic interfaces...)</description></item><item><title>Abusing the calling convention!</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#100845</link><pubDate>Mon, 29 Mar 2004 01:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100845</guid><dc:creator>Norman Diamond</dc:creator><description>&amp;gt; IUnknown *punk;&lt;br&gt;&amp;gt; psf-&amp;gt;QueryInterface(IID_IUnknown, (void**)&lt;br&gt;&amp;gt;  &amp;amp;punk);&lt;br&gt;&lt;br&gt;punk is not a void*.  punk is an IUnknown*.&lt;br&gt;&lt;br&gt;void** is not a universal pointer type.  void* is a universal pointer type, and char* and relatives are grandparented in to be equivalent in that way, but void** is not.&lt;br&gt;&lt;br&gt;Casting &amp;amp;punk to type (void**) is just as risky as casting it to type (int*) or (struct s*).  Casting &amp;amp;punk to type (void**) is just as risky as casting &amp;amp;some_int to type (double*).&lt;br&gt;&lt;br&gt;Casting &amp;amp;punk to type (void*) would be safe, but that is not what you did.&lt;br&gt;&lt;br&gt;If you want to obey the calling convention and avoid horrible deaths, you have to do this:&lt;br&gt;IUnknown *punk;&lt;br&gt;void *punkvoid;&lt;br&gt;psf-&amp;gt;QueryInterface(IID_IUnknown, &amp;amp;punkvoid);&lt;br&gt;punk = (IUnknown *) punkvoid;&lt;br&gt;&lt;br&gt;And you know it.  Lots of other MSDN contributors made the same identical mistake.  Many of your articles correct the mistakes of MSDN contributors, and this should have been one of them.  You'll probably tell me that it works in all VC++ implementations to date, but that doesn't make it correct code, you're still violating the calling convention.&lt;br&gt;&lt;br&gt;(By the way, the requirement for that (IUnknown *) cast, though safe, is still dangerous.  All usage of casts desensitizes people so they forget to check how dangerous casts usually are.  It would have been better if C++ still allowed C-style assignment directly from void* to other data pointer types, with implicit conversion instead of requiring the cast.  Of course the compiler would still generate code necessary for this conversion.)</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#100946</link><pubDate>Mon, 29 Mar 2004 07:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100946</guid><dc:creator>Raymond Chen</dc:creator><description>I agree that the distinction is theoretically necessary (on word-addressed machines), but COM assumes a byte-addressed machine.&lt;br&gt;&lt;br&gt;I think the intentionally-incorrect (void**) was chosen to try to catch people making the mistake&lt;br&gt;&lt;br&gt;IUnknown *punk; &lt;br&gt;psf-&amp;gt;QueryInterface(IID_IUnknown, punk); &lt;br&gt;&lt;br&gt;which would otherwise go unnoticed.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#101053</link><pubDate>Mon, 29 Mar 2004 11:49:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:101053</guid><dc:creator>DrPizza</dc:creator><description>&amp;quot;It would have been better if C++ still allowed C-style assignment directly from void* to other data pointer types, with implicit conversion instead of requiring the cast&amp;quot;&lt;br&gt;&lt;br&gt;&amp;quot;better&amp;quot; in the sense of preventing the compiler from catching certain bugs?&lt;br&gt;&lt;br&gt;How's that an improvement?&lt;br&gt;&lt;br&gt;I don't know about you, but I think it's quite desirable that this issue an error:&lt;br&gt;char ch(0);&lt;br&gt;char* pc(&amp;amp;ch);&lt;br&gt;void* pv(pc);&lt;br&gt;int* pi(pv);&lt;br&gt;*pi = 0; // ruh roh raggy.&lt;br&gt;&lt;br&gt;void* can point at anything, so it's not unreasonable that I should have to specify exactly what I want to convert to.&lt;br&gt;&lt;br&gt;It's not immediately clear how this is a calling convention issue; object representations (the requirement that&lt;br&gt;T t;&lt;br&gt;foo((void**)&amp;amp;t)&lt;br&gt;is equivalent to&lt;br&gt;T t;&lt;br&gt;void* pv(&amp;amp;t);&lt;br&gt;foo(&amp;amp;pv);&lt;br&gt;insofar as in either case the pointer can be dereferenced once to yield a T* and twice to yield a T) should surely not be specified as part of a calling convention.&lt;br&gt;&lt;br&gt;The use of C style casts is another abomination.&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#101842</link><pubDate>Tue, 30 Mar 2004 00:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:101842</guid><dc:creator>Norman Diamond</dc:creator><description>3/29/2004 12:53 AM Raymond Chen:&lt;br&gt;&lt;br&gt;&amp;gt; I agree that the distinction is&lt;br&gt;&amp;gt; theoretically necessary (on word-addressed&lt;br&gt;&amp;gt; machines), but COM assumes a byte-addressed&lt;br&gt;&amp;gt; machine.&lt;br&gt;&lt;br&gt;You've proved in other topics that you know why this excuse is invalid.&lt;br&gt;&lt;br&gt;I've read that there's a machine where some pointers can be 128 bytes long (that's the pointer not the item being pointed to), but I don't think all pointers are 128 bytes long on that machine.  I don't know if it's a byte-addressed machine though.  If we want to consider some known byte-addressed machines, we know of some cases where pointers to member functions aren't the same size as pointers to ordinary functions, though I admit that neither of these is a pointer to data or void*.&lt;br&gt;&lt;br&gt;&amp;gt; I think the intentionally-incorrect (void**)&lt;br&gt;&amp;gt; was chosen to try to catch people making the&lt;br&gt;&amp;gt; mistake&lt;br&gt;&amp;gt; IUnknown *punk;&lt;br&gt;&amp;gt; psf-&amp;gt;QueryInterface(IID_IUnknown, punk);&lt;br&gt;&amp;gt; which would otherwise go unnoticed.&lt;br&gt;&lt;br&gt;I'm really confused by this statement.  It doesn't see incorrect (intentionally or otherwise) to define the second parameter with type (void**).  So I can only guess at the moment, would you consider it more correct to define the second parameter with type (IUnknown**)?  But if that were done, then your example error would indeed be caught.  Besides, it would prevent querying for interfaces other than IUnknown, so I don't really think that would be more correct.&lt;br&gt;&lt;br&gt;On the other hand, use of a cast prevents the compiler from diagnosing lots of possible actual errors.  This is really why it is dangerous to desensitize people to the use of this dangerous tool.&lt;br&gt;&lt;br&gt;Anyway, you know that the following code works, and you know why it should be used:&lt;br&gt;void *punkvoid; &lt;br&gt;psf-&amp;gt;QueryInterface(IID_IUnknown, &amp;amp;punkvoid); &lt;br&gt;punk = (IUnknown *) punkvoid;&lt;br&gt;&lt;br&gt;&lt;br&gt;3/29/2004 4:49 AM DrPizza:&lt;br&gt;&lt;br&gt;&amp;gt; &amp;quot;better&amp;quot; in the sense of preventing the&lt;br&gt;&amp;gt; compiler from catching certain bugs?&lt;br&gt;&amp;gt; int* pi(pv); &lt;br&gt;&lt;br&gt;You think that C++'s requirement for coding casts prevents this bug?&lt;br&gt;int* pi = (int*) pv;&lt;br&gt;&lt;br&gt;What else are you going to do with your pv?  If you think it points to something, you're planning to use the value of that something eventually.  Sure when you think it points to something and it doesn't, that's a bug, but that bug is not eliminated by desensitizing people to the use of casts.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#102659</link><pubDate>Tue, 30 Mar 2004 08:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:102659</guid><dc:creator>DrPizza</dc:creator><description>&amp;quot;You think that C++'s requirement for coding casts prevents this bug? &amp;quot;&lt;br&gt;&lt;br&gt;It's self-evident.  The code won't compile.&lt;br&gt;&lt;br&gt;&amp;quot;What else are you going to do with your pv?&amp;quot;&lt;br&gt;Who knows?  Normally it's given to someone else to deal with because I'm working with some crufy C API.&lt;br&gt;&lt;br&gt;&amp;quot;If you think it points to something, you're planning to use the value of that something eventually. Sure when you think it points to something and it doesn't, that's a bug, but that bug is not eliminated by desensitizing people to the use of casts. &amp;quot;&lt;br&gt;&lt;br&gt;There is no desensitization.  Casts like that are extremely rare in good C++.  Far from desensitizing programmers, it makes abundantly clear to them that they're doing something that's potentially dangerous.  They only perform such casts infrequently, so it serves as an effective warning.&lt;br&gt;</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#104305</link><pubDate>Tue, 30 Mar 2004 23:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:104305</guid><dc:creator>Norman Diamond</dc:creator><description>&amp;gt;&amp;gt; You think that C++'s requirement for coding&lt;br&gt;&amp;gt;&amp;gt; casts prevents this bug?&lt;br&gt;&amp;gt;&amp;gt; int* pi = (int*) pv;&lt;br&gt;&amp;gt;&lt;br&gt;&amp;gt; It's self-evident. The code won't compile.&lt;br&gt;&lt;br&gt;That doesn't look very self-evident to me.&lt;br&gt;&lt;br&gt;&amp;gt; There is no desensitization. Casts like that&lt;br&gt;&amp;gt; are extremely rare in good C++.&lt;br&gt;&lt;br&gt;I wonder how to reply to this.&lt;br&gt;&lt;br&gt;1.  C++ forces that kind of cast to be used, whereas C allows pointers of type (void*) to be assigned to pointers that point to data.  That was because C knew that (void*) was added to meet a need, which it did meet, while it did not replace the need for ordinary pointers to be used normally.  Do you mean that good C++ code extremely rarely has any need for pointers of type (void*), as opposed to good C code which only moderately needed them?&lt;br&gt;&lt;br&gt;2.  At least it seems you're agreeing with me that this:&lt;br&gt;&amp;gt; [...] (void**)&amp;amp;punk [...]&lt;br&gt;is not good C++ code.  But the problem remains that even when this bad code is removed, C++ still forces a cast to be used in a subsequent assignment, in the location where C would not force it.</description></item><item><title>re: The ways people mess up IUnknown::QueryInterface</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#104752</link><pubDate>Wed, 31 Mar 2004 13:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:104752</guid><dc:creator>DrPizza</dc:creator><description>&amp;quot;1. C++ forces that kind of cast to be used, whereas C allows pointers of type (void*) to be assigned to pointers that point to data.&amp;quot;&lt;br&gt;Which is good, it prevents accidents.&lt;br&gt;&lt;br&gt;&amp;quot;That was because C knew that (void*) was added to meet a need, which it did meet, while it did not replace the need for ordinary pointers to be used normally. Do you mean that good C++ code extremely rarely has any need for pointers of type (void*), as opposed to good C code which only moderately needed them? &amp;quot;&lt;br&gt;Correct.  In general I would suggest that the only time void* should be used in C++ is when calling those unwrapped C APIs that require it.  Many of those APIs (though not this one) probably deserve lightweight wrappers anyway.&lt;br&gt;&lt;br&gt;&amp;quot;is not good C++ code. But the problem remains that even when this bad code is removed, C++ still forces a cast to be used in a subsequent assignment, in the location where C would not force it. &amp;quot;&lt;br&gt;But that's a /good/ thing, not a bad one.&lt;br&gt;</description></item><item><title>ok</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#114283</link><pubDate>Fri, 16 Apr 2004 01:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:114283</guid><dc:creator>Skywing</dc:creator><description>I'm gay</description></item><item><title>on getting IOleCommandTarget wrong (and a bit in the middle about ActiveX controls)</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#573777</link><pubDate>Wed, 12 Apr 2006 02:38:57 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:573777</guid><dc:creator>jeff's WebLog</dc:creator><description>IOleCommandTarget is very useful.&amp;amp;amp;nbsp; It provides a generic way of sending commands between objects.&amp;amp;amp;nbsp;...</description></item><item><title>Do not overload the E_NOINTERFACE error</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#1239913</link><pubDate>Fri, 08 Dec 2006 18:00:04 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1239913</guid><dc:creator>The Old New Thing</dc:creator><description>&lt;p&gt;Returning E_NOINTERFACE from IUnknown::QueryInterface has very specific meaning.&lt;/p&gt;
</description></item><item><title>on CComQIPtr</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#2078395</link><pubDate>Wed, 11 Apr 2007 01:43:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2078395</guid><dc:creator>jeff's WebLog</dc:creator><description>&lt;p&gt;You're writing some code that uses COM. Do you use SmartPointers or not use SmartPointers? Debate on&lt;/p&gt;
</description></item><item><title>How my lack of understanding of how processes exit on Windows XP forced a security patch to be recalled</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#2414849</link><pubDate>Fri, 04 May 2007 23:44:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2414849</guid><dc:creator>The Old New Thing</dc:creator><description>&lt;p&gt;Watch what?&lt;/p&gt;</description></item><item><title>The real cost of compatibility is not in the hacks; the hacks are small potatoes</title><link>http://blogs.msdn.com/oldnewthing/archive/2004/03/26/96777.aspx#4011672</link><pubDate>Mon, 23 Jul 2007 19:46:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4011672</guid><dc:creator>The Old New Thing</dc:creator><description>&lt;p&gt;It's in the design.&lt;/p&gt;</description></item></channel></rss>