Structured storage provides the equivalent of a complete file system for storing objects through the following elements:
The
IStorage()
,
IStream()
,
ILockBytes()
, and
IRootStorage()
interfaces, along
with a set of related interfaces --
IPersistStorage()
,
IPersist()
,
IPersistFile()
, and
IPersistStream()
.
Helper APIs that facilitate your implementation of structured storage, as well as a second set of APIs for compound files, COM's implementation of the structured storage interfaces. COM also provides a set of supporting structures and enumeration values used to organize parameters for interface methods and APIs.
A set of access modes for regulating access to compound files.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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:
IPropertyStorage()
IPropertySetStorage()
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.
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.
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
PROPVARIANT
s is, however,
not completely equivalent with the set of
VARIANT
s 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
VARIANT
s and
PROPVARIANT
s
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.
While the potential for uses of persistent property sets is not fully tapped, there are currently two primary uses:
Storing summary information with an object such as a document
Transferring property data between objects
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.
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.
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.
The following guidelines pertain to implementing the Summary Information property set described in the preceding section:
PID_TEMPLATE
refers to an external document
containing formatting and styling information.
The means by which the template
is located is implementation-defined.
PID_LASTAUTHOR
is the name stored in User
Information by the application.
For example, suppose Mary creates a document
on her machine and gives it to John, who then modifies and saves it.
Mary
is the author, John is the last saved by value.
PID_REVNUMBER
is the number of times the
File/Save command has been called on this document.
Each of the date/time values must be stored in Universal Coordinated Time (UTC).
PID_CREATE_DTM
is a read-only property;
this property should be set when a document is created, but should not be
subsequently changed.
For
PID_THUMBNAIL
, applications should
store data in
CF_DIB
or
CF_METAFILEPICT
format.
CF_METAFILEPICT is recommended.
PID_SECURITY
is the suggested security
level for the document.
By noting the security level on the document, an application
other than the originator of the document can adjust its user interface to
the properties appropriately.
An application should not display any information
about a password-protected document or allow modifications to enforced read-only
or locked-for-annotations documents.
Applications should warn the user about
read-only recommended if the user attempts to modify properties:
Security Level
|
Value
|
None | 0 |
Password protected | 1 |
Read-only recommended | 2 |
Read-only enforced | 4 |
Locked for annotations | 8 |
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:
Section Section 15.6.18
Section Section 15.6.21
Section Section 15.6.4
Section Section 15.6.1
In addition, there are three helper functions, designed to aid in dealing with propvariants:
PropVariantClear()
FreePropVariantArray()
PropVariantCopy()
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.
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.
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.
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:
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.
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()
.
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.
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.
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
.
IPropertyStorage::WritePropertyNames()
is implemented
using the property ID 0 dictionary as described above.
Property ID 0 is
not
accessible through
IPropertyStorage::ReadMultiple()
or
::WriteMultiple
.
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.
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.
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.
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:
HRESULT Next(
#include <objidl.h>
ULONG celt,
STATPROPSETSTG * rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumSTATPROPSETSTG ** ppenum
);
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.
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.
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:
If
IEnumSTATPROPSETSTG::Next()
cannot provide
STATPROPSETSTG.
fmtid,
zeros are written to that member.
This occurs when the property set does not
have a predefined name (such as \005SummaryInformation
)
and is not a legal
value.
The
DocumentSummaryInformation
property
set is special, in that
it may have two property set sections.
This property set is described in the
section titled The
DocumentSummaryInformation
Property
Set.
The second
section is referred to as the User-Defined Properties.
Each section is
identified with a unique Format ID.
When
IPropertySetStorage::Enum()
is
used to enumerate property sets, the User-Defined Property Set will not be
enumerated.
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].
The
STATPROPSETSTG
.grfFlags
member does not necessarily reflect whether
the property set is ANSI or not.
If PROPSETFLAG_ANSI is set, the property
set
is definitely ANSI.
If PROPSETFLAG_ANSI is clear, the property set could be
either Unicode or non-Unicode, because it is not possible to tell whether
it is
ANSI without opening it.
The
STATPROPSETSTG
.grfFlags
member does reflect whether the property set
is simple or not, so the setting of the
PROPSETFLAG_NONSIMPLE
flag is always
valid.
If
IEnumSTATPROPSETSTG::Next()
cannot provide
STATPROPSETSTG.
clsid,
it is set to all zeroes (CLSID_NULL
).
In the COM compound
file implementation,
this occurs when the property set is simple (the
PROPSETFLAG_NONSIMPLE
flag is
not set), or is non-simple but the CLSID was not explicitly set.
For non-simple
property sets, the CLSID that is received is the one that is maintained by
the
underlying
IStorage()
.
If
IEnumSTATPROPSETSTG::Next()
cannot provide
the time fields
[ctime,
mtime,
atime],
each non-supported time will be set
to zeroes.
In the COM compound file implementation, getting these values
depends on retrieving them from the underlying
IStorage()
implementation.
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.
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.
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.
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:
HRESULT Next(
#include <objidl.h>
ULONG celt,
STATPROPSTG * rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumSTATPROPSTG ** ppenum
);
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.
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.
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.
STATPROPSTG
,
IPropertyStorage::Enum()
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()
.
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.
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:
HRESULT Next(
#include <objidl.h>
ULONG celt,
STATSTG * rgelt,
ULONG * pceltFetched
);
HRESULT Skip(
#include <objidl.h>
ULONG celt
);
HRESULT Reset(
#include <objidl.h>
void
);
HRESULT Clone(
#include <objidl.h>
IEnumSTATSTG ** ppenum
);
CoGetMalloc()
,
IEnum
XXXX,
IStorage::EnumElements()
,
STATSTG
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.
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.
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()
.
IUnknown()
Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
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.
|
- Ensures that any internal buffers maintained by the
ILockBytes::Flush()
ILockBytes()
implementation are written out to the underlying physical storage.
HRESULT Flush(
#include <objidl.h>
void
);
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.
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.
IStorage::Commit()
,
ILockBytes--File-Based
Implementation
, ILockBytes--Global Memory
Implementation
- Restricts access to a specified range of bytes in the byte array.
ILockBytes::LockRegion()
HRESULT LockRegion(
#include <objidl.h>
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
);
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.
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.
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
.
[in] Specifies the byte offset for the beginning of the range.
[in] Specifies, in bytes, the length of the range to be restricted.
[in] Specifies the type of restrictions being requested on accessing
the range.
This parameter uses one of the values from the
LOCKTYPE
enumeration.
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.
ILockBytes::Stat()
,
ILockBytes::UnlockRegion()
,
IStream::LockRegion()
,
LOCKTYPE
,
ILockBytes--File-Based Implementation
,
ILockBytes--Global Memory Implementation
- Reads a specified number of bytes starting at a specified offset from the
beginning of the byte array object.
ILockBytes::ReadAt()
HRESULT ReadAt(
#include <objidl.h>
ULARGE_INTEGER ulOffset,
void * pv,
ULONG cb,
ULONG * pcbRead
);
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.
[in] Specifies the starting point from the beginning of the byte array for reading data.
[in] Points to the buffer into which the byte array is read.
[in] Specifies the number of bytes of data to attempt to read from the byte array.
[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.
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.
ILockBytes::WriteAt()
,
ILockBytes--File-Based
Implementation
,
ILockBytes--Global Memory
Implementation
- Changes the size of the byte array.
ILockBytes::SetSize()
HRESULT SetSize(
#include <objidl.h>
ULARGE_INTEGER cb
);
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.
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.
[in] Specifies the new size of the byte array as a number of bytes.
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.
ILockBytes::ReadAt()
,
ILockBytes::WriteAt()
,
ILockBytes--File-Based Implementation
,
ILockBytes--Global Memory Implementation
- Retrieves a STATSTG structure containing information for this byte array object.
ILockBytes::Stat()
HRESULT Stat(
#include <objidl.h>
STATSTG * pstatstg,
DWORD grfStatFlag
);
ILockBytes::Stat()
should supply information about
the byte array object
in a
STATSTG
structure.
[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.
[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.
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.
STATFLAG
,
STATSTG
,
ILockBytes--File-Based Implementation
,
ILockBytes--Global Memory Implementation
- Removes the access restriction on a previously locked range of
bytes.
ILockBytes::UnlockRegion()
HRESULT UnlockRegion(
#include <objidl.h>
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
);
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
[in] Specifies the byte offset for the beginning of the range.
[in] Specifies, in bytes, the length of the range that is restricted.
[in] Specifies the type of access restrictions previously placed on
the range.
This parameter uses a value from the
LOCKTYPE
enumeration.
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.
- Writes the specified number of bytes starting at a specified offset from the
beginning of the byte array.
ILockBytes::WriteAt()
HRESULT WriteAt(
#include <objidl.h>
ULARGE_INTEGER ulOffset,
void const * pv,
ULONG cb,
ULONG * pcbWritten
);
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.
[in] Specifies the starting point from the beginning of the byte array for the data to be written.
[in] Points to the buffer containing the data to be written.
[in] Specifies the number of bytes of data to attempt to write into the byte array.
[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.
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.
ILockBytes::ReadAt()
,
ILockBytes::SetSize()
,
ILockBytes--File-Based Implementation
,
ILockBytes--Global Memory 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.
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.
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.
ILockBytes()
,
IStorage()
,
IStream()
Implemented on a byte array object underlying an COM compound file storage object, and designed to read and write directly to global memory.
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()
.
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.
ILockBytes()
,
IStorage()
,
IStream()
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
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.
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the component object. |
- Retrieves the class identifier (CLSID) of an object.
The CLSID is a unique
value that identifies the code that can manipulate the persistent data.
IPersist::GetClassID()
HRESULT GetClassID((
#include <objidl.h>
CLSID * pClassID
);
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.
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.
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
).
IPersistStorage()
,
IPersistStream()
,
IPersistFile()
,
ReadClassStg()
[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.
S_OK
The CLSID was successfully retrieved.
E_FAIL
The CLSID could not be retrieved.
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()
.
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:
Any object that supports links to its files or to pseudo-objects within its files
A container application that supports links to objects within its compound file
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()
.
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the component object. |
|
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. |
- 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.
IPersistFile::GetCurFile()
HRESULT GetCurFile(
#include <objidl.h>
LPOLESTR * ppszFileName
);
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
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.
[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
.
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.
IPersistFile::Load()
,
IPersistFile::Save()
,
IPersistFile::SaveCompleted()
- Checks an object for changes since it was last saved to its current
file.
IPersistFile::IsDirty()
HRESULT IsDirty(
#include <objidl.h>
void
);
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.
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.
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.
S_OK
The object has changed since it was last saved.
S_FALSE
The object has not changed since the last save.
IAdviseSink::OnDataChange()
,
IDataObject::DAdvise()
,
IPersistStorage::IsDirty()
- Opens the specified file and initializes an object from the file contents.
IPersistFile::Load()
HRESULT Load(
#include <objidl.h>
LPCOLESTR pszFileName,
DWORD dwMode
);
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.
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.
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()
).
[in] Points to a zero-terminated string containing the absolute path of the file to open.
[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.
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.IRunningObjectTable::Register()
,
StgOpenStorage()
- Saves a copy of the object into the specified file.
IPersistFile::Save()
HRESULT Save(
#include <objidl.h>
LPCOLESTR pszFileName,
BOOL fRemember
);
This method can be called to save an object to the specified file in one of three ways:
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.
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.
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.
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.
[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.
[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.
S_OK
The object was successfully saved.
E_FAIL
The file was not saved.
IPersistFile::Save()
STG_E_
* errors.IPersistFile::GetCurFile()
,
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::SaveCompleted()
IPersistFile::Save()
call.
HRESULT SaveCompleted(
#include <objidl.h>
LPCOLESTR pszFileName
);
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.
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.
[in] Points to the absolute path of the file where the object was previously saved.
S_OK
Returned in all cases.
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.
An object implements this interface to save itself in memory.
A container calls the methods of this interface to instruct an object to save and load itself in memory.
IUnknown
Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
IPersist Method
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the component object. |
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. |
- Returns the size in bytes of the memory block needed to save the
object.
IPersistMemory::GetSizeMax()
HRESULT GetSizeMax(
#include <ocidl.h>
ULARGE_INTEGER * pcbSize
);
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.
The
GetSizeMax
implementation must return a conservative
estimate of the
necessary size because the
IPersistMemory::Save()
method
uses a fixed size
memory block.
[out] Pointer to a 64-bit unsigned integer value indicating the size in bytes of the memory needed to save this object.
S_OK
The size was successfully returned.
- Initializes the object to a default state.
This method is called
instead of
IPersistMemory::InitNew()
IPersistMemory::Load()
.
HRESULT InitNew((
#include <ocidl.h>
void
);
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.
If the object has already been initialized with
Load
,
then this method
must return
E_UNEXPECTED
.
- Checks the object for changes since it was last saved.
IPersistMemory::IsDirty()
HRESULT IsDirty(
#include <ocidl.h>
void
);
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.
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.
S_OK
The object has changed since it was last saved.
S_FALSE
The object has not changed since the last save.
- 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).
IPersistMemory::Load()
HRESULT Load(
#include <ocidl.h>
void * pvMem,
ULONG cbSize
);
Any object that implements
IPersistMemory()
has some
information to
load persistently, therefore
E_NOTIMPL
is not a valid return
code.
[in] Pointer to the address in memory from which the object can read up to cbSize bytes of its data.
[in] The amount of memory available at pvMem from which the object can read its data.
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
.
- 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.
IPersistMemory::Save()
HRESULT Save(
#include <ocidl.h>
void * pvMem,
BOOL fClearDirty,
ULONG cbSize
);
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()
.
[in] Pointer to the memory in which the object should save up to cbSize bytes of its data.
[in] A flag indicating whether the object should clear its dirty state
on return from
Save
or leave that state as-is.
[in] The amount of memory available at pvMem to which the object can write its data.
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
.
IPersistMemory::InitNew()
,
IPersistMemory::Load()
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.
An object implements this interface to enable saving its properties persistently.
A container calls the methods on this interface to instruct an object to load and save its properties to the supplied property bag.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
IPersist Method
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the component object. |
|
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. |
- Called by the container when the control is initialized to initialize
the property bag.
IPersistPropertyBag::InitNew()
HRESULT InitNew((
#include <ocidl.h>
void
);
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.
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.
- Called by the container to load the control's properties.
IPersistPropertyBag::Load()
HRESULT Load(
#include <ocidl.h>
IPropertyBag * pPropBag,
IErrorLog * pErrorLog
);
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.
[in] Pointer to the caller's
IPropertyBag()
interface
bag that the control uses to read its properties.
Cannot be
NULL
.
[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.
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.
IPersistPropertyBag::InitNew()
- Called by the container to save the object's properties.
IPersistPropertyBag::Save()
HRESULT Save(
#include <ocidl.h>
IPropertyBag * pPropBag,
BOOL fClearDirty,
BOOL fSaveAllProperties
);
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.
[in] Pointer to the caller's
IPropertyBag()
interface
through which the object can write properties.
Cannot be
NULL
.
[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.
[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
).
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.
IPersistPropertyBag::InitNew()
,
IPersistPropertyBag::Load()
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()
.
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 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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the object on which it is implemented. |
|
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. |
- 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.
IPersistStorage::HandsOffStorage()
HRESULT HandsOffStorage(
#include <objidl.h>
void
);
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.
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.
S_OK
The object has successfully entered
HandsOff
mode.
IPersistStorage::Save()
,
IPersistStorage::SaveCompleted()
,
IRootStorage::SwitchToFile()
- Initializes a new object, providing a pointer to the storage to
be used for the object.
IPersistStorage::InitNew()
HRESULT InitNew((
#include <objidl.h>
IStorage * pStg
);
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.
Rather than calling
IPersistStorage::InitNew()
directly,
you typically
call the
OleCreate
helper function which does the following:
Calls the
CoCreateInstance()
function to
create an instance
of the object class
Queries the new instance for the
IPersistStorage()
interface
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.
An implementation of
IPersistStorage::InitNew()
should
initialize the
object to its default state, taking the following steps:
Pre-open and cache the pointers to any streams or storages that the object will need to save itself to this storage.
Call
IPersistStorage::AddRef()
and cache
the storage pointer that is
passed in.
Call the
WriteFmtUserTypeStg()
function
to write the native
clipboard format and user type string for the object to the storage object.
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.
[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).
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.
IPersistStorage::Load()
,
WriteFmtUserTypeStg()
- Indicates whether the object has changed since it was last saved
to its current storage.
IPersistStorage::IsDirty()
HRESULT IsDirty(
#include <objidl.h>
void
);
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.
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.
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.
S_OK
The object has changed since it was last saved.
S_FALSE
The object has not changed since the last save.
IAdviseSink::OnDataChange()
,
IDataObject::DAdvise()
,
IPersistStorage::Save()
- Loads an object from its existing storage.
IPersistStorage::Load()
HRESULT Load(
#include <objidl.h>
IStorage * pStg
);
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.
Rather than calling
IPersistStorage::Load()
directly,
you typically call
the
OleLoad
helper function which does the following:
Create an uninitialized instance of the object class
Query the new instance for the
IPersistStorage()
interface
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.
Your implementation should perform the following steps to load an object:
Open the object's streams in the storage object, and read the necessary data into the object's internal data structures.
Clear the object's dirty flag.
Call the
IPersistStorage::AddRef()
method
and cache the passed in
storage pointer.
Keep open and cache the pointers to any streams or storages that the object will need to save itself to this storage.
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.
[in] IStorage pointer to the existing storage from which the object is to be loaded.
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.
GetConvertStg()
,
IPersistStorage::InitNew()
,
ReadFmtUserTypeStg()
,
SetConvertStg()
,
WriteFmtUserTypeStg()
- Saves an object, and any nested objects that it contains, into
the
specified storage.
The object is placed in
IPersistStorage::Save()
NoScribble
mode,
and it must not write to the specified storage until it receives a call to
its
IPersistStorage::SaveCompleted()
method.
HRESULT Save(
#include <objidl.h>
IStorage * pStgSave,
BOOL fSameAsLoad
);
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.
Rather than calling
IPersistStorage::Save()
directly,
you typically call
the
OleSave
helper function which performs the following
steps:
Call the
WriteClassStg()
function to write
the class
identifier for the object to the storage.
Call the
IPersistStorage::Save()
method.
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.
[in]IStorage pointer to the storage into which the object is to be saved.
[in]Indicates whether the specified storage is the current one, which was passed to the object by one of the following calls:
IPersistStorage::InitNew()
when it was
created.
IPersistStorage::Load()
when it was loaded.
IPersistStorage::SaveCompleted()
when it
was saved to a storage different from its current storage.
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.
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.
IPersistStorage::InitNew()
,
IPersistStorage::Load()
,
IPersistStorage::SaveCompleted()
,
IStorage::Commit()
,
IStorage::CopyTo()
,
WriteClassStg()
,
WriteFmtUserTypeStg()
- Notifies the object that it can revert from
IPersistStorage::SaveCompleted()
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.
HRESULT SaveCompleted(
#include <objidl.h>
IStorage * pStgNew
);
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.
[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
.
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()
.
IAdviseSink::OnSave()
,
IPersistStorage::HandsOffStorage()
,
IPersistStorage::Save()
,
IRootStorage::SwitchToFile()
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.
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.
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
Description
|
GetClassID()
|
Returns the class identifier (CLSID) for the component object. |
|
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. |
- Returns the size in bytes of the stream needed to save the object.
IPersistStream::GetSizeMax()
HRESULT GetSizeMax(
#include <objidl.h>
ULARGE_INTEGER * pcbSize
);
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.
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.
[out] Points to a 64-bit unsigned integer value indicating the size in bytes of the stream needed to save this object.
S_OK
The size was successfully returned.
- Checks the object for changes since it was last saved.
IPersistStream::IsDirty()
HRESULT IsDirty(
#include <objidl.h>
void
);
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.
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.
S_OK
The object has changed since it was last saved.
S_FALSE
The object has not changed since the last save.
- Initializes an object from the stream where it was previously saved.
IPersistStream::Load()
HRESULT Load(
#include <objidl.h>
IStream * pStm
);
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.
Rather than calling
IPersistStream::Load()
directly,
you typically call
the
OleLoadFromStream
function does the following:
Calls the
ReadClassStm()
function to get
the class
identifier from the stream.
Calls the
CoCreateInstance()
function to
create an instance of
the object.
Queries the instance for
IPersistStream()
.
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.
[in] IStream pointer to the stream from which the object should be loaded.
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.
CoCreateInstance()
,
ReadClassStm()
- Saves an object to the specified stream.
IPersistStream::Save()
HRESULT Save(
#include <objidl.h>
IStream * pStm,
BOOL fClearDirty
);
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.
Rather than calling
IPersistStream::Save()
directly,
you typically call
the
OleSaveToStream
helper function which does the following:
Calls
IPersistStream::GetClassID()
to get
the object's CLSID.
Calls the
WriteClassStm()
function to write
the object's CLSID
to the stream.
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.
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.
[in] IStream pointer to the stream into which the object should be saved.
[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.
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.
IPersist::GetClassID()
,
IStream::Write()
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.
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.
Use this interface to initialize a stream-based object and to save that object to a stream.
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
|
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. |
- Same as
IPersistStreamInit::GetSizeMax()
IPersistStream::GetSizeMax()
.
HRESULT GetSizeMax(
#include <ocidl.h>
ULARGE_INTEGER * pcbSize
);
- Initializes the object to a default state.
This method is called
instead of
IPersistStreamInit::InitNew()
IPersistStreamInit::Load()
.
HRESULT InitNew((
#include <ocidl.h>
void
);
If the object has already been initialized with
Load
,
then this method
must return
E_UNEXPECTED
.
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.
- Same as
IPersistStreamInit::IsDirty()
IPersistStream::IsDirty()
.
HRESULT IsDirty(
#include <ocidl.h>
void
);
- Same as
IPersistStreamInit::Load()
IPersistStream::Load()
.
HRESULT Load(
#include <ocidl.h>
LPSTREAM pStm
);
If the object has already been initialized with
InitNew()
,
then this
method must return
E_UNEXPECTED
.
- Same as
IPersistStreamInit::Save()
IPersistStream::Save()
.
HRESULT Save(
#include <ocidl.h>
LPSTREAM pStm ,
BOOL fClearDirty
);
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.
A container implements this interface to provide its object with a way to store their properties persistently.
An object calls the methods on this interface to read and write its properties into the container provided property bag.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
|
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. |
IErrorLog()
,
IPersistPropertyBag()
- Called by the control to read a property from the storage provided by the
container.
IPropertyBag::Read()
HRESULT Read(
#include <ocidl.h>
LPCOLESTR pszPropName,
VARIANT * pVar,
IErrorLog * pErrorLog
);
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.
[in] Pointer to the name of the property to read.
Cannot be
NULL
.
[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
.
[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.
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.
- Called by the control to write each property in turn to the storage provided
by the container.
IPropertyBag::Write()
HRESULT Write(
#include <ocidl.h>
LPCOLESTR pszPropName,
VARIANT * pVar
);
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.
[in] Pointer to the name of the property to write.
Cannot be
NULL
.
[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
.
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.
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.
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.
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.
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
|
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. |
IPropertyStorage()
,
IEnumSTATPROPSETSTG
,
STATPROPSETSTG
,
PROPVARIANT
- Creates and opens a new property set in the property set storage
object.
IPropertySetStorage::Create()
HRESULT Create(
#include <objidl.h>
REFFMTID fmtid,
CLSID * pclsid,
DWORD grfFlags,
DWORD grfMode,
IPropertyStorage ** ppPropStg
);
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:
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
isSTGM_SHARE_EXCLUSIVE
. To use the resulting property set in an access mode other thanSTGM_SHARE_EXCLUSIVE
, the caller should close the stream and then re-open it with a call toIPropertySetStorage::Open()
.
[in] Format identifier of the property set to be created.
[in] Pointer to the initial CLSID for this property set.
May be
NULL
, in which case it is set to all zeroes.
[in] Values from the
PROPSETFLAG
enumeration.
[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.
[out] Indirect pointer to the
IPropertyStorage()
interface on the new property storage sub-object.
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.
- Deletes one of the property sets contained in the property set
storage object.
IPropertySetStorage::Delete()
HRESULT Delete(
#include <objidl.h>
REFFMTID fmtid
);
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.
[in] Format identifier of the property set to be deleted.
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.
- 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
IPropertySetStorage::Enum()
IEnumSTATPROPSETSTG()
pointer
on the enumerator object.
HRESULT Enum(
#include <objidl.h>
IEnumSTATPROPSETSTG ** ppenum
);
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.
[out] Indirect pointer to the
IEnumSTATPROPSETSTG()
on the newly created enumeration object.
S_OK
The enumerator object was successfully created.
STG_E_INSUFFICIENTMEMORY
There is not sufficient memory to perform this operation.
IEnumSTATPROPSETSTG()
,
IEnumSTATPROPSETSTG--Compound
File
Implementation
- Opens a property set contained in the property set storage object.
IPropertySetStorage::Open()
HRESULT Open(
#include <objidl.h>
REFFMTID fmtid,
DWORD grfMode,
IPropertyStorage ** ppPropStg
);
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).
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 . |
[in] Format identifier of the property set to be opened.
[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.
[in] Indirect pointer to the
IPropertyStorage()
interface
on the requested property storage sub-object.
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.
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
.
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.
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.
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.
IPropertyStorage()
,
,IPropertySetStorage()
- Compound File
Implementation
STATPROPSETSTG
structure,
PROPSETFLAG
enumeration,
IStorage::EnumElements()
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.
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.
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.
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
IPropertyStorage()
,
,
IPropertySetStorage()
- Compound File
ImplementationIPropertyStorage-Standalone
Implementation
,
STATPROPSETSTG
,
PROPSETFLAG
,
IStorage::EnumElements()
,
STGM
,
StgCreatePropStg()
,
StgOpenPropStg()
,
StgCreatePropSetStg()
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.
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.
Use
IPropertyStorage()
to create and manage properties
that are stored in a given
property set.
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments reference count. |
Release()
|
Decrements reference count. |
|
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. |
IPropertySetStorage()
,
IEnumSTATPROPSTG
,
IEnumSTATPROPSETSTG
,
STATPROPSTG
,STATPROPSETSTG
,
PROPVARIANT
- Saves any changes made to a property storage object to the parent
storage object.
IPropertyStorage::Commit()
HRESULT Commit(
#include <objidl.h>
DWORD grfCommitFlags
);
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:
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. |
[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.
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.
IPropertyStorage::ReadMultiple()
,
IStorage::Commit()
- Deletes as many of the indicated properties as exist in this property
set.
IPropertyStorage::DeleteMultiple()
HRESULT DeleteMultiple(
#include <objidl.h>
ULONG cpspec,
PROPSPEC const rgpspec[]
);
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.
[in] Count of properties being deleted. May legally be zero, though this is a no-op, deleting no properties.
[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.
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
PROPSPEC
s 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.
- Deletes specified string names from the current property set.
IPropertyStorage::DeletePropertyNames()
HRESULT DeletePropertyNames(
#include <objidl.h>
ULONG cpropid,
PROPID const rgpropid[]
);
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.
[in] The size on input of the array rgpropid. If 0, no property names are deleted.
[in] Property identifiers for which string names are to be deleted.
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.
IPropertyStorage::ReadPropertyNames()
- Creates an enumerator object designed to enumerate data of type
IPropertyStorage::Enum()
STATPROPSTG
, which contains information on the current property
set.
On return, this method supplies a pointer to the
IEnumSTATPROPSTG()
pointer on this object.
HRESULT Enum(
#include <objidl.h>
IEnumSTATPROPSTG ** ppenum
);
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.
[out] Indirect pointer to the
IEnumSTATPROPSTG()
interface on the new enumeration object.
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.
IEnumSTATPROPSTG()
,
IEnumSTATPROPSTG--Compound
File
Implementation
- Reads specified properties from the current property set.
IPropertyStorage::ReadMultiple()
HRESULT ReadMultiple(
#include <objidl.h>
ULONG cpspec,
PROPSPEC const rgpspec[],
PROPVARIANT rgvar[]
);
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.
[in] Count of properties specified in the rgpspec array. May legally be zero, though this is a no-op, reading no properties.
[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.
[in, out] Caller-allocated array of
PROPVARIANT
s
that, on return, contains the values of the properties specified by
rgpspec.
The array must be able to receive at least
cpspec
PROPVARIANT
s.
The caller does not need
to initialize these
PROPVARIANT
s 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
.
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.
IPropertySetStorage()
,
IPropertyStorage::WriteMultiple()
,
IPropertyStorage::WritePropertyNames()
- Retrieves any existing string names for the specified property
identifiers.
IPropertyStorage::ReadPropertyNames()
HRESULT ReadPropertyNames(
#include <objidl.h>
ULONG cpropid,
PROPID const rgpropid[],
LPWSTR rglpwstrName[]
);
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.
[in] Number of elements on input of the array rgpropid. May legally be zero, though this is a no-op, reading no property names.
[in] Array of property identifiers for which names are to be retrieved.
[in, out] Caller-allocated array of size
cpropid
of
LPWSTR
s.
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()
.
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.
IPropertyStorage::WritePropertyNames()
,
IPropertyStorage::WriteMultiple()
- Discards all changes to the property set it was opened or changes
were last committed.
Has no effect on a direct-mode property set.
IPropertyStorage::Revert()
HRESULT Revert(
#include <objidl.h>
);
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
.
This method supports the standard return value
E_UNEXPECTED
, as well as
the following:
S_OK
Success.
- Retrieves information about the current open property set.
IPropertyStorage::Stat()
HRESULT Stat(
#include <objidl.h>
STATPROPSTG * pstatpsstg
);
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:
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.
|
[out] Pointer to a
STATPROPSETSTG
structure, which
contains statistics about the current open property set.
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.
STATPROPSETSTG
structure,
IPropertySetStorage::Enum()
,
FILETIME
structure
- Assigns a new CLSID to the current property storage object, and
persistently stores the CLSID with the object.
IPropertyStorage::SetClass()
HRESULT SetClass(
#include <objidl.h>
REFCLSID clsid
);
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.
[in] New CLSID to be associated with the property set.
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.
IPropertySetStorage::Create()
,
IPropertyStorage::Stat()
- Sets the modification, access, and creation times of this property
set, if supported by the implementation.
Not all implementations support all
these time values.
IPropertyStorage::SetTimes()
HRESULT SetTimes(
#include <objidl.h>
FILETIME const * pctime,
FILETIME const * patime,
FILETIME const * pmtime
);
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
.
[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.
[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.
[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.
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.
IPropertyStorage::Stat()
,
FILETIME
structure
- 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.
IPropertyStorage::WriteMultiple()
HRESULT WriteMultiple(
#include <objidl.h>
ULONG cpspec,
PROPSPEC const rgpspec[],
PROPVARIANT const rgvar[],
PROPID propidNameFirst
);
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.
[in] The number of properties being set. May legally be zero, though this is a no-op, writing no properties.
[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.
[in] An array (of size
cpspec) of
PROPVARIANT
s that contain the property values to be written.
The array must
be of the size specified by
cpspec.
[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.
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
PROPSPEC
s 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.
IPropertySetStorage::Create()
,
IPropertyStorage::ReadMultiple()
- Assigns string names to a specified array of property IDs in the
current property set.
IPropertyStorage::WritePropertyNames()
HRESULT WritePropertyNames(
#include <objidl.h>
ULONG cpropid,
PROPID const rgpropid[],
LPWSTR const rglpwstrName[]
);
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.
[in] Size on input of the array rgpropid. May legally be zero, though this is a no-op, writing no property names.
[in] Array of the property identifiers for which names are to be set.
[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).
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.
IPropertyStorage::ReadPropertyNames()
,
IPropertyStorage::ReadMultiple()
,
IPropertyStorage::WriteMultiple()
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.
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.
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
PROPVARIANT
s.
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.
IPropertyStorage()
,
IStorage::SetElementTimes()
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.
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.
There are some differences between the standalone implementation of the property set interfaces and the compound file implementation. In the compound file implementation of stream, storage, property set storage, and property storage objects, the various interfaces are able to coordinate with one another because they are part of a common implementation. In the standalone implementation, the interface implementations are distinct from one another.
As a result, the compound-file implementation handles concurrency issues
and
synchronizes the property set object with the storage or stream object.
With
the standalone implementation, the client is responsible for handling
concurrency and synchronization issues between the storage or stream object
and
the property set.
A client can meet these requirements by following two simple
rules.
First, never manipulate a property set using its stream or storage
interfaces while a property storage object is opened on it.
And, second, always
Commit a property storage object before calling Commit,
CopyTo
,
or
MoveElementTo
on an ancestor storage object.
Specifically,
the following items
require client attention:
In the compound file implementation, a single mechanism provides concurrency protection for the storage object and its associated property set objects. However, in the standalone implementation, the storage object implementation is separate from the property set implementation and each provides its own concurrency mechanisms. Thus, in the standalone implementation, the client is responsible for maintaining concurrency protection between the two implementations through a mutual exclusion mechanism.
In the compound file implementation, changes to property sets
are buffered
in a property set cache.
Then, when the
IStorage::Commit()
method is
called on the storage object, the compound files implementation automatically
flushes the property set changes from the property set buffer before the
storage object is committed.
Thus, the property set changes are made visible
as
part of the transaction being committed.
In the standalone implementation, the client must explicitly
flush the
property set buffer by calling
IPropertyStorage::Commit()
before calling
the
IStorage:Commit
method on the storage.
Alternately,
the client can
use the new
PROPSETFLAG_UNBUFFERED
value in the standalone
implementation to
write directly to the property set instead of caching changes to the property
set's internal buffer.
If
PROPSETFLAG_UNBUFFERED
is used,
the client's
responsibilities are automatically met.
The compound file implementation does
not support the
PROPSETFLAG_UNBUFFERED
value.
See the
PROPSETFLAG
enumeration for more information on using this value.
As with transacted storages, the compound file implementation
updates the
property set by flushing its internal buffer prior to executing a call to
IStorage::CopyTo()
or
IStorage::MoveElementTo()
.
Thus, changes to the
property set are reflected in the copied or moved storage element.
In the standalone implementation, the client must explicitly
flush the
property set buffer by calling
IPropertyStorage::Commit()
before calling
IStorage::CopyTo()
or
IStorage::MoveElementTo()
.
Alternately, the
client can use the new
PROPSETFLAG_UNBUFFERED
to write
directly to the property
set instead of caching changes to the property set buffer.
See the
PROPSETFLAG
enumeration for more information on using this
value.
The standalone implementation of
IPropertyStorage()
supports
the following methods:
IPropertyStorage::ReadMultiple()
Reads the properties specified in the
rgpspec
array
and supplies the
values of all valid properties in the
rgvar
array of
PROPVARIANT
s.
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
IPropertySetStorage-Standalone Implementation
,
IPropertyStorage()
,
IStorage::SetElementTimes()
,
StgOpenPropStg()
,
StgCreatePropStg()
,
StgCreatePropSetStg()
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.
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.
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.
IUnknown()
Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
IRootStorage Method
|
Description
|
SwitchToFile
|
Copy the file underlying this root storage object, then associate this storage with the copied file. |
IStorage()
,
StgCreateDocfile()
- 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.
IRootStorage::SwitchToFile()
HRESULT SwitchToFile(
#include <objidl.h>
LPOLESTR pszFile
);
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.
If you are implementing your own storage objects, the
IRootStorage()
methods (including
QueryInterface()
,
AddRef()
, and
Release()
) must not consume
additional memory or file
handles.
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.
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.
IPersistStorage::HandsOffStorage()
,
IPersistStorage::SaveCompleted()
,
IStorage::Commit()
,
IStorage::Stat()
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()
.
Use the system-supplied implementation of
IRootStorage()
only to
support saving files under low memory conditions.
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.
IRootStorage()
;
IRootStorage::SwitchToFile()
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.
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.
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
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.
|
- 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.
IStorage::Commit()
HRESULT Commit(
#include <objidl.h>
DWORD grfCommitFlags
);
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:
When committing changes to root storage objects, the caller
must check the
return value to determine whether the operation has been completed
successfully, and if not, that the old committed contents of the
IStorage()
are still intact and can be restored.
If this storage object was opened with some of its items excluded, then the caller is responsible for rewriting them before calling commit. Write mode is required on the storage opening for the commit to succeed.
Unless prohibiting multiple simultaneous writers on the same
storage
object, an application calling this method should specify at least
STGC_ONLYIFCURRENT
in the
grfCommitFlags
parameter to prevent the
changes made by one writer from inadvertently overwriting the changes made
by
another.
See Also
IStorage - Compound File Implementation
,
STGC
,
IStorage::Revert()
[in] Controls how the changes are committed to the storage object.
See
the
STGC
enumeration for a definition of these 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.
- Copies the entire contents of an open storage object to another storage object.
IStorage::CopyTo()
HRESULT CopyTo(
#include <objidl.h>
DWORD ciidExclude,
IID const * rgiidExclude,
SNB snbExclude,
IStorage * pstgDest
);
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.
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)
[in] The number of elements in the array pointed to by
rgiidExclude.
If
rgiidExclude
is
NULL
,
then
ciidExclude
is ignored.
[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.
[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
.
[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.
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.
IStorage - Compound File Implementation
,
IStorage::MoveElementTo()
,
IStorage::Revert()
- Creates and opens a new storage object nested within this storage
object.
IStorage::CreateStorage()
HRESULT CreateStorage(
#include <objidl.h>
const WCHAR * pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
IStorage ** ppstg
);
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
.
[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.
[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.
[in] Reserved for future use; must be zero.
[in] Reserved for future use; must be zero.
[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.
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.
IStorage - Compound File Implementation
,
IStorage::OpenStorage()
- 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.
IStorage::CreateStream()
HRESULT CreateStream(
#include <objidl.h>
const WCHAR * pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
IStream ** ppstm
);
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
.
[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.
[in] Specifies the access mode to use when opening the newly created
stream.
See the
STGM
enumeration values for descriptions
of the possible values.
[in] Reserved for future use; must be zero.
[in] Reserved for future use; must be zero.
[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
.
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.
IStorage - Compound File Implementation
,
IStorage::OpenStream()
,
IStream()
- Removes the specified storage or stream from this storage object.
IStorage::DestroyElement()
HRESULT DestroyElement(
#include <objidl.h>
wchar * pwcsName
);
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()
.
[in] Points to a wide character string that contains the name of the storage or stream to be removed.
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.
IStorage - Compound File Implementation
- Retrieves a pointer to an enumerator object that can be used to
enumerate the storage and stream objects contained within this storage object.
IStorage::EnumElements()
HRESULT EnumElements(
#include <objidl.h>
DWORD reserved1,
void * reserved2,
DWORD reserved3,
IEnumSTATSTG ** ppenum
);
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
[in] Reserved for future use; must be zero.
[in] Reserved for future use; must be
NULL
.
[in] Reserved for future use; must be zero.
[out] When successful, points to the location of an
IEnumSTATSTG()
pointer to new enumerator object.
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.
- Copies or moves a substorage or stream from this storage object
to another storage object.
IStorage::MoveElementTo()
HRESULT MoveElementTo(
#include <objidl.h>
const WCHAR * pwcsName,
IStorage * pstgDest,
LPWSTR pwcsNewName,
DWORD grfFlags
);
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.
[in] Points to a wide character string that contains the name of the element in this storage object to be moved or copied.
[in]
IStorage()
pointer to the destination storage
object.
[in] Points to a wide character string that contains the new name for the element in its new storage object.
[in] Specifies whether the operation should be a move (STGMOVE_MOVE
) or a copy (STGMOVE_COPY
).
See the
STGMOVE
enumeration.
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.
IStorage - Compound File Implementation
,
STGMOVE
,
IStorage::CopyTo()
- Opens an existing storage object with the specified name in the
specified access mode.
IStorage::OpenStorage()
HRESULT OpenStorage(
#include <objidl.h>
const WCHAR * pwcsName,
IStorage * pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage ** ppstg
);
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.
[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
.
[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.
[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.
[in] Must be NULL.
A non-NULL
value will return
STG_E_INVALIDPARAMETER
.
[in] Reserved for future use; must be zero.
[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.
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.
IStorage - Compound File Implementation
,
IStorage::CreateStorage()
- Opens an existing stream object within this storage object in the specified
access mode.
IStorage::OpenStream()
HRESULT OpenStream(
#include <objidl.h>
const WCHAR * pwcsName,
void * reserved1,
DWORD grfMode,
DWORD reserved2,
IStream ** ppstm
);
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
.
[in] Points to a wide character string that contains the name of the stream to open.
[in] Reserved for future use; must be
NULL
.
[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.
[in] Reserved for future use; must be zero.
[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.
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.
IStorage - Compound File Implementation
,
IStorage::CreateStream()
,
IStream()
- Renames the specified substorage or stream in this storage object.
IStorage::RenameElement()
HRESULT RenameElement(
#include <objidl.h>
const WCHAR * pwcsOldName,
const WCHAR * pwcsNewName
);
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.
[in] Points to a wide character string that contains the name of the substorage or stream to be changed.
[in] Points to a wide character string that contains the new name for the specified sustorage or stream.
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.
IStorage - Compound File Implementation
- Discards all changes that have been made to the storage object since the last
commit.
IStorage::Revert()
HRESULT Revert(
#include <objidl.h>
void
);
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()
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.
- Assigns the specified CLSID to this storage object.
IStorage::SetClass()
HRESULT SetClass(
#include <objidl.h>
REFCLSID clsid
);
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()
[in] The class identifier (CLSID) that is to be associated with the storage object.
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.
- Sets the modification, access, and creation times of the specified
storage element, if supported by the underlying file system.
IStorage::SetElementTimes()
HRESULT SetElementTimes(
#include <objidl.h>
const WCHAR * pwcsName,
FILETIME const * pctime,
FILETIME const * patime,
FILETIME const * pmtime
);
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()
[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.
[in] Either the new creation time for the element or
NULL
if the creation time is not to be modified.
[in] Either the new access time for the element or
NULL
if the access time is not to be modified.
[in] Either the new modification time for the element or
NULL
if the modification time is not to be modified.
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.
- Stores up to 32 bits of state information in this storage object.
IStorage::SetStateBits()
HRESULT SetStateBits(
#include <objidl.h>
DWORD grfStateBits,
DWORD grfMask
);
This interface is reserved for future use. The values for the state bits are not currently defined.
[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.
[in] A binary mask indicating which bits in grfStateBits are significant in this call.
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.
IStorage - Compound File Implementation
,
IStorage::Stat()
- Retrieves the STATSTG structure for this open storage object.
IStorage::Stat()
HRESULT Stat(
#include <objidl.h>
STATSTG * pstatstg,
DWORD grfStatFlag
);
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.
[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.
[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.
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.
IStorage - Compound File Implementation
,
STATFLAG
,
STATSTG
,
IEnumSTATSTG()
,
IStorage::SetClass()
,
IStorage::SetElementTimes()
,
IStorage::SetStateBits()
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()
.
Most applications use this implementation to to create and manage storages and streams.
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:
The
STGM_DELETEONRELEASE
flag is not supported.
Transacted mode is not supported for stream objects.
Opening the same stream more than once from the same storage
is not
supported.
The
STGM_SHARE_EXCLUSIVE
flag must be
specified.
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:
The
STGM_DELETEONRELEASE
flag is not supported.
Transacted mode is not supported for stream objects.
Opening the same stream more than once from the same storage
is not
supported.
The
STGM_SHARE_EXCLUSIVE
flag must be
specified.
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:
The
STGM_PRIORITY
flag is not supported
for non-root storages.
Opening the same storage object more than once from the same
parent
storage is not supported.
The
STGM_SHARE_EXCLUSIVE
flag
must be specified.
The
STGM_DELETEONRELEASE
flag is not supported.
If this flag is specified,
the function returns
STG_E_INVALIDFUNCTION
.
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.
IStorage()
,
IStream()
,
StgCreateDocfile()
,
StgOpenStorage()
,
ILockBytes()
,
IRootStorage()
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:
|
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.
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.
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.
IUnknown Methods
|
Description
|
QueryInterface()
|
Returns pointers to supported interfaces. |
AddRef()
|
Increments the reference count. |
Release()
|
Decrements the reference count. |
|
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. |
- Creates a new stream object with its own seek pointer that references the
same bytes as the original stream.
IStream::Clone()
HRESULT Clone(
#include <objidl.h>
IStream ** ppstm
);
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()
[out] When successful, points to the location of an
IStream()
pointer to the new stream object.
If an error occurs, this parameter
is
NULL
.
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.
- 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()
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.
HRESULT Commit(
#include <objidl.h>
DWORD grfCommitFlags
);
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()
[in] Controls how the changes for the stream object are committed.
See
the
STGC
enumeration for a definition of these 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.
- Copies a specified number of bytes from the current seek pointer in the stream
to the current seek pointer in another stream.
IStream::CopyTo()
HRESULT CopyTo(
#include <objidl.h>
IStream * pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER * pcbRead,
ULARGE_INTEGER * pcbWritten
);
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()
[in] Points to the destination stream. The stream pointed to by pstm can be a new stream or a clone of the source stream.
[in] Specifies the number of bytes to copy from the source stream.
[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.
[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.
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.
- Restricts access to a specified range of bytes in the stream.
Supporting this
functionality is optional since some file systems do not provide it.
IStream::LockRegion()
HRESULT LockRegion(
#include <objidl.h>
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
);
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.
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.
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()
[in] Integer that specifies the byte offset for the beginning of the range.
[in] Integer that specifies the length of the range, in bytes, to be restricted.
[in] Specifies the restrictions being requested on accessing the range.
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.
- Reads a specified number of bytes from the stream object into memory starting
at the current seek pointer.
IStream::Read()
HRESULT Read(
#include <objidl.h>
void * pv,
ULONG cb,
ULONG * pcbRead
);
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.
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.
[in] Points to the buffer into which the stream is read.
If an error
occurs, this value is
NULL
.
[in] Specifies the number of bytes of data to attempt to read from the stream object.
[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.
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.
IStream - Compound File Implementation
,
STGMOVE
,
IStorage::OpenStream()
,
IStream::Write()
- Discards all changes that have been made to a transacted stream since the
last
IStream::Revert()
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.
HRESULT Revert(
#include <objidl.h>
void
);
This method discards changes made to a transacted stream since the last commit operation.
See Also
IStream - Compound File Implementation
,
IStream::Commit()
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.
- 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::Seek()
HRESULT Seek(
#include <objidl.h>
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER * plibNewPosition
);
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()
[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.
[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.
[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.
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.
- Changes the size of the stream object.
IStream::SetSize()
HRESULT SetSize(
#include <objidl.h>
ULARGE_INTEGER libNewSize
);
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()
[in] Specifies the new size of the stream as a number of bytes.
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.
- Retrieves the STATSTG structure for this stream.
IStream::Stat()
HRESULT Stat(
#include <objidl.h>
STATSTG * pstatstg,
DWORD grfStatFlag
);
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.
[out] Points to a
STATSTG
structure where this method
places information about this stream object.
This pointer is
NULL
if an error occurs.
[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.
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.
IStream - Compound File Implementation
,
STATFLAG
,
STATSTG
- Removes the access restriction on a range of bytes previously
restricted with
IStream::UnlockRegion()
IStream::LockRegion()
.
HRESULT UnlockRegion(
#include <objidl.h>
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType
);
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()
[in] Specifies the byte offset for the beginning of the range.
[in] Specifies, in bytes, the length of the range to be restricted.
[in] Specifies the access restrictions previously placed on the range.
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.
- Writes a specified number from bytes into the stream object starting at the
current seek pointer.
IStream::Write()
HRESULT Write(
#include <objidl.h>
void const * pv,
ULONG cb,
ULONG * pcbWritten
);
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.
[in] Points to the buffer from which the stream should be written.
[in] The number of bytes of data to attempt to write into the stream.
[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.
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.
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.
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.
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.
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.
IStream()
,
IStorage()
,
CreateStreamOnHGlobal()
,
StgCreateDocfile()
,
StgOpenStorage()
- Calls
FreePropVariantArray()
PropVariantClear()
on each of the
PROPVARIANT
s in the rgvar array to zero the value of each of the members of
the array.
HRESULT FreePropVariantArray((
#include <objidl.h>
ULONG cVariant,
PROPVARIANT * rgvar[]
);
FreePropVariantArray()
calls
PropVariantClear()
on an array of
PROPVARIANT
s to clear all the valid members.
All valid
PROPVARIANTS
are freed.
If any of the
PROPVARIANT
s 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
.
[in] Count of elements in the
PROPVARIANT
array (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
).
S_OK
The variant types are recognized and all items that can be freed have been freed.
STG_E_INVALID_PARAMETER
One or more
PROPVARIANT
s has an unknown type.
- Converts a property set's storage or stream name to its format identifier.
PropStgNameToFmtId()
HRESULT PropStgNameToFmtId((
#include <objidl.h>
const LPOLESTR oszName,
FMTID * pfmtid
);
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
.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
[in] Pointer to a string containing the stream name of a simple property set or the storage name of a nonsimple property set.
[out] Pointer to a FMTID variable that receives the format identifier of the property set specified by oszName.
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.
PROPSETFLAG
,
StgCreatePropStg()
,
StgOpenPropStg()
- Frees all elements that can be freed in a given
PropVariantClear()
PROPVARIANT
structure.
HRESULT PropVariantClear((
#include <objidl.h>
PROPVARIANT * pvarg
);
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
.
[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
.
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.
- Copies the contents of a
PropVariantCopy()
PROPVARIANT
structure to another.
HRESULT PropVariantCopy((
#include <objidl.h>
PROPVARIANT * pDest,
PROPVARIANT * pvarg
);
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.
[in, out] Pointer to an uninitialized
PROPVARIANT
structure that receives the copy.
[in] Pointer to the
PROPVARIANT
to be copied.
S_OK
The copy was successfully completed.
STG_E_INVALID_PARAMETER
The variant has an unknown type.
- Reads the CLSID previously written to a storage object with the
ReadClassStg()
WriteClassStg()
.
WINOLEAPI ReadClassStg((
#include <ole2.h>
IStorage * pStg,
CLSID * pclsid
);
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.
[in] Pointer to the
IStorage()
interface on the storage
object containing the CLSID to be retrieved.
[out] Pointer to where the CLSID is written.
May return
CLSID_NULL
.
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.
WriteClassStg
,
IStorage::Stat()
,
STATSTG
structure.
- Reads the CLSID previously written to a stream object with the
ReadClassStm()
WriteClassStm()
method.
WINOLEAPI ReadClassStm((
#include <ole2.h>
IStream * pStm,
CLSID * pclsid
);
Most applications do not call the
ReadClassStm()
method directly.
COM calls it before making a call to an object's
IPersistStream::Load()
implementation.
[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()
.
[out] Pointer to where the CLSID is to be written.
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.
WriteClassStm()
,
ReadClassStg
,WriteClassStg
- Returns the clipboard format and user type previously saved with the
ReadFmtUserTypeStg()
WriteFmtUserTypeStg()
function.
WINOLEAPI ReadFmtUserTypeStg((
#include <ole2.h>
IStorage * pStg,
CLIPFORMAT * pcf,
LPWSTR * lplpszUserType
);
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.
[in] Pointer to the
IStorage()
interface on the storage
object from which the information is to be read.
[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.
[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()
.
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.
CoTaskMemFree()
,
WriteFmtUserTypeStg()
- 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
SetConvertStg()
GetConvertStg()
function.
WINOLEAPI SetConvertStg((
#include <ole2.h>
IStorage * pStg,
BOOL fConvert
);
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:
Unload the object if it is currently loaded.
Call
WriteClassStg()
to write the new CLSID
to the object
storage.
Call
WriteFmtUserTypeStg()
to write the
new user type name and
the existing main format to the storage.
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.
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:
Call the
GetConvertStg()
function to retrieve
the value of
the conversion bit.
If the bit is set, the server reads the data out of the object according to the format associated with the new CLSID.
When the object is asked to save itself, the object should
call
WriteFmtUserType
() using the normal native format and user
type of the
object.
The object should then call
SetConvertStg()
with the
fConvert
parameter set to
FALSE
to reset the object's conversion
bit.
IStorage()
pointer to the storage object in which
to set the conversion bit.
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.
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.
- Creates a new compound file storage object using the COM-provided
compound file implementation for the
StgCreateDocfile()
IStorage()
interface.
WINOLEAPI StgCreateDocfile((
#include <objbase.h>
const WCHAR * pwcsName,
DWORD grfMode,
DWORD reserved,
IStorage ** ppstgOpen
);
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.
[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.
[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.
[in] Reserved for future use; must be zero.
[out] Points to the location of the
IStorage()
pointer
to the new storage object.
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.
- 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
StgCreateDocfileOnILockBytes()
IStorage()
interface.
WINOLEAPI StgCreateDocfileOnILockBytes((
#include <objbase.h>
ILockBytes * plkbyt,
DWORD grfMode,
DWORD reserved,
IStorage ** ppstgOpen
);
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:
The storage structure of the document is the same as its storage structure when it is an embedded object, reducing the number of cases the application needs to handle.
One can write tools to access the COM embeddings and links within the document without special knowledge of the document's file format. An example of such a tool is a copy utility that copies all the documents included in a container containing linked objects. A copy utility like this needs access to the contained links to determine the extent of files to be copied.
The
IStorage()
implementation addresses
the problem of how to
commit the changes to the file.
An application using the
ILockBytes()
interface must handle these issues itself.
Future file systems will likely implement the
IStorage()
and
IStream()
interfaces as their native abstractions, rather
than
layer on top of a byte array as is done in compound files.
Such a file system
could be built so documents using the
IStorage()
interface
as their outer
level containment structure would get an automatic efficiency gain by having
the layering flattened when files are saved on the new file system.
[in] Points to the
ILockBytes()
interface on the
underlying byte array object on which to create a compound file.
[in] Specifies the access mode to use when opening the new compound
file.
For more information, see the
STGM
enumeration.
[in] Reserved for future use; must be zero.
[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
.
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.
- Creates a property set storage object from a specified storage object.
The
property set storage object supplies the system-provided, standalone implementation
of the
StgCreatePropSetStg()
IPropertySetStorage()
interface.
HRESULT StgCreatePropSetStg((
#include <objidl.h>
IStorage * pStorage,
DWORD dwReserved,
IPropertySetStorage ** ppPropSetStg
);
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
[in] Pointer to the storage object that contains one or more property sets.
Reserved for future use; must be zero.
[out] Address of
IPropertySetStorage()
pointer variable
that receives the
interface pointer to the property set storage object.
This function supports the standard return value
E_INVALIDARG
as well as
the following:
S_OK
The property set storage object was successfully created.
IPropertySetStorage-Standalone Implementation
- Creates and opens a property set in a specified storage or stream object.
The property set supplies the system-provided, standalone implementation of
the
StgCreatePropStg()
IPropertyStorage()
interface.
HRESULT StgCreatePropStg((
#include <objidl.h>
IUnknown * pUnk,
REFFMTID fmtid,
const CLSID * pclsid,
DWORD grfFlags,
DWORD dwReserved,
IPropertyStorage ** ppPropStg
);
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
[in] Pointer to the
IUnknown()
interface on the storage
or stream object that
stores the new property set.
[in] Format identifier of the property set to be created.
[in] Pointer to the initial CLSID for this property set.
May be
NULL
, in which case
pclsid
is set to all zeroes.
[in] Values from the
PROPSETFLAG
enumeration that
determine how the property set is created and opened.
[in] Reserved; must be zero.
[out] Address of the
IPropertyStorage()
pointer variable
that receives
the interface pointer to the new property set.
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.
IPropertySetStorage()
,
IPropertySetStorage-Standalone
Implementation
,
IPropertyStorage()
,
IPropertyStorage-Standalone Implementation
,
PROPSETFLAG
,
StgOpenPropStg()
,
StgCreatePropSetStg()
- Indicates whether a particular disk file contains a storage object.
StgIsStorageFile()
WINOLEAPI StgIsStorageFile((
#include <objbase.h>
const WCHAR * pwcsName
);
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
.
[in] Points to the name of the disk file to be examined. The pwcsName parameter is passed uninterpreted to the underlying file system.
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.
- Indicates whether the specified byte array contains a storage
object.
StgIsStorageILockBytes()
WINOLEAPI StgIsStorageILockBytes((
#include <objbase.h>
ILockBytes * plkbyt
);
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.
ILockBytes()
pointer to the byte array to be examined.
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.
StgIsStorageFile()
,
ILockBytes()
- Opens a specified property set in a specified storage or stream object.
The
property set supplies the system-provided, standalone implementation of the
StgOpenPropStg()
IPropertyStorage()
interface.
HRESULT StgOpenPropStg((
#include <objidl.h>
IUnknown * pUnk,
REFFMTID fmtid,
DWORD grfFlags,
DWORD dwReserved,
IPropertyStorage ** ppPropStg
);
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
[in] Interface pointer for
IUnknown()
interface on
the storage or stream object that contains the requested property set object.
[in] Format identifier of the property set to be opened.
[in] Values from the
PROPSETFLAG
enumeration.
[in] Reserved for future use; must be zero.
[out] Address of
IPropertyStorage()
pointer variable
that receives
the interface pointer to the requested property set.
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.
IPropertySetStorage()
,
IPropertySetStorage-Standalone
Implementation
,
IPropertyStorage()
,
IPropertyStorage-Standalone Implementation
,
PROPSETFLAG
,
StgCreatePropStg()
,
StgCreatePropSetStg()
- 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
StgOpenStorage()
IStorage::OpenStorage()
method.
WINOLEAPI StgOpenStorage((
#include <objbase.h>
const WCHAR * pwcsName,
IStorage * pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage ** ppstgOpen
);
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
.
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.
[in] Points to the path of the file storage object to open.
This parameter
is ignored if the
pStgPriority
parameter is not
NULL
.
[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.
[in] Specifies the access mode to use to open the storage object.
[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
.
[in] Indicates reserved for future use; must be zero.
[out] Address of
IStorage*
pointer variable that
receives the
interface pointer to the opened storage.
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
.
IStorage()
,
StgCreateDocfile()
,
StgOpenStorageEx
- Opens an existing storage object that does not reside in a disk
file, but instead has an underlying byte array provided by the caller.
StgOpenStorageOnILockBytes()
WINOLEAPI StgOpenStorageOnILockBytes((
#include <objbase.h>
ILockBytes * plkbyt,
IStorage * pStgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage ** ppstgOpen
);
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()
.
[in]
ILockBytes()
pointer to the underlying byte
array object that contains the storage object to be opened.
[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.
[in] Specifies the access mode to use to open the storage object.
[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.
[in] Indicates reserved for future use; must be zero.
[out] Points to the location of an
IStorage()
pointer
to the opened storage on successful return.
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.
StgOpenStorage()
,
StgCreateDocfileOnILockBytes()
- Sets the creation, access, and modification times of the indicated file, if
supported by the underlying file system.
StgSetTimes()
WINOLEAPI StgSetTimes((
#include <objbase.h>
WCHAR const * lpszName,
FILETIME const * pctime,
FILETIME const * patime,
FILETIME const * pmtime
);
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.
[in] Points to the name of the file to be changed.
[in] Points to the new value for the creation time.
[in] Points to the new value for the access time.
[in] Points to the new value for the modification time.
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
.
- Stores the specified CLSID in a storage object.
WriteClassStg()
WINOLEAPI WriteClassStg((
#include <ole2.h>
IStorage * pStg,
REFCLSID rclsid
);
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.
[in]
IStorage()
pointer to the storage object that
gets a new CLSID.
[in] Points to the CLSID to be stored with the object.
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.
- Stores the specified CLSID in the stream.
WriteClassStm()
WINOLEAPI WriteClassStm((
#include <ole2.h>
IStream * pStm,
REFCLSID rclsid
);
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.
[in]
IStream()
pointer to the stream into which the
CLSID is to be written.
[in] Specifies the CLSID to write to the stream.
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.
ReadClassStm()
,
WriteClassStg()
,
ReadClassStg()
- Writes a clipboard format and user type to the storage object.
WriteFmtUserTypeStg()
WINOLEAPI WriteFmtUserTypeStg((
#include <ole2.h>
IStorage * pStg,
CLIPFORMAT cf,
LPWSTR * lpszUserType
);
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.
[in]
IStorage()
pointer to the storage object where
the information is to be written.
[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.
[in] Points to the object's current user type.
It cannot be
NULL
.
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.
IPersistStorage::Save()
,
ReadFmtUserTypeStg()
- 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
CreateILockBytesOnHGlobal()
ILockBytes()
interface.
WINOLEAPI CreateILockBytesOnHGlobal((
#include <ole2.h>
HGLOBAL hGlobal,
BOOL fDeleteOnRelease,
ILockBytes ** ppLkbyt
);
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.
[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.
[in] IWhether the underlying handle for this byte array object should be automatically freed when the object is released.
[out] Address of
ILockBytes*
pointer variable that
receives the
interface pointer to the new byte array object.
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.
StgOpenStorageOnILockBytes()
,
GetHGlobalFromILockBytes()
,
ILockBytes()
- Creates a stream object stored in global memory.
CreateStreamOnHGlobal()
WINOLEAPI CreateStreamOnHGlobal((
#include <ole2.h>
HGLOBAL hGlobal,
BOOL fDeleteOnRelease,
LPSTREAM * ppstm
);
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.
[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.
[in] Whether the underlying handle for this stream object should be automatically freed when the stream object is released.
[out] Address of
IStream*
pointer variable that receives
the
interface pointer to the new stream object.
Its value cannot be
NULL
.
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.
CreateStreamOnHGlobal()
,
GetHGlobalFromStream
,
IStream::SetSize()
,<
In the
Win32 Programmer's Reference:
>
GlobalSize
<
in Win32
>
- Supplies the CLSID associated with the given filename.
GetClassFile()
WINOLEAPI GetClassFile((
#include <objbase.h>
LPCWSTR szFileName,
CLSID * pclsid
);
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:
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.
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.
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.
If all strategies fail, the function returns
MK_E_INVALIDEXTENSION
.
[in] Points to the filename for which you are requesting the associated CLSID.
[out] Points to the location where the associated CLSID is written on return.
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.
- Returns the current value of the convert bit for the specified storage object.
GetConvertStg()
WINOLEAPI GetConvertStg((
#include <ole2.h>
IStorage * pStg
);
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
.
[in]
IStorage()
pointer to the storage object from
which the convert bit is to be retrieved.
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.
- Retrieves a global memory handle to a byte array object created
using the
GetHGlobalFromILockBytes()
CreateILockBytesOnHGlobal()
function.
WINOLEAPI GetHGlobalFromILockBytes((
#include <ole2.h>
ILockBytes * pLkbyt,
HGLOBAL * phglobal
);
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.
[in] Points to the
ILockBytes()
interface on the
byte array object previously created by a call to the
CreateILockBytesOnHGlobal()
function.
[out] Points to the current memory handle used by the specified byte array object.
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.
StgOpenStorage()
,
CreateILockBytesOnHGlobal()
- Retrieves the global memory handle to a stream that was created through a
call to the
GetHGlobalFromStream()
CreateStreamOnHGlobal()
function.
WINOLEAPI GetHGlobalFromStream((
#include <ole2.h>
IStream * pstm,
HGLOBAL * phglobal
);
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.
[in]
IStream()
pointer to the stream object previously
created by a call to the
CreateStreamOnHGlobal()
function.
[out] Points to the current memory handle used by the specified stream object.
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.
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;
The low 32 bits of the Win32 date/time value.
The upper 32 bits of the Win32 date/time value.
The
FILETIME
data structure is used in the time conversion
functions between DOS and Win32.
CoDosDateTimeToFileTime()
,
CoFileTimeNow()
,
CoFileTimeToDosDateTime()
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;
Number of strings in the rgString buffer.
Size in bytes of the rgString buffer.
Pointer to an array of bytes containing the
<[REVIEW: NULL separated?]>
stream name strings from the
SNB
.
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
Format identifier of the current property set.
The CLSID associated with this property set.
Flag values of the property set, as specified in
IPropertySetStorage::Create()
.
Time in Universal Coordinated Time (UTC) that the property set was last modified.
Time in UTC at which this property set was created.
Time in UCT at which this property set was last accessed.
IPropertySetStorage::Create()
,
IEnumSTATPROPSETSTG()
,
IPropertyStorage::Stat()
,
FILETIME
structure
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
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()
.
A 32-bit identifier that uniquely identifies the property within the property set. All properties within property sets must have unique property identifiers.
Type of the property.
IPropertyStorage::Enum()
,
IEnumSTATPROPSTG()
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;
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.
Indicates the type of storage object.
This is one of the values from
the
STGTY
enumeration.
Specifies the size in bytes of the stream or byte array.
Indicates the last modification time for this storage, stream, or byte array.
Indicates the creation time for this storage, stream, or byte array.
Indicates the last access time for this storage, stream or byte array.
Indicates the access mode specified when the object was opened.
This
member is only valid in calls to
Stat
methods.
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.
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.
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.
Indicates the format of the storage object.
This is one of the values
from the
STGFMT
enumeration.
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;
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.
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
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.
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.
Unicode | Yes |
Import Library | IPROP.DLL |
Header File | IPROPIDL.H |
IPropertySetStorage::Create()
,
IPropertySetStorage::Open()
,
PropStgNameToFmtId()
,
StgCreatePropSetStg()
,
StgCreatePropStg()
,
StgOpenPropStg()
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;
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:
the user has indicated a willingness to risk losing the data
the low memory save sequence will be used to safely save the storage object to a smaller file
a previous commit returned
STG_E_MEDIUMFULL
but overwriting the existing data would provide enough space to commit changes
to the storage object
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.
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.
IPropertyStorage()
,
IStorage()
,
IStream()
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;
STGFMT_DOCUMENT
Indicates a document format.
STGFMT_DIRECTORY
Indicates a directory format.
STGFMT_CATALOG
Indicates a catalog format.
STGFMT_FILE
Indicates a file format.
STATSTG
,
StgCreateDocfile()
,
StgIsStorageFile()
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_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 |
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
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_
* GroupSTGM_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
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:
when you are trying to create a storage object on disk but a file of that name already exists
when you are trying to create a stream inside a storage object but a stream with the specified name already exists
when you are creating a byte array object but one with the specified name already exists
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.
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:
There is no support for substorages.
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.
The storage and stream objects cannot be marshaled.
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.
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
.
StgCreateDocfile()
,
IStream::Read()
,
IStorage()
,
StgCreateDocfileOnILockBytes()
,
StgOpenStorage()
,
StgOpenStorageOnILockBytes()
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;
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.
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;
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.
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;
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.
IStream::Seek()