前置知识:http://www.codemachine.com/article_tdi.html
创建socket的过程从ring3到AFD,基本是老样子。
在到达AfdCreate后,会有不同的分支
根据RING3传下来的EA,里面不同的变量判断,就跳转不同的分支。
1。默认分支
默认里面会调用
AfdCheckTDIFilter()
该函数检测 tcp/udp/rawip/tcp6/udp6/rawip6这6个设备是否有attached的设备
如果有则返回1,返回0的话,AfdCreate函数就接着调用AfdAllocateEndpoint创建ENDPOINT
2。第二个分支
上面AfdCheckTDIFilter函数返回1后,AfdCreate会返回一个错误码STATUS_MEDIA_CHANGED,回到应用层后,mssocket模块重新调用WsaSocket()创建socket。但这回EA不同,会跳转到第二个分支。
这个分支里面就是直接调用AfdAllocateEndpoint创建ENDPOINT
2个分支都调用了AfdAllocateEndpoint,那有什么不同?
不同是在AfdAllocateEndpoint这个函数里面。
AfdAllocateEndpoint函数有一个参数是传进TransportDeviceName的
在第一个分支里面TransportDeviceName参数为空
这样初始化_AFd_Endpoint结构的时候,就根据不同的情况初始化不同的字段值了。
如TransportDeviceName为这空,说明是没有tdi过滤驱动attach的情况,这时候是直接afd到tcpip路线(尼玛的,性感路线)
稍微看了下这里是怎么直接关联tcpip的。
在TransportDeviceName为空情况下的初始化是直接把tcpip驱动提供的一些回调函数设置到afd_endpoint结构里面,以后就可以直接调用了。
那这个回调函数怎么设置过来给afd驱动的呢?大致看了下,好像是
afd驱动调用netio!NmrRegisterProvider的注册函数,把自己的一外链表头注册进去。
估计是netio模块会tcpip的回调函数设置到这个链表里面(没空看了)
afd!AfdAllocateEndpoint()函数创建endpoint的时候,调用AfdTlFindAndReferenceTransport根据socket的地址,协议等属性找到特定的数据来填充endpoint结构
tcpip的回调函数所在的结构就是AfdTlFindAndReferenceTransport函数返回的。
完。
PS:上面提到afdcreate中判断变量是EA的 afd_open_packet->TransportDeviceNameLength
AfdAllocateEndpoint中判断的名字来源就是afd_open_packet->TransportDeviceName;
这个名字是device\udp这个格式
另外发现有个强大的字段IgnoreTDI。大家自己搜索吧