This example shows how to interpret a hex dump of a simple compound file. The screen shot above shows the layout of the file and directories. NB for this example the block size has been set to 0x100 (256), usually the block size is 0x800 (2048)

0x00 to 0xFF - The compound file header

The header contains info about the compond file, for instance its on-disk layout.

0x1234567 m_iMagic1 - First of the two magic numbers
0x89abcdef m_iMagic2 - Secong magic number
0x34 m_iHeaderSize - Size of the header in bytes
0x2 m_iVersion - Version of the DLL that created this compound file

0x1 m_iLowVersion - Lowest version of the DLL that can read this file
0x1 m_iAllocTableIndex - Block index of the allocation table (1 * block size = 0x100)
0x2 m_iFileTableIndex - Block index of the file table
0x3 m_iDirTableIndex - Block index of the directory table

0x4 m_iNamesIndex - Block index of the names table
0xffffffff m_iNextID - Block index to the next block. Not currently used
0x268 m_iPhysicalPosOfFileTable_FileTableEntry - Position of the file table in the file, this is a physical position, not a block index. See CompoundFileSys.LoadFromExistingStream
0xc8 m_iVirtualSizeOfFileTable - Size of the file table. See CompoundFileSys.LoadFromExistingStream

0x100 m_iBlockSize - Block size

0x100 to 0x1FF - The allocation table

Each block in the compound file has a corresponding entry in the allocation table. The allocation table is not a "map" of the file (e.g. the way MS-DOS FAT tables work). Rather each entry has an ID which is its block index, to check if a block is empty the allocation table needs to check if the ID has been used by any of the entries.

0xa1b55b1a BlockHeader::m_iMagic - magic number
0x6 BlockHeader::m_iTotalItems - number of items in the alloc table
0xffffffff m_iNext - next alloc table block in the chain

Each entry in the allocation table has 3 values (m_iID, m_iNext and m_iFlags). The image above shows a hex dump containing 3 allocation table entries (each with 3 values).

The first entry (m_iID = 5, m_iNext = -1 and m_iFlags = 0x20) if for block 5, which in this example is the block containing the users text (i.e. the file).

0x200 to 0x2FF - The file table

Every file in the compound file has a single entry in the file table. Since a file can span multiple blocks it can have any number of allocation table entries. Each file table entry has the index of the first allocation table entry, this entry's "m_iNext" value can be used to build the allocation block chain.

Notice that the file table does not have a "next" value. This is because the file table is accessed via a FSFilterStream. All tables other than the allocation table use a FSFilterStream.

0x70123afc BlockHeader::m_iMagic - magic number
0x06 BlockHeader::m_iTotalItems - number of items in the file table

Each entry in the allocation table has 8 values. The first entry is shown here.
0x5 m_iID - The files ID
0x5 m_iAllocTblIndex - Fist allocation block entry
0x3 m_iNameID - ID of the files name. See the name table
0x1 m_iDirID - Parent directory
0xffffffff m_iPropID - Property file ID
0x0 m_iCheckSum - File's checksum (not used)
0x40 m_iFlags - Flags
0xbb m_iLength - File's length

0x300 to 0x3FF - The directory table

0x19283746 BlockHeader::m_iMagic - magic number
0x02 BlockHeader::m_iTotalItems - number of items in the dir table

Each entry in the dir table has 5 values. The first entry is shown here.
0x2 m_iID - This directory's ID
0x2 m_iNameID - ID of the directory's name
0x1 m_iParentID - Parent directory
0xffffffff m_iPropID - Directory's property file
0x1 m_iFlags - Flags

0x400 to 0x4FF - The names table

The name IDs refered to above (in the file table and directory table) reference strings stored in the names table.

0x64faec70 BlockHeader::m_iMagic - magic number
0x02 BlockHeader::m_iTotalItems - number of items in the names table

The names are stored as length prefixed strings. If you look at the dump you should be able to see the three names "file 1-2", "dir 1-1" and "dir 1"

0x500 to 0x5FF - The first file (the rtf text)

This is the first, and only file in the example compound file. The user of the compund file has complete contro of what is stored in a file. The compound file will not prepend or append any data to the file. By using a FSFilterStream the file will work like any other Stream class.
In this example rich text has been saved in the file.

The entire file

frhed ( was used to create all the hex dumps shown on this page.