您的位置:首页 > 编程语言 > Java开发

关于Javabean或者实体的通用转化器

2013-07-02 12:55 483 查看

1.4.2.3 PacketAddAdapterNPF函数

[align=left]函数PacketAddAdapterNPF()向适配器链表g_AdaptersInfoList中添加一个节点。参数AdName是要添加的链表节点的适配器名称。如果函数成功则返回非0值。[/align]
[align=left]其主要代码如下所示:[/align]

[align=left]static BOOLEAN PacketAddAdapterNPF(PCHAR AdName, UINT flags)[/align]

[align=left]{[/align]
[align=left] LONG Status;[/align]
[align=left] LPADAPTER adapter = NULL;[/align]
[align=left] PPACKET_OID_DATA OidData = NULL;[/align]
[align=left] PADAPTER_INFO TmpAdInfo;[/align]
[align=left] PADAPTER_INFO TAdInfo; [/align]
[align=left] [/align]
[align=left] /*[/align]
[align=left] *检查ADAPTER_INFO::Name成员是否有足够的空间存储适配器名称[/align]
[align=left]*如果没有,函数返回失败[/align]
[align=left]*/[/align]
[align=left] if (strlen(AdName) + 1 > sizeof(TmpAdInfo->Name))[/align]
[align=left] {[/align]
[align=left] return FALSE;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left]/*获得g_AdaptersInfoMutex互斥信号*/[/align]
[align=left] WaitForSingleObject(g_AdaptersInfoMutex, INFINITE);[/align]
[align=left] [/align]
[align=left]/*查看适配器的名称是否已在适配器链表中,如是,则函数返回*/[/align]
[align=left] for(TAdInfo = g_AdaptersInfoList; TAdInfo != NULL; [/align]
[align=left]TAdInfo = TAdInfo->Next)[/align]
[align=left] {[/align]
[align=left] if(strcmp(AdName, TAdInfo->Name) == 0)[/align]
[align=left] {// AdName已存在链表中,函数返回[/align]
[align=left] ReleaseMutex(g_AdaptersInfoMutex);[/align]
[align=left] return TRUE;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //此处不能释放g_AdaptersInfoMutex互斥信号[/align]
[align=left]//如此时有两个线程试图添加同一个适配器,链表中将存在一个适配器的副本[/align]
[align=left] [/align]
[align=left] if(flags != INFO_FLAG_DONT_EXPORT)[/align]
[align=left] { //试图打开NPF适配器,查看它是否可用[/align]
[align=left] [/align]
[align=left] //试图打开适配器[/align]
[align=left] adapter = PacketOpenAdapterNPF(AdName);[/align]
[align=left] [/align]
[align=left] if(adapter != NULL)[/align]
[align=left] {[/align]
[align=left] //分配一个缓冲区,从驱动程序获得厂商的描述 [/align]
[align=left] OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,512);[/align]
[align=left] if (OidData == NULL) [/align]
[align=left] { //分配失败 [/align]
[align=left] PacketCloseAdapter(adapter);[/align]
[align=left] ReleaseMutex(g_AdaptersInfoMutex);[/align]
[align=left] TRACE_EXIT("PacketAddAdapterNPF");[/align]
[align=left] return FALSE;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left]//NPF适配器不可用,不添加到链表中 [/align]
[align=left] ReleaseMutex(g_AdaptersInfoMutex);[/align]
[align=left] TRACE_EXIT("AddAdapter");[/align]
[align=left] return FALSE;[/align]
[align=left] } [/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] /*[/align]
[align=left]*获得该适配器的PADAPTER_INFO结构体中各成员的值[/align]
[align=left]*/[/align]
[align=left] [/align]
[align=left] // PacketOpenAdapter成功,认为这是一个可用的适配器,[/align]
[align=left]//为它在适配器链表中分配一个条目。 [/align]
[align=left] TmpAdInfo = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(ADAPTER_INFO));[/align]
[align=left] if (TmpAdInfo == NULL) [/align]
[align=left] {//内存分配失败,函数返回[/align]
[align=left] …[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] // 复制适配器名称AdName到TmpAdInfo->Name中[/align]
[align=left] strncpy(TmpAdInfo->Name, AdName, [/align]
[align=left]sizeof(TmpAdInfo->Name)/ sizeof(TmpAdInfo->Name[0]) - 1);[/align]
[align=left] //无需给TmpAdInfo->Name添加结束符,[/align]
[align=left]//既然在尾部预留了一个字节,同时分配TmpAdInfo内存时已设为0。[/align]
[align=left] [/align]
[align=left] if(flags != INFO_FLAG_DONT_EXPORT)[/align]
[align=left] {[/align]
[align=left] PNPF_IF_ADDRESS_ITEM pAddressesFromRegistry;[/align]
[align=left] [/align]
[align=left] //对NIC驱动的查询,获得适配器的描述[/align]
[align=left]OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;[/align]
[align=left] OidData->Length = 256;[/align]
[align=left] ZeroMemory(OidData->Data, 256);[/align]
[align=left] [/align]
[align=left] Status = PacketRequest(adapter, FALSE, OidData);[/align]
[align=left] [/align]
[align=left] if(Status==0 || ((char*)OidData->Data)[0]==0)[/align]
[align=left] {[/align]
[align=left]//不能从NIC驱动程序获得适配器的描述信息 [/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //复制设备的描述[/align]
[align=left] strncpy(TmpAdInfo->Description, (PCHAR)OidData->Data,[/align]
[align=left] sizeof(TmpAdInfo->Description)/ sizeof(TmpAdInfo->Description[0]) - 1);[/align]
[align=left] //无需给TmpAdInfo->Name添加结束符,既然在尾部预留了一个[/align]
[align=left]//字节,同时分配TmpAdInfo内存时已设为0。[/align]
[align=left] [/align]
[align=left]//从注册表获得一个适配器的NetType结构体,[/align]
[align=left]//该结构体包含适配器的链接类型与速度[/align]
[align=left] Status = PacketGetLinkLayerFromRegistry(adapter, &(TmpAdInfo->LinkLayer));[/align]
[align=left] if (Status == FALSE)[/align]
[align=left] {//失败,函数返回[/align]
[align=left] …[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] //查询NIC驱动程序,获取适配器的MAC地址[/align]
[align=left]// 现在只支持以太网,等待补丁程序支持其它的链路层.[/align]
[align=left] OidData->Oid = OID_802_3_CURRENT_ADDRESS; [/align]
[align=left] OidData->Length = 256;[/align]
[align=left] ZeroMemory(OidData->Data, 256);[/align]
[align=left] [/align]
[align=left] Status = PacketRequest(adapter, FALSE, OidData);[/align]
[align=left] if(Status)[/align]
[align=left] {//成功获取MAC地址,地址长度设为6[/align]
[align=left] memcpy(TmpAdInfo->MacAddress, OidData->Data, 6);[/align]
[align=left] TmpAdInfo->MacAddressLen = 6; [/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {//获取MAC地址失败,设为00:00:00:00:00:00,长度设为0。 [/align]
[align=left] memset(TmpAdInfo->MacAddress, 0, 6);[/align]
[align=left] TmpAdInfo->MacAddressLen = 0;[/align]
[align=left] } [/align]
[align=left] [/align]
[align=left] //获取网络地址项PNPF_IF_ADDRESS_ITEM[/align]
[align=left] TmpAdInfo->pNetworkAddresses = NULL;[/align]
[align=left] //从注册表中获取一个适配器的网络地址项[/align]
[align=left] if(!PacketGetAddressesFromRegistry(TmpAdInfo->Name, [/align]
[align=left] &pAddressesFromRegistry))[/align]
[align=left] {[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left] PNPF_IF_ADDRESS_ITEM pCursor;[/align]
[align=left] [/align]
[align=left] //把pAddressesFromRegistry追加到链表[/align]
[align=left]//TmpAdInfo->pNetworkAddresses的尾部[/align]
[align=left] if (TmpAdInfo->pNetworkAddresses == NULL)[/align]
[align=left] {[/align]
[align=left] TmpAdInfo->pNetworkAddresses = [/align]
[align=left] pAddressesFromRegistry;[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left] pCursor = TmpAdInfo->pNetworkAddresses;[/align]
[align=left] while(pCursor->Next != NULL) [/align]
[align=left]pCursor = pCursor->Next;[/align]
[align=left] [/align]
[align=left] pCursor->Next = pAddressesFromRegistry;[/align]
[align=left] }[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] TmpAdInfo->Flags = INFO_FLAG_NDIS_ADAPTER; [/align]
[align=left]// NdisWan适配器不会被NPF驱动程序导出,[/align]
[align=left]//因此此处不可能见到它们[/align]
[align=left] [/align]
[align=left] //释放内存[/align]
[align=left] PacketCloseAdapter(adapter);[/align]
[align=left] GlobalFreePtr(OidData);[/align]
[align=left] }[/align]
[align=left] else[/align]
[align=left] {[/align]
[align=left] //是火线适配器,设置该标识,使后续调用将阻止它[/align]
[align=left] TmpAdInfo->Flags = INFO_FLAG_DONT_EXPORT;[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] /*更新g_AdaptersInfoList 链表*/[/align]
[align=left] TmpAdInfo->Next = g_AdaptersInfoList;[/align]
[align=left] g_AdaptersInfoList = TmpAdInfo;[/align]
[align=left] [/align]
[align=left]/*释放g_AdaptersInfoMutex互斥信号*/[/align]
[align=left] ReleaseMutex(g_AdaptersInfoMutex);[/align]
[align=left] [/align]
[align=left] return TRUE;[/align]

[align=left]}[/align]

函数PacketAddAdapterNPF()首先检查ADAPTER_INFO::Name成员是否有足够的空间存储适配器名称。然后获取g_AdaptersInfoMutex互斥信号。
查看要添加的适配器名称是否已在适配器链表中存在,如是,则函数返回。否则试图打开该NPF适配器,查看它是否可用。如果可用将分配一个缓冲区,用来从驱动程序获得厂商的描述信息。
获得该适配器的PADAPTER_INFO结构体中各成员的值。依次复制适配器名称,设备的描述,从注册表获得适配器的NetType结构体,查询NIC驱动程序,获取适配器的MAC地址,获取网络地址项PNPF_IF_ADDRESS_ITEM,并把它追加到链表TmpAdInfo->pNetworkAddresses的尾部。
最后更新g_AdaptersInfoList 链表,释放g_AdaptersInfoMutex互斥信号,函数成功返回。

函数调用了PacketRequest()、PacketGetLinkLayerFromRegistry()与PacketGetAddressesFromRegistry()函数。各函数的原型与作用分别如下:
函数PacketRequest()在驱动程序上执行一个查询/设置操作。函数原型如下:

BOOLEAN PacketRequest(LPADAPTER AdapterObject,

BOOLEAN Set,PPACKET_OID_DATA OidData)

参数AdapterObject指向一个_ADAPTER结构体。参数Set决定是设置(Set=TRUE)还是查询(Set=FALSE)操作。参数OidData是一个指向一个_PACKET_OID_DATA结构体的指针,该结构体包含了所接收的数据。
如果函数成功返回非0值。
[align=left]注意并不是所有的网络适配器实现了所有的查询/设置功能。 [/align]
[align=left] [/align]
该函数主要依赖于DeviceIoControl系统函数实现,如下面的调用

[align=left]Result=(BOOLEAN)DeviceIoControl([/align]

[align=left]AdapterObject->hFile,[/align]
[align=left](DWORD) Set ? (DWORD)BIOCSETOID : (DWORD)BIOCQUERYOID, OidData,[/align]
[align=left]sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData, sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL[/align]

[align=left]);[/align]

[align=left]在NPF中由NPF_IoControl函数中的如下代码处理该操作。[/align]

[align=left]NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)[/align]

[align=left]{[/align]
[align=left]…[/align]
[align=left]switch (FunctionCode){[/align]
[align=left]…[/align]
[align=left]case BIOCSETOID:[/align]
[align=left] case BIOCQUERYOID:[/align]
[align=left] …[/align]
[align=left]}[/align]
[align=left]…[/align]

[align=left]}[/align]

函数PacketGetLinkLayerFromRegistry()获得一个已打开适配器的NetType结构体,该结构体包含适配器的链路层的类型与速度(单位为bps)。函数原型如下:

[align=left]static BOOLEAN PacketGetLinkLayerFromRegistry([/align]

[align=left]LPADAPTER AdapterObject, NetType *type[/align]
[align=left])[/align]

[align=left]参数AdapterObject为一个已打开适配器的句柄,参数type是一个指向 NetType结构体的指针,它将被函数用链路层的类型与速度值填充。参数type的LinkType成员可以为下列的值之一: [/align]
[align=left]ØNdisMedium802_3: Ethernet (802.3) [/align]
[align=left]ØNdisMediumWan: WAN [/align]
[align=left]ØNdisMedium802_5: Token Ring (802.5) [/align]
[align=left]Ø NdisMediumFddi: FDDI [/align]
[align=left]ØNdisMediumAtm: ATM [/align]
[align=left]ØNdisMediumArcnet878_2: ARCNET (878.2) [/align]
[align=left] [/align]
[align=left]如果函数成功,返回非0值,否则返回0值。[/align]
该函数主要依赖于PacketRequest()函数实现,主要代码如下所示:

static BOOLEAN PacketGetLinkLayerFromRegistry(

LPADAPTER AdapterObject, NetType *type)
[align=left]{[/align]
[align=left] …[/align]
[align=left] //获得链路层的类型[/align]
[align=left] OidData->Oid = OID_GEN_MEDIA_IN_USE;[/align]
[align=left] OidData->Length = sizeof (ULONG);[/align]
[align=left] Status = PacketRequest(AdapterObject,FALSE,OidData);[/align]
[align=left] type->LinkType=*((UINT*)OidData->Data);[/align]
[align=left] [/align]
[align=left] //获得链路层的速度[/align]
[align=left] OidData->Oid = OID_GEN_LINK_SPEED;[/align]
[align=left] OidData->Length = sizeof (ULONG);[/align]
[align=left] Status = PacketRequest(AdapterObject,FALSE,OidData);[/align]
[align=left] …[/align]

}

[align=left]函数PacketGetAddressesFromRegistry()从注册表中获取一个适配器的网络地址项。函数原型如下:[/align]

static BOOLEAN PacketGetAddressesFromRegistry(

LPCSTR AdapterNameA,
PNPF_IF_ADDRESS_ITEM *ppItems

)

[align=left] 参数 AdapterName是存储适配器名称的字符串。参数ppItems是调用者分配的指向一个地址项指针的指针。函数将把该指针设置为从注册表中获得的地址。[/align]
[align=left]如果函数成功,返回非0值。[/align]
[align=left]函数从注册表中获得一个接口的信息,如IP地址、网络掩码地址与广播地址。用户传递进来的缓冲区将用npf_if_addr结构体填充,每一个都包含一个单独地址的数据。如果缓冲区已满,余下的地址信息将丢弃,因此如果只需要第一个地址,把它的大小设为sizeof(npf_if_addr)即可。[/align]
本文出自 “千江月” 博客,请务必保留此出处http://eslxf.blog.51cto.com/918801/198591
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: