找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 9389|回复: 1

区分本地网卡是物理网卡还是虚拟网卡

[复制链接]
发表于 2007-12-12 10:36:09 | 显示全部楼层 |阅读模式
GetAdaptersInfo 可以获得本机所有网卡的信息,然而这些网卡中可能包括虚拟网卡。例如,若安装了 VMWare 或者某些 VPN 客户端软件,则会出现若干虚拟网卡。它们在形式上与物理网卡几乎没有区别。 ipconfig 将它们与本地物理网卡等同对待。

有些人建议使用 MAC 地址中的 "locally administread bit" 来区分。而事实证明这是靠不住的。http://hi.baidu.com/xzq2000/blog ... cd762f07088b95.html
是目前我找到的比较实用的办法。

其原理是先由 GetAdaptersInfo 获取所有网卡的基本信息。然后利用网卡名去注册表中查找对应的硬件信息。若是物理网卡,其硬件信息中通常会包含 PCI 。

例如,某个网卡的名为 {ACA306D0-1D69-4116-BC2B-919B428AD084}。
他在注册表中的信息所在位置为:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{ACA306D0-1D69-4116-BC2B-919B428AD084}\Connection

若PnpInstanceID的值以PCI开头,说明是物理网卡,MediaSubType为01则是常见网卡,02为无线网卡。

以下代码是从上述网页中转贴。该例中仅当网卡为有线物理网卡时才返回true.
  1. bool IsLocalAdapter ( const char *pAdapterName ) const
  2. ...{
  3.     BOOL ret_value = FALSE;
  4. #define NET_CARD_KEY "System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}"
  5.     char szDataBuf[MAX_PATH+1];
  6.     DWORD dwDataLen = MAX_PATH;
  7.     DWORD dwType = REG_SZ;
  8.     HKEY hNetKey = NULL;
  9.     HKEY hLocalNet = NULL;
  10.     if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
  11.         return FALSE;
  12.     sprintf(szDataBuf, "%s\Connection", pAdapterName);
  13.     if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
  14.     ...{
  15.         RegCloseKey(hNetKey);
  16.         return FALSE;
  17.     }
  18.     if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
  19.     ...{
  20.         goto ret;
  21.     }
  22.     if (*((DWORD *)szDataBuf)!=0x01)
  23.         goto ret;
  24.     dwDataLen = MAX_PATH;
  25.     if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
  26.     ...{
  27.         goto ret;
  28.     }
  29.     if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
  30.         goto ret;
  31.     ret_value = TRUE;
  32. ret:
  33.     RegCloseKey(hLocalNet);
  34.     RegCloseKey(hNetKey);
  35.     return ret_value!=0;
  36. }
复制代码
 楼主| 发表于 2007-12-12 10:37:04 | 显示全部楼层

获得正确本地MAC地址,区分虚拟网卡

  1. void GetLocalMAC(char *buf)
  2. {
  3. IP_ADAPTER_INFO *IpAdaptersInfo =NULL;
  4. IP_ADAPTER_INFO *IpAdaptersInfoHead =NULL;
  5. IpAdaptersInfo = (IP_ADAPTER_INFO *) GlobalAlloc(GPTR, sizeof(IP_ADAPTER_INFO ));
  6. if (IpAdaptersInfo == NULL)
  7. {
  8.   return;
  9. }
  10. DWORD dwDataSize = sizeof( IP_ADAPTER_INFO );
  11. DWORD dwRetVal = GetAdaptersInfo(IpAdaptersInfo,&dwDataSize);
  12. if ( ERROR_SUCCESS != dwRetVal)
  13. {
  14.   GlobalFree( IpAdaptersInfo );
  15.   IpAdaptersInfo = NULL;
  16.   if( ERROR_BUFFER_OVERFLOW == dwRetVal)
  17.   {
  18.    IpAdaptersInfo =(IP_ADAPTER_INFO *) GlobalAlloc( GPTR, dwDataSize );
  19.    if (IpAdaptersInfo == NULL)
  20.    {
  21.     return;
  22.    }
  23.    if ( ERROR_SUCCESS != GetAdaptersInfo( IpAdaptersInfo, &dwDataSize ))
  24.    {
  25.     GlobalFree( IpAdaptersInfo );
  26.     return;
  27.    }
  28.   }
  29.   else
  30.   {
  31.    return;
  32.   }
  33. }
  34. //Save the head pointer of IP_ADAPTER_INFO structures list.
  35. IpAdaptersInfoHead = IpAdaptersInfo;
  36. do{
  37.   if (IsLocalAdapter(IpAdaptersInfo->AdapterName))
  38.   {
  39.    sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",
  40.     IpAdaptersInfo->Address[0],
  41.     IpAdaptersInfo->Address[1],
  42.     IpAdaptersInfo->Address[2],
  43.     IpAdaptersInfo->Address[3],
  44.     IpAdaptersInfo->Address[4],
  45.     IpAdaptersInfo->Address[5]);
  46.    //
  47.    break;
  48.   }
  49.   IpAdaptersInfo = IpAdaptersInfo->Next;
  50. }while (IpAdaptersInfo);
  51. if (IpAdaptersInfoHead != NULL)
  52. {
  53.   GlobalFree( IpAdaptersInfoHead );
  54. }
  55. }
  56. BOOL IsLocalAdapter(char *pAdapterName)
  57. {
  58. BOOL ret_value = FALSE;
  59. #define NET_CARD_KEY _T("System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}")
  60. char szDataBuf[MAX_PATH+1];
  61. DWORD dwDataLen = MAX_PATH;
  62. DWORD dwType = REG_SZ;
  63. HKEY hNetKey = NULL;
  64. HKEY hLocalNet = NULL;
  65. if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
  66.   return FALSE;
  67. wsprintf(szDataBuf, "%s\\Connection", pAdapterName);
  68. if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
  69. {
  70.   RegCloseKey(hNetKey);
  71.   return FALSE;
  72. }
  73. if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
  74. {
  75.   goto ret;
  76. }
  77. if (*((DWORD *)szDataBuf)!=0x01)
  78.   goto ret;
  79. dwDataLen = MAX_PATH;
  80. if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
  81. {
  82.   goto ret;
  83. }
  84. if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
  85.   goto ret;
  86. ret_value = TRUE;
  87. ret:
  88. RegCloseKey(hLocalNet);
  89. RegCloseKey(hNetKey);
  90. return ret_value;
  91. }
复制代码


以前的那个无法区分虚拟网卡,所以在得到MAC地址时会出现大量重复的现象,非常麻烦,这个就没有问题了。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}\{ACA306D0-1D69-4116-BC2B-919B428AD084}\Connection
网卡在注册表里的位置

区分PnpInstanceID,如果前面有PCI就是本机的真实网卡,MediaSubType为01则是常见网卡,02为无线网卡。
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-4-19 09:11 , Processed in 0.015526 second(s), 8 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表