阅读:1641回复:11
搞不定呀。用户被禁言,该主题自动屏蔽! |
|
最新喜欢:flyfox |
沙发#
发布于:2002-04-08 10:40
IoCallDriver(nextIrpStack,Irp);
第一个参数不对啊! |
|
板凳#
发布于:2002-04-08 12:42
用户被禁言,该主题自动屏蔽! |
|
地板#
发布于:2002-04-08 13:08
这个也不对,在调用这个函数的时候传进了两个参数,
第一个是设备对象指针, 第二个是请求包指针, 而IOCALLDRIVER也需要这两个参数啦! 传进这个函数的两个参数中,二个都要自己添写,其中,IRP可以直接向下发,而设备对象却要传进过滤设备对象的下一层设备对象 例子里面的应该是对的啊! |
|
地下室#
发布于:2002-04-08 13:25
用户被禁言,该主题自动屏蔽! |
|
5楼#
发布于:2002-04-08 13:46
在FilemonHookRoutine例程里: 有两点需要注意: 1.IoCallDriver(PDEVICE_OBJECT pLowerDevice, PIRP pIrp) IoCallDriver中的第一个参数是设备栈中的下一个设备对象指针。在FILE Monitor中存在于设备扩展中的FileSystem域中,所以第一个参数设为HookExt->FileSystem是对的,不用改;第二个参数是当前你构造的IRP:这里你千万要注意,如果你要调用下一层驱动程序,必须设置正确它的IRP栈,即: PIRP MyIrp=IoAllocateIrp(...) PIO_STACK_LOCATION nextIrp=GetNextIrpStackLocation(pIrp); IO_STATUS_BLOCK IoStatusBlock; //set main body of your own irp Myirp->AssociatedIrp.SystemBuffer = your buffer Myirp->UserEvent = your event objecdt Myirp->UserIosb = &IoStatusBlock; Myirp->Tail.Overlay.Thread = PsGetCurrentThread(); Myirp->Tail.Overlay.OriginalFileObject = FileObject; Myirp->RequestorMode = KernelMode; Myirp->Flags = 0; // Set up the I/O stack location.then nextstackLocation = IoGetNextIrpStackLocation(Myirp); nextStackLocation->MajorFunction = your Major function,such as IRP_MJ_READ; nextstackLocation->DeviceObject = DeviceObject; nextackLocation->FileObject = FileObject; ioStackLocation->Parameters.Read.Length = your buffer length // Set the completion routine. IoSetCompletionRoutine(Myirp, CompleteRead, 0, TRUE, TRUE, TRUE); (void) IoCallDriver(DeviceObject, irp);//千万注意,这里的DeviceObject是下一层设备对象。不是当前的设备对象,你可以通过IoGetDeviceObjectByPointer 或者IoGetRelatedDeviceObject得到这一个设备对象,然后将它保存在设备扩展中,File monitor就是这样做的。 // Wait for the I/O KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); return NT_SUCCESS( IoStatusBlock.Status );//最好不要这样:return MyIrp->IoStats.Status,因为IRP可能已经被完成例程释放。 } 2.第二个问题,在你的完成例程里,需要注意IRQL的问题,完成例程运行在低级驱动程序的线程环境中,因此它的IRQL只可能比你的驱动程序的IRQL级别高(一般来说都为DISPATCH_LEVEL),因此你可以这样来试试: if( KeGetCurrentIrql() == DISPATCH_LEVEL ) { //do some work } else { //not do some work } Best regards ! |
|
|
6楼#
发布于:2002-04-08 14:19
用户被禁言,该主题自动屏蔽! |
|
7楼#
发布于:2002-04-08 14:56
是这样的,当你需要在你的驱动程序中调用别的驱动程序时,一般的步骤都是先为你要调用的驱动程序构造好一个IRP,包括头部和堆栈。不过在你的这个程序中,你的设备对象本身处在这个栈中,因此你也可以不重新构造IRP,而只需正确下一层的IRP栈(这是必须的),因为I/O Manager当初将一个IRP传到这个设备栈的顶端的时候,只初始好了第一个IRP Stack Location,剩下的都需要用户去初始化。如果你不需要什么特殊的处理,你可以仅仅作这一个调用:
IoCopyCurrentIrpStackLocationToNext(pIrp)。具体的可以参阅 Art Baker Jerry Lozano的《Windows 2000设备驱动程序设计指南》第15章分层驱动程序的设计。 完成例程的作用当然是查看执行IRP_MJ_READ被目标驱动程序执行完后返回的文件内容(你不是想这样吗?),否则的话,目标驱动程序执行完IRP后,立即返回给I/O Manager,你哪里还有机会看读出的内容?所以设置完成例程是必须的。至于你说的执行到完成例程就蓝屏,很有可能是你当初的IRP栈没有设置妥当。另外,你千万要记住,不要试图在完成例程中访问分页内存。 Best regards ! |
|
|
8楼#
发布于:2002-04-08 15:38
我的目的是想知道读写文件的文件内容在那。还有几个问题: 刚刚回答不完整,很抱歉,特补充如下: 1)这个IoCompletion例程有什么用? IO完成例的作用刚刚已经说了,是为了在下层驱动程序完成指定的IRP时你还有机会接管IRP的后续处理,还能查看IRP的一些信息,能查看下层驱动程序处理的结果和返回的数据(在IRP返回给IO管理器或应用程序之前),如果你没有IO完成例程,你便失去了这样的一切机会。IO完成例程是可选的。 2)这里构造一个IRP有什么用? 这个问题刚刚已经回答过。 3)IoCompletion是什么时候运行的?它是一个线程?在IoSetCompletionRoutine时就开始运行? IO完成例是在下层驱动程序或目标驱动程序返回给设置IO管理器前被调用的,也就是在IRP被其处理完成时立即调用的一个例程;它运行在低层驱动程序的线程环境(这里的线程并非Win32的线程,但可以理解为系统线程,至少它是通过回调的方式调用的);它在IoSetCompletionRoutine时只是给下层驱动程序传递了它的地址,这时不运行,直到IPR被下层驱动程序处理完成时才激活。 4)IRQ级别不同,对程序有什么影响?就是为什么要分不同情况处理。 刚刚说过,IO完成例程运行在下层驱动程序的线程环境,因此它的IRQL一定比本身驱动程序的级别高,一般都是DISPATCH_LEVEL级别,在这样的级别里,是不允许访问分页内存的。 |
|
|
9楼#
发布于:2002-04-09 12:32
用户被禁言,该主题自动屏蔽! |
|
10楼#
发布于:2002-04-09 16:14
用户被禁言,该主题自动屏蔽! |
|
11楼#
发布于:2002-04-09 16:26
用户被禁言,该主题自动屏蔽! |
|