# PROPVARIANT

The PROPVARIANT structure is used in most of the methods of IPropertyStorage to define the type tag and the value of a property in a property set. There are five members. The first, the value type tag, and the last, the value of the property, are significant. The middle three are reserved for future use. The PROPVARIANT structure is defined as follows:

Note The bool member in previous definitions of this structure has been renamed to boolVal, since some compilers now recognize bool as a keyword.

    struct PROPVARIANT{
        VARTYPE        vt;          // value type tag
        WORD           wReserved1;
        WORD           wReserved2;
        WORD           wReserved3;
        union {
        // none                     // VT_EMPTY, VT_NULL, VT_ILLEGAL
        unsigned char  bVal;        // VT_UI1
        short          iVal;        // VT_I2
        USHORT         uiVal;       // VT_UI2
        long           lVal;        // VT_I4
        ULONG          ulVal;       // VT_UI4
        LARGE_INTEGER  hVal;        // VT_I8
        ULARGE_INTEGER uhVal;       // VT_UI8
        float          fltVal;      // VT_R4
        double         dblVal;      // VT_R8
        CY             cyVal;       // VT_CY
        DATE           date;        // VT_DATE
        BSTR           bstrVal;     // VT_BSTR
        VARIANT_BOOL   boolVal;        // VT_BOOL
        SCODE          scode;       // VT_ERROR
        FILETIME       filetime;    // VT_FILETIME
        LPSTR          pszVal;      // VT_LPSTR     // string in the current system Ansi code page
        LPWSTR         pwszVal;     // VT_LPWSTR    // string in Unicode
        CLSID*         puuid;       // VT_CLSID
        CLIPDATA*      pclipdata;   // VT_CF

        BLOB           blob;        // VT_BLOB, VT_BLOBOBJECT
        IStream*       pStream;     // VT_STREAM, VT_STREAMED_OBJECT
        IStorage*      pStorage;    // VT_STORAGE, VT_STORED_OBJECT

        CAUB           caub;         // VT_VECTOR | VT_UI1
        CAI            cai;          // VT_VECTOR | VT_I2
        CAUI           caui;         // VT_VECTOR | VT_UI2
        CAL            cal;          // VT_VECTOR | VT_I4
        CAUL           caul;         // VT_VECTOR | VT_UI4
        CAH            cah;          // VT_VECTOR | VT_I8
        CAUH           cauh;         // VT_VECTOR | VT_UI8
        CAFLT          caflt;        // VT_VECTOR | VT_R4
        CADBL          cadbl;        // VT_VECTOR | VT_R8
        CACY           cacy;         // VT_VECTOR | VT_CY
        CADATE         cadate;       // VT_VECTOR | VT_DATE
        CABSTR         cabstr;       // VT_VECTOR | VT_BSTR
        CABOOL         cabool;       // VT_VECTOR | VT_BOOL
        CASCODE        cascode;      // VT_VECTOR | VT_ERROR
        CALPSTR        calpstr;      // VT_VECTOR | VT_LPSTR
        CALPWSTR       calpwstr;     // VT_VECTOR | VT_LPWSTR
        CAFILETIME     cafiletime;   // VT_VECTOR | VT_FILETIME
        CACLSID        cauuid;       // VT_VECTOR | VT_CLSID
        CACLIPDATA     caclipdata;   // VT_VECTOR | VT_CF
        CAPROPVARIANT  capropvar;    // VT_VECTOR | VT_VARIANT
        }} PROPVARIANT

Remarks

PROPVARIANT is the fundamental data type by which property values are read and written through the IPropertyStorage interface.

The data type PROPVARIANT is related to the data type VARIANT, defined as part of Automation in OLE2 and defined in the Win32 SDK header file oleauto.h. Several definitions are reused from Automation, as follows:

    typedef struct  tagCY {
        unsigned long      Lo;
        long               Hi;
        } CY

    typedef CY             CURRENCY;
    typedef short          VARIANT_BOOL;
    typedef unsigned short VARTYPE;
    typedef double         DATE;
    typedef OLECHAR*       BSTR;

    typedef struct         tagCLIPDATA {
        ULONG              cbSize;  //Includes sizeof(ulClipFmt)
        long               ulClipFmt;
        BYTE*              pClipData;
        } CLIPDATA

In addition, several new data types that define counted arrays of other data types are required. The data types of all counted arrays begin with the letters CA (such as CAUB) and have an ORed vt value. The counted array structure has the following form (where name is the specific name of the counted array):

    #define TYPEDEF_CA(type, name)

        typedef struct tag ## name {\
            ULONG cElems;\
            type *pElems;\
            } name

Propvariant Type | Code | Propvariant Member | Value Representation
VT_EMPTY | 0 | None | A property with a type indicator of VT_EMPTY has no data associated with it; that is, the size of the value is zero.
VT_NULL | 1 | None | This is like a pointer to NULL.
VT_UI1 | 17 | bVal | 1-byte unsigned integer
VT_I2 | 2 | iVal | Two bytes representing a 2-byte signed integer value.
VT_UI2 | 18 | uiVal | 2-byte unsigned integer
VT_I4 | 3 | lVal | 4-byte signed integer value
VT_UI4 | 19 | ulVal | 4-byte unsigned integer
VT_I8 | 20 | hVal | 8-byte signed integer
VT_UI8 | 21 | uhVal | 8-byte unsigned integer
VT_R4 | 4 | fltVal | 32-bit IEEE floating point value
VT_R8 | 5 | dblVal | 64-bit IEEE floating point value
VT_CY | 6 | cyVal | 8-byte two's complement integer (scaled by 10,000). This type is commonly used for currency amounts.
VT_DATE | 7 | date | A 64-bit floating point number representing the number of days (not seconds) since December 31, 1899. For example, January 1, 1900 is 2.0, January 2, 1900 is 3.0, and so on). This is stored in the same representation as VT_R8.
VT_BSTR | 8 | bstrVal | Pointer to a null terminated Unicode string. The string is immediately preceded by a DWORD representing the byte count, but bstrVal points past this DWORD to the first character of the string. BSTRs must be allocated and freed using the OLE Automation SysAllocString and SysFreeString calls.
VT_BOOL | 11 | boolVal (bool in earlier designs) | Boolean value, a WORD containing 0 (false) or -1 (true).
VT_ERROR | 10 | scode | A DWORD containing a status code.
VT_FILETIME | 64 | filetime | 64-bit FILETIME structure as defined by Win32. It is recommended that all times be stored in Universal Coordinate Time (UTC).
VT_LPSTR | 30 | pszVal | Pointer to a null terminated ANSI string in the system default code page.
VT_LPWSTR | 31 | pwszVal | Pointer to a null terminated Unicode string in the user’s default locale.
VT_CLSID | 72 | puuid | Pointer to a CLSID (or other GUID).
VT_CF | 71 | pclipdata | Pointer to a CLIPDATA structure, described above.
VT_BLOB | 65 | blob | DWORD count of bytes, followed by that many bytes of data. The byte count does not include the four bytes for the length of the count itself; an empty BLOB would have a count of zero, followed by zero bytes. This is similar to VT_BSTR but does not guarantee a null byte at the end of the data.
VT_BLOBOBJECT | 70 | blob | A BLOB containing a serialized object in the same representation as would appear in a VT_STREAMED_OBJECT. That is, a DWORD byte count (where the byte count does not include the size of itself) which is in the format of a class identifier followed by initialization data for that class. The only significant difference between VT_BLOB_OBJECT and VT_STREAMED_OBJECT is that the former does not have the system-level storage overhead that the latter would have, and is therefore more suitable for scenarios involving numbers of small objects.
VT_STREAM | 66 | pStream | Pointer to an IStream interface, representing a stream which is a sibling to the “Contents” stream.
VT_STREAMED_ OBJECT | 68 | pStream | As in VT_STREAM, but indicates that the stream contains a serialized object, which is a CLSID followed by initialization data for the class. The stream is a sibling to the Contents stream that contains the property set.
VT_STORAGE | 67 | pStorage | Pointer to an IStorage interface, representing a storage object that is a sibling to the “Contents” stream.
VT_STORED_ OBJECT | 69 | pStorage | As in VT_STORAGE, but indicates that the designated IStorage contains a loadable object.
VT_VECTOR | 0x1000 | ca* | If the type indicator is one of the simple propvariant types ORed with this one, the value is one of the counted array values. This is a DWORD count of elements, followed by that many repetitions of the value. For example, a type indicator of VT_LPSTR|VT_VECTOR has a DWORD element count, a DWORD byte count, the first string data, padding bytes for 32-bit alignment (see below), a DWORD byte count, the second string data, and so on. Nonsimple types cannot be ORed with VT_VECTOR. These types are VT_STREAM, VT_STREAM_OBJECT, VT_STORAGE, VT_STORAGE_OBJECT. VT_BLOB and VT_BLOB_OBJECT types also cannot be ORed with VT_VECTOR.
VT_VARIANT | 12 | capropvar | A DWORD type indicator followed by the corresponding value. VT_VARIANT can be used only with VT_VECTOR.
VT_TYPEMASK | 0xFFF |  | Used as a mask for VT_VECTOR and other modifiers to extract the raw VT value.

Clipboard format identifiers, stored with the tag VT_CF, use one of five different representations (identified in the ulClipFmt member of the CLIPDATA structure):

ulClipFmt Value | pClipData value
-1L | a DWORD containing a built-in Windows clipboard format value.
-2L | a DWORD containing a Macintosh clipboard format value.
-3L | a GUID containing a format identifier (rarely used).
any positive value | a null-terminated string containing a Windows clipboard format name, one suitable for passing to RegisterClipboardFormat. The code page used for characters in the string is per the code page indicator. The “positive value” here is the length of the string, including the null byte at the end.
0L | no data (rarely used)

Within a vector of values, each repetition of a value is to be aligned to 32-bit boundaries. The exception to this rule is scalar types which are less than 32 bits: VT_UI1, VT_12, VT_U12, and VT_BOOL. Vectors of these values are packed.

Therefore, a value with type tag VT_I2 | VT_VECTOR would be a DWORD element count, followed by a sequence of packed 2-byte integers with no padding between them.

However, a value with type tag VT_LPSTR | VT_VECTOR would be a DWORD element count, followed by a sequence of (DWORD cch, char rgch[]) strings, each of which may be followed by null padding to round to a 32-bit boundary.