# IPropertyStorage-Compound File Implementation

The OLE implementation of the Structured Storage architecture is called compound files. Storage objects as implemented in compound files include an implementation of both IPropertyStorage, the interface that manages a single persistent property set, and IPropertySetStorage, the interface that manages groups of persistent property sets.

To get a pointer to the compound file implementation of IPropertyStorage, first call StgCreateDocfile to create a new compound file object or StgOpenStorage, to open a previously created compound file. Both functions supply a pointer to the object’s IStorage interface. When you want to deal with persistent property sets, call QueryInterface for the IPropertySetStorage interface, specifying the header-defined name for the interface identifier IID_IPropertySetStorage. Calling either the Create or Open method of that interface, you get a pointer to the IPropertyStorage interface, which you can use to call any of its methods.

##### 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 allows you to set 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. Calling the Enum method supplies a pointer to the compound file implementation of IEnumSTATPROPSTG, which allows you to enumerate the properties in the set.

Remarks

The compound file implementation of IPropertyStorage caches open property sets in memory in order to improve performance. As a result, changes to a property set are not written to the compound file until the Commit or Release (last reference) methods are called.

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 OLE compound file 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 opens. Because in a compound file STGM_SHARE_EXCLUSIVE is forced, multiple opens will fail. Opening the same storage object more than once from the same parent storage is not supported. The STGM_SHARE_EXCLUSIVE flag must be specified.

  In addition, to ensure thread-safe operation if the same stream- or storage-valued property is requested multiple times through the same IPropertyStorage pointer in the OLE compound file implementation, 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, etc.) and share flags (STGM_SHARE_EXCLUSIVE, etc) specified when the original property set was 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 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 this implementation, setting the CLSID on a non-simple property set (one that can legally contain storage- or stream-valued properties, as described in IPropertySetStorage::Create) also sets the CLSID on the underlying sub-storage so that 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 performs a commit (as in 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, returns E_OK.
IPropertyStorage::Enum
  Constructs an instance of 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 times from the underlying storage or stream. For simple storage sets, no times are maintained.
IPropertyStorage::SetTimes
  For non-simple property sets only, sets the times supported by the underlying storage. The compound file storage implementation supports all three: modification, access, and creation. This implementation of SetTimes calls the IStorage::SetElementTimes method of the underlying storage to retrieve these times.

See Also

IPropertyStorage, IStorage::SetElementTimes