我们处理IRP分两种情况,一种继续下发,一种结束,继续下发分两种,不管下发结果,一种是需要知道IRP执行结果,结束也分两种,成功和失败结果结束
过滤驱动与IRP处理方式
- IoCopyXXXX+完成例程(把IRP当前栈拷贝下去,为IRP设置一个完成例程,等待事件,当IRP下发之后,下层完成之后调用完成例程,发出信号通知完成例程,设置信号为有信号,所以上层就知道情况了)
- ioSkip+Iocall直接下发
- 结束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