阅读:1794回复:11
清斑竹和大虾们关注(50分):
一个值得讨论的问题:
请问下面三段代码在上层驱动程序看来有什么不同? 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在突然拔出设备时死机。 请大虾们帮忙想想,我已经被这个问题困扰了两个星期了。 |
|
|
沙发#
发布于:2002-07-22 12:11
第二个问题应该是完成例程处理有问题,
其余的不说,返回值用STATUS_MORE_PROCESSING_REQUIRED试试: return STATUS_MORE_PROCESSING_REQUIRED; 第三个除了有可能是设备没有完成请求在等待外与第二个相似。 |
|
|
板凳#
发布于:2002-07-22 14:30
第二个问题应该是完成例程处理有问题, 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函数。 |
|
|
地板#
发布于:2002-07-22 15:27
这个问题估计就不是Complete Routing的问题了。其实关于PNP_REMOVE_DEVICE的处理,按DDK中BULKUSB或ISOUSB的处理方式做,完全没有问题的。
|
|
|
地下室#
发布于:2002-07-22 20:00
我也是这样想的。不过我实在是按DDK的Filter的例子来的。
也罢,明天再试了之后还有问题再说。不过我还是想不通 Code 1和Code 2有什么不同。 |
|
|
5楼#
发布于:2002-07-23 08:38
椐DDK所说,1、2的区别就是在能不能设置完成例程上。根据实践,确实也是如此,我认为你的程序问题应该不在这里。
|
|
|
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\"。 |
|
|
7楼#
发布于:2002-07-23 11:04
CompletionRoutine到DDK的例子中找示例啊。
|
|
|
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. |
|
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; } |
|
10楼#
发布于:2002-07-23 11:23
疏忽了!
}else =>改为 }//else return STATUS_SUCCESS; } |
|
11楼#
发布于:2002-07-25 14:42
第二个问题应该是完成例程处理有问题, Code3改为return STATUS_MORE_PROCESSING_REQUIRED;问题解决了。 前两天试的时候程序太大了,还有其他的一些Bug,所以不成功。 今天将程序提炼了一下,只留下关键代码,问题不再出现。 |
|
|