Winoows内核设计思想之IRP
+ -

IRP完成例程IoSetCompletionRoutine的设计和实现原理

2021-07-14 524 0

在进行IRP下层传递时,通过上一节可知道,一种中使用IoCopyCurrentIrpStackLocationToNext,另一种是IoSkipCurrentIrpStackLocation。
其中在使用IoCopyCurrentIrpStackLocationToNext表示的是对当前的IRP当留当前设备栈,这样我们可以对其设置完成例程。当然这个完成例程并不是必须的,是可选的。
IRP完成例程的设置是通过IoSetCompletionRoutine函数实现的,Windows DDK提供了该函数的实现方法:

VOID
IoSetCompletionRoutine(
    _In_ PIRP Irp,
    _In_opt_ PIO_COMPLETION_ROUTINE CompletionRoutine,
    _In_opt_ __drv_aliasesMem PVOID Context,
    _In_ BOOLEAN InvokeOnSuccess,
    _In_ BOOLEAN InvokeOnError,
    _In_ BOOLEAN InvokeOnCancel
    )
//++
//
// Routine Description:
//
//     This routine is invoked to set the address of a completion routine which
//     is to be invoked when an I/O packet has been completed by a lower-level
//     driver.
//
// Arguments:
//
//     Irp - Pointer to the I/O Request Packet itself.
//
//     CompletionRoutine - Address of the completion routine that is to be
//         invoked once the next level driver completes the packet.
//
//     Context - Specifies a context parameter to be passed to the completion
//         routine.
//
//     InvokeOnSuccess - Specifies that the completion routine is invoked when the
//         operation is successfully completed.
//
//     InvokeOnError - Specifies that the completion routine is invoked when the
//         operation completes with an error status.
//
//     InvokeOnCancel - Specifies that the completion routine is invoked when the
//         operation is being canceled.
//
// Return Value:
//
//     None.
//
//--
{
    PIO_STACK_LOCATION irpSp;
    NT_ASSERT( (InvokeOnSuccess || InvokeOnError || InvokeOnCancel) ? (CompletionRoutine != NULL) : TRUE );
    irpSp = IoGetNextIrpStackLocation(Irp);
    irpSp->CompletionRoutine = CompletionRoutine;
    irpSp->Context = Context;
    irpSp->Control = 0;

    if (InvokeOnSuccess) {
        irpSp->Control = SL_INVOKE_ON_SUCCESS;
    }

    if (InvokeOnError) {
        irpSp->Control |= SL_INVOKE_ON_ERROR;
    }

    if (InvokeOnCancel) {
        irpSp->Control |= SL_INVOKE_ON_CANCEL;
    }
}

其中前三个参数代示需要设置完成例程的IPR,完成例程函数指针,调用完成例程时的自定义上下文。最后三个参数分别是InvokeOnSuccess、InvokeOnError和InvokeOnCancel,这三个参数比较有意思,分别表示IPR完成时,IRP错误时和IRP取消时是否调用该完成例程。
这些标志也是当记在STACK_LOCATION中。在IRP完成时,会进行标志判断,并执行相应的完成例程:

IofCompleteRequest的部分代码:

...
         /* Check if there is a Completion Routine to Call */
         if ((NT_SUCCESS(Irp->IoStatus.Status) &&
              (StackPtr->Control & SL_INVOKE_ON_SUCCESS)) ||
             (!NT_SUCCESS(Irp->IoStatus.Status) &&
              (StackPtr->Control & SL_INVOKE_ON_ERROR)) ||
             (Irp->Cancel &&
              (StackPtr->Control & SL_INVOKE_ON_CANCEL)))
         {
             /* Clear the stack location */
             IopClearStackLocation(StackPtr);
             /* Check for highest-level device completion routines */
             if (Irp->CurrentLocation == (Irp->StackCount + 1))
             {
                 /* Clear the DO, since the current stack location is invalid */
                 DeviceObject = NULL;
             }
             else
             {
                 /* Otherwise, return the real one */
                 DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
             }
             /* Call the completion routine */
             Status = StackPtr->CompletionRoutine(DeviceObject,
                                                  Irp,
                                                  StackPtr->Context);
             /* Don't touch the Packet in this case, since it might be gone! */
             if (Status == STATUS_MORE_PROCESSING_REQUIRED) return;
...

0 篇笔记 写笔记

IoCopyCurrentIrpStackLocationToNext和IoSkipCurrentIrpStackLocation操作的IO_STACK_LOCATION有什么区别
在Windows驱动中,传递IPR一般有两种操作:一种是调用IoSkipCurrentIrpStackLocation,表示跳过本层驱动的操作,直接转发至下层: IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(FDODeviceEx......
IRP完成例程IoSetCompletionRoutine的设计和实现原理
在进行IRP下层传递时,通过上一节可知道,一种中使用IoCopyCurrentIrpStackLocationToNext,另一种是IoSkipCurrentIrpStackLocation。其中在使用IoCopyCurrentIrpStackLocationToNext表示的是对当前的IRP当留当......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!