天天看點

建立IRP的四種不同方式

在驅動程式中,經常會調用其他的驅動程式;其中,手動構造 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 會設定這個事件。

繼續閱讀