macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
阅读:1640回复:11

搞不定呀。

楼主#
更多 发布于:2002-04-08 10:34
用户被禁言,该主题自动屏蔽!

最新喜欢:

flyfoxflyfox
guardee
驱动巨牛
驱动巨牛
  • 注册日期2002-11-08
  • 最后登录2010-05-29
  • 粉丝2
  • 关注1
  • 积分2分
  • 威望34点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-04-08 10:40
IoCallDriver(nextIrpStack,Irp);
第一个参数不对啊!
macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2002-04-08 12:42
用户被禁言,该主题自动屏蔽!
guardee
驱动巨牛
驱动巨牛
  • 注册日期2002-11-08
  • 最后登录2010-05-29
  • 粉丝2
  • 关注1
  • 积分2分
  • 威望34点
  • 贡献值0点
  • 好评度6点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-04-08 13:08
这个也不对,在调用这个函数的时候传进了两个参数,
第一个是设备对象指针,
第二个是请求包指针,
而IOCALLDRIVER也需要这两个参数啦!
传进这个函数的两个参数中,二个都要自己添写,其中,IRP可以直接向下发,而设备对象却要传进过滤设备对象的下一层设备对象
例子里面的应该是对的啊!
macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
地下室#
发布于:2002-04-08 13:25
用户被禁言,该主题自动屏蔽!
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2002-04-08 13:46
在FilemonHookRoutine例程里:
case IRP_MJ_READ:
if(是我的目录)
{
IoSetCompletionRoutine(Irp,ReadCompleted,NULL,TRUE,TRUE,TRUE);
IoCallDriver(nextIrpStack,Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}

ReadCompleted(...)
{
PCHAR pContext=Irp->AssociatedIrp.SystemBuffer;
DbgPrint((\"内容: %s\\n\",pContext));
if( Irp->PendingReturned ) {
   IoMarkIrpPending( Irp );
  }
  return Irp->IoStatus.Status;
}
刚进ReadCompleted就会兰屏。
为什么?


有两点需要注意:
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 !
Tom_lyd
macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
6楼#
发布于:2002-04-08 14:19
用户被禁言,该主题自动屏蔽!
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
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 !
Tom_lyd
Tom_lyd
驱动大牛
驱动大牛
  • 注册日期2001-09-02
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望1点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2002-04-08 15:38
我的目的是想知道读写文件的文件内容在那。还有几个问题:
1)这个IoCompletion例程有什么用?
2)这里构造一个IRP有什么用?
3)IoCompletion是什么时候运行的?它是一个线程?在IoSetCompletionRoutine时就开始运行?
4)IRQ级别不同,对程序有什么影响?就是为什么要分不同情况处理。
sorry,比较菜,早两三天问过了,还有很多没搞懂。

刚刚回答不完整,很抱歉,特补充如下:
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级别,在这样的级别里,是不允许访问分页内存的。


Tom_lyd
macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
9楼#
发布于:2002-04-09 12:32
用户被禁言,该主题自动屏蔽!
Tom.Cat
禁止发言
禁止发言
  • 注册日期2001-10-10
  • 最后登录2019-07-29
  • 粉丝1
  • 关注0
  • 积分-53792分
  • 威望197411点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
  • 社区居民
10楼#
发布于:2002-04-09 16:14
用户被禁言,该主题自动屏蔽!
macy
禁止发言
禁止发言
  • 注册日期2001-12-19
  • 最后登录2018-06-02
  • 粉丝0
  • 关注0
  • 积分6383分
  • 威望48270点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
11楼#
发布于:2002-04-09 16:26
用户被禁言,该主题自动屏蔽!
游客

返回顶部