複合文件CFB的存儲結構及格式解析

OLE 2.0(CFB)

CFB(Microsoft Compound File Binary)複合文件二進制的文件格式實現,也稱OLE(Object Linking and Embedding)即對象鏈接和嵌入或COM(Component Object Model)組件對象模型結構化存儲複合文件實現二進制文件格式,這樣的格式簡稱Compound File。簡單的說,OLE 結構化存儲的標準Windows COM 實現稱爲CF 複合文件。

傳統文件系統難以將多種對象放入一個文檔文件中,CF 提供了一個在單個文件中實現一個簡單文件系統的解決方案。結構化存儲定義瞭如何將一個文件當作是存儲對象和流對象兩種類型對象的分層集合。類似於文件系統,存儲對象對應目錄,而流對象對應文件。

圖片

  • storage object,存儲對象:類似於文件系統目錄,存儲對象可以包含其他存儲對象和流對象,並維護其下的子對象的位置、大小等信息。
  • stream object,流對象:類似於文件系統文件,流對象包含連續順序存儲的用戶數據。存儲對象可以包含一個被叫做CLSID的 object class GUID,可以用來識別一個application 去讀寫存儲對象下的流對象。
  • application,應用:參與原子事務的開始、傳輸和完成。
    • 與事務管理器通信,開始和完成事務。
    • 與事務管理器通信,將事務編排至到其他應用程序,或將事務從其他應用程序編排。
    • 與資源管理器通信,提交資源工作請求。

數據結構

一個Compound File 分爲多個長度相同的扇區(sector),扇區是磁盤的最小尋址單位,一個扇區 512字節。一部分扇區 元素可以組成一個鏈表,扇區號用於索引。如下,#0、#2、#4 構成一個鏈表。一個扇區鏈構成一個流,一個 扇區中只能存放一種類型的數據。

最小的複合文件CF 至少包含三個扇區:Header(512 bytes),一個FAT扇區(512 bytes),以及一個directory 扇區(512 bytes)。

圖片

具體的各扇區類型如下,

扇區類型 單個元素長度 大小 用途
Header 非固定 512 字節(實際有效76 字節,剩餘436 字節用於DIFAT) 包含這個複合文件的初始元數據,由offset 0 處開始
DIFAT 4字節(共128 個元素) 4109 + 419 用於FAT 尋址
FAT 4字節(共128 個元素) 4 * 128 = 512 字節 OLE 中的主要Allocator,用於mini FAT、directory、mini stream 等扇區尋址
Mini FAT 4字節(共128 個元素) 512 字節 mini stream 用戶數據的Allocator
Directory 128字節 128 * 4 = 512 字節 包含storage 對象或stream 對象的元數據
用戶自定義數據(即mini stream) 非固定 stream 對象的用戶自定義數據
Rang Lock 非固定 用於管理對複合文件的併發訪問的單個扇區。此扇區 必須包含文件偏移量 0x7FFFFFFF。
Unallocated
Free
非固定 OLE 的未分配空間

通常,每個扇區 512 字節

圖片

對於各扇區 值的含義,

圖片

圖片

一下是offvis 工具解析出的.doc 文件的ole header:

圖片

其中,ByteOrder 指定了複合文件中所有的整型區都是以小端little-endian 存儲,包含UTF16編碼的signature,不過用戶自定義數據流不受該限制。

最後剩餘4 * 109 = 436 bytes 空間用於存儲DIFAT 扇區地址。

DIFAT --> FAT-->|-mini FAT

                |-directory 

                |-mini stream

DIFAT 扇區

Double-indirect file allocation table (DIFAT) 數組用於存儲FAT 扇區,用於FAT 尋址。每個數組元素也是一個4 字節的FAT 扇區號。

1個DIFAT 扇區分爲512 字節(CFB_3),前4*127 字節用於FAT 尋址,最後4字節用於尋址下個DIFAT 扇區。DIFAT 起始地址在Header 中保存。

圖片

FAT 扇區

簡而言之,FAT 用於分配扇區。

扇區 鏈表和扇區 分配主要由File Allocation Table(FAT) 來管理,如FAT[N] 包含扇區 #N下個扇區。每個數組元素是一個32 位的扇區 號。FAT 數組的扇區s

圖片

FAT 扇區 的詳細結構如下:

圖片

每個FAT 扇區的偏移地址爲:

offset = (sector_number + 1) x sector_size

所以#0 FAT 扇區 的offset 不是0,而是sector_size。

Mini FAT 扇區

mini stream:爲了解決扇區空間浪費的問題,將內部stream object 的用戶定義數據部分均分爲多個mini stream。

與FAT 數組類似,只是mini FAT 數組存的是mini stream 的mini 扇區號,而不是Compound file 的扇區號。mini 扇區的地址存儲在FAT 標準鏈中,而此mini 扇區鏈的起始地址存在Header 中(first mini 扇區 num)

圖片

Directory entry 扇區

directory entry(目錄項)用於維護storage 對象和stream 對象的元數據。directory entry 數組包含多個目錄項,該數組存儲在一個目錄扇區中。

一個storage 對象或一個stream 對象對應一個目錄項,第一個目錄項對應root storage 對象。Directory 扇區 維護的數組空間由FAT分配。directory entry 固定128 字節。

圖片

starting sector location:stream 對象的首扇區地址。

* stream object:first 扇區 地址。
* root storage object:mini stream 的first 扇區 地址。
* storage object:全0 填充。

stream size:stream 對象中用戶自定義數據大小。

* stream object:用戶自定義數據大小。
* root storage object:mini stream 的大小。
* storage object:全0 填充。

Directory Entry Name (64 bytes): 此字段必須包含以UTF-16編碼的storage 或stream 名的Unicode字符串,且名稱必須以UTF-16終止空字符結束。

Directory Entry Name Length (2 bytes): directory entry name 的unicode 字符串長度,限制最大不超過64,單位字節。

Object type:如下

Type Value
Unknown or unallocated 0x00
Storage Object 0x01
Stream Object 0x02
Root Storage Object 0x05

Left Sibling ID (4 bytes): 左兄弟stream id

Right Sibling ID (4 bytes): 右兄弟stream id

Child ID (4 bytes): 子對象stream id

Root Directory entry

作爲第一個directory entry,對應root storage object,它是所有對象的root,它存儲了mini stream 的大小和第一個mini 扇區。

其他 Directory entry

對應普通storage object 、stream object,或者未分配對象。

cuteoff size:在mini stream 中存在的文件的截止大小(通常爲4,096字節)。

紅黑樹

控制層次結構的一層中的每一組兄弟對象(存儲對象下的所有子對象)都表示爲紅黑樹。這一組兄弟對象的父對象有一個指向樹頂的指針。紅黑樹是一種特殊的二叉搜索樹,其中每個節點都有一個紅色或黑色的顏色屬性。紅黑樹允許在存儲對象下的子對象列表中進行高效搜索。紅黑樹上的約束允許二叉樹大致平衡,因此插入、刪除和搜索操作是高效的。

用戶自定義數據扇區

FAT 或mini FAT 中 user-defined data 扇區s 構成一條鏈,每條鏈有一個單獨的directory entry 關聯,並維護其stream 對象的元數據,如大小、名字等。

Range Lock 扇區

位於文件的 0x7FFFFF00-0x7FFFFFFF 位置,用於支持併發、事務等CFB特性。Range lock 扇區 不允許存儲用戶自定義數據。Header、FAT、DIFAT、mini FAT、directory 鏈不允許存儲range lock 扇區 的地址。

複合文檔CF的大小限制

因爲兼容性原因,CFB-3 (512 字節的扇區)的複合文檔的大小不允許超過2GB。

常規最大sector 地址 MAXREGSECT = 0xFFFFFFFA,但是range lock 的起始地址是0x7FFFFF00,所以一個CFB_3 複合文件一般最大2GB。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章