1. 程式人生 > >C#將.spl剝離成.emf文件格式

C#將.spl剝離成.emf文件格式

.com 解析 交換 parse xxx 參考 sdk 打印機 作業

本文轉載自 星戰紫輝 http://www.cppblog.com/rawdata/archive/2009/02/23/74653.html

但C#代碼實現為本人原創。https://github.com/SnailDev/SnailDev.EmfParser 歡迎star或fork

關鍵字: 打印 SPL EMF 文件格式

Windows的假脫機打印會在Windows\System32\spool\PRINERS目錄下生成.spl和.shd文件,其中的打印內容存貯在.spl文件中,但是.spl文件格式似乎未公開,那麽如何才能將未知的.spl文件剝離成.emf文件呢?

首先,讓我們了解一下Windows打印機制,這是微軟的官網的一副打印流程圖片:

技術分享

其中ISV是應用軟件接口,IHV是硬件接口,左邊是XP的打印模型,右邊是Vista最新的XPS打印模型,但兩者可以互相轉換,具有良好的兼容性。不過,這裏暫時只關心XP系統的打印過程。

網絡打印過程圖:

技術分享

但是這些圖似乎還不夠詳細,那麽請看下面一副:(摘錄於論文:《基於關鍵字匹配的打印數據截獲系統》):

技術分享

基本的思路是: 打印過程發生時,GDI模塊和打印驅動(由打印機廠商提供)進行基本的數據交換,在假脫機設置環境下,生成打印機命令文件:.spl或.emf文件,作為一個打印池的作業,然後Windows後臺打印線程處理打印作業,將數據文件送至打印機打印,打印完刪除該打印文件。
好,現在回到正題:.spl文件該如何剝離成.emf呢?看一個例子:
在WinHex中打開一個.spl文件:
技術分享

參考: http://www.undocprint.org/formats/winspool/spl 中一些打印結構的定義。
首先,.spl文件都是以0x00010000簽名開頭,然後一個DWORD 是emf相關區的文件偏移,第3個DWORD是文檔描述字符串(UNICODE)的文件偏移,第4個DWORD 描述的是端口說明字符串(UNICODE)。大致結構如下:
技術分享

文件尾就是這個樣子:
技術分享

當定位到0x50的文件位置,讀取2個DWORD數據之後,就是.emf文件開始了。.emf文件格式是公開的,而且非常簡單,是一系列EMR_XXX開口結構的緊密排列,通常以EMR_HEADER(0x01)開頭,以EMR_EOF(0x0E)結尾。其實我們根本沒有必要去解析.emf文件格式,Windows SDK有專門顯示.emf文件的API,3個函數就搞定:
HENHMETAFILE hEMF = GetEnhMetaFile("EMF_DumpOK.emf");
PlayEnhMetaFile (dc.m_hDC, hEMF, &rc) ;
DeleteEnhMetaFile (hEMF) ;
然後.spl文件還有一些東西,現在還沒有解析出來,但是.emf文件已經剝離出來了,後面的可以先不理它。

代碼見本人github倉庫 https://github.com/SnailDev/SnailDev.EmfParser

C#將.spl剝離成.emf文件格式