Winoows内核设计思想之IRP
+ -

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

2021-07-14 585 0

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

  1. VOID
  2. IoSetCompletionRoutine(
  3. _In_ PIRP Irp,
  4. _In_opt_ PIO_COMPLETION_ROUTINE CompletionRoutine,
  5. _In_opt_ __drv_aliasesMem PVOID Context,
  6. _In_ BOOLEAN InvokeOnSuccess,
  7. _In_ BOOLEAN InvokeOnError,
  8. _In_ BOOLEAN InvokeOnCancel
  9. )
  10. //++
  11. //
  12. // Routine Description:
  13. //
  14. // This routine is invoked to set the address of a completion routine which
  15. // is to be invoked when an I/O packet has been completed by a lower-level
  16. // driver.
  17. //
  18. // Arguments:
  19. //
  20. // Irp - Pointer to the I/O Request Packet itself.
  21. //
  22. // CompletionRoutine - Address of the completion routine that is to be
  23. // invoked once the next level driver completes the packet.
  24. //
  25. // Context - Specifies a context parameter to be passed to the completion
  26. // routine.
  27. //
  28. // InvokeOnSuccess - Specifies that the completion routine is invoked when the
  29. // operation is successfully completed.
  30. //
  31. // InvokeOnError - Specifies that the completion routine is invoked when the
  32. // operation completes with an error status.
  33. //
  34. // InvokeOnCancel - Specifies that the completion routine is invoked when the
  35. // operation is being canceled.
  36. //
  37. // Return Value:
  38. //
  39. // None.
  40. //
  41. //--
  42. {
  43. PIO_STACK_LOCATION irpSp;
  44. NT_ASSERT( (InvokeOnSuccess || InvokeOnError || InvokeOnCancel) ? (CompletionRoutine != NULL) : TRUE );
  45. irpSp = IoGetNextIrpStackLocation(Irp);
  46. irpSp->CompletionRoutine = CompletionRoutine;
  47. irpSp->Context = Context;
  48. irpSp->Control = 0;
  49. if (InvokeOnSuccess) {
  50. irpSp->Control = SL_INVOKE_ON_SUCCESS;
  51. }
  52. if (InvokeOnError) {
  53. irpSp->Control |= SL_INVOKE_ON_ERROR;
  54. }
  55. if (InvokeOnCancel) {
  56. irpSp->Control |= SL_INVOKE_ON_CANCEL;
  57. }
  58. }

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

IofCompleteRequest的部分代码:

  1. ...
  2. /* Check if there is a Completion Routine to Call */
  3. if ((NT_SUCCESS(Irp->IoStatus.Status) &&
  4. (StackPtr->Control & SL_INVOKE_ON_SUCCESS)) ||
  5. (!NT_SUCCESS(Irp->IoStatus.Status) &&
  6. (StackPtr->Control & SL_INVOKE_ON_ERROR)) ||
  7. (Irp->Cancel &&
  8. (StackPtr->Control & SL_INVOKE_ON_CANCEL)))
  9. {
  10. /* Clear the stack location */
  11. IopClearStackLocation(StackPtr);
  12. /* Check for highest-level device completion routines */
  13. if (Irp->CurrentLocation == (Irp->StackCount + 1))
  14. {
  15. /* Clear the DO, since the current stack location is invalid */
  16. DeviceObject = NULL;
  17. }
  18. else
  19. {
  20. /* Otherwise, return the real one */
  21. DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject;
  22. }
  23. /* Call the completion routine */
  24. Status = StackPtr->CompletionRoutine(DeviceObject,
  25. Irp,
  26. StackPtr->Context);
  27. /* Don't touch the Packet in this case, since it might be gone! */
  28. if (Status == STATUS_MORE_PROCESSING_REQUIRED) return;
  29. ...

0 篇笔记 写笔记

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

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

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