Windows驱动编程(关于IoCopyCurrentIrpStackLocationToNext和IoSetCompletionRoutine以及IoCallDriver)

首先看看IoCopyCurrentIrpStackLocationToNext的实现:

#define IoCopyCurrentIrpStackLocationToNext( Irp ) { \   
    PIO_STACK_LOCATION __irpSp;        \   
    PIO_STACK_LOCATION __nextIrpSp;    \   
    __irpSp = IoGetCurrentIrpStackLocation( (Irp) );     \   
    __nextIrpSp = IoGetNextIrpStackLocation( (Irp) );    \   
    RtlCopyMemory(__nextIrpSp, __irpSp, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \     
    __nextIrpSp->Control = 0; }  

实际上就是把IO_STACK_LOCATION栈的本层对象拷贝到下一层,但是不拷贝CompletionRoutine和Context这两个域,也就是说只拷贝CompletionRoutine之前的域。(CompletionRoutine完成例程,Context完成例程的参数)

 

再看看IoSetCompletionRoutine的实现:

#define IoSetCompletionRoutine(irp,routine,completioncontext,success,error,cancel)\
#{ PIO_STACK_LOCATION irpsp;\
#ASSERT((success)|(error)|(cancel)?(routine)!=NULL:TRUE);\
#irpsp=IoGetNextIrpStackLocation((irp));\
#irpsp->completionroutine=(routine);\
#irpsp->context=(completioncontext);\
#irpsp->control=0;\
#if((success)){irpsp->control=SL_INVOKE_ON_SUCCESS;}\
#if((error)){irpsp->control  |= SL_INVOKE_ON_ERROR;}\
#if((cancel)){irpsp->control  |=  SL_INVOKE_ON_CANCEL;}  }\

刚开始看书的时候老师在这个位置产生疑惑,在本层调用IoSetCompletionRoutine设置下层驱动的完成例程时,为什么传进去的参数irp里指向的CurrentStackLocation还是本层的,而没有让它指向下一层的,这样子设置的完成例程不是为本层设置了吗。

现在看了实现才知道,原来IoSetCompletionRoutine实现里有取得下一层的IO_STACK_LOCATION对象,设置的完成例程也是为下一层的驱动设置的。

 

再看看IoCallDriver的部分实现:

     函数声明如下所示:

  1. NTSTATUS IoCallDriver(

  2. _In_ PDEVICE_OBJECT DeviceObject,

  3. _Inout_ PIRP Irp

  4. );

  5. 部分实现如下所示:

  6. Irp->CurrentLocation--;  
  7.   
  8.    if (Irp->CurrentLocation <= 0) {  
  9.        KiBugCheck3( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0 );  
  10.    }  
  11.   
  12.    irpSp = IoGetNextIrpStackLocation( Irp );  
  13.    Irp->Tail.Overlay.CurrentStackLocation = irpSp;  
  14.   
  15.    //  
  16.    // Save a pointer to the device object for this request so that it can  
  17.    // be used later in completion.  
  18.    //  
  19.   
  20.    irpSp->DeviceObject = DeviceObject;  
  21.   
  22.   
  23.    //  
  24.    // Invoke the driver at its dispatch routine entry point.  
  25.    //  
  26.   
  27.    driverObject = DeviceObject->DriverObject;  
  28.   
  29.    //  
  30.    // Prevent the driver from unloading.  
  31.    //  
  32.   
  33.   
  34.    status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,  
  35.                                                              Irp );

这里一定要注意的是参数_In_ PDEVICE_OBJECT DeviceObject必须是下层(也就是目标层)的设备对象,不能再把本层的设备对象传进去了,一般下层的设备对象都存储在设备扩展对象里。

由实现代码可知,根据传进去的下层的设备对象可以得到下层的驱动对象,然后就可以根据IRP的类型来调用下层驱动的各种派遣函数了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值