天天看点

再次理解IRPIRP使用注意参考资料

我们处理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

继续阅读