欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

IRP完成的几种常见错误

IRP完成的几种常见错误

直接上代码。
第一种:
NTSTATUS DispatchSomething(PDEVICE_OBJECT fidp, PIRP irp)
{
    PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fido->DevcieExtension;
    IoCopyCurrentIrpStackLocationToNext(irp);
    IoSetCompletionRoutine(irp, CompletionRoutine, ...);
    NTSTATUS status = IoCallDriver(pdx->LowerDevice, irp);
    if (STATUS_PENDING == status)
    {
        IoMarkIrpPending(Irp)
    }
    return status;
}
这种情况貌似很正确,当下层返回STATUS_PENDING的时候标记一下
其实错就错在当返回STATUS_PENDING的时候这个IRP可能已经完成了,这时候千万不要碰IRP了。

第二种:
NTSTATUS DispatchSomething(PDEVICE_OBJECT fido, PIRP irp)
{
    PDEVICE_EXTENSION pdx = fido->DeviceExtension;
    IoMarkIrpPending(irp);
    IoCopyCurrrentIrpStackLocationToNext(irp);
    IoSetCompletionRoutine(irp, TopDriverCompleteRoutine, ...);
    return IoCallDriver(pdx->LowrDevice, irp);
}
同样,看起来没什么问题,大不了我先标记一下吧。
这里的问题在于IoMarkIrpPending和STATUS_PENDING必须配对使用,这里是标记了要Pending,但是函数却有可能返回了别的值。
第三种:
NTSTATUS DeispatchSomething(PDEVCIE_OBJECT fido, PIRP irp)
{
    PDEVICE_EXTENSION pdx = fido->DeviceExtenson;
    KEVENT     event;
    KeInitializeEvent(&event, NotificaionEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(irp);
    IoSetCompletionRoutine(irp, CompletionRoutine, &event, TRUE,TRUE,TRUE);
    IoCallDriver(pdx->LowerDeviceObject, irp);
    KeWaitForSingleObject(&event, ...);
    Irp->IoStatus.Status = status;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    return status;
}
NTSTATUS CompletionRoutine(PDEVICE_OBJECT fido, PIRP irp, PVOID pev)
{
    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(irp);
    }
    KeSetEvent((PKEVENT)pev, IO_NO_CREMENT, FALSE);
    return STATUS_MORE_PROCESSING_REQUIRED;
}
这个是在完成例程中标记的,如果下层异步完成,则标记,看起来没错,其实也犯了和前一个一样的错误。

第四种:
VOID SomeFunction()
{
    PIRP irp = IoBuildAsynchronousFsdRequest(...);
    IoSetCompleteRoutine(irp, MyCompleteRoutine, ...);
    IoCallDriver(...);
}
NTSTATUS MyCompletionRoutine(PDEVCIE_OBJECT junk, PIRP irp, PVOID context)
{
    if (Irp->PendingReturned)
    {
        IoMarkIrpPending(irp);
    }
    IoFreeIrp(irp);
    return STATUS_MORE_PROCESISING_REQUIRED;
}
这种方式为自己构造IRP,然后传递给下层处理。
该情况的错误在于自己构造的IRP没有当前栈,所以也无法调用IoMarkIrpPending

在实际代码编写中一定要注意避免上述几种错误

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功