PROPVARIANT is Important
PROPVARIANT is an important COM structure that is used in many windows shell features like: Shell Namespace Extensions, Taskbar Jump List, Sensors and Windows Ribbon Framework, just to name a few.
In order to use these shell features in managed code, one must provide a .NET wrapper for this struct.
Now, you might have expected that if this struct is so important, there would be good .NET wrappers for it..
Unfortunately, this is not the case. The problem with this struct is that it is pretty complicated. It’s constructed from some simple fields and a union of ALL COM types. This includes 73 (!) types, from simple native types till SAFEARRAYs (COM arrays) of COM object types. So in order to marshal this type properly between native-managed boundaries, one must handle marshalling according to the actual union type (marshalling an integer is different than marshalling a string and different than marshalling a pointer to an array of objects).
One more thing that makes it hard to implement a managed version is that PROPVARIANT itself has a special treatment for one type, namely DECIMAL.
PROPVARIANT structure has a size of 20 bits (on 32 bits systems), its definition is something like:
The VARTYPE member specify the type of value the struct currently hold.
Now, If the VARTYPE equals VT_DECIMAL then the entire structure (including the VARTYPE part itself!) is being read as if it was a DECIMAL structure. Let me stress that again: On VT_DECIMAL the VARTYPE-part of the struct overlaps the DECIMAL structure.
The reason why this can work is that VARTYPE has a size of 2 bytes and it turns out that the first 2 bytes of the DECIMAL structure are reserved. So the values of the DECIMAL type and VARTYPE member can coexist.
The main point you should have understand until this point is that implementing a managed wrapper for PROPVARIANT is hard. Specifically if you want to support many types.
Google PROPVARIANT finds several implementations, which supports only a limited set of types.
In Adam’s implementation the VT_DECIMAL case is not handled. In contrast, Windows API Code Pack v1.0 has an implementation but unfortunately it is quite buggy. Let’s check it together:
The first problem is the call for Marshal.SizeOf on an enum value. If this was possible, it would have return the size of the enum, which is 4 bytes. Not the size of a DECIMAL struct (20).
The second problem is that Marshal.SizeOf can’t be called on an Enum, it immediately throws an ArgumentException with: “Type ‘System.Runtime.InteropServices.VarEnum’ cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed. “.
The third problem is in the concept. Setting a DECIMAL into a PROPVARIANT should not allocate any memory. The memory is already there, just copy the DECIMAL value onto the PROPVARIANT place.
The valueData element should not hold a pointer to the decimal. It should contain part of the decimal itself!
Our solution for setting a decimal into the PROPVARIANT structure is quite simple. It uses our knowledge on the exact structure of both DOUBLE and PROPVARIANT structures. The following code should be part of the PropVariant.cs file in Windows API Code Pack:
public void SetDecimal(decimal value)
int bits = Decimal.GetBits(value);
valueData = (IntPtr)bits;
valueDataExt = bits;
wReserved3 = (ushort)(bits >> 16);
wReserved2 = (ushort)(bits & 0x0000FFFF);
wReserved1 = (ushort)(bits >> 16);
valueType = (ushort)VarEnum.VT_DECIMAL;
decimal decVal // DECIMAL decVal
int bits = new int;
bits = (int)valueData;
bits = valueDataExt;
bits = (wReserved3 << 16) | wReserved2;
bits = (wReserved1 << 16);
return new decimal(bits);
What we do is taking the decimal apart, and setting the PropVariant fields according to the correct layout.
Now, since I don’t want to create my own version of Windows API Code Pack, I wrote a similar implementation that changes the private PropVariant fields from outside using reflection. Not the best piece of code but has the advantage of working on top of Windows API Code Pack v1.0. Hopefully they will fix it in a future version.
By the way, extension methods won’t work here since the PropVariant is defined as a struct and so is immutable, so making the extension method change its internals won’t have an affect on the original PropVariant. (Also, no “ref this PropVariant propVariant” is possible).
Here is the less intrusive version:
For the sake of completeness I provide PropVariant.cs, which is based on Windows API Code Pack v1.0 version with my fix for proper support for decimal values. Note that it was tested only on a 32bit machine.
Update: As I’ve mentioned at the end of the post Windows Ribbon for WinForms, Part 13 – DropDownColorPicker, I’ve created a newer version of PropVariant class which is a combination of both Windows API Code Pack version and PreviewRibbon version.
That’s it for now,