MSDN系列(14)--"NDIS Protocol Driver"入门

本文详细介绍了NDIS Protocol Driver的工作原理及其在Windows网络架构中的角色。内容包括NDIS协议驱动的基本概念、NDIS如何与其他驱动交互,以及如何在用户态进行测试。文章还探讨了ntoskrnl.exe中的一些运行时函数,并提供了有关如何编写和测试NDIS协议驱动的实例代码和步骤。此外,还提及了与之相关的注册表配置和卸载过程。
摘要由CSDN通过智能技术生成
日期: 2004-07-19 16:55
更新: 2004-08-17 16:23
链接: http://www.opencjk.org/~scz/windows/200408171624.txt

--------------------------------------------------------------------------
    ☆ NDIS Protocol Driver
    ☆ ntoskrnl.exe引出的一些运行时函数
    ☆ 一个完整的NDIS Protocol Driver框架
        a) NDIS协议驱动
            1) ndisprotocol.c
            2) sources
            3) makefile
            4) ndisprotocol.inf
        b) NDIS协议驱动的用户态测试程序
            1) ndisprotocoltest.c
            2) sources
            3) makefile
        c) NDIS组件配置程序
        d) 源代码目录结构
        e) 编译
        f) 安装
        g) 测试
        h) 卸载
        i) 一些遗留问题
    ☆ 参考资源

--------------------------------------------------------------------------

☆ NDIS Protocol Driver

[1]给了一张Windows网络架构图,有助于理解NDIS,推荐入门者先看看这张图。

[2]有一些关于Windows网络架构的讨论,这只是一种个人学术观点,仅供参考,不可
当成官方结论。

NDIS(Network Device Interface Specification)提供一个系统的、完整的Wrapper,
NDIS Miniport Driver、NDIS ProtocolDriver等等均属于"插入"这个Wrapper中的"
模块",这些驱动调用Wrapper提供的函数,同时也向Wrapper注册回调函数,整个运
作过程由Wrapper统一调度。Wrapper对应ndis.sys。

TDI Client Driver利用协议驱动上沿引出的TDI接口(Transport Data Interface)实
现命名管道、邮槽、Winsock等等。

下面这些注册表内容对应着Network Control Panel Applet (NCPA):

--------------------------------------------------------------------------
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E972-E325-11CE-BFC1-08002bE10318}
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E973-E325-11CE-BFC1-08002BE10318}
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E974-E325-11CE-BFC1-08002BE10318}
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Class/{4D36E975-E325-11CE-BFC1-08002BE10318}

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E972-E325-11CE-BFC1-08002BE10318}

    对应GUID_DEVCLASS_NET、Miniport Driver、Net。收到包后NDIS首先调用
    Miniport Driver进行处理。Miniport Driver负责控制网卡硬件特性,在协议驱
    动与网卡之间传递报文。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E973-E325-11CE-BFC1-08002BE10318}

    对应GUID_DEVCLASS_NETCLIENT、Client Driver、NetClient。"Client for
    Microsoft Networks"即是此类型驱动。负责向用户态提供NetBIOS Client API。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E974-E325-11CE-BFC1-08002BE10318}

    对应GUID_DEVCLASS_NETSERVICE、Service Driver、NetService。"File and
    Printer Sharing for Microsoft Networks"即是此类型驱动。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E975-E325-11CE-BFC1-08002BE10318}

    对应GUID_DEVCLASS_NETTRANS、Protocol Driver、NetTrans。负责实现各种网
    络协议,比如tcpip.sys实现了TCP/IP协议。协议驱动接收Miniport Driver上传
    的报文,也接收Client Driver、Service Driver、TDI Client Driver下传的报
    文。
--------------------------------------------------------------------------

中间层驱动(Intermediate Driver)是一种混合型驱动,位于Miniport Driver与协议
驱动之间,对下看起来像协议驱动,对上看起来像Miniport Driver。

在这些不同类型的驱动之间有一种操作叫作"绑定",其本质在于向NDIS Wrapper指明
报文(Packet)的传递路线。

☆ ntoskrnl.exe引出的一些运行时函数

> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find /I "printf"
       1397  574 00052BCB _snprintf
       1398  575 00052C22 _snwprintf
       1406  57D 00052D73 _vsnprintf
       1407  57E 00052DC9 _vsnwprintf
       1430  595 00053D4D sprintf
       1443  5A2 000543E0 swprintf
       1450  5A9 000544F4 vsprintf
> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find "_str"
       1399  576 00052C92 _stricmp
       1400  577 00052C97 _strlwr
       1401  578 00052CBA _strnicmp
       1402  579 00052CD0 _strnset
       1403  57A 00052D00 _strrev
       1404  57B 00052D30 _strset
       1405  57C 00052D50 _strupr
> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find " str"
       1432  597 00053DC0 strcat
       1433  598 00053EB0 strchr
       1434  599 00053F70 strcmp
       1435  59A 00053DB0 strcpy
       1436  59B 00054000 strlen
       1437  59C 00054080 strncat
       1438  59D 000541B0 strncmp
       1439  59E 000541F0 strncpy
       1440  59F 000542F0 strrchr
       1441  5A0 00054320 strspn
       1442  5A1 00054360 strstr
> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find "wcs"
       1408  57F 00052E38 _wcsicmp
       1409  580 00052E83 _wcslwr
       1410  581 00052EAF _wcsnicmp
       1411  582 00052F08 _wcsnset
       1412  583 00052F31 _wcsrev
       1413  584 00052F63 _wcsupr
       1422  58D 000531DB mbstowcs
       1451  5AA 0005454B wcscat
       1452  5AB 00054591 wcschr
       1453  5AC 000545B3 wcscmp
       1454  5AD 00054575 wcscpy
       1455  5AE 000545E5 wcscspn
       1456  5AF 00054628 wcslen
       1457  5B0 0005463E wcsncat
       1458  5B1 0005467B wcsncmp
       1459  5B2 000546B0 wcsncpy
       1460  5B3 000546ED wcsrchr
       1461  5B4 0005471D wcsspn
       1462  5B5 00054763 wcsstr
       1463  5B6 000547C1 wcstombs
> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find "mem"
       1424  58F 00053290 memchr
       1425  590 00053340 memcpy
       1426  591 00053680 memmove
       1427  592 000539C0 memset
> dumpbin /exports %systemroot%/system32/ntoskrnl.exe | find "_ito"
       1393  570 00052B76 _itoa
       1394  571 00052BA0 _itow

☆ 一个完整的NDIS Protocol Driver框架

a) NDIS协议驱动

XP SP1 DDK自带了一个名为ndisuio的例子(NDIS User mode I/O Protocol),但我没
有找到NT4 DDK中名为packet的例子。参[3]、[4]、[5],这些都是完整的协议驱动源
代码。

ndisuio演示了"connection-less NDIS 5.0/5.1 protocol driver",用户态程序可
简单地通过ReadFile/WriteFile直接操作链路层数据(物理帧)。对于sniffer一类的
需求,这已经足够了。ndisuio没有在其上沿提供TDI接口。ndisuio做了很多限制,
使得我们无法随心所欲地操作链路层数据。假设有如下结构:

struct etherheader
{
    unsigned char           eth_dst[6]; /* destination eth addr */
    unsigned char           eth_src[6]; /* source ether addr    */
    unsigned short int      eth_type;   /* packet type ID field */
};

ndisuio在DispatchWrite()例程中对eth_src、eth_type进行检查,发送报文时不能
伪造源MAC,必须匹配事先指定的eth_type。

ndisuio允许用户态程序通过DeviceIoControl()指定eth_type,但其在
DispatchDeviceControl()例程中做了限制,不能任意指定eth_type。

ndisuio在ProtocolReceive()、ProtocolReceivePacket()例程中对eth_type进行检
查,只接收与事先指定的eth_type相匹配的报文。

ndisuio允许用户态程序通过DeviceIoControl()向Miniport Driver设置OID,但其在
DispatchDeviceControl()例程中做了限制,只允许设置部分OID。

从ndisuio例子所附用户态测试程序的代码来看,曾经有一个版本的ndisuio未做前述
限制,至少发送报文时可以伪造源MAC。现在我们要做的就是简单地注释掉相应代码,
使得可以随心所欲地操作链路层数据。

XP事实上缺省安装了ndisuio,可用"net start ndisuio"加载这个隐藏的协议驱动。
据tk讲,2000也缺省安装ndisuio,我不确认是某个Service Pack带进来的,还是最
初就有。由于存在前述限制,ndisuio对我们来讲没有多少意义。

下面是XP SP1中与ndisuio相关的注册表内容,NDI是"Network Device Installer"的
缩写。

--------------------------------------------------------------------------
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E975-E325-11CE-BFC1-08002BE10318}/{03130807-B5F2-47A1-81B0-B870D16F272B}]
"Characteristics"=dword:00000028
"InfPath"="ndisuio.inf"
"InfSection"="Install"
"Description"="NDIS Usermode I/O Protocol"
"ComponentId"="ms_ndisuio"

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E975-E325-11CE-BFC1-08002BE10318}/{03130807-B5F2-47A1-81B0-B870D16F272B}/Ndi]
"Service"="Ndisuio"
"HelpText"="A driver to support user-mode I/O on NDIS devices"

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E975-E325-11CE-BFC1-08002BE10318}/{03130807-B5F2-47A1-81B0-B870D16F272B}/Ndi/Interfaces]
"UpperRange"="noupper"
"LowerRange"="ndis5,ndis4,ndis5_uio"
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/LEGACY_NDISUIO]
"NextInstance"=dword:00000001

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/LEGACY_NDISUIO/0000]
"Service"="Ndisuio"
"Legacy"=dword:00000001
"ConfigFlags"=dword:00000000
"Class"="LegacyDriver"
"ClassGUID"="{8ECC055D-047F-11D1-A537-0000F8753ED1}"
"DeviceDesc"="NDIS Usermode I/O Protocol"
"Capabilities"=dword:00000000

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/LEGACY_NDISUIO/0000/LogConf]

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Enum/Root/LEGACY_NDISUIO/0000/Control]
"ActiveService"="Ndisuio"
--------------------------------------------------------------------------
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Ndisuio]
"Type"=dword:00000001
"Start"=dword:00000003
"ErrorControl"=dword:00000001
"Tag"=dword:0000000c
"ImagePath"=hex(2):53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,44,00,/
  52,00,49,00,56,00,45,00,52,00,53,00,5c,00,6e,00,64,00,69,00,73,00,75,00,69,/
  00,6f,00,2e,00,73,00,79,00,73,00,00,00
"DisplayName"="NDIS Usermode I/O Protocol"
"Group"="NDIS"
"Description"="NDIS Usermode I/O Protocol"

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Ndisuio/Linkage]
"Bind"=hex(7):5c,00,44,00,65,00,76,00,69,00,63,00,65,00,5c,00,7b,00,33,00,46,/
  00,32,00,46,00,37,00,46,00,35,00,33,00,2d,00,39,00,34,00,43,00,43,00,2d,00,/
  34,00,43,00,38,00,33,00,2d,00,42,00,36,00,38,00,33,00,2d,00,34,00,33,00,30,/
  00,38,00,43,00,35,00,37,00,33,00,37,00,31,00,32,00,44,00,7d,00,00,00,5c,00,/
  44,00,65,00,76,00,69,00,63,00,65,00,5c,00,7b,00,34,00,46,00,44,00,45,00,38,/
  00,42,00,37,00,42,00,2d,00,31,00,42,00,41,00,31,00,2d,00,34,00,42,00,30,00,/
  41,00,2d,00,39,00,30,00,32,00,39,00,2d,00,31,00,34,00,31,00,45,00,31,00,33,/
  00,35,00,35,00,39,00,45,00,36,00,39,00,7d,00,00,00,00,00
"Route"=hex(7):22,00,7b,00,33,00,46,00,32,00,46,00,37,00,46,00,35,00,33,00,2d,/
  00,39,00,34,00,43,00,43,00,2d,00,34,00,43,00,38,00,33,00,2d,00,42,00,36,00,/
  38,00,33,00,2d,00,34,00,33,00,30,00,38,00,43,00,35,00,37,00,33,00,37,00,31,/
  00,32,00,44,00,7d,00,22,00,00,00,22,00,7b,00,34,00,46,00,44,00,45,00,38,00,/
  42,00,37,00,42,00,2d,00,31,00,42,00,41,00,31,00,2d,00,34,00,42,00,30,00,41,/
  00,2d,00,39,00,30,00,32,00,39,00,2d,00,31,00,34,00,31,00,45,00,31,00,33,00,/
  35,00,35,00,39,00,45,00,36,00,39,00,7d,00,22,00,00,00,00,00
"Export"=hex(7):5c,00,44,00,65,00,76,00,69,00,63,00,65,00,5c,00,4e,00,64,00,69,/
  00,73,00,75,00,69,00,6f,00,5f,00,7b,00,33,00,46,00,32,00,46,00,37,00,46,00,/
  35,00,33,00,2d,00,39,00,34,00,43,00,43,00,2d,00,34,00,43,00,38,00,33,00,2d,/
  00,42,00,36,00,38,00,33,00,2d,00,34,00,33,00,30,00,38,00,43,00,35,00,37,00,/
  33,00,37,00,31,00,32,00,44,00,7d,00,00,00,5c,00,44,00,65,00,76,00,69,00,63,/
  00,65,00,5c,00,4e,00,64,00,69,00,73,00,75,00,69,00,6f,00,5f,00,7b,00,34,00,/
  46,00,44,00,45,00,38,00,42,00,37,00,42,00,2d,00,31,00,42,00,41,00,31,00,2d,/
  00,34,00,42,00,30,00,41,00,2d,00,39,00,30,00,32,00,39,00,2d,00,31,00,34,00,/
  31,00,45,00,31,00,33,00,35,00,35,00,39,00,45,00,36,00,39,00,7d,00,00,00,00,/
  00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Ndisuio/Security]
"Security"=hex:01,00,14,80,90,00,00,00,9c,00,00,00,14,00,00,00,30,00,00,00,02,/
  00,1c,00,01,00,00,00,02,80,14,00,ff,01,0f,00,01,01,00,00,00,00,00,01,00,00,/
  00,00,02,00,60,00,04,00,00,00,00,00,14,00,fd,01,02,00,01,01,00,00,00,00,00,/
  05,12,00,00,00,00,00,18,00,ff,01,0f,00,01,02,00,00,00,00,00,05,20,00,00,00,/
  20,02,00,00,00,00,14,00,8d,01,02,00,01,01,00,00,00,00,00,05,0b,00,00,00,00,/
  00,18,00,fd,01,02,00,01,02,00,00,00,00,00,05,20,00,00,00,23,02,00,00,01,01,/
  00,00,00,00,00,05,12,00,00,00,01,01,00,00,00,00,00,05,12,00,00,00

[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Ndisuio/Enum]
"0"="Root//LEGACY_NDISUIO//0000"
"Count"=dword:00000001
"NextInstance"=dword:00000001
--------------------------------------------------------------------------

名为"Characteristics"的键值对应INF文件中的Characteristics项,0x28表示逻辑
或NCF_HIDDEN(0x08)、NCF_NOT_USER_REMOVABLE(0x20),即NCPA中不可见、不可通过
NCPA或设备管理器删除。调试协议驱动时,应在INF文件中指定0x00,这样才便于删
除、重新增加并测试。

1) ndisprotocol.c

本文所给完整框架(安装/卸载、驱动、用户态测试程序)完全是DDK自带例子代码,我
可写不出这么大的框架代码来。如有疑问,请问微软。

--------------------------------------------------------------------------
/*
* For x86/EWindows XP SP1 & VC 7 & Windows DDK 2600.1106
*/

/************************************************************************
*                                                                      *
*                               Head File                              *
*                                                                      *
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ndis.h>
#include <ntddk.h>
#include <windef.h>
#include <devioctl.h>

/************************************************************************
*                                                                      *
*                               Macro                                  *
*                                                                      *
************************************************************************/

#define INTERNALNAME                                L"//Device//NDISProtocolInternal"
#define EXTERNALNAME                                L"//??//NDISProtocolExternal"
#define PRIVATETAG                                  'OFSN'
#define NDISPROTOCOL_INDEX                          0x0800
#define IOCTL_NDISPROTOCOL_GET_PRIVATEFLAGS         CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 0,                                     /
    METHOD_BUFFERED,                                            /
    FILE_READ_ACCESS                                            /
)
#define IOCTL_NDISPROTOCOL_SET_PRIVATEFLAGS         CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 1,                                     /
    METHOD_BUFFERED,                                            /
    FILE_WRITE_ACCESS                                           /
)
#define IOCTL_NDISPROTOCOL_OPEN_DEVICE              CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 2,                                     /
    METHOD_BUFFERED,                                            /
    FILE_READ_ACCESS | FILE_WRITE_ACCESS                        /
)
#define IOCTL_NDISPROTOCOL_GET_OID_VALUE            CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 3,                                     /
    METHOD_BUFFERED,                                            /
    FILE_READ_ACCESS                                            /
)
#define IOCTL_NDISPROTOCOL_SET_OID_VALUE            CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 4,                                     /
    METHOD_BUFFERED,                                            /
    FILE_WRITE_ACCESS                                           /
)
#define IOCTL_NDISPROTOCOL_SET_ETHER_TYPE           CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 5,                                     /
    METHOD_BUFFERED,                                            /
    FILE_WRITE_ACCESS                                           /
)
#define IOCTL_NDISPROTOCOL_QUERY_BINDING            CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 6,                                     /
    METHOD_BUFFERED,                                            /
    FILE_READ_ACCESS                                            /
)
#define IOCTL_NDISPROTOCOL_BIND_WAIT                CTL_CODE    /
(                                                               /
    FILE_DEVICE_NETWORK,                                        /
    NDISPROTOCOL_INDEX + 7,                                     /
    METHOD_BUFFERED,                                            /
    FILE_READ_ACCESS | FILE_WRITE_ACCESS                        /
)

#define PRIVATEFLAGS_ETHERTYPE                      0x00000001
#define PRIVATEFLAGS_DEFAULT                        0x00000001

typedef struct _DEVICE_EXTENSION
{
    PDEVICE_OBJECT          DeviceObject;
    ULONG                   DeviceNumber;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

#define PRIVATEMIN(x,y)                             ((x)<(y)?(x):(y))
#define SET_FLAGS(_FlagsVar, _Mask, _BitsToSet)     (_FlagsVar) = ((_FlagsVar) & ~(_Mask)) | (_BitsToSet)
#define TEST_FLAGS(_FlagsVar, _Mask, _BitsToCheck)  (((_FlagsVar) & (_Mask)) == (_BitsToCheck))

#define PRIVATE_BIND_IDLE                           0x00000000
#define PRIVATE_BIND_OPENING                        0x00000001
#define PRIVATE_BIND_FAILED                         0x00000002
#define PRIVATE_BIND_ACTIVE                         0x00000004
#define PRIVATE_BIND_CLOSING                        0x00000008
#define PRIVATE_BIND_FLAGS                          0x0000000F

#define PRIVATE_OPEN_IDLE                           0x00000000
#define PRIVATE_OPEN_ACTIVE                         0x00000010
#define PRIVATE_OPEN_FLAGS                          0x000000F0

#define PRIVATE_RESET_IN_PROGRESS                   0x00000100
#define PRIVATE_NOT_RESETTING                       0x00000000
#define PRIVATE_RESET_FLAGS                         0x00000100

#define PRIVATE_MEDIA_CONNECTED                     0x00000000
#define PRIVATE_MEDIA_DISCONNECTED                  0x00000200
#define PRIVATE_MEDIA_FLAGS                         0x00000200

#define PRIVATE_READ_SERVICING                      0x00100000
#define PRIVATE_READ_FLAGS                          0x00100000

#define PRIVATE_UNBIND_RECEIVED                     0x10000000
#define PRIVATE_UNBIND_FLAGS                        0x10000000

#define DEFAULT_PACKET_FILTER                       (NDIS_PACKET_TYPE_DIRECTED|NDIS_PACKET_TYPE_MULTICAST|NDIS_PACKET_TYPE_BROADCAST)

typedef struct _ADAPTER_CONTEXT
{
    LIST_ENTRY              Link;
    NDIS_SPIN_LOCK          Lock;
    ULONG                   ReferenceCount;
    ULONG                   Flags;
    PFILE_OBJECT            FileObject;
    NDIS_STRING             DeviceName;
    NDIS_STRING             AdapterInstanceName;
    NDIS_STATUS             BindStatus;
    NDIS_EVENT              BindEvent;
    NDIS_HANDLE             SendPacketPool;
    NDIS_HANDLE             SendBufferPool;
    NDIS_HANDLE             RecvPacketPool;
    NDIS_HANDLE             RecvBufferPool;
    LIST_ENTRY              PendedWrites;
    ULONG                   PendedWriteCount;
    LIST_ENTRY              PendedReads;
    ULONG                   PendedReadCount;
    LIST_ENTRY              RecvPacketQueue;
    ULONG                   RecvPacketCount;
    NDIS_HANDLE             NdisBindingHandle;
    UCHAR                   CurrentAddress[6];
    ULONG                   MacOptions;
    ULONG                   MaximumFrameSize;
    NET_DEVICE_POWER_STATE  PowerState;
    NDIS_EVENT              PoweredUpEvent;
} ADAPTER_CONTEXT, *PADAPTER_CONTEXT;

typedef struct _BINDINGINFO
{
    ULONG                   BindingIndex;               // 0-based binding number
    ULONG                   DeviceNameOffset;           // from start of this struct
    ULONG                   DeviceNameLength;           // in bytes
    ULONG                   AdapterInstanceNameOffset;  // from start of this struct
    ULONG                   AdapterInstanceNameLength;  // in bytes
} BINDINGINFO, *PBINDINGINFO;

typedef struct _OIDVALUE
{
    NDIS_OID                Oid;
    UCHAR                   Value[sizeof(ULONG)];
} OIDVALUE, *POIDVALUE;

#define MIN_SEND_PACKET_NUM                         20
#define MAX_SEND_PACKET_NUM                         400

typedef struct _SEND_PACKET_PROTOCOLRESERVED
{
    PIRP                    Irp;
    ULONG                   ReferenceCount;

} SEND_PACKET_PROTOCOLRESERVED, *PSEND_PACKET_PROTOCOLRESERVED;

#define MIN_RECV_PACKET_NUM                         4
#define MAX_RECV_PACKET_NUM                         20
#define MAX_RECV_BUFFER_NUM                         20
#define MAX_RECV_QUEUE_NUM                          4

typedef struct _RECV_PACKET_PROTOCOLRESERVED
{
    LIST_ENTRY              Link;
    PNDIS_BUFFER            Buffer;
} RECV_PACKET_PROTOCOLRESERVED, *PRECV_PACKET_PROTOCOLRESERVED;

#define GETBUFFER(x)                                (((PRECV_PACKET_PROTOCOLRESERVED)(x)->ProtocolReserved)->Buffer)
#define GETLINK(x)                                  (&((PRECV_PACKET_PROTOCOLRESERVED)(x)->ProtocolReserved)->Link)
#define GETRECVPACKET(x)                            CONTAINING_RECORD(CONTAINING_RECORD(x, RECV_PACKET_PROTOCOLRESERVED, Link), NDIS_PACKET, ProtocolReserved)
#define GETREFERENCECOUNT(x)                        (((PSEND_PACKET_PROTOCOLRESERVED)(x)->ProtocolReserved)->ReferenceCount)
#define GETIRP(x)                                   (((PSEND_PACKET_PROTOCOLRESERVED)(x)->ProtocolReserved)->Irp)
#define GETCANCELID()                               (HighCancelId | (NdisInterlockedIncrement(&LowCancelId) & 0x00FFFFFF))

typedef struct _REQUEST_CONTEXT
{
    NDIS_REQUEST            NdisRequest;
    NDIS_EVENT              NdisRequestEvent;
    ULONG                   Status;
} REQUEST_CONTEXT, *PREQUEST_CONTEXT;

#pragma pack( push, 1 )

struct etherheader
{
    unsigned char           eth_dst[6]; /* destination eth addr */
    unsigned char           eth_src[6]; /* source ether addr    */
    unsigned short int      eth_type;   /* packet type ID field */
};

#pragma pack( pop )

#define swap_16(x)                                  ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#define swap_32(x)                                  ((((x) >> 24) & 0xff) | (((x) & 0xff) << 24) | (((x) >> 8) & 0xff00) | (((x) & 0xff00) << 8))

#define ETH_P_IP                                    0x0800          /* Internet Protocol packet     */
#define ETH_P_ARP                                   0x0806          /* Address Resolution packet    */
#define ETH_P_RARP                                  0x8035          /* Reverse Addr Res packet      */
#define ETH_P_8021P                                 0x8100          /* 802.1p                       */
#define ETH_P_DEFAULT                               ETH_P_ARP

/************************************************************************
*                                                                      *
*                            Function Prototype                        *
*                                                                      *
************************************************************************/

static NTSTATUS             NDISProtocolCreateDevice
(
    IN  PDRIVER_OBJECT          DriverObject,
    IN  ULONG                   DeviceNumber
);
static VOID                 NDISProtocolDeleteDevice
(
    IN  PDEVICE_OBJECT          DeviceObject
);
static NTSTATUS             NDISProtocolDispatch
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
static NTSTATUS             NDISProtocolDispatchRead
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
static VOID                 NDISProtocolReadCancel
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
static NTSTATUS             NDISProtocolDispatchWrite
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
#ifdef NDIS51
static VOID                 NDISProtocolWriteCancel
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
#endif
static NTSTATUS             NDISProtocolDispatchCleanup
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
static NTSTATUS             NDISProtocolDispatchDeviceControl
(
    IN  PDEVICE_OBJECT          DeviceObject,
    IN  PIRP                    Irp
);
static VOID                 NDISProtocolDriverUnload
(
    IN  PDRIVER_OBJECT          DriverObject
);
static PNDIS_PACKET         PrivateAllocateReceivePacket
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  UINT                    DataLength,
    OUT PUCHAR                 *pData
);
static VOID                 PrivateCancelPendingReads
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static NDIS_STATUS          PrivateCreateBinding
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  PWSTR                   DeviceName,
    IN  ULONG                   DeviceNameLength
);
static VOID                 PrivateDereferenceCount
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static VOID                 PrivateFlushReceiveQueue
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static VOID                 PrivateFreeAdapterContextResources
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static VOID                 PrivateFreeReceivePacket
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  PNDIS_PACKET            Packet
);
static NDIS_STATUS          PrivateGetOidValue
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    OUT PVOID                   OutputBuffer,
    IN  ULONG                   OutputBufferLength,
    OUT PULONG                  BytesWritten
);
static PADAPTER_CONTEXT     PrivateLookupDevice
(
    IN  PWSTR                   DeviceName,
    IN  ULONG                   DeviceNameLength
);
static NDIS_STATUS          PrivateNdisRequest
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  NDIS_REQUEST_TYPE       RequestType,
    IN  NDIS_OID                Oid,
    IN  PVOID                   InformationBuffer,
    IN  UINT                    InformationBufferLength,
    OUT PUINT                   BytesProcessed
);
static VOID                 PrivateNdisStatusToNtStatus
(
    IN  NDIS_STATUS             NdisStatus,
    IN  NTSTATUS               *NtStatus
);
static NTSTATUS             PrivateOpenDevice
(
    IN  PWSTR                   DeviceName,
    IN  ULONG                   DeviceNameLength,
    IN  PFILE_OBJECT            FileObject,
    OUT PADAPTER_CONTEXT       *pAdapterContext
);
static NDIS_STATUS          PrivateQueryBinding
(
    IN  PUCHAR                  Buffer,
    IN  ULONG                   InputBufferLength,
    IN  ULONG                   OutputBufferLength,
    OUT PULONG                  BytesReturned
);
static VOID                 PrivateQueueReceivePacket
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  PNDIS_PACKET            RecvPacket
);
static VOID                 PrivateReferenceCount
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static VOID                 PrivateSendDereferenceCount
(
    IN  PNDIS_PACKET            Packet
);
static VOID                 PrivateSendReferenceCount
(
    IN  PNDIS_PACKET            Packet
);
static VOID                 PrivateServiceReads
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static NDIS_STATUS          PrivateSetOidValue
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    OUT PVOID                   InputBuffer,
    IN  ULONG                   InputBufferLength
);
static VOID                 PrivateShutdownBinding
(
    IN  PADAPTER_CONTEXT        AdapterContext
);
static VOID                 PrivateSleep
(
    IN  UINT                    seconds
);
static BOOLEAN              PrivateValidateOid
(
    IN  NDIS_OID                Oid
);
static NDIS_STATUS          PrivateValidateOpenAndDoRequest
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  NDIS_REQUEST_TYPE       RequestType,
    IN  NDIS_OID                Oid,
    IN  PVOID                   InformationBuffer,
    IN  UINT                    InformationBufferLength,
    OUT PUINT                   BytesProcessed,
    IN  BOOLEAN                 WaitForPowerOn
);
static VOID                 PrivateWaitForPendingIO
(
    IN  PADAPTER_CONTEXT        AdapterContext,
    IN  BOOLEAN                 DoCancelPendingReads
);
static VOID                 ProtocolOpenAdapterComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_STATUS             Status,
    IN  NDIS_STATUS             OpenErrorStatus
);
static VOID                 ProtocolCloseAdapterComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_STATUS             Status
);
static VOID                 ProtocolSendComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNDIS_PACKET            Packet,
    IN  NDIS_STATUS             Status
);
static VOID                 ProtocolTransferDataComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNDIS_PACKET            Packet,
    IN  NDIS_STATUS             Status,
    IN  UINT                    BytesTransferred
);
static VOID                 ProtocolResetComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_STATUS             Status
);
static VOID                 ProtocolRequestComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNDIS_REQUEST           NdisRequest,
    IN  NDIS_STATUS             Status
);
static NDIS_STATUS          ProtocolReceive
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_HANDLE             MacReceiveContext,
    IN  PVOID                   HeaderBuffer,
    IN  UINT                    HeaderBufferSize,
    IN  PVOID                   LookAheadBuffer,
    IN  UINT                    LookaheadBufferSize,
    IN  UINT                    PacketSize
);
static VOID                 ProtocolReceiveComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext
);
static VOID                 ProtocolStatus
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_STATUS             GeneralStatus,
    IN  PVOID                   StatusBuffer,
    IN  UINT                    StatusBufferSize
);
static VOID                 ProtocolStatusComplete
(
    IN  NDIS_HANDLE             ProtocolBindingContext
);
static INT                  ProtocolReceivePacket
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNDIS_PACKET            Packet
);
static VOID                 ProtocolBindAdapter
(
    OUT PNDIS_STATUS            Status,
    IN  NDIS_HANDLE             BindContext,
    IN  PNDIS_STRING            DeviceName,
    IN  PVOID                   SystemSpecific1,
    IN  PVOID                   SystemSpecific2
);
static VOID                 ProtocolUnbindAdapter
(
    OUT PNDIS_STATUS            Status,
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  NDIS_HANDLE             UnbindContext
);
static NDIS_STATUS          ProtocolPnPEvent
(
    IN  NDIS_HANDLE             ProtocolBindingContext,
    IN  PNET_PNP_EVENT          NetPnPEvent
);
static VOID                 ProtocolUnload
(
        VOID
);
       NTSTATUS             DriverEntry
(
    IN  PDRIVER_OBJECT          DriverObject,
    IN  PUNICODE_STRING         RegistryPath
);

#ifdef ALLOC_PRAGMA

#pragma NDIS_INIT_FUNCTION      ( NDISProtocolCreateDevice          )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDeleteDevice          )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDispatch              )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDispatchRead          )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDispatchWrite         )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDispatchCleanup       )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDispatchDeviceControl )
#pragma NDIS_PAGEABLE_FUNCTION  ( NDISProtocolDriverUnload          )
#pragma NDIS_INIT_FUNCTION      ( DriverEntry                       )

#endif

/************************************************************************
*                                                                      *
*                            Static Global Var                         *
*                                                                      *
************************************************************************/

static ULONG                PrivateFlags        = PRIVATEFLAGS_DEFAULT;
static unsigned short int   EtherType           = ETH_P_DEFAULT;
static NDIS_HANDLE          NdisProtocolHandle  = ( NDIS_HANDLE )NULL;
static LIST_ENTRY           AdapterContextList;
static NDIS_SPIN_LOCK       Lock;
static NDIS_EVENT           BindsComplete;

#ifdef NDIS51
static ULONG                HighCancelId;
static ULONG                LowCancelId         = 0;
#endif

/************************************************************************/

static NTSTATUS NDISProtocolCreateDevice
(
    IN  PDRIVER_OBJECT  DriverObject,
    IN  ULONG           DeviceNumber
)
{
    NTSTATUS            status          = STATUS_SUCCESS;
    PDEVICE_OBJECT      DeviceObject    = NULL;
    PDEVICE_EXTENSION   DeviceExtension;
    UNICODE_STRING      DeviceName;
    UNICODE_STRING      SymbolicLinkName;
    SIZE_T              InternalNameLen;
    SIZE_T              ExternalNameLen;
    PWSTR               InternalName    = NULL;
    PWSTR               ExternalName    = NULL;

    KdPrint(( "Entering NDISProtocolCreateDevice()/n" ));
    InternalNameLen                 = sizeof( INTERNALNAME ) + 10 * sizeof( WCHAR );
    InternalName                    = ( PWSTR )ExAllocatePoolWithTag
    (
        PagedPool,
        InternalNameLen,
        PRIVATETAG
    );
    if ( NULL == InternalName )
    {
        status  = STATUS_INSUFFICIENT_RESOURCES;
        goto NDISProtocolCreateDevice_exit;
    }
    swprintf( InternalName, L"%s%u", INTERNALNAME, DeviceNumber );
    RtlInitUnicodeString( &DeviceName, InternalName );
    status                          = IoCreateDevice
    (
        DriverObject,
        sizeof( DEVICE_EXTENSION ),
        &DeviceName,
        FILE_DEVICE_NETWORK,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &DeviceObject
    );
    if ( !NT_SUCCESS( status ) )
    {
        goto NDISProtocolCreateDevice_exit;
    }
    DeviceObject->Flags            |= DO_DIRECT_IO;
    DeviceExtension                 = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
    DeviceExtension->DeviceObject   = DeviceObject;
    DeviceExtension->DeviceNumber   = DeviceNumber;
    ExternalNameLen                 = sizeof( EXTERNALNAME ) + 10 * sizeof( WCHAR );
    ExternalName                    = ( PWSTR )ExAllocatePoolWithTag
    (
        PagedPool,
        ExternalNameLen,
        PRIVATETAG
    );
    if ( NULL == ExternalName )
    {
        status  = STATUS_INSUFFICIENT_RESOURCES;
        goto NDISProtocolCreateDevice_exit;
    }
    swprintf( ExternalName, L"%s%u", EXTERNALNAME, DeviceNumber + 1 );
    RtlInitUnicodeString( &SymbolicLinkName, ExternalName );
    status                          = IoCreateSymbolicLink
    (
        &SymbolicLinkName,
        &DeviceName
    );

NDISProtocolCreateDevice_exit:

    if ( NULL != ExternalName )
    {
        ExFreePoolWithTag
        (
            ExternalName,
            PRIVATETAG
        );
        Exter
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值