IoSetCompletionRoutine宏注册一个IO完成例程,这个完成例程将会在调用此函数的驱动的下一层驱动完成IRP指定的操作请求时被调用。
void IoSetCompletionRoutine(
IN PIRP Irp,
IN PIO_COMPLETION_ROUTINE CompletionRoutine,
IN PVOID Context,
IN BOOLEAN InvokeOnSuccess,
IN BOOLEAN InvokeOnError,
IN BOOLEAN InvokeOnCancel
);
参数:
Irp
指向本驱动正在处理的IRP的指针
CompletionRoutine
驱动提供的完成例程专用接口,当他的下一层驱动程序完成请求包时被调用
Context
指向传递给完成例程的参数的指针。参数内容由驱动设置,并且只能存储在“非分页”(nonpaged)内存中,因为完成例程的中断请求级范围是IRQP<=DISPATCH_LEVEL.
InvokeOnSuccess
特指完成例程被调用时的IRP IO_STATUS_BLOCK子域为NT_SUCCESS
InvokeOnSuccess
特指完成例程被调用时的IRP IO_STATUS_BLOCK子域为不成功的情况
InvokeOnSuccess
特指完成例程被调用时的IRP IO_STATUS_BLOCK子域指明,它的下层驱动对传下来的这个IRP执行了IoCancelIrp操作
返回值:
无
头文件:
在wdm.h和ntddk.h中声明,需要包含上面两个头文件。
comment:
这个函数在它得到的IRP中设置了完成例程的偏移地址,因此下层驱动可以很容易的调用它。设备驱动链最底层的驱动程序不能调用这个函数。
IoSetCompletionRoutine注册了相应的回调函数,这类回调函数会在下一层设备完成它传递出去的操作请求时被调用,操作请求有以下几种
· With a success status value
· With a nonsuccess status value
· By canceling the IRP
通常,I/O status子域被下层设备驱动设置。高层驱动的完成例程可以读取但不应修改它。
高层驱动使用IoAllocateIrp或IoBuildAsynchronousFsdRequest 分配/建立 IRP,在调用IoCallDriver时传递驱动 分配/建立 的IRP参数前必须传递所有InvokeOnXXX参数为TRUE来调用此完成例程。当完成例程通过这个IRP被调用时它必须释放驱动建立的IRP和任何其他相关的资源,比如:IoBuildPartialMdl分配的MDL。这类驱动如果调用IoFreeIrp阻止I/0 manager完成这个驱动创建的IRP将会返回STATUS_MORE_PROCESSING_REQUIRED。(Such a driver should returnSTATUS_MORE_PROCESSING_REQUIRED when it calls IoFreeIrp to forestall the I/0 manager's completion processing for the driver-allocated IRP.)
那种在他们的完成例程执行前可能被unload的非即插即用类驱动要使用IoSetCompletionRoutineEx。
IoSetCompletionRoutine的调用者必须运行在IRQL<=DISPATCH_LEVEL.
评论(转):
此函数定义一个函数接口给下一层驱动调用,当下一层驱动完成给定的IRP任务时,就调用此函数设定的函数接口,从微软驱动结构来说,最上层接受应用程序发出的命令,做一些处理,并向下一层驱动发出IRP命令,驱动堆栈中驱动按此模式,依次处理命令并向下发出IRP命令,当最底层驱动完成以后,在依次调用此函数定义的函数接口,调用上层驱动的函数,完成操作,这样控制又由最低层依次返回应用程序,完成应用程序的一个调用驱动.