复合文档XLS---Excel表格文件实例分析
头中指明用于存放目录流的个sector为sector 10。目录总是存放于sector中,而不是short-sector中。故从SAT构建SID链为[10, 11, –2]。sector 10的偏移量为00001600H = 5632, sector 11的偏移量为00001800H = 6144。此例中sector的大小为512字节,因此每个sector包含4个目录入口(一个目录入口128字节),故此目录共包含8个入口。
<1>根仓库入口(Root Storage Entry)
个目录入口总是根目录入口,假定其内容如下:
00001600H 52 00 6F 00 6F 00 74 00 20 00 45 00 6E 00 74 00
00001610H 72 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00
00001620H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00001630H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
00001650H 10 08 02 00 00 00 00 00 C0 00 00 00 00 00 00 46
00001660H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00001670H 00 00 00 00 03 00 00 00 80 0D 00 00 00 00 00 00
1)前64个字节是此入口名字的字符数组(为16位的字符, 以个00结束),
可看出此入口的名字是“Root Entry”。
00001600H 52 00 6F 00 6F 00 74 00 20 00 45 00 6E 00 74 00
00001610H 72 00 79 00 00 00 00 00 00 00 00 00 00 00 00 00
00001620H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00001630H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2)接着2个字节表示用于存放上述字符数组的有效区域的大小,这里是22字节,只有10个有效字符。
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
3)接着1个字节表示入口类型,根仓库入口故为05H。
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
4)接着1个字节表示入口节点颜色,这里为红色,打破了根仓库入口为黑的规定。
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
5)接着4个字节表示其左节点的DID,再接着4个字节表示右节点的DID。对根仓库入口来说都是-1。
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
6)接着4个字节表示根仓库入口的成员构建的红黑树的根节点的DID,此例为1。
00001640H 16 00 05 00 FF FF FF FF FF FF FF FF 01 00 00 00
7)接着16个字节表示唯一标识符,说明这是一个仓库,其后4字节表示用户标识,再接着是两个时间标记,各8字节,表明此仓库的创建时间和后修改时间。这些数据都可忽略。
00001650H 10 08 02 00 00 00 00 00 C0 00 00 00 00 00 00 46
00001660H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00001670H 00 00 00 00 03 00 00 00 80 0D 00 00 00 00 00 00
8)接着4个字节表示短流存放流的个sector的SID,其后4字节表示短流存放流的大小。此例中个sector为sector 3,其大小为00000D80H = 3456字节。
00001670H 00 00 00 00 03 00 00 00 80 0D 00 00 00 00 00 00
9)后4个字节无有效数据,可忽略。
00001670H 00 00 00 00 03 00 00 00 80 0D 00 00 00 00 00 00
<1>第二个目录入口
第二个目录入口(DID 1)假定其内容如下:
00001680H 57 00 6F 00 72 00 6B 00 62 00 6F 00 6F 00 6B 00
00001690H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000016A0H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000016B0H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000016C0H 12 00 02 00 02 00 00 00 04 00 00 00 FF FF FF FF
000016D0H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000016E0H 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000016F0H 00 00 00 00 00 00 00 00 51 0B 00 00 00 00 00 00
用颜色标记的为重要数据。入口的名字是“Workbook”,它表示一个流。其左节点的DID是2,右节点的DID是4。其个sector的SID是0,其大小是00000B51H = 2897字节,小于4096字节,故其存放于短流存放流中。
<3>剩下的目录入口
从根仓库入口的个成员的DID(此为1)可以找到根仓库的所有成员。入口1有2个子节点,DID 2 和 DID 4,DID 2又有一个子节点DID 3,DID 3和DID 4都没有子节点了。因此根仓库包含DID 1、2、3、4这4个成员。
<4>流的SID链
短流存放流是存储在sector中的,小于4096字节的用户流(为短流)存储在短流存放流中,并使用SSAT构建SID链。
下表给出所有流的情况:
DID 流名 配置表 SID 链
0 Root Entry (短流存放流) SAT [3, 4, 5, 6, 7, 8, 9, –2]
1 Workbook SSAT [0, 1, 2, 3, 4, …, 43, 44, 45, –2]
2 <01H>CompObj SSAT [46, 47, –2]
3 <01H>Ole SSAT [48, –2]
4 <05H>SummaryInformation SSAT [49, 50, 51, 52, 53, –2]
<5>流的读取
短流存放流读取其SID链中的所有sector,此例中将按顺序读取sector 3,4,5,6,7,8,9,故此流的大小为512×7=3584字节。但是只有前3456字节有效(根仓库入口中指定的)。这3456字节被分成大小为64字节的short-sector,一共54个。
现在我们来读取流“<01H>CompObj”,其SID链为[46, 47, –2],此流是一个短流。其数据存放在short-sector 46和short-sector 47中。short-sector 46在短流存放流中的偏移量为2944字节,short-sector 47的偏移量为3008字节。