阅读:3882回复:12
请教TDI_CONNECT和TDI_ACCEPT的阻断
拜读了
http://www.driverdevelop.com/forum/viewthread.php?tid=59907#pid479904 文章中所说的TDI_CONNECT和TDI_ACCEPT的阻断,可是不明白具体如何实现。我不知道TDI_CONNECT和TDI_ACCEPT阻断的IRP的处理过程,特来请教大虾。 不知道上面帖子的两位当事人gjpland 还有allendeng还过来吗?也请教其他的所有大虾。 |
|
沙发#
发布于:2005-05-13 11:39
板主monkey? 你能告诉我答案吗? 好象点击此贴的人也不多, 版面上人气不太足哦 |
|
板凳#
发布于:2005-05-14 22:55
受到该请求,向应用发通知,等待上层应用程序返回,继续执行
|
|
|
地板#
发布于:2005-05-15 09:24
受到该请求,向应用发通知,等待上层应用程序返回,继续执行 谢谢lifeship,可是我还是不明白,这个过程难道不需要pending(irp)? 直接加上向应用程序的通知?然后WaitForSingleObject(appDlgEvent)? 从 http://www.driverdevelop.com/forum/viewthread.php?tid=59907#pid479904 ,以及您的回答上看,好象是和IRQL有关系,如果是在较高的IRQL上,就不需要pending(irp),是这样的吗?能给个参考文章吗? |
|
地下室#
发布于:2005-05-15 14:41
对于tdi_connect,简单的KeWaitForSingleObjec将irp pending 就可以了,没有什么可说的
但对于进来的连接,就没有这么简单了。 当tcp 收到syn包的时候,会调用tdi client注册的函数 ClientEventHandler, 这时候<=DPC level,不能pending, ClienEventHandler会建立一个AcceptIrp,传回给tcp,并注册一个 完成函数,当tcp完成三次握手的时候,会调用这个完成函数, 完成函数级别<=DPC level,也不能pending. gjpland 提到这个tdi_accept的irp完成的时候,pending,但是这个 irp并不是象一般的irp那样调用IoCalldriver 调用的, 而是在ClientEventHandler里面直接传给tcp driver,我们无法pending 不知道allendeng是如何pending的? 一般的结论,这种情况是不能pending,奇怪他们是如何做到的 |
|
5楼#
发布于:2005-05-15 21:40
首先谢谢zhaock的指点,我希望能继续讨论下去 :) btw:我想给这个帖子更多的分,可是修改分数的时候,最大可给分20分。发帖子的时候最高只能设定20分, :P
对于tdi_connect,简单的KeWaitForSingleObjec将irp pending 就可以了,没有什么可说的 我的理解是这样的,不知道对不对: int tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) { // do sth. if ( !rule_check( ) ) //未通过规则检查,弹出应用程序对话框,允许用户选择 { SetEvent( appDlgEvent ); //通知应用程序,WaitForSingleObject( appDlgEvent ); Pending( irp ); // ??? 需要吗 ??? //用户回答对话框后通知这里继续进行 keWaitForSingleObject( appDlgResponseEvent ); … …//处理用户返回的选择 switch appDlgResult : { case pass_for_ever: //放行,并添加规则 AddRule(); irp->IoStatus.Status = STATUS_SUCCESS; Break: Case pass_this_time: //放行 irp->IoStatus.Status = STATUS_SUCCESS; Break: Case deny: //丢弃 irp->IoStatus.Status = STATUS_CONNECTION_REFUSED; Break; } } //do otherthing,for exmaple ,set complete routine, etc. return result; } 但对于进来的连接,就没有这么简单了。 上面这些有出处没有?我想研究研究。我对gjpland说啊的理解是,z在tdi_accept_complete例程中进行pending 就可以了。 希望继续指点,直到这个问题答案变的非常清晰易懂。 |
|
6楼#
发布于:2005-05-16 09:53
你对tdi_connect的处理,是完全正确的.
<<在tdi_accept_complete例程中进行pending 就可以了 因为级别<=dpc level,是不能够pending的。 而gjpland说的对tdi_accept的pending,我认为尚没有说清楚, 但不知道allendeng是如何实现了的。 希望能把这个问题彻底讨论清楚。 |
|
7楼#
发布于:2005-05-17 05:32
我也很想知道. 哪位高手出来进一步说一下?
楼上那位说的dpc level 是指DISPATCH_LEVEL吗? 好象tdi_connect也是DISPATCH_LEVEL的, 不敢肯定,明日跟踪一下. 这是个普遍的问题, 无论是以TDI或NDIS为技术的包拦截, 都存在这个与应用程序打交道的等待问题. 网上有人说keWaitForSingleObject好象不是合适的方法, 要用 IoMarkIrpPending来悬挂IRP不进一步处理.可惜也是点到为止, 没有代码片段. 我还在瞎试, 有结果一定通知大家. 要是谁知道, 请告诉一声,我愿意给分. |
|
8楼#
发布于:2005-05-17 09:45
我也很想知道. 哪位高手出来进一步说一下? 等待中,看来我也应该学会调试 :-( 自己再找时间学好了。 我瞎猜,是不是这些技术属于核心机密啊,呵呵,要不怎么没有过来人清楚明白的说出来呢? |
|
9楼#
发布于:2005-05-17 10:10
dpc level就是dispatch level.
tdi_connect是在passive level. 谈不到,属于核心机密,都是做windows驱动一些基本的概念 但对于ClientEventHandler,从理论上讲因为是在dpc level,不能挂住。 gjpland 所说的过于简单,我没有搞清楚具体是如何实现的, 有这么做成功的朋友欢迎来指教一二 |
|
10楼#
发布于:2005-05-17 13:17
pending 的意思不是blocking,就是该irp不再处理了,等到某个合适的时候,有你的驱动再来完成它。
将一个irp pending的方法是这样的,在该irp的dispatch例程必须返回status_pending,这样该irp就pending住了(发出这个irp请求的线程会根据该请求时要求同步完成还是异步完成做出不同操作,要求同步,将在某个事件上等待该irp的完成),某个合适的时候,你可以调用iocompleterequest完成该irp。在完成的过程中,上层驱动程序可以继续通过在完成例程中返回_MORE_PROCESSING_REQUIRED 继续pending,这时候pending该irp的驱动有责任在某个时候来调用iocompeterequest来完成该irp,这里可以放到系统线程里去执行,这样将会成功的从dpc level调到了passive level。 但对于这里的情况,我试验失败了,理论上讲,这里的accept irp不是通过iocalldriver传下去的,而是直接通过回调函数传递给协议驱动,你可以发现你的dispatch例程是没有被调用的,但是完成例程得到了调用,所以,协议驱动应该对该irp调用了iocompleterequest,你可以成功的pending 住该irp,但不知道协议是通过什么来判断他是否成功的,以及协议驱动在调用完成后怎么处理该irp,所以也就无法控制其行为了。(理论上讲,他应该负责清理该irp,并产生一个apc,来通知上层调用accept的程序accept成功。这里实际上是做了很大一部分正常情况io manager的工作。),由于协议驱动可能在iocompleterequest返回后,做一些irp的清理工作(例如,释放该irp内存),所以,你虽然pending 住了该irp,但你在随后的处理中(例如一个workitem历程中处理),访问了该irp的内容,可能将会crash(我crash了:() |
|
|
11楼#
发布于:2005-05-17 14:55
pending 的意思不是blocking,就是该irp不再处理了,等到某个合适的时候,有你的驱动再来完成它。 我把pending理解成block了,看了你的解释,是应该可以实现对 tdi_accept的block的,类似于tdi_connect,我想allendeng也是这么 实现的。 但你下面的一些描述我认为不准确 协议驱动(tdi server,一般是tcp )调用iocompleterequest,这时候我们确实可以pending住,返回MORE_PROCESSING_REQUIRED,这个时候我们安排一个apc,去通知我们的应用程序,去让用户确认,在返回后我们的驱动再调用iocompleterequest 往上传到tdi client 。对accept irp的清理工作,并不是协议驱动做的,而应该是上层的tdi client来做的,accetp irp也是由它分配的,一般情况下,是afd,由于我们一直还没有返回,它也不会去释放这个irp,这个时候我们访问这个irp不会有问题.当我们驱动调用iocompleterequest时候 它才会释放掉这个irp 但tcp调用iocompleterequest,尽管被我们pending住了,我的理解这个时候从tcp协议的角度讲,这个连接已经建立了。 不知道我们这个时候返回拒绝,tdi client是不是会发送disconnect 到tcp通知断开这个连接。需要进一步测试一下。 但我认为不会出现你说的crash. 这是我的理解,请指正 |
|
12楼#
发布于:2005-05-26 15:07
同意,不知道兄台的测试结果出来了没有 |
|