您的位置:首页 > 编程语言 > C语言/C++

c++通过mac地址 获取 设备UUID

2015-08-27 12:32 585 查看

(注:仅支持pc端的设备UUID获取,不支持android和ios移动设备UUID的获取)

原料:vs2013+cocos2dx3.3+openssl+macaddr.h/cpp

第一步:

下载好OpenSSL,导入openssl文件夹到工程目录下

导入macaddr.h和macaddr.cpp到工程

头文件macaddr.h

#ifndef __MACADDR_H__
#define __MACADDR_H__

#include <windows.h>

#define MACADDRESS_BYTELEN  6                       // MAC地址字节长度

typedef struct _MACADDRESS
{
BYTE    SrcMacAddr[MACADDRESS_BYTELEN];         // 原生MAC地址
BYTE    CurMacAddr[MACADDRESS_BYTELEN];         // 当前MAC地址
} MACADDRESS;

#ifdef __cplusplus
extern "C"{
#endif

/*

*/
/*
功能     : 结合WMI和DeviceIoControl获取网卡原生MAC地址和当前MAC地址
入口参数  :
iQueryType  需要获取的网卡类型
0 : 包括USB网卡
1 : 不包括USB网卡
pMacAddress 存储网卡MAC地址
uSize       可存储的最大网卡数目
返回值:
-1  不支持的设备属性值
-2  WMI连接失败
-3  不正确的WQL查询语句
>=0 获取的网卡数目
*/
INT WDK_MacAddress(INT iQueryType, MACADDRESS * pMacAddress, INT iSize);

#ifdef __cplusplus
}
#endif

#endif


实现文件macaddr.cpp

#include <tchar.h>
#include <strsafe.h>
#include <algorithm>
#include "macaddr.h"

#ifdef __cplusplus
extern "C"
{
#endif
#include <ntddndis.h>
#include <setupapi.h>
#include <hidsdi.h>
#ifdef __cplusplus
}
#endif

#pragma comment (lib, "setupapi")
#pragma comment (lib, "hid")

const GUID GUID_QUERYSET[] = {
// 网卡原生MAC地址(包含USB网卡)
{0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},

// 网卡原生MAC地址(剔除USB网卡)
{0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C},
};

// 获取网卡原生MAC地址
static BOOL WDK_GetMacAddress(TCHAR * DevicePath, MACADDRESS * pMacAddress, INT iIndex, BOOL isIncludeUSB)
{
HANDLE  hDeviceFile;
BOOL    isOK = FALSE;

// 剔除虚拟网卡
if (_tcsnicmp(DevicePath + 4, TEXT("root"), 4) == 0)
{
return FALSE;
}

if (!isIncludeUSB)
{   // 剔除USB网卡
if (_tcsnicmp(DevicePath + 4, TEXT("usb"), 4) == 0)
{
return FALSE;
}
}

// 获取设备句柄
hDeviceFile = CreateFile(DevicePath,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

if (hDeviceFile != INVALID_HANDLE_VALUE)
{
ULONG   dwID;
BYTE    ucData[8];
DWORD   dwByteRet;

// 获取当前MAC地址
dwID = OID_802_3_CURRENT_ADDRESS;
isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
if (isOK)
{
memcpy(pMacAddress[iIndex].CurMacAddr, ucData, dwByteRet);

// 获取原生MAC地址
dwID = OID_802_3_PERMANENT_ADDRESS;
isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
if (isOK)
{
memcpy(pMacAddress[iIndex].SrcMacAddr, ucData, dwByteRet);
}
}

CloseHandle(hDeviceFile);
}

return isOK;
}

static BOOL WDK_GetProperty(TCHAR* DevicePath, INT iQueryType, MACADDRESS *pMacAddress, INT iIndex)
{
BOOL isOK = FALSE;

switch (iQueryType)
{
case 0:     // 网卡原生MAC地址(包含USB网卡)
isOK = WDK_GetMacAddress(DevicePath, pMacAddress, iIndex, TRUE);
break;

case 1:     // 网卡原生MAC地址(剔除USB网卡)
isOK = WDK_GetMacAddress(DevicePath, pMacAddress, iIndex, FALSE);
break;

default:
break;
}

return isOK;
}

INT WDK_MacAddress(INT iQueryType, MACADDRESS * pMacAddress, INT iSize)
{
HDEVINFO hDevInfo;
DWORD MemberIndex, RequiredSize;
SP_DEVICE_INTERFACE_DATA            DeviceInterfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA    DeviceInterfaceDetailData;
INT iTotal = 0;

// 判断查询类型是否支持
if ((iQueryType < 0) || (iQueryType >= sizeof(GUID_QUERYSET) / sizeof(GUID)))
{
return -2;  // 查询类型不支持
}

// 获取设备信息集
hDevInfo = SetupDiGetClassDevs(GUID_QUERYSET + iQueryType, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
return -1;
}

// 枚举设备信息集中所有设备
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
for (MemberIndex = 0; ((pMacAddress == NULL) || (iTotal < iSize)); MemberIndex++)
{   // 获取设备接口
if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, GUID_QUERYSET + iQueryType, MemberIndex, &DeviceInterfaceData))
{   // 设备枚举完毕
break;
}

// 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER
SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL);

// 申请接收缓冲区
DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

// 获取设备细节信息
if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL))
{
if (pMacAddress != NULL)
{
if (WDK_GetProperty(DeviceInterfaceDetailData->DevicePath, iQueryType, pMacAddress, iTotal))
{
iTotal++;
}
}
else
{
iTotal++;
}
}

free(DeviceInterfaceDetailData);
}

SetupDiDestroyDeviceInfoList(hDevInfo);

return iTotal;
}


第二步:

main代码调用出:

/*
缺省通用头文件,自己添加。比如:#include <stdio.h>等
*/
#include "openssl/md5.h"
#include "macaddr.h"
// openssl library
#pragma comment(lib, "libeay32")

int main()
{

MACADDRESS macaddr = { 0 };
MD5_CTX md5ctx = { 0 };
uint8_t md[16] = { 0 };

char mac[128] = { 0 }; //测试mac地址(MAC地址就如同我们身份证上的身份证号码,具有全球唯一性)

char g_deviceuuid[260] = { 0 };//根据mac地址 获取 设备UUID

if (WDK_MacAddress(1, &macaddr, 1) < 1)
return -1;

sprintf(mac, "src mac : ");
for (int i = 0; i < 6; i++)
sprintf(mac + 10 + i * 2, "%02X ", macaddr.SrcMacAddr[i]);
sprintf(mac + 22, "\ncur mac : ");
for (int i = 0; i < 6; i++)
sprintf(mac + 33 + i * 2, "%02X", macaddr.CurMacAddr[i]);
sprintf(mac + 45, "\n");

if (MD5_Init(&md5ctx) < 0)
return -1;
if (MD5_Update(&md5ctx, macaddr.SrcMacAddr, sizeof(macaddr.SrcMacAddr)) < 0)
{
MD5_Final(nullptr, &md5ctx);
return -1;
}
if (MD5_Final((unsigned char *)md, &md5ctx) < 0)
return -1;
for (int i = 0; i < 16; i++)
sprintf(g_deviceuuid + i * 2, "%02X", md[i]);

CCLOG("======>[%s]", g_deviceuuid);

return 0
}


最终:日志输出串就是设备UUID:======>[65C5459D3A2CC565F96A5223C85BC576 ]

**

第三步:

**

工程配置

1).拷贝openssl\bin\win32下的 libeay32.dll 到 Debug.win32(如果Release版本是Release.win32)目录下

2).配置 -> c/c++ -> 附加包含目录:..\openssl\include

3).配置 -> c/c++ -> 附加包含目录:C:\Program Files %28x86%29\Windows Kits\8.1\Include\shared

4).配置 -> 链接器 -> 附加库目录: C:\Program Files %28x86%29\Windows Kits\8.1\Lib\winv6.3\um\x86 和 ..\openssl\lib\win32
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  openssl