0

I am curious as to how to initialize a PROPVARIANT structure of VT_VARIANT | VT_VECTOR type. An existing model I am aware of is the HeadingPairs property of the DocumentSummaryInformation property set:

The HeadingPairs property is stored as a vector of variants, in repeating pairs of VT_LPSTR (or VT_LPWSTR) and VT_I4 values.

I am aware of the various Init functions, such as the InitPropVariantFromStringAsVector function to create a VT_VECTOR | VT_LPWSTR propvariant, but, as far as I know, there is no function to initialize a PROPVARIANT structure of VT_VARIANT | VT_VECTOR type.

Any help or suggestions would be appreciated.

Thank you.

iPhilip
  • 43
  • 6
  • Not sure it's a valid PROPVARIANT... VARIANT and PROPVARIANT don't "know" each other... Have you tried using InitPropVariantFromPropVariantVectorElem? – Simon Mourier Feb 28 '22 at 18:59
  • Thank you for your comment and suggestion. `VT_VARIANT = 12` and `VT_VECTOR = 0x1000` are a valid PROPVARIANT types ([link](https://learn.microsoft.com/en-us/windows/win32/api/propidlbase/ns-propidlbase-propvariant)). Unfortunately, `InitPropVariantFromPropVariantVectorElem` initializes a PROPVARIANT structure based on a **single** PROPVARIANT vector element. Thus, it doesn't create a structure of either of the desired types. – iPhilip Feb 28 '22 at 19:40
  • Yes, sorry, I meant InitPropVariantVectorFromPropVariant, passing first parameter as VT_ARRAY | VT_VARIANT. But it doesn't seem to work. – Simon Mourier Mar 01 '22 at 07:39

2 Answers2

1

You are correct that there is no ready-made Win32 function to initialize a PROPVARIANT with a vector of PROPVARIANT values. You are just going to have to initialize it manually, ie by allocating an array of PROPVARIANTs and then assigning a pointer to that array to the PROPVARIANT::capropvar.pElems field, and the array's length to the PROPVARIANT::capropvar.cElems field, eg:

int count = ...;
PROPVARIANT *arr = (PROPVARIANT*) CoTaskMemAlloc(count * sizeof(PROPVARIANT));

// initialize array values as needed...

PROPVARIANT pv;
PropVariantInit(&pv);
      
pv.vt = VT_VECTOR | VT_VARIANT;
pv.capropvar.pElems = arr;
pv.capropvar.cElems = count;

// use pv as needed...

PropVariantClear(&pv);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

Here's a prototype based on Remy's solution written in AutoHotkey:

VariantVector := [{vt:0x001F, val:"hello world"}, {vt:0x0003, val:3}]
VarSetCapacity(PropVariant, 8 + 2 * A_PtrSize, 0)
InitPropVariatFromVariantAsVector(PropVariant, VariantVector)
; Do something here...
PropVariantClear(PropVariant)
return

InitPropVariatFromVariantAsVector(ByRef PropVariant, VariantVector) {
   static VT_VARIANT := 0x000C
   static VT_VECTOR  := 0x1000
   static Size := 8 + 2 * A_PtrSize
   
   NumPut(VT_VARIANT | VT_VECTOR,  PropVariant, 0, "UShort")
   NumPut(VariantVector.Count(), PropVariant, 8, "UInt")
   ptr := DllCall("Ole32\CoTaskMemAlloc", "UPtr", Size * VariantVector.Count(), "Ptr")
   NumPut(ptr, PropVariant, 8 + A_PtrSize, "Ptr")
   
   for Each, Variant in VariantVector {
      Offset := Size * (Each - 1)
      NumPut(Variant.vt,  ptr + 0, Offset, "UShort")
      Switch Variant.vt
      {
         Case 0x0003: NumPut(Variant.val, ptr + 0, Offset + 8, "Int")  ; VT_I4
         Case 0x001E: DllCall("Shlwapi\SHStrDup", "AStr", Variant.val, "Ptr", ptr + Offset + 8, "Int")  ; VT_LPSTR
         Case 0x001F: DllCall("Shlwapi\SHStrDup", "WStr", Variant.val, "Ptr", ptr + Offset + 8, "Int")  ; VT_LPWSTR
         Default: throw Exception(A_ThisFunc ": Unsupported Variant Type.", -1, Format("0x{:04X}", Variant.vt))
      }
   }
}

PropVariantClear(ByRef PropVariant) {
   return DllCall("Ole32\PropVariantClear", "Ptr", &PropVariant, "Int")
}
iPhilip
  • 43
  • 6