再次理解IRP

85 篇文章 6 订阅
83 篇文章 9 订阅

我们处理IRP分两种情况,一种继续下发,一种结束,继续下发分两种,不管下发结果,一种是需要知道IRP执行结果,结束也分两种,成功和失败结果结束

过滤驱动与IRP处理方式

  1. IoCopyXXXX+完成例程(把IRP当前栈拷贝下去,为IRP设置一个完成例程,等待事件,当IRP下发之后,下层完成之后调用完成例程,发出信号通知完成例程,设置信号为有信号,所以上层就知道情况了)
  2. ioSkip+Iocall直接下发
  3. 结束IRP不下发
#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; }

 ioSkip就是先栈+1,iocall-1,就相当于直到下层栈了,而copy是要把这层栈拷贝到下层,因为还要返回完成信息。

IRP使用注意

当驱动将IRP已经IoCallDriver传递到下个驱动了,就不在拥有这个IRP权限了。如果想得到只能IoCompletion。若驱动的分发例程也还必须在IRP被下面驱动处理完成之后再处理他,IoCompletio例程必须返回STATUS_MORE_PROCESSING_REQUIRED,用来将IRP的所有权返回给分发例程。如此I/o管理器会停止IRP处理,将最终完成IRP的任务留给分发例程。分发例程能在之后调用IoCompleteRequest来处理这个IRP,或者还能标记这个IRP继续进一步处理。

我们关心这个IRP的处理结果 就用这个

Pending完成例程

IoCopyCurrentIrpStackLocationToNext  +完成例程

Pending完成例程

KEVENT event;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
CompRoutine,
&event,
TRUE,
TRUE,
TRUE
);
status = IoCallDriver(DeviceObject, Irp);
if (status == STATUS_PENDING) 
{
	status = KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL
);
ASSERT(NT_SUCCESS(status));
status = Irp->IoStatus.Status;
}

完成例程设置

NTSTATUS
CompRoutine(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context
    )
{
    PKEVENT event = Context;
    Irp->UserIosb->Status = Irp->IoStatus.Status;
    Irp->UserIosb->Information = Irp->IoStatus.Information;
    KeSetEvent(event , IO_NO_INCREMENT, FALSE);
    //IoFreeIrp(Irp);
    return STATUS_MORE_PROCESSING_REQUIRED;
}

忽略直接下发

IoSkipCurrentIrpStackLocation,下层设备拿到的IO_STACKLOCATION 和当前的一样
 


PDEVICE_EXTENSION   deviceExtension;
IoSkipCurrentIrpStackLocation(Irp);

//拿到保存在设备扩展里的下层设备

 


deviceExtension = 
	(PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

//下发
return IoCallDriver(
		deviceExtension->TargetDeviceObject, 
		Irp);

如果是不处理直接下发

 

PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );

手动构建IRP


IoAllocateIrp

IoGetNextIrpStackLocation

IoAllocateIrp /IoBuildDeviceIoControlRequest 

IoGetNextIrpStackLocation 

//例子:

//强制删除文件

//Sfilter里查询文件名字

 


错误的下发:
下发后就没有访问这个IRP的权限了 必须等待 和设置完成例程 例程中必须返回STATUS_MORE_PROCESSING_REQUIRED

// Forward request to next driver
IoCopyCurrentIrpStackLocationToNext( Irp );
// Send the IRP down
status = IoCallDriver( nextDevice, Irp );
// The following is an error because this driver
// no longer owns the IRP.
If (status == STATUS_PENDING)
{
	IoMarkIrpPending( Irp );//错误,无权操作Irp了
}
// Return the lower driver’s status
return status;

参考资料

https://blog.csdn.net/zhuhuibeishadiao/article/details/51179025

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值