

                     Compound Documents v1.00
                     ~~~~~~~~~~~~~~~~~~~~~~~~
                       Robert R. Marsh, SJ
                         rrm@sprynet.com
                 http://home.sprynet.com/sprynet/rrm/

   Compound Documents, or OLE Structured Storage, provide an
   ingenious and easy way to effectively create a full file-system
   within a file. A compound document functions as a 'directory'
   (or root storage in the lingo) which can contain 'sub-directories'
   (aka storages) and/or 'files' (aka streams).
   Compound documents also have the ability to automatically buffer
   any changes until they are committed or rolled back.

   Unfortunately, the association with OLE/ActiveX keeps many Delphi
   users away. But while the details can be messy there is no deep
   difficulty. Some Delphi encapsulations of compound files are
   already available but either cost big bucks or mirror the
   underlying API too closely with all its arcane flags many of which
   are mutually exclusive. The components presented here encapsulate
   the OLE structured storage API in a what is, I hope, a Delphi-
   friendly manner, free from all the OLE clutter. What's more they
   work in all three versions of Delphi (see below for a caveat).

   A TRootStorage object corresponds to a physical file on disk.
   Other TStorage objects correspond to sub-storages of a root
   storage. Apart from their mode of construction both objects have
   similar behavior. They have methods to manage the sub-storages
   and streams they contain (CopyElement, MoveElement, RenameElement,
   DeleteElement, CopyTo, ListStorages, ListStreams) and methods to
   handle transaction processing (Commit, Revert).

   TStorageStream objects always belong to a parent storage object.
   They are fully compatible with Delphi's other stream objects.
   Despite the impression given in many descriptions transaction
   processing does not work at the stream level but only for storages.

   Transaction processing operates by publishing any changes visible
   at one level in the storage hierarchy to the parent level. A
   storage has no knowledge of changes made at a deeper level until
   they percolate upwards through a series of Commit operations.
   When a root storage commits its changes they are written to the
   physical file.

   Both storages and streams can be created as temporary objects by
   providing no Name parameter. A unique name is generated by Windows
   and is available through the Name property. Such objects are self-
   deleting.

   The OLE documentation warns that compound files are optimized
   for common operations (like the reading and writing of streams)
   and that other operations (especially those involving the
   enumeration of storage elements) can be slow. Although I have
   provided some enumeration methods (ListStorages, ListStreams) you
   will get better performance if you create a separate stream to
   store such information for yourself. In general, I have found
   read/write operations to be about 2 to 3 times slower than
   equivalent operations on 'ordinary' file streams. Not bad
   considering the extra functionality.

   You can find out more about Compound Documents / OLE Structured
   Storage from the excellent book "Inside OLE" (2nd ed.) by Kraig
   Brockschmidt (Microsoft Press) or from the Microsoft Developers
   Network library (via http://microsoft.com/msdn/). Good luck!

   One of the benefits of these components is that someone has read
   the small print for you and made many illegal operations
   impossible. I realize, however, that I have probably misread in
   some cases. So if you find problems with this code please let me
   know at the address above so that I can learn from my mistakes.

   I referred above to a caveat regarding the use of these components
   with Delphi 1. There are two issues. First, as I understand it, OLE2
   came on the scene after Windows 3.1 so that plain vanilla
   installations don't include the necessary OLE dlls. Nevertheless,
   it would be rare to find a machine that hasn't had the OLE2 files
   added by one application or another. The second issue has more to
   do with Borland. The OLE2 DCU and PAS files they supplied with D1
   seem to be contain errors (even on the D2 and D3 CDs). I have taken
   the liberty of correcting the problems which pertain to Compound
   Documents and also changed some of the flag declaration to bring them
   more into line with D2 and D3. The result is a file called OLE2_16
   which must be used with CompDoc.DCU under Delphi 1. Other versions
   of Delphi can ignore this file.

   If you like these components and find yourself using them please
   consider making a donation to your favorite charity. I would also
   be pleased if you would make acknowledgement in any projects that
   make use of them.

   These components are supplied as is. The author disclaims all
   warranties, expressed or implied, including, without limitation,
   the warranties of merchantability and of fitness for any purpose.
   The author assumes no liability for damages, direct or
   consequential, which may result from their use.

           Copyright (c) 1998 Robert R. Marsh, S.J. &
          the British Province of the Society of Jesus

Robert R. Marsh, S.J.
January 6, 1998
