复合二进制文档

复合二进制文档（CFBF），简称复合文档，英文全名 Composite Document File V2 Document，是微软开发、用于实现COM结构化存储的文件格式，用于把多个对象内容存放在同一个硬盘文件。

Microsoft已经开放了这个文件格式。广泛用于Microsoft Word与Microsoft Access。也是Advanced Authoring Format的基础。

## 文件结构

CFBF文件头部是512字节，随后跟着是保存数据的扇区。扇区的长度在文件头部指定，通常是512字节或4096字节。

CFBF的扇区类型:

- FAT扇区
- MiniFAT扇区：用于Mini-Stream
- Double-Indirect FAT （DIFAT）扇区 - 包含FAT扇区索引的链表数据
- Directory扇区
- Stream扇区 - 包含数据内容
- Range Lock扇区 - 包含大文件的上锁的字节范围

### CFBF文件头

CFBF头是该文件的最前的512字节。对应于C语言数据结构为：

```c
 typedef unsigned long ULONG;    // 4 Bytes
 typedef unsigned short USHORT;  // 2 Bytes
 typedef short OFFSET;           // 2 Bytes
 typedef ULONG SECT;             // 4 Bytes
 typedef ULONG FSINDEX;          // 4 Bytes
 typedef USHORT FSOFFSET;        // 2 Bytes
 typedef USHORT WCHAR;           // 2 Bytes
 typedef ULONG DFSIGNATURE;      // 4 Bytes
 typedef unsigned char BYTE;     // 1 Byte
 typedef unsigned short WORD;    // 2 Bytes
 typedef unsigned long DWORD;    // 4 Bytes
 typedef ULONG SID;              // 4 Bytes
 typedef GUID CLSID;             // 16 Bytes

 struct StructuredStorageHeader { // [offset from start (bytes), length (bytes)]
     BYTE _abSig[8];             // [00H,08] {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1,
                                 // 0x1a, 0xe1} for current version
     CLSID _clsid;               // [08H,16] reserved must be zero (WriteClassStg/
                                 // GetClassFile uses root directory class id)
     USHORT _uMinorVersion;      // [18H,02] minor version of the format: 33 is
                                 // written by reference implementation
     USHORT _uDllVersion;        // [1AH,02] major version of the dll/format: 3 for
                                 // 512-byte sectors, 4 for 4 KB sectors
     USHORT _uByteOrder;         // [1CH,02] 0xFFFE: indicates Intel byte-ordering
     USHORT _uSectorShift;       // [1EH,02] size of sectors in power-of-two;
                                 // typically 9 indicating 512-byte sectors
     USHORT _uMiniSectorShift;   // [20H,02] size of mini-sectors in power-of-two;
                                 // typically 6 indicating 64-byte mini-sectors
     USHORT _usReserved;         // [22H,02] reserved, must be zero
     ULONG _ulReserved1;         // [24H,04] reserved, must be zero
     FSINDEX _csectDir;          // [28H,04] must be zero for 512-byte sectors,
                                 // number of SECTs in directory chain for 4 KB
                                 // sectors
     FSINDEX _csectFat;          // [2CH,04] number of SECTs in the FAT chain
     SECT _sectDirStart;         // [30H,04] first SECT in the directory chain
     DFSIGNATURE _signature;     // [34H,04] signature used for transactions; must
                                 // be zero. The reference implementation
                                 // does not support transactions
     ULONG _ulMiniSectorCutoff;  // [38H,04] maximum size for a mini stream;
                                 // typically 4096 bytes
     SECT _sectMiniFatStart;     // [3CH,04] first SECT in the MiniFAT chain
     FSINDEX _csectMiniFat;      // [40H,04] number of SECTs in the MiniFAT chain
     SECT _sectDifStart;         // [44H,04] first SECT in the DIFAT chain
     FSINDEX _csectDif;          // [48H,04] number of SECTs in the DIFAT chain
     SECT _sectFat[109];         // [4CH,436] the SECTs of first 109 FAT sectors
 };
```

### FAT扇区

每个FAT条目长度4字节，包含下个FAT链表条目的扇区号，或下述特定值：

- FREESECT (0xFFFFFFFF) - 未用扇区
- ENDOFCHAIN (0xFFFFFFFE) - FAT链表最后一个扇区
- FATSECT (0xFFFFFFFD) - 用于FAT数据存储
- DIFSECT (0xFFFFFFFC) - 用于DIFAT数据存储

### 词汇表

- FAT - 文件分配表，也称 SAT - 扇区分配表
- DIFAT - Double-Indirect File Allocation Table
- FAT Chain - 一群FAT条目指出分配给一个流的那些扇区
- Stream - 一个数据对象的内容
- Sector - 扇区，占据512或4096个字节