使用WMI可以获取本地计算机的mac信息,现在就用另外两种方法获取mac地址:
GetAdaptersInfo 和 GetAdaptersAddresses
GetAdaptersInfo
功能:
The GetAdaptersInfo function retrieves adapter information for the local computer.
原型:
DWORD GetAdaptersInfo(
_Out_ PIP_ADAPTER_INFO pAdapterInfo,
_Inout_ PULONG pOutBufLen
);
其中参数有PIP_ADAPTER_INFO:
typedef struct _IP_ADAPTER_INFO {
struct _IP_ADAPTER_INFO* Next;
DWORD ComboIndex;
char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
UINT AddressLength;
BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD Index;
UINT Type;
UINT DhcpEnabled;
PIP_ADDR_STRING CurrentIpAddress;
IP_ADDR_STRING IpAddressList;
IP_ADDR_STRING GatewayList;
IP_ADDR_STRING DhcpServer;
BOOL HaveWins;
IP_ADDR_STRING PrimaryWinsServer;
IP_ADDR_STRING SecondaryWinsServer;
time_t LeaseObtained;
time_t LeaseExpires;
} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO;
上面的结构体中,我们注意关注Type、AddressLength、Address
Type:
#define MIB_IF_TYPE_OTHER 1
#define MIB_IF_TYPE_ETHERNET 6
#define MIB_IF_TYPE_TOKENRING 9
#define MIB_IF_TYPE_FDDI 15
#define MIB_IF_TYPE_PPP 23
#define MIB_IF_TYPE_LOOPBACK 24
#define MIB_IF_TYPE_SLIP 28
上代码:
bool GetMacAddressByAdaptersInfo(std::string &mac_address)
{
bool ret = false;
ULONG out_buf_len = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO adapter_info = (IP_ADAPTER_INFO*)malloc(sizeof(IP_ADAPTER_INFO));
if (adapter_info == NULL)
return false;
// Make an initial call to GetAdaptersInfo to get the necessary size into the out_buf_len variable
if (GetAdaptersInfo(adapter_info, &out_buf_len) == ERROR_BUFFER_OVERFLOW)
{
free(adapter_info);
adapter_info = (IP_ADAPTER_INFO *)malloc(out_buf_len);
if (adapter_info == NULL)
return false;
}
if (GetAdaptersInfo(adapter_info, &out_buf_len) == NO_ERROR)
{
PIP_ADAPTER_INFO adapter = adapter_info;
for (; adapter != NULL; adapter = adapter->Next)
{
// 确保是以太网
if (adapter->Type != MIB_IF_TYPE_ETHERNET)
continue;
// 确保MAC地址的长度为 00-00-00-00-00-00
if (adapter->AddressLength != 6)
continue;
std::cout << "GetMacAddressByAdaptersInfo: " <<std::hex << int(adapter->Address[0]) <<" "
<< int(adapter->Address[1]) << " "
<< int(adapter->Address[2]) << " "
<< int(adapter->Address[3]) << " "
<< int(adapter->Address[4]) << " "
<< int(adapter->Address[5]) << std::endl;
ret = true;
break;
}
}
free(adapter_info);
return ret;
}
注意:
On Windows XP and later: Use the GetAdaptersAddresses function instead of GetAdaptersInfo.
所以稍后会介绍GetAdaptersAddresses。
GetAdaptersAddresses
功能:
The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.
原型:
“`cpp
ULONG WINAPI GetAdaptersAddresses(
In ULONG Family,
In ULONG Flags,
In PVOID Reserved,
Inout PIP_ADAPTER_ADDRESSES AdapterAddresses,
Inout PULONG SizePointer
);
第一个参数Family我们设置为AF_UNSPEC:
Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled.
其中参数PIP_ADAPTER_ADDRESSES:
```cpp
typedef struct _IP_ADAPTER_ADDRESSES {
union {
ULONGLONG Alignment;
struct {
ULONG Length;
DWORD IfIndex;
};
};
struct _IP_ADAPTER_ADDRESSES *Next;
PCHAR AdapterName;
PIP_ADAPTER_UNICAST_ADDRESS FirstUnicastAddress;
PIP_ADAPTER_ANYCAST_ADDRESS FirstAnycastAddress;
PIP_ADAPTER_MULTICAST_ADDRESS FirstMulticastAddress;
PIP_ADAPTER_DNS_SERVER_ADDRESS FirstDnsServerAddress;
PWCHAR DnsSuffix;
PWCHAR Description;
PWCHAR FriendlyName;
BYTE PhysicalAddress[MAX_ADAPTER_ADDRESS_LENGTH];
DWORD PhysicalAddressLength;
DWORD Flags;
DWORD Mtu;
DWORD IfType;
IF_OPER_STATUS OperStatus;
DWORD Ipv6IfIndex;
DWORD ZoneIndices[16];
PIP_ADAPTER_PREFIX FirstPrefix;
ULONG64 TransmitLinkSpeed;
ULONG64 ReceiveLinkSpeed;
PIP_ADAPTER_WINS_SERVER_ADDRESS_LH FirstWinsServerAddress;
PIP_ADAPTER_GATEWAY_ADDRESS_LH FirstGatewayAddress;
ULONG Ipv4Metric;
ULONG Ipv6Metric;
IF_LUID Luid;
SOCKET_ADDRESS Dhcpv4Server;
NET_IF_COMPARTMENT_ID CompartmentId;
NET_IF_NETWORK_GUID NetworkGuid;
NET_IF_CONNECTION_TYPE ConnectionType;
TUNNEL_TYPE TunnelType;
SOCKET_ADDRESS Dhcpv6Server;
BYTE Dhcpv6ClientDuid[MAX_DHCPV6_DUID_LENGTH];
ULONG Dhcpv6ClientDuidLength;
ULONG Dhcpv6Iaid;
PIP_ADAPTER_DNS_SUFFIX FirstDnsSuffix;
} IP_ADAPTER_ADDRESSES, *PIP_ADAPTER_ADDRESSES;
class="se-preview-section-delimiter">
上面结构体中我们关注:PhysicalAddressLength、PhysicalAddress
上代码:
bool GetMacAddressByAdaptersAddresses(std::string &mac_address)
{
bool ret = false;
ULONG out_buf_len = sizeof(IP_ADAPTER_ADDRESSES);
PIP_ADAPTER_ADDRESSES addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_len);
if (addresses == NULL)
return false;
// Make an initial call to GetAdaptersAddresses to get the necessary size into the ulOutBufLen variable
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &out_buf_len) == ERROR_BUFFER_OVERFLOW)
{
free(addresses);
addresses = (IP_ADAPTER_ADDRESSES*)malloc(out_buf_len);
if (addresses == NULL)
return false;
}
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, addresses, &out_buf_len) == NO_ERROR)
{
// If successful, output some information from the data we received
PIP_ADAPTER_ADDRESSES curr_addresses = addresses;
for (; curr_addresses != NULL; curr_addresses = curr_addresses->Next)
{
// 确保MAC地址的长度为 00-00-00-00-00-00
if (curr_addresses->PhysicalAddressLength != 6)
continue;
std::cout << "GetMacAddressByAdaptersAddresses: " << std::hex << int(curr_addresses->PhysicalAddress[0]) << " "
<< int(curr_addresses->PhysicalAddress[1]) << " "
<< int(curr_addresses->PhysicalAddress[2]) << " "
<< int(curr_addresses->PhysicalAddress[3]) << " "
<< int(curr_addresses->PhysicalAddress[4]) << " "
<< int(curr_addresses->PhysicalAddress[5]) << std::endl;
ret = true;
break;
}
}
free(addresses);
return ret;
}