0

I have an implementation of WMI client application in C++. I am looking to call ProtectKeyWithExternalKey method of the Win32_EncryptableVolume class. It takes a byte array as parameter (ExternalKey).

uint32 ProtectKeyWithExternalKey(
  [in, optional] string FriendlyName,
  [in, optional] uint8  ExternalKey[],
  [out]          string VolumeKeyProtectorID
);

When this method will be called using ExecMethod of IWbemServices class, we need to set IWbemClassObject object for input params and pass to ExecMethod.

    virtual HRESULT STDMETHODCALLTYPE ExecMethod( 
        /* [in] */ __RPC__in const BSTR strObjectPath,
        /* [in] */ __RPC__in const BSTR strMethodName,
        /* [in] */ long lFlags,
        /* [in] */ __RPC__in_opt IWbemContext *pCtx,
        /* [in] */ __RPC__in_opt IWbemClassObject *pInParams,
        /* [unique][in][out] */ __RPC__deref_opt_inout_opt IWbemClassObject **ppOutParams,
        /* [unique][in][out] */ __RPC__deref_opt_inout_opt IWbemCallResult **ppCallResult) = 0;

While setting IWbemClassObject, VARIANT type needs to be set.

    virtual HRESULT STDMETHODCALLTYPE Put( 
        /* [string][in] */ LPCWSTR wszName,
        /* [in] */ long lFlags,
        /* [in] */ VARIANT *pVal,
        /* [in] */ CIMTYPE Type) = 0;

What should be set to VARIANT (VARTYPE and member of union) for byte array (uint8[])?

typedef /* [wire_marshal] */ struct tagVARIANT VARIANT;

struct tagVARIANT
    {
    union 
        {
        struct __tagVARIANT
            {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union 
                {
                LONGLONG llVal;
                LONG lVal;
                BYTE bVal;
                SHORT iVal;
                FLOAT fltVal;
                DOUBLE dblVal;
                VARIANT_BOOL boolVal;
                _VARIANT_BOOL bool;
                SCODE scode;
                CY cyVal;
                DATE date;
                BSTR bstrVal;
                IUnknown *punkVal;
                IDispatch *pdispVal;
                SAFEARRAY *parray;
                BYTE *pbVal;
                SHORT *piVal;
                LONG *plVal;
                LONGLONG *pllVal;
                FLOAT *pfltVal;
                DOUBLE *pdblVal;
                VARIANT_BOOL *pboolVal;
                _VARIANT_BOOL *pbool;
                SCODE *pscode;
                CY *pcyVal;
                DATE *pdate;
                BSTR *pbstrVal;
                IUnknown **ppunkVal;
                IDispatch **ppdispVal;
                SAFEARRAY **pparray;
                VARIANT *pvarVal;
                PVOID byref;
                CHAR cVal;
                USHORT uiVal;
                ULONG ulVal;
                ULONGLONG ullVal;
                INT intVal;
                UINT uintVal;
                DECIMAL *pdecVal;
                CHAR *pcVal;
                USHORT *puiVal;
                ULONG *pulVal;
                ULONGLONG *pullVal;
                INT *pintVal;
                UINT *puintVal;
                struct __tagBRECORD
                    {
                    PVOID pvRecord;
                    IRecordInfo *pRecInfo;
                    }   __VARIANT_NAME_4;
                }   __VARIANT_NAME_3;
            }   __VARIANT_NAME_2;
        DECIMAL decVal;
        }   __VARIANT_NAME_1;
    } ;

Should it be BYTE* for union member? If yes, that would be pointer to unsigned char. How the size of byte array determined? Is it by null char for end of array? In other words, for passing byte array, is uint8* sufficient and size of array is not required?

And what should be initialized to VARTYPE member? Here is the enum.

enum VARENUM
    {
        VT_EMPTY    = 0,
        VT_NULL = 1,
        VT_I2   = 2,
        VT_I4   = 3,
        VT_R4   = 4,
        VT_R8   = 5,
        VT_CY   = 6,
        VT_DATE = 7,
        VT_BSTR = 8,
        VT_DISPATCH = 9,
        VT_ERROR    = 10,
        VT_BOOL = 11,
        VT_VARIANT  = 12,
        VT_UNKNOWN  = 13,
        VT_DECIMAL  = 14,
        VT_I1   = 16,
        VT_UI1  = 17,
        VT_UI2  = 18,
        VT_UI4  = 19,
        VT_I8   = 20,
        VT_UI8  = 21,
        VT_INT  = 22,
        VT_UINT = 23,
        VT_VOID = 24,
        VT_HRESULT  = 25,
        VT_PTR  = 26,
        VT_SAFEARRAY    = 27,
        VT_CARRAY   = 28,
        VT_USERDEFINED  = 29,
        VT_LPSTR    = 30,
        VT_LPWSTR   = 31,
        VT_RECORD   = 36,
        VT_INT_PTR  = 37,
        VT_UINT_PTR = 38,
        VT_FILETIME = 64,
        VT_BLOB = 65,
        VT_STREAM   = 66,
        VT_STORAGE  = 67,
        VT_STREAMED_OBJECT  = 68,
        VT_STORED_OBJECT    = 69,
        VT_BLOB_OBJECT  = 70,
        VT_CF   = 71,
        VT_CLSID    = 72,
        VT_VERSIONED_STREAM = 73,
        VT_BSTR_BLOB    = 0xfff,
        VT_VECTOR   = 0x1000,
        VT_ARRAY    = 0x2000,
        VT_BYREF    = 0x4000,
        VT_RESERVED = 0x8000,
        VT_ILLEGAL  = 0xffff,
        VT_ILLEGALMASKED    = 0xfff,
        VT_TYPEMASK = 0xfff
    } ;

Should it be VT_BLOB?

  • VT_BLOB [P] Length prefixed bytes

Please help. Thanks in advance!

ank
  • 79
  • 7
  • 1
    It's probably expecting a SAFEARRAY in the VARIANT. For an 1-dimensional array, you can use the SafeArrayCreateVector(VT_UI1, 0, count) function and create a VARIANT of type VT_ARRAY | VT_UI1 – Simon Mourier Mar 20 '20 at 13:00
  • 1
    Set values for any properties that do not inherit the values defined for the class by calling the IWbemClassObject::Put method. Refer [it](https://learn.microsoft.com/en-us/windows/win32/wmisdk/creating-and-declaring-an-instance-using-c-). – Strive Sun Mar 24 '20 at 08:11
  • Thanks @SimonMourier for the pointers. So, once SAFEARRAY is created using SafeArrayCreateVector, how should the data pointer be updated for an existing byte array? Should it be just internal pointer assignment like below or is there a method provided which does it? safeArray = SafeArrayCreateVector(VT_UI1, 0, size); safeArray->pvData = pData; – ank Mar 25 '20 at 23:13
  • 1
    Once you have created an array, you can access it's data using SafeArrayAccessData: https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-safearrayaccessdata – Simon Mourier Mar 26 '20 at 06:26

0 Answers0