WinPcap驱动程序的初始化与清除(六)(2)

2019-01-26 14:21

DriverEntry返回值是NTSTATUS的数据,NTSTATUS被定义为32位的无符号长整型。在驱动程序开发中,人们习惯用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 NdisRegisterProtocol( OUT PNDIS_STATUS Status,

OUT PNDIS_HANDLE NdisProtocolHandler,

IN NDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics, IN UINT CharacteristicsLength );

参数Status是指向调用者提供的一个变量的指针,该函数可以返回下列的值: NDIS_STATUS_SUCCESS

NDIS库把调用者注册为一个协议驱动程序 NDIS_STATUS_BAD_CHARACTERISTICS

对参数ProtocolCharacteristics 中MajorNdisVersion所描述的版本而言CharacteristicsLength太短 NDIS_STATUS_BAD_VERSION

参数ProtocolCharacteristics 中MajorNdisVersion描述的版本不可用 NDIS_STATUS_RESOURCES

资源不够,可能是内存,阻止NDIS库注册调用者

参数NdisProtocolHandle指向调用者提供的一个变量,函数将通过它返回一个描述已注册驱动的一个句柄。参数ProtocolCharacteristics指向一个

NDIS_PROTOCOL_CHARACTERISTICS结构体,由调用者设置。参数CharacteristicsLength描述ProtocolCharacteristics所指结构体的大小。

该调用的返回句柄NdisProtocolHandler对协议驱动程序是透明的,协议驱动程序必须保存该句柄,并在将来对NDIS的调用中作为输入参数传递,例如,打开低层适配器(调用NdisOpenAdapter函数时)。

在调用NdisRegisterProtocol之前,DriverEntry必须完成以下操作:

??????????对NDIS_PROTOCOL_CHARACTERISTICS结构

体进行零初始化,例如调用NdisZeroMemory函数。这将确保可选入口点的尚未使用的成员设置为NULL。如果该结构没被置零,那么在调用NdisRegisterProtocol之前,任何不使用的成员必须置为NULL;

??????????在NDIS_PROTOCOL_CHARACTERISTICS结构

中指定协议兼容的NDIS版本;

??????????在NDIS_PROTOCOL_CHARACTERISTICS结构

中设置驱动程序导出的必需的和可选的ProtocolXxx函数的地址。 在WinPcap的NPF中的具体实现为:首先分配一个NDIS_PROTOCOL_CHARACTERISTICS的结构体,然后执行零初始化,接着用协议数据(版本、名称等)与驱动程序所需回调函数的地址设置该结构体。最后调用NdisRegisterProtocol函数把NPF注册为一个NDIS协议驱动程序。下面为NPF中对应的代码:

//声明一个NDIS_PROTOCOL_CHARACTERISTICS结构实例ProtocolChar; NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;

//协议名称PacketDriver

NDIS_STRING ProtoName = NDIS_STRING_CONST(\

//对ProtocolChar的内存空间清零

RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

//用协议数据(版本、名称等)与回调函数地址设置ProtocolChar #ifdef #ifdef NDIS50

ProtocolChar.MajorNdisVersion = 5; #else

ProtocolChar.MajorNdisVersion = 3; #endif

ProtocolChar.MinorNdisVersion = 0; ProtocolChar.Reserved = 0;

ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete; ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete; ProtocolChar.SendCompleteHandler = NPF_SendComplete;

ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete; ProtocolChar.ResetCompleteHandler = NPF_ResetComplete; ProtocolChar.RequestCompleteHandler = NPF_RequestComplete; ProtocolChar.ReceiveHandler = NPF_tap;

ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete; ProtocolChar.StatusHandler = NPF_Status;

ProtocolChar.StatusCompleteHandler = NPF_StatusComplete; #ifdef NDIS50

ProtocolChar.BindAdapterHandler = NPF_BindAdapter; ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter; ProtocolChar.PnPEventHandler = NPF_PowerChange; ProtocolChar.ReceivePacketHandler = NULL; #endif

ProtocolChar.Name = ProtoName;

//把NPF注册为一个NDIS协议驱动程序 NdisRegisterProtocol( &Status,

&g_NdisProtocolHandle, &ProtocolChar,

sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

if (Status != NDIS_STATUS_SUCCESS) { //注册协议驱动程序到NDIF失败,程序结束 return Status; }

1.2.2 设置卸载例程和IRP的派遣函数

在DriverEntry函数中,一般设置卸载例程和IRP的派遣函数。设置卸载例程和设置派遣函数都是对驱动对象的设置。设备对象中的MajorFunction是一个函数指针数组,IRP_MJ_CREATE、IRP_MJ_ CLOSE、IRP_MJ_WR'lTE等代表数组的第几个元素。下列为NPF的DriverEntry函数中的设置:

DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open; DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close; DriverObject->MajorFunction[IRP_MJ_CLEANUP]= NPF_Cleanup; DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read; DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl; DriverObject->DriverUnload = NPF_Unload;// 卸载例程

1.2.3 获取系统中可用网络适配器的信息

函数getAdaptersList获取系统中可用的网络适配器信息,返回一个包含系统中可用网络适配器列表的字符串。如果getAdaptersList失败了,NPF试图通过调用getTcpBindings函数获得绑定了TCP/IP的网络适配器信息。函数getTcpBindings返回指向包含绑定了TCP/IP适配器的注册表键值的指针。

下面为DriverEntry函数中相关的代码。

bindP = getAdaptersList(); if (bindP == NULL) {

//在注册表中没找到适配器,试图复制TCP-IP绑定的适配器 tcpBindingsP = getTcpBindings();

if (tcpBindingsP == NULL) {

//没有找到绑定了TCP/IP的适配器,程序执行错误处理 goto RegistryError; }

bindP = (WCHAR*)tcpBindingsP;

bindT = (WCHAR*)(tcpBindingsP->Data);

} else {

bindT = bindP;

}

for (; *bindT != UNICODE_NULL;

bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) {

RtlInitUnicodeString(&macName, bindT);

NPF_CreateDevice(DriverObject, &macName);//给网络适配器创建一个设备 }

1.2.4 对可用的网络适配器创建一个设备

函数NPF_CreateDevice对一个给定的网络适配器创建一个设备。NPF驱动程序也调用NPF_CreateDevice函数,通过IoCreateDevice系统接口把Open/close,read/write与IOCTL请求的句柄地址传递给操作系统。

1.3 DriverEntry函数的具体实现

NPF的DriverEntry注册所有驱动程序的I/O回调函数、创建设备、在NDIS内把NPF定注册为一个协议驱动程序。NPF的DriverEntry函数的主要代码如下: packetNtx\\driver\\packet.c 91~282 NTSTATUS DriverEntry(

IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) {

?

/*根据操作系统的版本,定义跳过回环数据包的正确标识*/

//获得操作系统的版本

PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL); //根据不同的操作系统,定义跳过回环数据包的正确标识 if((OsMajorVersion == 5) && (OsMinorVersion == 0))

{ // Windows 2000 需要NDIS_FLAGS_DONT_LOOPBACK与

// NDIS_FLAGS_SKIP_LOOPBACK两个标识

g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K; } else

{ // Windows XP、Windows 2003与后续的操作系统

//只需要NDIS_FLAGS_DONT_LOOPBACK标识

g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK; }

/*初始化设备名称的前缀*/

NdisInitUnicodeString(&g_NPF_Prefix, g_NPF_PrefixBuffer);

/*获得CPU的个数,并保存该值*/ g_NCpu = NdisSystemProcessorCount();

/*零初化ProtocolChar结构体*/

RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));

/*向NDIS注册协议驱动程序*/

//用协议数据(版本、名称等)与回调函数地址设置ProtocolChar #ifdef NDIS50

ProtocolChar.MajorNdisVersion = 5; #else

ProtocolChar.MajorNdisVersion = 3; #endif

ProtocolChar.MinorNdisVersion = 0; ProtocolChar.Reserved = 0;

ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete; ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete; ProtocolChar.SendCompleteHandler = NPF_SendComplete;

ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete; ProtocolChar.ResetCompleteHandler = NPF_ResetComplete; ProtocolChar.RequestCompleteHandler = NPF_RequestComplete; ProtocolChar.ReceiveHandler = NPF_tap;

ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete; ProtocolChar.StatusHandler = NPF_Status;

ProtocolChar.StatusCompleteHandler = NPF_StatusComplete; #ifdef NDIS50

ProtocolChar.BindAdapterHandler = NPF_BindAdapter; ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter; ProtocolChar.PnPEventHandler = NPF_PowerChange; ProtocolChar.ReceivePacketHandler = NULL; #endif

ProtocolChar.Name = ProtoName;

//把NPF注册为一个NDIS协议驱动程序 NdisRegisterProtocol( &Status,

&g_NdisProtocolHandle,


WinPcap驱动程序的初始化与清除(六)(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:教育顾问呼出、学科分析、家庭教育话术-已印

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: