15    Persistent Storage

Structured storage provides the equivalent of a complete file system for storing objects through the following elements:

15.1    Interfaces

Structured storage services are organized into three categories of interfaces. Each set represents a successive level of indirection, or abstraction, between a compound file, the objects it contains, and the physical media on which these individual components are stored.

The first category of interfaces consists of IStorage(), IStream(), and IRootStorage(). The first two interfaces define how objects are stored within a compound file. These interfaces provide methods for opening storage elements, committing and reverting changes, copying and moving elements, and reading and writing streams. These interfaces do not understand the native data formats of the individual objects and therefore have no methods for saving those objects to persistent storage. The IRootStorage() interface has a single method for associating a compound document with an underlying file system name. Clients are responsible for implementing these interfaces on behalf of their compound files.

The second category of interfaces consists of the IPersist() interfaces, which objects implement to manage their persistent data. These interfaces provide methods to read the data formats of individual objects and therefore know how to store them. Objects are responsible for implementing these interfaces because clients do not know the native data formats of their nested objects. These interfaces, however, have no knowledge of specific physical storage media.

A third category consists of a single interface, ILockBytes(), which provides methods for writing files to specific physical media, such as a hard disk or tape drive. COM provides an ILockBytes() interface for the operating system's file system.

15.2    API Functions

Some of the API functions for structured storage are helper functions that perform a sequence of calls to other API functions and interface methods. You can use these helper functions as short cuts.

Other API functions provide access to COM's implementation of structured storage, Compound Files.

Finally, there are API functions for converting and emulating other objects. These functions provide services for one server application to work with data from another application. The data can be converted to the native format of the server application by reading the data from its original format but writing it in the native format of the object application. Or the data can remain in its original format while the server application both reads and writes the data in its original format.

15.3    Access Modes

In a world where multiple processes and users can access an object simultaneously, mechanisms for controlling that access are essential. COM provides these mechanisms by defining access modes for both storage and stream objects. The access mode specified for a parent storage object is inherited by its children, though you can place additional restrictions on the child storage or stream. A nested storage or stream object can be opened in the same mode or in a more restricted mode than that of its parent, but it cannot be opened in a less restricted mode than that of its parent.

You specify access modes by using the values listed in the STGM enumeration. These values serve as flags to be passed as arguments to methods in the IStorage() interface and associated API functions. Typically, several flags are combined in the parameter grfMode, using a Boolean OR operation.

The flags fall into six groups: transaction flags, storage creation flags, temporary creation flag, priority flag, access permission flags, and shared access flags. Only one flag from each group can be specified at a time.

15.3.1    Transaction Flags

An object can be opened in either direct or transacted mode. When an object is opened in direct mode, changes are made immediately and permanently. When an object is opened in transacted mode, changes are buffered so they can be explicitly committed or reverted once editing is complete. Committed changes are saved to the object while reverted changes are discarded. Direct mode is the default access mode.

Transacted mode is not required on a parent storage object in order to use it on a nested element. A transaction for a nested element, however, is nested within the transaction for its parent storage object. Therefore, changes made to a child object cannot be committed until those made to the parent are committed, and both are not committed until the root storage object (the top-level parent) is actually written to disk. In other words, the changes move outward: inner objects publish changes to the transactions of their immediate containers.

15.3.2    Storage Creation Flags

Storage creation flags specify what COM should do if an existing storage, stream, or lockbytes object has the same name as a new storage or stream object that you are creating. The default is to return an error message and not create the new object. You can use only one of these flags in a given creation call.

15.3.3    Temporary Creation Flag

The temporary creation flag indicates that the underlying file is to be automatically destroyed when the root storage object is released. This capability is most useful for creating temporary files.

15.3.4    Priority Flag

The priority flag opens a storage object in priority mode. When it opens an object, an application usually works from a snapshot copy because other applications may also be using the object at the same time. When opening a storage object in priority mode, however, the application has exclusive rights to commit changes to the object.

Priority mode enables an application to read some streams from storage before opening the object in a mode that would require the system to make a snapshot copy to be made. Since the application has exclusive access, it doesn't have to make a snapshot copy of the object. When the application subsequently opens the object in a mode where a snapshot copy is required, the application can exclude from the snapshot the streams it has already read, thereby reducing the overhead of opening the object.

Since other applications cannot commit changes to an object while it is open in priority mode, applications should keep it in that mode for as short a time as possible.

15.3.5    Access Permission Flags

Access permission flags specify the type of access a client application has to an open object: read, write, or read/write. Read permission enables an application to read the contents of a stream but not to write changes to the stream. Write permission enables an application to call a function that commits changes to an object's storage but not to read the contents of the stream. Read/write permission enables an application to either read the object's streams or write to the object's storage.

15.3.6    Shared Access Flags

The shared access flags specify the degree of access other applications can have to an object that your application is opening. You can deny read access, deny write access, or deny all access. You can also specify explicitly that no type of access be denied.

15.4    Storage Object Naming Conventions

Storage and stream objects are named according to a set of conventions.

The name of a root storage object is the actual name of the file in the underlying file system. It obeys the conventions and restrictions the file system imposes. Filename strings passed to storage-related methods and functions are passed on, uninterpreted and unchanged, to the file system.

The name of a nested element contained within a storage object is managed by the implementation of the particular storage object. All implementations of storage objects must support nested element names 32 characters in length (including the NULL terminator), although some implementations might support longer names. Whether the storage object does any case conversion is implementation-defined. As a result, applications that define element names must choose names that are acceptable in either situation. The COM implementation of compound files supports names up to 32 characters in length, and does not perform any case conversion.

15.5    Persistent Property Sets

While the kind of run-time properties that Automation and ActiveX Controls offer are important, they do not directly address the need to store information with objects persistently stored in the file system. These entities could include files (structured, compound, etc.), directories, and summary catalogs. COM provides both a standard serialized format for these persistent properties, and a set of interfaces and functions that allow you to create and manipulate the property sets and their properties.

Persistent properties are stored as sets, and one or more sets may be associated with a file system entity. These persistent property sets are intended to be used to store data that is suited to being represented as a collection of fine-grained values. They are not intended to be used as a large data base. They can be used to store summary information about an object on the system, which can then be accessed by any other object that understands how to interpret that property set.

Previous versions of COM specified very little with respect to properties and their usage, but did define a serialized format that allowed developers to store properties and property sets in an IStorage() instance. The property identifiers and semantics of a single property set, used for summary information about a document, was also defined. At that time, it was necessary to create and manipulate that structure directly as a data stream.

Now, however, COM defines two primary interfaces to manage property sets:

It is no longer necessary to deal with the serialized format directly when these interfaces are implemented on an object that supports the IStorage() interface (such as compound files). Writing properties through IPropertySetStorage() and IPropertyStorage() creates data that exactly conforms to the COM property set format, as viewed through IStorage() methods. The converse is also true--properties written to the COM property set format using IStorage() are visible through IPropertySetStorage() and IPropertyStorage() (although you cannot expect to write to IStream() and have the properties through IPropertyStorage() immediately available, or vice versa).

The IPropertySetStorage() interface defines methods that create and manage property sets. The IPropertyStorage() interface directly manipulates the properties within a property set. By calling the methods of these interfaces, an application developer can manage whatever property sets are appropriate for a given file system entity. Use of these interfaces provides one tuned reading and writing implementation for properties, rather than having an implementation in each application, which could suffer performance bottlenecks such as incessant seeking. You can implement the interfaces to enhance performance, so properties can be read and written more quickly by, for example, more efficient caching. Furthermore, IPropertyStorage() and IPropertySetStorage() make it possible to manipulate properties on entities that do not support IStorage(), although in general, most applications will not do so.

15.5.1    Managing Property Sets

A persistent property set contains related pieces of information in the form of properties. Each property set is identified with a FMTID, a GUID that allows programs accessing the property set to identify the property set and, through this identification, know how to interpret the properties it contains. Examples of property sets might be the character-formatting properties in a word processor or the rendering attributes of an element in a drawing program.

COM defines the IPropertySetStorage() interface to facilitate management of property sets. Through the methods of this interface, you can create a new property set, or open or delete an existing property set. In addition, it provides a method that creates an enumerator and supplies a pointer to its IEnumSTATPROPSETSTG() interface. You can call the methods of this interface to enumerate STATPROPSETSTG structures on your object, which will provide information about all of the property sets on the object.

When you create or open an instance of IPropertyStorage(), it is similar to opening an object that supports IStorage() or IStream(), because you need to specify the storage mode in which you are opening the interface. For IStorage(), these include the transaction mode, the read/write mode, and the sharing mode.

When you create a property set with a call to IPropertySetStorage::Create(), you specify whether the property set is to be simple or non-simple. A simple property set contains types that can be fully written within the property set stream, which is intended to be limited, and can, in fact, not be larger than 256 Kbytes. However, for those cases when you need to store a larger amount of information in the property set, you can specify that the property set be non-simple, allowing you to use one or more of the types that specify only a pointer to a storage or stream object. Also, if you need a transacted update, the property set must be non-simple. There is, of course, a certain performance penalty for opening these types, because it requires opening the stream or storage object to which you have the pointer.

If your application uses compound files, you can use the COM-provided implementation of these interfaces, which are implemented on the COM compound file storage object.

Each property set consists primarily of a logically connected group of properties, as described in the following section.

15.5.2    Managing Properties

Every property consists of a property identifier (unique within its property set), a type tag that represents the type of a value, and the value itself. The type tag describes the representation of the data in the value. In addition, a property may also be assigned a string name that can be used to identify the property, rather than using the required numerical property identifier. To create and manage properties, COM defines the IPropertyStorage() interface.

The IPropertyStorage() interface includes methods to read and write arrays of either properties themselves or just property names. The interface includes Commit and Revert methods that are similar to IStorage() methods of the same name. There are utility methods that allow you to set the CLSID of the property set, the times associated with the set, and get statistics about the property set. Finally, the Enum method creates an enumerator and returns a pointer to its IEnumSTATPROPSTG() interface. You can call the methods of this interface to enumerate STATPROPSTG structures on your object, which will provide information about all of the properties in the current property set.

To illustrate how properties are represented, if a specific property in a property set holds an animal's scientific name, that name could be stored as a zero-terminated string. Stored along with the name would be a type indicator to indicate that the value is a zero-terminated string. These properties might have the following characteristics:

Property ID String Identifier Type Indicator Value Represented
02 PID_ANIMALNAME VT_LPWSTR Zero-terminated Unicode string
03 PID_LEGCOUNT VT_I2 WORD

Any application that recognizes the property set format (identifying it through its FMTID) can look at the property with an identifier of PID_ANIMALNAME, determine it is a zero-terminated string, and read and write the value. While the application can call IPropertyStorage::ReadMultiple() to read any or all of a property set (having first obtained a pointer), the application must know how to interpret the property set.

A property value is passed through property interfaces as an instance of the type PROPVARIANT.

It is important to distinguish between these stored (persistent) properties, and run-time properties. Value type constants have names beginning with VT_. The set of valid PROPVARIANTs is, however, not completely equivalent with the set of VARIANTs used in Automation and ActiveX Controls.

The only difference between the two structures is the allowable set of VT_ tags in each. Where a certain property type can be used in both a VARIANT and a PROPVARIANT, the type tag (the VT_ value) always has an identical value. Further, for a given VT_ value, the in-memory representation used in both VARIANTs and PROPVARIANTs is identical. Taken all together, this approach allows the type system to catch disallowed type tags, while at the same time, allowing a knowledgeable client simply to do a pointer-cast when appropriate.

15.5.3    Using Property Sets

While the potential for uses of persistent property sets is not fully tapped, there are currently two primary uses:

COM property sets were designed to store data that is suited to representation as a moderately sized collection of fine-grained values. Data sets that are too large for this to be feasible should be broken into separate streams, storages, and/or property sets. The COM property set data format was not meant to provide a substitute for a database of many tiny objects.

This section discusses two ways to use property sets. The first describes an example of storing property sets within files to allow common access to the information in the property set, and describes the ``COM summary information'' property set standard. The second is an example that shows how to transfer property sets between applications or COM objects as an effective means of communication.

The following section describes the Summary Information property set as an example of property set definition.

15.5.3.1    The Summary Information Property Set

COM defines a standard common property set for storing summary information about documents. The Summary Information property set must be stored in an IStream() instance off of the root storage object; it is not valid to store the property set in the ``Contents'' stream of a named IStorage() instance.

For example, to create an ANSI simple property set, you would call IPropertySetStorage::Create() to create the property set, specifying PROPSETFLAG_ANSI (simple is the default mode), then write to it with a call to IPropertyStorage::WriteMultiple(). To read the property set, you would call IPropertyStorage::ReadMultiple().

All shared property sets are identified by a stream or storage name with the prefix ``\005'' (or 0x05) to show it is a property set shareable among applications, and the Summary Information property set is no exception. The name of the stream that contains the Summary Information property set is:

``\005SummaryInformation''

The FMTID for the Summary Information property set is:

  F29F85E0-4FF9-1068-AB91-08002B27B3D9

Use the DEFINE_GUID macro to define the FMTID for the property set:

DEFINE_GUID(FormatID_SummaryInformation, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, \
0x00, 0x2B, 0x27, 0xB3, 0xD9);

On an Intel byte-ordered machine, the FMTID has the following representation:

  E0 85 9F F2 F9 4F 68 10 AB 91 08 00 2B 27 B3 D9

The following table shows the string property names for the Summary Information property set, along with the respective property identifiers and VT type indicators.

Table 15-1:  String Property Names

Property Name Property ID String Property ID VT Type
Title PID_TITLE 0x00000002 VT_LPSTR
Subject PID_SUBJECT 0x00000003 VT_LPSTR
Author PID_AUTHOR 0x00000004 VT_LPSTR
Keywords PID_KEYWORDS 0x00000005 VT_LPSTR
Comments PID_COMMENTS 0x00000006 VT_LPSTR
Template PID_TEMPLATE 0x00000007 VT_LPSTR
Last Saved By PID_LASTAUTHOR 0x00000008 VT_LPSTR
Revision Number PID_REVNUMBER 0x00000009 VT_LPSTR
Total Editing Time PID_EDITTIME 0x0000000A VT_FILETIME (UTC)
Last Printed PID_LASTPRINTED 0x0000000B VT_FILETIME (UTC)
Create Time/Date (See note below) PID_CREATE_DTM 0x0000000C VT_FILETIME (UTC)
Last saved Time/Date (See note below) PID_LASTSAVE_DTM 0x0000000D VT_FILETIME (UTC)
Number of Pages PID_PAGECOUNT 0x0000000E VT_I4
Number of Words PID_WORDCOUNT 0x0000000F VT_I4
Number of Characters PID_CHARCOUNT 0x00000010 VT_I4
Thumbnail PID_THUMBNAIL 0x00000011 VT_CF
Name of Creating Application PID_APPNAME 0x00000012 VT_LPSTR
Security PID_SECURITY 0x00000013 VT_I4

Some methods of file transfer (such as a download from a BBS) do not maintain the file system's version of this information correctly.

15.5.3.1.1    Guidelines for Implementing the Summary Information Property Set

The following guidelines pertain to implementing the Summary Information property set described in the preceding section:

Table 15-2:  Security Levels

Security Level Value
None 0
Password protected 1
Read-only recommended 2
Read-only enforced 4
Locked for annotations 8

15.5.4    Property Set Implementations

COM provides a compound file implementation of the property set interfaces, along with three helper functions. These implementations are available through COM compound file storage objects, to which you can get a pointer through the functions StgCreateDocfile(), to create a new compound file storage object, and StgOpenStorage(), to open one that currently exists. The following section describes some performance characteristics of these implementations. For more information on specific interfaces and how to get a pointer to these interfaces, refer to the following in the reference section:

In addition, there are three helper functions, designed to aid in dealing with propvariants:

15.5.4.1    Performance Characteristics

A call to the COM compound file implementation of IPropertySetStorage() interface to create a property set causes either a stream or storage to be created through a call to IStorage::CreateStream() or IStorage::CreateStorage(). A default property set is created in memory, but not flushed to disk. When there is a call to IPropertyStorage::WriteMultiple(), it operates within the buffer.

When a property set is opened, IStorage::OpenStream() or IStorage::OpenStorage() is used. The entire property set stream is read into contiguous memory. IPropertyStorage::ReadMultiple() operations then operate by reading the memory buffer. Therefore, the first access is expensive in terms of time (because of disk reads) but subsequent accesses are very efficient. Writes may be slightly more expensive because SetSize operations on the underlying stream may be required to guarantee that disk space is available if data is added.

No guarantees are made as to whether IPropertyStorage::WriteMultiple() will flush updates. In general, the client should assume that IPropertyStorage::WriteMultiple only updates the in memory buffer. To flush data, IPropertyStorage::Commit() or IPropertyStorage::Release() (last release) should be called.

This design means that WriteMultiple may succeed but the data is not actually persistently written.

The size of the property set stream must not exceed 256K bytes.

15.5.5    Using Implemented Property Sets

Since the property set stream is read into memory in its entirety before a single property can be read or written, it is strongly recommended that property sets be kept small. ``Small'' is somewhere under 32K of data. This should not present too much of a problem because typically, ``in-line'' properties will be small items such as descriptive strings, keywords, timestamps, counts, author names, GUIDs, CLSIDs, etc.

For the storage of larger chunks of data, or where the total size of a set of related properties far exceeds the recommended amount, the use of non-simple types such as VT_STREAM and VT_STORAGE are strongly recommended. These are not stored inside the property set stream, so do not significantly affect the initial overhead of the first accessing/writing of a property. There is some effect because the property set stream contains the name of the sibling stream- or storage-valued property and this takes a small amount of time to process.

15.5.6    IPropertySetStorage Implementation Considerations

Several issues arise when considering how to provide an implementation of the IPropertySetStorage() interface that reads and writes the COM property set format. The following sections describe these considerations.

15.5.7    Names in IStorage

This is the most complex interoperability issue. In the IPropertySetStorage() interface, property sets are identified with FMTIDs, but in IStorage(), they are named with strings with a maximum length of 32 characters.

To accomplish this mapping, the first task is to establish a mapping between FMTIDs and strings. Converting in the one direction, you have a FMTID, and need a corresponding string name. First, check whether the FMTID is one of a fixed set of well-known values, and use the corresponding well-known string name if so:

Table 15-3:  FMTID String Names

FMTID String Name Semantic
F29F85E0-4FF9- 1068-AB91-08002B27B3D9 "\005SummaryInformation" COM summary information
D5CDD502-2E9C- 101B-9397-08002B2CF9AE "\005DocumentSummaryInformation" Office document summary information and user-defined properties.
D5CDD505-2E9C- 101B-9397-08002B2CF9AE "\005DocumentSummaryInformation" Office document summary information and user-defined properties.

The DocumentSummaryInformation property set is special in that it contains two sections. Multiple sections are not permitted in any other property set.

The first was defined as part of OLE; the second one was defined by Microsoft Office.

Otherwise, algorithmically form a string name in the following way. First, convert the FMTID to little-endian byte order if necessary. Then, take the 128 bits of the FMTID and consider them as one long bit string by concatenating each of the bytes together. The first bit of the 128 bit value is the least significant bit of the first byte in memory of the FMTID; the last bit of the 128 bit value is the most significant bit of the last byte in memory of the FMTID. Extend these 128 bits to 130 bits by adding two zero bits to the end. Next, chop the 130 bits into groups of five bits; there will be 26 such groups. Consider each group as an integer with reversed bit precedence. For example, the first of the 128 bits is the least significant bit of the first group of five bits; the fifth of the 128 bits is the most significant bit of the first group. Map each of these integers as an index into the array of thirty-two characters:

ABCDEFGHIJKLMNOPQRSTUVWXYZ012345

This yields a sequence of 26 Unicode characters that uses only uppercase characters and numerals. Note that no two characters in this range compare equally in a case-insensitive manner in any locale. The final string is the concatenation of the string ``\005'' onto the front of these 26 characters, for a total length of 27 characters.

The following code illustrates one way to map from FMTID to property string:

#define CBIT_BYTE        8
#define CBIT_CHARMASK    5
#define CCH_MAP          (1 << CBIT_CHARMASK)    // 32
#define CHARMASK         (CCH_MAP - 1)           // 0x1f
CHAR awcMap[CCH_MAP + 1] = ``abcdefghijklmnopqrstuvwxyz012345'';
WCHAR MapChar(ULONG i) {
    return((WCHAR) awcMap[i & CHARMASK]);
    }
VOID GuidToPropertyStringName(GUID *pguid, WCHAR awcname[]) {
    BYTE *pb = (BYTE *) pguid;
    BYTE *pbEnd = pb + sizeof(*pguid);
    ULONG cbitRemain = CBIT_BYTE;
    WCHAR *pwc = awcname;
    *pwc++ = ((WCHAR) 0x0005);
    while (pb < pbEnd) {
        ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
        if (cbitRemain >= CBIT_CHARMASK) {
            *pwc = MapChar(i);
            if (cbitRemain == CBIT_BYTE && *pwc >= L'a' && *pwc <= L'z') {
                *pwc += (WCHAR) (L'A' - L'a');
                }
            pwc++;
            cbitRemain -= CBIT_CHARMASK;
            if (cbitRemain == 0) {
                pb++;
                cbitRemain = CBIT_BYTE;
                }
            }
        else {
            if (++pb < pbEnd) {
                i |= *pb << cbitRemain;
                }
            *pwc++ = MapChar(i);
            cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
            }
        }
    *pwc = L'\0';
    }

Converters of property string names to GUIDs should accept lowercase letters as synonymous with their upper case counterparts. The following example shows one way to map from the property string to a FMTID:

ULONG
PropertySetNameToGuid(
    IN ULONG cwcname,
    IN WCHAR const awcname[],
    OUT GUID *pguid)
{
    ULONG Status = ERROR_INVALID_PARAMETER;
    WCHAR const *pwc = awcname;
    if (pwc[0] == WC_PROPSET0)
    {
        //Note: cwcname includes the WC_PROPSET0, and
        //sizeof(wsz...) includes the trailing L'\0', but
        //the comparison excludes both the leading
        //WC_PROPSET0 and the trailing L'\0'.
        if (cwcname == sizeof(wszSummary)/sizeof(WCHAR) &&
            wcsnicmp(&pwc[1], wszSummary, cwcname - 1) == 0)
        {
            *pguid = guidSummary;
            return(NO_ERROR);
        }
        if (cwcname == CWC_PROPSET)
        {
            ULONG cbit;
            BYTE *pb = (BYTE *) pguid - 1;
            ZeroMemory(pguid, sizeof(*pguid));
            for (cbit = 0; cbit < CBIT_GUID; cbit += 
            CBIT_CHARMASK)
            {
                ULONG cbitUsed = cibt % CBIT_BYTE;
                ULONG cbitStored;
                WCHAR wc;
                if (cbitUsed == 0)
                {
                    pb++;
                }
                wc = *++pwc - L'A';        //assume uppercase
                if (wc > CALPHACHARS)
                {
                    wc += (WCHAR) (L'A' - L'a')' //try lowercase
                    if (wc > CALPHACHARS)
                    {
                        wc += L'a' - L'0' + CALPHACHARS; //must 
                                                      be a digit
                        if (wc > CHARMASK)
                        {
                            goto fail;       //invalid character
                        }
                    }
                }
                *pb |= (BYTE) (wc << cbitUsed);
                cbitStored = min(CBIT_BYTE - cbitUsed, 
                CBIT_CHARMASK);
                //If the translated bits wouldn't fit in the 
                  current byte
                if (cbitStored < CBIT_CHARMASK)
                {
                    wc >>= CBIT_BYTE - cbitUsed;
                    if (cbit + cbitStored == CBIT_GUID)
                    {
                       if (wc !+0)
                       {
                           goto fail;        //extra bits
                       }
                       break;
                    }
                    pb++;
                    *pb |= (BYTE) wc;
                }
           }
           Status = NO_ERROR
      }
    }
fail:
    return(Status);
}

When attempting to open an existing property set (in IPropertySetStorage::Open()) the (root) FMTID in hand is converted to a string as depicted above. If an element of the IStorage() of that name exists, it is used. Otherwise, the open fails.

When creating a new property set, the above mapping determines the string name used.

15.5.8    Storage vs Stream for a Property Set

To provide applications the control they need to fully interoperate through the IPropertySetStorage() interface with the COM property set, the programmer must control whether a property set is stored in a storage or a stream. This is provided through the presence or absence of the PROPSETFLAG_NONSIMPLE flag in IPropertySetStorage::Create().

15.5.9    Setting the CLSID of the Property Set

IPropertyStorage::SetClass(), when invoked on a property stored in a compound file, will set the CLSID of the storage object through a call to IStorage::SetClass in addition to setting the class tag value stored in the COM property set. This provides a consistency and uniformity that creates better interaction with some tools.

15.5.10    Synchronization Points

When property sets are supported on the same object as is IStorage(), it is important to be aware of synchronization points between the base storage and the property storage. The property set storage holds the property set stream in an internal buffer until that buffer is commited through the IPropertyStorage::Commit() method. This is true whether IPropertyStorage() was opened in transacted mode or direct mode.

15.5.11    Code pages: Unicode strings, Macintosh, etc.

Another consideration is how Unicode property names are stored in the property ID 0 (the property name dictionary), which is not specified per se to use Unicode strings.

This is straightforward. Unicode officially has a code page value of 1200. To store Unicode values in the property name dictionary, use a code page value of 1200 for the whole property set (in property ID 1, of course), specified by the absence of the PROPSETFLAG_ANSI flag in IPropertySetStorage::Create(). Note that this has the side effect of storing all string values in the property set in Unicode. In all code pages, the count found at the start of a VT_LPSTR s a byte count, not a character count. This is necessary to provide for smooth interoperability with down-level clients.

The compound file implementation of IPropertySetStorage() creates all new property sets completely either in Unicode (code page 1200) or in the current system ANSI code page. This is controlled by the absence or presence of the PROPSETFLAG_ANSI flag in the grfFlags parameter of IPropertySetStorage::Create().

It is recommended that property sets be created or opened 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. If 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.

The setting of the PROPSETFLAG_ANSI flag as reported through a call to IPropertyStorage::Stat() simply reflects whether the underlying code page is not Unicode or is Unicode. Note, though, property ID 1 can be explicitly read to learn the code page.

Property ID 1 is accessible through IPropertyStorage::ReadMultiple(). However, it is read-only, and may not be updated with WriteMultiple. Further, it may not be deleted with DeleteMultiple.

15.5.12    Dictionary

IPropertyStorage::WritePropertyNames() is implemented using the property ID 0 dictionary as described above. Property ID 0 is not accessible through IPropertyStorage::ReadMultiple() or ::WriteMultiple.

15.5.13    Extensions

Property set extensions as defined in the original COM property set format have been removed and are not supported, except for the User Defined Properties section in the Document Summary Information property set.

15.6    Persistent Storage Interface Descriptions

15.6.1    IEnumSTATPROPSETSTG

The IEnumSTATPROPSETSTG() interface is used to iterate through an array of STATPROPSETSTG structures, which contain statistical information about the property sets managed by the current instance of IPropertySetStorage(). IEnumSTATPROPSETSTG() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

The implementation defines the order in which the property sets are enumerated. Property sets that are present when the enumerator is created, and are not removed during the enumeration, will be enumerated only once. Property sets added or deleted while the enumeration is in progress may or may not be enumerated, but, if enumerated, will not be enumerated more than once.

For information on how the COM compound document implementation of IEnumSTATPROPSETSTG:Next supplies members of the STATPROPSETSTG structure, refer to Section Section 15.6.2.

When to Implement

IEnumSTATPROPSETSTG() is implemented to enumerate the property sets supported by the current property set storage object. If you are using the compound file implementation of the storage object, a pointer to which is available through a call to StgCreateDocfile(), IEnumSTATPROPSETSTG() is implemented on that object, and a pointer is returned through a call to IPropertySetStorage::Enum(). If you are doing a custom implementation of IPropertySetStorage(), you need to implement IEnumSTATPROPSETSTG() to fill in a caller-allocated array of STATPROPSETSTG structures, each of which contains information about the nested elements in the storage object.

When to Use

Call IPropertySetStorage::Enum() to return a pointer to IEnumSTATPROPSETSTG(), the methods of which can then be called to enumerate STATPROSETSTG structures so the application can manage its property sets.

The prototypes of the methods are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        STATPROPSETSTG * rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumSTATPROPSETSTG ** ppenum );

See Also

IPropertyStorage::Enum()

15.6.2    IEnumSTATPROPSETSTG-Compound File Implementation

The compound file implementation of IEnumSTATPROPSETSTG() interface is used to enumerate through an array of STATPROPSETSTG structures, which contain statistical information about the properties managed by the compound file implementation of IPropertySetStorage(), which is associated with a current compound file storage object.

When to Use

Call the methods of IEnumSTATPROPSETSTG() to enumerate STATPROPSETSTG structures, each of which provides information about one of the property sets associated with the compound file storage object.

Description

IEnumSTATPROPSETSTG::Next()

Gets the next one or more STATPROPSETSTG structures (the number is specified by the celt parameter). The STATPROPSETSTG elements provided through a call to the compound file implementation of IEnumSTATPROPSETSTG::Next() follow these rules:

Notes

If you always create a property set using IPropertySetStorage::Create(), then, since a ``Character GUID'' is created for the storage name, IEnumSTATPROPSETSTG::Next() will return a nonzero, valid format identifier for the property set [STATPROPSETSTG.fmtid].

IEnumSTATPROPSETSTG::Skip()

Skips the number of elements specified in celt. Returns S_OK if the specified number of elements are skipped, returns S_FALSE if fewer elements than requested are skipped. In any other case, returns the appropriate error.

IEnumSTATPROPSETSTG::Reset()

Sets the cursor to the beginning of the enumeration. If successful, returns S_OK, otherwise, returns STG_E_INVALIDHANDLE.

IEnumSTATPROPSETSTG::Clone()

Copies the current enumeration state of this enumerator.

15.6.3    IEnumSTATPROPSTG

The IEnumSTATPROPSTG() interface is used to iterate through an array of STATPROPSTG structures, which contain statistical information about an open property storage containing a property set. IEnumSTATPROPSTG() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

The implementation defines the order in which the properties in the set are enumerated. Properties that are present when the enumerator is created, and are not removed during the enumeration, will be enumerated only once. Properties added or deleted while the enumeration is in progress may or may not be enumerated, but they will never be enumerated more than once.

Properties with property ID 0 (dictionary), property ID 1 (codepage indicator), or property ID greater than or equal to 0x80000000 are not enumerated.

Enumeration of a non-simple property does not necessarily indicate that the property can be read successfully through a call to IPropertyStorage::ReadMultiple(). This is because the performance overhead of checking existence of the indirect stream or storage is prohibitive during property enumeration. A client of this interface should code accordingly.

When to Implement

Implement IEnumSTATPROPSTG() to enumerate the properties within a property set. If you are using the compound file implementation of the storage object, a pointer to which is available through a call to StgCreateDocfile(), you can then query for a pointer to IPropertySetStorage(). After calling one of its methods either to open or create a property set, you can get a pointer to IEnumSTATPROPSTG() through a call to IPropertyStorage::Enum(). If you are doing a custom implementation of IPropertyStorage(), you also need to implement IEnumSTATPROPSTG() to fill in a caller-allocated array of STATPROPSTG structures. Each STATPROPSTG structure contains information about a simple property.

When to Use

Applications that support storage objects and persistent properties within those objects call IPropertyStorage::Enum() to return a pointer to IEnumSTATPROPSTG() to enumerate the properties in the current property set.

The prototypes of the methods are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        STATPROPSTG * rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumSTATPROPSTG ** ppenum );

See Also

IPropertyStorage::Enum()

15.6.4    IEnumSTATPROPSTG-Compound File Implementation

The compound file implementation of the IEnumSTATPROPSTG() interface is used to enumerate through properties, resulting in STATPROPSTG structures, which contain statistical information about the properties managed by the compound file implementation of IPropertyStorage(), which is associated with a current compound file storage object.

The constructor in the COM implementation of IEnumSTATPROPSTG() creates a class that reads the entire property set, and creates a static array which can be shared when IEnumSTATPROPSTG::Clone() is called.

When to Use

Call the compound file implementation of IEnumSTATPROPSTG() to enumerate the STATPROPSTG structures that contain information about the properties within the current property set. When you are using the compound file implementation of the property storage interfaces, call IPropertyStorage::Enum() to return a pointer to IEnumSTATPROPSTG() to manage the property storage object and the elements within it.

Description

IEnumSTATPROPSTG::Next()

Gets the next one or more STATPROPSTG structures (the number is specified by the celt parameter). Returns S_OK if successful.

IEnumSTATPROPSTG::Skip()

Skips the number of elements specified in celt. The next element to be enumerated through a call to Next then becomes the element after the ones skipped. Returns S_OK if celt elements were skipped; returns S_FALSE if fewer than celt elements were skipped.

IEnumSTATPROPSTG::Reset()

Sets the cursor to the beginning of the enumeration. If successful, returns S_OK, otherwise, returns STG_E_INVALIDHANDLE.

IEnumSTATPROPSTG::Clone()

Uses the constructor for the IEnumSTATPROPSTG() to create a copy of the array. Because the class that constructs the static array actually contains the object, this function mainly adds to the reference count.

See Also

STATPROPSTG, IPropertyStorage::Enum()

15.6.5    IEnumSTATSTG

The IEnumSTATSTG() interface is used to enumerate through an array of STATSTG structures, which contain statistical information about an open storage, stream, or byte array object. IEnumSTATSTG() has the same methods as all enumerator interfaces: Next, Skip, Reset, and Clone. For general information on these methods, refer to IEnumXXXX().

When to Implement

IEnumSTATSTG() is implemented to enumerate the elements of a storage object. If you are using the compound file implementation of the storage object, a pointer to which is available through a call to StgCreateDocfile(), IEnumSTATSTG() is implemented on that object, and a pointer is returned through a call to IStorage::EnumElements(). If you are doing a custom implementation of a storage object, you need to implement IEnumSTATSTG() to fill in a caller-allocated array of STATSTG structures, each of which contains information about the nested elements in the storage object.

When to Use

Containers call methods that return a pointer to IEnumSTATSTG() so the container can manage its storage object and the elements within it. Calls to the IStorage::EnumElements() method supplies a pointer to IEnumSTATDATA(). The caller allocates an array of STATSTG structures and the IEnumSTATSTG() methods fill in each structure with the statistics about one of the nested elements in the storage object. If present, the lpszName member of the STATSTG structure requires additional memory allocations through the IMalloc() interface, and the caller is responsible for freeing this memory, if it is allocated, by calling the IMalloc::Free() method. If the lpszName member is NULL, no memory is allocated, and, therefore, no memory needs to be freed.

The prototypes of the methods are as follows:

#include <objidl.h>

HRESULT Next(
        ULONG celt,
        STATSTG * rgelt,
        ULONG * pceltFetched );

#include <objidl.h>

HRESULT Skip(
        ULONG celt );

#include <objidl.h>

HRESULT Reset(
        void );

#include <objidl.h>

HRESULT Clone(
        IEnumSTATSTG ** ppenum );

See Also

CoGetMalloc(), IEnumXXXX, IStorage::EnumElements(), STATSTG

15.6.6    ILockBytes

The ILockBytes() interface is implemented on a byte array object that is backed by some physical storage, such as a disk file, global memory, or a database. It is used by an COM compound file storage object to give its root storage access to the physical device, while isolating the root storage from the details of accessing the physical storage.

When to Implement

Most applications will not implement the ILockBytes() interface because COM provides implementations for the two most common situations:

File-based implementation -- If you call StgCreateDocfile() function to create a compound file storage object, it contains an implementation of ILockBytes() that is associated with a byte array stored in a physical disk file. The compound file storage object calls the ILockBytes() methods--you do not call them directly in this implementation.

Memory-based implementation -- COM also provides a byte array object based on global memory that supports an implementation of ILockBytes(). You can get a pointer through a call to the CreateILockBytesOnHGlobal() function). Then, to create a compound file storage object on top of that byte array object, call the StgCreateDocfileOnILockBytes() function. The compound file storage object calls the ILockBytes() methods--you do not call them directly in this implementation.

There are situations in which it would be useful for an application to provide its own ILockBytes() implementation. For example, a database application could implement ILockBytes() to create a byte array object backed by the storage of its relational tables. However, it is strongly recommended that you use the COM-provided implementations. For a discussion of the advantages of using the COM implementations rather than creating your own, see the StgCreateDocfileOnILockBytes() API function, which creates a compound file storage object on top of a caller-provided byte array object.

If you choose to implement your own ILockBytes() interface, you should consider providing custom marshaling by implementing the IMarshal() interface as part of your byte array object. The reason for this is that when the COM-provided implementations of IStorage() and IStream() are marshaled to another process, their ILockBytes() interface pointers are also marshaled to the other process. The default marshaling mechanism creates a proxy byte array object (on which is the ILockBytes() interface) that transmits method calls back to the original byte array object. Custom marshaling can improve efficiency by creating a remote byte array object that can access the byte array directly.

When to Use

The ILockBytes() methods are called by the COM implementations of IStorage() and IStream() on the compound file object. Unless you are implementing IStorage() and IStream(), you would not need to call ILockBytes() methods directly. If you write your own ILockBytes() implementation, you can use the StgCreateDocfileOnILockBytes() function to create a compound file storage object backed by your implementation of ILockBytes().

Table 15-4:  ILockBytes Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-5:  ILockBytes Methods

ILockBytes() Methods Description
ReadAt Reads a specified number of bytes starting at a specified offset from the beginning of the byte array.
WriteAt Writes a specified number of bytes to a specified location in the byte array.
Flush Ensures that any internal buffers maintained by the byte array object are written out to the backing storage.
SetSize Changes the size of the byte array.
LockRegion Restricts access to a specified range of bytes in the byte array.
UnlockRegion Removes the access restriction on a range of bytes previously restricted with ILockBytes::LockRegion().
Stat Retrieves a STATSTG structure for this byte array object.

 

ILockBytes::Flush()

NAME

ILockBytes::Flush() - Ensures that any internal buffers maintained by the ILockBytes() implementation are written out to the underlying physical storage.

Synopsis

#include <objidl.h>

HRESULT Flush(
        void );

Description

ILockBytes::Flush() flushes internal buffers to the underlying storage device.

The COM-provided implementation of compound files calls this method during a transacted commit operation to provide a two-phase commit process that protects against loss of data.

Return Values

S_OK

The flush operation was successful.

STG_E_ACCESSDENIED

The caller does not have permission to access the byte array.

STG_E_MEDIUMFULL

The flush operation is not completed because there is no space left on the storage device.

E_FAIL

General failure writing data.

STG_E_TOOMANYFILESOPEN

Under certain circumstances, Flush does a dump-and-close to flush, which can lead to a return value of STG_E_TOOMANYFILESOPEN if no file handles are available.

STG_E_INVALIDHANDLE

An underlying file has been prematurely closed, or the correct floppy disk has been replaced by an invalid one.

See Also

IStorage::Commit(), ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation  

ILockBytes::LockRegion()

NAME

ILockBytes::LockRegion() - Restricts access to a specified range of bytes in the byte array.

Synopsis

#include <objidl.h>

HRESULT LockRegion(
        ULARGE_INTEGER libOffset,
        ULARGE_INTEGER cb,
        DWORD dwLockType );

Description

ILockBytes::LockRegion() restricts access to the specified range of bytes. Once a region is locked, attempts by others to gain access to the restricted range must fail with the STG_E_ACCESSDENIED error.

The byte range can extend past the current end of the byte array. Locking beyond the end of an array is useful as a method of communication between different instances of the byte array object without changing data that is actually part of the byte array. For example, an implementation of ILockBytes() for compound files could rely on locking past the current end of the array as a means of access control, using specific locked regions to indicate permissions currently granted.

The dwLockType parameter specifies one of three types of locking, using values from the LOCKTYPE enumeration. The types are as follows: locking to exclude other writers, locking to exclude other readers or writers, and locking that allows only one requestor to obtain a lock on the given range. This third type of locking is usually an alias for one of the other two lock types, and permits an Implementer to add other behavior as well. A given byte array might support either of the first two types, or both.

To determine the lock types supported by a particular ILockBytes() implementation, you can examine the grfLocksSupported member of the STATSTG structure returned by a call to ILockBytes::Stat().

Any region locked with ILockBytes::LockRegion() must later be explicitly unlocked by calling ILockBytes::UnlockRegion() with exactly the same values for the libOffset, cb, and dwLockType parameters. The region must be unlocked before the stream is released. Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.

Notes to Callers

Since the type of locking supported is optional and can vary in different implementations of ILockBytes(), you must provide code to deal with the STG_E_INVALIDFUNCTION error.

Notes to Implementers

Support for this method depends on how the storage object built on top of the ILockBytes() implementation is used. If you know that only one storage object at any given time can be opened on the storage device that underlies the byte array, then your ILockBytes() implementation does not need to support locking. However, if multiple simultaneous openings of a storage object are possible, then region locking is needed to coordinate them.

A LockRegion implementation can choose to support all, some, or none of the lock types. For unsupported lock types, the implementation should return STG_E_INVALIDFUNCTION.

Parameters

libOffset

[in] Specifies the byte offset for the beginning of the range.

cb

[in] Specifies, in bytes, the length of the range to be restricted.

dwLockType

[in] Specifies the type of restrictions being requested on accessing the range. This parameter uses one of the values from the LOCKTYPE enumeration.

Return Values

S_OK

The specified range of bytes was locked.

STG_E_INVALIDFUNCTION

Locking is not supported at all or the specific type of lock requested is not supported.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

STG_E_INVALIDHANDLE

An underlying file has been prematurely closed, or the correct floppy disk has been replaced by an invalid one.

See Also

ILockBytes::Stat(), ILockBytes::UnlockRegion(), IStream::LockRegion(), LOCKTYPE, ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation  

ILockBytes::ReadAt()

NAME

ILockBytes::ReadAt() - Reads a specified number of bytes starting at a specified offset from the beginning of the byte array object.

Synopsis

#include <objidl.h>

HRESULT ReadAt(
        ULARGE_INTEGER ulOffset,
        void * pv,
        ULONG cb,
        ULONG * pcbRead );

Description

ILockBytes::ReadAt() reads bytes from the byte array object. It reports the number of bytes that were actually read. This value may be less than the number of bytes requested if an error occurs or if the end of the byte array is reached during the read.

It is not an error to read less than the specified number of bytes if the operation encounters the end of the byte array. Note that this is the same end-of-file behavior as found in MS-DOS FAT file system files.

Parameters

ulOffset

[in] Specifies the starting point from the beginning of the byte array for reading data.

pv

[in] Points to the buffer into which the byte array is read.

cb

[in] Specifies the number of bytes of data to attempt to read from the byte array.

pcbRead

[out] Pointer to a location where this method writes the actual number of bytes read from the byte array. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes read.

Return Values

S_OK

Indicates that the specified number of bytes were read, or the maximum number of bytes were read up to the end of the byte array.

E_FAIL

Data could not be read from the byte array.

E_PENDING

Asynchronous Storage only: Part or all of the data to be read is currently unavailable.

STG_E_ACCESSDENIED

The caller does not have permission to access the byte array.

STG_E_READFAULT

The number of bytes to be read does not equal the number of bytes that were acutally read.

See Also

ILockBytes::WriteAt(), ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation  

ILockBytes::SetSize()

NAME

ILockBytes::SetSize() - Changes the size of the byte array.

Synopsis

#include <objidl.h>

HRESULT SetSize(
        ULARGE_INTEGER cb );

Description

ILockBytes::SetSize() changes the size of the byte array. If the cb parameter is larger than the current byte array, the byte array is extended to the indicated size by filling the intervening space with bytes of undefined value, as does ILockBytes::WriteAt(), if the seek pointer is past the current end-of-stream.

If the cb parameter is smaller than the current byte array, the byte array is truncated to the indicated size.

Notes to Callers

Callers cannot rely on STG_E_MEDIUMFULL being returned at the appropriate time because of cache buffering in the operating system or network. However, callers must be able to deal with this return code because some ILockBytes() implementations might support it.

Parameters

cb

[in] Specifies the new size of the byte array as a number of bytes.

Return Values

S_OK

The size of the byte array was successfully changed.

STG_E_ACCESSDENIED

The caller does not have permission to access the byte array.

STG_E_MEDIUMFULL

The byte array size is not changed because there is no space left on the storage device.

See Also

ILockBytes::ReadAt(), ILockBytes::WriteAt(), ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation  

ILockBytes::Stat()

NAME

ILockBytes::Stat() - Retrieves a STATSTG structure containing information for this byte array object.

Synopsis

#include <objidl.h>

HRESULT Stat(
        STATSTG * pstatstg,
        DWORD grfStatFlag );

Description

ILockBytes::Stat() should supply information about the byte array object in a STATSTG structure.

Parameters

pstatstg

[out] Points to a STATSTG structure in which this method places information about this byte array object. The pointer is NULL if an error occurs.

grfStatFlag

[in] Specifies whether this method should supply the pwcsName member of the STATSTG structure through values taken from the STATFLAG enumeration. If the STATFLAG_NONAME is specified, the pwcsName member of STATSTG is not supplied, thus saving a memory allocation operation. The other possible value, STATFLAG_DEFAULT, indicates that all STATSTG members be supplied.

Return Values

S_OK

The STATSTG structure was successfully returned at the specified location.

E_OUTOFMEMORY

The STATSTG structure was not returned due to a lack of memory for the name field in the structure.

STG_E_ACCESSDENIED

The STATSTG structure was not returned because the caller did not have access to the byte array.

STG_E_INSUFFICIENTMEMORY

The STATSTG structure was not returned, due to a lack of memory.

STG_E_INVALIDFLAG

The value for the grfStateFlag parameter is not valid.

STG_E_INVALIDPOINTER

The value for the pStatStg parameter is not valid.

See Also

STATFLAG, STATSTG, ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation  

ILockBytes::UnlockRegion()

NAME

ILockBytes::UnlockRegion() - Removes the access restriction on a previously locked range of bytes.

Synopsis

#include <objidl.h>

HRESULT UnlockRegion(
        ULARGE_INTEGER libOffset,
        ULARGE_INTEGER cb,
        DWORD dwLockType );

Description

ILockBytes::UnlockRegion() unlocks a region previously locked with a call to ILockBytes::LockRegion(). Each region locked must be explicitly unlocked, using the same values for the libOffset, cb, and dwLockType parameters as in the matching calls to ILockBytes::LockRegion(). Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.

See Also

ILockBytes::LockRegion(), LOCKTYPE, ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation

Parameters

libOffset

[in] Specifies the byte offset for the beginning of the range.

cb

[in] Specifies, in bytes, the length of the range that is restricted.

dwLockType

[in] Specifies the type of access restrictions previously placed on the range. This parameter uses a value from the LOCKTYPE enumeration.

Return Values

S_OK

The byte range was unlocked.

STG_E_INVALIDFUNCTION

Locking is not supported at all or the specific type of lock requested is not supported.

STG_E_LOCKVIOLATION

The requested unlock cannot be granted.

 

ILockBytes::WriteAt()

NAME

ILockBytes::WriteAt() - Writes the specified number of bytes starting at a specified offset from the beginning of the byte array.

Synopsis

#include <objidl.h>

HRESULT WriteAt(
        ULARGE_INTEGER ulOffset,
        void const * pv,
        ULONG cb,
        ULONG * pcbWritten );

Description

ILockBytes::WriteAt() writes the specified data at the specified location in the byte array. The number of bytes actually written must always be returned in pcbWritten, even if an error is returned. If the byte count is zero bytes, the write operation has no effect.

If ulOffset is past the end of the byte array and cb is greater than zero, ILockBytes::WriteAt() increases the size of the byte array. The fill bytes written to the byte array are not initialized to any particular value.

Parameters

ulOffset

[in] Specifies the starting point from the beginning of the byte array for the data to be written.

pv

[in] Points to the buffer containing the data to be written.

cb

[in] Specifies the number of bytes of data to attempt to write into the byte array.

pcbRead

[out] Pointer to a location where this method specifies the actual number of bytes written to the byte array. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes written.

Return Values

S_OK

Indicates that the specified number of bytes were written.

E_FAIL

A general failure occurred during the write.

E_PENDING

Asynchronous Storage only: Part or all of the data to be written is currently unavailable.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for writing this byte array.

STG_E_WRITEFAULT

The number of bytes to be written does not equal the number of bytes that were acutally written.

STG_E_MEDIUMFULL

The write operation was not completed because there is no space left on the storage device. The actual number of bytes written is still returned in pcbWritten.

See Also

ILockBytes::ReadAt(), ILockBytes::SetSize(), ILockBytes--File-Based Implementation, ILockBytes--Global Memory Implementation

15.6.7    ILockBytes - File-Based Implementation

Implemented on a byte array object underlying a COM compound file storage object, and designed to read and write directly to a disk file.

When to Use

Methods of ILockBytes() are called from the compound file implementations of IStorage() and IStream() on the compound file storage object created through a call to StgCreateDocfile(), so you do not need to call them directly.

Description

ILockBytes::ReadAt()

This method queries the wrapped pointer for the requested interface.

ILockBytes::WriteAt()

This method queries the wrapped pointer for the requested interface.

ILockBytes::Flush()

This method queries the wrapped pointer for the requested interface.

ILockBytes::SetSize()

This method queries the wrapped pointer for the requested interface.

ILockBytes::LockRegion()

The dwLockTypes parameter is set to LOCK_ONLYONCE or LOCK_EXCLUSIVE, which will allow or restrict access to locked regions.

ILockBytes::UnlockRegion()

This method unlocks the region locked by ILockBytes::LockRegion().

ILockBytes::Stat()

The COM-provided IStorage::Stat() implementation calls the ILockBytes::Stat() method to retrieve information about the byte array object. If there is no reasonable name for the byte array, the COM-provided ILockBytes::Stat() method returns NULL in the pwcsName field of the STATSTG structure.

See Also

ILockBytes(), IStorage(), IStream()

15.6.8    ILockBytes - Global Memory Implementation

Implemented on a byte array object underlying an COM compound file storage object, and designed to read and write directly to global memory.

When to Use

Methods of ILockBytes() are called from the compound file implementations of IStorage() and IStream() on the compound file storage object created through a call to StgCreateDocfile().

Description

ILockBytes::ReadAt()

This method queries the wrapped pointer for the requested interface.

ILockBytes::WriteAt()

This method queries the wrapped pointer for the requested interface.

ILockBytes::Flush()

This method queries the wrapped pointer for the requested interface.

ILockBytes::SetSize()

This method queries the wrapped pointer for the requested interface.

ILockBytes::LockRegion()

This implementation does not support locking, so dwLocksType is set to zero. It is the caller's responsibility to ensure accesses are valid and mutually exclusive.

ILockBytes::UnlockRegion()

This implementation does not support locking.

ILockBytes::Stat()

The COM-provided IStorage::Stat() implementation calls the ILockBytes::Stat() method to retrieve information about the byte array object. If there is no reasonable name for the byte array, the COM-provided ILockBytes::Stat() method returns NULL in the pwcsName field of the STATSTG structure.

See Also

ILockBytes(), IStorage(), IStream()

15.6.9    IPersist

The IPersist() interface defines the single method GetClassID(), which is designed to supply the CLSID of an object that can be stored persistently in the system. A call to this method can allow the object to specify which object handler to use in the client process, as it is used in the COM default implementation of marshaling.

IPersist() is the base interface for three other interfaces: IPersistStorage(), IPersistStream(), and IPersistFile(). Each of these interfaces, therefore, includes the GetClassID() method, and the appropriate one of these three interfaces is implemented on objects that can be serialized to a storage, a stream, or a file. The methods of these interfaces allow the state of these objects to be saved for later instantiations, and load the object using the saved state. Typically, the persistence interfaces are implemented by an embedded or linked object, and are called by the container application or the default object handler

When to Implement

You must implement the single method of IPersist() in implementing any one of the other persistence interfaces: IPersistStorage(), IPersistStream(), or IPersistFile(). Typically, for example, you would implement IPersistStorage() on an embedded object, IPersistFile() on a linked object, and IPersistStream() on a new moniker class, although their uses are not limited to these objects. You could implement IPersist() in a situation where all that is required is to obtain the CLSID of a persistent object, as it is used in marshaling.

When to Use

The single method of IPersist() is rarely called directly in application code. It is called by the default object handler to get the CLSID of an embedded object, or an object to be marshaled. A container application, for example, would probably not call the GetClassID() method directly unless it provided object handlers for specific classes of objects.

Table 15-6:  IPersist Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-7:  IPersist Methods

IPersist() Method Description
GetClassID() Returns the class identifier (CLSID) for the component object.

 

IPersist::GetClassID()

NAME

IPersist::GetClassID() - Retrieves the class identifier (CLSID) of an object. The CLSID is a unique value that identifies the code that can manipulate the persistent data.

Synopsis

#include <objidl.h>

HRESULT GetClassID((
        CLSID * pClassID );

Description

The GetClassID() method retrieves the class identifier (CLSID) for an object, used in later operations to load object-specific code into the caller's context.

Notes to Callers

A container application might call this method to retrieve the original CLSID of an object that it is treating as a different class. Such a call would be necessary if a user performed an editing operation that required the object to be saved. If the container were to save it using the treat-as CLSID, the original application would no longer be able to edit the object. Typically, in this case, the container calls the OleSave helper function, which performs all the necessary steps. For this reason, most container applications have no need to call this method directly.

The exception would be a container that provides an object handler for certain objects. In particular, a container application should not get an object's CLSID and then use it to retrieve class specific information from the registry.

Notes to Implementers

Typically, implementations of this method simply supply a constant CLSID for an object. If, however, the object's TreatAs registry key has been set by an application that supports emulation (and so is treating the object as one of a different class), a call to IPersist::GetClassID() must supply the CLSID specified in the TreatAs key. For more information on emulation, refer to CoTreatAsClass().

When an object is in the running state, the default handler calls an implementation of IPersist::GetClassID() that delegates the call to the implementation in the object. When the object is not running, the default handler instead calls the ReadClassStg() function to read the CLSID that is saved in the object's storage.

If you are writing a custom object handler for your object, you might want to simply delegate this method to the default handler implementation (see OleCreateDefaultHandler).

See Also

IPersistStorage(), IPersistStream(), IPersistFile(), ReadClassStg()

Parameters

pClassID

[out] Points to the location of the CLSID on return. The CLSID is a globally unique identifier (GUID) that uniquely represents an object class that defines the code that can manipulate the object's data.

Return Values

S_OK

The CLSID was successfully retrieved.

E_FAIL

The CLSID could not be retrieved.

15.6.10    IPersistFile

The IPersistFile() interface provides methods that permit an object to be loaded from or saved to a disk file, rather than a storage object or stream. Because the information needed to open a file varies greatly from one application to another, the implementation of IPersistFile::Load() on the object must also open its disk file.

The IPersistFile() interface inherits its definition from IPersist(), so all implementations must also include the GetClassID() method of IPersist().

When to Implement

Implement IPersistFile() when you want to read or write information from a separate file, which could be of any file format.

This interface should be implemented on any objects that support linking through a file moniker, including the following:

Typically, you implement the IPersistFile() interface as part of an aggregate object that includes other interfaces that are appropriate for the type of moniker binding that is supported.

For example, in either of the cases mentioned above, the moniker for the linked object can be a composite moniker. In the first case, a composite moniker identifies the pseudo-object contained within the file. In the second case, a composite moniker identifies the embedded object contained within the compound file. In either case of composite monikers, you must implement the IPersistFile() interface as part of the same object on which the IOleItemContainer() interface is implemented. Then, when the application for the linked object is run, COM queries for the IOleItemContainer() interface to locate the embedded object or the pseudo-object contained in the file.

As another example, if the moniker is a simple file moniker (i.e., the link is to the entire file), COM queries for the interface that the initiator of the bind operation requested. Typically, this is one of the compound document interfaces, such as IOleObject, IDataObject(), or IPersistStorage().

When to Use

Call methods in the IPersistFile() interface to load or save a linked object in a specified file.

When IPersistFile() is implemented on an object that supports linking through a file moniker and the application for the linked object is run, COM calls IPersistFile::Load(). Once the file is loaded, COM calls IPersistFile::QueryInterface() to get another interface pointer to the loaded object. The IPersistFile() interface is typically part of an aggregate object that offers other interfaces.

In this case, the only IPersistFile() method that COM calls is the Load method to load a file linked to a container, running the application associated with the file. It would also be unusual for applications to call other methods in this case, which support saving an object to a file. Generally, it is left to the end user and the application for the linked object to decide when to save the object. This differs from the situation for an embedded object, in which the container application uses the IPersistStorage() interface to provide the storage and to tell the object when to save itself.

Table 15-8:  IPersistFile Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-9:  IPersist Methods

IPersist() Method Description
GetClassID() Returns the class identifier (CLSID) for the component object.

Table 15-10:  IPersistFile Methods

IPersistFile() Methods Description
IsDirty Checks an object for changes since it was last saved to its current file.
Load Opens the specified file and initializes an object from the file contents.
Save Saves the object into the specified file.
SaveCompleted Notifies the object that it can revert from NoScribble mode to Normal mode.
GetCurFile Gets the current name of the file associated with the object.

 

IPersistFile::GetCurFile()

NAME

IPersistFile::GetCurFile() - Retrieves either the absolute path to the object's current working file or, if there is no current working file, the object's default filename prompt.

Synopsis

#include <objidl.h>

HRESULT GetCurFile(
        LPOLESTR * ppszFileName );

Description

This method returns the current filename or the default save prompt for the object.

This method allocates memory for the string returned in the ppszFileName parameter using the IMalloc::Alloc() method. The caller is responsible for calling the IMalloc::Free() method to free the string. Both the caller and this method use the COM task allocator provided by a call to CoGetMalloc().

The LPOLESTR type indicates a wide character string (two bytes per character); otherwise, the string has one byte per character.

The filename returned in ppszFileName is the name specified in a call to IPersistFile::Load() when the document was loaded; or in IPersistFile::SaveCompleted() if the document was saved to a different file.

If the object does not have a current working file, it should supply the default filename prompt that it would display in a ``Save As'' dialog. For example, the default save prompt for a word processor object could be:

*.txt

Notes to Callers

COM does not call the IPersistFile::GetCurFile() method. Applications would not call this method unless they are also calling the save methods of this interface.

In saving the object, you can call this method before calling IPersistFile:Save to determine whether the object has an associated file. If this method returns S_OK, you can then call IPersistFile::Save() with a NULL filename and a TRUE value for the fRemember parameter to tell the object to save itself to its current file. If this method returns S_FALSE, you can use the save prompt returned in the ppszFileName parameter to ask the end user to provide a filename. Then, you can call IPersistFile::Save() with the filename that the user entered to perform a ``Save As'' operation.

Parameters

ppszFileName

[out] Points to the location of a pointer to a zero-terminated string containing the path for the current file or the default filename prompt (such as *.txt). If an error occurs, ppszFileName is set to NULL.

Return Values

S_OK

A valid absolute path was successfully returned.

S_FALSE

The default save prompt was returned.

E_OUTOFMEMORY

The operation failed due to insufficient memory.

E_FAIL

The operation failed due to some reason other than insufficient memory.

See Also

IPersistFile::Load(), IPersistFile::Save(), IPersistFile::SaveCompleted()  

IPersistFile::IsDirty()

NAME

IPersistFile::IsDirty() - Checks an object for changes since it was last saved to its current file.

Synopsis

#include <objidl.h>

HRESULT IsDirty(
        void );

Description

This method checks whether an object has changed since it was last saved. Call it to determine whether an object should be saved before closing it. The dirty flag for an object is conditionally cleared in the IPersistFile::Save() method.

Notes to Callers

COM does not call IPersistFile::IsDirty(). Applications would not call it unless they are also saving an object to a file.

You should treat any error return codes as an indication that the object has changed. Unless this method explicitly returns S_FALSE, assume that the object must be saved.

Notes to Implementers

An object with no contained objects simply checks its dirty flag to return the appropriate result.

A container with one or more contained objects must maintain an internal dirty flag that is set when any of its contained objects has changed since it was last saved. To do this, the container should maintain an advise sink by implementing the IAdviseSink() interface. Then, the container can register each link or embedding for data change notifications with a call to IDataObject::DAdvise(). Then, the container can set its internal dirty flag when it receives an IAdviseSink::OnDataChange() notification. If the container does not register for data change notifications, the IPersistFile::IsDirty() implementation would call IPersistStorage::IsDirty() for each of its contained objects to determine whether they have changed.

The container can clear its dirty flag whenever it is saved, as long as the file to which the object is saved is the current working file after the save. Therefore, the dirty flag would be cleared after a successful ``Save'' or ``Save As'' operation, but not after a ``Save A Copy As . . .'' operation.

Return Values

S_OK

The object has changed since it was last saved.

S_FALSE

The object has not changed since the last save.

See Also

IAdviseSink::OnDataChange(), IDataObject::DAdvise(), IPersistStorage::IsDirty()  

IPersistFile::Load()

NAME

IPersistFile::Load() - Opens the specified file and initializes an object from the file contents.

Synopsis

#include <objidl.h>

HRESULT Load(
        LPCOLESTR pszFileName,
        DWORD dwMode );

Description

IPersistFile::Load() loads the object from the specified file. This method is for initialization only and does not show the object to the end user. It is not equivalent to what occurs when an end user selects the File Open command.

Notes to Callers

The BindToObject method in file monikers calls this method to load an object during a moniker binding operation (when a linked object is run). Typically, applications do not call this method directly.

Notes to Implementers

Because the information needed to open a file varies greatly from one application to another, the object on which this method is implemented must also open the file specified by the pszFileName parameter. This differs from the IPersistStorage::Load() and IPersistStream::Load(), in which the caller opens the storage or stream and then passes an open storage or stream pointer to the loaded object.

For an application that normally uses COM compound files, your IPersistFile::Load() implementation can simply call the StgOpenStorage() function to open the storage object in the specified file. Then, you can proceed with normal initialization. Applications that do not use storage objects can perform normal file-opening procedures.

When the object has been loaded, your implementation should register the object in the Running Object Table (see IRunningObjectTable::Register()).

Parameters

pszFileName

[in] Points to a zero-terminated string containing the absolute path of the file to open.

dwMode

[in] Specifies some combination of the values from the STGM enumeration to indicate the access mode to use when opening the file. IPersistFile::Load() can treat this value as a suggestion, adding more restrictive permissions if necessary. If dwMode is zero, the implementation should open the file using whatever default permissions are used when a user opens the file.

Return Values

S_OK

The object was successfully loaded.

E_OUTOFMEMORY

The object could not be loaded due to a lack of memory.

E_FAIL

The object could not be loaded for some reason other than a lack of memory.

IPersistFile::Load() STG_E_* error codes.

See Also

IRunningObjectTable::Register(), StgOpenStorage()  

IPersistFile::Save()

NAME

IPersistFile::Save() - Saves a copy of the object into the specified file.

Synopsis

#include <objidl.h>

HRESULT Save(
        LPCOLESTR pszFileName,
        BOOL fRemember );

Description

This method can be called to save an object to the specified file in one of three ways:

Save

Call IPersistFile::GetCurFile() first to determine whether the object has an associated filename. If so, call IPersistFile::Save() specifying NULL for the pszFileName parameter in this method to indicate that the object should be saved to its current file. Then call IPersistFile::SaveCompleted() to indicate completion.

Save As

Call IPersistFile::Save() specifying TRUE in the fRemember parameter and a non-NULL value, indicating the name of the new file the object is to be saved to, for the pszFileName parameter . Then call IPersistFile::SaveCompleted() to indicate completion.

Save a Copy As

Call IPersistFile::Save() specifying FALSE in the fRemember parameter and a non-NULL value, indicating the name of the new file the object is to be copied to, for the pszFileName parameter.

The implementer must detect which type of save operation the caller is requesting. If the pszFileName parameter is NULL, a ``Save'' is being requested. If the pszFileName parameter is not NULL, use the value of the fRemember parameter to distinguish between a ``Save As'' and a ``Save a Copy As''.

In ``Save'' or ``Save As'' operations, IPersistFile::Save() clears the internal dirty flag after the save and sends IAdviseSink::OnSave() notifications to any advisory connections. Also, in these operations, the object is in NoScribble mode until it receives an IPersistFile::SaveCompleted() call. In NoScribble mode, the object must not write to the file.

In the ``Save As'' scenario, the implementation should also send IAdviseSink::OnRename() notifications to any advisory.

In the ``Save a Copy As'' scenario, the implementation does not clear the internal dirty flag after the save.

Notes to Callers

COM does not call IPersistFile::Save(). Typically, applications would not call it unless they are saving an object to a file directly, which is generally left to the end-user.

Parameters

pszFileName

[in] Points to a zero-terminated string containing the absolute path of the file to which the object should be saved. If pszFileName is NULL, the object should save its data to the current file, if there is one.

fRemember

[in]Indicates whether the pszFileName parameter is to be used as the current working file. If TRUE, pszFileName becomes the current file and the object should clear its dirty flag after the save. If FALSE, this save operation is a ``Save A Copy As ...'' operation. In this case, the current file is unchanged and the object should not clear its dirty flag. If pszFileName is NULL, the implementation should ignore the fRemember flag.

Return Values

S_OK

The object was successfully saved.

E_FAIL

The file was not saved.

IPersistFile::Save() STG_E_* errors.

See Also

IPersistFile::GetCurFile(), IPersistFile::SaveCompleted()  

IPersistFile::SaveCompleted()

NAME

IPersistFile::SaveCompleted() - Notifies the object that it can write to its file. It does this by notifying the object that it can revert from NoScribble mode (in which it must not write to its file), to Normal mode (in which it can). The component enters NoScribble mode when it receives an IPersistFile::Save() call.

Synopsis

#include <objidl.h>

HRESULT SaveCompleted(
        LPCOLESTR pszFileName );

Description

IPersistFile::SaveCompleted() is called when a call to IPersistFile::Save() is completed, and the file that was saved is now the current working file (having been saved with ``Save'' or ``Save As'' operations). The call to Save puts the object into NoScribble mode so it cannot write to its file. When SaveCompleted is called, the object reverts to Normal mode, in which it is free to write to its file.

Notes to Callers

COM does not call the IPersistFile::SaveCompleted() method. Typically, applications would not call it unless they are saving objects directly to files, an operation which is generally left to the end-user.

Parameters

pszFileName

[in] Points to the absolute path of the file where the object was previously saved.

Return Values

S_OK

Returned in all cases.

See Also

IPersistFile::Save()

15.6.11    IPersistMemory

The IPersistMemory() interface operates exactly as IPersistStreamInit(), except that it allows the caller to provide a fixed-size memory block (identified with a void *) as opposed to IPersistStreamInit() which involves an arbitrarily expandable IStream().

The cbSize argument to the Load and Save methods indicate the amount of memory accessible through pvMem.

The IsDirty, GetSizeMax, and InitNew() methods are semantically and syntactically identical to those in IPersistStreamInit(). Only Load and Save differ.

When to Implement

An object implements this interface to save itself in memory.

When to Use

A container calls the methods of this interface to instruct an object to save and load itself in memory.

Table 15-11:  IPersistMemory Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-12:  IPersist Methods

IPersist Method Description
GetClassID() Returns the class identifier (CLSID) for the component object.

Table 15-13:  IPersistMemory Methods

IPersistMemory Methods Description
IsDirty Checks the object for changes since it was last saved.
Load Initializes an object from the memory block where it was previously saved.
Save Saves an object into the specified memory block and indicates whether the object should reset its dirty flag.
GetSizeMax Returns the size in bytes of the memory block needed to save the object.
InitNew() Initializes an object to a default state.

 

IPersistMemory::GetSizeMax()

NAME

IPersistMemory::GetSizeMax() - Returns the size in bytes of the memory block needed to save the object.

Synopsis

#include <ocidl.h>

HRESULT GetSizeMax(
        ULARGE_INTEGER * pcbSize );

Description

This method returns the size needed to save an object. You can call this method to determine the size and set the necessary buffers before calling the IPersistMemory::Save() method.

Notes to Implementers

The GetSizeMax implementation must return a conservative estimate of the necessary size because the IPersistMemory::Save() method uses a fixed size memory block.

Parameters

pcbSize

[out] Pointer to a 64-bit unsigned integer value indicating the size in bytes of the memory needed to save this object.

Return Values

S_OK

The size was successfully returned.

See Also

IPersistMemory::Save()  

IPersistMemory::InitNew()

NAME

IPersistMemory::InitNew() - Initializes the object to a default state. This method is called instead of IPersistMemory::Load().

Synopsis

#include <ocidl.h>

HRESULT InitNew((
        void );

Return Values

S_OK

The object successfully initialized itself.

E_NOTIMPL

The object requires no default initialization. This error code is allowed because an object may choose to implement IPersistMemory() simply for orthogonality or in anticipation of a future need for this method.

E_UNEXPECTED

This method was called after the object was already initialized with IPersistMemory::Load(). Only one initialization is allowed per instance.

E_OUTOFMEMORY

There was not enough memory for the object to initialize itself.

Notes to Implementers

If the object has already been initialized with Load, then this method must return E_UNEXPECTED.

See Also

IPersistMemory::Load()  

IPersistMemory::IsDirty()

NAME

IPersistMemory::IsDirty() - Checks the object for changes since it was last saved.

Synopsis

#include <ocidl.h>

HRESULT IsDirty(
        void );

Description

This method checks whether an object has changed since it was last saved so you can avoid losing information in objects that have not yet been saved. The dirty flag for an object is conditionally cleared in the IPersistMemory::Save() method.

Notes to Callers

You should treat any error return codes as an indication that the object has changed. In other words, unless this method explicitly returns S_FALSE, you must assume that the object needs to be saved.

Return Values

S_OK

The object has changed since it was last saved.

S_FALSE

The object has not changed since the last save.

See Also

IPersistMemory::Save()  

IPersistMemory::Load()

NAME

IPersistMemory::Load() - Instructs the object to load its persistent data from the memory pointed to by pvMem where cbSize indicates the amount of memory at pvMem. The object must not read past the address (BYTE*)((BYTE *)pvMem+cbSize).

Synopsis

#include <ocidl.h>

HRESULT Load(
        void * pvMem,
        ULONG cbSize );

Description

Any object that implements IPersistMemory() has some information to load persistently, therefore E_NOTIMPL is not a valid return code.

Parameters

pvMem

[in] Pointer to the address in memory from which the object can read up to cbSize bytes of its data.

cbSize

[in] The amount of memory available at pvMem from which the object can read its data.

Return Values

S_OK

The object successfully loaded its data.

E_UNEXPECTED

This method was called after the object was already initialized with IPersistMemory::Load(). Only one initialization is allowed per instance.

E_POINTER

The pointer in pvMem is NULL.

See Also

IPersistMemory::InitNew()  

IPersistMemory::Save()

NAME

IPersistMemory::Save() - Instructs the object to save its persistent data to the memory pointed to by pvMem where cbSize indicates the amount of memory available at pvMem. The object must not write past the address (BYTE*)((BYTE *)pvMem+cbSize). The fClearDirty flag determines whether the object is to clear its dirty state after the save is complete.

Synopsis

#include <ocidl.h>

HRESULT Save(
        void * pvMem,
        BOOL fClearDirty,
        ULONG cbSize );

Description

Any object that implements IPersistMemory() has some information to save persistently, therefore E_NOTIMPL is not a valid return code.

The caller should ideally allocate as many bytes as the object returns from IPersistMemory::GetSizeMax().

Parameters

pvMem

[in] Pointer to the memory in which the object should save up to cbSize bytes of its data.

fClearDirty

[in] A flag indicating whether the object should clear its dirty state on return from Save or leave that state as-is.

cbSize

[in] The amount of memory available at pvMem to which the object can write its data.

Return Values

S_OK

The object successfully initialized itself.

E_UNEXPECTED

This method was called before the object was initialized with IPersistMemory::InitNew() or IPersistMemory::Load().

E_INVALIDARG

The number of bytes indicated by cbSize is too small to allow the object to save itself completely.

E_POINTER

The pointer in pvMem is NULL.

See Also

IPersistMemory::InitNew(), IPersistMemory::Load()

15.6.12    IPersistPropertyBag

The IPersistPropertyBag() interface works in conjunction with IPropertyBag() and IErrorLog() to define an individual property-based persistence mechanism. Whereas a mechanism like IPersistStream() gives an object an IStream() in which to store its binary data, IPersistPropertyBag() provides an object with an IPropertyBag() interface through which it can save and load individual properties. The implementer of IPropertyBag() can then save those properties in whatever way it chooses, such as name/value pairs in a text file. Errors encountered in the process (on either side) are recorded in an error log through IErrorLog(). This error reporting mechanism work on a per-property basis instead of an all properties as a whole basis through just the return value of IPersist*::Load or IPersist*::Save.

The basic mechanism is that a container tells the object to save or load its properties through IPersistPropertyBag(). For each property, the object calls the container's IPropertyBag() interface passed to the IPersistPropertyBag() methods. IPropertyBag::Write() saves a property in whatever place the container wants to put it, and IPropertyBag::Read() retrieves a property.

This protocol is essentially a means of sequentially communicating individual property values from the object to the container, which is useful for doing save-as-text operations and the like. The object gives the container the choice of the format in which each property is saved, while retaining itself the decision as to which properties are saved or loaded.

When to Implement

An object implements this interface to enable saving its properties persistently.

When to Use

A container calls the methods on this interface to instruct an object to load and save its properties to the supplied property bag.

Table 15-14:  IPersistPropertyBag Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-15:  IPersist Methods

IPersist Method Description
GetClassID() Returns the class identifier (CLSID) for the component object.

Table 15-16:  IPersistPropertyBag Methods

IPersistPropertyBag() Methods Description
InitNew() Called by the container when the control is initialized to initialize the property bag.
Load Called by the container to load the control's properties.
Save Called by the container to save the object's properties.

See Also

IErrorLog(), IPropertyBag()  

IPersistPropertyBag::InitNew()

NAME

IPersistPropertyBag::InitNew() - Called by the container when the control is initialized to initialize the property bag.

Synopsis

#include <ocidl.h>

HRESULT InitNew((
        void );

Description

This method informs the object that it is being initialized as a newly created object.

E_NOTIMPL should not be returned--use S_OK when the object has nothing to do in the method.

Return Values

S_OK

The object successfully initialized itself. This should be returned even if the object doesn't do anything in the method.

CO_E_ALREADYINITIALISED

The object has already been initialized.

E_OUTOFMEMORY

The storage object was not initialized due to a lack of memory.

E_UNEXPECTED

The storage object was not initialized due to some reason other than a lack of memory.

See Also

IPersistPropertyBag::Load()  

IPersistPropertyBag::Load()

NAME

IPersistPropertyBag::Load() - Called by the container to load the control's properties.

Synopsis

#include <ocidl.h>

HRESULT Load(
        IPropertyBag * pPropBag,
        IErrorLog * pErrorLog );

Description

This method instructs the object to initialize itself using the properties available in the property bag, notifying the provided error log object when errors occur. All property storage must take place within this method call as the object cannot hold the IPropertyBag() pointer.

E_NOTIMPL is not a valid return code as any object implementing this interface must support the entire functionality of the interface.

Parameters

pPropBag

[in] Pointer to the caller's IPropertyBag() interface bag that the control uses to read its properties. Cannot be NULL.

pErrorLog

[in] Pointer to the caller's IErrorLog() interface in which the object stores any errors that occur during initialization. Can be NULL in which case the caller is not interested in errors.

Return Values

S_OK

The object successfully initialized itself.

E_UNEXPECTED

This method was called after IPersistPropertyBag::InitNew() has already been called. They two initialization methods are mutually exclusive.

E_OUTOFMEMORY

The properties were not loaded due to a lack of memory.

E_POINTER

The address in pPropBag is not valid (such as NULL) and therefore the object cannot initialize itself.

E_FAIL

The object was unable to retrieve a critical property that is necessary for the object's successful operation. The object was therefore unable to initialize itself completely.

See Also

IPersistPropertyBag::InitNew()  

IPersistPropertyBag::Save()

NAME

IPersistPropertyBag::Save() - Called by the container to save the object's properties.

Synopsis

#include <ocidl.h>

HRESULT Save(
        IPropertyBag * pPropBag,
        BOOL fClearDirty,
        BOOL fSaveAllProperties );

Description

This method instructs the object to save its properties to the specified property bag, optionally clearing the object's dirty flag. The caller can request that the object save all properties or that the object save only those that are known to have changed.

E_NOTIMPL is not a valid return code as any object implementing this interface must support the entire functionality of the interface.

Parameters

pPropBag

[in] Pointer to the caller's IPropertyBag() interface through which the object can write properties. Cannot be NULL.

fClearDirty

[in] A flag indicating whether the object should clear its dirty flag when saving is complete. TRUE means clear the flag, FALSE means leave the flag unaffected. FALSE is used when the caller wishes to do a Save Copy As type of operation.

fSaveAllProperties

[in] A flag indicating whether the object should save all its properties (TRUE) or only those that have changed since the last save or initialization (FALSE).

Return Values

S_OK

The object successfully saved the requested properties itself.

E_FAIL

There was a problem saving one of the properties. The object can choose to fail only if a necessary property could not be saved, meaning that the object can assume default property values if a given property is not seen through IPersistPropertyBag::Load() at some later time.

E_POINTER

The address in pPropBag is not valid (such as NULL) and therefore the object cannot initialize itself.

STG_E_MEDIUMFULL

The object was not saved because of a lack of space on the disk.

See Also

IPersistPropertyBag::InitNew(), IPersistPropertyBag::Load()

15.6.13    IPersistStorage

The IPersistStorage() interface defines methods that enable a container application to pass a storage object to one of its contained objects and to load and save the storage object. This interface supports the structured storage model, in which each contained object has its own storage that is nested within the container's storage.

The IPersistStorage() contract inherits its definition from IPersist(), so all implementations must also include the GetClassID() method of IPersist().

When to Implement

Any object that can be embedded in a container must implement the IPersistStorage() interface. This interface is one of the primary interfaces for a compound document object. Embeddable objects must also implement the IOleObject and IDataObject() interfaces.

The COM default handler for embedded objects provides an implementation of the IPersistStorage() interface that is used when the object is in the loaded state. Similarly, the COM default link handler provides an IPersistStorage() implementation that manages storage for a linked object. These default handlers both interact with the COM default cache implementation, which has its own IPersistStorage() implementation.

If you are providing a custom embedding or link handler for your objects, the handler must include an implementation of IPersistStorage(). You can delegate calls to the default handler so you can take advantage of the default cache implementation.

When to Use

When a COM container creates a new object, loads an existing object from storage, or inserts a new object in a clipboard or a drag-and-drop operation, the container uses the IPersistStorage() interface to initialize the object and put it in the loaded or running state. When an object is loaded or running, an COM container calls other IPersistStorage() methods to instruct the object to perform various save operations or to release its storage.

Typically, applications use helper functions such as OleLoad or OleCreate, rather than calling the IPersistStorage::Load() or IPersistStorage::InitNew() methods directly. Similarly, applications typically call the OleSave helper function rather than calling IPersistStorage::Save() directly.

Table 15-17:  IPersistStorage Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-18:  IPersist Methods

IPersist() Method Description
GetClassID() Returns the class identifier (CLSID) for the object on which it is implemented.

Table 15-19:  IPersistStorage Methods

IPersistStorage() Methods Description
IsDirty Indicates whether the object has changed since it was last saved to its current storage.
InitNew() Initializes a new storage object.
Load Initializes an object from its existing storage.
Save Saves an object, and any nested objects that it contains, into the specified storage object. The object enters NoScribble mode.
SaveCompleted Notifies the object that it can revert from NoScribble or HandsOff mode, in which in must not write to its storage object, to Normal mode in which it can.
HandsOffStorage Instructs the object to release all storage objects that have been passed to it by its container and to enter HandsOffAfterSave or HandsOffFromNormal mode.

See Also

IDataObject()  

IPersistStorage::HandsOffStorage()

NAME

IPersistStorage::HandsOffStorage() - Instructs the object to release all storage objects that have been passed to it by its container and to enter HandsOff mode, in which the object cannot do anything and the only operation that works is a close operation.

Synopsis

#include <objidl.h>

HRESULT HandsOffStorage(
        void );

Description

This method causes an object to release any storage objects that it is holding and to enter the HandsOff mode until a subsequent IPersistStorage::SaveCompleted() call. In HandsOff mode, the object cannot do anything and the only operation that works is a close operation.

A container application typically calls this method during a full save or low-memory full save operation to force the object to release all pointers to its current storage. In these scenarios, the HandsOffStorage call comes after a call to either OleSave or IPersistStorage::Save(), putting the object in HandsOffAfterSave mode. Calling this method is necessary so the container application can delete the current file as part of a full save, or so it can call the IRootStorage::SwitchToFile() method as part of a low-memory save.

A container application also calls this method when an object is in Normal mode to put the object in HandsOffFromNormal mode.

While the component object is in either HandsOffAfterSave or HandsOffFromNormal mode, most operations on the object will fail. Thus, the container should restore the object to Normal mode as soon as possible. The container application does this by calling the IPersistStorage::SaveCompleted() method, which passes a storage pointer back to the component object for the new storage object.

Notes to Implementers

This method must release all pointers to the current storage object, including pointers to any nested streams and storages. If the object contains nested objects, the container application must recursively call this method for any nested objects that are loaded or running.

Return Values

S_OK

The object has successfully entered HandsOff mode.

See Also

IPersistStorage::Save(), IPersistStorage::SaveCompleted(), IRootStorage::SwitchToFile()  

IPersistStorage::InitNew()

NAME

IPersistStorage::InitNew() - Initializes a new object, providing a pointer to the storage to be used for the object.

Synopsis

#include <objidl.h>

HRESULT InitNew((
        IStorage * pStg );

Description

A container application can call this method when it needs to initialize a new object, for example, with an InsertObject command.

An object that supports the IPersistStorage() interface must have access to a valid storage object at all times while it is running. This includes the time just after the object has been created but before it has been made persistent. The object's container must provide the object with a valid IStorage() pointer to the storage during this time through the call to IPersistStorage::InitNew(). Depending on the container's state, a temporary file might have to be created for this purpose.

If the object wants to retain the IStorage() instance, it must call IUnknown::AddRef() to increment its reference count.

After the call to IPersistStorage::InitNew(), the object is in either the loaded or running state. For example, if the object class has an in-process server, the object will be in the running state. However, if the object uses the default handler, the container's call to InitNew() only invokes the handler's implementation which does not run the object. Later if the container runs the object, the handler calls the IPersistStorage::InitNew() method for the object.

Notes to Callers

Rather than calling IPersistStorage::InitNew() directly, you typically call the OleCreate helper function which does the following:

  1. Calls the CoCreateInstance() function to create an instance of the object class

  2. Queries the new instance for the IPersistStorage() interface

  3. Calls the IPersistStorage::InitNew() method to initialize the object

The container application should cache the IPersistStorage() pointer to the object for use in later operations on the object.

Notes to Implementers

An implementation of IPersistStorage::InitNew() should initialize the object to its default state, taking the following steps:

  1. Pre-open and cache the pointers to any streams or storages that the object will need to save itself to this storage.

  2. Call IPersistStorage::AddRef() and cache the storage pointer that is passed in.

  3. Call the WriteFmtUserTypeStg() function to write the native clipboard format and user type string for the object to the storage object.

  4. Set the dirty flag for the object.

The first two steps are particularly important for ensuring that the object can save itself in low memory situations. Pre-opening and holding onto pointers to the stream and storage interfaces guarantee that a save operation to this storage will not fail due to insufficient memory.

Your implementation of this method should return the CO_E_ALREADYINITIALIZED error code if it receives a call to either the IPersistStorage::InitNew() method or the IPersistStorage::Load() method after it is already initialized.

Parameters

pStg

[in]IStorage pointer to the new storage object to be initialized. The container creates a nested storage object in its storage object (see IStorage::CreateStorage()). Then, the container calls the WriteClassStg() function to initialize the new storage object with the object class identifier (CLSID).

Return Values

S_OK

The new storage object was successfully initialized.

CO_E_ALREADYINITIALIZED

The object has already been initialized by a previous call to either the IPersistStorage::Load() method or the IPersistStorage::InitNew() method.

E_OUTOFMEMORY

The storage object was not initialized due to a lack of memory.

E_FAIL

The storage object was not initialized for some reason other than a lack of memory.

See Also

IPersistStorage::Load(), WriteFmtUserTypeStg()  

IPersistStorage::IsDirty()

NAME

IPersistStorage::IsDirty() - Indicates whether the object has changed since it was last saved to its current storage.

Synopsis

#include <objidl.h>

HRESULT IsDirty(
        void );

Description

This method checks whether an object has changed since it was last saved so you can save it before closing it. The dirty flag for an object is conditionally cleared in the IPersistStorage::Save() method.

For example, you could optimize a File:Save operation by calling the IPersistStorage::IsDirty() method for each object and then calling the IPersistStorage::Save() method only for those objects that are dirty.

Notes to Callers

You should treat any error return codes as an indication that the object has changed. In other words, unless this method explicitly returns S_FALSE, you must assume that the object needs to be saved.

Notes to Implementers

A container with one or more contained objects must maintain an internal dirty flag that is set whenever any of its contained objects are dirty.

Return Values

S_OK

The object has changed since it was last saved.

S_FALSE

The object has not changed since the last save.

See Also

IAdviseSink::OnDataChange(), IDataObject::DAdvise(), IPersistStorage::Save()  

IPersistStorage::Load()

NAME

IPersistStorage::Load() - Loads an object from its existing storage.

Synopsis

#include <objidl.h>

HRESULT Load(
        IStorage * pStg );

Description

This method initializes an object from an existing storage. The object is placed in the loaded state if this method is called by the container application. If called by the default handler, this method places the object in the running state.

Either the default handler or the object itself can hold onto the IStorage() pointer while the object is loaded or running.

Notes to Callers

Rather than calling IPersistStorage::Load() directly, you typically call the OleLoad helper function which does the following:

  1. Create an uninitialized instance of the object class

  2. Query the new instance for the IPersistStorage() interface

  3. Call IPersistStorage::Load() to initialize the object from the existing storage

You also call this method indirectly when you call the OleCreateFromData function or the OleCreateFromFile function to insert an object into a compound file (as in a drag-and-drop or clipboard paste operation).

The container should cache the IPersistStorage() pointer for use in later operations on the object.

Notes to Implementers

Your implementation should perform the following steps to load an object:

  1. Open the object's streams in the storage object, and read the necessary data into the object's internal data structures.

  2. Clear the object's dirty flag.

  3. Call the IPersistStorage::AddRef() method and cache the passed in storage pointer.

  4. Keep open and cache the pointers to any streams or storages that the object will need to save itself to this storage.

  5. Perform any other default initialization required for the object.

Steps 3 and 4 are particularly important for ensuring that the object can save itself in low memory situations. Holding onto pointers to the storage and stream interfaces guarantees that a save operation to this storage will not fail due to insufficient memory.

Your implementation of this method should return the CO_E_ALREADYINITIALIZED error code if it receives a call to either the IPersistStorage::InitNew() method or the IPersistStorage::Load() method after it is already initialized.

Parameters

pStg

[in] IStorage pointer to the existing storage from which the object is to be loaded.

Return Values

S_OK

The object was successfully loaded.

CO_E_ALREADYINITIALIZED

The object has already been initialized by a previous call to the IPersistStorage::Load() method or the IPersistStorage::InitNew() method.

E_OUTOFMEMORY

The object was not loaded due to lack of memory.

E_FAIL

The object was not loaded due to some reason besides a lack of memory.

See Also

GetConvertStg(), IPersistStorage::InitNew(), ReadFmtUserTypeStg(), SetConvertStg(), WriteFmtUserTypeStg()  

IPersistStorage::Save()

NAME

IPersistStorage::Save() - Saves an object, and any nested objects that it contains, into the specified storage. The object is placed in NoScribble mode, and it must not write to the specified storage until it receives a call to its IPersistStorage::SaveCompleted() method.

Synopsis

#include <objidl.h>

HRESULT Save(
        IStorage * pStgSave,
        BOOL fSameAsLoad );

Description

This method saves an object, and any nested objects it contains, into the specified storage. It also places the object into NoScribble mode. Thus, the object cannot write to its storage until a subsequent call to the IPersistStorage::SaveCompleted() method returns the object to Normal mode.

If the storage object is the same as the one it was loaded or created from, the save operation may be able to write incremental changes to the storage object. Otherwise, a full save must be done.

This method recursively calls the IPersistStorage::Save() method, the OleSave function, or the IStorage::CopyTo() method to save its nested objects.

This method does not call the IStorage::Commit() method. Nor does it write the CLSID to the storage object. Both of these tasks are the responsibilities of the caller.

Notes to Callers

Rather than calling IPersistStorage::Save() directly, you typically call the OleSave helper function which performs the following steps:

  1. Call the WriteClassStg() function to write the class identifier for the object to the storage.

  2. Call the IPersistStorage::Save() method.

  3. If needed, call the IStorage::Commit() method on the storage object.

Then, a container application performs any other operations necessary to complete the save and calls the SaveCompleted method for each object.

If an embedded object passes the IPersistStorage::Save() method to its nested objects, it must receive a call to its IPersistStorage::SaveCompleted() method before calling this method for its nested objects.

Parameters

pStgSave

[in]IStorage pointer to the storage into which the object is to be saved.

fSameAsLoad

[in]Indicates whether the specified storage is the current one, which was passed to the object by one of the following calls:

This parameter is set to FALSE when performing a ``Save As'' or ``Save A Copy To'' operation or when performing a full save. In the latter case, this method saves to a temporary file, deletes the original file, and renames the temporary file.

This parameter is set to TRUE to perform a full save in a low-memory situation or to perform a fast incremental save in which only the dirty components are saved.

Return Values

S_OK

The object was successfully saved.

STG_E_MEDIUMFULL

The object was not saved because of a lack of space on the disk.

E_FAIL

The object could not be saved due to errors other than a lack of disk space.

See Also

IPersistStorage::InitNew(), IPersistStorage::Load(), IPersistStorage::SaveCompleted(), IStorage::Commit(), IStorage::CopyTo(), WriteClassStg(), WriteFmtUserTypeStg()  

IPersistStorage::SaveCompleted()

NAME

IPersistStorage::SaveCompleted() - Notifies the object that it can revert from NoScribble or HandsOff mode, in which it must not write to its storage object, to Normal mode, in which it can. The object enters NoScribble mode when it receives an IPersistStorage::Save() call.

Synopsis

#include <objidl.h>

HRESULT SaveCompleted(
        IStorage * pStgNew );

Description

This method notifies an object that it can revert to Normal mode and can once again write to its storage object. The object exits NoScribble mode or HandsOff mode.

If the object is reverting from HandsOff mode, the pStgNew parameter must be non-NULL. In HandsOffFromNormal mode, this parameter is the new storage object that replaces the one that was revoked by the IPersistStorage::HandsOffStorage() method. The data in the storage object is a copy of the data from the revoked storage object. In HandsOffAfterSave mode, the data is the same as the data that was most recently saved. It is not the same as the data in the revoked storage object.

If the object is reverting from NoScribble mode, the pStgNew parameter can be NULL or non-NULL. If NULL, the object once again has access to its storage object. If it is not NULL, the component object should simulate receiving a call to its IPersistStorage::HandsOffStorage() method. If the component object cannot simulate this call, its container must be prepared to actually call the IPersistStorage::HandsOffStorage() method.

The IPersistStorage::SaveCompleted() method must recursively call any nested objects that are loaded or running.

If this method returns an error code, the object is not returned to Normal mode. Thus, the container object can attempt different save strategies.

Parameters

pStgNew

[in]IStorage pointer to the new storage object, if different from the storage object prior to saving. This pointer can be NULL if the current storage object does not change during the save operation. If the object is in HandsOff mode, this parameter must be non-NULL.

Return Values

S_OK

The object was successfully returned to Normal mode.

E_OUTOFMEMORY

The object remained in HandsOff mode or NoScribble mode due to a lack of memory. Typically, this error occurs when the object is not able to open the necessary streams and storage objects in pStgNew.

E_INVALIDARG

The pStgNew parameter is not valid. Typically, this error occurs if pStgNew is NULL when the object is in HandsOff mode.

E_UNEXPECTED

The object is in Normal mode, and there was no previous call to IPersistStorage::Save() or IPersistStorage::HandsOffStorage().

See Also

IAdviseSink::OnSave(), IPersistStorage::HandsOffStorage(), IPersistStorage::Save(), IRootStorage::SwitchToFile()

15.6.14    IPersistStream

The IPersistStream() interface provides methods for saving and loading objects that use a simple serial stream for their storage needs. The IPersistStream() interface inherits its definition from the IPersist() interface, and so the includes the GetClassID() method of IPersist().

One way in which it is used is to support COM moniker implementations. Each of the COM-provided moniker interfaces provides an IPersistStream() implementation through which the moniker saves or loads itself. An instance of the COM generic composite moniker class calls the IPersistStream() methods of its component monikers to load or save the components in the proper sequence in a single stream.

COM containers with embedded and linked component objects do not use this interface; they use the IPersistStorage() interface instead.

When to Implement

Implement the IPersistStream() interface on objects that are to be saved to a simple stream. Some objects of this type are monikers and some COM controls, although generally, controls use the IPersistStreamInit() interface, which has the same methods as IPersistStream(), with one added method, IPersistStreamInit::InitNew(). The IMoniker() interface is derived from the IPersistStream() interface, so you must implement the IPersistStream() interface if you are implementing a new moniker class.

When to Use

Call methods of IPersistStream() from a container application to save or load objects that are contained in a simple stream. When used to save or load monikers, typical applications do not call the methods directly, but allow the default link handler to make the calls to save and load the monikers that identify the link source. These monikers are stored in a stream in the storage for the linked object. If you are writing a custom link handler for your class of objects, you would call the methods of IPersistStream() to implement the link handler.

Table 15-20:  IPersistStream Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-21:  IPersist Methods

IPersist() Method Description
GetClassID() Returns the class identifier (CLSID) for the component object.

Table 15-22:  IPersistStream Methods

IPersistStream() Methods Description
IsDirty Checks the object for changes since it was last saved.
Load Initializes an object from the stream where it was previously saved.
Save Saves an object into the specified stream and indicates whether the object should reset its dirty flag.
GetSizeMax Return the size in bytes of the stream needed to save the object.

See Also

IMoniker()  

IPersistStream::GetSizeMax()

NAME

IPersistStream::GetSizeMax() - Returns the size in bytes of the stream needed to save the object.

Synopsis

#include <objidl.h>

HRESULT GetSizeMax(
        ULARGE_INTEGER * pcbSize );

Description

This method returns the size needed to save an object. You can call this method to determine the size and set the necessary buffers before calling the IPersistStream::Save() method.

Notes to Implementers

The GetSizeMax implementation should return a conservative estimate of the necessary size because the caller might call the IPersistStream::Save() method with a non-growable stream.

Parameters

pcbSize

[out] Points to a 64-bit unsigned integer value indicating the size in bytes of the stream needed to save this object.

Return Values

S_OK

The size was successfully returned.

See Also

IPersistStream::Save()  

IPersistStream::IsDirty()

NAME

IPersistStream::IsDirty() - Checks the object for changes since it was last saved.

Synopsis

#include <objidl.h>

HRESULT IsDirty(
        void );

Description

This method checks whether an object has changed since it was last saved so you can avoid losing information in objects that have not yet been saved. The dirty flag for an object is conditionally cleared in the IPersistStream::Save() method.

Notes to Callers

You should treat any error return codes as an indication that the object has changed. In other words, unless this method explicitly returns S_FALSE, you must assume that the object needs to be saved.

Note that the COM-provided implementations of the IPersistStream::IsDirty() method in the COM-provided moniker interfaces always return S_FALSE because their internal state never changes.

Return Values

S_OK

The object has changed since it was last saved.

S_FALSE

The object has not changed since the last save.

See Also

IPersistStream::Save()  

IPersistStream::Load()

NAME

IPersistStream::Load() - Initializes an object from the stream where it was previously saved.

Synopsis

#include <objidl.h>

HRESULT Load(
        IStream * pStm );

Description

This method loads an object from its associated stream. The seek pointer is set as it was in the most recent IPersistStream::Save() method. This method can seek and read from the stream, but cannot write to it.

On exit, the seek pointer must be in the same position it was in on entry, immediately past the end of the data.

Notes to Callers

Rather than calling IPersistStream::Load() directly, you typically call the OleLoadFromStream function does the following:

  1. Calls the ReadClassStm() function to get the class identifier from the stream.

  2. Calls the CoCreateInstance() function to create an instance of the object.

  3. Queries the instance for IPersistStream().

  4. Calls IPersistStream::Load().

The OleLoadFromStream function assumes that objects are stored in the stream with a class identifier followed by the object data. This storage pattern is used by the generic, composite-moniker implementation provided by COM.

If the objects are not stored using this pattern, you must call the methods separately yourself.

Parameters

pStm

[in] IStream pointer to the stream from which the object should be loaded.

Return Values

S_OK

The object was successfully loaded.

E_OUTOFMEMORY

The object was not loaded due to a lack of memory.

E_FAIL

The object was not loaded due to some reason other than a lack of memory.

See Also

CoCreateInstance(), ReadClassStm()  

IPersistStream::Save()

NAME

IPersistStream::Save() - Saves an object to the specified stream.

Synopsis

#include <objidl.h>

HRESULT Save(
        IStream * pStm,
        BOOL fClearDirty );

Description

IPersistStream::Save() saves an object into the specified stream and indicates whether the object should reset its dirty flag.

The seek pointer is positioned at the location in the stream at which the object should begin writing its data. The object calls the IStream::Write() method to write its data.

On exit, the seek pointer must be positioned immediately past the object data. The position of the seek pointer is undefined if an error returns.

Notes to Callers

Rather than calling IPersistStream::Save() directly, you typically call the OleSaveToStream helper function which does the following:

  1. Calls IPersistStream::GetClassID() to get the object's CLSID.

  2. Calls the WriteClassStm() function to write the object's CLSID to the stream.

  3. Calls IPersistStream::Save().

If you call these methods directly, you can write other data into the stream after the CLSID before calling IPersistStream::Save().

The COM-provided implementation of IPersistStream() follows this same pattern.

Notes to Implementers

The IPersistStream::Save() method does not write the CLSID to the stream. The caller is responsible for writing the CLSID.

The IPersistStream::Save() method can read from, write to, and seek in the stream; but it must not seek to a location in the stream before that of the seek pointer on entry.

Parameters

pStm

[in] IStream pointer to the stream into which the object should be saved.

fClearDirty

[in] Indicates whether to clear the dirty flag after the save is complete. If TRUE, the flag should be cleared. If FALSE, the flag should be left unchanged.

Return Values

S_OK

The object was successfully saved to the stream.

STG_E_CANTSAVE

The object could not save itself to the stream. This error could indicate, for example, that the object contains another object that is not serializable to a stream or that an IStream::Write() call returned STG_E_CANTSAVE.

STG_E_MEDIUMFULL

The object could not be saved because there is no space left on the storage device.

See Also

IPersist::GetClassID(), IStream::Write()

15.6.15    IPersistStreamInit

The IPersistStreamInit() interface is defined as a replacement for IPersistStream() in order to add an initialization method, InitNew(). This interface is not derived from IPersistStream(); it is mutually exclusive with IPersistStream(). An object chooses to support only one of the two interfaces, based on whether it requires the InitNew() method. Otherwise, the signatures and semantics of the other methods are the same as the corresponding methods of IPersistStream(), except as described below.

When to Implement

Implement this interface on any object that needs to support initialized stream-based persistence, regardless of whatever else the object does. The presence of the InitNew() method requires some changes to other methods that are common to IPersistStream(), as noted in the method descriptions.

When to Use

Use this interface to initialize a stream-based object and to save that object to a stream.

Table 15-23:  IPersistStreamInit Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-24:  IPersistStreamInit Methods

IPersistStreamInit() Methods Description
IsDirty Checks the object for changes since it was last saved.
Load Initializes an object from the stream where it was previously saved.
Save Saves an object into the specified stream and indicates whether the object should reset its dirty flag.
GetSizeMax Return the size in bytes of the stream needed to save the object.
InitNew() Initializes an object to a default state.

See Also

IPersistStream()  

IPersistStreamInit::GetSizeMax()

NAME

IPersistStreamInit::GetSizeMax() - Same as IPersistStream::GetSizeMax().

Synopsis

#include <ocidl.h>

HRESULT GetSizeMax(
        ULARGE_INTEGER * pcbSize );

 

IPersistStreamInit::InitNew()

NAME

IPersistStreamInit::InitNew() - Initializes the object to a default state. This method is called instead of IPersistStreamInit::Load().

Synopsis

#include <ocidl.h>

HRESULT InitNew((
        void );

Description

Notes to Implementers

If the object has already been initialized with Load, then this method must return E_UNEXPECTED.

Return Values

This method supports the standard return values E_OUTOFMEMORY and E_UNEXPECTED, as well as the following:

S_OK

The object successfully initialized itself.

E_NOTIMPL

The object requires no default initialization. This error code is allowed because an object may choose to implement IPersistStreamInit() simply for orthogonality or in anticipation of a future need for this method.

See Also

IPersistStreamInit::Load()  

IPersistStreamInit::IsDirty()

NAME

IPersistStreamInit::IsDirty() - Same as IPersistStream::IsDirty().

Synopsis

#include <ocidl.h>

HRESULT IsDirty(
        void );

 

IPersistStreamInit::Load()

NAME

IPersistStreamInit::Load() - Same as IPersistStream::Load().

Synopsis

#include <ocidl.h>

HRESULT Load(
        LPSTREAM pStm );

Notes to Implementers

If the object has already been initialized with InitNew(), then this method must return E_UNEXPECTED.  

IPersistStreamInit::Save()

NAME

IPersistStreamInit::Save() - Same as IPersistStream::Save().

Synopsis

#include <ocidl.h>

HRESULT Save(
        LPSTREAM pStm ,
        BOOL fClearDirty );

15.6.16    IPropertyBag

The IPropertyBag() interface provides an object with a property bag in which the object can persistently save its properties.

When a client wishes to have exact control over how individually named properties of an object are saved, it would attempt to use an object's IPersistPropertyBag() interface as a persistence mechanism. In that case the client supplies a property bag to the object in the form of an IPropertyBag() interface.

When the object wishes to read a property in IPersistPropertyBag::Load() it will call IPropertyBag::Read(). When the object is saving properties in IPersistPropertyBag::Save() it will call IPropertyBag::Write(). Each property is described with a name in pszPropName whose value is exchanged in a VARIANT. This information allows a client to save the property values as text, for instance, which is the primary reason why a client might choose to support IPersistPropertyBag().

The client records errors that occur during reading into the supplied error log.

When to Implement

A container implements this interface to provide its object with a way to store their properties persistently.

When to Use

An object calls the methods on this interface to read and write its properties into the container provided property bag.

Table 15-25:  IPropertyBag Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-26:  IPropertyBag Methods

IPropertyBag() Methods Description
Read Called by the control to read a property from the storage provided by the container.
Write Called by the control to write each property in turn to the storage provided by the container.

See Also

IErrorLog(), IPersistPropertyBag()  

IPropertyBag::Read()

NAME

IPropertyBag::Read() - Called by the control to read a property from the storage provided by the container.

Synopsis

#include <ocidl.h>

HRESULT Read(
        LPCOLESTR pszPropName,
        VARIANT * pVar,
        IErrorLog * pErrorLog );

Description

This method asks the property bag to read the property named with pszPropName into the caller-initialized VARIANT in pVar. Errors that occur are logged in the error log pointed to by pErrorLog.

When pVar->vt specifies another object pointer (VT_UNKNOWN or VT_DISPATCH) then the property bag is responsible for creating and initializing the object described by pszPropName. The action taken by the property bag depends on the value of pvar->punkVal or pvar->vdispVal. For example, if pvar->punkVal is non-NULL, the property bag initializes the existing object using the value of the pointer, usually querying for a persistence interface and calling the Load method. However, if pVar->punkVal is NULL, then the property bag creates a new object and loads it as appropriate.

E_NOTIMPL is not a valid return code since any object implementing this interface must support the entire functionality of the interface.

Parameters

pszPropName

[in] Pointer to the name of the property to read. Cannot be NULL.

pVar

[in, out] Pointer to the caller-initialized VARIANT that is to receive the property value on output. The method must set both type and value fields in the VARIANT before returning. If the caller initialized the pVar->vt field on entry, the property bag should attempt to coerce the value it knows into this type. If the caller sets pVar->vt to VT_EMPTY, the property bag can use a convenient type that is consistent with the data. For example, if the property is a string, the property bag cannot use VT_I4.

pErrorLog

[in] Pointer to the caller's IErrorLog() interface in which the property bag stores any errors that occur during reads. Can be NULL in which case the caller is not interested in errors.

Return Values

S_OK

The property was read successfully. The caller becomes responsible for any allocations that are contained in the VARIANT in pVar.

E_POINTER

The address in pszPropName is not valid (such as NULL).

E_INVALIDARG

The property named with pszPropName does not exist in the property bag.

E_FAIL

The property bag was unable to read the specified property, such as if the caller specified a data type to which the property bag could not coerce the known value. If the caller supplied an error log, a more descriptive error was sent there.

See Also

IPropertyBag::Write()  

IPropertyBag::Write()

NAME

IPropertyBag::Write() - Called by the control to write each property in turn to the storage provided by the container.

Synopsis

#include <ocidl.h>

HRESULT Write(
        LPCOLESTR pszPropName,
        VARIANT * pVar );

Description

This method asks the property bag to save the property named with pszPropName using the type and value in the caller-initialized VARIANT in pVar. In some cases the caller may be asking the property bag to save another object, that is, when pVar->vt is VT_UNKNOWN. In such cases, the property bag queries this object pointer for some persistence interface, like IPersistStream() or even IPersistPropertyBag() again and has that object save its data as well. Usually, this results in the property bag having some byte array for this object which can be saved as encoded text (hex string, MIME, etc.). When the property bag is later used to reinitialize a control, the client that owns the property bag must recreate the object when the caller asks for it, initializing that object with the previously saved bits.

This allows very efficient persistence operations for large BLOB properties like a picture, where the owner of the property bag itself directly asks the picture object (managed as a property in the control being saved) to save into a specific location. This avoids potential extra copy operations that would be involved with other property-based persistence mechanisms.

E_NOTIMPL is not a valid return code as any object implementing this interface must support the entire functionality of the interface.

Parameters

pszPropName

[in] Pointer to the name of the property to write. Cannot be NULL.

pVar

[in] Pointer to the caller-initialized VARIANT that holds the property value to save. The caller owns this VARIANT and is responsible for all allocations therein. That is, the property bag itself does not attempt to free data in the VARIANT.

Return Values

S_OK

The property bag successfully saved the requested property.

E_FAIL

There was a problem writing the property. It is possible that the property bag does not understand how to save a particular VARIANT type.

E_POINTER

The address in pszPropName or pVar is not valid (such as NULL). The caller must supply both.

See Also

IPropertyBag::Read()

15.6.17    IPropertySetStorage

Creates, opens, deletes, and enumerates property set storages that support instances of the IPropertyStorage() interface. The IPropertyStorage() interface manages a single property set in a property storage subobject; the IPropertySetStorage() interface manages the storage of groups of such property sets. IPropertySetStorage() can be supported by any file system entity, and is currently implemented in the COM compound file object.

The IPropertySetStorage() and IPropertyStorage() interfaces provide a uniform way to create and manage property sets, whether or not these sets reside in a storage object that supports IStorage(). When called through an object supporting IStorage() (such as structured and compound files and directories) or IStream(), the property sets created conform to the COM property set format. Similarly, properties written using IStorage() to the COM property set format are visible through IPropertySetStorage() and IPropertyStorage(). IPropertyStorage() does not support extensions to the COM serialized property set format or multiple sections, because you can get equivalent functionality as simply by creating new sets or by adding new properties to existing property sets.

IPropertySetStorage() methods identify property sets through a GUID called a format identifier (FMTID). The FMTID for a property set identifies the set of property identifiers in the property set, their meaning, and any constraints on the values. The format identifier of a property set should also provide the means to manipulate that property set. Only one instance of a given FMTID may exist at a time within a single property storage.

When to Implement

Implement IPropertySetStorage() to store persistent properties in the file system. If you are using the COM compound files implementation, you can use the implementation on the compound file object created through a call to StgCreateDocfile() or StgOpenStorage(). Once you have a pointer to any of the interface implementations (such as IStorage()) on this object, you can call QueryInterface() to get a pointer to the IPropertySetStorage() interface implementation.

When to Use

Call IPropertySetStorage() methods to create, open, or delete one or more property sets, or to enumerate the property sets contained in this property set storage.

Table 15-27:  IPropertySetStorage Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-28:  IPropertySetStorage Methods

IPropertySetStorage() Methods Description
Create Creates a new property set.
Open Opens a previously created property set.
Delete Deletes an existing property set.
Enum Creates and retrieves a pointer to an object that can be used to enumerate property sets.

See Also

IPropertyStorage(), IEnumSTATPROPSETSTG, STATPROPSETSTG, PROPVARIANT  

IPropertySetStorage::Create()

NAME

IPropertySetStorage::Create() - Creates and opens a new property set in the property set storage object.

Synopsis

#include <objidl.h>

HRESULT Create(
        REFFMTID fmtid,
        CLSID * pclsid,
        DWORD grfFlags,
        DWORD grfMode,
        IPropertyStorage ** ppPropStg );

Description

IPropertySetStorage::Create() creates and opens a new property set sub-object (supporting the IPropertyStorage() interface) contained in this property set storage object. The property set automatically contains code page and locale ID properties. These are set to the current system default, and the current user default, respectively.

The grfFlags parameter is a combination of values taken from the enumeration PROPSETFLAG.

The grfMode parameter specifies the access mode in which the newly created set is to be opened. Values for this parameter are as in the like-named parameter to IPropertySetStorage::Open, with the addition of the following values:

1.  grfMode Values

Value Meaning
STGM_FAILIFTHERE If another property set with the specified fmtid already exists, the call fails. This is the default action; that is, unless STGM_CREATE is specified, STGM_FAILIFTHERE is implied.
STGM_CREATE If another property set with the specified fmtid already exists, it is removed and replaced with this new one.
STGM_DIRECT Open the property set without an additional level of transaction nesting. This is the default (the behavior if neither STGM_DIRECT nor STGM_TRANSACTED is specified).
STGM_TRANSACTED Open the property set with an additional level of transaction nesting (beyond the transaction, if any, on this property set storage). This is possible only when you specify PROPSETFLAG_NONSIMPLE in the grfFlags parameter. Changes in the property set must be committed with IPropertyStorage::Commit() before they are visible to the transaction on this property set storage.
STGM_READ Read access is desired on the property set. Read permission is required on the property set storage.
STGM_WRITE Write access is desired on the property set. Write permission is not required on the property set storage; however, such write permission is required for changes in the storage to be committed.
STGM_READWRITE Read-write access is desired on the property set. Note that this flag is not the binary OR of the values STGM_READ and STGM_WRITE.
STGM_SHARE_EXCLUSIVE Prevents others from subsequently opening the property set either in STGM_READ or STGM_WRITE mode.

The only access mode supported by Create is STGM_SHARE_EXCLUSIVE. To use the resulting property set in an access mode other than STGM_SHARE_EXCLUSIVE, the caller should close the stream and then re-open it with a call to IPropertySetStorage::Open().

Parameters

fmtid

[in] Format identifier of the property set to be created.

pclsid

[in] Pointer to the initial CLSID for this property set. May be NULL, in which case it is set to all zeroes.

grfFlags

[in] Values from the PROPSETFLAG enumeration.

grfMode

[in] Access mode in which the newly created property set is to be opened, taken from certain values of the STGM enumeration, as described in the Remarks.

ppPropStg

[out] Indirect pointer to the IPropertyStorage() interface on the new property storage sub-object.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The property set was created.

STG_E_FILEALREADYEXISTS

A property set of the indicated name already exists, and STGM_CREATE was not specified.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

A parameter is invalid.

See Also

IPropertySetStorage::Open()  

IPropertySetStorage::Delete()

NAME

IPropertySetStorage::Delete() - Deletes one of the property sets contained in the property set storage object.

Synopsis

#include <objidl.h>

HRESULT Delete(
        REFFMTID fmtid );

Description

IPropertySetStorage::Delete() deletes the property set specified by its format identifier. Specifying a property set that does not exist returns an error. Open substorages and streams(opened through one of the storage- or stream-valued properties) are put into the reverted state.

Parameters

fmtid

[in] Format identifier of the property set to be deleted.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The property set was successfully deleted.

STG_E_FILENOTFOUND

The specified property set does not exist.

STG_E_ACCESSDENIED

The requested access to the property set storage object has been denied.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

The parameter is invalid.

 

IPropertySetStorage::Enum()

NAME

IPropertySetStorage::Enum() - Creates an enumerator object which contains information on the property sets stored in this property set storage. On return, this method supplies a pointer to the IEnumSTATPROPSETSTG() pointer on the enumerator object.

Synopsis

#include <objidl.h>

HRESULT Enum(
        IEnumSTATPROPSETSTG ** ppenum );

Description

IPropertySetStorage::Enum() creates an enumerator object that can be used to iterate through STATPROPSETSTG structures. These sometimes provide information on the property sets managed by IPropertySetStorage(). This method, on return, supplies a pointer to the IEnumSTATPROPSETSTG() interface on this enumerator object on return.

Parameters

ppenum

[out] Indirect pointer to the IEnumSTATPROPSETSTG() on the newly created enumeration object.

Return Values

S_OK

The enumerator object was successfully created.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

See Also

IEnumSTATPROPSETSTG(), IEnumSTATPROPSETSTG--Compound File Implementation  

IPropertySetStorage::Open()

NAME

IPropertySetStorage::Open() - Opens a property set contained in the property set storage object.

Synopsis

#include <objidl.h>

HRESULT Open(
        REFFMTID fmtid,
        DWORD grfMode,
        IPropertyStorage ** ppPropStg );

Description

The mode in which the property set is to be opened is specified in the parameter grfMode. These flags are taken from the STGM enumeration, but, for this method, legal values and their meanings are as follows (only certain combinations of these flag values are legal).

1.  IPropertySetStorage::Open grfMode Values

Value Meaning
STGM_DIRECT Open the property set without an additional level of transaction nesting. This is the default (the behavior if neither STGM_DIRECT nor STGM_TRANSACTED is specified).
STGM_TRANSACTED Open the property set with an additional level of transaction nesting (beyond the transaction, if any, on this property set storage object). Transacted mode is available only on non-simple property sets, because they use an IStorage() with a contents stream. Changes in the property set must be committed with a call to IPropertyStorage::Commit() before they are visible to the transaction on this property set storage.
STGM_READ Open the property set with read access. Read permission is required on the property set storage.
STGM_WRITE Open the property set with write access. Write permission is not required on the IPropertySetStorage(); however, such write permission is required for changes in the storage to be committed.
STGM_READWRITE Open the property set with read-write access. Note that this flag is not the binary OR of the values STGM_READ and STGM_WRITE.
STGM_SHARE_DENY_NONE Subsequent openings of the property set are not denied read or write access. Not available in compound file implementation.
STGM_SHARE_DENY_READ Subsequent openings of the property set in are denied read access. Not available in compound file implementation.
STGM_SHARE_DENY_WRITE Subsequent openings of the property set are denied write access. This value is typically used to prevent making unnecessary copies of an object opened by multiple users. If this value is not specified, a snapshot is made, whether there are subsequent openings or not. Thus, you can improve performance by specifying this value. Not available in compound file implementation.
STGM_SHARE_EXCLUSIVE The combination of STGM_SHARE_DENY_READ and STGM_SHARE_DENY_WRITE.

Parameters

fmtid

[in] Format identifier of the property set to be opened.

grfMode

[in] Access mode in which the newly created property set is to be opened. These flags are taken from the STGM enumeration. Flags that may be used and their meanings in the context of this method are described in the Remarks.

ppPropStg

[in] Indirect pointer to the IPropertyStorage() interface on the requested property storage sub-object.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

Success.

STG_E_FILENOTFOUND

A property set of the indicated name does not exist.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied, or the property set is corrupted.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

A parameter is invalid.

15.6.18    IPropertySetStorage-Compound File Implementation

The COM compound file storage object implementation includes 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 IPropertySetStorage(), 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 IStorage::QueryInterface() for the IPropertySetStorage() interface, specifying the header-defined name for the interface identifier IID_IPropertySetStorage.

When to Use

Call the methods of IPropertySetStorage() to create, open, or delete property sets in the current compound file property set storage. There is also a method that supplies a pointer to an enumerator that can be used to enumerate the property sets in the storage.

Description

IPropertySetStorage::Create()

Creates a new property set in the current compound file storage and, on return, supplies an indirect pointer to the IPropertyStorage() compound file implementation. In this implementation, property sets may be transacted only if PROPSETFLAG_NONSIMPLE is specified.

IPropertySetStorage::Open()

Opens an existing property set in the current property storage. On return, it supplies an indirect pointer to the compound file implementation of IPropertyStorage().

IPropertySetStorage::Delete()

Deletes a property set in this property storage.

IPropertySetStorage::Enum()

Creates an object that can be used to enumerate STATPROPSETSTG structures. Each STATPROPSETSTG structure provides information about a single property set. The implementation calls the constructor for IEnumSTATPROPSETSTG(), which, in turn, uses the pointer to the IStorage() interface to create a STATSTG enumerator, which is then used over the actual storage to get the information about the property sets.

Notes

The DocumentSummaryInformation property set is special, in that it may have two property set sections. The second section is referred to as the User-Defined Properties. Each section is identified with a unique Format ID, for example FMTID_DocumentSummaryInformation and FMTID_UserDefinedProperties.

When IPropertySetStorage::Create() is called to create the User-Defined Property Set, the first section is created automatically. Thus once FMTID_UserDefinedProperties is created, FMTID_DocumentSummaryInformation need not be created, but can be opened with a call to IPropertySetStorage::Open(). Note that creating the first section does not automatically create the second section. It is not possible to open both sections simultaneously.

When IPropertySetStorage::Create() is called to create the User-Defined Property Set, the first section is created automatically. Thus once FMTID_UserDefinedProperties is created, FMTID_DocumentSummaryInformation need not be created, but can be opened with a call to IPropertySetStorage::Open(). Note that creating the first section does not automatically create the second section. It is not possible to open both sections simultaneously.

Alternately, when IPropertySetStorage::Delete() is called to delete the first section, both sections are deleted. That is, calling IPropertySetStorage::Delete() with FMTID_DocumentSummaryInformation, causes both that section and the FMTID_UserDefinedProperties section to be deleted. Note that deleting the second section does not automatically delete the first section.

Finally, when IPropertySetStorage::Enum() is used to enumerate property sets, the User-Defined Property Set will not be enumerated.

See Also

IPropertyStorage(), IPropertySetStorage() - Compound File Implementation, STATPROPSETSTG structure, PROPSETFLAG enumeration, IStorage::EnumElements()

15.6.19    IPropertySetStorage-Standalone Implementation

The system-provided, standalone implementation of IPropertySetStorage() includes an implementation of both IPropertyStorage(), the interface that reads and writes properties in a property set storage, and IPropertySetStorage(), the interface that creates and opens property sets in a storage. The IEnumSTATPROPSTG() and IEnumSTATPROPSETSTG() interfaces are also provided in the standalone implementation.

To use the standalone implementation of IPropertySetStorage(), you first obtain a pointer to the system-provided, standalone implementation and associate the system-provided implementation with your storage object. To get a pointer to the standalone implementation of IPropertySetStorage(), call the StgCreatePropSetStg() function and provide the pStorage parameter specifying the storage object that will contain the property set. This function supplies you with a pointer to the new IPropertySetStorage() interface for the specified storage object.

The standalone implementation of IPropertySetStorage() 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 Section Section 15.6.18 for more information on the compound file implementation of this interface.

When to Use

Call the methods of IPropertySetStorage() to create, open, and delete property sets in any structured storage. There is also a method that supplies a pointer to the IEnumSTATPROPSETSTG() enumerator that can be used to enumerate the property sets in the storage.

The standalone implementation also provides the StgCreatePropStg() and the StgOpenPropStg() helper functions in addition to the Create and Open methods to create and open property sets. These two functions add support for the PROPSETFLAG_UNBUFFERED value so you can directly write changes to the property set instead of buffering them in a cache. See the PROPSETFLAG enumeration for more information on using this value.

Description

The standalone implementation of IPropertySetStorage() supports the following methods:

IPropertySetStorage::Create()

Creates a new property set in the storage and returns a pointer to the IPropertyStorage() interface on the property set.

If you plan to use the PROPSETFLAG_UNBUFFERED value, use the StgCreatePropStg() function instead to create and open the new property set and to obtain a pointer to the standalone implementation for the IPropertyStorage() interface on the property set.

IPropertySetStorage::Open()

Opens an existing property set in the storage and returns a pointer to the IPropertyStorage() interface on the property set.

If you plan to use the PROPSETFLAG_UNBUFFERED value, use the StgOpenPropStg() function instead to obtain a pointer to the standalone implementation of IPropertyStorage() on the specified property set.

IPropertySetStorage::Delete()

Deletes a property set in this property set storage.

IPropertySetStorage::Enum()

Creates an object that can be used to enumerate STATPROPSETSTG structures. Each STATPROPSETSTG structure provides information about a single property set.

Notes

The DocumentSummaryInformation property set is special, in that it may have two property set sections. The second property set is referred to as the User-Defined Properties. Each section is identified with a unique Format ID, for example FMTID_DocumentSummaryInformation and FMTID_UserDefinedProperties.

When IPropertySetStorage::Create() is called to create the User-Defined Property Set, the first section is created automatically. Thus once FMTID_UserDefinedProperties is created, FMTID_DocumentSummaryInformation need not be created, but can be opened with a call to IPropertySetStorage::Open(). Note that creating the first section does not automatically create the second section. It is not possible to open both sections simultaneously.

Alternately, when IPropertySetStorage::Delete() is called to delete the first section, both sections are deleted. That is, calling IPropertySetStorage::Delete() with FMTID_DocumentSummaryInformation, causes both that section and the FMTID_UserDefinedProperties section to be deleted. Note that deleting the second section does not automatically delete the first section.

Finally, when IPropertySetStorage::Enum() is used to enumerate property sets, the User-Defined Property Set is not enumerated.

Table 15-29:  IPropertySetStorage Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

See Also

IPropertyStorage(), IPropertySetStorage() - Compound File Implementation, IPropertyStorage-Standalone Implementation, STATPROPSETSTG, PROPSETFLAG, IStorage::EnumElements(), STGM, StgCreatePropStg(), StgOpenPropStg(), StgCreatePropSetStg()

15.6.20    IPropertyStorage

Manages the persistent properties of a single property set. Persistent properties consist of information that can be stored persistently in a property set, such as the summary information associated with a file. This contrasts with run-time properties associated with Controls and Automation, which can be used to affect system behavior. Use the methods of the IPropertySetStorage() interface to create or open a persistent property set. An IPropertySetStorage() instance can manage zero or more IPropertyStorage() instances.

Each property within a property set is identified by a property identifier, a four-byte ULONG value unique to that set. You can also assign a string name to a property through the IPropertyStorage() interface.

Property identifiers are different from the dispatch identifiers used in Automation dispid property name tags. One difference is that the general-purpose use of property identifier values zero and one is prohibited in IPropertyStorage(), while no such restriction exists in IDispatch(). In addition, while there is significant overlap in the data types for property values that may be used in IPropertyStorage() and IDispatch(), the sets are not identical. Persistent property data types used in IPropertyStorage() methods are defined in the PROPVARIANT structure.

When to Implement

Implement IPropertyStorage() when you want to store properties in the file system. If you are using the COM compound files implementation, the compound file object created through a call to StgCreateDocfile() includes an implementation of IPropertySetStorage(), which allows access to the implementation of IPropertyStorage(). Once you have a pointer to any of the interface implementations (such as IStorage()) on this object, you can call QueryInterface() to get a pointer to the IPropertySetStorage() interface implementation, and then call either the Open or Create method, as appropriate to obtain a pointer to the IPropertyStorage() interface managing the specified property set.

When to Use

Use IPropertyStorage() to create and manage properties that are stored in a given property set.

Table 15-30:  IPropertyStorage Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments reference count.
Release() Decrements reference count.

Table 15-31:  IPropertyStorage Methods

IPropertyStorage() Methods Description
ReadMultiple Reads property values in a property set.
WriteMultiple Writes property values in a property set.
DeleteMultiple Deletes properties in a property set.
ReadPropertyNames Gets corresponding string names for given property identifiers.
WritePropertyNames Creates or changes string names corresponding to given property identifiers.
DeletePropertyNames Deletes string names for given property identifiers.
SetClass Assigns a CLSID to the property set.
Commit As in IStorage::Commit(), flushes or commits changes to the property storage object.
Revert When the property storage is opened in transacted mode, discards all changes since the last commit.
Enum Creates and gets a pointer to an enumerator for properties within this set.
Stat Receives statistics about this property set.
SetTimes Sets modification, creation, and access times for the property set.

See Also

IPropertySetStorage(), IEnumSTATPROPSTG, IEnumSTATPROPSETSTG, STATPROPSTG,STATPROPSETSTG, PROPVARIANT  

IPropertyStorage::Commit()

NAME

IPropertyStorage::Commit() - Saves any changes made to a property storage object to the parent storage object.

Synopsis

#include <objidl.h>

HRESULT Commit(
        DWORD grfCommitFlags );

Description

As in IStorage::Commit(), ensures that any changes made to a property storage object are reflected in the parent storage.

In direct mode in the compound file implementation, this call causes any changes currently buffered up in memory to be flushed to the underlying property stream. In the compound file implementation for non-simple property sets, IStorage::Commit() is also called on the underlying substorage object with the passed grfCommitFlags parameter.

In transacted mode, this method causes the changes to be permanently reflected in the persistent image of the storage object. The changes that are committed must have been made to this property set since it was opened or since the last commit on this opening of the property set. One could think of the action of committing as publishing the changes that this level currently knows about one more layer outwards. Of course, this is still subject to any outer level transaction that may be present on the object in which this property set is contained. Write permission must be specified when the property set is opened (through IPropertySetStorage()) on the property set opening for the commit operation to succeed.

If the commit operation fails for any reason, the state of the property storage object is as it was before the commit.

This call has no effect on existing storage- or stream-valued properties opened from this property storage, but it does commit them.

Valid values for the grfCommitFlags parameter are as follows:

1.  Valid grfCommitFlags Values

Value Meaning
STGC_DEFAULT Commit per the usual transaction semantics. Last writer wins. This flag may not be specified with other flag values.
STGC_ONLYIFCURRENT Commit the changes only if the current persistent contents of the property set are the ones on which the changes about to be committed are based. That is, do not commit changes if the contents of the property set have been changed by a commit from another opening of the property set. The error STG_E_NOTCURRENT is returned if the commit does not succeed for this reason.
STGC_OVERWRITE Only useful when committing a transaction which has no further outer nesting level of transactioning, though legal in all cases. Indicates that the caller is willing to take some risk of data corruption at the expense of a decreased usage of disk on the destination volume. This flag is potentially useful in low disk space scenarios, though should be used only with caution.

Parameters

grfCommitFlags

[in] Flags specifying the conditions under which the commit is to be performed. Specific flags and their meanings are described in the following Remarks section.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The changes were saved successfully.

STG_E_NOTCURRENT

STGC_ONLYIFCURRENT was specified, but the optimistic concurrency control failed.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

One or more flags specified in grfCommitFlags is invalid.

See Also

IPropertyStorage::ReadMultiple(), IStorage::Commit()  

IPropertyStorage::DeleteMultiple()

NAME

IPropertyStorage::DeleteMultiple() - Deletes as many of the indicated properties as exist in this property set.

Synopsis

#include <objidl.h>

HRESULT DeleteMultiple(
        ULONG cpspec,
        PROPSPEC const rgpspec[] );

Description

IPropertyStorage::DeleteMultiple() must delete as many of the indicated properties as are in the current property set. If a deletion of a stream- or storage-valued property occurs while that property is open, the deletion will succeed and place the previously returned IStream() or IStorage() pointer in the reverted state.

Parameters

cpspec

[in] Count of properties being deleted. May legally be zero, though this is a no-op, deleting no properties.

rgpspec[]

[in] Properties to be deleted. A mixture of property identifiers and string-named properties is permitted. There may be duplicates, and there is no requirement that properties be specified in any order.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

All of the specified properties that exist in the property set have been deleted.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied. No properties were deleted.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation. Some properties may not have been deleted.

STG_E_INVALIDPARAMETER

At least one of the parameters is invalid, as when one of the PROPSPECs contains an illegal ulKind value. Some properties may not have been deleted.

STG_E_INVALIDPOINTER

May be returned when at least one of the pointers passed in is invalid. Some properties may not have been written. More frequently, an invalid pointer will instead result in an access violation.

 

IPropertyStorage::DeletePropertyNames()

NAME

IPropertyStorage::DeletePropertyNames() - Deletes specified string names from the current property set.

Synopsis

#include <objidl.h>

HRESULT DeletePropertyNames(
        ULONG cpropid,
        PROPID const rgpropid[] );

Description

For each property identifier in rgpropid, IPropertyStorage::DeletePropertyNames() removes the corresponding name-to-property identifier mapping, if any. An attempt to delete the name of a property that either does not exist or does not presently have a string name associated with it is silently ignored. This method has no effect on the properties themselves.

All the stored string property names can be deleted by deleting property identifier zero, but cpropid must be equal to 1 for this to not be an invalid parameter error.

Parameters

cpropid

[in] The size on input of the array rgpropid. If 0, no property names are deleted.

rgpropid[]

[in] Property identifiers for which string names are to be deleted.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

Success. The names of all of the indicated properties that exist in this set have been deleted.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied. No property names were deleted.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation. Some property names may not have been deleted.

STG_E_INVALIDPARAMETER

At least one of the parameters is invalid. Some property names may not have been deleted.

See Also

IPropertyStorage::ReadPropertyNames()  

IPropertyStorage::Enum()

NAME

IPropertyStorage::Enum() - Creates an enumerator object designed to enumerate data of type STATPROPSTG, which contains information on the current property set. On return, this method supplies a pointer to the IEnumSTATPROPSTG() pointer on this object.

Synopsis

#include <objidl.h>

HRESULT Enum(
        IEnumSTATPROPSTG ** ppenum );

Description

IPropertyStorage::Enum() creates an enumeration object that can be used to iterate STATPROPSTG structures. On return, this method supplies a pointer to an instance of IEnumSTATPROPSTG() interface on this objects whose methods you can call to obtain information on the current property set.

Parameters

ppenum

[out] Indirect pointer to the IEnumSTATPROPSTG() interface on the new enumeration object.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

A pointer to the enumerator has been retrieved.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

The parameter is invalid.

STG_E_READFAULT

Error reading storage.

See Also

IEnumSTATPROPSTG(), IEnumSTATPROPSTG--Compound File Implementation  

IPropertyStorage::ReadMultiple()

NAME

IPropertyStorage::ReadMultiple() - Reads specified properties from the current property set.

Synopsis

#include <objidl.h>

HRESULT ReadMultiple(
        ULONG cpspec,
        PROPSPEC const rgpspec[],
        PROPVARIANT rgvar[] );

Description

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 COM 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.

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 structures. Properties can be specified either by property identifier or by optional string name. It is not necessary to specify properties in any particular order in the array. The array can contain duplicate properties, resulting in duplicate property values on return for simple properties. Non-simple properties should return access denied on an attempt to open them a second time. The array can contain a mixture of property identifiers and string identifiers.

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 to VT_EMPTY.

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.

See Also

IPropertySetStorage(), IPropertyStorage::WriteMultiple(), IPropertyStorage::WritePropertyNames()  

IPropertyStorage::ReadPropertyNames()

NAME

IPropertyStorage::ReadPropertyNames() - Retrieves any existing string names for the specified property identifiers.

Synopsis

#include <objidl.h>

HRESULT ReadPropertyNames(
        ULONG cpropid,
        PROPID const rgpropid[],
        LPWSTR rglpwstrName[] );

Description

For each property identifier in the list of property identifiers supplied in the rgpropid array, IPropertyStorage::ReadPropertyNames() retrieves the corresponding string name, if there is one. String names are created either by specifying the names in calls to IPropertyStorage::WriteMultiple() when you are creating the property, or through a call to IPropertyStorage::WritePropertyNames(). In any case, the string name is optional; all properties must have a property identifier.

String names mapped to property identifiers must be unique within the set.

Parameters

cpropid

[in] Number of elements on input of the array rgpropid. May legally be zero, though this is a no-op, reading no property names.

rgpropid[]

[in] Array of property identifiers for which names are to be retrieved.

rglpwstrName[]

[in, out] Caller-allocated array of size cpropid of LPWSTRs. On return, the implementation fills in this array. A given entry contains either the corresponding string name of a property identifier or NULL if the property identifier has no string name.

Each LPWSTR member of the array should be freed using CoTaskMemFree().

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

One or more string names were retrieved and all members of rglpwstrName are valid (either NULL or a valid LPWSTR).

S_FALSE

No string names were retrieved because none of the requested property identifiers have string names presently associated with them in this property storage object (this result does not address whether the given property identifiers presently exist in the set).

STG_E_INVALIDHEADER

The property name dictionary was not found.

STG_E_READFAULT

Error reading the storage.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied. No string names were retrieved.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation. No string names were retrieved.

STG_E_INVALIDPARAMETER

A parameter is invalid. No string names were retrieved.

HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)

There was a failed attempt to translate a Unicode string to or from ANSI.

See Also

IPropertyStorage::WritePropertyNames(), IPropertyStorage::WriteMultiple()  

IPropertyStorage::Revert()

NAME

IPropertyStorage::Revert() - Discards all changes to the property set it was opened or changes were last committed. Has no effect on a direct-mode property set.

Synopsis

#include <objidl.h>

HRESULT Revert(
         );

Description

For transacted-mode property sets, discards all changes that have been made in this property set since set was opened or the time it was last committed (depending on which is later). After this operation, any existing storage- or stream-valued properties that have been opened from the property set being reverted are invalid and can no longer be used. The error STG_E_REVERTED will be returned on all calls except Release() using these streams or storages.

For direct-mode property sets, this request is ignored and returns S_OK.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

Success.

See Also

IPropertyStorage::Commit()  

IPropertyStorage::Stat()

NAME

IPropertyStorage::Stat() - Retrieves information about the current open property set.

Synopsis

#include <objidl.h>

HRESULT Stat(
        STATPROPSTG * pstatpsstg );

Description

IPropertyStorage::Stat() fills in and returns a pointer to a STATPROPSETSTG structure, containing statistics about the current property set. STATPROPSETSTG fields have the following meanings:

1.  Meanings of STATPROPSETSTG Fields

Field Meaning
fmtid The FMTID of this property set, specified when the property set was initially created.
clsid The CLSID of this property set, specified when the property set was initially created and possibly modified thereafter with IpropertyStorage::SetClass. If not set, the value will be CLSID_NULL.
grfFlags The flag values this set was created with. For details, see IpropertySetStorage::Create.
mtime The time in UTC (FILETIME) at which this property set was last modified. Not all IPropertyStorage() implementations maintain modification times on property sets; those who do not will return zero for this value.
ctime The time in UTC (FILETIME) at which this property set was created. Not all IPropertyStorage() implementations maintain creation times on property sets; those that do not will set this value to 0.
atime The time in UTC (FILETIME) at which this property set was last accessed. Not all IPropertyStorage() implementations maintain last access times on property sets; those that do not will set this value to 0.

Parameters

pstatpsstg

[out] Pointer to a STATPROPSETSTG structure, which contains statistics about the current open property set.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

Statistics were successfully obtained.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

The parameter is invalid.

See Also

STATPROPSETSTG structure, IPropertySetStorage::Enum(), FILETIME structure  

IPropertyStorage::SetClass()

NAME

IPropertyStorage::SetClass() - Assigns a new CLSID to the current property storage object, and persistently stores the CLSID with the object.

Synopsis

#include <objidl.h>

HRESULT SetClass(
        REFCLSID clsid );

Description

Assigns a CLSID to the current property storage object. The CLSID has no relationship to the stored property identifiers. Assigning a CLSID allows a piece of code to be associated with a given instance of a property set; such code, for example, might manage the user interface. Different CLSIDs can be associated with different property set instances that have the same FMTID.

If the property set is created with NULL specified as the IPropertySetStorage::Create() pclsid parameter, the CLSID is set to all zeroes.

The current CLSID on a property storage object can be retrieved with a call to IPropertyStorage::Stat(). The initial value for the CLSID can be specified at the time that the storage is created with a call to IPropertySetStorage::Create().

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.

Parameters

clsid

[in] New CLSID to be associated with the property set.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

The CLSID has been assigned.

STG_E_ACCESSDENIED

The requested access to the IPropertyStorage() interface has been denied. The CLSID was not assigned.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation. The CLSID was not assigned.

STG_E_INVALIDPARAMETER

The parameter is invalid. The CLSID was not assigned.

See Also

IPropertySetStorage::Create(), IPropertyStorage::Stat()  

IPropertyStorage::SetTimes()

NAME

IPropertyStorage::SetTimes() - Sets the modification, access, and creation times of this property set, if supported by the implementation. Not all implementations support all these time values.

Synopsis

#include <objidl.h>

HRESULT SetTimes(
        FILETIME const * pctime,
        FILETIME const * patime,
        FILETIME const * pmtime );

Description

Sets the modification, access, and creation times of the current open property set, if supported by the implementation (not all implementations support all these time values). Unsupported timestamps are always reported as zero, enabling the caller to test for support. A call to IPropertyStorage::Stat() supplies (among other information) timestamp information.

Notice that this functionality is provided as an IPropertyStorage() method on a property storage object that is already open, in contrast to being provided as a method in IPropertySetStorage(). Normally, when the SetTimes method is not explicitly called, the access and modification times are updated as a side effect of reading and writing the property set. When SetTimes is used, the latest specified times supersede either default times or time values specified in previous calls to SetTimes.

Parameters

pctime

[in] Pointer to the new creation time for the property set. May be NULL, indicating that this time is not to be modified by this call.

patime

[in] Pointer to the new access time for the property set. May be NULL, indicating that this time is not to be modified by this call.

pmtime

[in] Pointer to the new modification time for the property set. May be NULL, indicating that this time is not to be modified by this call.

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

All the requested times have been successfully updated.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied; no times have been updated.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation.

STG_E_INVALIDPARAMETER

The parameter is invalid. This error is returned if an attempt is made to set a time value which is not supported by this implementation.

See Also

IPropertyStorage::Stat(), FILETIME structure  

IPropertyStorage::WriteMultiple()

NAME

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.

Synopsis

#include <objidl.h>

HRESULT WriteMultiple(
        ULONG cpspec,
        PROPSPEC const rgpspec[],
        PROPVARIANT const rgvar[],
        PROPID propidNameFirst );

Description

If a specified property already exists, its 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. The string name is stored in the same format as a VT_BSTR. Refer also to the discussion above 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.

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.

See Also

IPropertySetStorage::Create(), IPropertyStorage::ReadMultiple()  

IPropertyStorage::WritePropertyNames()

NAME

IPropertyStorage::WritePropertyNames() - Assigns string names to a specified array of property IDs in the current property set.

Synopsis

#include <objidl.h>

HRESULT WritePropertyNames(
        ULONG cpropid,
        PROPID const rgpropid[],
        LPWSTR const rglpwstrName[] );

Description

IPropertyStorage::WritePropertyNames() assigns string names to property identifiers passed to the method in the rgpropid array. It associates each string name in the rglpwstrName array with the respective property identifier in rgpropid. It is explicitly valid to define a name for a property identifier that is not currently present in the property storage object.

It is also valid to change the mapping for an existing string name (determined by a case-insensitive match). That is, you can use the WritePropertyNames method to map an existing name to a new property identifier, or to map a new name to a property identifier that already has a name in the dictionary. In either case, the original mapping is deleted. Property names must be unique (as are property identifiers) within the property set.

The storage of string property names preserves the case. String property names are limited in length to 128 characters. Property names that begin with the binary Unicode characters 0x0001 through 0x001F are reserved for future use.

Parameters

cpropid

[in] Size on input of the array rgpropid. May legally be zero, though this is a no-op, writing no property names.

rgpropid[]

[in] Array of the property identifiers for which names are to be set.

rglpwstrName[]

[in] Array of new names to be assigned to the corresponding property identifiers in the rgpropid array. These names may not exceed 255 characters (not including the NULL terminator).

Return Values

This method supports the standard return value E_UNEXPECTED, as well as the following:

S_OK

Success. All of the indicated string names were successfully set.

STG_E_INVALIDNAME

At least one of the indicated property identifier values does not exist in this property set. No names were set.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied. No property names have been changed in the storage.

STG_E_INSUFFICIENTMEMORY

There is not sufficient memory to perform this operation. Some names may not have been set.

STG_E_INVALIDPARAMETER

A parameter is invalid. Some names may not have been set.

HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION)

There was a failed attempt to translate a Unicode string to or from ANSI.

See Also

IPropertyStorage::ReadPropertyNames(), IPropertyStorage::ReadMultiple(), IPropertyStorage::WriteMultiple()

15.6.21    IPropertyStorage-Compound File Implementation

The COM 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.

Description

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 COM 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 COM 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()

15.6.22    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.

Description

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:

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.

Table 15-32:  IPropertyStorage Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

See Also

IPropertySetStorage-Standalone Implementation, IPropertyStorage(), IStorage::SetElementTimes(), StgOpenPropStg(), StgCreatePropStg(), StgCreatePropSetStg()

15.6.23    IRootStorage

The IRootStorage() interface contains a single method that switches a storage object to a different underlying file and saves the storage object to that file. The save operation occurs even with low memory conditions and uncommitted changes to the storage object. A subsequent call to IStorage::Commit() is guaranteed to not consume any additional memory.

When to Implement

Storage objects that are based on a file should implement IRootStorage() in addition to the IStorage() interface. For storage objects that are not file-based, this interface is not necessary.

COM provides an implementation of a storage object, including the IRootStorage() interface, as part of its compound file implementation.

When to Use

The primary use for the IRootStorage() interface is to save a storage object to a file during low memory conditions. Typically, the container application calls the IRootStorage() interface to switch to a new file.

If you have an IStorage() pointer to a compound file object, you can call IStorage::QueryInterface() with IID_IRootStorage to obtain a pointer to the IRootStorage() interface.

Table 15-33:  IRootStorage Methods in VTable Order

IUnknown() Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-34:  IRootStorage Methods

IRootStorage Method Description
SwitchToFile Copy the file underlying this root storage object, then associate this storage with the copied file.

See Also

IStorage(), StgCreateDocfile()  

IRootStorage::SwitchToFile()

NAME

IRootStorage::SwitchToFile() - Copies the current file associated with the storage object to a new file. The new file is then used for the storage object and any uncommitted changes.

Synopsis

#include <objidl.h>

HRESULT SwitchToFile(
        LPOLESTR pszFile );

Description

The IRootStorage::SwitchToFile() method copies the file associated with the storage object. A COM container calls SwitchToFile to perform a full save on a file in a low-memory situation. Typically, this is done only after a normal full save operation (i.e., save to temporary file, delete original file, rename temporary file) has failed with an E_OUTOFMEMORY error.

It is illegal to call SwitchToFile if the storage object or anything contained within it has been marshalled to another process. As a consequence, before calling SwitchToFile, the container must call the IPersistStorage::HandsOffStorage() method for any element within the storage object that is loaded or running. The HandsOffStorage method forces the element to release its storage pointers and enter the hands-off storage mode. The container must also release all pointers to streams or storages that are contained in this root storage. After the full save operation is completed, the container returns the contained elements to normal storage mode.

Notes to Implementors

If you are implementing your own storage objects, the IRootStorage() methods (including QueryInterface(), AddRef(), and Release()) must not consume additional memory or file handles.

Parameters

pszFile

Specifies the filename for the new file. It cannot be the name of an existing file. If NULL, this method creates a temporary file with a unique name, and you can call IStorage::Stat() to retrieve the name of the temporary file.

Return Values

S_OK

The file was successfully copied.

STG_E_MEDIUMFULL

The file was not copied because of insufficient space on the storage device.

STG_E_ACCESSDENIED

The file was not copied because the caller does not have permission to access storage device.

STG_E_INVALIDPOINTER

The file was not copied because the pszFile pointer is invalid.

STG_E_FILEALREADYEXISTS

The file was not copied because the new filename (pszFile) points to an existing file.

See Also

IPersistStorage::HandsOffStorage(), IPersistStorage::SaveCompleted(), IStorage::Commit(), IStorage::Stat()

15.6.24    IRootStorage - Compound File Implementation

COM's compound file implementation of IRootStorage() provides a way to support saving files in low-memory or low disk-space situations. For information on how this interface behaves, see IRootStorage().

When to Use

Use the system-supplied implementation of IRootStorage() only to support saving files under low memory conditions.

Description

It is possible to call COM's implementation of IRootStorage::SwitchToFile() to do a normal Save As operation to

another file. Applications that do so, however, may not be compatible with future generations of COM storage. To avoid this possibility, applications performaing a Save As operation should manually create the second docfile and invoke

IStorage::CopyTo. IRootStorage::SwitchToFile should beused only in emergency (low memory or disk space) situations.

See Also

IRootStorage(); IRootStorage::SwitchToFile()

15.6.25    IStorage

The IStorage() interface supports the creation and management of structured storage objects. Structured storage allows hierarchical storage of information within a single file, and is often referred to as "a file system within a file". Elements of a structured storage object are storages and streams. Storages are analogous to directories, and streams are analogous to files. Within a structured storage there will be a primary storage object that may contain substorages, possibly nested, and streams. Storages provide the structure of the object, and streams contain the data, which is manipulated through the IStream() interface.

The IStorage() interface provides methods for creating and managing the root storage object, child storage objects, and stream objects. These methods can create, open, enumerate, move, copy, rename, or delete the elements in the storage object.

An application must release its IStorage() pointers when it is done with the storage object to deallocate memory used. There are also methods for changing the date and time of an element.

There are a number of different modes in which a storage object and its elements can be opened, determined by setting values from the STGM enumeration. One aspect of this is how changes are committed. You can set direct mode, in which in which changes to an object are immediately written to it, or transacted mode, in which changes are written to a buffer until explicitly committed. The IStorage() interface provides methods for committing changes and reverting to the last-committed version. Other storage modes set, for example, a stream can be opened in read only mode or read/write mode. For more information, refer to the STGM enumeration.

Other methods provide a means to gain access to information about a storage object and its elements through the STATSTG structure.

When to Implement

Generally, you would not implement this interface unless you were defining a new storage scheme for your system. COM provides a compound file implementation of the IStorage() interface that supports transacted access. COM provides a set of helper APIs to facilitate using the compound file implementation of storage objects. Refer to Section Section 15.6.26.

When to Use

Call the methods of IStorage() to manage substorages or streams within the current storage. This management includes creating, opening, or destroying sub-storages or streams, as well as managing aspects such as time stamps, names, etc. You can also commit changes or revert to previous version for storages opened in transacted mode. The methods of IStorage() do not include means to read and write data--this is reserved for IStream(), which manages the actual data. While the IStorage() and IStream() interfaces are used to manipulate the storage object and its elements, the IPersistStorage() interface contains methods that are called to serialize the storage object and its elements to a disk file.

Table 15-35:  IStorage Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-36:  IStorage Methods

IStorage() Methods Description
CreateStream Creates and opens a stream object with the specified name contained in this storage object.
OpenStream Opens an existing stream object within this storage object using the specified access permissions in grfMode.
CreateStorage Creates and opens a new storage object within this storage object.
OpenStorage Opens an existing storage object with the specified name according to the specified access mode.
CopyTo Copies the entire contents of this open storage object into another storage object. The layout of the destination storage object may differ.
MoveElementTo Copies or moves a substorage or stream from this storage object to another storage object.
Commit Reflects changes for a transacted storage object to the parent level.
Revert Discards all changes that have been made to to the storage object since the last commit operation.
EnumElements Returns an enumerator object that can be used to enumerate the storage and stream objects contained within this storage object.
DestroyElement Removes the specified storage or stream from this storage object.
RenameElement Renames the specified storage or stream in this storage object.
SetElementTimes Sets the modification, access, and creation times of the indicated storage element, if supported by the underlying file system.
SetClass Assigns the specified CLSID to this storage object.
SetStateBits Stores up to 32 bits of state information in this storage object.
Stat Returns the STATSTG structure for this open storage object.

 

IStorage::Commit()

NAME

IStorage::Commit() - Ensures that any changes made to a storage object open in transacted mode are reflected in the parent storage; for a root storage, reflects the changes in the actual device, for example, a file on disk. For a root storage object opened in direct mode, this method has no effect except to flush all memory buffers to the disk. For non-root storage objects in direct mode, this method has no effect.

Synopsis

#include <objidl.h>

HRESULT Commit(
        DWORD grfCommitFlags );

Description

IStorage::Commit() makes permanent changes to a storage object that is in transacted mode, in which changes are accumulated in a buffer, and not reflected in the storage object until there is a call to this method. The alternative is to open an object in direct mode, in which changes are immediately reflected in the storage object and so does not require a commit operation. Calling this method on a storage opened in direct mode has no effect, unless it is a root storage, in which case it ensures that changes in memory buffers are written to the underlying storage device.

The commit operation publishes the current changes in this storage object and its children to the next level up in the storage hierarchy. To undo current changes before committing them, call IStorage::Revert() to roll back to the last-committed version.

Calling IStorage::Commit() has no effect on currently-opened nested elements of this storage object. They are still valid and can be used. However, the IStorage::Commit() method does not automatically commit changes to these nested elements. The commit operation publishes only known changes to the next higher level of the storage hierarchy. Thus, transactions to nested levels must be committed to this storage object before they can be committed to higher levels.

In commit operations, you need to take steps to ensure that data is protected during the commit process:

See Also

IStorage - Compound File Implementation, STGC, IStorage::Revert()

Parameters

grfCommitFlags

[in] Controls how the changes are committed to the storage object. See the STGC enumeration for a definition of these values.

Return Values

S_OK

Changes to the storage object were successfully committed to the parent level.

E_PENDING

Asynchronous Storage only: Part or all of the data to be committed is currently unavailable.

STG_E_INVALIDFLAG

The value for the grfCommitFlags parameter is not valid.

STG_E_INVALIDPARAMETER

One of the parameters was not valid.

STG_E_NOTCURRENT

Another open instance of the storage object has committed changes. Thus, the current commit operation may overwrite previous changes.

STG_E_MEDIUMFULL

No space left on device to commit.

STG_E_TOOMANYOPENFILES

The commit operation could not be completed because there are too many open files.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

 

IStorage::CopyTo()

NAME

IStorage::CopyTo() - Copies the entire contents of an open storage object to another storage object.

Synopsis

#include <objidl.h>

HRESULT CopyTo(
        DWORD ciidExclude,
        IID const * rgiidExclude,
        SNB snbExclude,
        IStorage * pstgDest );

Description

This method merges elements contained in the source storage object with those already present in the destination. The layout of the destination storage object may differ from the source storage object.

The copy process is recursive, invoking IStorage::CopyTo() and IStream::CopyTo() on the elements nested inside the source.

When copying a stream on top of an existing stream with the same name, the existing stream is first removed and then replaced with the source stream. When copying a storage on top of an existing storage with the same name, the existing storage is not removed. As a result,, after the copy operation, the destination IStorage() contains older elements, unless they were replaced by newer ones with the same names.

A storage object may expose interfaces other than IStorage(), including IRootStorage(), IPropertyStorage(), or IPropertySetStorage(). The rgiidExclude parameter provides a way to exclude any or all of these additional interfaces from the copy operation.

A caller with a newer or more efficient copy of an existing substorage or stream object may want to exclude the current versions of these objects from the copy operation. The snbExclude and rgiidExclude parameters provide two different ways of excluding a storage objects existing storages or streams.

Note to Callers

The most common way to use this method is to copy everything possible from the source to the destination, as in most Full Save and SaveAs operations. The following example illustrates this call:

pstg->CopyTo(0, Null, Null, pstgDest)

Parameters

ciidExclude

[in] The number of elements in the array pointed to by rgiidExclude. If rgiidExclude is NULL, then ciidExclude is ignored.

rgiidExclude

[in] An array of interface identifiers that either the caller knows about and does not want to be copied or that the storage object does not support but whose state the caller will later explicitly copy. The array can include IStorage(), indicating that only stream objects are to be copied, and IStream(), indicating that only storage objects are to be copied. An array length of zero indicates that only the state exposed by the IStorage() object is to be copied; all other interfaces on the object are to be ignored. Passing NULL indicates that all interfaces on the object are to be copied.

snbExclude

[in] A string name block (refer to SNB) that specifies a block of storage or stream objects that are not to be copied to the destination. These elements are not created at the destination. If IID_IStorage is in the rgiidExclude array, this parameter is ignored. This parameter may be NULL.

pstgDest

[in] Points to the open storage object into which this storage object is to be copied. The destination storage object can be a different implementation of the IStorage() interface from the source storage object. Thus, IStorage::CopyTo() can only use publicly available methods of the destination storage object. If pstgDest is open in transacted mode, it can be reverted by calling its IStorage::Revert() method.

Return Values

S_OK

The storage object was successfully copied.

E_PENDING

Asynchronous Storage only: Part or all of the data to be copied is currently unavailable.

STG_E_ACCESSDENIED

The destination storage object is a child of the source storage object.

STG_E_INSUFFICIENTMEMORY

The copy was not completed due to a lack of memory.

STG_E_INVALIDPOINTER

The pointer specified for the storage object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_TOOMANYOPENFILES

The copy was not completed because there are too many open files.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_MEDIUMFULL

The copy was not completed because the storage medium is full.

See Also

IStorage - Compound File Implementation, IStorage::MoveElementTo(), IStorage::Revert()  

IStorage::CreateStorage()

NAME

IStorage::CreateStorage() - Creates and opens a new storage object nested within this storage object.

Synopsis

#include <objidl.h>

HRESULT CreateStorage(
        const WCHAR * pwcsName,
        DWORD grfMode,
        DWORD reserved1,
        DWORD reserved2,
        IStorage ** ppstg );

Description

If a storage with the name specified in the pwcsName parameter already exists within the parent storage object, and the grfMode parameter includes the STGM_CREATE flag, the existing storage is replaced by the new one. If the grfMode parameter includes the STGM_CONVERT flag, the existing element is converted to a stream object named CONTENTS and the new storage object is created containing the CONTENTS stream object. The destruction of the old element and the creation of the new storage object are both subject to the transaction mode on the parent storage object.

If a storage object with the same name already exists and grfMode is set to STGM_FAILIFTHERE, this method fails with the return value STG_E_FILEALREADYEXISTS.

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the newly created storage object. This name can be used later to reopen the storage object.

grfMode

[in] Specifies the access mode to use when opening the newly created storage object. See the STGM enumeration values for descriptions of the possible values.

reserved1

[in] Reserved for future use; must be zero.

reserved2

[in] Reserved for future use; must be zero.

ppstg

[out] When successful, points to the location of the IStorage() pointer to the newly-created storage object. This parameter is set to NULL if an error occurs.

Return Values

S_OK

The storage object was created successfully.

E_PENDING

Asynchronous Storage only: Part or all of the necessary data is currently unavailable.

STG_E_ACCESSDENIED

Insufficient permissions to create storage object.

STG_E_FILEALREADYEXISTS

The name specified for the storage object already exists in the storage object and the grfmode flag includes the flag STGM_FAILIFTHERE.

STG_E_INSUFFICIENTMEMORY

The storage object was not created due to a lack of memory.

STG_E_INVALIDFLAG

The value specified for the grfMode flag is not a valid STGM enumeration value.

STG_E_INVALIDFUNCTION

The specified combination of grfMode flags is not supported.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the storage object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The storage object was not created because there are too many open files.

STG_S_CONVERTED

The existing stream with the specified name was replaced with a new storage object containing a single stream called CONTENTS. The new storage object will be added.

See Also

IStorage - Compound File Implementation, IStorage::OpenStorage()  

IStorage::CreateStream()

NAME

IStorage::CreateStream() - Creates and opens a stream object with the specified name contained in this storage object. All elements within a storage object -- both streams and other storage objects -- are kept in the same name space.

Synopsis

#include <objidl.h>

HRESULT CreateStream(
        const WCHAR * pwcsName,
        DWORD grfMode,
        DWORD reserved1,
        DWORD reserved2,
        IStream ** ppstm );

Description

If a stream with the name specified in the pwcsName parameter already exists and the grfMode parameter includes the STGM_CREATE flag, the existing stream is replaced by a newly created one. Both the destruction of the old stream and the creation of the new stream object are subject to the transaction mode on the parent storage object.

If the stream already exists and grfMode is set to STGM_FAILIFTHERE, this method fails with the return value STG_E_FILEALREADYEXISTS.

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the newly created stream. This name can be used later to open or reopen the stream.

grfMode

[in] Specifies the access mode to use when opening the newly created stream. See the STGM enumeration values for descriptions of the possible values.

reserved1

[in] Reserved for future use; must be zero.

reserved2

[in] Reserved for future use; must be zero.

ppstm

[out] On return, points to the location of the new IStream() interface pointer. This is only valid if the operation is successful. When an error occurs, this parameter is set to NULL.

Return Values

S_OK

The new stream was successfully created

E_PENDING

Asynchronous Storage only: Part or all of the necessary data is currently unavailable.

STG_E_ACCESSDENIED

Insufficient permissions to create stream.

STG_E_FILEALREADYEXISTS

The name specified for the stream already exists in the storage object and the grfmode flag includes the flag STGM_FAILIFTHERE.

STG_E_INSUFFICIENTMEMORY

The stream was not created due to a lack of memory.

STG_E_INVALIDFLAG

The value specified for the grfMode flag is not a valid STGM enumeration value.

STG_E_INVALIDFUNCTION

The specified combination of grfMode flags is not supported. For example, if this method is called without the STGM_SHARE_EXCLUSIVE flag.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the stream object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The stream was not created because there are too many open files.

See Also

IStorage - Compound File Implementation, IStorage::OpenStream(), IStream()  

IStorage::DestroyElement()

NAME

IStorage::DestroyElement() - Removes the specified storage or stream from this storage object.

Synopsis

#include <objidl.h>

HRESULT DestroyElement(
        wchar * pwcsName );

Description

The DestroyElement method deletes a substorage or stream from the current storage object. After a successful call to DestroyElement, any open instance of the destroyed element from the parent storage becomes invalid.

If a storage object is opened in transacted mode, destruction of an element requires that the call to DestroyElement be followed by a call to IStorage::Commit().

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the storage or stream to be removed.

Return Values

S_OK

The element was successfully removed.

E_PENDING

Asynchronous Storage only: Part or all of the element's data is currently unavailable.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for removing the element.

STG_E_FILENOTFOUND

The element with the specified name does not exist.

STG_E_INSUFFICIENTMEMORY

The element was not removed due to a lack of memory.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the element was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The element was not removed because there are too many open files.

See Also

IStorage - Compound File Implementation  

IStorage::EnumElements()

NAME

IStorage::EnumElements() - Retrieves a pointer to an enumerator object that can be used to enumerate the storage and stream objects contained within this storage object.

Synopsis

#include <objidl.h>

HRESULT EnumElements(
        DWORD reserved1,
        void * reserved2,
        DWORD reserved3,
        IEnumSTATSTG ** ppenum );

Description

The enumerator object returned by this method implements the IEnumSTATSTG() interface, one of the standard enumerator interfaces that contain the Next, Reset, Clone, and Skip methods. IEnumSTATSTG() enumerates the data stored in an array of STATSTG structures.

The storage object must be open in read mode to allow the enumeration of its elements.

The order in which the elements are enumerated and whether the enumerator is a snapshot or always reflects the current state of the storage object, and depends on the IStorage() implementation.

See Also

IStorage - Compound File Implementation, IEnumXXXX(), IEnumSTATSTG(), STATSTG

Parameters

reserved1

[in] Reserved for future use; must be zero.

reserved2

[in] Reserved for future use; must be NULL.

reserved3

[in] Reserved for future use; must be zero.

ppenum

[out] When successful, points to the location of an IEnumSTATSTG() pointer to new enumerator object.

Return Values

S_OK

The enumerator object was successfully returned.

E_PENDING

Asynchronous Storage only: Part or all of the element's data is currently unavailable.

STG_E_INSUFFICIENTMEMORY

The enumerator object could not be created due to lack of memory.

STG_E_INVALIDPARAMETER

One of the parameters was not valid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

 

IStorage::MoveElementTo()

NAME

IStorage::MoveElementTo() - Copies or moves a substorage or stream from this storage object to another storage object.

Synopsis

#include <objidl.h>

HRESULT MoveElementTo(
        const WCHAR * pwcsName,
        IStorage * pstgDest,
        LPWSTR pwcsNewName,
        DWORD grfFlags );

Description

The IStorage::MoveElementTo() method is typically the same as invoking the IStorage::CopyTo() method on the indicated element and then removing the source element. In this case, the MoveElementTo method uses only the publicly available functions of the destination storage object to carry out the move.

If the source and destination storage objects have special knowledge about each other's implementation (they could, for example, be different instances of the same implementation), this method can be implemented more efficiently.

Before calling this method, the element to be moved must be closed, and the destination storage must be open.

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the element in this storage object to be moved or copied.

pstgDest

[in] IStorage() pointer to the destination storage object.

pwcsNewName

[in] Points to a wide character string that contains the new name for the element in its new storage object.

grfFlags

[in] Specifies whether the operation should be a move (STGMOVE_MOVE) or a copy (STGMOVE_COPY). See the STGMOVE enumeration.

Return Values

S_OK

The storage object was successfully copied or moved.

E_PENDING

Asynchronous Storage only: Part or all of the element's data is currently unavailable.

STG_E_ACCESSDENIED

The destination storage object is a child of the source storage object.

STG_E_FILENOTFOUND

The element with the specified name does not exist.

STG_E_FILEALREADYEXISTS

The specified file already exists.

STG_E_INSUFFICIENTMEMORY

The copy or move was not completed due to a lack of memory.

STG_E_INVALIDFLAG

The value for the grfFlags parameter is not valid.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the storage object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The copy or move was not completed because there are too many open files.

See Also

IStorage - Compound File Implementation, STGMOVE, IStorage::CopyTo()  

IStorage::OpenStorage()

NAME

IStorage::OpenStorage() - Opens an existing storage object with the specified name in the specified access mode.

Synopsis

#include <objidl.h>

HRESULT OpenStorage(
        const WCHAR * pwcsName,
        IStorage * pstgPriority,
        DWORD grfMode,
        SNB snbExclude,
        DWORD reserved,
        IStorage ** ppstg );

Description

Storage objects can be opened with STGM_DELETEONRELEASE, in which case the object is destroyed when it receives its final release. This is useful for creating temporary storage objects.

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the storage object to open. It is ignored if pstgPriority is non-NULL.

pstgPriority

[in] If the pstgPriority parameter is not NULL, it is an IStorage() pointer to a previous opening of an element of the storage object, usually one that was opened in priority mode. The storage object should be closed and re-opened according to grfMode. When the IStorage::OpenStorage() method returns, pstgPriority is no longer valid. Use the value supplied in the ppstg parameter. If the pstgPriority parameter is NULL, it is ignored.

grfMode

[in] Specifies the access mode to use when opening the storage object. See the STGM enumeration values for descriptions of the possible values. Whatever other modes you may choose, you must at least specify STGM_SHARE_EXCLUSIVE when calling this method.

snbExclude

[in] Must be NULL. A non-NULL value will return STG_E_INVALIDPARAMETER.

reserved

[in] Reserved for future use; must be zero.

ppstg

[out] When the operation is successful, points to the location of an IStorage() pointer to the opened storage object. This parameter is set to NULL if an error occurs.

Return Values

S_OK

The storage object was opened successfully.

E_PENDING

Asynchronous Storage only: Part or all of the storage's data is currently unavailable.

STG_E_ACCESSDENIED

Insufficient permissions to open storage object.

STG_E_FILENOTFOUND

The storage object with the specified name does not exist.

STG_E_INSUFFICIENTMEMORY

The storage object was not opened due to a lack of memory.

STG_E_INVALIDFLAG

The value specified for the grfMode flag is not a valid STGM enumeration value.

STG_E_INVALIDFUNCTION

The specified combination of grfMode flags is not supported.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the storage object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The storage object was not created because there are too many open files.

STG_S_CONVERTED

The existing stream with the specified name was replaced with a new storage object containing a single stream called CONTENTS. In direct mode, the new storage is immediately written to disk. In transacted mode, the new storage is written to a temporary storage in memory and later written to disk when it is committed.

See Also

IStorage - Compound File Implementation, IStorage::CreateStorage()  

IStorage::OpenStream()

NAME

IStorage::OpenStream() - Opens an existing stream object within this storage object in the specified access mode.

Synopsis

#include <objidl.h>

HRESULT OpenStream(
        const WCHAR * pwcsName,
        void * reserved1,
        DWORD grfMode,
        DWORD reserved2,
        IStream ** ppstm );

Description

IStorage::OpenStream() opens an existing stream object within this storage object in the access mode specified in grfMode. There are restrictions on the permissions that can be given in grfMode. For example, the permissions on this storage object restrict the permissions on its streams. In general, access restrictions on streams should be stricter than those on their parent storages. Compound-file streams must be opened with STGM_SHARE_EXCLUSIVE.

Parameters

pwcsName

[in] Points to a wide character string that contains the name of the stream to open.

reserved1

[in] Reserved for future use; must be NULL.

grfMode

[in] Specifies the access mode to be assigned to the open stream. See the STGM enumeration values for descriptions of the possible values. Whatever other modes you may choose, you must at least specify STGM_SHARE_EXCLUSIVE when calling this method.

reserved2

[in] Reserved for future use; must be zero.

ppstm

[out] On successful return, points to the location of an IStream() pointer to the newly-opened stream object. This parameter is set to NULL if an error occurs.

Return Values

S_OK

The stream was successfully opened.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable.

STG_E_ACCESSDENIED

Insufficient permissions to open stream.

STG_E_FILENOTFOUND

The stream with specified name does not exist.

STG_E_INSUFFICIENTMEMORY

The stream was not opened due to a lack of memory.

STG_E_INVALIDFLAG

The value specified for the grfMode flag is not a valid STGM enumeration value.

STG_E_INVALIDFUNCTION

The specified combination of grfMode flags is not supported. For example, if this method is called without the STGM_SHARE_EXCLUSIVE flag.

STG_E_INVALIDNAME

Invalid value for pwcsName.

STG_E_INVALIDPOINTER

The pointer specified for the stream object was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The stream was not opened because there are too many open files.

See Also

IStorage - Compound File Implementation, IStorage::CreateStream(), IStream()  

IStorage::RenameElement()

NAME

IStorage::RenameElement() - Renames the specified substorage or stream in this storage object.

Synopsis

#include <objidl.h>

HRESULT RenameElement(
        const WCHAR * pwcsOldName,
        const WCHAR * pwcsNewName );

Description

IStorage::RenameElement() renames the specified substorage or stream in this storage object. An element in a storage object cannot be renamed while it is open. The rename operation is subject to committing the changes if the storage is open in transacted mode.

The IStorage::RenameElement() method is not guaranteed to work in low memory with storage objects open in transacted mode. It may work in direct mode.

Parameters

pwcsOldName

[in] Points to a wide character string that contains the name of the substorage or stream to be changed.

pwcsNewName

[in] Points to a wide character string that contains the new name for the specified sustorage or stream.

Return Values

S_OK

The element was successfully renamed.

E_PENDING

Asynchronous Storage only: Part or all of the element's data is currently unavailable.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for renaming the element.

STG_E_FILENOTFOUND

The element with the specified old name does not exist.

STG_E_FILEALREADYEXISTS

The element specified by the new name already exists.

STG_E_INSUFFICIENTMEMORY

The element was not renamed due to a lack of memory.

STG_E_INVALIDNAME

Invalid value for one of the names.

STG_E_INVALIDPOINTER

The pointer specified for the element was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

STG_E_TOOMANYOPENFILES

The element was not renamed because there are too many open files.

See Also

IStorage - Compound File Implementation  

IStorage::Revert()

NAME

IStorage::Revert() - Discards all changes that have been made to the storage object since the last commit.

Synopsis

#include <objidl.h>

HRESULT Revert(
        void );

Description

For storage objects opened in transacted mode, the IStorage::Revert() method discards any uncommitted changes to this storage object or changes that have been committed to this storage object from nested elements.

After this method returns, any existing elements (substorages or streams) that were opened from the reverted storage object are invalid and can no longer be used. Specifying these reverted elements in any call except IStorage::Release() returns the error STG_E_REVERTED

This method has no effect on storage objects opened in direct mode.

See Also

IStorage - Compound File Implementation, IStorage::Commit()

Return Values

S_OK

The revert operation was successful.

E_PENDING

Asynchronous Storage only: Part or all of the storage's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_INSUFFICIENTMEMORY

The revert operation could not be completed due to a lack of memory.

STG_E_TOOMANYOPENFILES

The revert operation could not be completed because there are too many open files.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

 

IStorage::SetClass()

NAME

IStorage::SetClass() - Assigns the specified CLSID to this storage object.

Synopsis

#include <objidl.h>

HRESULT SetClass(
        REFCLSID clsid );

Description

When first created, a storage object has an associated CLSID of CLSID_NULL. Call this method to assign a CLSID to the storage object.

Call the IStorage::Stat() method to retrieve the current CLSID of a storage object.

See Also

IStorage - Compound File Implementation, IStorage::Stat()

Parameters

clsid

[in] The class identifier (CLSID) that is to be associated with the storage object.

Return Values

S_OK

The CLSID was successfully assigned.

E_PENDING

Asynchronous Storage only: Part or all of the storage's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for assigning a class identifier to the storage object.

STG_E_MEDIUMFULL

Not enough space was left on device to complete the operation.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

 

IStorage::SetElementTimes()

NAME

IStorage::SetElementTimes() - Sets the modification, access, and creation times of the specified storage element, if supported by the underlying file system.

Synopsis

#include <objidl.h>

HRESULT SetElementTimes(
        const WCHAR * pwcsName,
        FILETIME const * pctime,
        FILETIME const * patime,
        FILETIME const * pmtime );

Description

This method sets time statistics for the specified storage element within this storage object.

Not all file systems support all of the time values. This method sets those times that are supported and ignores the rest. Each of the time value parameters can be NULL; indicating that no modification should occur.

Call the IStorage::Stat() method to retrieve these time values.

See Also

IStorage - Compound File Implementation, IStorage::Stat()

Parameters

pwcsName

[in] The name of the storage object element whose times are to be modified. If NULL, the time is set on the root storage rather than one of its elements.

pctime

[in] Either the new creation time for the element or NULL if the creation time is not to be modified.

patime

[in] Either the new access time for the element or NULL if the access time is not to be modified.

pmtime

[in] Either the new modification time for the element or NULL if the modification time is not to be modified.

Return Values

S_OK

The time values were successfully set.

E_PENDING

Asynchronous Storage only: Part or all of the element's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for changing the element.

STG_E_FILENOTFOUND

The element with the specified name does not exist.

STG_E_INSUFFICIENTMEMORY

The element was not changed due to a lack of memory.

STG_E_INVALIDNAME

Invalid value for the element name.

STG_E_INVALIDPOINTER

The pointer specified for the element was invalid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

STG_E_TOOMANYOPENFILES

The element was not changed because there are too many open files.

STG_E_REVERTED

The storage object has been invalidated by a revert operation above it in the transaction tree.

 

IStorage::SetStateBits()

NAME

IStorage::SetStateBits() - Stores up to 32 bits of state information in this storage object.

Synopsis

#include <objidl.h>

HRESULT SetStateBits(
        DWORD grfStateBits,
        DWORD grfMask );

Description

This interface is reserved for future use. The values for the state bits are not currently defined.

Parameters

grfStateBits

[in] Specifies the new values of the bits to set. No legal values are defined for these bits; they are all reserved for future use and must not be used by applications.

grfMask

[in] A binary mask indicating which bits in grfStateBits are significant in this call.

Return Values

S_OK

The state information was successfully set.

E_PENDING

Asynchronous Storage only: Part or all of the storage's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for changing this storage object.

STG_E_INVALIDFLAG

The value for the grfStateBits or grfMask parameters are not valid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

See Also

IStorage - Compound File Implementation, IStorage::Stat()  

IStorage::Stat()

NAME

IStorage::Stat() - Retrieves the STATSTG structure for this open storage object.

Synopsis

#include <objidl.h>

HRESULT Stat(
        STATSTG * pstatstg,
        DWORD grfStatFlag );

Description

IStorage::Stat() retrieves the STATSTG structure for the current storage. This structure contains statistical information about the storage. IStorage::EnumElements() creates an enumerator object with the IEnumSTATSTG() interface, though which you can enumerate the substorages and streams of a storage through the STATSTG structure of each.

Parameters

pstatstg

[out] On return, points to a STATSTG structure where this method places information about the open storage object. This parameter is NULL if an error occurs.

grfStatFlag

[in] Specifies that some of the fields in the STATSTG structure are not returned, thus saving a memory allocation operation. Values are taken from the STATFLAG enumeration.

Return Values

S_OK

The STATSTG structure was successfully returned at the specified location.

E_PENDING

Asynchronous Storage only: Part or all of the storage's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for accessing statistics for this storage object.

STG_E_INSUFFICIENTMEMORY

The STATSTG structure was not returned due to a lack of memory.

STG_E_INVALIDFLAG

The value for the grfStateFlag parameter is not valid.

STG_E_INVALIDPARAMETER

One of the parameters was invalid.

See Also

IStorage - Compound File Implementation, STATFLAG, STATSTG, IEnumSTATSTG(), IStorage::SetClass(), IStorage::SetElementTimes(), IStorage::SetStateBits()

15.6.26    IStorage - Compound File Implementation

The compound file implementation of IStorage() allows you to create and manage substorages and streams within a storage object residing in a compound file object. To create a compound file object and get an IStorage() pointer, call the API function StgCreateDocfile(). To open an existing compound file object and get its root IStorage() pointer, call StgOpenStorage().

When to Use

Most applications use this implementation to to create and manage storages and streams.

Description

IStorage::CreateStream()

Creates and opens a stream object with the specified name contained in this storage object. The COM-provided compound file implementation of the IStorage::CreateStream() method does not support the following behaviors:

IStorage::OpenStream()

Opens an existing stream object within in this storage object using the specified access modes specified in the grfMode parameter. The COM-provided compound file implementation of the IStorage::OpenStream() method does not support the following behavior:

IStorage::CreateStorage()

The COM-provided compound file implementation of the IStorage::CreateStorage() method does not support the STGM_DELETEONRELEASE flag. Specifying this flag causes the method to return STG_E_INVALIDFLAG.

IStorage::OpenStorage()

Opens an existing storage object with the specified name in the specified access mode. The COM-provided compound file implementation of the IStorage::OpenStorage() method does not support the following behavior:

IStorage::CopyTo()

Copies only the substorages and streams of this open storage object into another storage object. The rgiidExclude parameter can be set to IID_IStream to copy only substorages, or to IID_IStorage to copy only streams.

IStorage::MoveElementTo()

Copies or moves a substorage or stream from this storage object to another storage object.

IStorage::Commit()

Ensures that any changes made to a storage object open in transacted mode are reflected in the parent storage; for a root storage, reflects the changes in the actual device, for example, a file on disk. For a root storage object opened in direct mode, this method has no effect except to flush all memory buffers to the disk. For non-root storage objects in direct mode, this method has no effect.

The COM-provided compound files implementation uses a two phase commit process unless STGC_OVERWRITE is specified in the grfCommitFlags parameter. This two-phase process ensures the robustness of data in case the commit operation fails. First, all new data is written to unused space in the underlying file. If necessary, new space is allocated to the file. Once this step has been successfully completed, a table in the file is updated using a single sector write to indicate that the new data is to be used in place of the old. The old data becomes free space to be used at the next commit. Thus, the old data is available and can be restored in case an error occurs when committing changes. If STGC_OVERWRITE is specified, a single phase commit operation is used.

IStorage::Revert()

Discards all changes that have been made to the storage object since the last commit.

IStorage::EnumElements()

Creates and retrieves a pointer to an enumerator object that can be used to enumerate the storage and stream objects contained within this storage object.The COM-provided compound file implementation takes a snapshot.

IStorage::DestroyElement()

Removes the specified element (substorage or stream) from this storage object.

IStorage::RenameElement()

Renames the specified substorage or stream in this storage object.

IStorage::SetElementTimes()

Sets the modification, access, and creation times of the specified storage element. The COM-provided compound file implementation maintains modification and change times for internal storage objects. For root storage objects, whatever is supported by the underlying file system (or ILockBytes()) is supported. The compound file implementation does not maintain any time stamps for internal streams. Unsupported time stamps are reported as zero, enabling the caller to test for support.

IStorage::SetClass()

Assigns the specified CLSID to this storage object.

IStorage::SetStateBits()

Stores up to 32 bits of state information in this storage object. The state set by this method is for external use only. The COM-provided compound file implementation does not perform any action based on the state.

IStorage::Stat()

Retrieves the STATSTG structure for this open storage object.

See Also

IStorage(), IStream(), StgCreateDocfile(), StgOpenStorage(), ILockBytes(), IRootStorage()

15.6.27    IStream

The IStream() interface supports reading and writing data to stream objects. Stream objects contain the data in a structured storage object, where storages provide the structure. Simple data can be written directly to a stream, but most frequently, streams are elements nested within a storage object. They are similar to standard files.

The IStream() interface defines methods similar to the MS-DOS FAT file functions. For example, each stream object has its own access rights and a seek pointer. The main difference between a stream object and a DOS file is that streams are not opened using a file handle, but through an IStream() interface pointer.

The methods in this interface present your object's data as a contiguous sequence of bytes that you can read or write. There are also methods for committing and reverting changes on streams open in transacted mode and methods for restricting access to a range of bytes in the stream.

Streams can remain open for long periods of time without consuming file system resources. The IStream::Release() method is similar to a close function on a file. Once released, the stream object is no longer valid and cannot be used.

Clients of asynchronous monikers can choose between a data-pull or data-push model for driving an asynchronous IMoniker::BindToStorage() operation and for receiving asynchronous notifications. The table below compares the behavior of asynchronous IStream::Read() and IStream::Seek() calls returned in IBindStatusCallback::OnDataAvailable in these two download models:

Table 15-37:  IStream Read and Seek Asynchronous Behavior

IStream() method call Behavior in data-pull model Behavior in data-push model
IStream::Read() is called to read partial data, (i.e. not all the available data) Returns S_OK. The client must continue to read all available data before returning from IBindStatusCallback:: OnDataAvailable or else the bind operation is blocked. (i.e. read until S_FALSE or E_PENDING is returned) Returns S_OK. Even if the client returns from IBindStatusCallback:: OnDataAvailable at this point the bind operation continues and IBindStatusCallback:: OnDataAvailable will be called again repeatedly until the binding finishes.
IStream::Read() is called to read all the available data Returns E_PENDING if the bind operation has not completed, and IBindStatusCallback:: OnDataAvailable will be called again when more data is available. Same as data-pull model.
IStream::Read() is called to read all the available data and the bind operation is over (end-of-file) Returns S_FALSE. There will be a subsequent call to IBindStatusCallback:: OnDataAvailable with the grfBSC flag set to BSCF_ LASTDATANOTIFICATION. Same as data-pull model.
IStream::Seek() is called IStream::Seek() doesn't work in data-pull model IStream::Seek() doesn't work in data-push model.

For general information on this topic, see Asynchronous Monikers and Data-Pull-Model versus Data Push-Model for more specific information. Also, see Managing Memory Allocation for details on COM's rules for managing memory.

When to Implement

Implement IStream() on a container or object application when you require functionality not provided by the COM compound file implementation. The specification of IStream() defines more functionality that the COM implementation supports. In addition, if you are creating a stream object that is larger than the heap in your machine's memory and you are using a global memory handle, the compound file implementation calls GlobalRealloc internally whenever it needs more memory, which can be extremely inefficient. In this case, the preferred solution is to implement an IStream() that uses memory allocated by VirtualAlloc instead of GlobalAlloc. This can reserve a large chunk of virtual address space and then commit memory within that address space as required. No data copying occurs and memory is committed only as it is needed. For more information, refer to Section Section 15.6.28.

When to Use

Call the methods of the IStream() interface from a container or application to read and write the data for an object. Since stream objects can be marshaled to other processes, applications can share the data in storage objects without having to use global memory.

Table 15-38:  IStream Methods in VTable Order

IUnknown Methods Description
QueryInterface() Returns pointers to supported interfaces.
AddRef() Increments the reference count.
Release() Decrements the reference count.

Table 15-39:  IStream Methods

IStream() Methods Description
Read Reads a specified number of bytes from the stream object into memory starting at the current seek pointer.
Write Writes a specified number from bytes into the stream object starting at the current seek pointer.
Seek Changes the seek pointer to a new location relative to the beginning of the stream, the end of the stream, or the current seek pointer.
SetSize Changes the size of the stream object.
CopyTo Copies a specified number of bytes from the current seek pointer in the stream to the current seek pointer in another stream.
Commit Ensures that any changes made to a stream object open in transacted mode are reflected in the parent storage object.
Revert Discards all changes that have been made to a transacted stream since the last IStream::Commit() call.
LockRegion Restricts access to a specified range of bytes in the stream. Supporting this functionality is optional since some file systems do not provide it.
UnlockRegion Removes the access restriction on a range of bytes previously restricted with IStream::LockRegion().
Stat Retrieves the STATSTG structure for this stream.
Clone Creates a new stream object that references the same bytes as the original stream but provides a separate seek pointer to those bytes.

 

IStream::Clone()

NAME

IStream::Clone() - Creates a new stream object with its own seek pointer that references the same bytes as the original stream.

Synopsis

#include <objidl.h>

HRESULT Clone(
        IStream ** ppstm );

Description

This method creates a new stream object for accessing the same bytes but using a separate seek pointer. The new stream object sees the same data as the source stream object. Changes written to one object are immediately visible in the other. Range locking is shared between the stream objects.

The initial setting of the seek pointer in the cloned stream instance is the same as the current setting of the seek pointer in the original stream at the time of the clone operation.

See Also

IStream - Compound File Implementation, IStream::CopyTo()

Parameters

ppstm

[out] When successful, points to the location of an IStream() pointer to the new stream object. If an error occurs, this parameter is NULL.

Return Values

S_OK

The stream was successfully cloned.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_INSUFFICIENT_MEMORY

The stream was not cloned due to a lack of memory.

STG_E_INVALIDPOINTER

The ppStm pointer is not valid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::Commit()

NAME

IStream::Commit() - Ensures that any changes made to a stream object open in transacted mode are reflected in the parent storage. If the stream object is open in direct mode, IStream::Commit() has no effect other than flushing all memory buffers to the next level storage object. The COM compound file implementation of streams does not support opening streams in transacted mode.

Synopsis

#include <objidl.h>

HRESULT Commit(
        DWORD grfCommitFlags );

Description

This method ensures that changes to a stream object opened in transacted mode are reflected in the parent storage. Changes that have been made to the stream since it was opened or last committed are reflected to the parent storage object. If the parent is opened in transacted mode, the parent may still revert at a later time rolling back the changes to this stream object. The compound file implementation does not support opening streams in transacted mode, so this method has very little effect other than to flush memory buffers. For more information, refer to Section Section 15.6.28.

If the stream is open in direct mode, this method ensures that any memory buffers have been flushed out to the underlying storage object. This is much like a flush in traditional file systems.

The IStream::Commit() method is useful on a direct mode stream when the implementation of the IStream() interface is a wrapper for underlying file system APIs. In this case, IStream::Commit() would be connected to the file system's flush call.

See Also

IStream - Compound File Implementation, IStorage::Commit()

Parameters

grfCommitFlags

[in] Controls how the changes for the stream object are committed. See the STGC enumeration for a definition of these values.

Return Values

S_OK

Changes to the stream object were successfully committed to the parent level.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_MEDIUMFULL

The commit operation failed due to lack of space on the storage device.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::CopyTo()

NAME

IStream::CopyTo() - Copies a specified number of bytes from the current seek pointer in the stream to the current seek pointer in another stream.

Synopsis

#include <objidl.h>

HRESULT CopyTo(
        IStream * pstm,
        ULARGE_INTEGER cb,
        ULARGE_INTEGER * pcbRead,
        ULARGE_INTEGER * pcbWritten );

Description

This method copies the specified bytes from one stream to another. The seek pointer in each stream instance is adjusted for the number of bytes read or written. This method is equivalent to reading cb bytes into memory using IStream::Read() and then immediately writing them to the destination stream using IStream::Write(), although IStream::CopyTo() will be more efficient.

The destination stream can be a clone of the source stream created by calling the IStream::Clone() method.

If IStream::CopyTo() returns an error, you cannot assume that the seek pointers are valid for either the source or destination. Additionally, the values of pcbRead and pcbWritten are not meaningful even though they are returned.

If IStream::CopyTo() returns successfully, the actual number of bytes read and written are the same.

To copy the remainder of the source from the current seek pointer, specify the maximum large integer value for the cb parameter. If the seek pointer is the beginning of the stream, this technique copies the entire stream.

See Also

IStream - Compound File Implementation, IStream::Read(), IStream::Write(), IStream::Clone()

Parameters

pstm

[in] Points to the destination stream. The stream pointed to by pstm can be a new stream or a clone of the source stream.

cb

[in] Specifies the number of bytes to copy from the source stream.

pcbRead

[out] Pointer to the location where this method writes the actual number of bytes read from the source. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes read.

pcbWritten

[out] Pointer to the location where this method writes the actual number of bytes written to the destination. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes written.

Return Values

S_OK

The stream object was successfully copied.

E_PENDING

Asynchronous Storage only: Part or all of the data to be copied is currently unavailable. For more information see Asynchronous Storage.

STG_E_INVALIDPOINTER

The value of one of the pointer parameters is not valid.

STG_E_MEDIUMFULL

The stream is not copied because there is no space left on the storage device.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::LockRegion()

NAME

IStream::LockRegion() - Restricts access to a specified range of bytes in the stream. Supporting this functionality is optional since some file systems do not provide it.

Synopsis

#include <objidl.h>

HRESULT LockRegion(
        ULARGE_INTEGER libOffset,
        ULARGE_INTEGER cb,
        DWORD dwLockType );

Description

The byte range can extend past the current end of the stream. Locking beyond the end of a stream is useful as a method of communication between different instances of the stream without changing data that is actually part of the stream.

Three types of locking can be supported: locking to exclude other writers, locking to exclude other readers or writers, and locking that allows only one requestor to obtain a lock on the given range, which is usually an alias for one of the other two lock types. A given stream instance might support either of the first two types, or both. The lock type is specified by dwLockType, using a value from the LOCKTYPE enumeration.

Any region locked with IStream::LockRegion() must later be explicitly unlocked by calling IStream::UnlockRegion() with exactly the same values for the libOffset, cb, and dwLockType parameters. The region must be unlocked before the stream is released. Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.

Notes to Callers

Since the type of locking supported is optional and can vary in different implementations of IStream(), you must provide code to deal with the STG_E_INVALIDFUNCTION error.

This method has no effect in the compound file implementation, because the implementation does not support range locking.

Notes to Implementors

Support for this method is optional for implementations of stream objects since it may not be supported by the underlying file system. The type of locking supported is also optional. The STG_E_INVALIDFUNCTION error is returned if the requested type of locking is not supported.

See Also

IStream - Compound File Implementation, LOCKTYPE, IStream::UnlockRegion()

Parameters

libOffset

[in] Integer that specifies the byte offset for the beginning of the range.

cb

[in] Integer that specifies the length of the range, in bytes, to be restricted.

dwLockType

[in] Specifies the restrictions being requested on accessing the range.

Return Values

S_OK

The specified range of bytes was locked.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_INVALIDFUNCTION

Locking is not supported at all or the specific type of lock requested is not supported.

STG_E_LOCKVIOLATION

Requested lock is supported, but cannot be granted because of an existing lock.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::Read()

NAME

IStream::Read() - Reads a specified number of bytes from the stream object into memory starting at the current seek pointer.

Synopsis

#include <objidl.h>

HRESULT Read(
        void * pv,
        ULONG cb,
        ULONG * pcbRead );

Description

This method reads bytes from this stream object into memory. The stream object must be opened in STGM_READ mode. This method adjusts the seek pointer by the actual number of bytes read.

The number of bytes actually read is returned in the pcbRead parameter.

Notes to Callers

The actual number of bytes read can be fewer than the number of bytes requested if an error occurs or if the end of the stream is reached during the read operation.

Some implementations might return an error if the end of the stream is reached during the read. You must be prepared to deal with the error return or S_OK return values on end of stream reads.

Parameters

pv

[in] Points to the buffer into which the stream is read. If an error occurs, this value is NULL.

cb

[in] Specifies the number of bytes of data to attempt to read from the stream object.

pcbRead

[out] Pointer to a location where this method writes the actual number of bytes read from the stream object. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the actual number of bytes read.

Return Values

S_OK

Data was successfully read from the stream object.

S_FALSE

The data could not be read from the stream object.

E_PENDING

Asynchronous Storage only: Part or all of the data to be read is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for reading this stream object.

STG_E_INVALIDPOINTER

One of the pointer values is invalid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

See Also

IStream - Compound File Implementation, STGMOVE, IStorage::OpenStream(), IStream::Write()  

IStream::Revert()

NAME

IStream::Revert() - Discards all changes that have been made to a transacted stream since the last IStream::Commit() call. On streams open in direct mode and streams using the COM compound file implementation of IStream::Revert(), this method has no effect.

Synopsis

#include <objidl.h>

HRESULT Revert(
        void );

Description

This method discards changes made to a transacted stream since the last commit operation.

See Also

IStream - Compound File Implementation, IStream::Commit()

Return Values

S_OK

The stream was successfully reverted to its previous version.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

 

IStream::Seek()

NAME

IStream::Seek() - Changes the seek pointer to a new location relative to the beginning of the stream, to the end of the stream, or to the current seek pointer.

Synopsis

#include <objidl.h>

HRESULT Seek(
        LARGE_INTEGER dlibMove,
        DWORD dwOrigin,
        ULARGE_INTEGER * plibNewPosition );

Description

IStream::Seek() changes the seek pointer so subsequent reads and writes can take place at a different location in the stream object. It is an error to seek before the beginning of the stream. It is not, however, an error to seek past the end of the stream. Seeking past the end of the stream is useful for subsequent writes, as the stream will at that time be extended to the seek position immediately before the write is done.

You can also use this method to obtain the current value of the seek pointer by calling this method with the dwOrigin parameter set to STREAM_SEEK_CUR and the dlibMove parameter set to 0 so the seek pointer is not changed. The current seek pointer is returned in the plibNewPosition parameter.

See Also

IStream - Compound File Implementation, STREAM_SEEK, IStream::Read(), IStream::Write()

Parameters

dlibMove

[in] Displacement to be added to the location indicated by dwOrigin. If dwOrigin is STREAM_SEEK_SET, this is interpreted as an unsigned value rather than signed.

dwOrigin

[in] Specifies the origin for the displacement specified in dlibMove. The origin can be the beginning of the file, the current seek pointer, or the end of the file. See the STREAM_SEEK enumeration for the values.

plibNewPosition

[out] Pointer to the location where this method writes the value of the new seek pointer from the beginning of the stream. You can set this pointer to NULL to indicate that you are not interested in this value. In this case, this method does not provide the new seek pointer.

Return Values

S_OK

The seek pointer has been successfully adjusted.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_INVALIDPOINTER

The value of the plibNewPosition parameter is not valid.

STG_E_INVALIDFUNCTION

The value of the dwOrigin parameter is not valid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::SetSize()

NAME

IStream::SetSize() - Changes the size of the stream object.

Synopsis

#include <objidl.h>

HRESULT SetSize(
        ULARGE_INTEGER libNewSize );

Description

IStream::SetSize() changes the size of the stream object. Call this method to preallocate space for the stream. If the libNewSize parameters larger than the current stream size, the stream is extended to the indicated size by filling the intervening space with bytes of undefined value. This operation is similar to the IStream::Write() method if the seek pointer is past the current end-of-stream.

If the libNewSize parameter is smaller than the current stream, then the stream is truncated to the indicated size.

The seek pointer is not affected by the change in stream size.

Calling IStream::SetSize() can be an effective way of trying to obtain a large chunk of contiguous space.

See Also

IStream - Compound File Implementation, IStream::Write()

Parameters

libNewSize

[in] Specifies the new size of the stream as a number of bytes.

Return Values

S_OK

The size of the stream object was successfully changed.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_MEDIUMFULL

The stream size is not changed because there is no space left on the storage device.

STG_E_INVALIDFUNCTION

The value of the libNewSize parameter is not valid. Since streams cannot be greater than 232 bytes in the COM-provided implementation, the high DWORD of libNewSize must be 0. If it is nonzero, this parameter is not valid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::Stat()

NAME

IStream::Stat() - Retrieves the STATSTG structure for this stream.

Synopsis

#include <objidl.h>

HRESULT Stat(
        STATSTG * pstatstg,
        DWORD grfStatFlag );

Description

IStream::Stat() retrieves a pointer to the STATSTG structure that contains information about this open stream. When this stream is within a structured storage and IStorage::EnumElements() is called, it creates an enumerator object with the IEnumSTATSTG() interface on it, which can be called to enumerate the storages and streams through the STATSTG structures associated with each of them.

Parameters

pstatstg

[out] Points to a STATSTG structure where this method places information about this stream object. This pointer is NULL if an error occurs.

grfStatFlag

[in] Specifies that this method does not return some of the fields in the STATSTG structure, thus saving a memory allocation operation. Values are taken from the STATFLAG enumeration.

Return Values

S_OK

The STATSTG structure was successfully returned at the specified location.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for accessing statistics for this storage object.

STG_E_INSUFFICIENTMEMORY

The STATSTG structure was not returned due to a lack of memory.

STG_E_INVALIDFLAG

The value for the grfStateFlag parameter is not valid.

STG_E_INVALIDPOINTER

The pStatStg pointer is not valid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

See Also

IStream - Compound File Implementation, STATFLAG, STATSTG  

IStream::UnlockRegion()

NAME

IStream::UnlockRegion() - Removes the access restriction on a range of bytes previously restricted with IStream::LockRegion().

Synopsis

#include <objidl.h>

HRESULT UnlockRegion(
        ULARGE_INTEGER libOffset,
        ULARGE_INTEGER cb,
        DWORD dwLockType );

Description

IStream::UnlockRegion() unlocks a region previously locked with the IStream::LockRegion() method. Locked regions must later be explicitly unlocked by calling IStream::UnlockRegion() with exactly the same values for the libOffset, cb, and dwLockType parameters. The region must be unlocked before the stream is released. Two adjacent regions cannot be locked separately and then unlocked with a single unlock call.

See Also

IStream - Compound File Implementation, LOCKTYPE, IStream::LockRegion()

Parameters

libOffset

[in] Specifies the byte offset for the beginning of the range.

cb

[in] Specifies, in bytes, the length of the range to be restricted.

dwLockType

[in] Specifies the access restrictions previously placed on the range.

Return Values

S_OK

The byte range was unlocked.

E_PENDING

Asynchronous Storage only: Part or all of the stream's data is currently unavailable. For more information see Asynchronous Storage.

STG_E_INVALIDFUNCTION

Locking is not supported at all or the specific type of lock requested is not supported.

STG_E_LOCKVIOLATION

The requested unlock cannot be granted.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

 

IStream::Write()

NAME

IStream::Write() - Writes a specified number from bytes into the stream object starting at the current seek pointer.

Synopsis

#include <objidl.h>

HRESULT Write(
        void const * pv,
        ULONG cb,
        ULONG * pcbWritten );

Description

IStream::Write() writes the specified data to a stream object. The seek pointer is adjusted for the number of bytes actually written. The number of bytes actually written is returned in the pcbWrite parameter. If the byte count is zero bytes, the write operation has no effect.

If the seek pointer is currently past the end of the stream and the byte count is non-zero, this method increases the size of the stream to the seek pointer and writes the specified bytes starting at the seek pointer. The fill bytes written to the stream are not initialized to any particular value. This is the same as the end-of-file behavior in the MS-DOS FAT file system.

With a zero byte count and a seek pointer past the end of the stream, this method does not create the fill bytes to increase the stream to the seek pointer. In this case, you must call the IStream::SetSize() method to increase the size of the stream and write the fill bytes.

The pcbWrite parameter can have a value even if an error occurs.

In the COM-provided implementation, stream objects are not sparse. Any fill bytes are eventually allocated on the disk and assigned to the stream.

Parameters

pv

[in] Points to the buffer from which the stream should be written.

cb

[in] The number of bytes of data to attempt to write into the stream.

pcbWritten

[out] Pointer to a location where this method writes the actual number of bytes written to the stream object. The caller can set this pointer to NULL, in which case, this method does not provide the actual number of bytes written.

Return Values

S_OK

The data was successfully written into the stream object.

E_PENDING

Asynchronous Storage only: Part or all of the data to be written is currently unavailable. For more information see Asynchronous Storage.

STG_E_MEDIUMFULL

The write operation was not completed because there is no space left on the storage device.

STG_E_ACCESSDENIED

The caller does not have sufficient permissions for writing this stream object.

STG_E_CANTSAVE

Data cannot be written for reasons other than no access or space.

STG_E_INVALIDPOINTER

One of the pointer values is invalid.

STG_E_REVERTED

The object has been invalidated by a revert operation above it in the transaction tree.

STG_E_WRITEFAULT

The write operation was not completed due to a disk error.

See Also

IStream - Compound File Implementation

15.6.28    IStream - Compound File Implementation

The IStream() interface supports reading and writing data to stream objects. Stream objects contain the data in a structured storage object, where storages provide the structure. Simple data can be written directly to a stream, but most frequently, streams are elements nested within a storage object. They are similar to standard files.

The specification of IStream() defines more functionality than the COM implementation supports. For example, the IStream() interface defines streams up to 264 bytes in length requiring a 64-bit seek pointer. However, the COM implementation only supports streams up to 232 bytes in length and read and write operations are always limited to 232 bytes at a time. The COM implementation also does not support stream transactioning or region locking.

When you want to create a simple stream based on global memory, you can get an IStream() pointer by calling the API function CreateStreamOnHGlobal(). To get an IStream() pointer within a compound file object, call either StgCreateDocfile() or StgOpenStorage(). These functions retrieve an IStorage() pointer, with which you can then call CreateStream/OpenStream for an IStream() pointer. In either case, the same IStream() implementation code is used.

When to Use

Call the methods of IStream() to read and write data to a stream.

Since stream objects can be marshaled to other processes, applications can share the data in storage objects without having to use global memory. In the COM compound file implementation of stream objects, the custom marshaling facilities in COM create a remote version of the original object in the new process when the two processes have shared memory access. Thus, the remote version does not need to communicate with the original process to carry out its functions.

The remote version of the stream object shares the same seek pointer as the original stream. If you do not want to share the seek pointer, you should use the IStream::Clone() method to provide a copy of the stream object for the remote process.

Notes

If you are creating a stream object that is larger than the heap in your machine's memory and you are using an HGLOBAL, the stream object calls GlobalRealloc internally whenever it needs more memory. Because GlobalRealloc always copies data from the source to the destination, increasing a stream object from 20M to 25M, for example, consumes immense amounts of time. This is due to the size of the increments copied and is worsened if there is less than 45M of memory on the machine because of disk swapping.

The preferred solution is to implement an IStream() that uses memory allocated by VirtualAlloc instead of GlobalAlloc. This can reserve a large chunk of virtual address space and then commit memory within that address space as required. No data copying occurs and memory is committed only as it is needed.

Another alternative is to call the IStream::SetSize() method on the stream object to increase the memory allocation in advance. This is not, however, as efficient as using VirtualAlloc as described above.

Description

IStream::Read()

Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. This implementation returns S_OK if the end of the stream was reached during the read. (This is the same as the ``end of file'' behavior found in the MS-DOS FAT file system.

IStream::Write()

Writes a specified number from bytes into the stream object starting at the current seek pointer. In this implementation, stream objects are not sparse. Any fill bytes are eventually allocated on the disk and assigned to the stream.

IStream::Seek()

Changes the seek pointer to a new location relative to the beginning of the stream, to the end of the stream, or to the current seek pointer.

IStream::SetSize()

Changes the size of the stream object. In this implementation, there is no guarantee that the space allocated will be contiguous

IStream::CopyTo()

Copies a specified number of bytes from the current seek pointer in the stream to the current seek pointer in another stream.

IStream::Commit()

The compound file implementation of IStream() supports opening streams only in direct mode, not transacted mode. Therefore, the method has no effect when called other than to flush all memory buffers to the next storage level.

In this implementation, it does not matter if you commit changes to streams, you need only commit changes for storage objects.

IStream::Revert()

This implementation does not support transacted streams, so a call to this method has no effect.

IStream::LockRegion()

Range-locking is not supported by this implementation, so a call to this method has no effect.

IStream::UnlockRegion()

Removes the access restriction on a range of bytes previously restricted with IStream::LockRegion().

IStream::Stat()

Retrieves the STATSTG structure for this stream

IStream::Clone()

Creates a new stream object with its own seek pointer that references the same bytes as the original stream.

See Also

IStream(), IStorage(), CreateStreamOnHGlobal(), StgCreateDocfile(), StgOpenStorage()

15.7    Persistent Storage API Descriptions

 

FreePropVariantArray()

NAME

FreePropVariantArray() - Calls PropVariantClear() on each of the PROPVARIANTs in the rgvar array to zero the value of each of the members of the array.

Synopsis

#include <objidl.h>

HRESULT FreePropVariantArray((
        ULONG cVariant,
        PROPVARIANT * rgvar[] );

Description

FreePropVariantArray() calls PropVariantClear() on an array of PROPVARIANTs to clear all the valid members. All valid PROPVARIANTS are freed. If any of the PROPVARIANTs contain illegal VT-types, valid members are freed and the function returns STG_E_INVALIDPARAMETER.

Passing NULL for rgvar is legal, and produces a return code of S_OK.

Parameters

cVariant

[in] Count of elements in the PROPVARIANT array (rgvar).

rgvar

[in] Pointer to an initialized array of PROPVARIANT structures for which any deallocatable elements are to be freed. On exit, all zeroes are written to the PROPVARIANT (thus tagging them as VT_EMPTY).

Return Values

S_OK

The variant types are recognized and all items that can be freed have been freed.

STG_E_INVALID_PARAMETER

One or more PROPVARIANTs has an unknown type.

See Also

PropVariantClear()  

PropStgNameToFmtId()

NAME

PropStgNameToFmtId() - Converts a property set's storage or stream name to its format identifier.

Synopsis

#include <objidl.h>

HRESULT PropStgNameToFmtId((
        const LPOLESTR oszName,
        FMTID * pfmtid );

Description

ProgStgNameToFmtId maps a simple property set's stream name or a non-simple property set's storage name to its format identifier.

This function is useful in creating or opening a property set using the PROPSETFLAG_UNBUFFERED value with the StgCreatePropStg() and StgOpenPropStg() functions. See the PROPSETFLAG enumeration for more information on the use of PROPSETFLAG_UNBUFFERED.

1.  PropStgNameToFmtId Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

Parameters

oszName

[in] Pointer to a string containing the stream name of a simple property set or the storage name of a nonsimple property set.

pfmtid

[out] Pointer to a FMTID variable that receives the format identifier of the property set specified by oszName.

Return Values

This function supports the standard return value E_INVALIDARG as well as the following:

S_OK

The format identifier of the property set was successfully returned.

STG_E_INVALIDNAME

The oszName parameter was invalid.

See Also

PROPSETFLAG, StgCreatePropStg(), StgOpenPropStg()  

PropVariantClear()

NAME

PropVariantClear() - Frees all elements that can be freed in a given PROPVARIANT structure.

Synopsis

#include <objidl.h>

HRESULT PropVariantClear((
        PROPVARIANT * pvarg );

Description

At any level of indirection, a NULL pointer is ignored. For example, in a VT_CF PROPVARIANT, the pvarg-pclipdatap-ClipData could be NULL. In this case, the pvarg-pclipdatap-ClipData pointer would be ignored, but the pvarg-pclipdata pointer would be freed.

On return, this function writes zeroes to the specified PROPVARIANT, so the VT-type is VT_EMPTY.

Passing NULL as the pvarg parameter produces a return code of S_OK.

Parameters

pvarg

[in] Pointer to an initialized PROPVARIANT structure for which any deallocatable elements are to be freed. On return, all zeroes are written to the PROPVARIANT.

Return Values

S_OK

The VT types are recognized and all items that can be freed have been freed.

STG_E_INVALID_PARAMETER

The variant has an unknown VT type.

See Also

FreePropVariantArray()  

PropVariantCopy()

NAME

PropVariantCopy() - Copies the contents of a PROPVARIANT structure to another.

Synopsis

#include <objidl.h>

HRESULT PropVariantCopy((
        PROPVARIANT * pDest,
        PROPVARIANT * pvarg );

Description

Copies a PROPVARIANT by value so the original pvarg and new pDest may be freed independently with calls to PropVariantClear(). For non-simple PROPVARIANT types such as VT_STREAM, VT_STORAGE, etc, which require a subobject, the copy is made by reference. The pointer is copied and AddRef() is called on it. It is illegal to pass NULL for either pDest or pvarg.

Parameters

pDest

[in, out] Pointer to an uninitialized PROPVARIANT structure that receives the copy.

pvarg

[in] Pointer to the PROPVARIANT to be copied.

Return Values

S_OK

The copy was successfully completed.

STG_E_INVALID_PARAMETER

The variant has an unknown type.

 

ReadClassStg()

NAME

ReadClassStg() - Reads the CLSID previously written to a storage object with the WriteClassStg().

Synopsis

#include <ole2.h>

WINOLEAPI ReadClassStg((
        IStorage * pStg,
        CLSID * pclsid );

Description

This function is simply a helper function that calls the IStorage::Stat() method and retrieves the CLSID previously written to the storage object with a call to WriteClassStg() from the STATSTG structure.

Parameters

pStg

[in] Pointer to the IStorage() interface on the storage object containing the CLSID to be retrieved.

pclsid

[out] Pointer to where the CLSID is written. May return CLSID_NULL.

Return Values

This function supports the standard return value E_OUTOFMEMORY, as well as the following:

S_OK

The CLSID was returned successfully.

This function also returns any of the error values returned by the IStorage::Stat() method.

See Also

WriteClassStg, IStorage::Stat(), STATSTG structure.  

ReadClassStm()

NAME

ReadClassStm() - Reads the CLSID previously written to a stream object with the WriteClassStm() method.

Synopsis

#include <ole2.h>

WINOLEAPI ReadClassStm((
        IStream * pStm,
        CLSID * pclsid );

Description

Most applications do not call the ReadClassStm() method directly. COM calls it before making a call to an object's IPersistStream::Load() implementation.

Parameters

pStm

[in] Pointer to the IStream() interface on the stream object containing the CLSID to be read. This CLSID must have been previously written to the stream object using WriteClassStm().

pclsid

[out] Pointer to where the CLSID is to be written.

Return Values

S_OK

The CLSID was successfully retrieved.

STG_E_READFAULT

End of file was reached.

This function also returns any of the error values returned by the IStream::Read() method.

See Also

WriteClassStm(), ReadClassStg,WriteClassStg  

ReadFmtUserTypeStg()

NAME

ReadFmtUserTypeStg() - Returns the clipboard format and user type previously saved with the WriteFmtUserTypeStg() function.

Synopsis

#include <ole2.h>

WINOLEAPI ReadFmtUserTypeStg((
        IStorage * pStg,
        CLIPFORMAT * pcf,
        LPWSTR * lplpszUserType );

Description

This function returns the clipboard format and the user type string from the specified storage object. The WriteClassStg() function must have been called before calling the ReadFmtUserTypeStg() function.

Parameters

pStg

[in] Pointer to the IStorage() interface on the storage object from which the information is to be read.

pcf

[out] Pointer to where the clipboard format is to be written on return. It can be NULL, indicating the format is of no interest to the caller.

lplpszUserType

[out] Address of LPWSTR pointer variable that receives a pointer to the user type string. The caller can specify NULL for this parameter, indicating that the user type is of no interest. This function allocates memory for the string. The caller is responsible for freeing the memory with CoTaskMemFree().

Return Values

This function supports the standard return values E_FAIL, E_INVALIDARG, and E_OUTOFMEMORY, as well as the following:

S_OK

The requested information was read successfully.

This function also returns any of the error values returned by the IStream::Read() method.

See Also

CoTaskMemFree(), WriteFmtUserTypeStg()  

SetConvertStg()

NAME

SetConvertStg() - Sets the convert bit in a storage object to indicate that the object is to be converted to a new class when it is opened. The setting can be retrieved with a call to the GetConvertStg() function.

Synopsis

#include <ole2.h>

WINOLEAPI SetConvertStg((
        IStorage * pStg,
        BOOL fConvert );

Description

The SetConvertStg() function determines the status of the convert bit in a contained object. It is called by both the container application and the server in the process of converting an object from one class to another. When a user specifies through a Convert To dialogue (which the container produces with a call to the OleUIConvert function) that an object is to be converted, the container must take the following steps:

  1. Unload the object if it is currently loaded.

  2. Call WriteClassStg() to write the new CLSID to the object storage.

  3. Call WriteFmtUserTypeStg() to write the new user type name and the existing main format to the storage.

  4. Call SetConvertStg() with the fConvert parameter set to TRUE to indicate that the object has been tagged for conversion to a new class the next time it is loaded.

  5. Just before the object is loaded, call OleDoAutoConvert to handle any needed object conversion, unless you call OleLoad, which calls it internally.

When an object is initialized from a storage object and the server is the destination of a Convert To operation, the object server should do the following:

  1. Call the GetConvertStg() function to retrieve the value of the conversion bit.

  2. If the bit is set, the server reads the data out of the object according to the format associated with the new CLSID.

  3. When the object is asked to save itself, the object should call WriteFmtUserType() using the normal native format and user type of the object.

  4. The object should then call SetConvertStg() with the fConvert parameter set to FALSE to reset the object's conversion bit.

Parameters

pStg

IStorage() pointer to the storage object in which to set the conversion bit.

fConvert

If TRUE, sets the conversion bit for the object to indicate the object is to be converted when opened. If FALSE, clears the conversion bit.

Return Values

S_OK

Indicates the object's conversion bit was set successfully.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

E_OUTOFMEMORY

Indicates the conversion bit was not set due to a lack of memory.

E_INVALIDARG

Indicates one or more arguments are invalid.

E_UNEXPECTED

Indicates an unexpected error occurred.

See the IStorage::CreateStream(), IStorage::OpenStream(), ISequentialStream::Read, and ISequentialStream::Write methods for possible storage and stream access errors.

See Also

GetConvertStg()  

StgCreateDocfile()

NAME

StgCreateDocfile() - Creates a new compound file storage object using the COM-provided compound file implementation for the IStorage() interface.

Synopsis

#include <objbase.h>

WINOLEAPI StgCreateDocfile((
        const WCHAR * pwcsName,
        DWORD grfMode,
        DWORD reserved,
        IStorage ** ppstgOpen );

Description

The StgCreateDocfile() function creates a new storage object using the COM-provided, compound-file implementation for the IStorage() interface. The name of the open compound file can be retrieved by calling the IStorage::Stat() method.

StgCreateDocfile() creates the file if it does not exist. If it does exist, the use of the STGM_CREATE, STGM_CONVERT, and STGM_FAILIFTHERE flags in the grfMode parameter indicate how to proceed. See the STGM enumeration for more information on these values.

If the compound file is opened in transacted mode (the grfMode parameter specifies STGM_TRANSACTED) and a file with this name already exists, the existing file is not altered until all outstanding changes are committed. If the calling process lacks write access to the existing file (because of access control in the file system), the grfMode parameter can only specify STGM_READ and not STGM_WRITE or STGM_READWRITE. The resulting new open compound file can still be written to, but a subsequent commit operation will fail (in transacted mode, write permissions are enforced at commit time).

Specifying STGM_SIMPLE provides a much faster implementation of a compound file object in a limited, but frequently-used case. This can be used by applications that require a compound file implementation with multiple streams and no storages. The simple mode does not support all of the methods on IStorage(). For more information, refer to the STGM enumeration.

If the grfMode parameter specifies STGM_TRANSACTED and no file yet exists with the name specified by the pwcsName parameter, the file is created immediately. In an access-controlled file system, the caller must have write permissions in the file system directory in which the compound file is created. If STGM_TRANSACTED is not specified, and STGM_CREATE is specified, an existing file with the same name is destroyed before creating the new file.

StgCreateDocfile() can be used to create a temporary compound file by passing a NULL value for the pwcsName parameter. However, these files are temporary only in the sense that they have a system-provided unique name-- one that is probably meaningless to the user. The caller is responsible for deleting the temporary file when finished with it, unless STGM_DELETEONRELEASE was specified for the grfMode parameter.

Parameters

pwcsName

[in] Points to the path of the compound file to create. It is passed uninterpreted to the file system. This can be a relative name or NULL. If NULL, a temporary compound file is allocated with a unique name.

grfMode

[in] Specifies the access mode to use when opening the new storage object. For more information, see the STGM enumeration. If the caller specifies transacted mode together with STGM_CREATE or STGM_CONVERT, the overwrite or conversion takes place at the time the storage object is opened and therefore is not revertible.

reserved

[in] Reserved for future use; must be zero.

ppstgOpen

[out] Points to the location of the IStorage() pointer to the new storage object.

Return Values

S_OK

Indicates the compound file was successfully created.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

STG_E_FILEALREADYEXISTS

Indicates the compound file already exists and grfMode is set to STGM_FAILIFTHERE.

STG_S_CONVERTED

Indicates the specified file was successfully converted to Storage format.

STG_E_INSUFFICIENTMEMORY

Indicates the compound file was not created due to a lack of memory.

STG_E_INVALIDNAME

Indicates bad name in the pwcsName parameter.

STG_E_INVALIDPOINTER

Indicates bad pointer in the pwcsName parameter or the ppStgOpen parameter.

STG_E_INVALIDFLAG

Indicates bad flag combination in the grfMode pointer.

STG_E_TOOMANYOPENFILES

Indicates the compound file was not created due to a lack of file handles.

STG_E_SHAREVIOLATION

Access denied because another caller has the file open and locked.

See also any file system errors for other error return values.

See Also

StgCreateDocFileOnILockBytes  

StgCreateDocfileOnILockBytes()

NAME

StgCreateDocfileOnILockBytes() - Creates and opens a new compound file storage object on top of a byte array object provided by the caller. The storage object supports the COM-provided, compound-file implementation for the IStorage() interface.

Synopsis

#include <objbase.h>

WINOLEAPI StgCreateDocfileOnILockBytes((
        ILockBytes * plkbyt,
        DWORD grfMode,
        DWORD reserved,
        IStorage ** ppstgOpen );

Description

The StgCreateDocfileOnILockBytes() function creates a storage object on top of a byte array object using the COM-provided, compound-file implementation of the IStorage() interface. StgCreateDocfileOnILockBytes() can be used to store a document in a relational database. The byte array (indicated by the pLkbyt parameter, which points to the ILockBytes() interface on the object) is used for the underlying storage in place of a disk file.

Except for specifying a programmer-provided byte-array object, StgCreateDocfileOnILockBytes() is similar to the StgCreateDocfile() function. For more information, refer to StgCreateDocfile().

The newly created compound file is opened according to the access modes in the grfMode parameter. For conversion purposes, the file is always considered to already exist. As a result, it is not useful to use the STGM_FAILIFTHERE value, because it always causes an error to be returned. However, STGM_CREATE and STGM_CONVERT are both still useful.

The ability to build a compound file on top of a byte array object is provided to support having the data (underneath an IStorage() and IStream() tree structure) live in a non-persistent space. Given this capability, there is nothing preventing a document that is stored in a file from using this facility. For example, a container might do this to minimize the impact on its file format caused by adopting COM. However, it is recommended that COM documents adopt the IStorage() interface for their own outer-level storage. This has the following advantages:

Parameters

plkbyt

[in] Points to the ILockBytes() interface on the underlying byte array object on which to create a compound file.

grfMode

[in] Specifies the access mode to use when opening the new compound file. For more information, see the STGM enumeration.

reserved

[in] Reserved for future use; must be zero.

ppstgOpen

[out] Points to the location of the IStorage() pointer on the new storage object.

This function can also return any file system errors or Win32 errors wrapped in an HRESULT.

Return Values

S_OK

Indicates the compound file was successfully created.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_FILEALREADYEXISTS

Indicates the compound file already exists and the grfMode parameter is set to STGM_FAILIFTHERE.

STG_E_INSUFFICIENTMEMORY

Indicates the storage object was not created due to a lack of memory.

STG_E_INVALIDPOINTER

Indicates a bad pointer was in the pLkbyt parameter or the ppStgOpen parameter.

STG_E_INVALIDFLAG

Indicates a bad flag combination was in the grfMode parameter.

STG_E_TOOMANYOPENFILES

Indicates the storage object was not created due to a lack of file handles.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

STG_E_SHAREVIOLATION

Access denied because another caller has the file open and locked.

STG_S_CONVERTED

Indicates the compound file was successfully converted. The original byte array object was successfully converted to IStorage() format.

This function can also return any file system errors, or Win32 errors wrapped in an HRESULT, or ILockBytes() interface error return values.

See Also

StgCreateDocfile()  

StgCreatePropSetStg()

NAME

StgCreatePropSetStg() - Creates a property set storage object from a specified storage object. The property set storage object supplies the system-provided, standalone implementation of the IPropertySetStorage() interface.

Synopsis

#include <objidl.h>

HRESULT StgCreatePropSetStg((
        IStorage * pStorage,
        DWORD dwReserved,
        IPropertySetStorage ** ppPropSetStg );

Description

StgCreatePropSetStg() calls IUnknown::AddRef() on the storage object specified by pStorage. The caller is responsible for releasing the object when it is no longer needed.

1.  StgCreatePropSetStg Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

Parameters

pStorage

[in] Pointer to the storage object that contains one or more property sets.

dwReserved

Reserved for future use; must be zero.

ppPropSetStg

[out] Address of IPropertySetStorage() pointer variable that receives the interface pointer to the property set storage object.

Return Values

This function supports the standard return value E_INVALIDARG as well as the following:

S_OK

The property set storage object was successfully created.

See Also

IPropertySetStorage-Standalone Implementation  

StgCreatePropStg()

NAME

StgCreatePropStg() - Creates and opens a property set in a specified storage or stream object. The property set supplies the system-provided, standalone implementation of the IPropertyStorage() interface.

Synopsis

#include <objidl.h>

HRESULT StgCreatePropStg((
        IUnknown * pUnk,
        REFFMTID fmtid,
        const CLSID * pclsid,
        DWORD grfFlags,
        DWORD dwReserved,
        IPropertyStorage ** ppPropStg );

Description

StgCreatePropStg() creates and opens a new property set which supplies the system-provided, standalone implementation of the IPropertyStorage() interface. The new property set is contained in the storage or stream object specified by pUnk. The value of the grfFlags parameter indicates whether pUnk specifies a storage or stream object. For example, if PROPSETFLAG_NONSIMPLE is set, then pUnk can be queried for an IStorage() interface on a storage object.

In either case, this function calls pUnk->AddRef for the storage or stream object containing the property set. It is the responsibility of the caller to release the object when it is no longer needed.

This function is similar to the IPropertySetStorage::Create() method. However, StgCreatePropStg() adds the pUnk parameter and supports the PROPSETFLAG_UNBUFFERED value for the grfFlags parameter. Use this function instead of the Create method if you have an IStorage() interface that does not support the IPropertySetStorage() interface, or if you want to use the PROPSETFLAG_UNBUFFERED value. See the PROPSETFLAG enumeration for more information on using this PROPSETFLAG_UNBUFFERED.

The property set automatically contains code page and locale ID properties. These are set to the current system default and the current user default, respectively.

The grfFlags parameter is a combination of values taken from the enumeration PROPSETFLAG. The new enumeration value PROPSETFLAG_UNBUFFERED is supported. See the PROPSETFLAG enumeration for more information on the use of this value.

1.  StgCreatePropStg Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

Parameters

pUnk

[in] Pointer to the IUnknown() interface on the storage or stream object that stores the new property set.

fmtid

[in] Format identifier of the property set to be created.

pclsid

[in] Pointer to the initial CLSID for this property set. May be NULL, in which case pclsid is set to all zeroes.

grfFlags

[in] Values from the PROPSETFLAG enumeration that determine how the property set is created and opened.

dwReserved

[in] Reserved; must be zero.

ppPropStg

[out] Address of the IPropertyStorage() pointer variable that receives the interface pointer to the new property set.

Return Values

This function supports the standard return values E_INVALIDARG and E_UNEXPECTED, as well as the following:

S_OK

The property set was created.

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied.

STG_E_INVALIDHEADER

The property set is corrupted.

STG_E_INSUFFICIENTMEMORY

There is not enough memory to perform this operation.

STG_E_INVALIDFLAG

A flag in the grfMode or grfFlags parameter was invalid.

STG_E_INVALIDPARAMETER

A parameter is invalid.

STG_E_MEDIUMFULL

The storage object could not be increased in size to hold the default property set.

See Also

IPropertySetStorage(), IPropertySetStorage-Standalone Implementation, IPropertyStorage(), IPropertyStorage-Standalone Implementation, PROPSETFLAG, StgOpenPropStg(), StgCreatePropSetStg()  

StgIsStorageFile()

NAME

StgIsStorageFile() - Indicates whether a particular disk file contains a storage object.

Synopsis

#include <objbase.h>

WINOLEAPI StgIsStorageFile((
        const WCHAR * pwcsName );

Description

At the beginning of the disk file underlying a storage object is a signature distinguishing a storage object from other file formats. The StgIsStorageFile() function is useful to applications whose documents use a disk file format that might or might not use storage objects.

If a root compound file has been created in transacted mode but not yet committed, this method still returns S_OK.

Parameters

pwcsName

[in] Points to the name of the disk file to be examined. The pwcsName parameter is passed uninterpreted to the underlying file system.

Return Values

S_OK

Indicates the file contains a storage object.

S_FALSE

Indicates the file does not contain a storage object.

STG_E_INVALIDFILENAME

Indicates a bad filename was passed in the pwcsName parameter.

STG_E_FILENOTFOUND

Indicates the file was not found.

This function can also return any file system errors or Win32 errors wrapped in an HRESULT.

See Also

StgIsStorageILockBytes()  

StgIsStorageILockBytes()

NAME

StgIsStorageILockBytes() - Indicates whether the specified byte array contains a storage object.

Synopsis

#include <objbase.h>

WINOLEAPI StgIsStorageILockBytes((
        ILockBytes * plkbyt );

Description

At the beginning of the byte array underlying a storage object is a signature distinguishing a storage object (supporting the IStorage() interface) from other file formats. The StgIsStorageILockBytes() function is useful to applications whose documents use a byte array (a bye array object supports the ILockBytes() interface) that might or might not use storage objects.

Parameters

plkbyt

ILockBytes() pointer to the byte array to be examined.

Return Values

S_OK

Indicates the specified byte array contains a storage object.

S_FALSE

Indicates the specified byte array does not contain a storage object.

This function can also return any file system errors, or Win32 errors wrapped in an HRESULT, or ILockBytes() interface error return values.

See Also

StgIsStorageFile(), ILockBytes()  

StgOpenPropStg()

NAME

StgOpenPropStg() - Opens a specified property set in a specified storage or stream object. The property set supplies the system-provided, standalone implementation of the IPropertyStorage() interface.

Synopsis

#include <objidl.h>

HRESULT StgOpenPropStg((
        IUnknown * pUnk,
        REFFMTID fmtid,
        DWORD grfFlags,
        DWORD dwReserved,
        IPropertyStorage ** ppPropStg );

Description

StgOpenPropStg() opens the requested property set and supplies the system-provided, standalone implementation of the IPropertyStorage() interface. The requested property set is contained in the storage or stream object specified by pUnk. The value of the grfFlags parameter indicates whether pUnk specifies a storage or stream object. For example, if PROPSETFLAG_NONSIMPLE is set, then pUnk can be queried for an IStorage() interface on a storage object.

In either case, this function calls pUnk->AddRef for the storage or stream object containing the property set. It is the responsibility of the caller to release the object when it is no longer needed.

This function is similar to the IPropertySetStorage::Open() method. However, StgOpenPropStg() adds the pUnk and grfFlags parameters, including the PROPSETFLAG_UNBUFFERED value for the grfFlags parameter. Use this function instead of the Open method if you have an IStorage() interface that does not support the IPropertySetStorage() interface, or if you want to use the PROPSETFLAG_UNBUFFERED value. See the PROPSETFLAG enumeration for more information on using PROPSETFLAG_UNBUFFERED.

The grfFlags parameter is a combination of values taken from the enumeration PROPSETFLAG. The new enumeration value PROPSETFLAG_UNBUFFERED is supported. See the PROPSETFLAG enumeration for more information on the use of this value.

1.  StgOpenPropStg Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

Parameters

pUnk

[in] Interface pointer for IUnknown() interface on the storage or stream object that contains the requested property set object.

fmtid

[in] Format identifier of the property set to be opened.

grfFlags

[in] Values from the PROPSETFLAG enumeration.

dwReserved

[in] Reserved for future use; must be zero.

ppPropStg

[out] Address of IPropertyStorage() pointer variable that receives the interface pointer to the requested property set.

Return Values

This function supports the standard return values E_INVALIDARG and E_UNEXPECTED, as well as the following:

S_OK

The property set was opened.

STG_E_FILENOTFOUND

A property set was not found in the specified object (pUnk).

STG_E_ACCESSDENIED

The requested access to the property storage object has been denied, or the property set is corrupted.

STG_E_INVALIDHEADER

The property set is corrupted.

STG_E_INSUFFICIENTMEMORY

There is not enough memory to perform this operation.

STG_E_INVALIDFLAG

A flag in the grfMode or grfFlags parameter was invalid.

STG_E_INVALIDPARAMETER

A parameter is invalid.

See Also

IPropertySetStorage(), IPropertySetStorage-Standalone Implementation, IPropertyStorage(), IPropertyStorage-Standalone Implementation, PROPSETFLAG, StgCreatePropStg(), StgCreatePropSetStg()  

StgOpenStorage()

NAME

StgOpenStorage() - Opens an existing root storage object in the file system. You can use this function to open compound files, but you cannot use it to open directories, files, or summary catalogs. Nested storage objects can only be opened using their parent's IStorage::OpenStorage() method.

Synopsis

#include <objbase.h>

WINOLEAPI StgOpenStorage((
        const WCHAR * pwcsName,
        IStorage * pstgPriority,
        DWORD grfMode,
        SNB snbExclude,
        DWORD reserved,
        IStorage ** ppstgOpen );

Description

The StgOpenStorage() function opens the specified root storage object according to the access mode in the grfMode parameter, and, if successful, supplies an IStorage() pointer to the opened storage object in the ppstgOpen parameter.

To support the Simple mode for saving a storage object with no substorages, the StgOpenStorage() function accepts the following flag combinations as valid modes in the grfMode parameter: STGM_SIMPLE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE and STGM_SIMPLE|STGM_READ|STGM_SHARE_EXCLUSIVE.

To support the single-writer, multi-reader, direct mode, the following flag combinations are valid modes in the grfMode parameter: STGM_READWRITE|STGM_SHARE_DENY_WRITE and STGM_READ|STGM_SHARE_DENY_NONE.

Notes

Opening a storage object in read and/or write mode without denying writer permission to others (the grfMode parameter specifies STGM_SHARE_DENY_WRITE) can be a time-consuming operation since the StgOpenStorage() call must make a snapshot of the entire storage object.

Applications often try to open storage objects with the following access permissions:

STGM_READ_WRITE | STGM_SHARE_DENY_WRITE 
    // transacted vs. direct mode omitted for exposition

If the application succeeds, it never needs to do a snapshot copy. If it fails, the application can revert to using the permissions and make a snapshot copy:

STGM_READ_WRITE 
    // transacted vs. direct mode omitted for exposition

In this case, the application should prompt the user before doing a time-consuming copy. Alternatively, if the document sharing semantics implied by the access modes are appropriate, the application could try to open the storage as follows:

STGM_READ | STGM_SHARE_DENY_WRITE 
    // transacted vs. direct mode omitted for exposition

In this case, if the application succeeds, a snapshot copy will not have been made (because STGM_SHARE_DENY_WRITE was specified, denying others write access).

To reduce the expense of making a snapshot copy, applications can open storage objects in priority mode (grfMode specifies STGM_PRIORITY).

The snbExclude parameter specifies a set of element names in this storage object that are to be emptied as the storage object is opened: streams are set to a length of zero; storage objects have all their elements removed. By excluding certain streams, the expense of making a snapshot copy can be significantly reduced. Almost always, this approach is used after first opening the storage object in priority mode, then completely reading the now-excluded elements into memory. This earlier priority mode opening of the storage object should be passed through the pstgPriority parameter to remove the exclusion implied by priority mode. The calling application is responsible for rewriting the contents of excluded items before committing. Thus, this technique is most likely only useful to applications whose documents do not require constant access to their storage objects while they are active.

Parameters

pwcsName

[in] Points to the path of the file storage object to open. This parameter is ignored if the pStgPriority parameter is not NULL.

pstgPriority

[in] Most often NULL. If not NULL, this parameter is used instead of the pwcsName parameter to specify the pointer to the IStorage() interface on the storage object to open. It points to a previous opening of a root storage object, most often one that was opened in priority mode.

After the StgOpenStorage() function returns, the storage object specified in the pStgPriority parameter on function entry is invalid, and can no longer be used. Instead, use the one specified in the ppStgOpen parameter.

grfMode

[in] Specifies the access mode to use to open the storage object.

snbExclude

[in] If not NULL, this parameter points to a block of elements in this storage that are to be excluded as the storage object is opened. The exclusion occurs independent of whether a snapshot copy happens on the open. May be NULL.

reserved

[in] Indicates reserved for future use; must be zero.

ppstgOpen

[out] Address of IStorage* pointer variable that receives the interface pointer to the opened storage.

Return Values

S_OK

Indicates the storage object was successfully opened.

STG_E_FILENOTFOUND

Indicates the specified file does not exist.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

STG_E_SHAREVIOLATION

Access denied because another caller has the file open and locked.

STG_E_FILEALREADYEXISTS

Indicates the file exists but is not a storage object.

STG_E_TOOMANYOPENFILES

Indicates the storage object was not opened because there are too many open files.

STG_E_INSUFFICIENTMEMORY

Indicates the storage object was not opened due to a lack of memory.

STG_E_INVALIDNAME

Indicates bad name in the pwcsName parameter.

STG_E_INVALIDPOINTER

Indicates bad pointer in one of the parameters: snbExclude, pwcsName, pstgPriority, or ppStgOpen.

STG_E_INVALIDFLAG

Indicates bad flag combination in the grfMode parameter.

STG_E_INVALIDFUNCTION

Indicates STGM_DELETEONRELEASE specified in the grfMode parameter.

STG_E_OLDFORMAT

Indicates the storage object being opened was created by the Beta 1 storage provider. This format is no longer supported.

STG_E_NOTSIMPLEFORMAT

Indicates that the STGM_SIMPLE flag was specified in the grfMode parameter and the storage object being opened was not written in simple mode.

STG_E_OLDDLL

Indicates the DLL being used to open this storage object is a version prior to the one used to create it.

STG_E_PATHNOTFOUND

Specified path does not exist.

This function can also return any file system errors or Win32 errors wrapped in an HRESULT.

See Also

IStorage(), StgCreateDocfile(), StgOpenStorageEx  

StgOpenStorageOnILockBytes()

NAME

StgOpenStorageOnILockBytes() - Opens an existing storage object that does not reside in a disk file, but instead has an underlying byte array provided by the caller.

Synopsis

#include <objbase.h>

WINOLEAPI StgOpenStorageOnILockBytes((
        ILockBytes * plkbyt,
        IStorage * pStgPriority,
        DWORD grfMode,
        SNB snbExclude,
        DWORD reserved,
        IStorage ** ppstgOpen );

Description

StgOpenStorageOnILockBytes() opens the specified root storage object. The storage object is opened according to the access mode in the grfMode parameter; a pointer to the IStorage() interface on the opened storage object is supplied through the ppstgOpen parameter.

The storage object must have been previously created by the StgCreateDocfileOnILockBytes() function.

Except for specifying a programmer-provided byte-array object, StgOpenStorageOnILockBytes() is similar to the StgOpenStorage() function. For more information, refer to StgOpenStorage().

Parameters

plkbyt

[in] ILockBytes() pointer to the underlying byte array object that contains the storage object to be opened.

pStgPriority

[in] Most often NULL. If not NULL, this parameter is used instead of the plkbyt parameter to specify the storage object to open. In this case, it points to the IStorage() interface on a previously opened root storage object, most often one that was opened in priority mode.

After the StgOpenStorageOnILockBytes() function returns, the storage object specified in the pStgPriority parameter on function entry is invalid, and can no longer be used; use the one specified in the ppStgOpen parameter instead.

grfMode

[in] Specifies the access mode to use to open the storage object.

snbExclude

[in] Can be NULL. If not NULL, this parameter points to a block of elements in this storage that are to be excluded as the storage object is opened. This exclusion occurs independent of whether a snapshot copy happens on the open.

reserved

[in] Indicates reserved for future use; must be zero.

ppstgOpen

[out] Points to the location of an IStorage() pointer to the opened storage on successful return.

Return Values

S_OK

The storage object was successfully opened.

STG_E_FILENOTFOUND

The specified byte array does not exist.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

STG_E_SHAREVIOLATION

Access denied because another caller has the file open and locked.

STG_E_FILEALREADYEXISTS

The byte array exists but is not a storage object.

STG_E_TOOMANYOPENFILES

The storage object was not opened because there are too many open files.

STG_E_INSUFFICIENTMEMORY

The storage object was not opened due to a lack of memory.

STG_E_INVALIDNAME

Either pwcsName or snbExclude contains an invalid name.

STG_E_INVALIDPOINTER

Either snbExclude, pwcsName, pstgPriority, or ppStgOpen contains an invalid pointer.

STG_E_INVALIDFLAG

The grfMode parameter contains a bad flag combination.

STG_E_INVALIDFUNCTION

The access mode STGM_DELETEONRELEASE was specified in the grfMode parameter.

STG_E_OLDDLL

The DLL being used to open this storage object is a version prior to the one used to create it.

STG_E_OLDFORMAT

The storage object being opened was created by the Beta 1 storage provider. This format is no longer supported.

This function can also return any file system errors, or Win32 errors wrapped in an HRESULT, or ILockBytes() interface error return values.

See Also

StgOpenStorage(), StgCreateDocfileOnILockBytes()  

StgSetTimes()

NAME

StgSetTimes() - Sets the creation, access, and modification times of the indicated file, if supported by the underlying file system.

Synopsis

#include <objbase.h>

WINOLEAPI StgSetTimes((
        WCHAR const * lpszName,
        FILETIME const * pctime,
        FILETIME const * patime,
        FILETIME const * pmtime );

Description

The StgSetTimes() function sets the time values for the specified file. Each of the time value parameters can be NULL, indicating no modification should occur.

It is possible that one or more of these time values are not supported by the underlying file system. This function sets the times that can be set and ignores the rest.

Parameters

lpszName

[in] Points to the name of the file to be changed.

pctime

[in] Points to the new value for the creation time.

patime

[in] Points to the new value for the access time.

pmtime

[in] Points to the new value for the modification time.

Return Values

S_OK

Indicates time values successfully set.

STG_E_FILENOTFOUND

Indicates element does not exist.

STG_E_INVALIDNAME

Indicates bad name passed in the lpszName parameter, or a file system error.

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

This function can also return any file system errors or Win32 errors wrapped in an HRESULT.  

WriteClassStg()

NAME

WriteClassStg() - Stores the specified CLSID in a storage object.

Synopsis

#include <ole2.h>

WINOLEAPI WriteClassStg((
        IStorage * pStg,
        REFCLSID rclsid );

Description

The WriteClassStg() function writes a CLSID to the specified storage object so it can be read by the ReadClassStg() function. Container applications typically call this function before calling the IPersistStorage::Save() method.

Parameters

pStg

[in] IStorage() pointer to the storage object that gets a new CLSID.

rclsid

[in] Points to the CLSID to be stored with the object.

Return Values

S_OK

Indicates the CLSID was successfully written to the file.

STG_E_MEDIUMFULL

Indicates the CLSID could not be written due to lack of memory.

IStorage::SetClass() method error return values.

See Also

ReadClassStg()  

WriteClassStm()

NAME

WriteClassStm() - Stores the specified CLSID in the stream.

Synopsis

#include <ole2.h>

WINOLEAPI WriteClassStm((
        IStream * pStm,
        REFCLSID rclsid );

Description

The WriteClassStm() function writes a CLSID to the specified stream object so it can be read by the ReadClassStm() function. Most applications do not call WriteClassStm() directly. COM calls it before making a call to an object's IPersistStream::Save() method.

Parameters

pStm

[in] IStream() pointer to the stream into which the CLSID is to be written.

rclsid

[in] Specifies the CLSID to write to the stream.

Return Values

S_OK

Indicates the CLSID was successfully written.

STG_E_MEDIUMFULL

The CLSID could not be written because there is no space left on device.

IStorage::SetClass() method error return values.

See Also

ReadClassStm(), WriteClassStg(), ReadClassStg()  

WriteFmtUserTypeStg()

NAME

WriteFmtUserTypeStg() - Writes a clipboard format and user type to the storage object.

Synopsis

#include <ole2.h>

WINOLEAPI WriteFmtUserTypeStg((
        IStorage * pStg,
        CLIPFORMAT cf,
        LPWSTR * lpszUserType );

Description

The WriteFmtUserTypeStg() function must be called in an object's implementation of the IPersistStorage::Save() method. It must also be called by document-level objects that use structured storage for their persistent representation in their save sequence.

To read the information saved, applications call the ReadFmtUserTypeStg() function.

Parameters

pStg

[in] IStorage() pointer to the storage object where the information is to be written.

cf

[in] Specifies the clipboard format that describes the structure of the native area of the storage object. The format tag includes the policy for the names of streams and substorages within this storage object and the rules for interpreting data within those streams.

lpszUserType

[in] Points to the object's current user type. It cannot be NULL.

Return Values

S_OK

Indicates the information was written successfully.

STG_E_MEDIUMFULL

Indicates information could not be written due to lack of space on the storage medium.

IStream::Write() method error return values.

See Also

IPersistStorage::Save(), ReadFmtUserTypeStg()  

CreateILockBytesOnHGlobal()

NAME

CreateILockBytesOnHGlobal() - Creates a byte array object that allows you use global memory as the physical device underneath a compound file implementation. This object supports an OLE implementation of the ILockBytes() interface.

Synopsis

#include <ole2.h>

WINOLEAPI CreateILockBytesOnHGlobal((
        HGLOBAL hGlobal,
        BOOL fDeleteOnRelease,
        ILockBytes ** ppLkbyt );

Description

The CreateILockBytesOnHGlobal() function creates a byte array object based on global memory. This object supports an OLE implementation of the ILockBytes() interface, and is intended to be used as the basis for a compound file. You can then use the supplied ILockBytes() pointer in a call to the StgCreateDocfileOnILockBytes() function to build a compound file on top of this byte array object. The ILockBytes() instance calls the GlobalReAlloc function to grow the memory block as needed.

The current contents of the memory block are undisturbed by the creation of the new byte array object. After creating the ILockBytes() instance, you can use the StgOpenStorageOnILockBytes() function to reopen a previously existing storage object already contained in the memory block. You can also call GetHGlobalFromILockBytes() to get the global memory handle associated with the byte array object created by CreateILockBytesOnHGlobal().

If you free the hGlobal memory handle, the byte array object is no longer valid. You must call the ILockBytes::Release() method before freeing the memory handle.

The value of the hGlobal parameter can be changed by a subsequent call to the GlobalReAlloc function; thus, you cannot rely on this value after the byte array object is created.

Parameters

hGlobal

[in] Memory handle allocated by the GlobalAlloc function. The handle must be allocated as moveable and nondiscardable. If the handle is to be shared between processes, it must also be allocated as shared. New handles should be allocated with a size of zero. If hGlobal is NULL, CreateILockBytesOnHGlobal() internally allocates a new shared memory block of size zero.

fDeleteOnRelease

[in] IWhether the underlying handle for this byte array object should be automatically freed when the object is released.

ppLkbyt

[out] Address of ILockBytes* pointer variable that receives the interface pointer to the new byte array object.

Return Values

This function supports the standard return values E_INVALIDARG and E_OUTOFMEMORY, as well as the following:

S_OK

The byte array object was created successfully.

See Also

StgOpenStorageOnILockBytes(), GetHGlobalFromILockBytes(), ILockBytes()  

CreateStreamOnHGlobal()

NAME

CreateStreamOnHGlobal() - Creates a stream object stored in global memory.

Synopsis

#include <ole2.h>

WINOLEAPI CreateStreamOnHGlobal((
        HGLOBAL hGlobal,
        BOOL fDeleteOnRelease,
        LPSTREAM * ppstm );

Description

The CreateStreamOnHGlobal() function creates a stream object in memory that supports the COM implementation of the IStream() interface. The returned stream object supports both reading and writing, is not transacted, and does not support locking.

The initial contents of the stream are the current contents of the memory block provided in the hGlobal parameter. If the hGlobal paramter is NULL, this function internally allocates memory.

The current contents of the memory block are undisturbed by the creation of the new stream object. Thus, you can use this function to open an existing stream in memory.

The initial size of the stream is the size of the memory handle returned by the Win32 GlobalSize function. Because of rounding, this is not necessarily the same size that was originally allocated for the handle. If the logical size of the stream is important, you should follow the call to this function with a call to the IStream::SetSize() method.

After you have created the stream object with CreateStreamOnHGlobal(), you can call GetHGlobalFromStream() to get the global memory handle associated with the stream object.

Parameters

hGlobal

[in] Memory handle allocated by the GlobalAlloc function. The handle must be allocated as moveable and nondiscardable. If the handle is to be shared between processes, it must also be allocated as shared. New handles should be allocated with a size of zero. If hGlobal is NULL, the CreateStreamOnHGlobal() function internally allocates a new shared memory block of size zero.

fDeleteOnRelease

[in] Whether the underlying handle for this stream object should be automatically freed when the stream object is released.

ppstm

[out] Address of IStream* pointer variable that receives the interface pointer to the new stream object. Its value cannot be NULL.

Return Values

This function supports the standard return values E_INVALIDARG and E_OUTOFMEMORY, as well as the following:

S_OK

The stream object was created successfully.

See Also

CreateStreamOnHGlobal(), GetHGlobalFromStream, IStream::SetSize(),<

In the Win32 Programmer's Reference: > GlobalSize <in Win32 >  

GetClassFile()

NAME

GetClassFile() - Supplies the CLSID associated with the given filename.

Synopsis

#include <objbase.h>

WINOLEAPI GetClassFile((
        LPCWSTR szFileName,
        CLSID * pclsid );

Description

When given a filename, the GetClassFile() function finds the CLSID associated with that file. Examples of its use are in OleCreateFromFile, which is passed a file name and requires an associated CLSID, and in the COM implementation of IMoniker::BindToObject(), which, when a link to a file-based document is activated, calls GetClassFile() to locate the object application that can open the file.

GetClassFile() uses the following strategies to determine an appropriate CLSID:

  1. If the file contains a storage object, as determined by a call to the StgIsStorageFile() function, GetClassFile() returns the CLSID that was written with the IStorage::SetClass() method.

  2. If the file is not a storage object, the GetClassFile() function attempts to match various bits in the file against a pattern in the registry. A pattern in the registry can contain a series of entries of the form:

    regdb key = offset, cb, mask, value
    

    The value of the offset item is an offset from the beginning or end of the file and the cb item is a length in bytes. These two values represent a particular byte range in the file. (A negative value for the offset item is interpreted from the end of the file). The mask value is a bit mask that is used to perform a logical AND operation with the byte range specified by offset and cb. The result of the logical AND operation is compared with the value item. If the mask is omitted, it is assumed to be all ones.

    Each pattern in the registry is compared to the file in the order of the patterns in the database. The first pattern where each of the value items matches the result of the AND operation determines the CLSID of the file. For example, the pattern contained in the following entries of the registry requires that the first four bytes be AB CD 12 34 and the last four bytes be FE FE FE FE:

    HKEY_CLASSES_ROOT 
        FileType 
            {12345678-0000-0001-C000-000000000095} 
                0 = 0, 4, FFFFFFFF, ABCD1234 
                1 = -4, 4, , FEFEFEFE
    

    If a file contains such a pattern, the CLSID {12345678-0000-0001-C000-000000000095} will be associated with this file.

  3. If the above strategies fail, the GetClassFile() function searches for the File Extension key in the registry that corresponds to the .ext portion of the filename. If the database entry contains a valid CLSID, this function returns that CLSID.

  4. If all strategies fail, the function returns MK_E_INVALIDEXTENSION.

Parameters

szFileName

[in] Points to the filename for which you are requesting the associated CLSID.

pclsid

[out] Points to the location where the associated CLSID is written on return.

Return Values

S_OK

Indicates the CLSID was successfully supplied.

MK_E_CANTOPENFILE

Indicates unable to open the specified filename.

MK_E_INVALIDEXTENSION

Indicates the specified extension in the registry is invalid.

This function can also return any file system errors.

See Also

WriteClassStg()  

GetConvertStg()

NAME

GetConvertStg() - Returns the current value of the convert bit for the specified storage object.

Synopsis

#include <ole2.h>

WINOLEAPI GetConvertStg((
        IStorage * pStg );

Description

The GetConvertStg() function is called by object servers that support the conversion of an object from one format to another. The server must be able to read the storage object using the format of its previous CLSID and write the object using the format of its new CLSID to support the object's conversion. For example, a spreadsheet created by one application can be converted to the format used by a different application.

The convert bit is set by a call to the SetConvertStg() function. A container application can call this function on the request of an end user, or a setup program can call it when installing a new version of an application. An end user requests converting an object through the Convert To dialog box. When an object is converted, the new CLSID is permanently assigned to the object, so the object is subsequently associated with the new CLSID.

Then, when the object is activated, its server calls the GetConvertStg() function to retrieve the value of the convert bit from the storage object. If the bit is set, the object's CLSID has been changed, and the server must read the old format and write the new format for the storage object.

After retrieving the bit value, the object application should clear the convert bit by calling the SetConvertStg() function with its fConvert parameter set to FALSE.

Parameters

pStg

[in] IStorage() pointer to the storage object from which the convert bit is to be retrieved.

Return Values

S_OK

Indicates the convert bit is set to TRUE.

S_FALSE

Indicates the convert bit is cleared (FALSE).

STG_E_ACCESSDENIED

Access denied because the caller has insufficient permission, or another caller has the file open and locked.

STG_E_LOCKVIOLATION

Access denied because another caller has the file open and locked.

IStorage::OpenStream(), IStorage::OpenStorage(), and ISequentialStream::Read storage and stream access errors.

See Also

SetConvertStg()  

GetHGlobalFromILockBytes()

NAME

GetHGlobalFromILockBytes() - Retrieves a global memory handle to a byte array object created using the CreateILockBytesOnHGlobal() function.

Synopsis

#include <ole2.h>

WINOLEAPI GetHGlobalFromILockBytes((
        ILockBytes * pLkbyt,
        HGLOBAL * phglobal );

Description

After a call to CreateILockBytesOnHGlobal(), which creates a byte array object on global memory, GetHGlobalFromILockBytes() retrieves a pointer to the handle of the global memory underlying the byte array object. The handle this function returns might be different from the original handle due to intervening calls to the GlobalRealloc function.

The contents of the returned memory handle can be written to a clean disk file, and then opened as a storage object using the StgOpenStorage() function.

This function only works within the same process from which the byte array was created.

Parameters

pLkbyt

[in] Points to the ILockBytes() interface on the byte array object previously created by a call to the CreateILockBytesOnHGlobal() function.

phglobal

[out] Points to the current memory handle used by the specified byte array object.

Return Values

S_OK

Indicates the handle was returned successfully.

E_INVALIDARG

Indicates invalid value specified for the pLkbyt parameter. It can also indicate that the byte array object passed in is not one created by the CreateILockBytesOnHGlobal() function.

See Also

StgOpenStorage(), CreateILockBytesOnHGlobal()  

GetHGlobalFromStream()

NAME

GetHGlobalFromStream() - Retrieves the global memory handle to a stream that was created through a call to the CreateStreamOnHGlobal() function.

Synopsis

#include <ole2.h>

WINOLEAPI GetHGlobalFromStream((
        IStream * pstm,
        HGLOBAL * phglobal );

Description

The handle this function returns may be different from the original handle due to intervening GlobalRealloc calls.

This function can be called only from within the same process from which the byte array was created.

Parameters

pstm

[in] IStream() pointer to the stream object previously created by a call to the CreateStreamOnHGlobal() function.

phglobal

[out] Points to the current memory handle used by the specified stream object.

Return Values

S_OK

Indicates the handle was successfully returned.

E_INVALIDARG

Indicates invalid value specified for the pstm parameter. It can also indicate that the stream object passed in is not one created by a call to the CreateStreamOnHGlobal() function.

15.8    Persistent Storage Structure Descriptions

15.8.1    FILETIME

The FILETIME data structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601. It is the means by which Win32 determines the date and time. FILETIME is used by the CoDosDateTimeToFileTime(), CoFileTimeToDosDateTime(), and CoFileTimeNow() functions. It is defined as follows:

typedef struct STRUCT tagFILETIME 
{
    DWORD  dwLowDateTime;
    DWORD  dwHighDateTime;
} FILETIME;

Members

dwLowDateTime

The low 32 bits of the Win32 date/time value.

dwHighDateTime

The upper 32 bits of the Win32 date/time value.

Description

The FILETIME data structure is used in the time conversion functions between DOS and Win32.

See Also

CoDosDateTimeToFileTime(), CoFileTimeNow(), CoFileTimeToDosDateTime()

15.8.2    RemSNB

The RemSNB structure is used for marshaling the SNB data type.

Defined in the IStorage() interface (storag.idl).

typedef struct tagRemSNB { 
    unsigned                long     ulCntStr; 
    unsigned                long     ulCntChar; 
    [size_is(ulCntChar)]    wchar_t  rgString[]; 
} RemSNB; 
typedef [transmit_as(RemSNB)] wchar_t  **SNB;

Members

ulCntStr

Number of strings in the rgString buffer.

ulCntChar

Size in bytes of the rgString buffer.

rgString

Pointer to an array of bytes containing the

<[REVIEW: NULL separated?]>

stream name strings from the SNB.

See Also

IStorage()

15.8.3    STATPROPSETSTG

Contains information about a property set. To get this information, call IPropertyStorage::Stat(), which fills in a buffer containing the information describing the current property set. To enumerate the STATPROPSETSTG structures for the property sets in the current property set storage, call IPropertySetStorage::Enum() to get a pointer to an enumerator. You can then call the enumeration methods of the IEnumSTATPROPSETSTG() interface on the enumerator. The structure is defined as follows:

typedef struct tagSTATPROPSETSTG {
    FMTID       fmtid; 
    CLSID       clsid;
    DWORD       grfFlags;
    FILETIME    mtime;
    FILETIME    ctime;
    FILETIME    atime;
    } STATPROPSETSTG

Members

fmtid

Format identifier of the current property set.

clsid

The CLSID associated with this property set.

grfFlags

Flag values of the property set, as specified in IPropertySetStorage::Create().

mtime

Time in Universal Coordinated Time (UTC) that the property set was last modified.

ctime

Time in UTC at which this property set was created.

atime

Time in UCT at which this property set was last accessed.

See Also

IPropertySetStorage::Create(), IEnumSTATPROPSETSTG(), IPropertyStorage::Stat(), FILETIME structure

15.8.4    STATPROPSTG

Each STATPROPSTG structure contains information about a single property in a property set. This information is the property identifier and type tag, and the optional string name that may be associated with the property.

IPropertyStorage::Enum() supplies a pointer to the IEnumSTATPROPSTG() interface on an enumerator object that can be used to enumerate through the STATPROPSTG structures for the properties in the current property set. STATPROPSTG is defined as follows:

typedef struct    tagSTATPROPSTG {
    LPWSTR        lpwstrName;
    PROPID        propid;
    VARTYPE       vt;
} STATPROPSTG

Members

lpwstrName

Wide-character string containing the optional string name that can be associated with the property. May be NULL. This member must be freed using CoTaskMemFree().

propid

A 32-bit identifier that uniquely identifies the property within the property set. All properties within property sets must have unique property identifiers.

vt

Type of the property.

See Also

IPropertyStorage::Enum(), IEnumSTATPROPSTG()

15.8.5    STATSTG

The STATSTG structure contains statistical information about an open storage, stream, or byte array object. This structure is used in the IEnumSTATSTG(), ILockBytes(), IStorage(), and IStream() interfaces.

<Defined in the IStream() interface (stream.idl).>

typedef struct tagSTATSTG 
{ 
    LPWSTR          pwcsName; 
    DWORD           type; 
    ULARGE_INTEGER  cbSize; 
    FILETIME        mtime; 
    FILETIME        ctime; 
    FILETIME        atime; 
    DWORD           grfMode; 
    DWORD           grfLocksSupported; 
    CLSID           clsid; 
    DWORD           grfStateBits; 
    DWORD           reserved; 
} STATSTG;

Members

pwcsName

Points to a NULL-terminated string containing the name. Space for this string is allocated by the method called and freed by the caller (refer to CoTaskMemFree()). You can specify not to return this member by specifying the STATFLAG_NONAME value when you call a method that returns a STATSTG structure, except for calls to IEnumSTATSTG::Next, which provides no way to specify this value.

type

Indicates the type of storage object. This is one of the values from the STGTY enumeration.

cbSize

Specifies the size in bytes of the stream or byte array.

mtime

Indicates the last modification time for this storage, stream, or byte array.

ctime

Indicates the creation time for this storage, stream, or byte array.

atime

Indicates the last access time for this storage, stream or byte array.

grfMode

Indicates the access mode specified when the object was opened. This member is only valid in calls to Stat methods.

grfLocksSupported

Indicates the types of region locking supported by the stream or byte array. See the LOCKTYPES enumeration for the values available. This member is not used for storage objects.

clsid

Indicates the class identifier for the storage object; set to CLSID_NULL for new storage objects. This member is not used for streams or byte arrays.

grfStateBits

Indicates the current state bits of the storage object, that is, the value most recently set by the IStorage::SetStateBits() method. This member is not valid for streams or byte arrays.

dwStgFmt

Indicates the format of the storage object. This is one of the values from the STGFMT enumeration.

See Also

IStorage::SetElementTimes()

15.9    Persistent Storage Enumeration Descriptions

15.9.1    LOCKTYPE

The LOCKTYPE enumeration values indicate the type of locking requested for the specified range of bytes. The values are used in the ILockBytes::LockRegion() and IStream::LockRegion() methods.

<Defined in the IStream() interface (stream.idl).>

typedef enum tagLOCKTYPE 
{ 
    LOCK_WRITE        = 1, 
    LOCK_EXCLUSIVE    = 2, 
    LOCK_ONLYONCE     = 4 
} LOCKTYPE;

Elements

LOCK_WRITE

If this lock is granted, the specified range of bytes can be opened and read any number of times, but writing to the locked range is prohibited except for the owner that was granted this lock.

LOCK_EXCLUSIVE

If this lock is granted, writing to the specified range of bytes is prohibited except for the owner that was granted this lock.

LOCK_ONLYONCE

If this lock is granted, no other LOCK_ONLYONCE lock can be obtained on the range. Usually this lock type is an alias for some other lock type. Thus, specific implementations can have additional behavior associated with this lock type.

15.9.2    PROPSETFLAG

The PROPSETFLAG enumeration values define characteristics of a property set. The values are used in the grfFlags parameter of IPropertySetStorage() methods, the StgCreatePropStg() function, and the StgOpenPropStg() function.

typedef enum PROPSETFLAG {
    PROPSETFLAG_DEFAULT      = 0,
    PROPSETFLAG_NONSIMPLE    = 1,
    PROPSETFLAG_ANSI         = 2,
    PROPSETFLAG_UNBUFFERED   = 4
    } PROPSETFLAG

Elements

PROPSETFLAG_NONSIMPLE

If specified, storage-valued and stream-valued properties are permitted in the newly created set. Otherwise, they are not permitted. In the compound file and standalone implementations, property sets may be transacted only if PROPSETFLAG_NONSIMPLE is specified.

PROPSETFLAG_ANSI

If specified, all string values in the property set that are not explicitly Unicode (those other than VT_LPWSTR) are stored with the current system ANSI code page (see the Win32 function GetACP). Use of this value is not recommended, as described in the following Remarks section.

If this value is absent, string values in the new property set are stored in Unicode. The degree of control afforded by this value is necessary so clients using the property-related interfaces can interoperate well with standard property sets such as the COM summary information, which may exist in the ANSI code page.

PROPSETFLAG_UNBUFFERED

Used only with the StgCreatePropStg() and StgOpenPropStg() functions, that is, in the standalone implementations of property set interfaces. If specified in these functions, changes to the property set are not buffered. Instead, changes are always written directly to the property set. A property set is changed by calls to its IPropertyStorage() methods. However, by default, changes are buffered in an internal property set cache and are subsequently written to the property set when the IPropertyStorage::Commit() method is called.

Setting PROPSETFLAG_UNBUFFERED reduces performance since the property set's internal buffer is automatically flushed after every change to the property set. However, writing changes directly prevents coordination problems. For example, suppose the storage object is opened in transacted mode, and the property set is buffered. Then, if you call the IStorage::Commit() method on the storage object, the property set changes will not be picked up as part of the transaction, since they are in a buffer that has not been flushed yet. You must call IPropertyStorage::Commit() prior to calling IStorage::Commit() to flush the property set buffer before committing changes to the storage. As an alternative to making two calls, you can set PROPSETFLAG_UNBUFFERED so that changes are always written directly to the property set and are never buffered in the property set's internal cache. Then, the changes will be picked up when the transacted storage is committed.

Description

These values can be set and checked using bitwise operations that determine how property sets are created and opened. Property sets are created using the IPropertySetStorage::Create() method or the StgCreatePropStg() function. They are opened using the IPropertySetStorage::Open() method or the StgOpenPropStg() function.

It is recommended that property sets be created as Unicode, by not setting the PROPSETFLAG_ANSI flag in the grfFlags parameter. 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 converted 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.

Table 15-40:  PROPSETFLAG Programming Information

Unicode Yes
Import Library IPROP.DLL
Header File IPROPIDL.H

See Also

IPropertySetStorage::Create(), IPropertySetStorage::Open(), PropStgNameToFmtId(), StgCreatePropSetStg(), StgCreatePropStg(), StgOpenPropStg()

15.9.3    STGC

The STGC enumeration constants specify the conditions for performing the commit operation in the IStorage::Commit() and IStream::Commit() methods.

Defined in the IOLETypes pseudo-interface (oletyp.idl).

typedef enum tagSTGC 
{ 
    STGC_DEFAULT                               = 0, 
    STGC_OVERWRITE                             = 1, 
    STGC_ONLYIFCURRENT                         = 2, 
    STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE    = 4 
} STGC;

Elements

STGC_DEFAULT

None of the other values apply. You can specify this condition or some combination of the other three. You would use this value mainly to make your code more readable.

STGC_OVERWRITE

The commit operation can overwrite existing data to reduce overall space requirements. This value is not recommended for typical usage because it is not as robust as the default case. In this case, it is possible for the commit to fail after the old data is overwritten but before the new data is completely committed. Then, neither the old version nor the new version of the storage object will be intact.

You can use this value in cases where:

Note that the commit operation checks for adequate space before any overwriting occurs. Thus, even with this value specified, if the commit operation fails due to space requirements, the old data will remain safe. The case where data loss can occur is when the commit operation fails due to some reason other than lack of space and the STGC_OVERWRITE value was specified.

STGC_ONLYIFCURRENT

Prevents multiple users of a storage object from overwriting one another's changes. The commit operation occurs only if there have been no changes to the saved storage object since the user most recently opened the storage object. Thus, the saved version of the storage object is the same version that the user has been editing. If other users have changed the storage object, the commit operation fails and returns the STG_E_NOTCURRENT value. You can override this behavior by calling the Commit method again using the STGC_DEFAULT value.

STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE

Commits the changes to a write-behind disk cache, but does not save the cache to the disk. In a write-behind disk cache, the operation that writes to disk actually writes to a disk cache, thus increasing performance. The cache is eventually written to the disk, but usually not until after the write operation has already returned. The performance increase comes at the expense of an increased risk of losing data if a problem occurs before the cache is saved and the data in the cache is lost.

If you do not specify this value, then committing changes to root-level storage objects is robust even if a disk cache is used. The two-phase commit process ensures that data is stored on the disk and not just to the disk cache.

Description

You can specify STGC_DEFAULT or some combination of the other three values. Typically, you would use STGC_ONLYIFCURRENT to protect the storage object in cases where more than one user can edit the object simultaneously.

See Also

IPropertyStorage(), IStorage(), IStream()

15.9.4    STGFMT

This enumeration is defined but not used.

The STGFMT enumeration values indicate the format of a storage object and are used in the STATSTG structure and in the StgCreateDocFile and StgIsStorageFile() functions.

<Defined in the IOLETypes pseudo-interface (oletyp.idl).>

typedef enum tagSTGFMT 
{ 
    STGFMT_DOCUMENT     = 0, 
    STGFMT_DIRECTORY    = 1, 
    STGFMT_CATALOG      = 2, 
    STGFMT_FILE         = 3 
} STGFMT;

Elements

STGFMT_DOCUMENT

Indicates a document format.

STGFMT_DIRECTORY

Indicates a directory format.

STGFMT_CATALOG

Indicates a catalog format.

STGFMT_FILE

Indicates a file format.

See Also

STATSTG, StgCreateDocfile(), StgIsStorageFile()

15.9.5    STGM

The STGM enumeration values are used in the storage and stream interfaces to indicate the conditions for creating and deleting the object and access modes for the object.

The STGM values are used in the IStorage() and IStream() interfaces, and in the StgCreateDocfile() and StgCreateDocfileOnILockBytes() functions to indicate the conditions for creating and deleting the object and access modes for the object.

STGM values are as follows:

Table 15-41:  STGM Values

STGM_DIRECT 0x00000000L
STGM_TRANSACTED 0x00010000L
STGM_SIMPLE 0x08000000L
STGM_READ 0x00000000L
STGM_WRITE 0x00000001L
STGM_READWRITE 0x00000002L
STGM_SHARE_DENY_NONE 0x00000040L
STGM_SHARE_DENY_READ 0x00000030L
STGM_SHARE_DENY_WRITE 0x00000020L
STGM_SHARE_EXCLUSIVE 0x00000010L
STGM_PRIORITY 0x00040000L
STGM_DELETEONRELEASE 0x04000000L
STGM_CREATE 0x00001000L
STGM_CONVERT 0x00020000L
STGM_FAILIFTHERE 0x00000000L
STGM_NOSCRATCH 0x00100000L

Elements

STGM_DIRECT, STGM_TRANSACTED, STGM_SIMPLE Group

STGM_DIRECT

In direct mode, each change to a storage element is written as it occurs. This is the default.

STGM_TRANSACTED

In transacted mode, changes are buffered and are written only if an explicit commit operation is called. The changes can be ignored by calling the Revert method in the IStream() or IStorage() interfaces. The COM compound file implementation does not support transacted streams, which means that streams can be opened only in direct mode, and you cannot revert changes to them. Transacted storages are, however, supported.

STGM_SIMPLE

STGM_SIMPLE is a mode that provides a much faster implementation of a compound file in a limited, but frequently used case. It is described in detail in the following Remarks section.

STGM_READ, STGM_WRITE, STGM_READWRITE Group

STGM_READ

For stream objects, STGM_READ allows you to call the IStream::Read() method. For storage objects, you can enumerate the storage elements and open them for reading.

STGM_WRITE

STGM_WRITE lets you save changes to the object.

STGM_READWRITE

STGM_READWRITE is the combination of STGM_READ and STGM_WRITE.

STGM_SHARE_* Group

STGM_SHARE_DENY_NONE

Specifies that subsequent openings of the object are not denied read or write access.

STGM_SHARE_DENY_READ

Prevents others from subsequently opening the object in STGM_READ mode. It is typically used on a root storage object.

STGM_SHARE_DENY_WRITE

Prevents others from subsequently opening the object in STGM_WRITE mode. This value is typically used to prevent unnecessary copies made of an object opened by multiple users. If this value is not specified, a snapshot is made, independent of whether there are subsequent opens or not. Thus, you can improve performance by specifying this value.

STGM_SHARE_EXCLUSIVE

The combination of STGM_SHARE_DENY_READ and STGM_SHARE_DENY_WRITE.

STGM_PRIORITY

STGM_PRIORITY

Opens the storage object with exclusive access to the most recently committed version. Thus, other users cannot commit changes to the object while you have it open in priority mode. You gain performance benefits for copy operations, but you prevent others from committing changes. So, you should limit the time you keep objects open in priority mode. You must specify STGM_DIRECT and STGM_READ with priority mode.

STGM_DELETEONRELEASE

STGM_DELETEONRELEASE

Indicates that the underlying file is to be automatically destroyed when the root storage object is released. This capability is most useful for creating temporary files.

STGM_CREATE, STGM_CONVERT, STGM_FAILIFTHERE Group

STGM_CREATE

Indicates that an existing storage object or stream should be removed before the new one replaces it. A new object is created when this flag is specified, only if the existing object has been successfully removed.

This flag is used in three situations:

STGM_CONVERT

Creates the new object while preserving existing data in a stream named CONTENTS. In the case of a storage object or a byte array, the old data is flattened to a stream regardless of whether the existing file or byte array currently contains a layered storage object.

STGM_FAILIFTHERE

Causes the create operation to fail if an existing object with the specified name exists. In this case, STG_E_FILEALREADYEXISTS is returned. STGM_FAILIFTHERE applies to both storage objects and streams.

STGM_NOSCRATCH

Not used.

Description

You can combine these flags but you can only choose one flag from each group of related flags. Groups are indicated under the headings in the previous section.

The STGM_SIMPLE flag is applicable only when combined with:

STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE

Note that direct mode is implied by the absence of STGM_TRANSACTED.

This mode is useful for applications that perform complete save operations. It has the following constraints:

  1. There is no support for substorages.

  2. Access to streams follows a linear pattern. Once a stream is released, that stream cannot be opened for read/write operations again. The IStorage::OpenStream() method is not supported in this implementation.

  3. The storage and stream objects cannot be marshaled.

  4. Each stream is at least 4096 bytes in length. If fewer than 4096 bytes are written into a stream by the time the stream is released, the stream will be extended to contain 4096 bytes.

  5. In this compound file implementation, only a subset of the methods of IStorage() and IStream() are available.

Specifically, in simple mode, supported IStorage() methods are QueryInterface(), AddRef(), Release(), CreateStream, Commit, and SetClass. In addition, SetElementTimes is supported with a NULL name, allowing applications to set times on a root storage in simple mode.

Supported IStream() methods are QueryInterface(), AddRef(), Release(), Write, Seek, SetSize, and Read.

All the other methods of IStorage() and IStream() return STG_E_INVALIDFUNCTION.

See Also

StgCreateDocfile(), IStream::Read(), IStorage(), StgCreateDocfileOnILockBytes(), StgOpenStorage(), StgOpenStorageOnILockBytes()

15.9.6    STGMOVE

The STGMOVE enumeration values indicate whether a storage element is to be moved or copied. They are used in the IStorage::MoveElementTo() method.

<Defined in the IOLETypes pseudo-interface (oletyp.idl).>

typedef enum tagSTGMOVE 
{ 
    STGMOVE_MOVE    = 0, 
    STGMOVE_COPY    = 1 
} STGMOVE;

Elements

STGMOVE_MOVE

Indicates the method should move the data from the source to the destination.

STGMOVE_COPY

Indicates the method should copy the data from the source to the destination. A copy is the same as a move except the source element is not removed after copying the element to the destination. Copying an element on top of itself is undefined.

See Also

IStorage::MoveElementTo()

15.9.7    STGTY

The STGTY enumeration values are used in the type member of the STATSTG structure to indicate the type of the storage element. A storage element is a storage object, a stream object, or a byte array object (LOCKBYTES).

<Defined in the IStream() interface (stream.idl).>

typedef enum tagSTGTY 
{ 
    STGTY_STORAGE      = 1, 
    STGTY_STREAM       = 2, 
    STGTY_LOCKBYTES    = 3, 
    STGTY_PROPERTY     = 4 
} STGTY;

Elements

STGTY_STORAGE

Indicates that the storage element is a storage object.

STGTY_STREAM

Indicates that the storage element is a stream object.

STGTY_LOCKBYTES

Indicates that the storage element is a byte array object.

STGTY_PROPERTY

Indicates that the storage element is a property storage object.

See Also

IStream(), STATSTG

15.9.8    STREAM_SEEK

The STREAM_SEEK enumeration values specify the origin from which to calculate the new seek pointer location. They are used for the dworigin parameter in the IStream::Seek() method. The new seek position is calculated using this value and the dlibMove parameter.

<Defined in the IStream() interface (stream.idl).>

typedef enum tagSTREAM_SEEK 
{ 
    STREAM_SEEK_SET    = 0, 
    STREAM_SEEK_CUR    = 1, 
    STREAM_SEEK_END    = 2 
} STREAM_SEEK;

Elements

STREAM_SEEK_SET

The new seek pointer is an offset relative to the beginning of the stream. In this case, the dlibMove parameter is the new seek position relative to the beginning of the stream.

STREAM_SEEK_CUR

The new seek pointer is an offset relative to the current seek pointer location. In this case, the dlibMove parameter is the signed displacement from the current seek position.

STREAM_SEEK_END

The new seek pointer is an offset relative to the end of the stream. In this case, the dlibMove parameter is the new seek position relative to the end of the stream.

See Also

IStream::Seek()