建立匯出驅動程式

匯出驅動程式是核心模式 DLL,可由各種其他硬體特定或裝置堆疊特定元件載入,但沒有完整核心模式驅動程式的某些特性。 具體而言,匯出驅動程式沒有分派資料表、它沒有在 驅動程式堆疊中的位置,而且在服務控制管理員的資料庫中沒有將它定義為系統服務的專案。 雖然匯出驅動程式沒有 分派資料表,但它可以將 分派常式 提供給標準驅動程式。 標準驅動程式會將分派常式插入自己的分派資料表。 匯出驅動程式具有永遠不會呼叫的存根 DriverEntry 常式。

核心模式匯出驅動程式特別適合實作與基礎堆疊和硬體特性無關的驅動程式組部分。

Windows 包含其他驅動程式所載入的數個匯出驅動程式,例如:

  • SCSI 埠驅動程式
  • 磁帶類別驅動程式
  • IDE 控制器驅動程式都是系統提供的匯出驅動程式

標準驅動程式也可以做為匯出驅動程式。 若要讓驅動程式以兩種方式運作,它必須建置為匯出驅動程式,並載入為一般驅動程式。

建置匯出驅動程式

若要在 Visual Studio 中建立匯出驅動程式,請使用下列程式:

  1. 從範本建立新的專案,例如 空白 WDM 驅動程式
  2. 將模組定義檔新增至專案,例如:
LIBRARY mydriver.sys
EXPORTS
  DllInitialize PRIVATE
  DllUnload PRIVATE

核心模式 DLL 的進入點一律為 DllInitialize。 系統會在載入 DLL 之後立即呼叫核心模式 DLL 的 DllInitialize 常式。 匯出驅動程式必須提供 DllInitialize 常式。 您可以使用 DllInitialize 常式來取得或初始化 DLL 中其他常式所需的資源。

您無法使用 DLLENTRY 宏來指定進入點。

NTSTATUS DllInitialize(
  _In_ PUNICODE_STRING RegistryPath
);

RegistryPath 是計數 Unicode 字串的指標,指定 DLL 登錄機碼的路徑, HKEY_LOCAL_MACHINE\CurrentControlSet\Services\DllName。 DLL 常式可以使用此金鑰來儲存 DLL 特定資訊。 一旦 DllInitialize 結束,RegistryPath 所指向的緩衝區就會釋出。 因此,如果 DLL 使用金鑰, DllInitialize 必須複製金鑰名稱。

建置程式會產生具有 .lib 副檔名的匯出程式庫,以及具有.sys副檔名的匯出驅動程式。

從匯出驅動程式匯入函式

若要匯入匯出驅動程式所匯出的函式,您應該使用 Ntdef.h 中定義的 DECLSPEC_IMPORT 宏來宣告函式。 例如:

DECLSPEC_IMPORT int LoadPrinterDriver (int arg1); 

此宏會解析為 __declspec (dllimport) 需要之平臺上的儲存類別宣告,而不需要在這些平臺上解析為任何專案。

在匯出驅動程式中,應該使用 DECLSPEC_EXPORT 宏宣告要匯出的函式。 此宏會解析為 __declspec ( dllexport) 需要之平臺上的儲存體類別宣告,而且在不需要的平臺上,則不會解析為任何專案。 如果匯出驅動程式將分派常式提供給標準驅動程式,則不需要匯出該常式。

載入和卸載匯出驅動程式

匯出驅動程式必須安裝在 %Windir%\System32\Drivers 目錄中。 從 Windows 2000 開始,作業系統會保留參考計數,指出匯出驅動程式的函式已由其他驅動程式匯入的次數。 每當其中一個匯入驅動程式卸載時,系統就會遞減此計數。 當參考計數降為零時,系統會卸載匯出驅動程式。 不過,匯出驅動程式必須包含標準進入點和卸載常式、 DllInitializeDllUnload,否則作業系統將不會啟用此參考計數機制。

當系統卸載 DLL 時,系統會呼叫核心模式 DLL 的 DllUnload 常式。

NTSTATUS DllUnload(void);

匯出驅動程式必須提供 DllUnload 常式。 您可以使用 DllUnload 常式來釋放 DLL 中常式所使用的任何資源。