首页
社区
课程
招聘
[旧帖] [原创]IRP完成的几种常见错误 0.00雪花
发表于: 2010-4-2 12:30 2683

[旧帖] [原创]IRP完成的几种常见错误 0.00雪花

2010-4-2 12:30
2683

直接上代码。
第一种:
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

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


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 51
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
申请验证码啊
2010-4-2 12:31
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3

如果可以
楼主把出错的后的现象描述清楚
或者有实例那就更好了
2010-4-2 12:36
0
游客
登录 | 注册 方可回帖
返回
//