在驅動程式中,經常會調用其他的驅動程式;其中,手動構造
IRP
,然後將
IRP
傳遞到相應驅動程式的派遣函數中是一種比較簡單的方法,下面就來介紹下手動建立
IRP
的幾種不同的方法及其特點。
建立
IRP
總共有
4
種方法。分別通過調用:
IoBuildSynchronousFsdRequest
、
IoBuildAsynchronousFsdRequest
、
IoBuildDeviceIoControl
和
IoAllocateIrp
這
4
個核心功能來完成。這其中,
IoAllocateIrp
是比較底層的核心功能,其餘的三個核心功能是屬於靠近上層的核心功能,而且這三個函數都是通過調用
IoAllocateIrp
實現的。
這幾個函數都是文檔化的函數,原型都可以在
DDK Documentation
中查到,這裡就不多說了,下面主要來說說它們的不同點:
1.
可建立的
IRP
類型
這四個函數可以建立的
IRP
的類型是不同的。
IoBuildSynchronousFsdRequest
用於建立同步的
IRP
請求,但是只可以建立以下類型的
IRP
:
IRP_MJ_PNP
,IRP_MJ_READ,IRP_MJ_WRITE,IRP_MJ_FLUSH_BUFFERS
和IRP_MJ_SHUTDOWN
;
IoBuildAsynchronousFsdRequest
可建立的
IRP
類型和
IoBuildSynchronousFsdRequest
一樣(從名字就可以看出來),只是它是用來建立非同步
IRP
請求。
IoBuildDeviceIoControl
可以建立的
IRP
類型為:IRP_MJ_DEVICE_CONTROL
和IRP_MJ_INTERNAL_DEVICE_CONTROL
。而且
IoBuildDeviceIoControl
只能建立同步的
IRP
。在這三個函數中,都有一個
ULONG
的輸入參數指定建立的
IRP
類型。
IoAllocateIrp
函數的使用比較靈活,他可以建立任意類型的
IRP
,但不是由參數指定,而是建立後自行填寫,要求使用者對
IRP
的結構有比較熟悉的理解。
2.
建立後
IRP
對象的刪除
IoBuildSynchronousFsdRequest
、
IoBuildAsynchronousFsdRequest
和
IoBuildDeviceIoControl
核心功能在建立完
IRP
後,不需要程式員負責刪除
IRP
,作業系統會自動刪除。而用
IoAllocateIrp
核心功能建立
IRP
時,需要程式員自己調用
IoFreeIrp
核心功能刪除
IRP
對象。
3.
關聯的事件
IoBuildSynchronousFsdRequest
和
IoBuildDeviceIoControl
在建立
IRP
時,需要為它們準備好一個事件,這個事件會和
IRP
請求相關聯,當
IRP
請求被結束時該事件觸發。程式中要用
KeWaitForSingleObject
函數等待。
IoBuildAsynchronousFsdRequest
函數建立
IRP
時則不需要準備事件,不過可以通過
IRP
的
UserEvent
子域來通知
IRP
請求的結束。
當執行
IoCompleteRequest
核心功能時,作業系統會檢查
IRP
的
UserEvent
子域是否為空白。如果該子域為空白,則它代表一個事件指標,這時
IoCompleteRequest
會設定這個事件。