日期: 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
更新: 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