PropVariant Documentation
This is just a short comment about the documentation for the PropVariant. It may, however, save you some hours of debugging. (At least it would have saved me some if someone had posted this!)If you ever try to marshal a PropVariant that contains a serialized structure/object with "vt" set to "VT_BLOB" (65), then take note of this:
The documentation tells you that the PropVariant structure contains a 32 bits integer that is the count of the byte array, followed by that many bytes of data.
This is not right, the PropVariant contains a 32 bits integer that is the count of the byte array followed by a 32 bits pointer to the array of byte.
Just keep this in mind: The PropVariant will always be 16 bytes long, The embedded anonymous Union always be 8 bytes long even if the data it contains is smaller than 8 bytes. The data will always be found at offset 8 in the structure and will be little endian.
Context
Since some are interested to know what I am talking about, I will add a little bit of context here.
First let start with the strait answer. A PropVariant is an unmanaged data type that is used to access the properties from the devices property store.
Devices are of course any pieces of hardware .. chips on the mother board, mouse, storage device, sound card, graphic card, ... etc. Basically any thing that works with a device driver !
------------
Now, let's talk a bit about this PropVariant.
A propVariant, as a Variant, is a container that can hold any type of data. You can assign an integer, a string, an object an interface, ...etc and the propvariant will be able to contain it.
You can think of it as an unmanaged equivalent of the managed type "Object" that can be assigned any object.
However, there is a big difference between a Propvariant and an object. The data contain in a propVariant is un-typed. This is causing a big problem when comes time to use it in managed code. C# and VB are strongly typed languages and cannot deal with any un-typed data.
Therefore, when marshaling a PropVariant to managed language, the first thing to do is to discover what kind of data the PropVariant contains ( Since like I said, it can contain any kind of data ) an then we need to create an managed object with an equivalent data type and and assign to this object an equivalent value. ( And this is not always easy since managed data types and unmanaged data types are really two different beasts )
One question can be raised here; Why implementing a PropVariant since the namespace "Microsoft.VisualStudio.OLE.Interop" expose an implementation of the PropVariant?
There are two good reasons for that:
1) Memory leaks: The PropVariant is used to access the devices properties, and this is done through COM interfaces that require that the property value be be passed using variables passed by Ref. Therefore, your application creates the variable and the data in it is filled by the device. The rule under Windows, is that the party that creates the variable is responsive to perform the resources clean up. So, your application is responsive to perform the clean up of the ummanaged resources allocated to return the value.
The implementation of the PropVariant in the namespace "Microsoft.VisualStudio.OLE.Interop" is not a IDisposable class therefore, unless you have a good knowledge of what need to be disposed, how and when, memory leaks
2) The second reason is that the implementation in the namespace "Microsoft.VisualStudio.OLE.Interop" always return the data types as an IntPtr, regardless of what it is, byte, string, pointer, integer, structure, ...etc. And this is not really friendly !
-------------
Finally, a word about what I am implementing.
I am implementing a class that, when access from unmanaged code, will expose itself as a Propvariant Structure, and when access from managed code, will expose itself as a strongly typed object (And typed in respect with the kind of data type contain in the Propvariant)
Therefore the class must be able at runtime to auto discover its data type and change its own type to the appropriate equivalent type.
The Type change must also be done such way that even using reflection, it will reflect on the right type.
The type change should also not affect that if the variable is send back to unmanaged code, it keeps the ability to expose itself as a PropVariant
(And of course without using late binding or narrowing cast)
The class will also provide some tools to properly insure that the unmanaged resources gets cleaned up.
We will see how it goes, I might post the code for this class somewhere. If I do I'll add a link to it here.
References
http://msdn.microsoft.com/en-us/library/windows/desktop/aa380072(v=vs.85).aspx