winston 发表于 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.


bool IsLocalAdapter ( const char *pAdapterName ) const
...{
    BOOL ret_value = FALSE;

#define NET_CARD_KEY "System\CurrentControlSet\Control\Network\{4D36E972-E325-11CE-BFC1-08002BE10318}"
    char szDataBuf;
    DWORD dwDataLen = MAX_PATH;
    DWORD dwType = REG_SZ;
    HKEY hNetKey = NULL;
    HKEY hLocalNet = NULL;

    if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
      return FALSE;
    sprintf(szDataBuf, "%s\Connection", pAdapterName);
    if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
    ...{
      RegCloseKey(hNetKey);
      return FALSE;
    }
    if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
    ...{
      goto ret;
    }
    if (*((DWORD *)szDataBuf)!=0x01)
      goto ret;
    dwDataLen = MAX_PATH;
    if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
    ...{
      goto ret;
    }
    if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
      goto ret;

    ret_value = TRUE;

ret:
    RegCloseKey(hLocalNet);
    RegCloseKey(hNetKey);

    return ret_value!=0;

}

winston 发表于 2007-12-12 10:37:04

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


void GetLocalMAC(char *buf)
{
IP_ADAPTER_INFO *IpAdaptersInfo =NULL;
IP_ADAPTER_INFO *IpAdaptersInfoHead =NULL;

IpAdaptersInfo = (IP_ADAPTER_INFO *) GlobalAlloc(GPTR, sizeof(IP_ADAPTER_INFO ));

if (IpAdaptersInfo == NULL)
{
return;
}

DWORD dwDataSize = sizeof( IP_ADAPTER_INFO );
DWORD dwRetVal = GetAdaptersInfo(IpAdaptersInfo,&dwDataSize);

if ( ERROR_SUCCESS != dwRetVal)
{
GlobalFree( IpAdaptersInfo );
IpAdaptersInfo = NULL;

if( ERROR_BUFFER_OVERFLOW == dwRetVal)
{
   IpAdaptersInfo =(IP_ADAPTER_INFO *) GlobalAlloc( GPTR, dwDataSize );
   if (IpAdaptersInfo == NULL)
   {
    return;
   }
   if ( ERROR_SUCCESS != GetAdaptersInfo( IpAdaptersInfo, &dwDataSize ))
   {
    GlobalFree( IpAdaptersInfo );
    return;
   }

}
else
{
   return;
}

}

//Save the head pointer of IP_ADAPTER_INFO structures list.
IpAdaptersInfoHead = IpAdaptersInfo;

do{
if (IsLocalAdapter(IpAdaptersInfo->AdapterName))
{
   sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",
    IpAdaptersInfo->Address,
    IpAdaptersInfo->Address,
    IpAdaptersInfo->Address,
    IpAdaptersInfo->Address,
    IpAdaptersInfo->Address,
    IpAdaptersInfo->Address);
   //
   break;
}

IpAdaptersInfo = IpAdaptersInfo->Next;

}while (IpAdaptersInfo);

if (IpAdaptersInfoHead != NULL)
{
GlobalFree( IpAdaptersInfoHead );
}
}


BOOL IsLocalAdapter(char *pAdapterName)
{
BOOL ret_value = FALSE;

#define NET_CARD_KEY _T("System\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}")
char szDataBuf;
DWORD dwDataLen = MAX_PATH;
DWORD dwType = REG_SZ;
HKEY hNetKey = NULL;
HKEY hLocalNet = NULL;

if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
return FALSE;
wsprintf(szDataBuf, "%s\\Connection", pAdapterName);
if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
{
RegCloseKey(hNetKey);
return FALSE;
}
if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
{
goto ret;
}
if (*((DWORD *)szDataBuf)!=0x01)
goto ret;
dwDataLen = MAX_PATH;
if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
{
goto ret;
}
if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
goto ret;

ret_value = TRUE;

ret:
RegCloseKey(hLocalNet);
RegCloseKey(hNetKey);

return ret_value;
}



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

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

区分PnpInstanceID,如果前面有PCI就是本机的真实网卡,MediaSubType为01则是常见网卡,02为无线网卡。
页: [1]
查看完整版本: 区分本地网卡是物理网卡还是虚拟网卡