IPropertyStorage-Standalone Implementation
The system-provided, standalone implementation of IPropertySetStorage includes an implementation of IPropertyStorage, the interface that reads and writes properties in a property set storage. The IPropertySetStorage interface creates and opens property sets in a storage. The IEnumSTATPROPSTG and IEnumSTATPROPSETSTG interfaces are also provided in the standalone implementation.
To get a pointer to the standalone implementation of IPropertyStorage, call the StgCreatePropStg function if you are creating a new property set or StgOpenPropStg if you want to obtain the interface pointer on an existing property set (or call the Create or Open methods of the IPropertySetStorage standalone implementation).
The standalone implementation of IPropertyStorage creates property sets on any storage or stream object, not just on compound file storages and streams. The standalone implementation does not depend on compound files and can be used with any implementation of structured storages. See the section IPropertyStorage-Compound File Implementation in the Object Services section of the Platform SDK for more information on the compound file implementation of this interface.
When to Use
Use IPropertyStorage to manage properties within a single property set. Its methods support reading, writing, and deleting both properties and the optional string names that can be associated with property identifiers. Other methods support the standard commit and revert storage operations. There is also a method that sets times associated with the property storage, and another that permits the assignment of a CLSID that can be used to associate other code, such as user interface code, with the property set. The Enum method supplies a pointer to the standalone implementation of IEnumSTATPROPSTG, which enumerates the properties in the set.
Remarks
There are some differences between the standalone implementation of the property set interfaces and the compound file implementation. In the compound file implementation of stream, storage, property set storage, and property storage objects, the various interfaces are able to coordinate with one another because they are part of a common implementation. In the standalone implementation, the interface implementations are distinct from one another.
As a result, the compound-file implementation handles concurrency issues and synchronizes the property set object with the storage or stream object. With the standalone implementation, the client is responsible for handling concurrency and synchronization issues between the storage or stream object and the property set. A client can meet these requirements by following two simple rules. First, never manipulate a property set using its stream or storage interfaces while a property storage object is opened on it. And, second, always Commit a property storage object before calling Commit, CopyTo, or MoveElementTo on an ancestor storage object. Specifically, the following items require client attention:
-
In the compound file implementation, a single mechanism provides concurrency protection for the storage object and its associated property set objects. However, in the standalone implementation, the storage object implementation is separate from the property set implementation and each provides its own concurrency mechanisms. Thus, in the standalone implementation, the client is responsible for maintaining concurrency protection between the two implementations through a mutual exclusion mechanism.
-
In the compound file implementation, changes to property sets are buffered in a property set cache. Then, when the IStorage::Commit method is called on the storage object, the compound files implementation automatically flushes the property set changes from the property set buffer before the storage object is committed. Thus, the property set changes are made visible as part of the transaction being committed.
-
In the standalone implementation, the client must explicitly flush the property set buffer by calling IPropertyStorage::Commit before calling the IStorage:Commit method on the storage. Alternately, the client can use the new PROPSETFLAG_UNBUFFERED value in the standalone implementation to write directly to the property set instead of caching changes to the property set's internal buffer. If PROPSETFLAG_UNBUFFERED is used, the client's responsibilities are automatically met. The compound file implementation does not support the PROPSETFLAG_UNBUFFERED value. See the PROPSETFLAG enumeration for more information on using this value.
-
As with transacted storages, the compound file implementation updates the property set by flushing its internal buffer prior to executing a call to IStorage::CopyTo or IStorage::MoveElementTo. Thus, changes to the property set are reflected in the copied or moved storage element.
-
In the standalone implementation, the client must explicitly flush the property set buffer by calling IPropertyStorage::Commit before calling IStorage::CopyTo or IStorage::MoveElementTo. Alternately, the client can use the new PROPSETFLAG_UNBUFFERED to write directly to the property set instead of caching changes to the property set buffer. See the PROPSETFLAG enumeration for more information on using this value.
The standalone implementation of IPropertyStorage supports the following methods:
-
IPropertyStorage::ReadMultiple
-
Reads the properties specified in the rgpspec array and supplies the values of all valid properties in the rgvar array of PROPVARIANTs.
In the system-provided, standalone implementation, duplicate property identifiers that refer to stream- or storage-types result in multiple calls to IStorage::OpenStream or IStorage::OpenStorage and the success or failure of ReadMultiple depends on the underlying storage implementation's ability to share open storages.
In addition, to ensure thread-safe operation if the same stream- or storage-valued property is requested multiple times through the same IPropertyStorage pointer, the open will succeed or fail depending on whether or not the property is already open and on whether the underlying file system handles multiple opens of a stream or storage. Thus, the ReadMultiple operation on a stream- or storage-valued property always results in a call to IStorage::OpenStream, or IStorage::OpenStorage, passing the access (STGM_READWRITE, for example) and share values (STGM_SHARE_EXCLUSIVE, for example) specified when the property set was originally opened or created.
If the method fails, the values written to rgvar[] are undefined. If some stream- or storage-valued properties are opened successfully but an error occurs before execution is complete, these properties should be released before the method returns.
-
IPropertyStorage::WriteMultiple
-
Writes the properties specified in the rgpspec[] array, assigning them the PROPVARIANT tags and values specified in rgvar[]. Properties that already exist are assigned the specified PROPVARIANT values, and properties that do not currently exist are created.
-
IPropertyStorage::DeleteMultiple
-
Deletes the properties specified in the rgpspec[].
-
IPropertyStorage::ReadPropertyNames
-
Reads existing string names associated with the property identifiers specified in the rgpropid[] array.
-
IPropertyStorage::WritePropertyNames
-
Assigns string names specified in the rglpwstrName array to property identifiers specified in the rgpropid array.
-
IPropertyStorage::DeletePropertyNames
-
Deletes the string names of the property identifiers specified in the rgpropid array by writing NULL to the property name.
-
IPropertyStorage::SetClass
-
Sets the CLSID field of the property set stream. In the standalone implementation, setting the CLSID on a non-simple property set (one that can contain storage- or stream-valued properties, as described in IPropertySetStorage::Create) also sets the CLSID on the underlying sub-storage so it can be obtained through a call to IStorage::Stat.
-
IPropertyStorage::Commit
-
For both simple and non-simple property sets, flushes the memory image to the disk subsystem. In addition, for non-simple transacted-mode property sets, this method calls IStorage::Commit on the property set.
-
IPropertyStorage::Revert
-
For non-simple property sets only, calls the underlying storage's Revert method and re-opens the 'contents' stream. For simple property sets, only returns E_OK.
-
IPropertyStorage::Enum
-
Creates an enumerator object that implements IEnumSTATPROPSTG, the methods of which can be called to enumerate the STATPROPSTG structures that provide information about each of the properties in the set.
This implementation creates an array into which the entire property set is read and which can be shared when IEnumSTATPROPSTG::Clone is called.
-
IPropertyStorage::Stat
-
Fills in the fields of a STATPROPSETSTG structure, which contains information about the property set as a whole. On return, supplies a pointer to the structure.
For non-simple storage sets, this implementation calls IStorage::Stat (or IStream::Stat) to get the information from the underlying storage or stream.
-
IPropertyStorage::SetTimes
-
For non-simple property sets only, sets the times supported by the underlying storage. This implementation of SetTimes calls the IStorage::SetElementTimes method of the underlying storage to modify the times. It supports the times supported by the underlying method which can be modification time, access time, or creation time.
Programming Information
| Windows NT |
4.0/SP2 or with IPROP.DLL |
| Win95 |
Yes; requires IPROP.DLL |
| Win32s |
No |
| Unicode |
Yes |
| Import Library |
IPROP.DLL |
| Header File |
IPROPIDL.H |
See Also
IPropertySetStorage-Standalone Implementation, IPropertyStorage, IStorage::SetElementTimes, StgOpenPropStg, StgCreatePropStg, StgCreatePropSetStg