IStream - Compound File Implementation

The IStream interface supports reading and writing data to stream objects. In a structured storage object, stream objects contain the data and storages provide the structure. Simple data can be written directly to a stream, but more 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 2⁶⁴ bytes in length requiring a 64-bit seek pointer. However, the COM implementation only supports streams up to 2³² bytes in length (4 GB) and read and write operations are always limited to 2³² bytes at a time. The COM implementation also does not support stream transactioning or region locking.

To create a simple stream based on global memory, 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 or OpenStream for an IStream pointer. In either case, the same IStream implementation code is used.

Note

The compound file implementation of structured storage does not succeed on a QueryInterface method for ISequentialStream, but it includes the Read and Write methods through the IStream interface pointer.

 

When to Use

Call the methods of IStream to read and write data to a stream.

Because 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, use the IStream::Clone method to provide a copy of the stream object for the remote process.

Note

If creating a stream object that is larger than the heap in your computer's memory and you are using an HGLOBAL handle to a global memory object, the stream object calls the GlobalRealloc method internally when it requires more memory. Because GlobalRealloc always copies data from the source to the destination, increasing a stream object from 20 MB to 25 MB, for example, requires large amounts of time. This is due to the size of the increments copied and is worsened if there is less than 45 MB of memory on the computer because of disk swapping.

The preferred solution is to implement an IStream method 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 required.

An alternative to GlobalRealloc 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.

 

Methods

ISequentialStream::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.)

ISequentialStream::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.

A simple-mode IStream is subject to the following constraints.

  • A stream is simple mode if it was created or opened from a simple-mode storage. A storage is simple mode if it is created or opened with the STGM_SIMPLE flag set in the grfMode parameter.
  • The Clone and CopyTo methods are not supported.
  • The Stat method is supported, but the STATFLAG_NONAME value must be specified.

IStream

IStorage

CreateStreamOnHGlobal

StgCreateDocfile

StgOpenStorage