在 Windows XP 時代,圖片或影音資料夾中常見一個隱藏檔案 Thumbs.db,這是系統用來快取縮略圖的資料庫。有了它,資源管理員開啟大量圖片資料夾時不需即時產生縮略圖,顯示速度大幅提升。若能在自訂圖片管理程式中復用這些快取資料,便能無縫整合系統資源管理器的縮略圖功能。然而,Thumbs.db 的檔案結構與存取 API 並未公開,經研究發現其採用結構化儲存格式,這在 COM 時代廣泛使用,但在 .NET 中微軟未提供原生支援。
結構化儲存本質上是一個儲存在單一檔案中的檔案系統,包含「資料夾」與「檔案」的階層結構。類似 WinRAR 封裝多檔案的邏輯,它允許在不移動大量資料的情況下修改內容。以 Word 文件為例,若採用循序儲存,插入第一頁內容需移動後續所有頁面;若視為小型檔案系統,每頁為資料夾、段落為檔案,修改即變得靈活高效。

在 COM 中,IStorage 對應「資料夾」,IStream 對應「檔案」。IStorage 提供建立/開啟串流、建立/開啟儲存體、列舉元素、複製、移動、提交等方法;IStream 則提供讀寫、定位、鎖定、複製等操作,用法類似 .NET 的 System.IO.Stream。一般結構化儲存的資料夾中會有一個 IStream 保存目錄資訊。
Thumbs.db 中包含一個名為 Catalog 的 IStream,儲存所有快取縮略圖的檔名列表,分為兩段:
由於缺乏官方文件,需自行定義對應結構,並注意記憶體配置順序:
[StructLayout(LayoutKind.Sequential)]
public struct CatalogHeader
{
public short Reserved1;
public short Reserved2;
public int ThumbCount;
public int ThumbWidth;
public int ThumbHeight;
}
[StructLayout(LayoutKind.Sequential)]
public struct CatalogItem
{
public int Reserved1;
private int m_ItemId;
public int ItemId { get { return m_ItemId; } set { m_ItemId = value; BuildItemIdString(m_ItemId); } }
public DateTime Modified;
public string FileName;
public short Reserved2;
public string ItemIdString { get; private set; }
private void BuildItemIdString(int itemId)
{
var temp = itemId.ToString();
var buffer = new char[temp.Length];
for (int i = 0; i < temp.Length; ++i) buffer[i] = temp[temp.Length - i - 1];
ItemIdString = new string(buffer);
}
}
特別注意:Thumbs.db 內部資料採用倒序儲存(字串反轉、整數位元組反序),這增加了解析難度。
StgOpenStorage 開啟檔案取得 IStorage 介面。Catalog 串流讀取目錄結構。CatalogHeader 與 CatalogItem 陣列。ItemIdString 開啟對應的縮略圖 IStream。IStream::Read 讀取影像資料(略過前 12 位元組表頭)。.NET 僅內建 IStream 定義,IStorage 需自行定義或參考 pinvoke.net 現成定義。