IPropertyStorage::WriteMultiple
Writes a
specified group of properties to the current property set. If a property with a
specified name already exists, it is replaced, even when the old and new types
for the property value are different. If a property of a given name or property
identifier does not exist, it is created.
HRESULT
WriteMultiple(
ULONG cpspec, |
//The number of properties being set. |
PROPSPEC const rgpspec[], |
//Property specifiers |
PROPVARIANT const rgvar[], |
//Array of PROPVARIANT values |
PROPID propidNameFirst |
//Minimum value for property identifiers when they
must be allocated |
); |
|
Parameters
cpspec
[in] The
number of properties being set. May legally be zero, though this is a no-op,
writing no properties.
rgpspec[]
[in] Array of
the specifiers to which properties are to be set. These are in no particular
order, and may legally contain duplicates (the last specified is to take
effect). A mixture of property identifiers and string names is permitted.
rgvar[]
[in] An array
(of size cpspec) of PROPVARIANTs that contain the property values to be
written. The array must be of the size specified by cpspec.
propidNameFirst
[in]
Specifies the minimum value for the property identifiers the method must assign
if the rgpspec parameter specifies string-named properties for which no
property identifiers currently exist. If all string-named properties specified
already exist in this set, and thus already have property identifiers, this
value is ignored. When not ignored, this value must be at least two (property
identifiers 0and 1 are reserved for special uses) and less than 0x80000000
(property identifier values beyond that are reserved for special use).
HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)
There was a
failed attempt to translate a Unicode string to or from Ansi.
Return Values
This method
supports the standard return value E_UNEXPECTED, as well as the following:
S_OK
All of the
indicated properties were successfully written.
STG_E_ACCESSDENIED
The requested
access to the property storage object has been denied. No properties have been
written. The property set was opened in STGM_READ mode.
STG_E_INSUFFICIENTMEMORY
There is not
sufficient memory to perform this operation. Some properties may or may not
have been written.
STG_E_INVALIDPARAMETER
At least one
of the parameters is invalid. Some properties may not have been written. This
error would be returned in several situations, for example: 1) rgvar may
be NULL; 2) a stream- or storage-valued property is present in rgpspec
but the property set was created without PROPSETFLAG_NONSIMPLE; 3) one or more
property variant types may be invalid; 4) one of the PROPSPECs contains an
illegal ulKind value.
STG_E_INVALIDPOINTER
May be
returned when at least one of the pointers passed in is invalid. Some properties
may or may not have been written. More frequently, an invalid pointer will
instead result in an access violation.
STG_E_WRITEFAULT
Error writing
the storage.
STG_E_REVERTED
The property
set was reverted. For example, if the property set is deleted while open (by
using IPropertySetStorage::Delete) this status would be returned.
STG_E_MEDIUMFULL
The disk is
full. Some properties may or may not have been written.
STG_E_PROPSETMISMATCHED
An attempt
was made to write a non-simple (stream- or storage-valued) property to a simple
property set.
Remarks
If a
specified property already exists, it s value is replaced with the new one,
even when the old and new types for the property value are different. If you
specify a property identifier that does not exist, that property is created. If
a string name is supplied for a property which does not exist, the method will
allocate a property identifier for that property, and the name will be added to
the dictionary.
When
allocating a property identifier, the implementation can choose any value not
currently in use in the property set for a property identifier, as long as it
is not 0 or 1 or greater than 0x80000000, all of which are reserved values. The
propidNameFirst parameter establishes a minimum value for property
identifiers within the set, and must be greater than 1 and less than
0x80000000.
If there is
an attempt to write a property that already exists with an invalid parameter,
the method should return STG_E_INVALIDPARAMETER; if the property does not
exist, it should not be created. This behavior facilitates the use of a ReadMultiple
- update - WriteMultiple sequence to update a group of
properties without requiring that the calling code ensure that all the
requested properties in the call to ReadMultiple were retrieved.
It is
recommended that property sets be created as Unicode, by not setting the PROPSETFLAG_ANSI
flag in the grfFlags parameter of IPropertySetStorage::Create. It
is also recommended that you avoid using VT_LPSTR values, and use VT_LPWSTR
values instead. When the property set code page is Unicode, VT_LPSTR string
values are converted to Unicode when stored, and back to multibyte string
values when retrieved. When the code page of the property set is not Unicode,
property names, VT_BSTR strings, and non-simple property values are converted
to multibyte strings when stored, and converted back to Unicode when retrieved,
all using the current system ANSI code page.
To create
stream or storage object as a property in a nonsimple property set, call IPropertyStorage::WriteMultiple.
While you would also call this method to update simple properties, it is not an
efficient way to update stream and storage objects in a property set. This is
because updating one of these properties through a call to WriteMultiple
creates in the property storage object a copy of the passed-in data, and the IStorage
or IStream pointers are not retained beyond the duration of this call.
It is usually more efficient to update stream or storage objects by first
calling IPropertyStorage::ReadMultiple to get the interface pointer to
the stream or storage, then writing data through 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 is still likely
to be a transaction on the property set as a whole. Further, a property-based
stream or storage is opened in read-write mode, if possible, given the mode on
the property set; otherwise, read mode is used.
When the copy
is made, the underlying CopyTo operation on VT_STREAM properties operates on
the current seek position of the source. The seek position is destroyed on
failure, but on success it is at EOF.
If a stream
or storage property does not exist, passing an IStream or IStorage
pointer with a value of NULL creates an empty stream or storage property value.
If a stream or storage property is already open from a call to ReadMultiple,
a NULL value must cause the WriteMultiple operation to truncate it and
return S_OK, placing the previously returned stream- and storage-valued
pointers into the reverted state (as happens in the compound file
implementation.)
Storage- and
stream-valued properties always manifest themselves to downlevel clients as
sibling streams or storages to the stream containing the main contents of the
property set they are never stored directly
in-line in the property set. This allows smooth interoperability and control
when down-level clients interact with up-level clients. Thus, from a downlevel
perspective, property sets containing IStream or IStorage valued
properties are always stored in a storage object, not a stream. The specific
name of the sibling used is completely under the control of the IPropertyStorage
implementation, as long as the name is from the non-reserved part of the IStorage
name space. See Appendix C of the OLE Programmer s Guide for a discussion of
the serialized property set format for further details. As is described there,
the string name is stored in the same format as a VT_BSTR. Refer also to the
earlier discussion in this method of multibyte to Unicode conversions for
property names.
If the WriteMultiple
method returns an error when writing stream- or storage-valued properties (indirect
properties), the amount of data actually written is undefined. If the caller
requires consistency of the property set and its indirect properties when
writing stream- and/or storage-valued properties, use of transacted mode is
advised.
If an
implicit deletion of a stream- or storage-valued property occurs while that
property is open, (as, for example, when a VT_I4 is written over a VT_STREAM),
the deletion will succeed and place the previously returned IStream pointer in
the reverted state.
See Also