什么是STATUS_PENDING?
如果我还没有使你困惑,我们就继续谈谈STATUS_PENDING和IoMarkIrpPending。 他们的用途是什么? 用途就是我们可以处理异步IRP并且让上层驱动和I/O管理器了解。 第一部分STATUS_PENDING返回是最佳的,所以如果我们想等,我们仅仅需要为异步操作返回它。第二部分是IoMarkIrpPending实际上是传播IRP上的未决返回状态。这种方式我们不需要总是调用KeSetEvent,只需要做的就是在返回STATUS_PENDING的情况下处理。
另外的用途就是中间层的驱动可以改变STATUS_PENDING状态为STATUS_SUCCESS ,不需要自始至终地沿着驱动栈传递全部未决的状态。
完成例程怎样工作的?
每一个设备的STACK LOCATION或许都有一个相关联的完成例程。目前被调用的完成例程是上层驱动的,而不是当前驱动的。当前驱动完成irp后,他自己知道什么时候完成的。所以当驱动完成完成后,就会在当前栈域中查看完成例程,如果存在就调用。在调用之前,当前的IO_STACK_LOCATION就会移到指向上层驱动的域。这是很重要的,稍候我们将会看到。如果驱动没有完成IRP,他就会调用IoMarkIrpPending向上传递未决的状态。这是因为驱动返回STATUS_PENDING,他一定要标记IRP为未决的。上层驱动如果不是返回与底层驱动同样的状态,就不需要标记IRP为未决状态。或许他会中途拦截STATUS_PENDING,并且等待完成。然后它会停止IRP的完成,当返回状态不是STATUS_PENDING.时,再完成它。
现在如果你的驱动创建IRP,你不用被迫把IRP标记为未决的。你知道这是为什么?因为你没有IO_STACK_LOCATION,你没有在设备栈上。实际上如果你这么做了,你会破毁内存。
注意这个例子代码会展示一个的完成例程,它会调用IoMarkIrpPending,即便是完成例程中创建的IRP。这也是不应该发生的。实际上,如果你看了真实的代码,如果创建了同步的IRP,通常完成例程是不存在的,或者存在而仅仅返回更多处理的状态。
摘自: http://hi.baidu.com/combojiang/blog/item/d556aacf00260638f9dc6136.html