GetAdaptersInfo -20151116 防止返回的mac出现null

20151116

From:http://blog.csdn.net/weiyumingwww/article/details/17554461

转载URL:http://www.cnblogs.com/ourran/p/4968502.html

测试环境win7 x64 vs2013

工程下载地址:链接:http://pan.baidu.com/s/1pJAbwgz 密码:ifst

代码改为:

mac.h 内容

#ifndef __MAC_MAC_H
#define __MAC_MAC_H#include <windows.h>
#include <iphlpapi.h>       // API GetAdaptersInfo 头文件
#include <shlwapi.h>        // API StrCmpIA 头文件
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "shlwapi.lib")
#include <Strsafe.h>        // API StringCbPrintfA 头文件
#include <shellapi.h>       // API lstrcpyA 头文件#define BUF_SIZE 254
#define MAX_SIZE 254UINT GetAdapterCharacteristics(char* adapter_name);
int GetMAC(BYTE mac[BUF_SIZE]);
void GetMacAddress( char* mac );#endif

mac.c 内容

#include "stdafx.h"
#include "mac.h"

//
// 功能:获取适配器特性
// 参数:
// adapter_name 适配器 ID
// 返回值:成功则返回由参数指定的适配器的特性标志,是一个 DWORD 值,失败返回 0
//
UINT GetAdapterCharacteristics(char* adapter_name)
{
if(adapter_name == NULL || adapter_name[0] == 0)
return 0;

HKEY root = NULL;
// 打开存储适配器信息的注册表根键
if(ERROR_SUCCESS != RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &root))
return 0;

DWORD subkeys = 0;
// 获取该键下的子键数
if(ERROR_SUCCESS != RegQueryInfoKeyA(root, NULL, NULL, NULL, &subkeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
subkeys = 100;

DWORD ret_value = 0;
for(DWORD i = 0; i < subkeys; i++)
{
// 每个适配器用一个子键存储,子键名为从 0 开始的 4 位数
char subkey[MAX_SIZE];
memset(subkey, 0, MAX_SIZE);
StringCbPrintfA(subkey, MAX_SIZE, "%04u", i);

// 打开该子键
HKEY hKey = NULL;
if(ERROR_SUCCESS != RegOpenKeyExA(root, subkey, 0, KEY_READ, &hKey))
continue;

// 获取该子键对应的适配器 ID,存于 name 中
char name[MAX_PATH];
DWORD type = 0;
DWORD size = MAX_PATH;
if(ERROR_SUCCESS != RegQueryValueExA(hKey, "NetCfgInstanceId", NULL, &type, (LPBYTE)name, &size))
{
RegCloseKey(hKey);
continue;
}

// 对比该适配器 ID 是不是要获取特性的适配器 ID
if(StrCmpIA(name, adapter_name) != 0)
{
RegCloseKey(hKey);
continue;
}

// 读取该适配器的特性标志,该标志存储于值 Characteristics 中
DWORD val = 0;
size = 4;
LSTATUS ls = RegQueryValueExA(hKey, "Characteristics", NULL, &type, (LPBYTE)&val, &size);
RegCloseKey(hKey);

if(ERROR_SUCCESS == ls)
{
ret_value = val;
break;
}
}

RegCloseKey(root);
return ret_value;
}

//
// 功能:获取 Mac 地址的二进制数据
// 参数:
// mac 用于输出 Mac 地址的二进制数据的缓冲区指针
// 返回值:成功返回 mac 地址的长度,失败返回 0,失败时 mac 中保存一些简单的错误信息,可适当修改,用于调试
//
int GetMAC(BYTE mac[BUF_SIZE])
{
#define NCF_PHYSICAL 0x4
DWORD AdapterInfoSize = 0;
if(ERROR_BUFFER_OVERFLOW != GetAdaptersInfo(NULL, &AdapterInfoSize))
{
StringCbPrintfA((LPSTR)mac, BUF_SIZE, "GetMAC Failed! ErrorCode: %d", GetLastError());
return 0;
}

void* buffer = malloc(AdapterInfoSize);
if(buffer == NULL)
{
lstrcpyA((LPSTR)mac, "GetMAC Failed! Because malloc failed!");
return 0;
}

PIP_ADAPTER_INFO pAdapt = (PIP_ADAPTER_INFO)buffer;
if(ERROR_SUCCESS != GetAdaptersInfo(pAdapt, &AdapterInfoSize))
{
StringCbPrintfA((LPSTR)mac, BUF_SIZE, "GetMAC Failed! ErrorCode: %d", GetLastError());
free(buffer);
return 0;
}

int mac_length = 0;
while(pAdapt)
{
if(pAdapt->AddressLength >= 6 && pAdapt->AddressLength <= 8)
{
memcpy(mac, pAdapt->Address, pAdapt->AddressLength);
mac_length = pAdapt->AddressLength;

UINT flag = GetAdapterCharacteristics(pAdapt->AdapterName);
BOOL is_physical = ((flag & NCF_PHYSICAL) == NCF_PHYSICAL);
if(is_physical)
break;
}
pAdapt = pAdapt->Next;
}
free(buffer);
return mac_length;
}

//
// 功能:获取 Mac 地址,使用时直接调用此函数即可
// 参数:
// mac 用于存储 Mac 地址的缓冲区指针
// 返回值:无返回值,函数执行完后会把 Mac 地址以16进制的形式存于参数指定的缓冲区中,若有错误,缓冲区中保存的是错误信息
//
void GetMacAddress( char* mac )
{
BYTE buf[BUF_SIZE];
memset(buf, 0, BUF_SIZE);

int len = GetMAC(buf);
if(len <= 0)
{
lstrcpyA(mac, (LPCSTR)buf);
return;
}

if(len == 6)
StringCbPrintfA(mac, BUF_SIZE, "%02X-%02X-%02X-%02X-%02X-%02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
else
StringCbPrintfA(mac, BUF_SIZE, "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
}

用方法获取到的mac在部分机器上会出现获取到的mac为null;

20150923

From:https://msdn.microsoft.com/en-us/library/aa365917

控制台工程下载地址: 链接:http://pan.baidu.com/s/1o6xjJmy 密码:gyxo

mfc工程下载地址: 链接:http://pan.baidu.com/s/1pJORZw3 密码:djau

GetAdaptersInfo function

The GetAdaptersInfo function retrieves adapter information for the local computer.

On Windows XP and later:  Use the GetAdaptersAddresses function instead of GetAdaptersInfo.

Syntax

C++
DWORD GetAdaptersInfo(_Out_   PIP_ADAPTER_INFO pAdapterInfo,_Inout_ PULONG           pOutBufLen
);

Examples

This example retrieves the adapter information and prints various properties of each adapter.

C++
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "IPHLPAPI.lib")#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))/* Note: could also use malloc() and free() */int __cdecl main()
{/* Declare and initialize variables */// It is possible for an adapter to have multiple
// IPv4 addresses, gateways, and secondary WINS servers
// assigned to the adapter.
//
// Note that this sample code only prints out the
// first entry for the IP address/mask, and gateway, and
// the primary and secondary WINS server for each adapter. PIP_ADAPTER_INFO pAdapterInfo;PIP_ADAPTER_INFO pAdapter = NULL;DWORD dwRetVal = 0;UINT i;/* variables used to print DHCP time info */struct tm newtime;char buffer[32];errno_t error;ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof (IP_ADAPTER_INFO));if (pAdapterInfo == NULL) {printf("Error allocating memory needed to call GetAdaptersinfo\n");return 1;}
// Make an initial call to GetAdaptersInfo to get
// the necessary size into the ulOutBufLen variableif (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {FREE(pAdapterInfo);pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);if (pAdapterInfo == NULL) {printf("Error allocating memory needed to call GetAdaptersinfo\n");return 1;}}if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {pAdapter = pAdapterInfo;while (pAdapter) {printf("\tComboIndex: \t%d\n", pAdapter->ComboIndex);printf("\tAdapter Name: \t%s\n", pAdapter->AdapterName);printf("\tAdapter Desc: \t%s\n", pAdapter->Description);printf("\tAdapter Addr: \t");for (i = 0; i < pAdapter->AddressLength; i++) {if (i == (pAdapter->AddressLength - 1))printf("%.2X\n", (int) pAdapter->Address[i]);elseprintf("%.2X-", (int) pAdapter->Address[i]);}printf("\tIndex: \t%d\n", pAdapter->Index);printf("\tType: \t");switch (pAdapter->Type) {case MIB_IF_TYPE_OTHER:printf("Other\n");break;case MIB_IF_TYPE_ETHERNET:printf("Ethernet\n");break;case MIB_IF_TYPE_TOKENRING:printf("Token Ring\n");break;case MIB_IF_TYPE_FDDI:printf("FDDI\n");break;case MIB_IF_TYPE_PPP:printf("PPP\n");break;case MIB_IF_TYPE_LOOPBACK:printf("Lookback\n");break;case MIB_IF_TYPE_SLIP:printf("Slip\n");break;default:printf("Unknown type %ld\n", pAdapter->Type);break;}printf("\tIP Address: \t%s\n",pAdapter->IpAddressList.IpAddress.String);printf("\tIP Mask: \t%s\n", pAdapter->IpAddressList.IpMask.String);printf("\tGateway: \t%s\n", pAdapter->GatewayList.IpAddress.String);printf("\t***\n");if (pAdapter->DhcpEnabled) {printf("\tDHCP Enabled: Yes\n");printf("\t  DHCP Server: \t%s\n",pAdapter->DhcpServer.IpAddress.String);printf("\t  Lease Obtained: ");/* Display local time */error = _localtime32_s(&newtime, (__time32_t*) &pAdapter->LeaseObtained);if (error)printf("Invalid Argument to _localtime32_s\n");else {// Convert to an ASCII representation error = asctime_s(buffer, 32, &newtime);if (error)printf("Invalid Argument to asctime_s\n");else/* asctime_s returns the string terminated by \n\0 */printf("%s", buffer);}printf("\t  Lease Expires:  ");error = _localtime32_s(&newtime, (__time32_t*) &pAdapter->LeaseExpires);if (error)printf("Invalid Argument to _localtime32_s\n");else {// Convert to an ASCII representation error = asctime_s(buffer, 32, &newtime);if (error)printf("Invalid Argument to asctime_s\n");else/* asctime_s returns the string terminated by \n\0 */printf("%s", buffer);}} elseprintf("\tDHCP Enabled: No\n");if (pAdapter->HaveWins) {printf("\tHave Wins: Yes\n");printf("\t  Primary Wins Server:    %s\n",pAdapter->PrimaryWinsServer.IpAddress.String);printf("\t  Secondary Wins Server:  %s\n",pAdapter->SecondaryWinsServer.IpAddress.String);} elseprintf("\tHave Wins: No\n");pAdapter = pAdapter->Next;printf("\n");}} else {printf("GetAdaptersInfo failed with error: %d\n", dwRetVal);}if (pAdapterInfo)FREE(pAdapterInfo);return 0;
}

  

转载于:https://www.cnblogs.com/ourran/p/4831571.html

获取mac地址方法之一 GetAdaptersInfo()相关推荐

  1. 获取MAC地址的四种方法(转)

    https://www.cnblogs.com/zlshmily/p/10058560.html zlshmily 在实际的应用系统中,我们往往会需要在程序运行时获取当前机器的网卡的MAC地址,以便作 ...

  2. Windows获取本机MAC地址方法(C语言)

    Windows获取本机MAC地址方法(C语言) 用到的方法有两种:Netbios()和GetAdaptersInfo(); Netbios 获取步骤主要分为三步: 一.枚举本机所有LAN 二.重设每个 ...

  3. android 获取网卡mac_Java获取Linux安卓设备的mac地址方法

    Java如何获取Linux或安卓Android设备的mac地址呢?方法非常简单,只需要使用下方代码即可轻松通过java获取mac地址了,代码如下:public String getMacAddress ...

  4. wince下获取mac地址的简单方法!

    下,可以通过访问注册表获取mac地址,可是非常可惜的是有些系统的注册表不提供这个键值,另外也可以通过 DeviceIoControl这类函数获得,但是所有方法要么不全面,要么不够简单或者有些平台bsp ...

  5. php获取手机的mac地址,Android手机获取Mac地址的方法

    [导读]这篇文章主要为大家详细介绍了Android手机获取Mac地址的方法,具有一定的参考价值 最常用的方法,通过WiFiManager获取:/** * 通过WiFiManager获取mac地址 *  ...

  6. ASP.NET获取IP地址与MAC地址方法

    获取服务器的IP地址方法以DNS法较为简单实用,如下: private void ButtonIP_Click(object sender, System.EventArgs e) { Syste  ...

  7. android 手机固定mac地址吗,Android手机获取Mac地址的几种方法

    最常用的方法,通过WiFiManager获取: /** * 通过WiFiManager获取mac地址 * @param context * @return */ private static Stri ...

  8. linux用c++获取mac地址,网卡地址,网口地址,网卡序号ip地址,不使用 ioctl(sock, SIOCGIFCONF, ifc)获取网络接口名称,这个接口有时会返回-1获取不到,换方法获取

    linux用c++获取mac地址,不使用 ioctl(sock, SIOCGIFCONF, &ifc)获取网络接口名称,这个接口有时会返回-1获取不到,换方法获取 1.弃用 SIOCGIFCO ...

  9. android 4g获取mac地址,Android手机获取Mac地址的几种方法

    最常用的方法,通过WiFiManager获取: /** * 通过WiFiManager获取mac地址 * @param context * @return */ private static Stri ...

最新文章

  1. jQuery AJAX 网页无刷新上传示例
  2. 火狐访问HTTPS网站显示连接不安全的解决方法
  3. BLOCK层基本概念:bio,request,request_queue
  4. batch size 训练时间_深度学习 | Batch Size大小对训练过程的影响
  5. java 监听队列_spring+activemq实战之配置监听多队列实现不同队列消息消费
  6. extern C的用法解析
  7. c++ 预处理命令 预定义变量用法
  8. 「JupyterNotebook-bug」Jupyter Notebook卸载已安装的第三方库不能输入yes的问题
  9. python安装scipy出现红字_windows下安装numpy,scipy遇到的问题总结
  10. java es 搜索_使用elasticsearch从多个列表中搜索
  11. java cookbook中文版_Java Client快速入门指南
  12. 个人网页制作 大学生个人网页设计 个人网站模板 简单静态HTML个人网页作品 HTML+CSS+JavaScript
  13. 证书-解决非对称加密的公钥信任问题
  14. 各浏览器flash插件下载地址
  15. 极域教师端和学生端链接不上,出现这种问题怎么解决
  16. 垃圾场恶臭环境监测系统方案
  17. android开机动画切换
  18. spring_boot 发布成war包 ,部署到外部的tomcat
  19. 一个三线程序员的2020年,CSDN 10 万粉里程碑达成,SpringBoot项目瘦身指南
  20. c语言 空指令的作用,单片机C语言编程空指令产生短延时怎么办

热门文章

  1. 一篇文章教你如何制作二次元角色建模!
  2. 5年,14款近满分神作,这个独立团队打造了他们的游戏宇宙
  3. yuzu模拟器linux,Yuzu Early Acces
  4. 2022跨年代码(HTML·资源都是网上的可以直接使用)
  5. net start mysql 无法启动mysql解决方案之一【NET HELPMSG 3534】
  6. cmd命令【实施工程师技能】
  7. SQL基础【十八、事物】(sql事物慎用,还是写业务逻辑代码好一些,入伙涉及到更换数据啥的很麻烦!)
  8. MySQL create table as与create table like对比
  9. 导入导出 Oracle 分区表数据
  10. TypeScript 参数属性