An .msg file is a Compound File Binary file, a small file system inside
one file, described by Microsoft in
[MS-CFB]
(the release of 26 October 2026 was read on 2026-11-12). This page gives what a reader needs to
find the storages and streams; what they hold is on
storages and properties. Numbers are
little-endian.
Header
The first 512 bytes. In version 4 files the rest of the first 4,096-byte sector is zeros.
| Offset | Size | Field |
|---|---|---|
0 | 8 | Signature D0 CF 11 E0 A1 B1 1A E1. |
8 | 16 | CLSID, zeros. |
24 | 2 | Minor version, 003E. |
26 | 2 | Major version: 3 (512-byte sectors) or 4 (4,096-byte sectors). |
28 | 2 | Byte order mark, FFFE. |
30 | 2 | Sector shift: 9 for version 3, 12 for version 4. |
32 | 2 | Mini sector shift, 6 (64-byte mini sectors). |
34 | 6 | Reserved, zero. |
40 | 4 | Number of directory sectors (0 in version 3). |
44 | 4 | Number of FAT sectors. |
48 | 4 | First directory sector. |
52 | 4 | Transaction signature: a save counter if the writer supports transactions, otherwise 0. |
56 | 4 | Mini stream cut-off, 4,096: streams smaller than this live in the mini stream. |
60 | 4 | First mini FAT sector. |
64 | 4 | Number of mini FAT sectors. |
68 | 4 | First DIFAT sector. |
72 | 4 | Number of DIFAT sectors. |
76 | 436 | The first 109 DIFAT entries: the sector numbers of the FAT sectors. |
Sector n starts at byte (n + 1) × sector size.
Allocation tables
- The FAT is an array of 4-byte entries, one per sector, giving the next sector of the chain.
- The DIFAT lists the FAT sectors: 109 in the header, then chained DIFAT sectors, each holding entries and, in its last 4 bytes, the next DIFAT sector.
- The mini FAT does the same for 64-byte mini sectors inside the mini stream, which is the root entry’s stream.
| Value | Name | Meaning |
|---|---|---|
00000000–FFFFFFF9 | REGSECT | Next sector in the chain. |
FFFFFFFA | MAXREGSECT | Largest sector number. |
FFFFFFFB | – | Reserved. |
FFFFFFFC | DIFSECT | The sector is a DIFAT sector. |
FFFFFFFD | FATSECT | The sector is a FAT sector. |
FFFFFFFE | ENDOFCHAIN | Last sector of a chain. |
FFFFFFFF | FREESECT | Unused. |
Directory entries
The directory is a stream of 128-byte entries. Entry 0 is the root storage. The children of each storage form a red-black tree.
| Offset | Size | Field |
|---|---|---|
0 | 64 | Name, UTF-16 with a terminating zero; at most 31 characters, without /, \, : or !. |
64 | 2 | Name length in bytes, including the zero. |
66 | 1 | Object type: 0 unused, 1 storage, 2 stream, 5 root storage. |
67 | 1 | Colour: 0 red, 1 black. |
68 | 4 | Left sibling ID (FFFFFFFF none). |
72 | 4 | Right sibling ID. |
76 | 4 | Child ID: root of this storage’s tree. |
80 | 16 | CLSID. |
96 | 4 | State bits. |
100 | 8 | Creation time, FILETIME. |
108 | 8 | Modification time, FILETIME. |
116 | 4 | Starting sector (in the mini stream if the size is below the cut-off; for the root, the mini stream’s first sector). |
120 | 8 | Stream size; for the root, the mini stream’s size. In version 3 files it is at most 2 GB; some old writers left the high 4 bytes uninitialised, so the specification recommends ignoring them. |
Siblings are ordered by name length first, then by upper-cased name.