<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>voyce &#187; COM</title>
	<atom:link href="http://www.voyce.com/index.php/category/software-development/com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.voyce.com</link>
	<description>Programming and debugging tidbits</description>
	<lastBuildDate>Sat, 03 Jul 2010 12:40:51 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>.NET 4.0 Type Equivalence causes BadImageFormatException</title>
		<link>http://www.voyce.com/index.php/2010/04/23/net-4-0-type-equivalence-causes-badimageformatexception/</link>
		<comments>http://www.voyce.com/index.php/2010/04/23/net-4-0-type-equivalence-causes-badimageformatexception/#comments</comments>
		<pubDate>Fri, 23 Apr 2010 10:53:33 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[WinDbg]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET4]]></category>
		<category><![CDATA[CLR]]></category>
		<category><![CDATA[IL]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=840</guid>
		<description><![CDATA[Interop assemblies containing certain constructs will cause a BadImageFormatException in .NET 4.0]]></description>
			<content:encoded><![CDATA[<p>I recently discovered a nasty backward compatibility problem with the new type equivalence feature in .NET 4.0. Luckily it&#8217;s relatively difficult to hit it if you&#8217;re in a pure-C# environment, but if you happen to generate any assemblies directly using IL, you should watch out. Read on for all the gory details.<br />
<span id="more-840"></span></p>
<h2>What is .NET type equivalence?</h2>
<p>Described at a high level <a href="http://msdn.microsoft.com/en-us/library/dd997297.aspx">here</a>, .NET 4.0 type equivalence essentially gives you a way of indicating that different .NET types represent the same underlying COM type and is most commonly used in COM interop scenarios. One of the reasons for its introduction is to save developers from having to ship large interop DLLs with their software, e.g. the multi-megabyte Microsoft.Office.Interop. Instead the compiler can inline the definition of any types used, and mark them appropriately as representing the original COM types. </p>
<h2>The error</h2>
<p>We noticed that whenever we built and ran an application that referenced a DLL using .NET 2.0, it worked. Doing the same thing with .NET 4.0 caused a <a href="http://msdn.microsoft.com/en-us/library/system.badimageformatexception.aspx">BadImageFormatException</a>.<br />
<code><br />
Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' or one of its dependencies. An attempt was made to load a program with an incorrect format.<br />
   at X.Main()<br />
</code> </p>
<h2>Let&#8217;s dig!</h2>
<p>So, the BadImageFormatException doesn&#8217;t actually tell us much. Let&#8217;s break out WinDbg and see what we can find. Running the faulting app we can see several C++ exceptions before the CLR exception is thrown:<br />
<code><br />
(178c.790): C++ EH exception - code e06d7363 (first chance)<br />
...<br />
(178c.790): C++ EH exception - code e06d7363 (first chance)<br />
(178c.790): CLR exception - code e0434352 (first chance)<br />
</code><br />
I changed the exception handling settings to stop on C++ exceptions (<code>sxe eh</code>) then ran again to see where things were going wrong. It stopped here:<br />
<code><br />
0:000> kp<br />
ChildEBP RetAddr<br />
0012d15c 79084c0f KERNEL32!RaiseException+0x53<br />
0012d194 793371be MSVCR100_CLR0400!_CxxThrowException+0x48<br />
0012d5e4 79455cae clr!EEFileLoadException::Throw+0x1a8<br />
0012d634 794558d2 clr!CompareTypeTokens+0x200<br />
0012d6b0 791b5c00 clr!IsTypeDefEquivalent+0x102<br />
0012d6d4 791b2ca8 <b>clr!MethodTableBuilder::CheckForTypeEquivalence</b>+0x94<br />
0012d7ac 791b27c9 clr!MethodTableBuilder::BuildMethodTableThrowing+0x60d<br />
0012d9a4 791a4578 clr!ClassLoader::CreateTypeHandleForTypeDefThrowing+0x88e<br />
</code><br />
Interesting. Notice how the call stack contains some .NET 4.0 specific methods relating to the new type equivalence feature. We&#8217;re hitting a new code path, which is consistent with the fact that running against a down-level CLR works.</p>
<p>After a bit more toing-and-froing, I discovered that the C++ exception is thrown when <code>clr!MDInternalRO::IsValidToken</code> returns an error. By disassembling the function we can see it&#8217;s just looking at various bits in the token value, and it decides that the value passed (0&#215;02000000) isn&#8217;t valid. Looking at the output from ildasm that token doesn&#8217;t appear anywhere. And if we add a dump of the value, we can see that it indeed doesn&#8217;t look like the other tokens: </p>
<pre>
0:000> bu clr!MDInternalRO::IsValidToken "dd esp+8 L1; g"
...
0012f5a8  02000001
0012f31c  06000001
0012f2c0  02000002
0012f0f4  02000002
0012ebe4  01000001
0012e944  23000001
...
0012d5f4  02000000
(18ec.1ec8): C++ EH exception - code e06d7363 (first chance)
</pre>
<h2>What&#8217;s the culprit?</h2>
<p>So it looks pretty conclusive; the DLL contains something that the CLR isn&#8217;t expecting. But what? It&#8217;s time to break out the oldest tool in the troubleshooting box: the binary chop!</p>
<p>Eventually I got the referenced DLL down to only a single simple construct. Can you guess what it is? A global literal value. A <em>real</em> global value, one that isn&#8217;t even part of a type. Crazy huh? In IL it looks like this:<br />
<code><br />
.field public static literal valuetype Test.MyEnum LiteralValue = int32(0x00000001)<br />
</code><br />
It&#8217;s a literal value of an enumerated type. That&#8217;s important: using a value of a simple type (say int32) does not provoke the error.</p>
<p>Now, I wasn&#8217;t even sure that this is a valid IL construct, but according to the ECMA IL spec, specifically <a href="http://jilc.sourceforge.net/ecma_p2_cil.shtml#_Toc524940530">partition II, section 15</a>, it is:</p>
<blockquote><p>The CLI also supports global fields, which are fields declared outside of any type definition. Global fields shall be static.</p></blockquote>
<p>So it looks like we&#8217;re not doing anything illegal, backed up by the fact that the .NET 2.0 CLR can make use of it without a problem.</p>
<p>Interestingly, there&#8217;s another aspect that influences whether this code path is hit. As mentioned above, type equivalence is intended for use with interop libraries. As such, it only kicks in if your referenced assembly is marked with the PrimaryInteropAssembly attribute, e.g.:</p>
<p><code><br />
  .custom instance void [mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32,int32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 )<br />
</code></p>
<h2>The Fix?</h2>
<p>The issue is currently with Microsoft product support. Let&#8217;s see what they come up with; is it too esoteric for a hotfix&#8230;?</p>
<h2>The Repro</h2>
<p>Here&#8217;s some code and instructions on how to repro the problem.</p>
<ol>
<li>Build the IL into a DLL using ilasm.<br />
<code>"c:\WINNT\Microsoft.NET\Framework\v2.0.50727\ilasm.exe" /dll Test.il /output=Test.dll</code>
</li>
<li>Build the application into a .NET 4.0 EXE that references the DLL<br />
<code>"c:\winnt\Microsoft.NET\Framework\v4.0.30319\csc.exe" TestConsumer.cs /reference:Test.dll</code>
</li>
<li>Run the resulting <code>TestConsumer.exe</code> application and you&#8217;ll get the exception</li>
</ol>
<p><b>Test.il</b><br />
<code><br />
.assembly extern mscorlib<br />
{<br />
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )<br />
  .ver 2:0:0:0<br />
}<br />
.assembly Test<br />
{<br />
  .custom instance void [mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32,int32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 )<br />
  .hash algorithm 0x00008004<br />
  .ver 1:0:0:0<br />
}<br />
.module Test.dll<br />
.imagebase 0x00400000<br />
.file alignment 0x00000200<br />
.stackreserve 0x00100000<br />
.subsystem 0x0003<br />
.corflags 0x00000001 </p>
<p>.field public static literal valuetype Test.MyEnum LiteralValue = int32(0x00000001)</p>
<p>.class public auto ansi sealed Test.MyEnum<br />
       extends [mscorlib]System.Enum<br />
{<br />
  .field public specialname rtspecialname int32 value__<br />
  .field public static literal valuetype Test.MyEnum Zero = int32(0x00000000)<br />
  .field public static literal valuetype Test.MyEnum One = int32(0x00000001)<br />
}<br />
</code><br />
<b>TestConsumer.cs</b></p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">class</span> X
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> Main<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        var v <span style="color: #008000;">=</span> Test.<span style="color: #0000FF;">MyEnum</span>.<span style="color: #0000FF;">Zero</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2010/04/23/net-4-0-type-equivalence-causes-badimageformatexception/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Beware of using stack-based COM objects from .NET</title>
		<link>http://www.voyce.com/index.php/2010/01/21/beware-of-using-stack-based-com-objects-from-net/</link>
		<comments>http://www.voyce.com/index.php/2010/01/21/beware-of-using-stack-based-com-objects-from-net/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 17:16:57 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[WinDbg]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[mscorwks]]></category>
		<category><![CDATA[win32]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=618</guid>
		<description><![CDATA[COM objects that don't have the expected lifetime can cause chaos when combined with .NETs garbage collection system.]]></description>
			<content:encoded><![CDATA[<p>There are all sorts of nasty things to be aware of if you&#8217;re mixing reference-counted COM objects with garbage-collected .NET. For instance, if you&#8217;re implementing COM objects in C++ then you&#8217;re free to allocate them anywhere you like; on the heap or perhaps on the stack if you know they&#8217;re only used in some specific scope.</p>
<p>But what happens if during the lifetime of that stack based COM object, it gets used from .NET? A runtime callable wrapper (RCW) will be created around the object. And this RCW expects to be able to keep the underlying object alive by incrementing its reference count. Of course, the stack-based object will soon go out of scope, and regardless of its reference count the object will be destroyed and the pointer that the RCW contains will no longer be valid. It points into the stack, so when the RCW gets cleaned-up, the CLR will call via this pointer into memory that contains garbage and you&#8217;ll get something nasty like an access violation or illegal instruction exception. </p>
<p><span id="more-618"></span></p>
<p>It&#8217;s fairly easy to reproduce this to see where things go wrong. It can be useful to see where the CLR blows up, and how we can identify this as the cause.</p>
<p>Lets start by creating a simple pseudo-COM object that implements just the bare minimum to be usable:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">class</span> MyClass <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> IUnknown
<span style="color: #008000;">&#123;</span>
<span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
	MyClass<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">:</span>l<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
	STDMETHOD_<span style="color: #008000;">&#40;</span>ULONG, AddRef<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> InterlockedIncrement<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>l<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
	STDMETHOD_<span style="color: #008000;">&#40;</span>ULONG, Release<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> InterlockedDecrement<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>l<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
	STDMETHOD<span style="color: #008000;">&#40;</span>QueryInterface<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#40;</span>REFIID iid, <span style="color: #0000ff;">void</span> <span style="color: #000040;">**</span> ppvObject<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>iid <span style="color: #000080;">==</span> IID_IUnknown<span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #000040;">*</span>ppvObject <span style="color: #000080;">=</span> <span style="color: #0000dd;">this</span><span style="color: #008080;">;</span>
			AddRef<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                        <span style="color: #0000ff;">return</span> S_OK<span style="color: #008080;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0000ff;">return</span> E_NOINTERFACE<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
	<span style="color: #0000ff;">long</span> l<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></div></div>

<p>We&#8217;ll also need a COM visible .NET object that will use the object. It doesn&#8217;t actually need to be COM visible, but that&#8217;s the easiest way to access it from C++, in my opinion.</p>
<p>I&#8217;ve created the COM object in F#. It&#8217;s a trivial class that has a single interface, with a single method that takes the object we pass to it and prints its type. This is enough for the RCW to be created.</p>

<div class="wp_syntax"><div class="code"><pre class="fsharp" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">open</span> System
<span style="color: #06c; font-weight: bold;">open</span> System<span style="color: #000080;">.</span><span style="color: #505090;">Runtime</span><span style="color: #000080;">.</span><span style="color: #505090;">InteropServices</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">module</span> Module1 <span style="color: #000080;">=</span>
&nbsp;
    <span style="color: #000080;">&#91;</span><span style="color: #000080;">&lt;</span>ComVisible<span style="color: #000080;">&#40;</span><span style="color: #06c; font-weight: bold;">true</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">;</span> InterfaceType<span style="color: #000080;">&#40;</span>ComInterfaceType<span style="color: #000080;">.</span><span style="color: #505090;">InterfaceIsIUnknown</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">&gt;</span><span style="color: #000080;">&#93;</span>
    <span style="color: #06c; font-weight: bold;">type</span> <span style="color: #06c; font-weight: bold;">public</span> IConsumer <span style="color: #000080;">=</span> 
        <span style="color: #06c; font-weight: bold;">abstract</span> <span style="color: #06c; font-weight: bold;">member</span> UseObject <span style="color: #000080;">:</span> o<span style="color: #000080;">:</span>obj <span style="color: #000080;">-&gt;</span> unit
&nbsp;
    <span style="color: #000080;">&#91;</span><span style="color: #000080;">&lt;</span>ComVisible<span style="color: #000080;">&#40;</span><span style="color: #06c; font-weight: bold;">true</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">;</span> ClassInterface<span style="color: #000080;">&#40;</span>ClassInterfaceType<span style="color: #000080;">.</span><span style="color: #505090;">None</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">&gt;</span><span style="color: #000080;">&#93;</span>
    <span style="color: #06c; font-weight: bold;">type</span> <span style="color: #06c; font-weight: bold;">public</span> Consumer<span style="color: #000080;">&#40;</span><span style="color: #000080;">&#41;</span> <span style="color: #000080;">=</span>
        <span style="color: #06c; font-weight: bold;">interface</span> IConsumer <span style="color: #06c; font-weight: bold;">with</span>
            <span style="color: #06c; font-weight: bold;">member</span> this<span style="color: #000080;">.</span><span style="color: #505090;">UseObject</span> <span style="color: #000080;">&#40;</span>o<span style="color: #000080;">:</span>obj<span style="color: #000080;">&#41;</span> <span style="color: #000080;">=</span>
                Console<span style="color: #000080;">.</span><span style="color: #505090;">WriteLine</span> <span style="color: #000080;">&#40;</span>sprintf <span style="color: #008080;">&quot;%A&quot;</span> <span style="color: #000080;">&#40;</span>o<span style="color: #000080;">.</span><span style="color: #505090;">GetType</span><span style="color: #000080;">&#40;</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">&#41;</span><span style="color: #000080;">&#41;</span></pre></div></div>

<p>We can compile this into a DLL, then run regasm with the /tlb switch to generate a type library (TLB):</p>
<pre>
fsc -o:obj\Debug\testStackObjectsFs.dll Module1.fs
regasm /tlb:testStackObjectsFs.tlb testStackObjectsFs.dll
</pre>
<p>That can be #imported back into our test harness:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#import &quot;testStackObjectsFs.tlb&quot;</span></pre></div></div>

<p>Now we&#8217;re ready to put together some code that creates an instance of our object on the stack and passes it to our .NET component:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// Create an instance of our &quot;COM object&quot; on the stack</span>
	MyClass obj<span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #666666;">// Create a managed object</span>
	testStackObjectsFs<span style="color: #008080;">::</span><span style="color: #007788;">IConsumerPtr</span> mgd<span style="color: #008000;">&#40;</span>__uuidof<span style="color: #008000;">&#40;</span>testStackObjectsFs<span style="color: #008080;">::</span><span style="color: #007788;">Consumer</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #666666;">// and pass our COM object to it</span>
	mgd<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>UseObject<span style="color: #008000;">&#40;</span>_variant_t<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> _tmain<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, _TCHAR<span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #666666;">// Initialise the COM runtime, for our purposes it doesn't</span>
	<span style="color: #666666;">// matter which threading model we use</span>
	CoInitializeEx<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">NULL</span>, COINIT_MULTITHREADED<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #666666;">// Call a separate function, to ensure stack-based objects</span>
	<span style="color: #666666;">// are out-of-scope on return.</span>
	Foo<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
	<span style="color: #666666;">// Wait for some input</span>
	_getch<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Now, if you run this from within Visual Studio, if you&#8217;re vigilant (and you haven&#8217;t got your debugger set to stop on access violations), then you&#8217;ll notice this in the output window after the return statement executes:<br />
<code><br />
...<br />
The thread 'Win32 Thread' (0x15b0) has exited with code 11001 (0x2af9).<br />
The thread 'Win32 Thread' (0x1110) has exited with code 0 (0x0).<br />
<b>First-chance exception at 0x00850a2b in testStackObjects.exe: 0xC0000005: Access violation reading location 0x00850a2b.</b><br />
The thread 'DebuggerRCThread::ThreadProcStatic' (0x1534) has exited with code 0 (0x0).<br />
The thread 'RPC Callback Thread' (0x12b8) has exited with code 0 (0x0).<br />
...<br />
</code><br />
Lets ramp up WinDbg, attach to the process (that _getch comes in useful here) and find out what&#8217;s going on in a bit more detail.</p>
<p>If we let the app run to the point of failure in WinDbg, we can see that the CLR was in the act of shutting down when it caused the exception:<br />
<code><br />
0:002> kp<br />
ChildEBP RetAddr<br />
WARNING: Frame IP not in any known module. Following frames may be wrong.<br />
00dae3fc 79f4c1b5 0xe06ff8<br />
00dae450 79f4c26c mscorwks!ReleaseTransitionHelper+0x5f<br />
00dae494 79f4c2d0 mscorwks!SafeReleaseHelper+0x8c<br />
00dae4c8 79faaa01 mscorwks!SafeRelease+0x2f<br />
00dae4fc 79faa7c8 mscorwks!IUnkEntry::Free+0x68<br />
00dae510 79faa91d mscorwks!RCW::ReleaseAllInterfaces+0x18<br />
00dae540 79faa949 mscorwks!RCW::ReleaseAllInterfacesCallBack+0xbd<br />
00dae570 7a0792ac mscorwks!RCW::Cleanup+0x22<br />
00dae57c 7a079714 mscorwks!RCWCleanupList::ReleaseRCWListRaw+0x16<br />
00dae5ac 7a0797df mscorwks!RCWCleanupList::ReleaseRCWListInCorrectCtx+0xdf<br />
00dae5fc 79fdc140 mscorwks!RCWCleanupList::CleanupAllWrappers+0x77<br />
00dafe90 79fdc7aa mscorwks!RCWCache::ReleaseWrappersWorker+0x103<br />
00dafed8 79fd9f95 mscorwks!ReleaseRCWsInCaches+0x27<br />
00dafee0 79f3c76a mscorwks!InnerCoEEShutDownCOM+0x1e<br />
00daff14 79f92015 mscorwks!WKS::GCHeap::FinalizerThreadStart+0x1fc<br />
00daffb4 7c80b683 mscorwks!Thread::intermediateThreadProc+0x49<br />
00daffec 00000000 kernel32!BaseThreadStart+0x37<br />
</code><br />
Essentially it&#8217;s cleaning up the currently unused RCWs &#8211; including our malformed one &#8211; and as part of doing this, it&#8217;s calling Release on the underlying COM object, via the mscorwks!SafeRelease function. SafeRelease wraps the call to potentially (and definitely, in this case) dangerous unmanaged code with various exception handlers, enabling it to silently handle access violations. </p>
<p>If we run the app again, and this time break while it&#8217;s waiting for the keypress, before it attempts to clean up the RCWs, then we can examine the wrapper ourselves, using the approach I set out in <a href="http://www.voyce.com/index.php/2009/09/03/getting-iunknown-from-__comobject/">this post</a>.</p>
<p>List all of the untyped COM object wrappers:</p>
<pre>
0:002> !dumpheap -type System.__ComObject
 Address       MT     Size
<font color="blue"><b>01418628</b></font> 79306e60       16
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
79306e60        1           16 System.__ComObject
Total 1 objects
</pre>
<p>Use the address of the object to obtain its object header:<br />
<code><br />
0:002> dd <font color="blue">1418628</font>-4 L1<br />
01418624  0800<font color="red"><b>0002</b></font><br />
</code><br />
Use the syncblk identifier in the header to get the syncblk:</p>
<pre>
0:002> !syncblk <font color="red">2</font>
Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner
    2 <font color="darkgreen"><b>001e4d9c</b></font>            0         0 00000000     none    01418628 System.__ComObject
-----------------------------
Total           2
CCW             0
RCW             0
ComClassFactory 0
Free            0
</pre>
<p>Get the address of the RCW from the sync block:<br />
<code><br />
0:008> dd <font color="darkgreen">001e4d9c</font>+1c L1<br />
001e4db8  001e7dc8<br />
0:008> dd 001e7dc8+c L1<br />
001e7dd4  <font color="purple"><b>001de828</b></font><br />
</code><br />
And dump out the relevant bits of the RCW, the vtable of the object, at offset 0&#215;88, and the IUnknown pointer, at offset 0&#215;64:<br />
<code><br />
0:008> dds <font color="purple">001de828</font>+88 L1<br />
001de8b0  0041ac78 testStackObjects!MyClass::`vftable'<br />
0:008> dds <font color="purple">001de828</font>+64 L1<br />
001de88c  0012fe7c<br />
</code><br />
We can use <code>!address</code> to do a quick sanity check on the pointer and verify what we know to be the case; it&#8217;s stack memory:</p>
<pre>
0:008> !address 0012fe7c
    00030000 : 00124000 - 0000c000
                    Type     00020000 MEM_PRIVATE
                    Protect  00000004 PAGE_READWRITE
                    State    00001000 MEM_COMMIT
                    Usage    <b>RegionUsageStack</b>
                    Pid.Tid  490.13dc
</pre>
<p>If we run the app on again to the point that it fails, we can clearly see the address of the object being passed as an argument to <code>mscorwks!IUnkEntry::Free</code>.</p>
<p>So the moral of the story is; don&#8217;t pretend some arbitrary piece of stack memory is a real, reference counted COM object. You may be saving the cost of a heap allocation, but even if your app works OK today, it may not tomorrow when someone introduces a piece of .NET code somewhere in your object graph.</p>
<h4>Bonus Extra Content</h4>
<p>As a bonus tip, here are a couple of WinDbg breakpoints that can be used to dump each RCW as it&#8217;s created and destroyed.<br />
<code><br />
bu 79faa974 "dds @ecx L23; g"<br />
bu 79faa538 "dd @esp+20 L1; dds poi(@esp+20)+88 L1; g"<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2010/01/21/beware-of-using-stack-based-com-objects-from-net/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting IUnknown from __ComObject</title>
		<link>http://www.voyce.com/index.php/2009/09/03/getting-iunknown-from-__comobject/</link>
		<comments>http://www.voyce.com/index.php/2009/09/03/getting-iunknown-from-__comobject/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 22:51:35 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[WinDbg]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[mscorwks]]></category>
		<category><![CDATA[RCW]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=330</guid>
		<description><![CDATA[How do you find the unmanaged COM object that's being referenced by a .NET object?]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m working in an environment with a lot of mixed managed (F#) and unmanaged (C++ COM) code. One of the big problems with this is the mix of lifetime management techniques; .NET uses garbage collection while COM relies on reference counting. Furthermore .NET garbage collection is somewhat non-deterministic, which adds further complexity.</p>
<p>So quite often in our mixed code-base, we find that the .NET garbage collection process doesn&#8217;t kick in when we need it to. For instance, when we&#8217;ve allocated a lot of memory in the COM code that .NET isn&#8217;t aware of. Memory exhaustion has to get pretty bad for the GC to occur at any other time than during a .NET allocation, either the system-wide low-memory event has to be signalled or an <code>OutOfMemoryException</code> needs to be thrown. In both of these cases it&#8217;s probably too late to do anything about it.</p>
<p>In this case it&#8217;s extremely useful to be able to see what .NET objects are still alive, and what COM objects they&#8217;re hanging on to. Unfortunately this isn&#8217;t as easy as it might seem.<br />
<span id="more-330"></span><br />
The COM object itself hides within a weakly-typed <code>System.__ComObject</code> or a strongly-typed managed wrapper, depending on whether rich type information is available. Furthermore, a runtime controller RCW (runtime callable wrapper) is what actually holds a pointer to the object itself, and this structure is internal to mscorwks.dll.</p>
<p>So how can we untangle this and, on finding a <code>__ComObject</code> that happens to still be alive (i.e. is not reachable in the object graph and is therefore eligible for garbage collection) identify which COM object it&#8217;s hanging on to.</p>
<p>First of all, let&#8217;s see how many <code>__ComObjects</code> are still alive. In this case, it&#8217;s only one (phew!):</p>
<pre>
0:005> !DumpHeap -type __ComObject
 Address       MT     Size
01453b74 79306e60       16
total 1 objects
Statistics:
      MT    Count    TotalSize Class Name
79306e60        1           16 System.__ComObject
Total 1 objects
</pre>
<p>And you remember the layout of .NET objects in memory, don&#8217;t you? Of course you do! The 4 bytes prior to the address displayed (<code>01453b74</code>) are the &#8220;object header&#8221;. The exact content of the header is apparently undocumented. Let&#8217;s see what it contains (at least on a 32-bit platform, your mileage may vary):</p>
<pre>
0:005> dd 01453b74-4 L1
01453b70  08000002
</pre>
<p>According to various sources the object header contains 2 fields; a handle and a sync block index. If the object is an RCW, the handle is always 0&#215;08000. You can use the index with SOS&#8217;s <code>!syncblk</code> command to de-reference it:</p>
<pre>
0:005> !syncblk 2
Index SyncBlock MonitorHeld Recursion Owning Thread Info  SyncBlock Owner
    2 001e0fec            0         0 00000000     none    01453b74 System.__ComObject
-----------------------------
Total           3
CCW             0
RCW             1
ComClassFactory 0
Free            0
</pre>
<p>The sync block itself is an undocumented structure, but after a bit of investigation, it turns out that at offset 0&#215;1c there is a pointer to a further structure that contains the &#8220;interop information&#8221;:</p>
<pre>
0:005> dd 001e0fec+1c L1
001e1008  001e9510
</pre>
<p>And from this, we can obtain a pointer to the RCW itself. We&#8217;re almost there!</p>
<pre>
0:005> dd 001e9510+c L1
001e951c  001e5380
</pre>
<p>The RCW is a pretty large structure, but for our purposes there are only a couple of interesting fields: the IUnknown pointer at 0&#215;64, and the object&#8217;s virtual function table pointer at 0&#215;88. If you use <code>dds</code> you can easily see any symbols associated with these pointers:</p>
<pre>
0:005> dds 01e5380+64 L1
001e53e4  00ef6c24
</pre>
<pre>
0:005> dds 01e5380+88 L1
001e5408  00eb9710 rcwrepro!ATL::CComObject<ctestObject>::`vftable'
</pre>
<p>This is the salient information; we now know exactly what type of COM object we&#8217;re dealing with. This is obviously a bit fragile, given that it relies on structures from mscorwks that may well change in newer versions of the runtime (I&#8217;ll check on .NET 4 when I get a chance). It&#8217;s also a bit of a pain to go through all these steps manually in WinDbg, so I put together a simple extension DLL to do it automatically given the address of the __ComObject. I&#8217;ll upload that and blog about it soon.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2009/09/03/getting-iunknown-from-__comobject/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Getting .NET type information in the unmanaged world</title>
		<link>http://www.voyce.com/index.php/2008/12/01/getting-net-type-information-in-the-unmanaged-world/</link>
		<comments>http://www.voyce.com/index.php/2008/12/01/getting-net-type-information-in-the-unmanaged-world/#comments</comments>
		<pubDate>Mon, 01 Dec 2008 15:48:33 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[ccw]]></category>
		<category><![CDATA[IDispatch]]></category>
		<category><![CDATA[invoke]]></category>
		<category><![CDATA[type]]></category>
		<category><![CDATA[unmanaged]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=55</guid>
		<description><![CDATA[One of the tools that I write and maintain displays type information for COM objects hidden behind &#8220;handles&#8221; in Excel spreadsheets. The underlying objects can either support an interface that allows them to be richly rendered to XML, or the viewer will fall-back to using metadata and displaying the supported interfaces and their properties and methods. It [...]]]></description>
			<content:encoded><![CDATA[<p>One of the tools that I write and maintain displays type information for COM objects hidden behind &#8220;handles&#8221; in Excel spreadsheets. The underlying objects can either support an interface that allows them to be richly rendered to XML, or the viewer will fall-back to using metadata and displaying the supported interfaces and their properties and methods. It will also invoke parameterless property getters &#8211; making the assumption that doing so won&#8217;t change the state of the object &#8211; and display the returned value. This is a useful way of getting some visibility on otherwise completely opaque values.</p>
<p>In order to obtain the type information about the COM objects, the tool uses type libraries, and the associated <a href="http://msdn.microsoft.com/en-us/library/ms221549.aspx">ITypeLib </a>and <a href="http://msdn.microsoft.com/en-us/library/ms221696.aspx">ITypeInfo</a> interfaces, which, with a little effort, can be used to iterate over all the coclasses, interfaces and functions in the library. But the difficulty lies in obtaining a type library when all you&#8217;re given is an already-instantiated object. In theory, COM allows you to know no more about an object than what interfaces it supports. But in practice, there are a variety of ways you can circumvent this and get to the type information.</p>
<p>For unmanaged COM objects you can use the information in the registry (or SxS configuration) and obtain the server (DLL) that contain a TLB embedded as a resource, or the type library filename itself. I won&#8217;t go into that now, there&#8217;s plenty of information about the location of these common registry keys elsewhere on the internet.</p>
<p>But for managed COM objects &#8211; well, COM callable wrappers (CCWs) &#8211; you have a different problem: registry scraping will never work and there may not even be an associated type library. The InprocServer32 registry entry always points to mscoree.dll, which obviously doesn&#8217;t have an embedded type library, and unless you&#8217;ve registered the assembly with /tlb (which is a pain) then you won&#8217;t have entries under HKEY_CLASSES_ROOT\Typelib and a TLB file to load.</p>
<p>So, if you&#8217;re in the unmanaged world, and all you&#8217;ve got is a pointer to a live CCW, what can you do?</p>
<p>Well, the easiest thing is to use <a href="http://msdn.microsoft.com/en-us/library/ms687303(VS.85).aspx">IProvideClassInfo</a>. This is supported by all CCWs, and provides a way to get an auto-generated (by the CLR) ITypeInfo implementation for the managed class. In fact, this is what I actually used to implement the solution eventually, but along the way I discovered some other interesting aspects of the CCW.</p>
<p>There is another interface that it supports: _Object, the unmanaged version of System.Object, which supports basic .NET functionality such as ToString and GetType. I couldn&#8217;t find it declared anywhere in the Platform or .NET SDK headers, so I put together a version that I could use from C++:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: Lucida Sans Typewriter;">
<p style="margin: 0px;"><span style="color: #0000ff;">struct</span> <span style="color: #0000ff;">__declspec</span>(<span style="color: #0000ff;">uuid</span>(<span style="color: #800000;">&#8220;{65074F7F-63C0-304E-AF0A-D51741CB4A8D}&#8221;</span>)) Object : <span style="color: #0000ff;">public</span> IDispatch</p>
<p style="margin: 0px;">{</p>
<p style="margin: 0px;"><span style="color: #0000ff;">public</span>:</p>
<p style="margin: 0px;"><span style="color: #008000;">// We don&#8217;t actually call these methods, doing so seems to return</span></p>
<p style="margin: 0px;"><span style="color: #008000;">// COR_E_INVALIDOPERATION. Instead we just use the IDispatch::Invoke</span></p>
<p style="margin: 0px;"><span style="color: #008000;">// and use the DISPID of the methods.</span></p>
<p style="margin: 0px;"><span style="color: #0000ff;">virtual</span> HRESULT STDMETHODCALLTYPE ToString(BSTR *) = 0;</p>
<p style="margin: 0px;"><span style="color: #0000ff;">virtual</span> HRESULT STDMETHODCALLTYPE Equals(VARIANT, VARIANT_BOOL *) = 0;</p>
<p style="margin: 0px;"><span style="color: #0000ff;">virtual</span> HRESULT STDMETHODCALLTYPE GetHashCode(<span style="color: #0000ff;">long</span> *) = 0;</p>
<p style="margin: 0px;"><span style="color: #0000ff;">virtual</span> HRESULT STDMETHODCALLTYPE GetType(mscorlib::_Type **) = 0;</p>
<p style="margin: 0px;">};</p>
</div>
<p><!--EndFragment-->Despite the presence of the virtual functions in this &#8220;interface&#8221;, we&#8217;re not actually going to call them. Instead we&#8217;ll call through the IDispatch that it derives from. It may be possible to use them directly, but see the comment describing what happens when I tried it. Calling via IDispatch may seem slightly odd, because the object itself claims not to support it (QueryInteface returns E_NOINTERFACE).</p>
<p>The methods on the _Object interface have well-known DISPIDs:</p>
<table border="0">
<tbody>
<tr>
<td>ToString</td>
<td>0&#215;00000000</td>
</tr>
<tr>
<td>Equals</td>
<td>0&#215;60020001</td>
</tr>
<tr>
<td>GetHashCode</td>
<td>0&#215;60020002</td>
</tr>
<tr>
<td>GetType</td>
<td>0&#215;60020003</td>
</tr>
</tbody>
</table>
<p>So we can use that to invoke the GetType method:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: Lucida Sans Typewriter;">
<p style="margin: 0px;">DISPPARAMS parms;</p>
<p style="margin: 0px;">parms.cArgs = 0;</p>
<p style="margin: 0px;">parms.cNamedArgs = 0;</p>
<p style="margin: 0px;">_variant_t vType;</p>
<p style="margin: 0px;">hr = pObject-&gt;Invoke(0&#215;60020003, IID_NULL, 0, DISPATCH_METHOD, &amp;parms, &amp;vType, NULL, NULL);</p>
</div>
<p><!--EndFragment-->And we get back a <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices._type.aspx">_Type</a> interface that allows us to navigate around the type information in the same way as we can with System.Type! Just #import mscorlib.tlb and you get all the interfaces you need to e.g. iterate over all the interfaces implemented by a type, and invoke a function on them:</p>
<div style="font-size: 10pt; background: white; color: black; font-family: Lucida Sans Typewriter;">
<p style="margin: 0px;"><span style="color: #0000ff;">#import</span> <span style="color: #800000;">&lt;mscorlib.tlb&gt;</span> rename(<span style="color: #800000;">&#8220;ReportEvent&#8221;</span>,<span style="color: #800000;">&#8220;xReportEvent&#8221;</span>)</p>
<p style="margin: 0px;">&#8230;</p>
<p style="margin: 0px;">mscorlib::_TypePtr t(V_UNKNOWN(&amp;vType));</p>
<p style="margin: 0px;">CComSafeArray&lt;LPUNKNOWN&gt; saInterfaces(t-&gt;GetInterfaces());</p>
<p style="margin: 0px;">&#8230;</p>
<p style="margin: 0px;">mscorlib::_TypePtr tInterface((LPUNKNOWN)saInterfaces.GetAt(n));</p>
<p style="margin: 0px;">&#8230;</p>
<p style="margin: 0px;">result = tInterface-&gt;InvokeMember(_bstr_t(<span style="color: #800000;">&#8220;Function&#8221;</span>),</p>
<p style="margin: 0px;">(mscorlib::BindingFlags)</p>
<p style="margin: 0px;">(mscorlib::BindingFlags_GetProperty +</p>
<p style="margin: 0px;">mscorlib::BindingFlags_InvokeMethod +</p>
<p style="margin: 0px;">mscorlib::BindingFlags_Public +</p>
<p style="margin: 0px;">mscorlib::BindingFlags_Instance +</p>
<p style="margin: 0px;">mscorlib::BindingFlags_IgnoreCase),</p>
<p style="margin: 0px;">NULL, _variant_t(punk), NULL, NULL, NULL, NULL);</p>
</div>
<p>So this turns out to be quite nice: you can get rich managed type information even if you&#8217;re running in the unmanaged world.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2008/12/01/getting-net-type-information-in-the-unmanaged-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Beware cached IDispatch</title>
		<link>http://www.voyce.com/index.php/2008/11/10/beware-cached-idispatch/</link>
		<comments>http://www.voyce.com/index.php/2008/11/10/beware-cached-idispatch/#comments</comments>
		<pubDate>Mon, 10 Nov 2008 11:32:15 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[IDispatch]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[VBScript]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=51</guid>
		<description><![CDATA[I&#8217;ve kinda given it away there with the title, but we had an interesting set of symptoms exhibited the other day while trying to call a function in an Excel workbook via F#. It appeared that the function being called would fail depending on what had been called previously. Very odd.
A bit of background: as you [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve kinda given it away there with the title, but we had an interesting set of symptoms exhibited the other day while trying to call a function in an Excel workbook via F#. It appeared that the function being called would fail depending on what had been called previously. Very odd.</p>
<p>A bit of background: as you may know, if you add functions to the worksheet or workbook code in Excel then they appear as callable methods on the objects themselves. This is achieved with the use of dynamic dispatch and IDispatch. For example, creating a workbook with this function in it&#8217;s VBA code:</p>
<p><code>Public Function Foo() As Double<br />
    Foo = 100<br />
End Function</code></p>
<p>Means you can call it like this:</p>
<p><code>MsgBox CStr(ThisWorkbook.Foo)</code></p>
<p>As well as being able to call it like this from within the Excel session (i.e. in other VBA code in the process), you can also access it externally using the COM object model that Office applications expose. For instance, you can use VBScript:</p>
<p><code>Dim excel, wkb<br />
Set excel = CreateObject("Excel.Application")<br />
Set wkb = excel.Workbooks.Open("a.xls")<br />
WScript.Echo wkb.Foo<br />
</code></p>
<p>Or, more interesting, using F#:</p>
<div style="font-family: Lucida Sans Typewriter; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;">    <span style="color: #0000ff;">let</span> excel = <span style="color: #0000ff;">new</span> Excel.ApplicationClass()</p>
<p style="margin: 0px;">    <span style="color: #0000ff;">let</span> wkb = excel.Workbooks.Open(<span style="color: #a31515;">@&#8221;c:\a.xls&#8221;</span>)</p>
<p style="margin: 0px;">    wkb.GetType().InvokeMember(<span style="color: #a31515;">&#8220;Foo&#8221;</span>, BindingFlags.InvokeMethod, <span style="color: #0000ff;">null</span>, wkb, <span style="color: #0000ff;">null</span>)</p>
</div>
<p>The key part here is that we&#8217;re using wks.GetType() to get a managed representation of the unmanaged Excel COM interface. Under the covers this is creating a runtime callable wrapper (RCW) to wrap the worksheet COM object.</p>
<p>However, the problem we were seeing was that opening multiple sheets resulted in failures to call the method in certain situations. Although the VBA signature was exactly the same in all of the sheets, it seemed that opening b.xls after a.xls, would fail; returning null when we expected it to return a value. If we opened c.xls after b.xls, it would fail in a different way; never actually making it to the body of the function. Very odd.</p>
<p>My first suspicion was that it was somehow related to COM object vs .NET object lifetime. This is quite a common problem whens invoking Excel using managed code. It&#8217;s bad mixing COM and .NET anyway; generally deterministic, reference-counted lifetime semantics don&#8217;t play well with the garbage collector. Throwing an app with a full-blown UI being managed as COM object into the mix just complicates matters further. Anyway, it&#8217;s been widely discussed, so I won&#8217;t say any more about it here; suffice to say that calling Marshal.ReleaseCOMObject and GC.Collect got us to the point where we could see the Excel process terminating, so we knew that the failure wasn&#8217;t due to some state being cached inside there.</p>
<p>So we concentrated on different aspects of the problem:</p>
<ul>
<li>Given the pattern of failures, it seemed that the order of opening the sheets and calling affected the outcome. This hinted that something was persisting betweeen calls, but not in the client (Excel) site.</li>
<li>The code had previously worked when written in VBScript, so there was nothing intrinsically wrong with the operations we were performing.</li>
</ul>
<p>This seemed to strongly indicate that something was being cached at the .NET level. And the major difference between the .NET code and the VBScript was that the former used Type.GetType() on the worksheet object to get it&#8217;s managed representation, while the latter used the IDispatch directly.</p>
<p>So it looked like GetType() was caching some information about the particular IDispatch implementation that it encountered first, then reusing that for subsequent worksheet implementations which actually had a slightly different layout, i.e. although they also had the Foo function which we were trying to call, they had a different set of other dynamic functions too.</p>
<p>After a bit of digging about I uncovered this gem: <a href="http://blogs.msdn.com/mbend/archive/2007/04/18/the-mapping-between-interface-pointers-and-runtime-callable-wrappers-rcws.aspx">the mapping between interface pointers and runtime callable wrappers</a>. Which seemed to describe exactly what we were seeing. The first time through the loop, the runtime is asked to get the type and is given a COM pointer, for which it creates a RCW that we can use to invoke Foo. The second time through the loop, the runtime thinks it&#8217;s seen the object before, so rather than perform the expensive operation of creating the RCW again, it just returns the original one. The problem is, the underlying COM object is different!</p>
<p>So, in order to prevent the runtime for trying to cache the RCW, we need to use <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.getuniqueobjectforiunknown(VS.80).aspx">Marshal.GetUniqueObjectForIUnknown</a> and that does the trick nicely. We first need to get an IUnknown for our object, than convert that back into an object, which is actually a RCW:</p>
<div style="font-family: Lucida Sans Typewriter; font-size: 10pt; color: black; background: white;">
<p style="margin: 0px;">    <span style="color: #0000ff;">let</span> wkb = Marshal.GetUniqueObjectForIUnknown(Marshal.GetIUnknownForObject(wkb))</p>
</div>
<p>Although it&#8217;s less efficent, at least the code works, and it finally allows us to call the dynamic methods on the workbook object from F# .NET.</p>
<p>It will be interesting to see how <code>dynamic</code> in .NET 4.0 addresses this kind of issue.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2008/11/10/beware-cached-idispatch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Static libraries are Evil</title>
		<link>http://www.voyce.com/index.php/2008/09/24/static-libraries-are-evil/</link>
		<comments>http://www.voyce.com/index.php/2008/09/24/static-libraries-are-evil/#comments</comments>
		<pubDate>Wed, 24 Sep 2008 15:27:27 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[dll]]></category>
		<category><![CDATA[lib]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=41</guid>
		<description><![CDATA[In my opinion.
Why? Well, because it&#8217;s too easy to use them as an excuse for not defining your shared library interfaces properly.
The reason this is on my mind recently is that several hundred, yes, you heard that right, several hundred DLLs have been released by my group over the last, ooh, 10 years or so. [...]]]></description>
			<content:encoded><![CDATA[<p>In my opinion.</p>
<p>Why? Well, because it&#8217;s too easy to use them as an excuse for not defining your shared library interfaces properly.</p>
<p>The reason this is on my mind recently is that several hundred, yes, you heard that right, several <em>hundred</em> DLLs have been released by my group over the last, ooh, 10 years or so. They are all still in use. Each of them has burned into it a copy of the library that deals with interfacing with Excel. That means each of these has it&#8217;s own little internal copy of the current state-of-the-art. The problem with that is; the state-of-the-art moves on. And how do you go about updating the DLLs that are already in production? You have to re-release them. In an environment where thes DLLs are used for marking the profit and loss on a large derivatives trading book, that&#8217;s not a small undertaking. And it&#8217;s made worse if, say the DLL in question was last released with a different version of the compiler.</p>
<p>My approach would be to refactor this shared static library (.lib) into a stand-alone DLL.</p>
<p>At this point, people start saying &#8220;oh, but then you&#8217;ve got a single point of failure, if you release a broken version of that DLL, everything will stop working!&#8221;. Not exactly a compelling argument. If the functionality of the DLL is well defined, and there are well known entry points it should be easy to put together a comprehensive black-box test suite. In fact we already do that with all our other DLLs (COM servers). The fact that this shared library *isn&#8217;t* a DLL has meant that it&#8217;s fallen through the testing cracks; another good reason to refactor it.</p>
<p>The internal interface to the shared library is already relatively well defined. It has a set of header files that define all of the functions and classes that are consumed by others. It&#8217;s a relatively small step to compile it as a DLL, rather than a static library. The problem then becomes one of maintenance, dealing with the inevitable changes to the external interface in a backwardly compatible way.</p>
<p>And that&#8217;s the problem. It requires some effort. Elsewhere in our codebase we use COM as a magic cure-all for avoiding having to deal with versioning: interface immutability rules. All interfaces are public, no published interface ever changes, object identity is based purely on interfaces supported. If you haven&#8217;t got these crutches to rely on, then you have to enforce the rules yourself, which can be both logistically and technically difficult when you&#8217;re dealing with C++.</p>
<p>But it&#8217;s not impossible. And I really think it would be better than having hundreds of DLLs all containing subtley different versions of the same code, and being unable to change behaviour across the board without having to build, test and release them all.</p>
<p>Maybe you&#8217;ve got a different opinion?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2008/09/24/static-libraries-are-evil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>F# &#8211; A little gotcha with GuidAttribute</title>
		<link>http://www.voyce.com/index.php/2008/08/18/f-a-little-gotcha/</link>
		<comments>http://www.voyce.com/index.php/2008/08/18/f-a-little-gotcha/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 13:20:43 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[guidattribute fsharp]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=39</guid>
		<description><![CDATA[Be careful when using the [&#60;Guid("...")&#62;] attribute on your COM-visible classes in F#. If you mistakenly use the curly-bracket delimited format for the GUID, regasm will silently, yes, silently, fail to add any CLSID entries for your class. That means it will be cocreatable by the prog ID, but not the CLSID. Ouch.
No doubt this will be [...]]]></description>
			<content:encoded><![CDATA[<p>Be careful when using the [&lt;Guid("...")&gt;] attribute on your COM-visible classes in F#. If you mistakenly use the curly-bracket delimited format for the GUID, regasm will silently, yes, <em>silently</em>, fail to add any CLSID entries for your class. That means it will be cocreatable by the prog ID, but not the CLSID. Ouch.</p>
<p>No doubt this will be addressed in the CTP release, due in a couple of weeks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2008/08/18/f-a-little-gotcha/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting COM registration data with the activation context API</title>
		<link>http://www.voyce.com/index.php/2007/08/15/getting-com-registration-data-with-the-activation-context-api/</link>
		<comments>http://www.voyce.com/index.php/2007/08/15/getting-com-registration-data-with-the-activation-context-api/#comments</comments>
		<pubDate>Wed, 15 Aug 2007 22:25:41 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=17</guid>
		<description><![CDATA[When moving code from “traditional” registry-based COM to shiny new side-by-side, registration-free COM, there are a few places where you might need an analog for things like looking up a DLL name from a prog ID. E.g. in the registry-based world, you can go from a Prog ID for a class to it’s physical DLL [...]]]></description>
			<content:encoded><![CDATA[<p>When moving code from “traditional” registry-based COM to shiny new side-by-side, registration-free COM, there are a few places where you might need an analog for things like looking up a DLL name from a prog ID. E.g. in the registry-based world, you can go from a Prog ID for a class to it’s physical DLL filename by doing this:</p>
<ul>
<li>Get CLSID from the ProgID</li>
<li>Look up filename in HKCR\CLSID\{clsguid}\InprocServer32</li>
</ul>
<p>Now obviously, if you attempt this on a machine where the components are only being used via SxS (i.e. have never been registered) the CLSIDFromProgID step will work &#8211; OLE32.DLL, which implements this function, is aware of SxS &#8211; but the subsequent steps won’t because the information isn’t in the registry.</p>
<p>I guess this is really breaking because we’re taking advantage of our knowledge of COM internals, rather than going via the official APIs. Although as far as I know the “correct” way of doing the progid-&gt;(type library) DLL mapping is via <a href="http://msdn2.microsoft.com/en-us/library/ms687303.aspx">IProvideClassInfo</a>, but that relies on the COM objects supporting this interface, and unfortunately we have, err, several &#8211; hundred &#8211; that don’t.</p>
<p>So, I set about looking to see if there was a way to get this information using the activation context APIs. All the information is there in the manifest, so how do we get it &#8211; without something nasty like querying the manifest XML directly?</p>
<p>There are only a handful of functions in the ActCtx API, and one of them &#8211; <strong><a href="http://msdn2.microsoft.com/en-us/library/aa375148.aspx"><strong>FindActCtxSectionGuid</strong></a></strong> &#8211; looks relevant. By calling this with the <strong>ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION</strong> flag, it looks like we can get some data from the manifest based on our COM object CLSID.</p>
<p>Here’s the problem. The returned data from this function is a <strong>ACTCTX_SECTION_KEYED_DATA</strong> structure, and as far as I can tell this is essentially an opaque blob, with a couple of length indicators. I couldn’t find any documentation about what the lpData member was supposed to point to (if you know any better, please let me know)!</p>
<p>I decided to break out WinDbg, and see what OLE32!CLSIDFromProgID did, as I assumed that this must be doing something similar. It was! In fact, it was calling FindActCtxSectionString to map the prog ID to a CLSID, then using this in a call to FindActCtxSectionGuid. After a bit of disassembly, and some staring at the memory window in Visual Studio, I got a good enough idea of the contents to be able to figure out how the data referenced the filename:</p>
<p style="margin: 0pt">    <span style="color: blue">typedef</span> <span style="color: blue">struct</span> tagSECTION_DATA</p>
<p style="margin: 0pt">    {</p>
<p style="margin: 0pt">        DWORD dwSize; <span style="color: green">// 0×78 (120) structure size?</span></p>
<p style="margin: 0pt">        DWORD _2; <span style="color: green">// 0×00</span></p>
<p style="margin: 0pt">        DWORD dwSectionType; <span style="color: green">// 0×04 (ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)</span></p>
<p style="margin: 0pt">        GUID clsid; <span style="color: green">// CLSID of class?</span></p>
<p style="margin: 0pt">        GUID _5; <span style="color: green">// Some other GUID</span></p>
<p style="margin: 0pt">        GUID _6; <span style="color: green">// CLSID of class again…?</span></p>
<p style="margin: 0pt">        GUID _7; <span style="color: green">// NULL</span></p>
<p style="margin: 0pt">        DWORD dwFileNameLength; <span style="color: green">// file name size in bytes</span></p>
<p style="margin: 0pt">        DWORD dwFileNameSectionOffset; <span style="color: green">// file name offset into data.lpSectionBase</span></p>
<p style="margin: 0pt">        DWORD dwProgIDLength; <span style="color: green">// progid size in bytes</span></p>
<p style="margin: 0pt">        DWORD dwProgIDOffset; <span style="color: green">// offset from start of this structure to progid (0×78)</span></p>
<p style="margin: 0pt">        BYTE _8[28]; <span style="color: green">//Unknown</span></p>
<p style="margin: 0pt">        <span style="color: green">// Prog ID string follows</span></p>
<p style="margin: 0pt">    } SECTION_DATA;</p>
<p>So now you can cast the data member to this structure and easily extract the filename, voila!</p>
<p style="margin: 0pt">    ACTCTX_SECTION_KEYED_DATA data;</p>
<p style="margin: 0pt">    data.cbSize = <span style="color: blue">sizeof</span>(data);</p>
<p style="margin: 0pt">&nbsp;</p>
<p style="margin: 0pt">    <span style="color: blue">if</span> (!FindActCtxSectionGuid(FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX,</p>
<p style="margin: 0pt">        NULL,</p>
<p style="margin: 0pt">        ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,</p>
<p style="margin: 0pt">        &amp;guid,</p>
<p style="margin: 0pt">        &amp;data))</p>
<p style="margin: 0pt">    {</p>
<p style="margin: 0pt">        <span style="color: blue">return</span> GetLastError();</p>
<p style="margin: 0pt">    }</p>
<p style="margin: 0pt">    <span style="color: blue">if</span>(data.ulDataFormatVersion == 1) <span style="color: green">// Fail-safe in case internal format changes…?</span></p>
<p style="margin: 0pt">    {</p>
<p style="margin: 0pt">        <span style="color: green">// Cast returned data to our structure type</span></p>
<p style="margin: 0pt">        SECTION_DATA *pdata = <span style="color: blue">static_cast</span>&lt;SECTION_DATA *&gt;(data.lpData);</p>
<p style="margin: 0pt">        <span style="color: green">// DLL filename can be found in the section base data at specified offset</span></p>
<p style="margin: 0pt">        std::wstring filename(</p>
<p style="margin: 0pt">            <span style="color: blue">reinterpret_cast</span>&lt;<span style="color: blue">wchar_t</span> *&gt;( ((BYTE *)data.lpSectionBase + pdata-&gt;dwFileNameSectionOffset) ));</p>
<p style="margin: 0pt">    }</p>
<p><font size="2">So the SxS compliant version of the CLSID to filename/typelibrary is:</font></p>
<ul>
<li>Get CLSID from the ProgID</li>
<li>Look up GUID in current activation context using FindActCtxSectionGuid</li>
<li>Decipher returned data to get filename</li>
</ul>
<p>I’m sure this will break horribly when they change the internal format of the activation context data (in fact, it’s probably different now between XP and Vista &#8211; many things in the SxS world are), but hopefully we can use the ulDataFormatVersion to do some basic sanity checking.</p>
<p>Now if only some of those useful looking functions in sxs.dll were documented…</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2007/08/15/getting-com-registration-data-with-the-activation-context-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Tracking COM memory using IMallocSpy</title>
		<link>http://www.voyce.com/index.php/2007/05/25/tracking-com-memory-using-imallocspy/</link>
		<comments>http://www.voyce.com/index.php/2007/05/25/tracking-com-memory-using-imallocspy/#comments</comments>
		<pubDate>Fri, 25 May 2007 22:28:36 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=15</guid>
		<description><![CDATA[&#160;
&#160;
One of my aims at work is to simplify the development and testing regime as much as possible, and this mostly consists of making sure we’re using the most appropriate tools and technologies wherever possible. In the context of correctness checking this involves determining whether the time we spend installing, configuring and chasing down false [...]]]></description>
			<content:encoded><![CDATA[<p class="postentry">&nbsp;</p>
<p class="snap_preview">&nbsp;</p>
<p class="postentry">One of my aims at work is to simplify the development and testing regime as much as possible, and this mostly consists of making sure we’re using the most appropriate tools and technologies wherever possible. In the context of correctness checking this involves determining whether the time we spend installing, configuring and chasing down false positives in third-party tools such as Purify outweighs their benefits.</p>
<p class="postentry">As a rule I’d always favour using built-in, vendor provided hooks rather than a bolt-on product, and as such I was interested in what we could do with the IMallocSpy functionality in the COM runtime, as our group’s software is almost all COM based.</p>
<p class="postentry">It turned up some interesting things…</p>
<p class="postentry">The first was the behaviour of CoRevokeMallocSpy. Stupidly I originally neglected to check the return value, and then when I did, found it was returning E_ACCESSDENIED. It turns out that this means there are still allocations that occurred when the spy was active that haven’t been freed. Given that my use of the spy was to check for leaked allocations in the first place, this was a bit annoying; at least, it meant I couldn’t overload the lifetime of my spy object, to, say, dump a list of leaks when it was destroyed. If there were any leaks it never got destroyed!</p>
<p class="postentry">The next problem was that it seemed whenever I had an app that called the apparently innocous CLSIDFromProgID, it would leak memory. For example:</p>
<pre>addr: 0x0015eb20:
size: 0x2c (44)
contents:
c0 31 fd 76 30 c8 15 00 01 00 00 00 01 00 12 00 .1.v0...........
28 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01 f0 ad ba bc ec 15 00 94 ec 15 00             ............
[0x77583315] CSpyMalloc_Alloc+0x49
[0x774fd073] CoTaskMemAlloc+0x13
[0x76fd18fb] operator new+0xe
[0x76fd5c6b] StgDatabase::InitClbFile+0x2e
[0x76fdc190] StgDatabase::InitDatabase+0x623c
[0x770076fa] OpenComponentLibraryEx+0x3e
[0x77005306] OpenComponentLibraryTS+0x1a
[0x76fd954d] _RegGetICR+0x761f
[0x76fd1f24] CoRegGetICR+0xffff877d
[0x76fd6a20] IsSelfRegProgID+0x65
[0x76fd80f9] CComCLBCatalog::GetClassInfoFromProgId+0x1783
[0x77518a6d] CComCatalog::GetClassInfoFromProgId+0x100
[0x77518964] CComCatalog::GetClassInfoFromProgId+0x1e
[0x775188a0] CLSIDFromProgID+0x76
[0x004120f5] wmain+0xa5
[0x004173a6] __tmainCRTStartup+0x1a6
[0x004171ed] wmainCRTStartup+0xd
[0x7c816fd7] BaseProcessStart+0x23</pre>
<p class="postentry">Looking at the stack trace, it seemed there was some kind of internal caching going on, but what was confusing me was that I was under the impression that all memory allocated by the COM runtime would be freed by the time CoUninitialize was done. After all, you can’t make any further COM calls after this point. If you don’t believe me, just try using a static CComPtr, and see what happens in DllMainCRTStartup when your app exits.</p>
<p class="postentry">After a bit of poking about with WinDbg (thank goodness we get decent symbols for the OS now), I could see that some kind of “database” was being created within CLBCATQ.DLL:</p>
<pre>0:000&gt; k
ChildEBP RetAddr¼br&gt; 0012faf4 770076fa CLBCATQ!StgDatabase::InitDatabase
0012fb18 77005306 CLBCATQ!OpenComponentLibraryEx+0x3e
0012fb34 76fd954d CLBCATQ!OpenComponentLibraryTS+0x1a
0012fdd0 76fd1f24 CLBCATQ!_RegGetICR+0x205
0012fdf0 76fd6a20 CLBCATQ!CoRegGetICR+0x29
0012fe48 76fd80f9 CLBCATQ!IsSelfRegProgID+0x6b
0012fe88 77518a6d CLBCATQ!CComCLBCatalog::GetClassInfoFromProgId+0x51
0012fec0 77518964 ole32!CComCatalog::GetClassInfoFromProgId+0x149
0012fee0 775188a0 ole32!CComCatalog::GetClassInfoFromProgId+0x1e
0012ff0c 00401340 ole32!CLSIDFromProgID+0x95
0012ff7c 00401cae testleakcheck!wmain+0x60
0012ffc0 7c816fd7 testleakcheck!__tmainCRTStartup+0x10f [f:\rtm\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 583]
0012fff0 00000000 kernel32!BaseProcessStart+0x23</pre>
<p class="postentry"> I could see by looking at the exports that there was a function called CoRegCleanup in CLBCATQ.DLL that looked like it could be used to free up this storage before I did my leak checking. Calling it by dynamically getting the function pointer using GetProcAddress did make a difference, but there was still some memory not freed, and I didn’t feel comfortable using an undocumented function in this way.</p>
<p class="postentry">Then I remembered the magical OANOCACHE environment variable.</p>
<p class="postentry">This is used to tell the COM runtime not to cache memory used for BSTRs, VARIANTs, SAFEARRAYs, or anything else allocated using CoTaskMalloc. So, I set the variable, re-ran the test and voila! the apparent leaks disappeared. There must be something in CLBCATQ that detects the environment varibale and disables it’s internal cache.</p>
<p class="postentry">So the moral of the story is; if you’re attempting to reliably track memory usage with IMallocSpy, remember to make sure you have OANOCACHE set, otherwise you will always end up with memory not being freed until late into process teardown.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2007/05/25/tracking-com-memory-using-imallocspy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bug in _com_ptr_t::QueryStdInterfaces</title>
		<link>http://www.voyce.com/index.php/2007/03/02/bug-in-_com_ptr_tquerystdinterfaces/</link>
		<comments>http://www.voyce.com/index.php/2007/03/02/bug-in-_com_ptr_tquerystdinterfaces/#comments</comments>
		<pubDate>Fri, 02 Mar 2007 22:36:53 +0000</pubDate>
		<dc:creator>ian</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Software Development]]></category>

		<guid isPermaLink="false">http://www.voyce.com/?p=8</guid>
		<description><![CDATA[Just thought I’d bring people’s attention to a bug in the COM support classes that ship with Visual Studio 2005/VC8.
It’s a fairly unusual edge case (at least, if you’re not being passed VARIANTs from a script language), where the _variant_t helper class attempts to extract a standard COM interface (IUnknown or IDispatch) from a VARIANT [...]]]></description>
			<content:encoded><![CDATA[<p class="postentry">Just thought I’d bring people’s attention to a bug in the COM support classes that ship with Visual Studio 2005/VC8.</p>
<p>It’s a fairly unusual edge case (at least, if you’re not being passed VARIANTs from a script language), where the _variant_t helper class attempts to extract a standard COM interface (IUnknown or IDispatch) from a VARIANT that’s being passed “byref”, e.g. has a type or’ed with VT_BYREF.</p>
<p>In this case the code in comip.h uses VariantCopy to “derefence” the pointer &#8211; convert it from, say, VT_DISPATCH|VT_BYREF to VT_DISPATCH &#8211; but if this succeeds, it then proceeds to use the wrong local variable, varSrc, rather than varDest that it’s just converted. The effect is that it causes an access violation.</p>
<p>Here’s the code snippet in question:</p>
<style>                .cf { font-family: Lucida Sans Typewriter; font-size: 10pt; color: black; background: white; }  .cl { margin: 0px; }  .cb1 { color: green; }  .cb2 { color: blue; } .cbhilite { color: black; background-color:yellow; }</style>
<p class="cf">
<p class="cl">    <span class="cb1">// Try to extract either IDispatch* or an IUnknown* from</span></p>
<p class="cl">    <span class="cb1">// the VARIANT</span></p>
<p class="cl">    <span class="cb1">//</span></p>
<p class="cl">    HRESULT QueryStdInterfaces(<span class="cb2">const</span> _variant_t&amp; varSrc) <span class="cb2">throw</span>()</p>
<p class="cl">    {</p>
<p class="cl">        <span class="cb2">if</span> (V_VT(&amp;varSrc) == VT_DISPATCH) {</p>
<p class="cl">            <span class="cb2">return</span> _QueryInterface(V_DISPATCH(&amp;varSrc));</p>
<p class="cl">        }</p>
<p class="cl">&nbsp;</p>
<p class="cl">        <span class="cb2">if</span> (V_VT(&amp;varSrc) == VT_UNKNOWN) {</p>
<p class="cl">            <span class="cb2">return</span> _QueryInterface(V_UNKNOWN(&amp;varSrc));</p>
<p class="cl">        }</p>
<p class="cl">&nbsp;</p>
<p class="cl">        <span class="cb1">// We have something other than an IUnknown or an IDispatch.</span></p>
<p class="cl">        <span class="cb1">// Can we convert it to either one of these?</span></p>
<p class="cl">        <span class="cb1">// Try IDispatch first</span></p>
<p class="cl">        <span class="cb1">//</span></p>
<p class="cl">        VARIANT varDest;</p>
<p class="cl">        VariantInit(&amp;varDest);</p>
<p class="cl">&nbsp;</p>
<p class="cl">        HRESULT hr = VariantChangeType(&amp;varDest, <span class="cb2">const_cast</span>(<span class="cb2">static_cast</span>&lt;<span class="cb2">const</span> VARIANT*&gt;(&amp;varSrc)), 0, VT_DISPATCH);</p>
<p class="cl">        <span class="cb2">if</span> (SUCCEEDED(hr)) {</p>
<p class="cl">            hr = _QueryInterface(V_DISPATCH(<span class="cbhilite">&amp;varSrc</span>)); <span class="cb1">// Should be &amp;varDest</span></p>
<p class="cl">        }</p>
<p class="cl">&nbsp;</p>
<p class="cl">        <span class="cb2">if</span> (hr == E_NOINTERFACE) {</p>
<p class="cl">            <span class="cb1">// That failed … so try IUnknown</span></p>
<p class="cl">            <span class="cb1">//</span></p>
<p class="cl">            VariantInit(&amp;varDest);</p>
<p class="cl">            hr = VariantChangeType(&amp;varDest, <span class="cb2">const_cast</span>(<span class="cb2">static_cast</span>&lt;<span class="cb2">const</span> VARIANT*&gt;(&amp;varSrc)), 0, VT_UNKNOWN);</p>
<p class="cl">            <span class="cb2">if</span> (SUCCEEDED(hr)) {</p>
<p class="cl">                hr = _QueryInterface(V_UNKNOWN(<span class="cbhilite">&amp;varSrc</span>)); <span class="cb1">// Should be &amp;varDest</span></p>
<p class="cl">            }</p>
<p class="cl">        }</p>
<p class="cl">&nbsp;</p>
<p class="cl">        VariantClear(&amp;varDest);</p>
<p class="cl">        <span class="cb2">return</span> hr;</p>
<p class="cl">    }</p>
<p>Looks like it’s the same in Visual Studio 2005 SP1, but Microsoft are aware of the problem, and hopefully there’ll be a patch soon.</p>
<p>Hope this saves you some time!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.voyce.com/index.php/2007/03/02/bug-in-_com_ptr_tquerystdinterfaces/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
