1. 程式人生 > >【轉載】印表機驅動體系結構!

【轉載】印表機驅動體系結構!


3.1.1印表機圖形DLL

本部分提供以下主題: 

■3.1.1.1印表機圖形DLL介紹 

■3.1.1.2由印表機圖形DLL定義的函式 

■3.1.1.3印表機圖形DLL例項 

■3.1.1.4繪製一個列印作業 

■3.1.1.5支援裝置字型 

■3.1.1.6返回專用的印表機資訊 

■3.1.1.7選擇使用者模式或核心模式 

■3.1.1.8構建一個印表機圖形DLL 



3.1.1.1印表機圖形DLL介紹

印表機圖形DLL實現了在第一部分的第3章支援DDI中描述的Drv為前輟的DDI函式。 這些DLL具有以下列兩項責任: 

■幫助GDI繪製列印作業:一個印表機圖形DLL可以支援DDI繪製函式來處理那些必須以特定裝置的方式執行以及那些不能由GDI的繪製引擎完成的繪製操作
。 


■傳送繪製資料流到假離線:印表機圖形DLL通常以RAW資料型別(包括命令序列)產生一個輸出流,假離線可以通過列印監視器將它傳送到印表機硬體。 



一個印表機圖形DLL必需提供的、特定印表機型別的繪製幫助的總數量,依賴於硬體的繪製能力幷包括以下情形: 

■GDI繪製引擎用一個GDI管理的表面執行所有的繪製,圖形的DLL不提供任何的DDI繪製函式。 

■圖形DLL提供一些DDI繪製函式用一個GDI管理的表面與GDI繪製引擎一起工作。 由圖形DLL提供繪製DDI函式可以選擇性地回撥GDI繪製引擎的GDI支援的服務。 

■圖形DLL通過提供DDI繪製函式和一個裝置管理的表面來執行所有的繪製。 

例如,當微軟統一印表機驅動程式使用一個裝置管理的表面時,微軟統一印表機驅動程式(Unidrv:Microsoft Universal Printer Driver)使用一個GDI管理的表面並提供一些DDI繪製函式
。 


更多的關於在圖形驅動程式中提供繪製幫助的資訊,參考第一部分的第2章表面型別和第一部分的第3章支援DDI部分的內容。 

印表機圖形DLL在EMF假脫一個列印作業時不能呼叫,當EMF列印處理器回放EMF記錄時適當的圖形DLL呼叫。 

但要注意,印表機圖形DLL不能傳送繪製的列印作業到硬體,被繪製的資料流返回到假離線,假脫機發送該資料流到一個埠監視器,該埠監視器是一個使用者模式的介面到一個核心模式的本地並行埠或網路埠的微埠驅動程式 

對Windows 2000來說,可以設計一個印表機的圖形DLL以在核心模式執行,或者可以設計它在使用者模式執行,更多的資訊可以參考選擇使用者模式或核心模式部分的內容

下面的兩個圖表示當一個應用程式用GDI建立一個列印作業時發生的資料流,第一個圖表是一個使用者模式的印表機圖形DLL
。 




插入圖3-1 列印作業資料流,使用一個使用者模式的印表機圖形DLL 



第二個圖表是一個核心模式的印表機圖形DLL。 



插入圖3-2 列印作業資料流,使用一個核心模式的印表機圖形DLL 



注意,在圖表中,如果從GDI輸出的格式是EMF,印表機圖形DLL在EMF列印處理器回放EMF作業記錄前不接收作業,也要注意的是EMF列印處理器改變輸出格式到非EMF格式。 

上面兩個圖表示了一個完整的本地環境,如果印表機連線到一個伺服器,EMF記錄則通常客戶的GDI繪製引擎(GRE)拷貝來產生,然後假脫到一個本地檔案後送到伺服器,伺服器的假離線拷貝讀該檔案並將這些記錄送到伺服器的EMF列印處理器,並且伺服器端的GRE拷貝呼叫伺服器印表機圖形DLL。 



3.1.1.2由印表機圖形DLL定義的函式

如果所有的圖形驅動程式,印表機圖形DLL負責定義以下的DDI函式,由初始化驅動程式DrvEnableDriver函式的入口點開始,其餘的函式以字母順序列出。 

函式名稱 描述 

DrvEnableDriver 
允許驅動程式初始化它自身並返回支援DDI函式的指標 

DrvCompletePDEV 
對一個裝置例項提供具有GDI控制代碼的驅動程式 

DrvDisableDriver 
(可選)允許驅動程式在解除安裝之前執行清除工作 

DrvDisablePDEV 
允許驅動程式刪除裝置特定例項的資訊 

DrvDisableSurface 
允許驅動程式刪除繪製表面 

DrvEnablePDEV 
允許驅動程式提供具有物理裝置特徵的GDI並初始化裝置特定例項的資訊 

DrvEnableSurface 
允許驅動程式建立繪製表面 

DrvQueryDeviceSupport 
(可選)返回被請求的特定裝置的資訊 

DrvQuery 
(可選)返回被請求的特定驅動程式的資訊 




印表機圖形DLL也對定義以下特定列印的DDI函式負責,它們在繪製列印作業過程中的某一特定點時被呼叫。 

函式 何時呼叫 

DrvEndDoc 
當GDI已經結束髮送一個文件到驅動程式以備繪製時 

DrvNextBand 
(可選)當GDI已經結束繪製一個物理頁面的一個區帶(band),這樣驅動程式可以將該區傳送到印表機 

DrvQueryPerBandInfo 
(可選)在GDI開始為一個物理頁面繪製區帶之前,這樣驅動程式可以提供具有特定區帶資訊的GDI。 

DrvSendPage 
當GDI已經結束繪製物理頁面,這樣驅動程式可以將此頁面傳送到印表機。 

DrvStartBanding 
(可選)當GDI準備繪製時開始傳送一個物理頁面的區帶資訊到驅動程式 

DrvStartDoc 
當GDI準備繪製時開始傳送一個文件到驅動程式 

DrvStartPage 
當GDI準備繪製時開始傳送一個文件頁到驅動程式 




通常,一個印表機圖形DLL也定義任何必需的附加DDI函式以完成列印作業繪製。 被定義函式的數量及型別依賴於: 

■是否驅動程式支援繪製表面時使用被管理的GDI或被管理的裝置(或者兩者都支援),更多的資訊,可以參考第一部分的第2章表面型別。 

■一個繪製操作可以被GDI函式處理而不是由驅動程式自身執行的程度。 更多的資訊,參考第一部分第3章支援DDI部分的內容。 

所有的由印表機圖形DLL定義的函式都是被GDI核心模式圖形繪製引擎(GRE)來呼叫的。 

DrvEnableDriver和DrvQueryDriverInfo函式由圖形DLL匯出,所有其他支援DDI函式的地址放置於一個由DrvEnableDriver函式返回的表中。 



3.1.1.3印表機圖形DLL例項

plotter.dll的原始碼是印表機圖形DLL為微軟繪圖儀驅動程式提供的,與些DDK一起提供,其程式碼放置於包含DDK例項目錄的子目錄中。 



3.1.1.4繪製一個列印作業

列印作業或者是在它們建立時繪製,或者是被假脫成為EMF記錄繪製。 在後一種情況下,繪製發生在當EMF列印處理器(Winprint.dll)回放EMF記錄時。 繪製則由一系列對GDI的Win32繪製函式的呼叫構成,並以CreateDC為呼叫的開始。 

當一個應用程式呼叫GDI的CreateDC函式來建立印表機的裝置裝置環境,GDI檢檢視是否有合適的印表機圖形DLL被裝載,如果沒有,GDI裝載DLL並呼叫它的DrvEnableDriver函式,該函式不會被再次呼叫,除非驅動程式被重新裝載。 

接下來,GDI呼叫印表機圖形DLL的DrvEnablePDEV函式,這樣驅動程式可以建立一個裝置例項並返回裝置特徵。 GDI用返回的資訊以建立裝置例項的內部描述。 圖形DLL必須用這一控制代碼作為一個Eng為字首,由GDI繪製引擎(參考第一部分第2章GDI支援服務)提供的回撥的輸入。 

呼叫圖形DLL的DrvEnableSurface函式之後,驅動程式可以通過呼叫EngCreateBitmap為裝置例項建立一個繪製表面,或者,如果繪製表面是裝置管理的,則呼叫EngCreateDeviceSurface。 如果EngCreateBitmap不能提供一個足夠大的點陣圖來包含整個的物理頁面,並且如果驅動程式支援頁面分割槽帶的功能,EngMarkBandingSurface可以被呼叫以通知進行GDI分割槽帶的工作。 最後,EngAssociateSurface必須被呼叫以允許GDI將建立的表面與特定裝置例項協調,並允許GDI知道哪一個驅動程式提供的DDI繪製函式(如果任意)應當在繪製這一特殊表面時呼叫。 

從這一點來看,一個繪製表面已經建立並且繪製可以開始,對每一個繪製的文件來說,GDI在印表機圖形DLL中呼叫以下的函式: 

l DrvStartDoc 

For each physical page{ 

l DrvStartPage 

DrStartBanding 

For each banding surface{ 

DrvQueryPerbandInfo 

Rendering operations 

DrvNextBand 



DrvSendPage 



l DrvendDoc 

除DrvqueryPerBandInfo函式之外,這些函式都是為了允許印表機圖形DLL向印表機硬體傳送控制序列(通過呼叫EngWritePrinter),並執行初始化或完成處理一個文件、頁面或區帶等任何內部操作。 

印表機圖形DLL負責在適當的時間傳送繪製圖像(即,繪製表面的內容)到印表機(通過呼叫EngWritePrinter),如下: 

■對GDI管理或裝置管理的位圖表面:繪製表面是GDI提供的或驅動程式提供的點陣圖,印表機圖形DLL可以分出一些起繪製函式(參考第一部分第2章的表面協商部分),如果使用了頁面區帶,DrvNextBand函式應當傳送繪製表面內容。 如果不使用區帶,DrvSendPage函式應當傳送繪製表面內容。 

■對裝置管理的向量表面:繪製表面是在裝置裡,印表機圖形DLL分出的所有繪製函式(參考第一部分第2章的表面協商部分),並且這些函式在繪製操作過程中傳送影象資料到印表機,而頁面分帶區不能被使用。 

如果預料任意由印表機DLL提供的DDI函式可以潛在執行5秒以上,就應當包括至少每5秒一次呼叫EngCheckAbort至少每5秒一次的程式碼並看是否列印作業被中斷。 

在GDI呼叫DrvendDoc以指明一個文件已經繪製完成後,它呼叫DrvDisableSurface如果DrvEnableSurface呼叫EngCreateBitmap,則DrvdisableSurface必須呼叫EngDeletesurface。 

GDI在一個應用程式呼叫DrvDeleteDC時呼叫一個印表機圖形DLL的DrvDisablePDEV函式。 

如果一個應用程式在列印一個文件時呼叫GDI的ResetDC函式,GDI建立一個新的裝置裝置環境併為該新裝置裝置環境呼叫印表機圖形DLL的DrvEnablePDEV函式。 然後,GDI呼叫DrvResetPDEV函式,這樣圖形DLL可以用從舊的裝置環境獲得的資訊修改新的裝置環境。 接著,DrvDisableSurface及DrvDisablePDEV為舊的裝置環境而呼叫,對新的裝置環境,接下來被呼叫的函式就是DrvEnableSurface。 最後,GDI呼叫DrvStartDoc在一個新頁上進行繪製。 

GDI呼叫DrvDisableDriver優先於解除安裝印表機圖形DLL。 

如果印表機硬體支援GDI繪製函式不支援的繪製操作,則印表機圖形DLL可以提供一個DrvDrawEscape函式。 

如果需要支援通過GDI函式不能實現的繪製或非繪製的操作,則一個印表機圖形DLL需要提供一個DrvEscape函式。 例如,微軟的Postscript印表機驅動程式用escape來支援Postscript入口點,或者,一個應用程式也許需要獲得一個傳真機的電話號碼,DrvEscape函式也用於指出由DrvDrawEscape函式支援的操作。 



3.1.1.5支援裝置字型

如果一個印表機提供裝置字型,印表機圖形DLL必須定義一個DrvTextOut函式以產生文字輸出命令,圖形DLL必須也定義以下函式: 

DrvQueryAdvanceWidths 

DrvQueryFont 

DrvQueryFontData 

DrvQueryFontTree 

更多的關於支援裝置字型的資訊,參考第一部分第3章中的支援DDI字型及文字函式部分。 



3.1.1.6返回專用的印表機資訊

GDI有時請求印表機圖形DLL返回在列印作業之間的印表機專用的資訊,通過呼叫這些DrvQuery字首的DDI函式如DrvqueryAdvanceWidths(如果被圖形DLL定義)。 

什麼時候會發生這些的一個例子是在字處理應用程式中維持了一個所見即所得(WYSIWYG)螢幕顯示的可列印頁面。 為了準確地顯示文字中的線的間斷,字處理器必須對字元寬度及其他選定的印表機實現的字型的尺度進行基準線的合適性計算。 



3.1.1.7選擇使用者模式或核心模式

在4.0版以前的Windows NT中,GDI及所有的圖形驅動程式都是在使用者模式下執行,在4.0版中,這些元件被移到核心模式,這一改變提高了顯示裝置的效能,但對列印裝置的效能獲得並不顯著,不足以抵消繼承使用者模式失去的優點。 

因此,對Windows 2000,可以設計一個印表機圖形DLL以在核心模式下執行,或者可以設計在使用者模式下執行。 使用者模式下的印表機圖形DLL執行提供以下超過核心模式下執行的優點: 

■無限制的棧空間 

■存取Win32 API 

■更少的導致系統崩潰的潛在因素 

■使用者模式的糾錯器,更容易糾錯 

■更好的浮點計算能力,儘管DDI浮點函式不是必需的 

■呼叫任何定製的,廠商提供的使用者模式的但不是Windows 2000印表機驅動程式體系結構中描述的部分的DLL的能力。 



在使用者模式下使用圖形DDI 

一個使用者模式印表機圖形DLL並沒有限定於去呼叫GDI支援的服務(第一部分第2章)和其他以Eng為字首的圖形DDI回撥函式。 但是,有一些必須遵從的規則: 

■如同核心模式圖形DLL,使用者模式圖形DLL必須呼叫圖形DDI的版本函式以建立或修改繪製表面,這些回撥函式是GDI支援的服務,並且不允許呼叫這些繪製函式在Win32中的等效的函式。 

對使用者模式的DLL,呼叫這些繪製的回撥函式被使用者模式的GDI客戶端截聽,之後,客戶端會通知GDI的核心模式圖形繪製引擎(GRE)。 

■下面的以Eng為字首的DDI函式不能被使用者模式的DLL呼叫。 

EngCreatePath 

EngCreateClip 

EngDeleteClip 

EngGetTypeFontList 

EngMapModule 

EngDebugBreak 

所有其他以Eng為字首的函式對核心模式的印表機圖形DLL都是可用的,在使用者模式下也是也用的。 對那些與Win32完全等效的函式,如EngGetPrinter或EngGetPrinterDriver,則Win32等效的函式被呼叫。 沒有完全與Win32等效的函式,則在GDI客戶端來實現。 

■使用者模式的印表機圖形DLL可以繼續用DDI函式以實現對浮點的支援。 



將一個存在的印表機圖形DLL轉換到使用者模式 

如果以前開發過運行於核心模式的印表機圖形DLL,對Windows 2000來說,會有以下選擇: 

1.什麼也不做。 已經存在的核心模式的印表機圖形DLL將會繼續在核心模式下工作,微軟也許會在以後的作業系統發行版本中刪除對核心模式印表機圖形DLL的支援。 

2.轉換該DLL到使用者模式下執行。 為了執行,只需增加一個DrvQueryDriverInfo函式到DLL,然後遵從構建印表機圖形DLL的規則。 



在建立一個新的在使用者模式下的印表機圖形DLL 

當開發一個新的執行在使用者模式下的印表機圖形DLL時,可以繼續使用所有的被核心模式DLL使用的圖形DDI函式。 但是,也有下邊這些選擇: 

■對以Eng為字首有完全等效Win32的函式,可以呼叫Win32函式,這些函式由以下一些函式構成: 

EngAllocMem EngGetForm EngMulDiv 

EngAllocUserMem EngGetLastError EngSetLastError 

EngEnumForms EngGetPrinter EngSetPrinterData 

EngFreeMem EngGetPrinterData EngUnloadImage 

EngFreeUserMem EngGetPrinterDriver EngWritePrinter 

EngFindImageProAddress EngLoadImage 



■對以Eng為字首的那些與Win 32函式符合一些簡單功能的函式,可以呼叫Win32函式,這些函式由以下一些函式組成: 

EngAcquirSemaphore EngGetCurrentCodePage 

EngMultiByteToWideChar EngCreateSemaphore 

EngGetDriverName EngQueryLocalTime 

EngDeleteSemaphore EngGetPrinterDataFileName 

EngReleaseSemaphore EngFindResource 

EngLoadModule EngUnicodeToMultiByteN 

EngFreeModule EngMultiByteToUnicodeN 

EngWideCharToMultiByte 



■對那些建立或修改一個繪製服務的函式,新的驅動程式必須繼續呼叫GDI支援服務而不是它們等效的Win32函式。 

■不使用DDI函式來支援浮點,可以使用FLOAT資料型別。 





3.1.1.8構建一個印表機圖形DLL

當構建一個印表機圖形DLL時,必須清楚打算在使用者模式下執行和打算在核心模式下執行的DLL之間的以下差別: 

構建印表機圖形DLL的規則 

使用者模式圖形DLL 核心模式圖形DLL 

在source檔案中,設定TARGETTYPE=DYNLINK 
在source檔案中,設定TARGETTYPE=GDI_DRIVER 

處理器巨集USERMODE_DRVER必須在winddi.h包含之前在source檔案中被定義 
處理器巨集USERMODE_DRIVER不能被定義 

物件模組必須被與umpdddi.lib和gdi32.lib匯入庫連結在一起 
物件模組必須與win32k.lib匯入庫連結 

DrvQueryDriverInfo函式必須返回DRVQUERY_USERMODE 
DrvQueryDriverInfo函式必須給DRVQUERY_USERMODE返回FALSE(或二者選擇其一,該函式可以被省略) 




3.1.2印表機介面DLL

本部分提供以下主題: 

■3.1.2.1印表機介面DLL介紹 

■3.1.2.2由印表機介面DLL定義的函式 

■3.1.2.3印表機介面DLL例項 

■3.1.2.4為印表機建立原型表單頁面 



3.1.2.1印表機介面DLL介紹

印表機通常給使用者提供大量的可修改配置的選擇,這些選擇項可以在每一個被付印的文件中被改變。 如頁面、托架、字型選擇、影象精度、尺寸、色彩等等都必須可以通過使用者介面被存取,也可以被應用程式呼叫。 

一個印表機驅動程式的印表機介面DLL,它是執行在使用者模式下,負責匯出一個使用者的介面到印表機的配置選項。 提供這一介面包括為印表機建立原型表單頁面。 應用程式(如列印摺疊器)通過呼叫由列印假離線匯出的Win32函式顯示介面,並且,假離線返過來,又呼叫由印表機介面DLL定義的函式。 

為配置選項提供一個使用者介面不是印表機介面DLL的唯一責任,DLL同時也匯出假離線可以呼叫的函式以通知驅動程式列印相關的系統事件,如驅動程式安裝、升級或者新增印表機及印表機連線等。 



3.1.2.2由印表機介面DLL定義的函式

印表機介面DLL匯出函式列於下面表格中: 

函式 目的 

DllEntryPoint 
初始化DLL的入口點,通常呼叫DLLMain(在平臺的SDK文件中有描述) 

DrvConvertDevMode 
轉化專用的DEVMODE結構到另外一個版本 

DrvDeviceCapabilites 
返回請求的關於一個印表機能力的資訊 

DrvDevicePropertySheets 
呼叫CPSUI以產生描述印表機屬性的表單頁面屬性 

DrvDocumentEvent 
(可選)允許印表機介面DLL去處理與列印文件相關的一定的事件 

DrvDriverEvent 
(可選)允許印表機介面DLL對假離線來的已經發生的關於特定印表機事件的訊息通知作響應 

DrvDocumentPropertySheets 
呼叫CPSUI以產生描述列印文件屬性的表單頁面屬性 

DrvPrinterEvent 
允許印表機介面DLL對假離線來的已發生的關於特定印表機的事件的訊息通知作響應 

DrvQueryColorProfile 
(可選)允許印表機介面DLL指定一個ICC的profile以在色彩管理中使用 

DrvQueryJobAttributes 
(可選)允許印表機介面DLL指定諸如列印多個文件頁面在一個物理頁上(“N-up”列印)、打頁某一頁面的多個拷貝以及校對頁面等 

DrvQueryPrintEx 
決定一個列印作業是否能用印表機當前配置進行列印 

DrvUpgradePrinter 
(可選)當一個新版本的驅動程式增加到系統時,修改印表機的登錄檔設定 




3.1.2.3印表機介面DLL例項

plotui.dll的原始碼,即微軟繪圖儀驅動程式的印表機介面DLL與此DDK一起提供,其程式碼放置於包含DDK示例程式碼的目錄樹的子目錄中。 



3.1.2.4為印表機建立原型表單頁面

印表機介面DLL,與CPSUI連在一起,負責建立Windows 2000使用者從事的與印表機及列印文件相關的檢視及修改配置引數表單頁面的屬性。 每一個印表機介面的DLL必須提供一個DrvDevicePropertySheets函式以建立特定印表機頁面和一個DrvDocumentPropertySheets函式以建立特定文件的頁表。 

為了理解這些函式是怎樣被設計,閱讀描述CPSUI、顯示錶單頁面屬性包括應用程式之間的互動、列印假離線、印表機介面DLL以及CPSUI執行流等許多在印表機驅動程式中使用CPSUI一章中描述的內容是非常重要的。 



3.1.3印表機資料檔案

微軟提供的印表機驅動程式利用資料檔案來描述各個列印裝置,更多的資訊,可以參考以下幾章內容: 

■微軟統一印表機驅動程式:描述了.gpd檔案 

■微軟Postscript印表機驅動程式:描述了.ppd檔案 

■微軟繪圖儀印表機驅動程式:描述了.pcd檔案