每個驅動程式物件都代表已載入內核模式驅動程式的映像。 I/O 管理員會配置 DRIVER_OBJECT 結構,並將它當做輸入參數傳遞給驅動程式的 DriverEntry、 AddDevice 和選擇性 的 Reinitialize 例程,以及將其 卸 除例程,如果有的話。
驅動程式物件部分不透明。 驅動程式寫入器必須知道驅動程序物件的特定成員,才能初始化驅動程式,並在驅動程式可卸載時卸除驅動程式。 驅動程式物件的下列成員可供驅動程式存取。
語法
typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
PFAST_IO_DISPATCH FastIoDispatch;
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT, *PDRIVER_OBJECT;
成員
Type
指定驅動程式物件的物件類型識別碼。 I/O 管理員會在配置驅動程式對象時設定此欄位。 驅動程式不應該使用或修改此欄位。
Size
指定驅動程式對象結構的大小,以位元組為單位。 I/O 管理員會在配置驅動程式對象時設定此欄位。 驅動程式不應該使用或修改此欄位。
DeviceObject
驅動程式所建立之裝置對象連結清單中的第一個裝置物件的指標。 此欄位會將單一驅動程式建立的所有裝置連結在清單上。 驅動程式成功呼叫 IoCreateDevice 時,I/O管理員會自動更新此成員。 驅動程式可以使用此成員和 DEVICE_OBJECT的 NextDevice 成員來周遊驅動程式所建立之所有裝置物件的完整清單。 這在驅動程式卸除期間特別有用,以確保已正確清除所有裝置物件。
Flags
包含系統定義的旗標,描述驅動程式的各種屬性和狀態。 此欄位提供驅動程式物件的可延伸旗標位置。 這些旗標是由 I/O 管理員和其他系統元件所設定和維護。 驅動程式不應該直接修改此欄位。
DriverStart
指向將驅動程式映像載入系統記憶體中的基底虛擬位址。 此位址代表核心位址空間中驅動程式程式代碼區段的開頭。 載入驅動程式時,I/O 管理員會設定此值。
DriverSize
指定記憶體中驅動程式映像的大小,以位元組為單位。 此值代表已載入驅動程式的總記憶體使用量,包括程式代碼、數據和其他區段。 載入驅動程式時,I/O 管理員會設定此值。
DriverSection
指向驅動程式的區段物件,此物件代表記憶體管理員中的驅動程式映像。 這是記憶體管理員和載入器在內部使用的不透明系統結構。 驅動程式不應該存取或修改這個成員。
DriverExtension
驅動程式延伸模組的指標。 驅動程式擴充功能的唯一可存取成員是 DriverExtension->AddDevice,驅動程式的 DriverEntry 例程會儲存驅動程式的 AddDevice 例程。
DriverName
包含驅動程式的 Unicode 字串名稱。 錯誤記錄線程會使用此欄位來判斷 I/O 要求或系結至的驅動程式名稱。 這通常是 \Driver\DriverName 格式,其中 DriverName 會對應至登錄中的驅動程式服務名稱。 I/O 管理員會根據驅動程式的登錄組態來設定此值。
HardwareDatabase
\Registry\Machine\Hardware 登錄中硬件組態信息的路徑指標。
FastIoDispatch
定義驅動程式快速 I/O 進入點之 FAST_IO_DISPATCH 結構的指標。 這個選擇性指標指向驅動程式的替代進入點陣列,以取得「快速 I/O」支援。 使用個別參數直接叫用驅動程式例程,而不是使用標準 IRP 呼叫機制來執行快速 I/O。 請注意,這些函式只能用於同步 I/O,以及快取檔案時。 這個成員只能由文件系統驅動程式 (FSD) 和網路傳輸驅動程式使用。
DriverInit
驅動程式 DriverEntry 例程的進入點位址。 I/O 管理員會將此字段設定為在載入驅動程式時指向驅動程式的初始化函式。 這是將驅動程式載入記憶體時,在驅動程式中呼叫的第一個函式,負責初始化驅動程式物件並設定分派例程。
DriverStartIo
驅動程式 StartIo 例程的進入點,如果有任何,驅動程式初始化時,DriverEntry 例程所設定。 如果驅動程式沒有 StartIo 例程,此成員會 NULL。
DriverUnload
驅動程式 卸除 例程的進入點,如果有的話,驅動程式初始化時,DriverEntry 例程所設定。 如果驅動程式沒有 Unload 例程,此成員會 NULL。
MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]
分派數據表,其中包含驅動程式 DispatchXxx 例程的進入點陣列。 數位列的索引值是 IRP_MJ_XXX 值,代表每個 IRP 主要函式程式碼 。 這個主要函式分派數據表必須是 物件中的最後一個字段,才能維持可延伸。 每個驅動程式都必須設定此陣列中的進入點,IRP_MJ_XXX 驅動程序處理的要求。 如需詳細資訊,請參閱 撰寫分派例程。
為了協助 驅動程式的程式代碼分析、靜態驅動程序驗證器 (SDV) 和其他驗證工具,每個 DispatchXxx 例程都會使用 DRIVER_DISPATCH 類型宣告,如下列程式代碼範例所示:
DRIVER_DISPATCH DispatchXxx;
然後,回呼例程會實作如下:
_Use_decl_annotations_
NTSTATUS
DispatchXxx(
struct _DEVICE_OBJECT *DeviceObject,
struct _IRP *Irp
)
{
// Function body
}
DRIVER_DISPATCH函式類型定義於 Wdm.h 頭檔中。 若要在執行程式代碼分析工具時更準確地識別錯誤,請務必將 _Use_decl_annotations_ 批註新增至函式定義。
_Use_decl_annotations_ 批注可確保在頭檔中套用至DRIVER_DISPATCH函式類型的批注。 如需函式宣告需求的詳細資訊,請參閱 使用 WDM 驅動程式的函式角色類型來宣告函式。 如需 _Use_decl_annotations_的相關信息,請參閱 批注函式行為。
言論
每個內核模式驅動程式的初始化例程都應該命名為 DriverEntry ,讓系統會自動載入驅動程式。 如果這個例程的名稱是別的,驅動程式寫入器必須定義連結器初始化例程的名稱;否則,系統載入器或 I/O 管理員找不到驅動程式的傳輸位址。 其他標準驅動程式例程的名稱可以由驅動程式寫入器自行決定選擇。
驅動程式必須設定其 DispatchXxx 驅動程式物件中的進入點,該進入點會在載入驅動程式時傳入 DriverEntry 例程。 裝置驅動程式必須為 IRP_MJ_XXX 設定一或多個 DispatchXxx 進入點, 需要相同類型裝置的任何驅動程式才能處理。 較高層級的驅動程式必須設定一或多個 DispatchXxx 進入點,讓所有 IRP_MJ_XXX 都必須傳遞至基礎設備驅動器。 否則,驅動程式不會針對驅動程序物件中未設定 DispatchXxx 例程的任何 IRP_MJ_XXX 傳送 IRP。 如需一組 IRP_MJ_XXX 需要不同類型基礎裝置驅動程式才能處理的詳細資訊,請參閱 IRP 主要函式程式碼。
DriverEntry 例程也會在驅動程式對象中設定驅動程式的 AddDevice、StartIo 和/或 Unload 進入點。
設備驅動器可以使用 HardwareDatabase 字串,在載入驅動程式時從登錄取得硬體組態資訊。 驅動程式會獲得此字串的唯讀存取權。
RegistryPath 輸入 DriverEntry 例程會指向 \Registry\Machine\System\CurrentControlSet\Services\DriverName 機碼,其中 driverName 的值 專案會識別驅動程式。 此登入機碼包含驅動程式的服務組態,包括下列值:
- 啟動:應載入驅動程式時(開機、系統、自動、需求或停用)
- 類型:服務類型(核心驅動程式、檔案系統驅動程式等)
- ErrorControl:如果驅動程式無法載入,系統應該如何回應
- ImagePath:驅動程式二進位檔的路徑
驅動程式可以在其服務 金鑰的參數子 機碼下儲存其他組態數據。 至於輸入驅動程序物件中的 HardwareDatabase,驅動程式會獲得此字串的只讀存取權。
驅動程式物件內的未記載成員應該視為無法存取。 具有對象成員位置相依性的驅動程式,或存取未記載成員的驅動程式可能無法在一段時間內保持可攜式且與其他驅動程式互通。
要求
| 要求 | 價值 |
|---|---|
| 標頭 | wdm.h (包括 Wdm.h、Ntddk.h、Ntifs.h) |