复合文档二进制格式(compound File binary Format:CFBF)基本上以扇区(sector)为单位,sector大小由文件头中的信息决定,文件头是固定大小为512的扇区:
CFBF本身的扇区类型分为以下几种:
1. CFBF本身定义好的数据结构,如Header,Directory Entry。
2. 扇区的映射表,称为FAT。以链表的形式记录了与扇区相连的扇区。
3. 扇区映射表的索引,包括Header._sectFat[109];这个实例中没有这种类型的扇区,只有当扇区映射表的数量超过了109时才会有。
4. 目录结构表,其SECT索引放在FAT中,由Header._sectDirStart决定起始的SECT。
5. 数据本身,有两种类型:一种为正常的Stream,其SECT索引放在FAT中,由SID#._sectStart决定起始的索引,另外一种为MiniStream,其SECT索引放在MiniFAT中,由SID#0._sectStart决定起始的索引。
SECT #-1(header)
文件位置 | 数据长度 | 数据内容 | 对应的变量 | 含义 | 说明 |
0x00 | 8 | DOCF 11E0 A1B1 1AE1 | _abSig | CFBF格式的标志 | |
0x08 | 16 | 0000 0000 0000 0000 0000 0000 0000 0000 | _clid | ||
0x18 | 2 | 0x3E | _uMinorVersion; | minor version of the format: 33 is written by reference implementation | |
0x1A | 2 | 3 | _uDllVersion; | 扇区长度为512-byte. | major version of the dll/format: 3 for 512-byte sectors, 4 for 4 KB sectors |
0x1C | 2 | 0xFFFE | _uByteOrder; | 0xFFFE: indicates Intel byte-ordering | |
0x1E | 2 | 9 | _uSectorShift; | 512-byte/sector | size of sectors in power-of-two; typically 9 indicating 512-byte sectors |
0x20 | 2 | 6 | _uMiniSectorShift; | 64-byte/mini-sector | size of mini-sectors in power-of-two; typically 6 indicating 64-byte mini-sectors |
0x22 | 2 | 0 | _usReserved; | reserved, must be zero | |
0x24 | 4 | 0 | _ulReserved1; | reserved, must be zero | |
0x28 | 4 | 0 | _csectDir; | not used for 512-byte sectors | must be zero for 512-byte sectors, number of SECTs in directory chain for 4 KB sectors |
0x2C | 4 | 1 | _csectFat; | 当前文件包含了一个Fat扇区 | number of SECTs in the FAT chain |
0x30 | 4 | 1 | _sectDirStart | SECT #1 是第一个文件夹扇区 | first SECT in the directory chain |
0x34 | 4 | 0 | _signature; | not used, transactions not supported | signature used for transactions; must be zero. The reference implementation does not support transactions |
0x38 | 4 | 0x00001000 | _ulMiniSectorCutoff | 4096 bytes | maximum size for a mini stream; typically 4096 bytes |
0x3C | 4 | 0x00000002 | _sectMiniFatStart | SECT#2 is first MiniFAT sector | first SECT in the MiniFAT chain |
0x40 | 4 | 0x00000001 | _csectMiniFat | 1 MiniFAT sector in this file | number of SECTs in the MiniFAT chain |
0x44 | 4 | 0xFFFFFFFE | _sectDifStart | no DIFAT, file is < 7Mb | first SECT in the DIFAT chain |
0x48 | 4 | 0 | _csectDIF | no DIFAT sectors in this file | number of SECTs in the DIFAT chain |
0x4C | 4 | 00000000 | _sectFat[0] | SECT#0 is the first FAT sector | the SECTs of first 1 FAT sectors |
0x50 | 432 | FFFFFFFF ... (continues with FFFFFFFF) | _sectFat[1..108] | free FAT sectors | FAT扇区的索引,说明哪些SECT是FAT扇区。 |
Sector #0:
文件位置 | 数据长度 | 数据内容 | 对应变量 | 含义 | 说明 |
0x200 | 4 | 0xFFFFFFFD | N/A |
_sectFat[0]指向SECT #0,也就是当前扇区.FAT扇区的标志。 |
0xFFFFFFFD说明这个扇区为SECTs的索引. 本身代表了FAT中的第0个SECT,也就是扇区本身。 |
0x204 | 4 | 0xFFFFFFFE | N/A | _sectDirStart指向SECT #1,表示后面已经没有SECT了。 | 这个位置代表了FAT中的第1个SECT。 |
0x208 | 4 | 0xFFFFFFFE | N/A | _sectMiniFatStart指向SECT #2,表示后面已经没有SECT了。 | 这个位置代表了FAT中的第2个SECT。 |
0x20C | 4 | 0x4 | N/A | 这个位置代表了FAT中的第3个SECT。 | |
0x210 | 496 | 0xFFFFFFFF | N/A | 空闲的SECT索引。 |
SECT #1:
_sectDirStart = 1, 说明这个扇区为目录区,一个目录的数据结构大小为128-byte,所以每个扇区可以包含4个目录。
Directory Entry用到的枚举类型如下:
typedef enum tagSTGTY {
STGTY_INVALID = 0, // unknown storage type
STGTY_STORAGE = 1, // element is a storage object
STGTY_STREAM = 2, // element is a stream object
STGTY_LOCKBYTES = 3, // element is an ILockBytes object
STGTY_PROPERTY = 4, // element is an IPropertyStorage object
STGTY_ROOT = 5 // element is a root storage
} STGTY;
typedef enum tagDECOLOR {
DE_RED = 0,
DE_BLACK = 1
} DECOLOR;
文件位置 | 数据长度 | 数据内容 | 对应变量 | 含义 | 说明 |
0x480 | 64 | L"Storage 1" | _ab[32] | 文件夹名称。 | Unicode格式的字符串,也是文件夹的名称,包含'/0',所以最长为31个字符。 |
0x4C0 | 2 | 0x14 | _cb | _ab[32]中实际用到的字节(byte)数,包含'/0'. | |
0x4C2 | 1 | 1 | _mse | STGTY_STORAGE,说明当前的节点为Storage类型 | 文件夹类型,如STGTY_STORAGE、STGTY_STREAM |
0x4C3 | 1 | 1 | _bflags | DE_BLACK | DECOLOR的枚举类型。 |
0x4C4 | 4 | 0xFFFFFFFF | _sidLeftSib | 没有左兄弟 | 当前Entry的左边的兄弟节点的SID。 |
0x4C8 | 4 | 0xFFFFFFFF | _sidRightSib | 没有右兄弟 | 当前Entry的右边的兄弟节点的SID。 |
0x4CC | 4 | 2 | _sidChild | SID为2的Entry为第一个子节点 | 当前节点的子节点的SID。仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效。 |
0x4D0 | 16 | 0000 0000 0000 0000 0000 0000 0000 0000 | _clsId | 唯一标识符,仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效. | |
0x4E0 | 4 | 0 | _dwUserFlags | 未定义 | 自定义标志位,仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效。 |
0x4E4 | 8 | 0000 0000 0000 0000 | _time[0] | 未设置 | 目录创建时间,仅当_mse=STGTY_STORAGE时有效。 |
0x4EC | 8 | 0000 0000 0000 0000 | _time[1] | 目录修改时间,仅当_mse=STGTY_STORAGE时有效。 | |
0x4F4 | 4 | 0 | _sectStart | STORAGE不包含Stream,只能包含Storage | Stream的起始扇区,仅当_mse=STGTY_STREAM时有效。 |
0x4F8 | 4 | 0 | _ulSizeLow | 数据的总长度。 | Stream的字节数,仅当_mse=STGTY_STREAM时有效。 |
0x4FC | 4 | 0 | _ulSizeHigh | 对512字节长度的扇区无效,高64位用来表示4k长度扇区的数据长度。 |
文件位置 | 数据长度 | 数据内容 | 对应变量 | 含义 | 说明 |
0x500 | 64 | L"Stream 1" | _ab[32] | 文件夹名称。 | Unicode格式的字符串,也是文件夹的名称,包含'/0',所以最长为31个字符。 |
0x540 | 2 | 0x12 | _cb | _ab[32]中实际用到的字节(byte)数,包含'/0'. | |
0x542 | 1 | 2 | _mse | STGTY_STREAM,说明当前的节点为Stream类型 | 文件夹类型,如STGTY_STORAGE、STGTY_STREAM |
0x543 | 1 | 1 | _bflags | DE_BLACK | DECOLOR的枚举类型。 |
0x544 | 4 | 0xFFFFFFFF | _sidLeftSib | 没有左兄弟 | 当前Entry的左边的兄弟节点的SID。 |
0x548 | 4 | 0xFFFFFFFF | _sidRightSib | 没有右兄弟 | 当前Entry的右边的兄弟节点的SID。 |
0x54C | 4 | 0 | _sidChild | Stream没有子节点 | 当前节点的子节点的SID。仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效。 |
0x550 | 16 | 0000 0000 0000 0000 0000 0000 0000 0000 | _clsId | 唯一标识符,仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效. | |
0x560 | 4 | 0 | _dwUserFlags | 未定义 | 自定义标志位,仅当_mse=STGTY_STORAGE or STGTY_ROOT时有效。 |
0x564 | 8 | 0000 0000 0000 0000 | _time[0] | 未设置 | 目录创建时间,仅当_mse=STGTY_STORAGE时有效。 |
0x56C | 8 | 0000 0000 0000 0000 | _time[1] | 目录修改时间,仅当_mse=STGTY_STORAGE时有效。 | |
0x574 | 4 | 0 | _sectStart | _ulSizeLow < _ulMiniSectorCutoff,所以Stream数据被放在MiniFAT中,从第0个MiniSector开始 | Stream的起始扇区,仅当_mse=STGTY_STREAM时有效。 |
0x578 | 4 | 0x220 | _ulSizeLow | 数据长度,小于Header._ulMiniSectorCutoff | Stream的字节数,仅当_mse=STGTY_STREAM时有效。 |
0x57C | 4 | 0 | _ulSizeHigh | 对512字节长度的扇区无效,高64位用来表示4k长度扇区的数据长度。 |
第三个Directory Entry为空。
SECT #2:
由Header._sectMiniFatStart = 2 我们知道当前SECT为MiniFAT。
文件位置 | 数据长度 | 数据内容 | 对应变量 | 含义 | 说明 |
0x600 | 4 | 0x00000001 | N/A | SID2._sectStart = 0,所以当前值为下一个MiniSector的索引 | 当前minisector的下一个索引,下同 |
0x604 | 4 | 0x00000002 | N/A | 下个MiniSector为MiniSECT #2,下同 | |
0x608 | 4 | 0x00000003 | N/A | 下个MiniSECT=3 | |
0x60C | 4 | 0x00000005 | N/A | 下个MiniSECT为5 | |
0x610 | 4 | 0x00000006 | N/A | ||
0x614 | 4 | 0x00000007 | N/A | 下个MiniSECT=7 | |
0x618 | 4 | 0x00000008 | N/A | ||
0x61C | 4 | 0xFFFFFFFFE | N/A | 数据结束 | |
...... | 0xFFFFFFFFF | N/A | 空闲的索引 | ||
SECT #3
SID0._sectStart指明了当前SECT为MiniStream sector。
000800: 4461 7461 2066 6F72 2073 7472 6561 6D20 Data for stream
000810: 3144 6174 6120 666F 7220 7374 7265 616D 1Data for stream
000820: 2031 4461 7461 2066 6F72 2073 7472 6561 1Data for strea
. . .
000A00: 7461 2066 6F72 2073 7472 6561 6D20 3144 ta for stream 1D
000A10: 6174 6120 666F 7220 7374 7265 616D 2031 ata for stream 1
结束