IPropertyStorage::ReadMultiple
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 |
); |
|
Parameters
cpspec
[in] Count of
properties specified in the rgpspec array. May legally be zero, though
this is a no-op, reading no properties.
rgpspec[]
[in] The
properties to be read in the PROPSPEC
rgvar[]
[in, out]
Caller-allocated array of PROPVARIANTs that, on return, contains the values of
the properties specified by rgpspec. The array must be able to receive
at least cpspec PROPVARIANTs. The caller does not need to initialize
these PROPVARIANTs in any particular way; the implementation must fill in all
field members correctly on return. If there is no other appropriate value, the
implementation must set the vt member of each PROPVARIANT
Return Values
This method
supports the standard return value E_UNEXPECTED, as well as the following:
S_OK
Success. At
least some of the requested properties were retrieved.
S_FALSE
All the
property names or identifiers had valid syntax, but none of them exist in this
property set. Accordingly, no properties were retrieved., and each PROPVARIANT
structure is set to VT_EMPTY.
STG_E_ACCESSDENIED
The requested
access to the property set has been denied, or, when one or more of the
properties is a stream or storage object, access to that substorage or
substream has been denied. (The storage or stream may already be open). No
properties were retrieved.
STG_E_INSUFFICIENTMEMORY
There is not
sufficient memory to perform this operation. No properties were retrieved.
STG_E_INVALIDPARAMETER
At least one
of the parameters is invalid, such as when one of the PROPSPECs contains an
illegal ulKind value. No properties were retrieved.
STG_E_INVALIDPOINTER
At least one
of the pointers passed in is invalid. No properties were retrieved.
HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)
There was a
failed attempt to translate a Unicode string to or from Ansi.
Remarks
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
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 IStreamFS1VT1 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.
See Also