阅读:7009回复:25
圣诞礼物-中间层驱动的工作原理在我刚接触NDIS的时候,在本论坛受益匪浅,现在将中间层驱动的一些看法写出来,给新学习NDIS的一点点方向,希望大家多提批评意见。 由于有些图,所以只能用附件了 |
|
|
沙发#
发布于:2004-12-27 15:30
咋不能下载呢?
|
|
板凳#
发布于:2004-12-27 18:33
上传了DOC老是不能下载,只能把图该为文本了,真的对不起,如果谁需要给我发MAIL把。
中间层驱动工作原理 作者:noble 联系方式:noble _shi @21cn.com 本文如有错误,请联系作者,谢谢。 (1)注册表常识: 1)、设备数据库所在的注册表健值为: HKLMSYSTEMCurrentControlSetEnum ENUM子项中是一个设备数据库,在数据库存放计算机中所有安装的,并且被系统认识到的设备。 所有的用户(包括管理员)都不能更改ENUM项的内容。这是为了保护操作系统和安装的设备的完整性。为了更改设备的设置,应该使用“设备管理器”。 为了在设备管理器中现实隐藏的,非即插即用的,以及没有连接到计算机上的所有设备,你应该首先在命令解释器中敲入命令set DEVMGR_SHOW_NONPRESENT_DEVICES=1,然后启动设备管理器,就可以在设备管理器中删除和重新配置这些设备了。 2)、硬件设备类所在的注册表健值为: HKLMSYSTEMCurrentControlSetControlClass Class项下存放硬件设备类的配置信息。在Class项下的每个子项都代表一个设备类,子项的名称使用“唯一全局标识符(GUIS)”,这些标识符存放该设备类的配置信息。在每个类标识符下,还会有以4位数命名的子项,他们代表该设备类里的具体设备,其他的配置数据只应用于该具体设备。 如网卡的设备类是{4D36E972-E325-11CE-BFC1-08002BE10318},并假定我们网卡对应的4为数命名子项名为0005。 其中 HKLMSYSTEMCurrentControlSetClass{4D36E972-E325-11CE-BFC1-08002BE10318}\ 05Linkage 中: Export:代表该设备在设备名字空间输出的设备名字。 RootDevice:代表当前设备的GUID。中间层驱动这里有两个GUID,第一个是自己的GUID,第二个是该中间层驱动绑定的下层MINIPORT的GUID。 UpperBind:代表上层绑定它的NDIS协议驱动或NDIS中间层驱动。当某个协议驱动绑定该MINIPORT设备时,则这个协议驱动的名字必须出现在UpperBind健值的字符串中,否则不能进行绑定。也就是说,UpperBind健值的字符串决定了那个协议驱动(当然也包括中间层驱动注册的协议)和当前的MINIPORT设备绑定,即,它决定了NDIS的上下层绑定关系。 注:一般添加中间层驱动后,中间层驱动只插入到真是网卡和相应协议中间,不会插入到虚拟网卡(如安装虚拟机后虚拟出来的网卡设备)和相应协议中间。 3)、驱动程序所在的注册表健值为: HKLMSYSTEMCurrentControlSetServices ENUM子项 通常如果某个服务下存在ENUM子项,表明该服务是用来控制某个设备或者设备交互的,它的下面存放该设备的实例。用户不要去试图修改该子项的内容,因为每次系统启动时,都会重写该子项的内容。 LINKAGE子项 值项Bind 存放该协议所在绑定栈的最低层小端口设备实例(即MINIPORT)。 值项Export 存放该服务必须访问的对象,该对象必须已经安装在系统中,并且该服务能够使用。 值项Route 指定子项Linkage从那里获取绑定数据。 Parameters Adapters子项 这里,我们只解释中间层驱动中该子项的意义。为此,我们假设当前我们讨论的HKLMSYSTEMCurrentControlSetServicesXXXX中的XXXX为中间层驱动。 对于中间层驱动,该子项下含有一个子项,是以我们当前中间层驱动绑定的下层MINIPORT设备的GUID命名的,在我的系统中,健值如下: {102454C2-9DB3-42A1-B4CF-6A8B67A516C0} 在{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项有个健,名称为UpperBindings,该健的健值是当前中间层驱动的MINIPORT设备名称,在我的系统中为如下健值: Device {5BF5A311-13E4-4746-8865-339DDD6C73AF} (2)中间层驱动 在我们的函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()中,会调用一系列函数(如NdisOpenProtocolConfiguration、NdisReadConfiguration)来访问注册表,其实都是访问ParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}子项。 注意,函数NDIS_PROTOCOL_CHARACTERISTICS-> BindAdapterHandler()的倒数第二个参数是SystemSpecific1,如果我们安装的是XPASSTHRU,则其具体指的是如下字符串: xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0} 其中xfilter 是XPASSTHRU的,而{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同。 函数NdisOpenProtocolConfiguration()其实只是构造一个查询注册表的RTL_QUERY _REGISTRY_TABLE结构(该结构在利用函数RtlQueryRegistryValues()查询注册表是使用)。并将这个结构封装到NDIS_WRAPPER_CONFIGURATION_HANDLE结构中,然后作为NdisOpenProtocolConfiguration()的第二个参数返回。 其实NdisOpenProtocolConfiguration()构造的RTL_QUERY_REGISTRY_TABLE结构的含义也就是查询HKLMSYSTEMCurrentControlSetServices xfilterParametersAdapters{ 102454C2-9DB3-42A1-B4CF-6A8B67A516C0}下的健值(xfilter 会随着安装不同的中间层驱动而不同,{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}在不同的系统中不同,下面均省略这些注释)。 函数NdisReadConfiguration()有两个作用,它首先修改在函数NdisOpenProtocolConf iguration()构造的RTL_QUERY_REGISTRY_TABLE结构。也就是在查询HKLMSYSTEM CurrentControlSetServices xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B6 7A516C0}的基础上加上了一个健,将其变成HKLMSYSTEMCurrentControlSetServices xfilterParametersAdapters{102454C2-9DB3-42A1-B4CF-6A8B67A516C0}UpperBindings。然后函数NdisReadConfiguration()会调用函数RtlQueryRegistryValues()查询新构造的这个注册表,并将结果存储在调用函数NdisReadConfiguration()时的第二个参数中。在我的系统中,RtlQueryRegistryValues()读出的这个新构造的这个注册表的健值是:Device {5BF5A311-13E4-4746-8865-339DDD6C73AF}(后面我们称为RESULT1),它其实是我们注册的中间层驱动(XPASSTHRU)的设备输出(其构造是Device+GUID)。 其实我们读出的这个中间层驱动(XPASSTHRU)的设备(即我们刚才读出的那个健值RESULT1)只在后面的函数NdisIMInitializeDeviceInstanceEx()中才用得着,并且RESULT1是作为函数NdisIMInitializeDeviceInstanceEx()的第二个参数的。 这里有个地方让人感到迷惑,即在函数BindAdapterHandler()我们一旦调用了函数NdisOpenAdapter()绑定了一个下层的MINIPORT,为什么还要调用函数NdisIMInitializeDeviceInstanceEx()初始化我们中间层驱动自己的MINIPORT(因为函数NdisIMInitializeDeviceInstanceEx()的参数是RESULT1,而RESULT1代表我们中间层驱动的MINIPORT)。为了解释这个原因,我们先做如下假设。 ------------------------------------------ ------------------------------------------ | PROT-IM | | PROT-TCPIP | ------------------------------------------ ------------------------------------------ | | ------------------------------------------ ------------------------------------------ | NDIS_OPEN_BLOCK1 | | NDIS_OPEN_BLOCK2 | ------------------------------------------ ------------------------------------------ | | ------------------------------------------ ------------------------------------------ | MINIPORT-NIC | | MINIPORT-IM | ------------------------------------------ ------------------------------------------ 我们假设我们系统安装了一个中间层驱动(假设为XPASSTRHU),在上图中,PROT-IM和MINIPORT-IM分别代表我们中间层驱动的协议驱动程序和小端口驱动程序,PROT-TCPIP代表真正的协议驱动程序,MINIPORT-NIC代表真是网卡的小端口驱动程序。 当PROT-TCPIP需要发送数据时,会调用函数NdisSend(),其实它会调用MINIPORT-IM中的发送数据函数,但是MINIPORT-IM和MINIPORT-NIC没联系,按照常规是不能发送数据到MINIPORT-NIC的。但是我们可以看到PROT-IM是可以和MINIPORT-NIC互相发送数据的,所以我们必须将MINIPORT-IM和PROT-IM联系起来。 另外当MINIPORT-NIC需要将数据提交给PROT-TCPIP时,只能首先将数据提交给PROT-IM,PROT-IM也只能通过MINIPORT-IM才能和PROT-TCPIP联系起来。 所以必须将PROT-IM和MINIPORT-IM联系起来。有人说这两个东西都是我们中间层驱动注册得,难道还联系不起来吗?不错,但是不管怎样你都得通过你得代码才能将他们联系起来呀!下面我们就介绍联系得方法。 我们以XPASSTHRU为例,在其函数ProtocolBindAdapter()中,先分配了一个ADAPT结构(这个结构是自己定义的,可根据用户的需要定义)。当调用函数ProtocolBindAdapter()调用函数NdisOpenAdapter()进行绑定时,是以&Adapt->BindingHandle作为函数NdisOpenAdapter()的第三个参数的,这样Adapt->BindingHandle就指向了NDIS_OPEN_BLOCK1(注意,调用函数NdisOpenAdapter()时的第三个参数会返回指向绑定以后的NDIS_OPEN_BLOCK指针)。然后函数ProtocolBindAdapter()会调用函数NdisIMInitializeDeviceInstanceEx(),该函数会进一步调用XPASSTHRU的NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数。上面我们讨论过,NdisIMInitializeDeviceInstanceEx()中的第二个参数就是XPASSTHRU注册的小端口驱动的设备实例(即上面的RESULT1)。在函数NdisIMInitializeDeviceInstanceEx()中会根据设备名称(RESULT1),找到对应的MINIPORT结构,并将其指针作为参数传递给NDIS_MINIPORT_CHARACTERISTICS->InitializeHandler()函数(以后简称InitializeHandler()函数)。在InitializeHandler()函数中,会进一步将MINIPORT结构指针赋值给ADAPT->MiniportHandle(ADAPT就是上面在函数ProtocolBindAdapter()中分配的那个结构)。 这样数据结构ADAPT中就含有了两个指针,一个指向NDIS_OPEN_BLOCK1,另一个指向MINIPORT-IM,而NDIS_OPEN_BLOCK1和PROT-IM是密切联系的,所以ADAPT就将PROT-IM和MINIPORT-IM紧密的联系起来了。 另外注意,NDIS_MINIPORT_BLOCK->DeviceContext是指向我们的ADAPT结构的,这个赋值在函数NdisIMInitializeDeviceInstanceEx()中完成。上面谈到了也是在函数NdisIMInitializeDeviceInstanceEx()中完成了从ADAPT-> MiniportHandle到MINIPORT的绑定,所以在函数NdisIMInitializeDeviceInstanceEx()中完成了ADAPT和MINIPORT的互相连接(即指针互相指向)。 函数InitializeHandler()中可以利用句柄MINIPORT的句柄得到我们的ADAPT结构,具体实现这个功能的函数是NdisIMGetDeviceContext(),这个函数的参数是个NDIS_HANDLE类型,但是在该函数内部,会将这个参数转换成NDIS_MINIPORT_BLOCK结构,并返回NDIS_MINIPORT_BLOCK->DeviceContext。 在函数NdisOpenAdapter()中,除了上面提到的完成了由Adapt->BindingHandle到NDIS_OPEN_BLOCK1的指向外,还完成了我们没有提到的由NDIS_OPEN_BLOCK1-> ProtocolBindingContext到ADAPT的指向,所以函数NdisOpenAdapter()完成了ADAPT和NDIS_OPEN_BLOCK1的互相连接(即指针互相指向)。 讲到这里,我们上图完善为下图: ------------------------------------ ----------------------------------- | PROT-IM | | PROT-TCPIP | ------------------------------------ ------------------------------------ | ------------------------------ | ------------------------------------ | ADAPT | ------------------------------------ | NDIS_OPEN_BLOCK1 | ---- |---BindingHandle | |NDIS_OPEN_BLOCK2 | | ProtocolBindingContext-|---- | | | | ------------------------------------ | MiniportHandle | ------------------------------------- | -----------------|------------- | ------------------------------------ | | ------------------------------------ | MINIPORT-NIC | | |----------------- |MINIPORT-IM | | | |----------------------- |DeviceContext | ------------------------------------ ------------------------------------- 下面大家也许就可以做一些HOOK了,例如对OPEN_BLOCK结构的HOOK,对ADAPT的HOOK等,这里就不作介绍了,呵呵。 [编辑 - 12/27/04 by noble_shi] [编辑 - 12/27/04 by noble_shi] [编辑 - 12/27/04 by noble_shi] |
|
地板#
发布于:2004-12-30 16:03
请给我发一份
谢谢! micmil@tom.com |
|
地下室#
发布于:2004-12-31 09:56
能不能把这篇文档发一份给我呀,我也是刚入门开始的,急需!!
zhangzx@vtion.com.cn |
|
5楼#
发布于:2005-01-02 11:45
你好,
希望也能给我一份, ooio_karl@126.com 多谢了! |
|
6楼#
发布于:2005-01-02 21:18
其实是可以下载的,用FlashGet或其他下载工具就可以。
|
|
|
7楼#
发布于:2005-01-11 08:55
对,可以下,感谢共享!
|
|
|
8楼#
发布于:2005-01-19 11:56
好文章,感谢中。。。
|
|
9楼#
发布于:2005-01-31 14:50
顶~~
|
|
|
10楼#
发布于:2005-02-02 17:23
给我一份呀,多谢!
magicfound@163.com |
|
11楼#
发布于:2005-03-10 20:58
感谢大哥,小弟要一份。
songty44@126.com |
|
12楼#
发布于:2005-03-15 19:26
我想要一份jhaoq@hotmail.com
|
|
|
13楼#
发布于:2005-03-19 21:44
也可给我一份谢谢!
harryccf@163.com |
|
|
14楼#
发布于:2005-03-30 18:55
感谢搂主分享!!
|
|
15楼#
发布于:2005-04-04 23:31
正好需要资料,真是一场及时雨,谢谢了!
|
|
|
16楼#
发布于:2005-06-15 09:50
佩服!
写得很好,可给我一份祥细的资料吗? 邮箱:qiyidi@163.com 谢谢! [编辑 - 6/15/05 by qiyidi] |
|
17楼#
发布于:2007-07-20 10:08
能给我发一份吗?
j_qq@163.com。。谢谢 |
|
18楼#
发布于:2007-07-20 10:58
我是新手中的新手,论坛里的兄弟都像LZ这样就好了。
真是感谢啊! |
|
19楼#
发布于:2007-07-21 21:24
学习中!!!
|
|
上一页
下一页