IoMarkIrpPending

来源:互联网 发布:美工专业培训 编辑:程序博客网 时间:2024/05/18 11:26

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文档。