PROPVARIANT helpers #1 - Initialization

PROPVARIANTs are easy to misuse. Because the data members are so cryptic, it is easy to get confused or to overlook errors.

To help alleviate these and other problems (including readability), we provide a series of PROPVARIANT helpers for common uses. There are a lot of 'em, so I will split this over several days. Here's the first batch which deal with initializing a PROPVARIANT with a particular type of data.

// The following are the most common and straightforward to use.
void PropVariantInit ( PROPVARIANT * pvar ); // VT_EMPTY
HRESULT InitPropVariantFromBoolean(BOOL fVal, __out PROPVARIANT *ppropvar); // VT_BOOL
HRESULT InitPropVariantFromInt16(SHORT nVal, __out PROPVARIANT *ppropvar); // VT_I2
HRESULT InitPropVariantFromUInt16(USHORT uiVal, __out PROPVARIANT *ppropvar); // VT_UI2
HRESULT InitPropVariantFromInt32(LONG lVal, __out PROPVARIANT *ppropvar); // VT_I4
HRESULT InitPropVariantFromUInt32(ULONG ulVal, __out PROPVARIANT *ppropvar); // VT_UI4
HRESULT InitPropVariantFromInt64(LONGLONG llVal, __out PROPVARIANT *ppropvar); // VT_I8
HRESULT InitPropVariantFromUInt64(ULONGLONG ullVal, __out PROPVARIANT *ppropvar); // VT_UI8
HRESULT InitPropVariantFromDouble(DOUBLE dblVal, __out PROPVARIANT *ppropvar); // VT_R8
HRESULT InitPropVariantFromString(PCWSTR psz, __out PROPVARIANT *ppropvar); // VT_LPWSTR
HRESULT InitPropVariantFromGUIDAsBuffer(REFGUID guid, __out PROPVARIANT *ppropvar); // VT_VECTOR | VT_UI1
PSSTDAPI InitPropVariantFromCLSID(REFCLSID clsid, __out PROPVARIANT *ppropvar); // VT_GUID
PSSTDAPI InitPropVariantFromFileTime(const FILETIME *pftIn, __out PROPVARIANT *ppropvar); // VT_FILETIME

// These are interesting. They deserve their own posts (...note to self...)
PSSTDAPI InitPropVariantFromStringAsVector(
PCWSTR psz, __out PROPVARIANT *ppropvar); // VT_VECTOR | VT_LPWSTR
PSSTDAPI InitPropVariantFromPropVariantVectorElem(
REFPROPVARIANT propvarIn, ULONG iElem, __out PROPVARIANT *ppropvar);
PSSTDAPI InitPropVariantFromStrRet(
__in STRRET *pstrret, PCUITEMID_CHILD pidl, __out PROPVARIANT *ppropvar); // VT_LPWSTR

// The following are vector versions:
// VT_VECTOR | VT_LPWSTR
PSSTDAPI InitPropVariantFromStringVector(
__in_ecount_opt(cElems) PCWSTR *prgsz, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_BOOL
PSSTDAPI InitPropVariantFromBoolVector(
__in_ecount_opt(cElems) const BOOL *prgf, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_I2
PSSTDAPI InitPropVariantFromInt16Vector(
__in_ecount_opt(cElems) const SHORT *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_UI2
PSSTDAPI InitPropVariantFromUInt16Vector(
__in_ecount_opt(cElems) const USHORT *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_I4
PSSTDAPI InitPropVariantFromInt32Vector(
__in_ecount_opt(cElems) const LONG *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_UI4
PSSTDAPI InitPropVariantFromUInt32Vector(
__in_ecount_opt(cElems) const ULONG *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_I8
PSSTDAPI InitPropVariantFromInt64Vector(
__in_ecount_opt(cElems) const LONGLONG *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_UI8
PSSTDAPI InitPropVariantFromUInt64Vector(
__in_ecount_opt(cElems) const ULONGLONG *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_DOUBLE
PSSTDAPI InitPropVariantFromDoubleVector(
__in_ecount_opt(cElems) const DOUBLE *prgn, ULONG cElems, __out PROPVARIANT *ppropvar);

// VT_VECTOR | VT_FILETIME
PSSTDAPI InitPropVariantFromFileTimeVector(
__in_ecount_opt(cElems) const FILETIME *prgft, ULONG cElems, __out PROPVARIANT *ppropvar);

// These helpers are used less frequently. I may talk about them eventually.
PSSTDAPI InitPropVariantVectorFromPropVariant(
REFPROPVARIANT propvarSingle, __out PROPVARIANT *ppropvarVector);
PSSTDAPI InitPropVariantFromBuffer(
const void *pv, UINT cb, __out PROPVARIANT *ppropvar); // VT_VECTOR | VT_UI1
PSSTDAPI InitPropVariantFromResource(
HINSTANCE hinst, UINT id, VARTYPE vtSaveIn, __out PROPVARIANT *ppropvar); // VT_LPWSTR
PSSTDAPI InitPropVariantFromGUIDAsString(
REFGUID guid, __out PROPVARIANT *ppropvar); // VT_LPWSTR

All these helpers live in propvarutil.h (except for PropVariantInit which lives in propidl.h). Non-inline helpers are implemented in propsys.dll.

As it may be some time before I blog about individual functions, if you are anxious to hear the nitty gritty, just send me a note.

Comments

  • Anonymous
    September 15, 2006
    This is cool stuff, thanks for blogging about this!

    I have a suggestion about the various new PropVariant/Variant helper functions.  Can you get the SDK people to put them all in a separate section?  Right now they're thrown in with the rest of the shell functions, making the already massive-and-unorganized shell function reference even more bloated.  These new functions are seperate enough to warrant their own section of the documentstion. :)
  • Anonymous
    September 15, 2006
    I will certainly pass that on to our doc writers.  They are probably aware of this too, but I think they are entirely focused on getting the content written and fleshed out first.  I agree this isn't ideal, but the pragmatic side of me says that the content is more important to get right.

    On the bright side, almost all the property system APIs are defined in propsys.idl/h, propvarutil.h, or propidl.idl/h.  You can just open those and see most of the functions and interfaces that are available. [Update 2006/09/19: I talked to our doc writer and he used words like "horrendous" and "unacceptable", so you are not alone.  He said they have sometimes attempted to use better organization, but that they have not had time scheduled to tackle such a challenge.  They are currently working around the clock to get accurate documentation in place about each API that will ship with Vista.  Unfortunately, we will have to live with this flat structure for the first release of the SDK.