《winpcap驱动程序的初始化与清除(六)》由会员分享,可在线阅读,更多相关《winpcap驱动程序的初始化与清除(六)(28页珍藏版)》请在金锄头文库上搜索。
1、深度剖析 WinPcap 之 (六)驱动程序的初始化与清除驱动程序的初始化主要由函数 DriverEntry完成,卸载主要由函数 DriverUnload完成。下面主要分析驱动程序的初始化与清除过程,以及相关的基础知识。图 5-1 函数调用关系图1.1 结构体_NDIS_PROTOCOL_CHARACTERISTICS结构体_NDIS_PROTOCOL_CHARACTERISTICS 的定义如下:typedef struct _NDIS_PROTOCOL_CHARACTERISTICS UCHAR MajorNdisVersion;UCHAR MinorNdisVersion;UINT Res
2、erved;OPEN_ADAPTER_COMPLETE_HANDLER OpenAdapterCompleteHandler;CLOSE_ADAPTER_COMPLETE_HANDLER CloseAdapterCompleteHandler;SEND_COMPLETE_HANDLER SendCompleteHandler;TRANSFER_DATA_COMPLETE_HANDLER TransferDataCompleteHandler;RESET_COMPLETE_HANDLER ResetCompleteHandler;REQUEST_COMPLETE_HANDLER RequestC
3、ompleteHandler;RECEIVE_HANDLER ReceiveHandler;RECEIVE_COMPLETE_HANDLER ReceiveCompleteHandler;STATUS_HANDLER StatusHandler;STATUS_COMPLETE_HANDLER StatusCompleteHandler;NDIS_STRING Name;/使用下列任何成员,需要把 MajorNdisVersion设置为 0x04或 0x05/RECEIVE_PACKET_HANDLER ReceivePacketHandler;BIND_HANDLER BindAdapterH
4、andler;UNBIND_HANDLER UnbindAdapterHandler;PNP_EVENT_HANDLER PnPEventHandler;UNLOAD_PROTOCOL_HANDLER UnloadHandler;/使用下列任何成员,需要把 MajorNdisVersion设置为 0x05/面向连接的协议驱动程序使用,不分析。/CO_SEND_COMPLETE_HANDLER CoSendCompleteHandler;CO_STATUS_HANDLER CoStatusHandler;CO_RECEIVE_PACKET_HANDLER CoReceivePacketHandl
5、er;CO_AF_REGISTER_NOTIFY_HANDLER CoAfRegisterNotifyHandler; NDIS_PROTOCOL_CHARACTERISTICS, *PNDIS_PROTOCOL_CHARACTERISTICS;下面分别说明结构体_NDIS_PROTOCOL_CHARACTERISTICS 各成员的作用,其中,只在面向连接的协议驱动程序中使用的成员不作分析说明。MajorNdisVersion描述驱动程序所使用 NDIS库的主要版本。当前值为 0x05(WinPcap 当前使用的为版本5,NDIS 目前已到版本 6),虽然 NDIS库支持早期采用 NDIS V
6、4.0开发的驱动程序,但不再对 V3.0版本的协议驱动程序进行支持。MinorNdisVersion描述 NDIS的次版本,当前为 0x00。Reserved该成员保留给系统使用。OpenAdapterCompleteHandler这是一个必须提供的函数。如果协议驱动程序对 NdisOpenAdapter的调用返回NDIS_STATUS_PENDING,则接着调用 ProtocolOpenAdapterComplete来完成绑定操作。CloseAdapterCompleteHandler这是一个必须提供的函数。如果协议驱动程序对 NdisCloseAdapter的调用返回NDIS_STATUS
7、_PENDING,则接着调用 ProtocolCloseAdapterComplete来完成解除绑定操作。SendCompleteHandler这是一个必须提供的函数。如果协议驱动程序对 NdisSendPackets或 NdisSend 的调用返回 NDIS_STATUS_PENDING,则接着调用 SendCompleteHandler来完成发送处理。TransferDataCompleteHandler如果协议驱动程序可以把它自己绑定到一个低层非面向连接的 NIC驱动程序(以NdisMIndicateReceivePacket指定并不是接收所有的数据包)上,这就是一个必须提供的函数。当协
8、议驱动程序发起传输数据请求,对 NdisTransferData的调用返回NDIS_STATUS_PENDING时,ProtocolTransferDataComplete 函数被调用。专门面向连接的协议驱动程序不需要 ProtocolTransferDataComplete 函数。ResetCompleteHandler这是一个必须提供的函数。当协议驱动程序调用 NdisReset函数执行复位操作,返回值为NDIS_STATUS_PENDING,则接着调用 ProtocolResetComplete完成复位操作。RequestCompleteHandler这是一个必须提供的函数。当协议驱动程
9、序调用 NdisRequest函数查询和设置操作,返回值为 NDIS_STATUS_PENDING,则调用 ProtocolRequestComplete完成操作。ReceiveHandler对绑定到一个非面向连接的 NIC驱动程序上的 NDIS协议驱动程序,这是一个必须提供的函数。ProtocolReceive 决定协议驱动程序的使用者对一个被接收的网络数据包是否感兴趣,如果感兴趣,就复制所需要的数据,可能地,调用 NdisTransferData重新获取剩余的所需数据包。ReceiveCompleteHandler这是一个必须提供的函数。驱动程序完成前面所述的一个或多个从一个 NIC驱动程
10、序接收所需数据的操作后,ProtocolReceiveComplete 完成诸如通知协议驱动程序使用者之类的后处理。StatusHandler这是一个必须提供的函数。ProtocolStatus 函数用来处理低层 NIC驱动程序所指示状态的改变。StatusCompleteHandler这是一个必须提供的函数。ProtocolStatusComplete 完成一个状态改变的操作,该操作由底层驱动程序调用 NdisMIndicateStatus发起。Name一个 NDIS_STRING类型,包含调用者初始化的一个字符串,用来命名该驱动程序,采用系统默认的字符集。对 Windows 2000与后面
11、的驱动,该字符串为 Unicode字符。也就是说,对 Windows 2000与以后的版本,NDIS 定义 NDIS_STRING类型为一个 UNICODE_STRING类型。当协议被安装时,该字符串必须与注册表所指定的(在 Services条目之下)匹配。NdisRegisterProtocol把所提供的字符串转换为大写字符,因此一个协议驱动程序的编写者不能假设通过改变一个已经注册协议名称的大小写来为驱动创建一个唯一的名称。ReceivePacketHandler这是一个可选函数。如果协议驱动程序绑定到支持多数据包(multipacket )的 NIC驱动程序(通过调用 NdisMIndic
12、ateReceivePacket指定),那么 ProtocolReceivePacket函数应该被提供。BindAdapterHandler这是一个必须提供的函数。NDIS 调用该函数请求协议驱动程序绑定到低层网卡或虚拟网卡上,网卡名作为该处理程序的参数传递。UnbindAdapterHandler这是一个必须提供的函数。NDIS 调用 ProtocolUnbindAdapter释放对低层网卡或虚拟网卡的绑定,网卡名作为参数传递。当绑定成功解除时,ProtocolUnbindAdapter 函数调用NdisCloseAdapter,并释放资源。PnPEventHandler这是一个必须提供的函
13、数。NDIS 调用 ProtocolPnPEvent来指示即插即用事件或电源管理事件。UnloadHandler这是一个可选函数。NDIS 调用 ProtocolUnload函数来响应用户卸载中间层驱动程序的请求。对于每一个绑定的适配器,在调用 NDIS的 ProtocolUnbindAdapter 之后,调用ProtocolUnload函数卸载驱动程序。ProtocolUnload 执行驱动程序决定的清除操作。1.2 NPF的 DriverEntry函数的主要流程和编写普通应用程序一样,驱动程序也有个入口函数,也就是首先被执行的函数。该函数通常被命名为 DriverEntry,可以指定另外的
14、名称,但最好遵循这个名称。该函数的原型如下:NTSTATUSDriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath);DriverEntry主要是对驱动程序进行初始化工作,它由系统进程所调用。在 Windows中有个特殊的进程叫做系统进程。打开进程管理器,可见里面有个名为 System的进程就是系统进程。系统进程在系统启动的时候,就已经被创建了。图 5-2 System进程驱动加载的时候,系统进程启动新的线程,调用执行体组件中的对象管理器,创建一个驱动对象。这个驱动对象是一个 DRIVER_OBJEC
15、T的结构体。另外,系统进程调用执行体组件中的配置管理程序,查询此驱动程序在注册表中对应的项。系统线程调用驱动程序的 DriverEntry例程时,同时传进两个参数,分别是pDrivelobject和 pRegistryPath。其中,第一个是指向刚才被创建驱动对象的指针,第二个是指向设备服务键的键名称符串的指针。为了和 NDIS库建立通信,驱动程序的 DriverEntry必须调用 NdisRegisterProtocol作为协议驱动程序注册,稍候将作详细描述。DriverEntry返回值是 NTSTATUS的数据,NTSTATUS 被定义为 32位的无符号长整型。在驱动程序开发中,人们习惯用
16、 NTSTATUS返回状态。DriverEntry 的返回值如果表示成功,则意味着加载驱动成功,否则意味着加载驱动失败,调用对象管理程序销毁驱动对象。如果该程序成功,它必须返回 STATUS_SUCCESS,否则,它必须返回一个在 ntstatus.h定义的错误状态码。下面列出 STATUS_SUCCESS与 STATUS_UNSUCCESSFUL的定义。st1:*behavior:url(#ieooui) #define STATUS_SUCCESS (NTSTATUS)0x00000000L)#define STATUS_UNSUCCESSFUL (NTSTATUS)0xC0000001L)1.2.1 协议驱动程序注册驱动程序在 DriverEntry环境中通过调用 NdisRegisterProtocol向 NDIS注册ProtocolXxx函数。NdisRegisterProtocol 定义如下:VOID NdisRegisterPro