IoMarkIrpPending
IoMarkIrpPending例程用於標記指定的IRP,標誌着某個驅動的分發例程(分發函數)因需要被其他的驅動程序進一步處理最終返回STATUS_PENDING狀態。
VOID IoMarkIrpPending( IN OUT PIRP Irp );
參數:Irp
將被標記爲Pending狀態的IRP指針。
返回值:
無
Comments:
除非IRP的派遣例程完成這個IRP或向下層驅動傳遞,否則派遣例程必須調用IoMarkIrpPending掛起這個IRP。否則I/0 manager將在這個函數返回時試圖完成該IRP。
調用IoMarkIrpPending後,派遣例程必須返回STATUS_PENDING,儘管有些函數在派遣例程的IoMarkIrpPending返回前完成了這個IRP。
如果驅動隊列收到了IRP,它應該先把這些要進入隊列的IRP掛起(通過調用IoMarkIrpPending)在放入隊列。否則隊列中的未掛起的IRP可能被其他的驅動例程取出並完成(調用 IoCompleteRequest)和釋放(由系統來做),如果在這時再調用IoMarkIrpPending就會導致系統的crash。
如果驅動設置了一個完成例程然後向下層驅動傳遞IRP,它的完成例程應該檢測IRP->PendingReturned標誌域(Flag)。如果這個子域被設置成TRUE,完成例程就必須調用IoMarkIrpPending掛起該IRP。(完成例程不返回STATUS_PENDING,更多信息參考:Implementing an IoCompletion Routine)。
Warning:
創建和發送IRP給其他的設備棧不得在完成例程(Completion Routine)中調用IoMarkIrpPending掛起自己創建的IRP。這個調用會毀壞前面被分配的內存,因爲這是所有驅動對應的location stack中最後一個location stack,也就是前面已經沒有IRP_STACK_LOCATION了。
驅動程序把IRP向下傳遞後,等待一個事件對象不應該把IRP設置爲Pending,它的完成例程應該設置事件對象並返回STATUS_MORE_PROCESSING_REQUIRED。
必要條件:
IRQL:Any level
頭文件:在wdm.h中聲明,需要包含wdm.h,Ntddk.h,Ntifs.h。
下面是我對上面幾句話的理解:
“如果驅動隊列收到了IRP,它應該先把這些要進入隊列的IRP掛起(通過調用IoMarkIrpPending)在放入隊列。否則隊列中的未掛起的IRP可能被其他的驅動例程取出並完成(調用 IoCompleteRequest)和釋放(由系統來做),如果在這時再調用IoMarkIrpPending就會導致系統的crash。”
當然若IRP被IO manager Free掉了再引用肯定會引起系統的crash,因爲內存違規訪問。主要是這裏:“驅動收到IRP後要先掛起然後再入隊列,這樣可以防止系統crash”,我認爲IoMarkIrpPending函數會引起該IRP引用計數(reference)的“加1”,所以即使該IRP被一個其它的Driver完成(調用IoCompletionRequest,估計引起引用計數“減1”)也不會被IO manager Free掉,不過還有一種方式是IoFreeIrp,這種方式我認爲不適用與非自己創建的IRP,也可能這句不準確,更多IoFreeIrp的資料請自己查看DDK或WDK文檔。