阅读:2285回复:19
关于IoSetCompletionRoutine,50分!
小弟想做一个包过滤程序,
过滤函数如下: NTSTATUS Pass( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { DbgPrint(\"get Package!!!\\n\"); PIO_STACK_LOCATION pIrpStack; pIrpStack = IoGetCurrentIrpStackLocation( Irp ); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, GenericCompletion, 0, TRUE, TRUE, TRUE ); return IoCallDriver( m_TcpgetDevice, Irp); } NTSTATUS GenericCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { if(Irp->PendingReturned) { IoMarkIrpPending(Irp); } return STATUS_SUCCESS; } 但是发现一个问题,第一次调用IoSetCompletionRoutine没有问题, 当接到第二个irp时,再调用IoSetCompletionRoutine,就会蓝屏, 希望有经验的大虾多指教! 谢谢! |
|
最新喜欢:![]() |
沙发#
发布于:2002-05-23 22:46
猜想可能和IRP的排队有关系吧
不过就这些好像看不出什么问题 看看IoStartNextPacket之类的调用有没有问题 |
|
板凳#
发布于:2002-05-24 08:42
前一个Irp没有完成,当然不能再处理Irp的例程。
在Completion中加入IoCompleteRequest的调用。 |
|
|
地板#
发布于:2002-05-24 09:14
对呀,你自己的完成例程里怎么不调用IoCompleteRequest
你注册了一个回调的完成例程,最主要的就是调用IoCompleteRequest来完成irp的 |
|
|
地下室#
发布于:2002-05-24 09:51
首先非常感谢你们的回复。
但是我试了一下, 将GenericCompletion改成这样。 NTSTATUS GenericCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { IoCompleteRequest(Irp,IO_NO_INCREMENT); return STATUS_SUCCESS; } 但结果还是一样的。。。。。。。。 |
|
5楼#
发布于:2002-05-24 10:07
完成一个IRP必须先填充IoStatus块的Status和Information成员,然后调用IoCompleteRequest例程。Status值就是NTSTATUS.H中定义的状态代码。表5-1简要地列出了常用的状态代码。而Information值要取决于你完成的是何种类型的IRP以及是成功还是失败。通常情况下,如果IRP完成失败(即,完成的结果是某种错误状态),你应把Information域置0。如果你成功地完成了一个数据传输IRP,通常应该把Information域设置成传输的字节量。
NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS status, ULONG_PTR Information) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = Information; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } |
|
|
6楼#
发布于:2002-05-24 10:26
谢谢,这位大哥如此热心小弟感激涕零。。。。。
我按照你说的填充了information和status NTSTATUS GenericCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } 但执行到IoSetCompletionRoutine还是出错。。。。。唉。。。苦 |
|
7楼#
发布于:2002-05-24 10:32
以下是全部代码,很短,可否请各位大哥帮忙分析一下IoSetCompletionRoutine出错的原因,小弟先行谢过了。
#include \"PassThrough.h\" ///////////////////////////////////////////////////////////////////////////// PDEVICE_OBJECT phddo = NULL; PDEVICE_OBJECT m_TcpgetDevice; PDEVICE_OBJECT TcpDevice; ///////////////////////////////////////////////////////////////////////////// #pragma code_seg(\"INIT\") // start INIT section ///////////////////////////////////////////////////////////////////////////// // DriverEntry: // extern \"C\" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNICODE_STRING TcpDeviceName; PDRIVER_OBJECT TcpDriver; PDEVICE_OBJECT TcpgetDevice; PDRIVER_DISPATCH Empty; NTSTATUS status; PFILE_OBJECT FileObject; int i = 0; DriverObject->DriverUnload = PassThroughUnload; Empty = DriverObject->MajorFunction[IRP_MJ_CREATE]; RtlInitUnicodeString( &TcpDeviceName, L\"\\\\Device\\\\Tcp\"); status = IoGetDeviceObjectPointer( &TcpDeviceName, FILE_ALL_ACCESS, &FileObject, &TcpDevice ); if(!NT_SUCCESS(status)) { DbgPrint(\"IoGetDeviceObjectPointer error!\\n\"); return status; } DbgPrint(\"IoGetDeviceObjectPointer ok!\\n\"); status = IoCreateDevice( DriverObject, sizeof(PHDIO_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &phddo ); if(!NT_SUCCESS(status)) { return status; } TcpgetDevice = IoAttachDeviceToDeviceStack( phddo, TcpDevice); if(!TcpgetDevice) { IoDeleteDevice(phddo); DbgPrint(\"IoAttachDeviceToDeviceStack error!\\n\"); return STATUS_SUCCESS; } m_TcpgetDevice = TcpgetDevice; TcpDriver = TcpgetDevice->DriverObject; for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++) { if((TcpDriver->MajorFunction!=Empty)&&(DriverObject->MajorFunction==Empty)) { DriverObject->MajorFunction = Pass; } } ObDereferenceObject(FileObject); return status; } NTSTATUS Pass( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { DbgPrint(\"get Package!!!\\n\"); PIO_STACK_LOCATION pIrpStack; pIrpStack = IoGetCurrentIrpStackLocation( Irp ); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, GenericCompletion, NULL, TRUE, TRUE, TRUE ); return IoCallDriver( m_TcpgetDevice, Irp); } NTSTATUS GenericCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) { //if(Irp->PendingReturned) //{ // IoMarkIrpPending(Irp); //} Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } //////////////////////////////////////////////////////////////////////////// // PassThoughUnload // // Description: // Unload the driver by removing any remaining objects, etc. // // Arguments: // Pointer to the Driver object // // Return Value: // None #pragma code_seg(\"PAGE\") // start PAGE section VOID PassThroughUnload(IN PDRIVER_OBJECT DriverObject) { IoDetachDevice(TcpDevice); IoDeleteDevice(phddo); DbgPrint(\"Driver Unload Success completed\\n\"); } ////////////////////////////////////////////////////////////////////////////// |
|
8楼#
发布于:2002-05-24 10:36
呵呵!他们告诉你的是错误的,你的完成例程里面估计是因为你的返回值有错误,可能是下层驱动程序还没有完成该IRP,而你却返回成功,你应该返回的是Irp->IoStatus.Status,因为下层驱动程序对该IRP的处理状态放在这里了!对于不想下发该IRP的话,那么是可以这样完成该IRP的
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; 该代码就是把该请求的IRP完成了,也不把IRP下发到下一层驱动程序了! |
|
9楼#
发布于:2002-05-24 10:39
我也写过filter driver,它的pass 和completion部分基本和你相同,没有什么问题,我估计可能是你其它部分有点问题:)
|
|
10楼#
发布于:2002-05-24 11:01
、、、、、、、、、、、、、、、、、
for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++) { if((TcpDriver->MajorFunction!=Empty)&&(DriverObject->MajorFunction==Empty)) { DriverObject->MajorFunction = Pass; } } 、、、、、、、、、、、、、、、、、、、、、 是不是有问题,显然是要对MajorFunction数组操作的 for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++) { if((TcpDriver->MajorFunction!=Empty)&&(DriverObject->MajorFunction==Empty)) { DriverObject->MajorFunction = Pass; } } |
|
|
11楼#
发布于:2002-05-24 11:02
首先非常感谢你们的回复。 在你的完成例程中不应该加入IoCompleteRequest。因为此IRP处理不是你来做的,IoCompleteRequest应该由下层来调用。 此外,将黑体部分改成FALSE。 IoSetCompletionRoutine( Irp, GenericCompletion, NULL, TRUE, TRUE, TRUE ); |
|
|
12楼#
发布于:2002-05-24 11:04
糟糕,没改掉
应该是: for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++) { if((TcpDriver->MajorFunction!=Empty)&&(DriverObject->MajorFunction==Empty)) { DriverObject->MajorFunction = Pass; } } |
|
|
13楼#
发布于:2002-05-24 11:08
faint
怎么回事 非得让我敲进去 应该是MajorFuntion |
|
|
14楼#
发布于:2002-05-24 11:10
明白了,数组下标显示不出来
算了。 |
|
|
15楼#
发布于:2002-05-24 11:51
在你的完成例程中不应该加入IoCompleteRequest。因为此IRP处理不是你来做的,IoCompleteRequest应该由下层来调用。 这个irp又不是它自己创建的,也是由上层传下来的,当然要调用IoCompleteRequest |
|
|
16楼#
发布于:2002-05-24 12:36
[quote] 在你的完成例程中不应该加入IoCompleteRequest。因为此IRP处理不是你来做的,IoCompleteRequest应该由下层来调用。 这个irp又不是它自己创建的,也是由上层传下来的,当然要调用IoCompleteRequest [/quote] 你的完成例程为什么会被调用?是因为下层driver将它完成了,因而你有必要再IoCompleteRequest吗? |
|
|
17楼#
发布于:2002-05-24 12:44
返回值改为STATUS_MORE_PROCESSING_REQUIRED试试。
|
|
|
18楼#
发布于:2002-05-24 12:50
引用: 你如果不调用IoCompleteRequest,你的上层驱动程序怎么办,它什么时候调用他的完成例程 |
|
|
19楼#
发布于:2002-05-24 13:58
终于解决了,原来是#pragma code_seg(\"PAGE\")
的问题,删掉就没事了。。。。 多谢大家! 真想给你们每个人100分,可惜我分数没那么多:( |
|