关于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
相关文章推荐
- java 中实体Bean和Map互相转化
- java 将集合中的对象转化成成实体Bean
- java 将集合中的对象转化成成实体Bean
- [示例代码]通用JavaBean资源配置(Generic JavaBean Resources)
- java中Map转化为bean
- Java实现Slor实体bean数据的索引创建
- windows下关于使用eclipse开发web服务器后台项目完整配置(jsp+javabean+servlet)
- 如何将java文件转化成jar 或者exe
- 读取.sql文件,转化为javabean
- 关于Java二进制和十六进制转化的一点问题
- xml与java实体相互转化
- 关于Java中List对象的分页思想,按10个或者n个数对list进行分组
- Java中关于Json对象类型和字符串类型之间互相转化的问题
- java集合或对象转化为json数组或者对象的方法
- 从别人那里转来的关于java中时间日期的转化 大家一起来学习一下
- 关于java中方法或者函数,形参,实参的个人理解
- JavaBean List Map Json的转化
- java方式的将java对象以及list或者map转化为json数据
- java.text.format 将字符串“060503”转化为06:05:03或者将"20081002102030“转化为2008-10-02 10:00:30
- 利用Java的反射机制实现Bean实体与Map自动转换的工具类