Reads specified properties from the current property set.
HRESULT ReadMultiple(
ULONG cpspec, //Count of properties being read
PROPSPEC const rgpspec[], //Array of the properties to be read
PROPVARIANT rgvar[] //Array of PROPVARIANTs containing the
//property values on return
);
This method supports the standard return value E_UNEXPECTED, as well as the following:
IPropertyStorage::ReadMultiple reads as many of the properties specified in the rgpspec array as are found in the property set. As long as any of the properties requested is read, a request to retrieve a property that does not exist is not an error. Instead, this must cause VT_EMPTY to be written for that property to the rgvar[] array on return. When none of the requested properties exist, the method should return S_FALSE, and set VT_EMPTY in each PROPVARIANT. If any other error is returned, no property values are retrieved, and the caller need not worry about releasing them.
The rgpspec parameter is an array of PROPSPEC structures, which specify for each property either its property identifier or, if one is assigned, a string identifier. You can map a string to a property identifier by calling IPropertyStorage::WritePropertyNames. The use of property identifiers is, however, likely to be significantly more efficient than the use of strings.
Properties that are requested by string name (PRSPEC_LPWSTR) are mapped case-insensitively to property identifiers as they are specified in the current property set (and according to the current system locale).
All propvariants, except for those that are pointers to streams and storages, are called simple propvariants. These simple propvariants receive data by value, so a call to IPropertyStorage::ReadMultiple supplies a copy of the data that the caller then owns. To create or update these properties, call IPropertyStorage::WriteMultiple.
In contrast, the variant types VT_STREAM, VT_STREAMEDOBJECT, VT_STORAGE, and VT_STOREDOBJECT are non-simple properties, because rather than supplying a value, the method retrieves a pointer to the indicated interface, from which the data can then be read. These types permit the storage of large amounts of information through a single property. There are several issues that arise in using non-simple properties.
To create these properties, as for the other properties, call IPropertyStorage::WriteMultiple. Rather than calling the same method to update, however, it is more efficient to first call IPropertyStorage::ReadMultiple to get the interface pointer to the stream or storage, then write data using the IStream or IStorage methods. A stream or storage opened through a property is always opened in direct mode, so an additional level of nested transaction is not introduced. There may, however, still be a transaction on the property set as a whole, depending on how it was opened or created through IPropertySetStorage. Further, the access and share mode tags specified when the property set is opened or created, are passed to property-based streams or storages.
The lifetimes of property-based stream or storage pointers, although theoretically independent of their associated IPropertyStorage and IPropertySetStorage pointers, in fact, effectively depend on them. The data visible through the stream or storage is related to the transaction on the property storage object from which it is retrieved, just as for a storage object (supporting IStorage) with contained stream and storage sub-objects. If the transaction on the parent object is aborted, existing IStream and IStorage pointers subordinate to that object enter a "zombie" state. Because IPropertyStorage is the only interface on the property storage object, the useful lifetime of the contained IStream and IStorage pointers is bounded by the lifetime of the IPropertyStorage interface.
The implementation must also deal with the situation where the same stream- or storage-valued property is requested multiple times through the same IPropertyStorage interface instance. For example, in the OLE compound file implementation, the open will succeed or fail depending on whether or not the property is already open.
Another issue is multiple opens in transacted mode. The result depends on the isolation level that was specified through a call to IPropertySetStorage methods, (either the Open or Create method, through the STGM flags) at the time that the property storage was opened .
If the call to open the property set specifies read-write access, IStorage- and IStream-valued properties are always opened with read-write access. Data can then be written through these interfaces, changing the value of the property, which is the most efficient way to update these properties. The property value itself does not have an additional level of transaction nesting, so changes are scoped under the transaction (if any) on the property storage object.
Windows NT: Use version 4.0 or later.
Windows: Use Windows 95 or later. Available as a redistributable for Windows 95.
Windows CE: Unsupported.
Header: Declared in objidl.h.
IPropertySetStorage, IPropertyStorage::WriteMultiple, IPropertyStorage::WritePropertyNames