Henry
驱动牛犊
驱动牛犊
  • 注册日期2001-04-27
  • 最后登录2011-06-20
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望27点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
阅读:1794回复:11

清斑竹和大虾们关注(50分):

楼主#
更多 发布于:2002-07-22 10:26
一个值得讨论的问题:
请问下面三段代码在上层驱动程序看来有什么不同?
Code 1:

Read()
{
...
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(dx->LowerDeviceObject, Irp);
}


Code 2:
Read()
{
...
IoCopyCurrentIrpStackLocationIrpToNext(Irp);
IoSetCompletionRoutine(ReadCompletion, ...);
return IoCallDriver(dx->LowerDeviceObject, Irp);
}

ReadCompletion()
{
return STATUS_SUCCESS;
}


Code 3:

Read()
{
...
EVENT event;
KeInitializeEvent(&event);
IoCopyCurrentIrpStackLocationIrpToNext(Irp);
IoSetCompletionRoutine(ReadCompletion,&event,  ...);
Status = IoCallDriver(dx->LowerDeviceObject, Irp);
if (Status == STATUS_PENDING){
   KeWaitForSingleObject(event, ...);
}
}

ReadCompletion(PVOID pContext)
{
PKEVENT pevent = (PKEVENT)(pContext);
KeSetEvent(pevent, 1, FALSE);
return STATUS_SUCCESS;
}


我的手柄过滤驱动程序,在游戏控制器中测试。
使用Code 1没有问题。
使用Code 2游戏控制器中所有的值全部为0
使用Code 3在突然拔出设备时死机。
请大虾们帮忙想想,我已经被这个问题困扰了两个星期了。
驱动人生。
tigerzd
驱动老牛
驱动老牛
  • 注册日期2001-08-25
  • 最后登录2004-12-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-07-22 12:11
第二个问题应该是完成例程处理有问题,
其余的不说,返回值用STATUS_MORE_PROCESSING_REQUIRED试试:
return STATUS_MORE_PROCESSING_REQUIRED;
第三个除了有可能是设备没有完成请求在等待外与第二个相似。
犯强汉者,虽远必诛! [img]http://www.driverdevelop.com/forum/upload/tigerzd/2002-12-13_sf10.JPG[/img]
Henry
驱动牛犊
驱动牛犊
  • 注册日期2001-04-27
  • 最后登录2011-06-20
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望27点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-07-22 14:30
第二个问题应该是完成例程处理有问题,
其余的不说,返回值用STATUS_MORE_PROCESSING_REQUIRED试试:
return STATUS_MORE_PROCESSING_REQUIRED;
第三个除了有可能是设备没有完成请求在等待外与第二个相似。


Code 2返回值用STATUS_MORE_PROCESSING_REQUIRED,结果是系统速度变得奇慢无比,只有将设备拔掉。

修改后的Code 3的代码如下:
Read()
{
...
InterlockedIncrement(&dx->PendingIoCount);
EVENT event;
KeInitializeEvent(&event);
IoCopyCurrentIrpStackLocationIrpToNext(Irp);
IoSetCompletionRoutine(ReadCompletion,&event, ...);
Status = IoCallDriver(dx->LowerDeviceObject, Irp);
if (Status == STATUS_PENDING){
KeWaitForSingleObject(event, ...);
}
InterlockedDecrement(&dx->PendingIoCount);
if (dx->PendingIoCount < 0){
    KeSetEvent(&dx->IoCompletionEvent);
}
return Irp->IoStatus.Status;
}

IRP_MJ_PNP [IRP_MN_REMOVE_DEVICE]:
    IoCallDriver(dx->LowerDeviceObject, Irp);   --- (1)
    if (dx->PendingIoCount > 0){
        InterlockedDecrement(&dx->PendingIoCount);
        KeWaitForSingleObject(dx->IoCompletionEvent);
    }
    // Free Memory
    ...
    
    IoDetachDevice(dx->LowerDeviceObject);
    IoDeleteObject(fdo);
    return STATUS_SUCCESS;
}

在执行完语句(1)之后,马上跳到ReadCompletionRoutine中
然后Read函数返回STATUS_DEVICE_NOT_CONNECTED,接着是
IRP_MJ_CLEANUP, IRP_MJ_CLOSE,然后系统在_VWIN32_CloseVxDHandle + 0121处出错。
如果Read函数返回STATUS_SUCCESS,则系统不会出错,但是在游戏控制器中的设备列表中设备不会消除,还是显示连接。再一次插入设备时,再也没有调用Read函数。
驱动人生。
tigerzd
驱动老牛
驱动老牛
  • 注册日期2001-08-25
  • 最后登录2004-12-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-07-22 15:27
这个问题估计就不是Complete Routing的问题了。其实关于PNP_REMOVE_DEVICE的处理,按DDK中BULKUSB或ISOUSB的处理方式做,完全没有问题的。
犯强汉者,虽远必诛! [img]http://www.driverdevelop.com/forum/upload/tigerzd/2002-12-13_sf10.JPG[/img]
Henry
驱动牛犊
驱动牛犊
  • 注册日期2001-04-27
  • 最后登录2011-06-20
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望27点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2002-07-22 20:00
我也是这样想的。不过我实在是按DDK的Filter的例子来的。
也罢,明天再试了之后还有问题再说。不过我还是想不通
Code 1和Code 2有什么不同。
驱动人生。
tigerzd
驱动老牛
驱动老牛
  • 注册日期2001-08-25
  • 最后登录2004-12-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-07-23 08:38
椐DDK所说,1、2的区别就是在能不能设置完成例程上。根据实践,确实也是如此,我认为你的程序问题应该不在这里。
犯强汉者,虽远必诛! [img]http://www.driverdevelop.com/forum/upload/tigerzd/2002-12-13_sf10.JPG[/img]
Henry
驱动牛犊
驱动牛犊
  • 注册日期2001-04-27
  • 最后登录2011-06-20
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望27点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2002-07-23 11:01
按DDK的介绍来说,问题不在这里。
但我重试了好多次,只要一装上CompletionRoutine,就会有问题,
哪怕是在CompletionRoutine中什么也不做。不装就没有问题。
真是搞不懂!再说了,我翻遍了DDK的Help文档也只看到在IoSetCompletionRoutine函数中有提到CompletionRoutine的原型。
对于怎样写CompletionRoutine只字不提。


BTW:哪位好心人可以帮忙试试。
我的FilterDriver安装位置在Enum\\Hid\\VID_XXXX&PID_XXXX\\LowerFilters : \"LowHid.sys\"。
驱动人生。
tigerzd
驱动老牛
驱动老牛
  • 注册日期2001-08-25
  • 最后登录2004-12-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2002-07-23 11:04
CompletionRoutine到DDK的例子中找示例啊。
犯强汉者,虽远必诛! [img]http://www.driverdevelop.com/forum/upload/tigerzd/2002-12-13_sf10.JPG[/img]
aiherong
驱动牛犊
驱动牛犊
  • 注册日期2002-06-07
  • 最后登录2007-01-10
  • 粉丝0
  • 关注0
  • 积分21分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-07-23 11:06
Code 1.If you call IoSkipCurrentIrpStackLocation before calling IoCallDriver, the next-lower driver receives the same IO_STACK_LOCATION that your driver received

Code 2.An IRP passed in a call to IoCallDriver becomes inaccessible to the higher-level driver, unless the higher-level driver has called IoSetCompletionRoutine to set up an IoCompletion routine for the IRP. If it has, the IRP input to the IoCompletion routine has its I/O status block set by the lower drivers, and all lower-level drivers\' I/O stack locations are filled with zeros.

IoCompletion routine too mono,Perhaps be care more.
aiherong
驱动牛犊
驱动牛犊
  • 注册日期2002-06-07
  • 最后登录2007-01-10
  • 粉丝0
  • 关注0
  • 积分21分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2002-07-23 11:19
给个栗子:
NTSTATUS IOCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Context)
{
    if (Irp->PendingReturned) {IoMarkIrpPending(Irp);}
    else
    {
        if (Irp->IoStatus.Status==STATUS_SUCCESS)
        {
// We process only IOCTL_SERIAL_SET_BAUD_RATE and
// IOCTL_SERIAL_SET_LINE_CONTROL requests
// (serial.h file from serial driver
// sample from DDK is used)
            IOReq *req;
            CAttachedDevice *p=(CAttachedDevice *) Context;
            PIO_STACK_LOCATION cur;
            cur = IoGetCurrentIrpStackLocation(Irp);
            switch(
cur->Parameters.DeviceIoControl.IoControlCode)
            {
            case IOCTL_SERIAL_SET_BAUD_RATE:
                req=new (NonPagedPool) IOReq(REQ_SETBAUDRATE,
                    sizeof(ULONG),sizeof(ULONG),
                    Irp->AssociatedIrp.SystemBuffer);
                ((CAttachedDevice *) Context)->New(req);
                break;
            case IOCTL_SERIAL_SET_LINE_CONTROL:
                req=new (NonPagedPool) IOReq(REQ_SETLINECONTROL,
                    sizeof(SERIAL_LINE_CONTROL),
                    sizeof(SERIAL_LINE_CONTROL),
                    Irp->AssociatedIrp.SystemBuffer);
                ((CAttachedDevice *) Context)->New(req);
                break;
            }//switch
        }//if
    }else
    return STATUS_SUCCESS;
}
aiherong
驱动牛犊
驱动牛犊
  • 注册日期2002-06-07
  • 最后登录2007-01-10
  • 粉丝0
  • 关注0
  • 积分21分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2002-07-23 11:23
疏忽了!

}else  =>改为 }//else
return STATUS_SUCCESS;
}

Henry
驱动牛犊
驱动牛犊
  • 注册日期2001-04-27
  • 最后登录2011-06-20
  • 粉丝0
  • 关注0
  • 积分4分
  • 威望27点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2002-07-25 14:42
第二个问题应该是完成例程处理有问题,
其余的不说,返回值用STATUS_MORE_PROCESSING_REQUIRED试试:
return STATUS_MORE_PROCESSING_REQUIRED;
第三个除了有可能是设备没有完成请求在等待外与第二个相似。


Code3改为return STATUS_MORE_PROCESSING_REQUIRED;问题解决了。
前两天试的时候程序太大了,还有其他的一些Bug,所以不成功。
今天将程序提炼了一下,只留下关键代码,问题不再出现。
驱动人生。
游客

返回顶部