阅读:1517回复:15
有请大侠们出手 ,很急的说!
调用iomanager的device queue的程序处理异步I/O,调试时,在问号处出现page fault 0e,为什么??!这个问题困扰了很长时间了,请高手指正:
NTSTATUS DispatchControl(PDEVICE_OBJECT fdo, PIRP Irp) { // DispatchControl PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; NTSTATUS status; ... ... UsbBuildInterruptOrBulkTransferRequest(&urb_1,sizeof(_URB_BULK_OR_INTERRUPT_TRANSFER), pdx->houtpipe, buff,NULL,m_seglen,0,NULL); PIRP Irp_1 = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->LowerDeviceObject, NULL, 0, NULL, 0, TRUE,NULL, NULL); if (!Irp_1) { KdPrint((DRIVERNAME \" - Unable to allocate IRP for sending URB\\n\")); return STATUS_INSUFFICIENT_RESOURCES; } PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp_1); stack->Parameters.Others.Argument1 = (PVOID) &urb_1; IoMarkIrpPending(Irp_1); IoStartPacket(fdo,Irp_1,NULL,OnCancel); status=STATUS_PENDING; return status; } VOID StartIo(IN PDEVICE_OBJECT pdo, IN PIRP Irp) { KIRQL oldirql; NTSTATUS status; IoAcquireCancelSpinLock(&oldirql); if (Irp != pdo->CurrentIrp || Irp->Cancel) { IoReleaseCancelSpinLock(oldirql); return; } else { IoSetCancelRoutine(Irp, NULL); IoReleaseCancelSpinLock(oldirql); } PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) pdo->DeviceExtension; PVOID ctx; IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)OnComplete, (PVOID) ctx, TRUE, FALSE,FALSE); status=IoCallDriver(pdx->LowerDeviceObject, Irp); return; } NTSTATUS OnComplete(PDEVICE_OBJECT pdo, PIRP Irp, PDEVICE_EXTENSION pdx) { LONG m_seglen; URB urb; URB urb_1; KEVENT event; IO_STATUS_BLOCK iostatus; if (Irp->PendingReturned) { IoMarkIrpPending(Irp); } Irp->IoStatus.Status=STATUS_SUCCESS; Irp->IoStatus.Information =pdx->Length; IoStartNextPacket(pdo,TRUE); ------------------??? IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } |
|
沙发#
发布于:2002-06-27 14:34
IoStartNextPacket(pdo,TRUE); ------------------???
IoCompleteRequest(Irp, IO_NO_INCREMENT); 这两句话调个顺序试试 |
|
|
板凳#
发布于:2002-06-27 15:16
感谢回答,不过问题依然.
|
|
地板#
发布于:2002-06-27 17:06
对了
像你这种情况,好像是不能调用 IoCompleteRequest的 |
|
|
地下室#
发布于:2002-06-28 08:03
那怎么做呢?zydcat大侠
|
|
5楼#
发布于:2002-06-28 08:47
这是walter oney的那本书上给的例子,你试试。
中层驱动和底层的完成例程是不一样的 NTSTATUS CompletionRoutine(PDEVICE_OBJECT device, PIRP Irp, PVOID context) { if (Irp->PendingReturned) IoMarkIrpPending(Irp); ... return <some status code>; } |
|
|
6楼#
发布于:2002-06-28 09:08
感谢zydcat大侠的回答.
不过,这是一个usb的驱动程序,iocalldriver调用的是系统总线驱动,应该是底层了吧,我的oncomplete程序就是参考了walt oney的书,现在好像掉到了一个陷阱中,出不来了,还望大侠帮忙. |
|
7楼#
发布于:2002-06-28 09:13
另外,在用softice追时.当进入oncomplete程序时,观察变量fdo,pdx都是一些非法值,我想这就是??句处的错误原因吧,可是又是哪出了问题呢?
|
|
8楼#
发布于:2002-06-28 09:37
不对,
status=IoCallDriver(pdx->LowerDeviceObject, Irp); 这句话表明你还是将Irp传到底层去了,所以这一层不能调用IoCompleteRequest 另外IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)OnComplete, (PVOID) ctx, TRUE, FALSE,FALSE); 的第三个参数应该和OnComplete的第三个参数相同, 这就是你的pdx是非法值得原因, |
|
|
9楼#
发布于:2002-06-28 11:23
进入oncomplete程序中,为何ctx还是为空?难道iocalldriver没有给ctx赋值?不懂不懂.
|
|
10楼#
发布于:2002-06-28 11:31
老大
ctx不是由iocalldriver付值得 他是由你付值得 你想把什么传给oncomplete,就把什么放到IoSetCompletionRoutine的第三个参数上 明白 比如: IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE)OnComplete,(PDEVICE_EXTENSION) pdx , TRUE, FALSE,FALSE) 这时候,在oncomplete的第三个参数就是pdx 你的程序中光定义个cpx空指针,然后又到OnComplete中使用这个空指针,把他当做pdx,当然会出事 |
|
|
11楼#
发布于:2002-06-28 14:38
你的程序好厉害啊!居然能够在STARTIO里面调用IOCALLDRIVER
|
|
12楼#
发布于:2002-06-28 14:42
zydcat大侠,很感谢你的指点.经过调试我发现,在oncomplete程序中,fdo是指irp 这一stack的设备,即usb总线驱动设备,而在iostartnextpacket中,是指此usb设备,因而我用ctx传值过来,应该这样做吗?不是很清楚的问大侠.
|
|
13楼#
发布于:2002-06-28 14:48
guardee大侠,你的意思不很明白,请明确说明好吗?你的意思是不是:startio\'s irql太高,而不能调用irql也很高的iocalldriver?
本人初学,许多问题不清楚,希望大侠指正. |
|
14楼#
发布于:2002-06-28 14:54
zydcat大侠,很感谢你的指点.经过调试我发现,在oncomplete程序中,fdo是指irp 这一stack的设备,即usb总线驱动设备,而在iostartnextpacket中,是指此usb设备,因而我用ctx传值过来,应该这样做吗?不是很清楚的问大侠. 你可以传任何值,但是你在IoSetCompletionRoutine传的什么值,就要在oncomplete中接到同样的值。 说了那么多,其实oncomplete中的第三个参数就是由IoSetCompletionRoutine中的第三个参数付给的 |
|
|
15楼#
发布于:2002-06-28 14:57
你的程序好厉害啊!居然能够在STARTIO里面调用IOCALLDRIVER 这应该没问题吧,startio例程的irql是DISPATCH_LEVEL吧,而IoCallDriver must be running at IRQL <= DISPATCH_LEVEL 应该可以吧,如果不可以早就兰屏了 |
|
|