yummi! A new namespace! Let's have a look at ComTypes (NET 2.0)


I just had some COM interop work, and decided to use STGMEDIUM and
FORMATETC.
These structs, are necessary for many CLIPboard operations. But what draws my attention?
the MSDN says this:

typedef struct tagSTGMEDIUM

{

    DWORD tymed;

    [switch_type(DWORD), switch_is((DWORD) tymed)]

    union {

        [case(TYMED_GDI)]      HBITMAP        hBitmap;

        [case(TYMED_MFPICT)]   HMETAFILEPICT  hMetaFilePict;

        [case(TYMED_ENHMF)]    HENHMETAFILE   hEnhMetaFile;

        [case(TYMED_HGLOBAL)]  HGLOBAL        hGlobal;

        [case(TYMED_FILE)]     LPWSTR         lpszFileName;

        [case(TYMED_ISTREAM)]  IStream        *pstm;

        [case(TYMED_ISTORAGE)] IStorage       *pstg;

        [default] ;

    };

    [unique] IUnknown *pUnkForRelease;

}STGMEDIUM;

typedef STGMEDIUM *LPSTGMEDIUM;
As we all know, a union, in C++ is just a keyword which makes it's member variables start all at the same memory location. In a .NET struct, we can have the same result by using the following atribute: [StructLayout(LayoutKind.Explicit)]
For each structure member,. you now can specify an offset.
Our dear developers, decided for us, that we should not have that luxury of difficult choices having a struct with explicit layout, but let's not complain about this for now...
There is something -more- seriously wrong.

Have a look at the built in interop defintion (in the .NET 2.0 framework!)
(namespace System.Runtime.InteropServices.ComTypes)
public struct STGMEDIUM
{
public object pUnkForRelease;
public TYMED tymed;
public IntPtr unionmember;
}
 
After some crashes, I found that the definition, contains the correct members  at the wrong location!

As you can see, this defintion, is wrong and should be
public struct STGMEDIUM
{

public TYMED tymed;
public IntPtr unionmember;
public object pUnkForRelease;
}
 
A similar problem exists with FORMATETC. I'll not bother you with the details, but let's just post the correct defition. Next time, if you need these structs, don't use the one from the .NET 2.0 interop layer...

[StructLayout(LayoutKind.Sequential)]
public struct FORMATETC
{
   public short cfFormat;
   public IntPtr ptd;
   [
MarshalAs(UnmanagedType.U4)]
   public DVASPECT dwAspect; 
   public int lindex;
   [
MarshalAs(UnmanagedType.U4)]
   public TYMED tymed;
};

blog comments powered by Disqus