一个大多数人写过滤驱动都存在的问题

就凑合写写,凑合看看吧

 

写过滤驱动的时候,一般有一个这样的需要,

在过滤某个请求request1的时候,进入到过滤的dispatch1函数,此时,我们需要发送IRP查询某些信息,但这些信息需要在request1完成后才能查询得到。

于是常见的会有2种写法:

第一种:

CompleteRoutine(context)

{

KeSetEvent(&context->NoticEvent, IO_NO_INCREMENT, FALSE);

return STATUS_MORE_PROCESSING_REQUIRED;

}

///

dispatch1(irp)

{

IO_STATUS_BLOCK ioStatusBlock;

IoSetCompletionRoutine( Irp, CompleteRoutine, (PVOID)context, TRUE, TRUE, TRUE );

iocallDriver(NextDevice, irp);

KeWaitForSingleObject(&context->NoticEvent)

 

queryIrp = TdiBuildInternalDeviceControlIrp( TDI_QUERY_INFORMATION, 

NextDeviceObject, 
irps->FileObject, 
NULL, 
&ioStatusBlock 
);

iocallDriver(queryIrp)

}

 

=================================

CompleteRoutine2(context)

{

.....

iocallDriver(queryIrp)

.....

}

 

第二种写法:

dispatch1(irp)

{

IO_STATUS_BLOCK ioStatusBlock;

 

queryIrp = TdiBuildInternalDeviceControlIrp( TDI_QUERY_INFORMATION, 

NextDeviceObject, 
irps->FileObject, 
NULL, 
&ioStatusBlock 
);

IoSetCompletionRoutine( Irp, CompleteRoutine2, (PVOID)context, TRUE, TRUE, TRUE );

iocallDriver(NextDevice, irp);

}

2种方法的代码大概如上,它们的区别主要是发起queryIrp的不同位置,第一种是直接在dispatch1中发起,第二种则是在完成例程中发起(不少网上流传的代码是这样)。

在极端的情况下会发生严重的后果,这个严重的情况就是当上面的第二种情况涉及到3条线程的时候则会出现。哪3条线程呢?

第1条:dispatch1()这个原始的请求线程

第2条:CompleteRoutine2(),当request1被异步完成时,那CompleteRoutine2就是在第2条线程中被调用的

第3条:在CompleteRoutine2()中发起queryIRP,当queryIrp这个IRP被异步完成时,则会IoCompleteRequest(queryIRP)的调用者是第3条线程

在上面情况发生时,第3条线程是Io manager在处理,它会使用special apc来完成,这个special apc的执行环境会回到第2条线程中执行,这时会把结果拷到当初建立的queryIrp 的ioStatusBlock 结构中

但如果这时候线程1,已经返回或者退出了的话,那这个ioStatusBlock 就很危险了,因为当初的ioStatusBlock 是在第1条线程栈中的,special apc 拷结果的时候,也许ioStatusBlock 的地址是新起线程的栈(第1条线程退出),

或者还是线程1的其它函数的栈。发生这种情况就会发现蓝屏的原因不知道为什么栈上的数据被改了,原因很难查明,特别还不是必现的!

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/kkindof/p/3597301.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值