As we've seen in the last two sections, both IStorage and IStream have a member function named Stat, along with IStorage::EnumElements, which returns an IEnumSTATSTG pointer. All of these functions deal with the STATSTG structure, which contains information such as the name of the element, creation and modification times, the type of object (storage or stream), the access mode under which the object is opened, and whether the object supports region locking:
typedef struct FARSTRUCT tagSTATSTG
{
char FAR *pwcsName; //Name of element
DWORD type; //Type of element
ULARGE_INTEGER cbSize; //Size of element
FILETIME mtime; //Last mod date/time
FILETIME ctime; //Creation date/time
FILETIME atime; //Last access date/time
DWORD grfMode; //Mode element opened in
DWORD grfLocksSupported; //Support region locking?
CLSID clsid; //CLSID of element
DWORD grfStateBits; //Current state
DWORD reserved;
} STATSTG;
//For type field
typedef enum tagSTGTY
{
STGTY_STORAGE = 1, //Storage object
STGTY_STREAM = 2, //Stream object
STGTY_LOCKBYTES = 3, //Byte array object (Compound Files)
} STGTY;
//For grfLocksSupported
typedef enum tagLOCKTYPE
{
LOCK_WRITE = 1,
LOCK_EXCLUSIVE = 2,
LOCK_ONLYONCE = 4
} LOCKTYPE;
The mtime, ctime, atime, and clsid fields are meaningful only for storage elements, whereas grfLocksSupported is meaningful only for streams. Furthermore, grfMode is not meaningful in the context of IEnumSTATSTG, only in Stat calls.
The mtime field (modification time) will contain a different time stamp depending on whether the mode of the storage is direct or transacted. (See the next section.) The value of mtime for a transacted storage will be the time of the last commit. For a direct storage, mtime will contain the time of the last call to IStorage::Commit or the last call to IStorage::Release because Commit has no impact on a direct-mode storage other than flushing buffers.
You might have noticed the STGTY_LOCKBYTES flag that crept in here: this specifically identifies a LockBytes object that is peculiar to Compound Files, OLE's storage implementation. It is not strictly part of the general Structured Storage specification.
One more important point to remember about a STATSTG structure is that pwcsName points to a buffer allocated with the task allocator from CoGetMalloc. The client that calls Stat or IStorage::EnumElements becomes responsible for this memory, so you must free it with CoTaskMemFree.
In looking through the IStorage and IStream members, we've seen a number of references to access modes such as transacted and direct. It's time now to look at all of these modes along with the other features of this technology.