當裝置驅動程式通過調用 IoCreateDevice 建立裝置對象時,I/O 管理器在 DEVICE_OBJECT 結構的 Flags 欄位中設定 DO_DEVICE_INITIALIZING。DO_DEVICE_INITIALIZING 的目的是防止其它組件在驅動程式完成初始化裝置對象之前向裝置發送 I/O。
每次開啟裝置的一個控制代碼時,以及任何時候驅動程式試圖附加到一個裝置堆疊時(檢查堆棧頂部裝置對象的這個標誌),I/O 管理器都檢查 DO_DEVICE_INITIALIZING。如果設定 DO_DEVICE_INITIALIZING,那麼 I/O 管理器將不允許另一個組件使用諸如 CreateFile、OpenFile 或 IoGetDeviceObjectPointer 之類的函數通過名稱開啟裝置。DO_DEVICE_INITIALIZING 不會阻止驅動程式接收隨插即用請求或來自堆棧中高層驅動程式的請求,它僅僅防止組件開啟裝置。
對於驅動程式在其 DriverEntry 常式中建立的任何裝置對象,由 I/O 管理器負責清除 DO_DEVICE_INITIALIZING。對於除 DriverEntry 之外的任何常式中建立的任何裝置對象,由驅動程式負責清除 DO_DEVICE_INITIALIZING。
傳統驅動程式(例如為 Windows NT 4 編寫的非隨插即用驅動程式)在 DriverEntry 中建立它們的裝置對象。隨插即用驅動程式通常在 AddDevice 中建立它們的裝置對象,但是隨插即用驅動程式可能在 DriverEntry 中建立控制裝置物件(例如,公開自己的裝置介面或者支援某個應用程式可以開啟的獨佔堆棧中的裝置)。(驅動程式不把控制裝置物件報告給隨插即用或者將它們附加到裝置堆疊。)
驅動程式負責從常式(驅動程式在其中建立裝置對象)返回之前準備接收 I/O 請求。對於不同類型的驅動程式,涉及的步驟有所不同;對於隨插即用驅動程式,步驟通常包括將裝置的 PDO 指標儲存到裝置擴充中、定義標誌來跟蹤裝置的隨插即用狀態、設定電源管理標誌以及建立或初始化軟體資源(例如驅動程式用來管理其裝置的事件和自旋鎖)。驅動程式還可以註冊裝置介面或建立一個或多個到其裝置的符號連結。
對於在 DriverEntry 中建立的裝置對象,I/O 管理器允許 DriverEntry 一返回就開啟裝置。對於隨插即用驅動程式,驅動程式堆棧必須在 I/O 管理器允許開啟裝置之前成功完成一個啟動請求 (IRP_MN_START_DEVICE)。雖然隨插即用驅動程式可能需要在 AddDevice 和啟動請求之間處理一些來自堆棧中其它驅動程式的請求(例如,儲存連接埠驅動程式必須在此時間間隔內處理 SRB_FUNCTION_CLAIM_DEVICE),但是驅動程式在裝置被啟動之前不接收任何建立請求或基於檔案對象的 I/O 請求。從驅動程式清除此標誌到隨插即用管理器啟動裝置的時間,驅動程式不需要針對 IRP_MJ_CREATE 或基於檔案控制代碼傳入的 I/O 請求進行同步。
下列代碼是一個簡化的 AddDevice 常式的例子(基於 Windows DDK 中的 Toaster 樣本)。(已經從這個例子中刪除錯誤檢查和初始化裝置擴充的代碼。完整的代碼請參見 %winddk%/src/general/toaster/func/featured1/ 上的 Toaster 功能驅動程式樣本)。
NTSTATUS ToasterAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; PFDO_DATA fdoData; POWER_STATE powerState;PAGED_CODE();// Create a function device object. status = IoCreateDevice (DriverObject, sizeof (FDO_DATA), NULL, // No Name FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);// Code to initialize the device extension.// Attach driver to the device stack. fdoData->NextLowerDriver = IoAttachDeviceToDeviceStack (deviceObject, PhysicalDeviceObject);// Clear the DO_DEVICE_INITIALIZING flag.// Note:Do not clear this flag until the driver has set the // device power state and the power DO flags. //deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;return status; }
您應該做什嗎?
| • |
清除驅動程式在除 DriverEntry 之外的常式(例如隨插即用驅動程式的 AddDevice 常式)中建立的任何裝置對象的 DO_DEVICE_INITIALIZING 標誌。 |
| • |
在初始化裝置對象之後到從常式返回之前清除 DO_DEVICE_INITIALIZING。 |