轉載請標明出處:https://www.cnblogs.com/tangZH/p/11176995.html
更多精彩文章:http://77blogs.com/?p=283
CHM格式為CHM頭,CHM頭節,內容三部分組成。
總體格式圖:
初始化頭包含了CHM的相關信息。格式如下:
0000:char [4]'ITSF'
0004:DWORD 3(版本號)
0008:DWORD 文件頭總長度,包括標題節表和
以下數據。
000C:DWORD 1(未知)
0010:DWORD 時間戳。
被認為是一個大端的DWORD,它似乎包含
秒(MSB)和小數秒(第二個字節)。
第三個和第四個字節可能包含更多的小數
位。最后一個字節中的4個最低有效位是
不變。
0014:DWORD 語言代碼:英文 0X0409,簡體中文:0X0804
0018:GUID {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
0028:GUID {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
頭節記錄。它是2個條目,每個條目的長度為10個字節,具有以下格式:
0000:QWORD 頭節的偏移量
0008:QWORD 頭節的長度
這兩個頭節分別指向頭節0和頭節1,根據這兩個頭節的偏移量便可以讀到兩個頭節。
內容節偏移。在版本2文件中,此數據不存在,因為內容部分緊跟在目錄之后:
0000:QWORD 內容節的偏移量
頭節0。此部分包含文件的總大小,而不是其他內容。
0000:DWORD 0X01FE(未知)
0004:DWORD 0(未知)
0008:QWORD 文件大小
0010:DWORD 0(未知)
0014:DWORD 0(未知)
頭節1。.chm文件的核心部分:它包含的文件和信息的目錄。
目錄頭:
0000:char [4]'ITSP'
0004:DWORD 版本號1
0008:DWORD 目錄頭的長度
000C:DWORD 0X0a(未知)
0010:DWORD 0X1000目錄塊大小
0014:DWORD 快速引用塊密度,通常為2。
0018:DWORD 索引樹的深度
1:沒有索引,2:一層索引,以此類推。
001C:DWORD 根索引塊的塊號,如果沒有則為-1
(盡管至少有一個文件有0,盡管沒有
index chunk,可能是個bug。)
0020:DWORD 第一個PMGL(列表)塊的塊號
0024:DWORD 最后一個PMGL(列表)塊的塊號
0028:DWORD -1(未知)
002C:DWORD 目錄塊數(總計)
0030:DWORD Windows語言ID
0034:GUID {5D02926A-212E-11D0-9DF9-00A0C922E6EC}
0044:DWORD 0X54(這又是長度),同0X1000
0048:DWORD -1(未知)
004C:DWORD -1(未知)
0050:DWORD -1(未知)
目錄頭之后緊跟着目錄塊,有兩種目錄塊:列表塊和索引塊,如果只有一個列表快,那么將沒有索引塊。
列表塊:
0000:char [4]'PMGL'
0004:DWORD 結尾處的自由空間和/或quickref區域的長度目錄塊
0008:DWORD 始終為0。
000C:DWORD 讀取時上一個列表塊的塊號
順序目錄(如果這是第一個列表塊,則為-1)
0010:DWORD 讀取時下一個列表塊的塊號
順序目錄(如果這是最后一個列表塊,則為-1)
0014:目錄列表條目(到quickref區域)排序方式根據文件名; 排序不區分大小寫。
quickref區域是從塊的末尾向后寫入。對於文件中的每n個條目存在一個quickref條目,其中n被計算為1 +(1 << quickref density)。因此,對於密度= 2,n = 5。
其格式從后到前為:
Chunklen-0002:整個數據塊中的項數
Chunklen-0004:從0項到n項之間的偏移量
Chunklen-0006:從0項到2n項之間的偏移量
......
目錄列表條目的格式如下:
ENCINT:名字長度
UTF-8:編碼的名稱(UTF-8編碼)
ENCINT:內容部分
ENCINT:偏移量
ENCINT:長度
偏移量是從文件解壓縮之后的正文段開始計算的。長度也指解壓后的長度。
目錄中表示的文件有兩種:用戶數據和格式相關文件。與格式相關的文件具有以“::”開頭的名稱,用戶數據文件的名稱以“/”開頭。
索引塊:
0000:char [4]'PMGI'
0004:DWORD 目錄塊末尾的quickref / free(空余)區域的長度
0008:目錄索引項
PMGI中的quickref區域與PMGL中的相同,當索引塊的層次較高時,將不再存儲數據塊號而是存儲下一層的索引號。
目錄索引項的格式如下:
ENCINT:名字長度
UTF-8:名稱(UTF-8編碼)
ENCINT:以此名稱開始的列表塊的塊號
內容:
在版本3中,內容通常緊跟在文件頭之后,並且位於文件頭表之后的DWORD指示的位置。在版本2中,內容緊跟在文件頭之后。目錄中的所有內容部分0位置都與該點相關。其他內容部分存儲在內容部分0中。而且所有此文件夾中的正文部分的第0段都放在這個位置上。其他的正文段都在這個正文段里面。
名單列表文件
在內容部分0和目錄中存在名為“:: DataSpace / NameList”的文件。此文件包含所有內容部分的名稱。格式如下:
0000:WORD 文件長度,用文字表示 0002:WORD 文件中的條目數 每個條目: 0000:WORD 單詞中的名稱長度,不包括終止null 0002:WORD 。以0表示所有entry的結束。名稱的編碼類似於UFT-16。 段的名稱目前為止只有兩種,Uncompressed和MSCompressed,分別表示未壓縮文件和Microsoft LZX壓縮算法壓縮的文件。 xxxx:WORD 0
Section_data:
對於段落編號不為0的段落,還有另一個文件:DataSpace / Storage / <Section_Name> / Content,它存儲段落的壓縮信息。 因此,在解析非零段落時,需要兩個步驟。 第一步是獲取第,並獲取段落名稱。 第二步是使用段落名稱查找相應的段落。
其余與格式相關的文件: ::DataSpace/Storage/<SectionName>/ControlData
共0x20個字節,存儲關於壓縮的信息:
參考鏈接:
https://wenku.baidu.com/view/c2f81e21aaea998fcc220e22.html?pn=1