首页
社区
课程
招聘
[原创]深入理解协议驱动NDISPROT,附改动后清晰代码
发表于: 2012-11-13 23:05 8854

[原创]深入理解协议驱动NDISPROT,附改动后清晰代码

2012-11-13 23:05
8854
注册这个ID很久了,但是一直潜水。

这次我详细的阅读了NDISPROT的代码,详细到考虑过FLAG的定义,每个函数的逻辑,本人很讨厌乱用do-while.并把NDISPROT改动到面目全非,去掉了NDISPROT自己定义的(所有-2)的宏,力图以一个更清晰的方式把NDISPROT写出来。

期间收获挺多,当然是针对如我一般的新人而言,对NDISPROT的架构机制理解的很明确了,估计谁翻出来一个变量我能知道是哪个函数里,怎么用的。。

现在把我改动过的WNDISPROT的代码发上来,里面部分保留了寒江独钓对NDISPROT的注释,如有不妥请告知删除。

顺便求个工作

wNdisProt即是改动后的驱动代码,wn是测试程序,用法同DDK自带的uiotest:

usage: wn [options] <devicename>
options:
       -e: Enumerate devices
       -r: Read
       -w: Write (default)
       -l <length>: length of each packet (default: 100)
       -n <count>: number of packets (defaults to infinity)
       -m <MAC address> (defaults to local MAC)
       -f Use a fake address to send out the packets.

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 284
活跃值: (3609)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
2
可能字太少,都进来看看就走了,那就说些什么吧。怎么去理解,怎么更快看懂协议驱动。

陆陆续续读代码,写代码,调代码,有一些心得体会,写出来大家看看,有砖就拍,共同进步。这还是第一次认真写心得体会。

我认为,一个东西本身携带关于它本身的信息越多越好,但是应该简洁易懂的表现出来。比如,函数的命名,变量的命名。但是,有的东西复杂到简单的命名不能望出来它的意思和作用时,就需要必要的描述,同样遵循简洁易懂规则。而且描述在代码里的位置,所占行数,会不会影响联系上下代码,或者让读者严重分心,以及它的形式与代码的易区分程度,都决定了代码内描述的质量。当三言两句仍说不清的时候,这时候应该在代码外加描述了。我还是很讨厌代码内大篇幅的注释的。

第二,条理,或者说分类。共同完成一项功能的函数放到一个C里面,当一个C里面函数很多时,应该是再细分功能的时候了。而且每个函数间加上必要的空行和分割符,分隔符上有几个名词代表函数的功能最好。。

第三,包装。尽量减少不必要的包装,并以清晰公认的含义来命名必要的包装。世界是复杂的,人们总是试图把这种复杂包装起来,给以良好清晰的接口。但是让人去适度触摸内部机制,比包上一层华丽的包装来的好。反例微软示例代码里的各种宏。

第四,阅读指引。就是上文所提及的代码外描述。由它来引导您去理解整个代码,给一条平缓的理解曲线。本文后续部分就企图来做一个针对笔者前面发的wNdisProt的阅读指引。为什么不用ddk里的NdisProt去讲解,因为笔者认为它在可理解性上是有不足的,这也是wNdisProt诞生的原因。

首先是filesList,打开目录,可以看到:
      
debug.h                   包含了dprintf宏的定义,及其他两个很有效的宏的定义,还有标记的定义
functions.h               这是wNdisProt里所有函数的声明
struct.h                  这是wNdisProt里所有用到的结构的定义

wNdisProt.c               本人习惯在工程名命名的C里面写驱动入口函数与分发函数
exCallBack.c              这个是exCallBack函数
BindUnbind.c              协议驱动的绑定与反绑定极其相关函数的定义
IndicateStatus.c          从命令里看出来它是IndicateStatus函数的集合,是从BindUnbind.c里独立出来的,独立原因是BindUnbind.c里函数太多了
recv.c                    这是接收函数的结合,wNdisProt.c里DriverEntry的DispatchRead也在其内
send.c                    这是发送函数的结合,wNdisProt.c里DriverEntry的DispatchWrite也在其内
           
由于没有用过其他代码阅读的工具,目前本人觉得在VS+VAX的环境里阅读代码还是挺愉快的。

首先,自然是看DriverEntry与分发函数,wNdisProt里就是在wNdisProt.c文件里。
首先遇到NDISPROT_GLOBALS    Globals = {0};,这是个全局变量的一个结构。点到NDISPROT_GLOBALS,点VS窗口那个go,会跳到struct.h里对NDISPROT_GLOBALS里的定义:

//=============WNDISPROT_GLOBALS================

typedef struct _NDISPROT_GLOBALS
{
    PDRIVER_OBJECT          pDriverObject;
    PDEVICE_OBJECT          pDeviceObject;
    NDIS_HANDLE             NdisProtocolHandle;
    UCHAR                   PartialCancelId;    // for cancelling sends
    ULONG                   LocalCancelId;
    LIST_ENTRY              ListOpenContext;    // of OPEN_CONTEXT structures
    NDIS_SPIN_LOCK          GlobalLock;         // to protect the above
    NDIS_EVENT              BindsComplete;      // have we seen NetEventBindsComplete?

} NDISPROT_GLOBALS, *PNDISPROT_GLOBALS;

所有变量的作用请望名生义。有一个ListOpenContext,看名字它是一个由OpenContext构成的List,暂时不去深入。然后点工具栏中的向后定位按钮回到wNdisProt.c,继续阅读。

DriverEntry的逻辑如下:

创建设备
创建链接
注册协议 NdisRegisterProtocol
初始化全局变量的有关内容


其中注册协议时填写的协议结构如下(此结构由系统定义于ndis.h中):
    protocolChar.MajorNdisVersion            = 5;
    protocolChar.MinorNdisVersion            = 0;
    protocolChar.Name                        = nsProtoName;
    protocolChar.OpenAdapterCompleteHandler  = NdisProtOpenAdapterComplete;
    protocolChar.CloseAdapterCompleteHandler = NdisProtCloseAdapterComplete;
    protocolChar.SendCompleteHandler         = NdisProtSendComplete;
    protocolChar.TransferDataCompleteHandler = NdisProtTransferDataComplete;
    protocolChar.ResetCompleteHandler        = NdisProtResetComplete;
    protocolChar.RequestCompleteHandler      = NdisProtRequestComplete;
    protocolChar.ReceiveHandler              = NdisProtReceive;
    protocolChar.ReceiveCompleteHandler      = NdisProtReceiveComplete;
    protocolChar.StatusHandler               = NdisProtStatus;
    protocolChar.StatusCompleteHandler       = NdisProtStatusComplete;
    protocolChar.BindAdapterHandler          = NdisProtBindAdapter;
    protocolChar.UnbindAdapterHandler        = NdisProtUnbindAdapter;
    protocolChar.UnloadHandler               = NULL;
    protocolChar.ReceivePacketHandler        = NdisProtReceivePacket;
    protocolChar.PnPEventHandler             = NdisProtPnPEventHandler;

实现每一个Handler函数,协议驱动就写好了。
2012-11-15 15:54
0
雪    币: 268
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
写详细点,说不定能骗个精华
2012-11-15 16:18
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主你好,我刚研究ndisprot,有关问题想请教,我直接使用wdk的例子,在xp下用uiotest测试,总是不成功,我调试了下发现设备打开不成功。好像是设备名的问题,是我使用uiotest不当还是例子有问题呢?
2013-12-17 01:31
0
雪    币: 284
活跃值: (3609)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
5
一看日期是一年前的帖子了,忘的差不多了。
你很容易怀疑WDK吗?
问问题的时候,请说明你是怎么做的,遇到了什么提示。
只能说,WDK没错。
而你给出的信息里,猜不出来是哪里的问题。
2013-12-17 02:07
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
我猜也是我的弱智错误,编译和加载驱动都没有问题,然后用uiotest的时候,打开cmd到当前目录,然后输入uiotest -e,没有反应输入uiotest -[其他选项]的时候就是显示fail to open XXX,不知道是不是我uiotest使用错误
2013-12-20 19:49
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我想做一个防火墙,还在慢慢啃,PS:大牛注意身体,早睡早起
2013-12-20 19:56
0
雪    币: 284
活跃值: (3609)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
8
[QUOTE=摸奶赏月;1248746]我猜也是我的弱智错误,编译和加载驱动都没有问题,然后用uiotest的时候,打开cmd到当前目录,然后输入uiotest -e,没有反应输入uiotest -[其他选项]的时候就是显示fail to open XXX,不知道是不是我uiotest使用错误[/QUOTE]

NDIS驱动不能直接加载使用,
这是WDK的帮助里NDISPROT的安装和使用说明:

INSTALLATION
The driver is installed using the INF file ndisprot.inf, which is provided in the driver directory. In Network Connections UI, select an adapter and open Properties.

Click Install, then Protocol, then Add, and then Have disk. Then point to the location of the .inf and driver.

Select Sample NDIS Protocol Driver and click OK. After installing the protocol, copy over the test application uiotest.exe to a convenient location. Please note that the driver service has been set to manual start in the INF file. As a result, it doesn't get loaded automatically when you install.

USAGE
To start the driver, type

          Net start ndisprot

To stop the driver, type

          Net stop ndisprot

To test the driver, run uiotest. For help on usage, run uiotest -?

usage: UIOTEST [options] <devicename>
options:
       -e: Enumerate devices
       -r: Read
       -w: Write (default)
       -l <length>: length of each packet (default: 100)
       -n <count>: number of packets (defaults to infinity)
       -m <MAC address> (defaults to local MAC)
2013-12-20 20:19
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
多谢前辈
2013-12-20 20:27
0
雪    币: 3407
活跃值: (1242)
能力值: ( LV13,RANK:335 )
在线值:
发帖
回帖
粉丝
10
厉害啊~  13年我刚毕业的时候,那个时候驱动,汇编,一行都看不懂
2019-4-13 14:21
0
游客
登录 | 注册 方可回帖
返回
//