Commit d2da3411 authored by captainwong's avatar captainwong

wmi

parent b657c6e8
#include "DeviceUniqueIdentifier.h"
#include <Windows.h>
#include <algorithm>
#include <math.h>
#include <strsafe.h>
#include <tchar.h>
#include <ntddndis.h>
#include <WbemIdl.h>
#include <comdef.h>
#include <comutil.h>
#include <atlconv.h>
#include <jlib/utf8.h>
#pragma comment (lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib")
namespace jlib {
namespace win32 {
namespace DeviceUniqueIdentifier {
namespace detail {
struct DeviceProperty {
enum { PROPERTY_MAX_LEN = 128 }; // 属性字段最大长度
wchar_t szProperty[PROPERTY_MAX_LEN];
};
struct WQL_QUERY
{
const wchar_t* szSelect = nullptr;
const wchar_t* szProperty = nullptr;
};
inline WQL_QUERY getWQLQuery(QueryType queryType) {
switch (queryType) {
case DeviceUniqueIdentifier::MAC_ADDR:
return // 网卡当前MAC地址
{ L"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
L"MACAddress" };
case DeviceUniqueIdentifier::MAC_ADDR_REAL:
return // 网卡原生MAC地址
{ L"SELECT * FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))",
L"PNPDeviceID" };
case DeviceUniqueIdentifier::HARDDISK_SERIAL:
return // 硬盘序列号
{ L"SELECT * FROM Win32_DiskDrive WHERE (SerialNumber IS NOT NULL) AND (MediaType LIKE 'Fixed hard disk%')",
L"SerialNumber" };
case DeviceUniqueIdentifier::MOTHERBOARD_UUID:
return // 主板序列号
{ L"SELECT * FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)",
L"SerialNumber" };
case DeviceUniqueIdentifier::MOTHERBOARD_MODEL:
return // 主板型号
{ L"SELECT * FROM Win32_BaseBoard WHERE (Product IS NOT NULL)",
L"Product" };
case DeviceUniqueIdentifier::CPU_ID:
return // 处理器ID
{ L"SELECT * FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)",
L"ProcessorId" };
case DeviceUniqueIdentifier::BIOS_SERIAL:
return // BIOS序列号
{ L"SELECT * FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)",
L"SerialNumber" };
case DeviceUniqueIdentifier::WINDOWS_PRODUCT_ID:
return // Windows 产品ID
{ L"SELECT * FROM Win32_OperatingSystem WHERE (SerialNumber IS NOT NULL)",
L"SerialNumber" };
default:
return { L"", L"" };
}
}
static BOOL WMI_DoWithHarddiskSerialNumber(wchar_t* SerialNumber, UINT uSize)
{
UINT iLen;
UINT i;
iLen = wcslen(SerialNumber);
if (iLen == 40) // InterfaceType = "IDE"
{ // 需要将16进制编码串转换为字符串
wchar_t ch, szBuf[32];
BYTE b;
for (i = 0; i < 20; i++) { // 将16进制字符转换为高4位
ch = SerialNumber[i * 2];
if ((ch >= '0') && (ch <= '9')) {
b = ch - '0';
} else if ((ch >= 'A') && (ch <= 'F')) {
b = ch - 'A' + 10;
} else if ((ch >= 'a') && (ch <= 'f')) {
b = ch - 'a' + 10;
} else { // 非法字符
break;
}
b <<= 4;
// 将16进制字符转换为低4位
ch = SerialNumber[i * 2 + 1];
if ((ch >= '0') && (ch <= '9')) {
b += ch - '0';
} else if ((ch >= 'A') && (ch <= 'F')) {
b += ch - 'A' + 10;
} else if ((ch >= 'a') && (ch <= 'f')) {
b += ch - 'a' + 10;
} else { // 非法字符
break;
}
szBuf[i] = b;
}
if (i == 20) { // 转换成功
szBuf[i] = L'\0';
StringCchCopyW(SerialNumber, uSize, szBuf);
iLen = wcslen(SerialNumber);
}
}
// 每2个字符互换位置
for (i = 0; i < iLen; i += 2) {
std::swap(SerialNumber[i], SerialNumber[i + 1]);
}
// 去掉空格
std::remove(SerialNumber, SerialNumber + wcslen(SerialNumber) + 1, L' ');
return TRUE;
}
// 通过“PNPDeviceID”获取网卡原生MAC地址
static BOOL WMI_DoWithPNPDeviceID(const wchar_t* PNPDeviceID, wchar_t* MacAddress, UINT uSize)
{
wchar_t DevicePath[MAX_PATH];
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 生成设备路径名
StringCchCopyW(DevicePath, MAX_PATH, L"\\\\.\\");
StringCchCatW(DevicePath, MAX_PATH, PNPDeviceID);
// {ad498944-762f-11d0-8dcb-00c04fc3358c} is 'Device Interface Name' for 'Network Card'
StringCchCatW(DevicePath, MAX_PATH, L"#{ad498944-762f-11d0-8dcb-00c04fc3358c}");
// 将“PNPDeviceID”中的“/”替换成“#”,以获得真正的设备路径名
std::replace(DevicePath + 4, DevicePath + 4 + wcslen(PNPDeviceID), (int)L'\\', (int)L'#');
// 获取设备句柄
hDeviceFile = CreateFileW(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_PERMANENT_ADDRESS;
isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
if (isOK) { // 将字节数组转换成16进制字符串
for (DWORD i = 0; i < dwByteRet; i++) {
StringCchPrintfW(MacAddress + (i << 1), uSize - (i << 1), L"%02X", ucData[i]);
}
MacAddress[dwByteRet << 1] = L'\0'; // 写入字符串结束标记
}
CloseHandle(hDeviceFile);
}
return isOK;
}
static BOOL WMI_DoWithProperty(QueryType queryType, wchar_t* szProperty, UINT uSize)
{
BOOL isOK = TRUE;
switch (queryType) {
case MAC_ADDR_REAL: // 网卡原生MAC地址
isOK = WMI_DoWithPNPDeviceID(szProperty, szProperty, uSize);
break;
case HARDDISK_SERIAL: // 硬盘序列号
isOK = WMI_DoWithHarddiskSerialNumber(szProperty, uSize);
break;
case MAC_ADDR: // 网卡当前MAC地址
// 去掉冒号
std::remove(szProperty, szProperty + wcslen(szProperty) + 1, L':');
break;
default:
// 去掉空格
std::remove(szProperty, szProperty + wcslen(szProperty) + 1, L' ');
}
return isOK;
}
std::wstring getMachineGUID()
{
std::wstring res;
/*using namespace winreg;
try {
RegKey key;
key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography");
res = key.GetStringValue(L"MachineGuid");
} catch (RegException& e) {
res = utf8::a2w(e.what());
} catch (std::exception& e) {
res = utf8::a2w(e.what());
} */
try {
std::wstring key = L"SOFTWARE\\Microsoft\\Cryptography";
std::wstring name = L"MachineGuid";
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey) != ERROR_SUCCESS)
throw std::runtime_error("Could not open registry key");
DWORD type;
DWORD cbData;
if (RegQueryValueExW(hKey, name.c_str(), NULL, &type, NULL, &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw std::runtime_error("Could not read registry value");
}
if (type != REG_SZ) {
RegCloseKey(hKey);
throw "Incorrect registry value type";
}
std::wstring value(cbData / sizeof(wchar_t), L'\0');
if (RegQueryValueExW(hKey, name.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&value[0]), &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw "Could not read registry value";
}
res = value;
RegCloseKey(hKey);
} catch (std::runtime_error& e) {
res = utf8::a2w(e.what());
}
return res;
}
} // end of namespace detail
bool query(size_t queryTypes, std::vector<std::wstring>& results)
{
std::vector<QueryType> vec;
if (queryTypes & MAC_ADDR) {
vec.push_back(MAC_ADDR);
}
if (queryTypes & MAC_ADDR_REAL) {
vec.push_back(MAC_ADDR_REAL);
}
if (queryTypes & HARDDISK_SERIAL) {
vec.push_back(HARDDISK_SERIAL);
}
if (queryTypes & MOTHERBOARD_UUID) {
vec.push_back(MOTHERBOARD_UUID);
}
if (queryTypes & MOTHERBOARD_MODEL) {
vec.push_back(MOTHERBOARD_MODEL);
}
if (queryTypes & CPU_ID) {
vec.push_back(CPU_ID);
}
if (queryTypes & BIOS_SERIAL) {
vec.push_back(BIOS_SERIAL);
}
if (queryTypes & WINDOWS_PRODUCT_ID) {
vec.push_back(WINDOWS_PRODUCT_ID);
}
auto ok = query(vec, results);
if (queryTypes & WINDOWS_MACHINE_GUID) {
results.push_back(detail::getMachineGUID());
}
return ok;
}
// 基于Windows Management Instrumentation(Windows管理规范)
bool query(const std::vector<QueryType>& queryTypes, std::vector<std::wstring>& results)
{
bool ok = false;
// 初始化COM
HRESULT hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hres)) {
return false;
}
// 设置COM的安全认证级别
hres = CoInitializeSecurity(
NULL,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL
);
if (FAILED(hres)) {
CoUninitialize();
return false;
}
// 获得WMI连接COM接口
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
reinterpret_cast<LPVOID*>(&pLoc)
);
if (FAILED(hres)) {
CoUninitialize();
return false;
}
// 通过连接接口连接WMI的内核对象名"ROOT//CIMV2"
IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pSvc
);
if (FAILED(hres)) {
_com_error e(hres);
e.ErrorMessage();
pLoc->Release();
CoUninitialize();
return false;
}
// 设置请求代理的安全级别
hres = CoSetProxyBlanket(
pSvc,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
return false;
}
for (auto queryType : queryTypes) {
auto query = detail::getWQLQuery(queryType);
// 通过请求代理来向WMI发送请求
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(query.szSelect),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator
);
if (FAILED(hres)) {
pSvc->Release();
pLoc->Release();
CoUninitialize();
continue;
}
// 循环枚举所有的结果对象
while (pEnumerator) {
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
pEnumerator->Next(
WBEM_INFINITE,
1,
&pclsObj,
&uReturn
);
if (uReturn == 0) {
break;
}
// 获取属性值
{
VARIANT vtProperty;
VariantInit(&vtProperty);
pclsObj->Get(query.szProperty, 0, &vtProperty, NULL, NULL);
detail::DeviceProperty deviceProperty{};
StringCchCopyW(deviceProperty.szProperty, detail::DeviceProperty::PROPERTY_MAX_LEN, vtProperty.bstrVal);
VariantClear(&vtProperty);
// 对属性值做进一步的处理
if (detail::WMI_DoWithProperty(queryType, deviceProperty.szProperty, detail::DeviceProperty::PROPERTY_MAX_LEN)) {
results.push_back(deviceProperty.szProperty);
ok = true;
pclsObj->Release();
break;
}
}
pclsObj->Release();
} // End While
// 释放资源
pEnumerator->Release();
}
pSvc->Release();
pLoc->Release();
CoUninitialize();
return ok;
}
std::wstring join_result(const std::vector<std::wstring>& results, const std::wstring& conjunction)
{
std::wstring result;
auto itBegin = results.cbegin();
auto itEnd = results.cend();
if (itBegin != itEnd) {
result = *itBegin++;
}
for (; itBegin != itEnd; itBegin++) {
result += conjunction;
result += *itBegin;
}
return result;
}
}
}
}
#pragma once
#include <string>
#include <vector>
namespace jlib
{
namespace win32
{
namespace DeviceUniqueIdentifier
{
#include "wmi.h"
#include <ntddndis.h> // OID_802_3_PERMANENT_ADDRESS ...
#include <strsafe.h> // StringCch
#include <unordered_map>
#include <algorithm>
#include "../utf8.h"
namespace jlib {
namespace win32 {
namespace DeviceUniqueIdentifier {
/*
参考1:
......@@ -48,8 +48,9 @@ enum QueryType : size_t {
更换硬盘后设备ID也必须随之改变, 不然也会影响授权等应用。
因此,很多授权软件没有考虑使用硬盘序列号。
而且,不一定所有的电脑都能获取到硬盘序列号。
因此,采用bootable(唯一)硬盘作为标识
*/
HARDDISK_SERIAL = 1 << 2,
BOOTABLE_HARDDISK_SERIAL = 1 << 2,
//! 主板序列号
/*
......@@ -100,29 +101,47 @@ enum QueryType : size_t {
WINDOWS_MACHINE_GUID = 1 << 8,
};
static const wchar_t* queryTypeString(QueryType type)
{
switch (type) {
case QueryType::MAC_ADDR: return L"MAC_ADDR ";
case QueryType::MAC_ADDR_REAL: return L"MAC_ADDR_REAL ";
case QueryType::BOOTABLE_HARDDISK_SERIAL: return L"BOOTABLE_HARDDISK_SERIAL";
case QueryType::MOTHERBOARD_UUID: return L"MOTHERBOARD_UUID ";
case QueryType::MOTHERBOARD_MODEL: return L"MOTHERBOARD_MODEL ";
case QueryType::CPU_ID: return L"CPU_ID ";
case QueryType::BIOS_SERIAL: return L"BIOS_SERIAL ";
case QueryType::WINDOWS_PRODUCT_ID: return L"WINDOWS_PRODUCT_ID ";
case QueryType::WINDOWS_MACHINE_GUID: return L"WINDOWS_MACHINE_GUID ";
default: return L"UNKNOWN QueryType ";
}
}
enum {
RecommendedQueryTypes = WINDOWS_MACHINE_GUID
| WINDOWS_PRODUCT_ID
| BIOS_SERIAL
| CPU_ID
| MOTHERBOARD_MODEL
RecommendedQueryTypes = BOOTABLE_HARDDISK_SERIAL
| MOTHERBOARD_UUID
| MOTHERBOARD_MODEL
| CPU_ID
| BIOS_SERIAL
| WINDOWS_PRODUCT_ID
| WINDOWS_MACHINE_GUID
,
AllQueryTypes = RecommendedQueryTypes
| HARDDISK_SERIAL
| MAC_ADDR_REAL
| MAC_ADDR
,
};
typedef std::unordered_map<QueryType, std::wstring> QueryResults;
/**
* @brief 查询信息
* @param[in] queryTypes QueryType集合
* @param[in,out] results 查询结果集合
* @return 成功或失败
*/
bool query(size_t queryTypes, std::vector<std::wstring>& results);
static bool query(size_t queryTypes, QueryResults& results);
/**
* @brief 查询信息
......@@ -130,7 +149,7 @@ bool query(size_t queryTypes, std::vector<std::wstring>& results);
* @param[in,out] results 查询结果集合
* @return 成功或失败
*/
bool query(const std::vector<QueryType>& queryTypes, std::vector<std::wstring>& results);
static bool query(const std::vector<QueryType>& queryTypes, QueryResults& results);
/**
* @brief 连接查询结果为一个字符串
......@@ -138,8 +157,256 @@ bool query(const std::vector<QueryType>& queryTypes, std::vector<std::wstring>&
* @param[in,out] conjunction 连词
* @return 将结果以连词连接起来组成的字符串
*/
std::wstring join_result(const std::vector<std::wstring>& results, const std::wstring& conjunction);
static std::wstring join_result(const QueryResults& results, const std::wstring& conjunction);
// Implementation
namespace detail
{
inline const wchar_t* getWQLQuery(QueryType queryType) {
switch (queryType) {
case DeviceUniqueIdentifier::MAC_ADDR:
return // 网卡当前MAC地址
L"SELECT MACAddress FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))" ;
case DeviceUniqueIdentifier::MAC_ADDR_REAL:
return // 网卡原生MAC地址
L"SELECT PNPDeviceID FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))";
case DeviceUniqueIdentifier::MOTHERBOARD_UUID:
return // 主板序列号
L"SELECT SerialNumber FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)";
case DeviceUniqueIdentifier::MOTHERBOARD_MODEL:
return // 主板型号
L"SELECT Product FROM Win32_BaseBoard WHERE (Product IS NOT NULL)";
case DeviceUniqueIdentifier::CPU_ID:
return // 处理器ID
L"SELECT ProcessorId FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)";
case DeviceUniqueIdentifier::BIOS_SERIAL:
return // BIOS序列号
L"SELECT SerialNumber FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)";
case DeviceUniqueIdentifier::WINDOWS_PRODUCT_ID:
return // Windows 产品ID
L"SELECT SerialNumber FROM Win32_OperatingSystem WHERE (SerialNumber IS NOT NULL)";
case WINDOWS_MACHINE_GUID:
return // 系统UUID
L"SELECT UUID FROM Win32_ComputerSystemProduct";
break;
default:
return L"" ;
}
}
// 通过“PNPDeviceID”获取网卡原生MAC地址
static BOOL parsePNPDeviceID(const wchar_t* PNPDeviceID, std::wstring& macAddress)
{
wchar_t DevicePath[MAX_PATH];
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 生成设备路径名
StringCchCopyW(DevicePath, MAX_PATH, L"\\\\.\\");
StringCchCatW(DevicePath, MAX_PATH, PNPDeviceID);
// {ad498944-762f-11d0-8dcb-00c04fc3358c} is 'Device Interface Name' for 'Network Card'
StringCchCatW(DevicePath, MAX_PATH, L"#{ad498944-762f-11d0-8dcb-00c04fc3358c}");
// 将“PNPDeviceID”中的“/”替换成“#”,以获得真正的设备路径名
std::replace(DevicePath + 4, DevicePath + 4 + wcslen(PNPDeviceID), (int)L'\\', (int)L'#');
// 获取设备句柄
hDeviceFile = CreateFileW(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_PERMANENT_ADDRESS;
isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
if (isOK) { // 将字节数组转换成16进制字符串
macAddress.clear();
for (DWORD i = 0; i < dwByteRet; i++) {
wchar_t tmp[4];
swprintf_s(tmp, 4, i == dwByteRet - 1 ? L"%02X" : L"%02X:", ucData[i]);
macAddress += tmp;
}
}
CloseHandle(hDeviceFile);
}
return isOK;
}
static std::wstring getMachineGUID()
{
std::wstring res;
try {
std::wstring key = L"SOFTWARE\\Microsoft\\Cryptography";
std::wstring name = L"MachineGuid";
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey) != ERROR_SUCCESS)
throw std::runtime_error("Could not open registry key");
DWORD type;
DWORD cbData;
if (RegQueryValueExW(hKey, name.c_str(), NULL, &type, NULL, &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw std::runtime_error("Could not read registry value");
}
if (type != REG_SZ) {
RegCloseKey(hKey);
throw "Incorrect registry value type";
}
std::wstring value(cbData / sizeof(wchar_t), L'\0');
if (RegQueryValueExW(hKey, name.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&value[0]), &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw "Could not read registry value";
}
if (value.back() == L'\0') {
value.erase(value.size() - 1, 1);
}
res = value;
RegCloseKey(hKey);
} catch (std::runtime_error& e) {
res = utf8::a2w(e.what());
}
return res;
}
} // namespace detail
static bool query(size_t queryTypes, QueryResults& results)
{
std::vector<QueryType> vec;
if (queryTypes & MAC_ADDR) {
vec.push_back(MAC_ADDR);
}
if (queryTypes & MAC_ADDR_REAL) {
vec.push_back(MAC_ADDR_REAL);
}
if (queryTypes & BOOTABLE_HARDDISK_SERIAL) {
vec.push_back(BOOTABLE_HARDDISK_SERIAL);
}
if (queryTypes & MOTHERBOARD_UUID) {
vec.push_back(MOTHERBOARD_UUID);
}
if (queryTypes & MOTHERBOARD_MODEL) {
vec.push_back(MOTHERBOARD_MODEL);
}
if (queryTypes & CPU_ID) {
vec.push_back(CPU_ID);
}
if (queryTypes & BIOS_SERIAL) {
vec.push_back(BIOS_SERIAL);
}
if (queryTypes & WINDOWS_PRODUCT_ID) {
vec.push_back(WINDOWS_PRODUCT_ID);
}
auto ok = query(vec, results);
return ok;
}
static bool query(const std::vector<QueryType>& queryTypes, QueryResults& results)
{
std::vector<std::wstring> values, errors;
auto output = [&values](const std::wstring& key, const std::wstring& value) {
values.push_back(value);
};
auto error = [&errors](HRESULT hr, const std::wstring& msg) {
errors.push_back(msg);
};
wmi::WmiBase wmi(L"ROOT\\CIMV2", output, error);
if (!wmi.prepare()) {
return false;
}
for (auto queryType : queryTypes) {
/*if (queryType == WINDOWS_MACHINE_GUID) {
results[WINDOWS_MACHINE_GUID] = (detail::getMachineGUID());
continue;
} else */
if (queryType == BOOTABLE_HARDDISK_SERIAL) {
auto sz = values.size();
if (wmi.execute(L"SELECT DiskIndex FROM Win32_DiskPartition WHERE Bootable = TRUE") && values.size() == sz + 1) {
auto index = values.back(); values.pop_back();
if (wmi.execute(L"SELECT SerialNumber FROM Win32_DiskDrive WHERE Index = " + index)) {
results[queryType] = values.back(); values.pop_back();
continue;
}
}
} else {
auto wql = detail::getWQLQuery(queryType);
auto sz = values.size();
if (wmi.execute(wql) && values.size() > sz) {
if (queryType == MAC_ADDR_REAL) {
auto value = values.back(); values.pop_back();
if (detail::parsePNPDeviceID(value.data(), value)) {
results[queryType] = value;
}
while (values.size() > sz) {
value = values.back(); values.pop_back();
if (detail::parsePNPDeviceID(value.data(), value)) {
results[queryType] += L"|" + value;
}
}
} else {
results[queryType] = values.back(); values.pop_back();
while (values.size() > sz) {
results[queryType] += L"|" + values.back(); values.pop_back();
}
}
continue;
}
}
// error
if (!errors.empty()) {
results[queryType] = errors.back(); errors.pop_back();
} else {
results[queryType] = std::wstring(L"Get ") + queryTypeString(queryType) + L" failed";
}
}
return true;
}
static std::wstring join_result(const QueryResults& results, const std::wstring& conjunction)
{
std::wstring result;
auto itBegin = results.cbegin();
auto itEnd = results.cend();
if (itBegin != itEnd) {
result = itBegin->second;
itBegin++;
}
for (; itBegin != itEnd; itBegin++) {
result += conjunction;
result += itBegin->second;
}
return result;
}
} // namespace DeviceUniqueIdentifier
} // namespace win32
} // namespace jlib
#pragma once
#include "wmi.h"
#include <atlconv.h>
#include <ntddndis.h>
#include <math.h>
#include <strsafe.h>
#include <unordered_map>
#include <algorithm>
#include "../utf8.h"
#pragma comment (lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib")
namespace jlib {
namespace win32 {
namespace DeviceUniqueIdentifier {
/*
参考1:
《设备唯一标识方法(Unique Identifier):如何在Windows系统上获取设备的唯一标识》
http://www.vonwei.com/post/UniqueDeviceIDforWindows.html
参考2:
《通过WMI获取网卡MAC地址、硬盘序列号、主板序列号、CPU ID、BIOS序列号》
https://blog.csdn.net/b_h_l/article/details/7764767
*/
enum QueryType : size_t {
/*
当前网卡MAC
MAC地址可能是最常用的标识方法,但是现在这种方法基本不可靠:
一个电脑可能存在多个网卡,多个MAC地址,
如典型的笔记本可能存在有线、无线、蓝牙等多个MAC地址,
随着不同连接方式的改变,每次MAC地址也会改变。
而且,当安装有虚拟机时,MAC地址会更多。
MAC地址另外一个更加致命的弱点是,MAC地址很容易手动更改。
因此,MAC地址基本不推荐用作设备唯一ID。
*/
MAC_ADDR = 1,
/*
当前网卡原生MAC
可以轻易修改网卡MAC,但无法修改原生MAC
*/
MAC_ADDR_REAL = 1 << 1,
/*
硬盘序列号
在Windows系统中通过命令行运行“wmic diskdrive get serialnumber”可以查看。
硬盘序列号作为设备唯一ID存在的问题是,很多机器可能存在多块硬盘,
特别是服务器,而且机器更换硬盘是很可能发生的事情,
更换硬盘后设备ID也必须随之改变, 不然也会影响授权等应用。
因此,很多授权软件没有考虑使用硬盘序列号。
而且,不一定所有的电脑都能获取到硬盘序列号。
因此,采用bootable(唯一)硬盘作为标识
*/
BOOTABLE_HARDDISK_SERIAL = 1 << 2,
//! 主板序列号
/*
在Windows系统中通过命令行运行“wmic csproduct get UUID”可以查看。
主板UUID是很多授权方法和微软官方都比较推崇的方法,
即便重装系统UUID应该也不会变
(笔者没有实测重装,不过在一台机器上安装双系统,获取的主板UUID是一样的,
双系统一个windows一个Linux,Linux下用“dmidecode -s system-uuid”命令可以获取UUID)。
但是这个方法也有缺陷,因为不是所有的厂商都提供一个UUID,
当这种情况发生时,wmic会返回“FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF”,
即一个无效的UUID。
*/
MOTHERBOARD_UUID = 1 << 3,
//! 主板型号
MOTHERBOARD_MODEL = 1 << 4,
/*
CPU ID
在Windows系统中通过命令行运行“wmic cpu get processorid”就可以查看CPU ID。
目前CPU ID也无法唯一标识设备,Intel现在可能同一批次的CPU ID都一样,不再提供唯一的ID。
而且经过实际测试,新购买的同一批次PC的CPU ID很可能一样。
这样作为设备的唯一标识就会存在问题。
*/
CPU_ID = 1 << 5,
//! BIOS序列号
BIOS_SERIAL = 1 << 6,
/*
Windows 产品ID
在“控制面板\系统和安全\系统”的最下面就可以看到激活的Windows产品ID信息,
另外通过注册表“HKEY_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion”也可以看到看到“ProductId”字段。
不过这个产品ID并不唯一,不同系统或者机器重复的概率也比较大。
虚拟机中克隆的系统,使用同一个镜像安装激活的系统,其产品ID就可能一模一样。
经过实测,笔者在两台Thinkpad笔记本上发现其ProductId完全一样。
*/
WINDOWS_PRODUCT_ID = 1 << 7,
/*
Windows MachineGUID
Windows安装时会唯一生成一个GUID,
可以在注册表“HKEY_MACHINE\SOFTWARE\Microsoft\Cryptography”中查看其“MachineGuid”字段。
这个ID作为Windows系统设备的唯一标识不错,不过值得注意的一点是,与硬件ID不一样,
这个ID在重装Windows系统后应该不一样了。
这样授权软件在重装系统后,可能就需要用户重新购买授权。
*/
WINDOWS_MACHINE_GUID = 1 << 8,
};
static const wchar_t* queryTypeString(QueryType type)
{
switch (type) {
case QueryType::MAC_ADDR: return L"MAC_ADDR ";
case QueryType::MAC_ADDR_REAL: return L"MAC_ADDR_REAL ";
case QueryType::BOOTABLE_HARDDISK_SERIAL: return L"BOOTABLE_HARDDISK_SERIAL";
case QueryType::MOTHERBOARD_UUID: return L"MOTHERBOARD_UUID ";
case QueryType::MOTHERBOARD_MODEL: return L"MOTHERBOARD_MODEL ";
case QueryType::CPU_ID: return L"CPU_ID ";
case QueryType::BIOS_SERIAL: return L"BIOS_SERIAL ";
case QueryType::WINDOWS_PRODUCT_ID: return L"WINDOWS_PRODUCT_ID ";
case QueryType::WINDOWS_MACHINE_GUID: return L"WINDOWS_MACHINE_GUID ";
default: return L"UNKNOWN QueryType ";
}
}
enum {
RecommendedQueryTypes = BOOTABLE_HARDDISK_SERIAL
| MOTHERBOARD_UUID
| MOTHERBOARD_MODEL
| CPU_ID
| BIOS_SERIAL
| WINDOWS_PRODUCT_ID
| WINDOWS_MACHINE_GUID
,
AllQueryTypes = RecommendedQueryTypes
| MAC_ADDR_REAL
| MAC_ADDR
,
};
typedef std::unordered_map<QueryType, std::wstring> QueryResults;
/**
* @brief 查询信息
* @param[in] queryTypes QueryType集合
* @param[in,out] results 查询结果集合
* @return 成功或失败
*/
static bool query(size_t queryTypes, QueryResults& results);
/**
* @brief 查询信息
* @param[in] queryTypes QueryType集合
* @param[in,out] results 查询结果集合
* @return 成功或失败
*/
static bool query(const std::vector<QueryType>& queryTypes, QueryResults& results);
/**
* @brief 连接查询结果为一个字符串
* @param[in] results 查询结果集合
* @param[in,out] conjunction 连词
* @return 将结果以连词连接起来组成的字符串
*/
static std::wstring join_result(const QueryResults& results, const std::wstring& conjunction);
// Implementation
namespace detail
{
inline const wchar_t* getWQLQuery(QueryType queryType) {
switch (queryType) {
case DeviceUniqueIdentifier::MAC_ADDR:
return // 网卡当前MAC地址
L"SELECT MACAddress FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))" ;
case DeviceUniqueIdentifier::MAC_ADDR_REAL:
return // 网卡原生MAC地址
L"SELECT PNPDeviceID FROM Win32_NetworkAdapter WHERE (MACAddress IS NOT NULL) AND (NOT (PNPDeviceID LIKE 'ROOT%'))";
case DeviceUniqueIdentifier::MOTHERBOARD_UUID:
return // 主板序列号
L"SELECT SerialNumber FROM Win32_BaseBoard WHERE (SerialNumber IS NOT NULL)";
case DeviceUniqueIdentifier::MOTHERBOARD_MODEL:
return // 主板型号
L"SELECT Product FROM Win32_BaseBoard WHERE (Product IS NOT NULL)";
case DeviceUniqueIdentifier::CPU_ID:
return // 处理器ID
L"SELECT ProcessorId FROM Win32_Processor WHERE (ProcessorId IS NOT NULL)";
case DeviceUniqueIdentifier::BIOS_SERIAL:
return // BIOS序列号
L"SELECT SerialNumber FROM Win32_BIOS WHERE (SerialNumber IS NOT NULL)";
case DeviceUniqueIdentifier::WINDOWS_PRODUCT_ID:
return // Windows 产品ID
L"SELECT SerialNumber FROM Win32_OperatingSystem WHERE (SerialNumber IS NOT NULL)";
case WINDOWS_MACHINE_GUID:
return // 系统UUID
L"SELECT UUID FROM Win32_ComputerSystemProduct";
break;
default:
return L"" ;
}
}
// 通过“PNPDeviceID”获取网卡原生MAC地址
static BOOL parsePNPDeviceID(const wchar_t* PNPDeviceID, std::wstring& macAddress)
{
wchar_t DevicePath[MAX_PATH];
HANDLE hDeviceFile;
BOOL isOK = FALSE;
// 生成设备路径名
StringCchCopyW(DevicePath, MAX_PATH, L"\\\\.\\");
StringCchCatW(DevicePath, MAX_PATH, PNPDeviceID);
// {ad498944-762f-11d0-8dcb-00c04fc3358c} is 'Device Interface Name' for 'Network Card'
StringCchCatW(DevicePath, MAX_PATH, L"#{ad498944-762f-11d0-8dcb-00c04fc3358c}");
// 将“PNPDeviceID”中的“/”替换成“#”,以获得真正的设备路径名
std::replace(DevicePath + 4, DevicePath + 4 + wcslen(PNPDeviceID), (int)L'\\', (int)L'#');
// 获取设备句柄
hDeviceFile = CreateFileW(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_PERMANENT_ADDRESS;
isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
if (isOK) { // 将字节数组转换成16进制字符串
macAddress.clear();
for (DWORD i = 0; i < dwByteRet; i++) {
wchar_t tmp[4];
swprintf_s(tmp, 4, i == dwByteRet - 1 ? L"%02X" : L"%02X:", ucData[i]);
macAddress += tmp;
}
}
CloseHandle(hDeviceFile);
}
return isOK;
}
static std::wstring getMachineGUID()
{
std::wstring res;
try {
std::wstring key = L"SOFTWARE\\Microsoft\\Cryptography";
std::wstring name = L"MachineGuid";
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, key.c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &hKey) != ERROR_SUCCESS)
throw std::runtime_error("Could not open registry key");
DWORD type;
DWORD cbData;
if (RegQueryValueExW(hKey, name.c_str(), NULL, &type, NULL, &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw std::runtime_error("Could not read registry value");
}
if (type != REG_SZ) {
RegCloseKey(hKey);
throw "Incorrect registry value type";
}
std::wstring value(cbData / sizeof(wchar_t), L'\0');
if (RegQueryValueExW(hKey, name.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&value[0]), &cbData) != ERROR_SUCCESS) {
RegCloseKey(hKey);
throw "Could not read registry value";
}
if (value.back() == L'\0') {
value.erase(value.size() - 1, 1);
}
res = value;
RegCloseKey(hKey);
} catch (std::runtime_error& e) {
res = utf8::a2w(e.what());
}
return res;
}
} // namespace detail
static bool query(size_t queryTypes, QueryResults& results)
{
std::vector<QueryType> vec;
if (queryTypes & MAC_ADDR) {
vec.push_back(MAC_ADDR);
}
if (queryTypes & MAC_ADDR_REAL) {
vec.push_back(MAC_ADDR_REAL);
}
if (queryTypes & BOOTABLE_HARDDISK_SERIAL) {
vec.push_back(BOOTABLE_HARDDISK_SERIAL);
}
if (queryTypes & MOTHERBOARD_UUID) {
vec.push_back(MOTHERBOARD_UUID);
}
if (queryTypes & MOTHERBOARD_MODEL) {
vec.push_back(MOTHERBOARD_MODEL);
}
if (queryTypes & CPU_ID) {
vec.push_back(CPU_ID);
}
if (queryTypes & BIOS_SERIAL) {
vec.push_back(BIOS_SERIAL);
}
if (queryTypes & WINDOWS_PRODUCT_ID) {
vec.push_back(WINDOWS_PRODUCT_ID);
}
auto ok = query(vec, results);
return ok;
}
static bool query(const std::vector<QueryType>& queryTypes, QueryResults& results)
{
std::vector<std::wstring> values, errors;
auto output = [&values](const std::wstring& key, const std::wstring& value) {
values.push_back(value);
};
auto error = [&errors](HRESULT hr, const std::wstring& msg) {
errors.push_back(msg);
};
wmi::WmiBase wmi(L"ROOT\\CIMV2", output, error);
wmi.prepare();
for (auto queryType : queryTypes) {
/*if (queryType == WINDOWS_MACHINE_GUID) {
results[WINDOWS_MACHINE_GUID] = (detail::getMachineGUID());
continue;
} else */if (queryType == BOOTABLE_HARDDISK_SERIAL) {
auto sz = values.size();
if (wmi.execute(L"SELECT DiskIndex FROM Win32_DiskPartition WHERE Bootable = TRUE") && values.size() == sz + 1) {
auto index = values.back(); values.pop_back();
if (wmi.execute(L"SELECT SerialNumber FROM Win32_DiskDrive WHERE Index = " + index)) {
results[queryType] = values.back(); values.pop_back();
continue;
}
}
} else {
auto wql = detail::getWQLQuery(queryType);
auto sz = values.size();
if (wmi.execute(wql) && values.size() > sz) {
if (queryType == MAC_ADDR_REAL) {
auto value = values.back(); values.pop_back();
if (detail::parsePNPDeviceID(value.data(), value)) {
results[queryType] = value;
}
while (values.size() > sz) {
value = values.back(); values.pop_back();
if (detail::parsePNPDeviceID(value.data(), value)) {
results[queryType] += L"|" + value;
}
}
} else {
results[queryType] = values.back(); values.pop_back();
while (values.size() > sz) {
results[queryType] += L"|" + values.back(); values.pop_back();
}
}
continue;
}
}
// error
if (!errors.empty()) {
results[queryType] = errors.back(); errors.pop_back();
} else {
results[queryType] = std::wstring(L"Get ") + queryTypeString(queryType) + L" failed";
}
}
return true;
}
static std::wstring join_result(const QueryResults& results, const std::wstring& conjunction)
{
std::wstring result;
auto itBegin = results.cbegin();
auto itEnd = results.cend();
if (itBegin != itEnd) {
result = itBegin->second;
itBegin++;
}
for (; itBegin != itEnd; itBegin++) {
result += conjunction;
result += itBegin->second;
}
return result;
}
} // namespace DeviceUniqueIdentifier
} // namespace win32
} // namespace jlib
#pragma once
/**
* 主要参考了 https://blog.csdn.net/breaksoftware/article/category/9269057
*/
#include <Windows.h>
#include <comdef.h>
#include <WbemIdl.h>
#include <atlbase.h>
#include <atlcom.h>
#include <comdef.h>
#include <string>
#include <functional>
#pragma comment (lib, "comsuppw.lib")
#pragma comment (lib, "wbemuuid.lib")
#if !defined(UNICODE) && !defined(_UNICODE)
#error wmi only works with unicode!
#endif
#define JLIB_CHECK_HR(hr) if (FAILED(hr)) break;
#define JLIB_CHECK_HR2(hr, errorFunc) if (FAILED(hr)) { if (errorFunc) { errorFunc(hr, _com_error(hr).ErrorMessage()); } break; }
#define JLIB_CHECK_WMI_HR(hr) if ((hr) != WBEM_S_NO_ERROR) break;
......
......@@ -5,10 +5,6 @@ VisualStudioVersion = 16.0.29209.62
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testDeviceUniqueIdentifierHeaderOnly", "testDeviceUniqueIdentifierHeaderOnly\testDeviceUniqueIdentifierHeaderOnly.vcxproj", "{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testDeviceUniqueIdentifier", "testDeviceUniqueIdentifier\testDeviceUniqueIdentifier.vcxproj", "{CA7812A3-9E48-4A94-B39A-32EED587E38A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_win32", "test_win32\test_win32.vcxproj", "{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_qt", "test_qt\test_qt.vcxproj", "{B12702AD-ABFB-343A-A199-8E24837244A3}"
......@@ -54,9 +50,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "win32", "win32", "{B5D9E71E-2BFE-4D04-A66A-4CB0A103CD77}"
ProjectSection(SolutionItems) = preProject
..\jlib\win32\clipboard.h = ..\jlib\win32\clipboard.h
..\jlib\win32\DeviceUniqueIdentifier.cpp = ..\jlib\win32\DeviceUniqueIdentifier.cpp
..\jlib\win32\DeviceUniqueIdentifier.h = ..\jlib\win32\DeviceUniqueIdentifier.h
..\jlib\win32\deviceuniqueidentifierheaderonly.h = ..\jlib\win32\deviceuniqueidentifierheaderonly.h
..\jlib\win32\deviceuniqueidentifier.h = ..\jlib\win32\deviceuniqueidentifier.h
..\jlib\win32\file_op.h = ..\jlib\win32\file_op.h
..\jlib\win32\memory_micros.h = ..\jlib\win32\memory_micros.h
..\jlib\win32\MyWSAError.h = ..\jlib\win32\MyWSAError.h
......@@ -223,6 +217,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_clipboard", "test_clip
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_wmi", "test_wmi\test_wmi.vcxproj", "{79A2C0A6-B8BB-406F-A732-C6300A611EC8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testDeviceUniqueIdentifier", "testDeviceUniqueIdentifier\testDeviceUniqueIdentifier.vcxproj", "{CA7812A3-9E48-4A94-B39A-32EED587E38A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......@@ -239,22 +235,6 @@ Global
{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5}.Release|x64.Build.0 = Release|x64
{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5}.Release|x86.ActiveCfg = Release|Win32
{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5}.Release|x86.Build.0 = Release|Win32
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Debug|x64.ActiveCfg = Debug|x64
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Debug|x64.Build.0 = Debug|x64
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Debug|x86.ActiveCfg = Debug|Win32
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Debug|x86.Build.0 = Debug|Win32
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Release|x64.ActiveCfg = Release|x64
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Release|x64.Build.0 = Release|x64
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Release|x86.ActiveCfg = Release|Win32
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}.Release|x86.Build.0 = Release|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x64.ActiveCfg = Debug|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x64.Build.0 = Debug|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x86.ActiveCfg = Debug|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x86.Build.0 = Debug|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x64.ActiveCfg = Release|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x64.Build.0 = Release|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x86.ActiveCfg = Release|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x86.Build.0 = Release|Win32
{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB}.Debug|x64.ActiveCfg = Debug|x64
{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB}.Debug|x64.Build.0 = Debug|x64
{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB}.Debug|x86.ActiveCfg = Debug|Win32
......@@ -341,14 +321,20 @@ Global
{79A2C0A6-B8BB-406F-A732-C6300A611EC8}.Release|x64.Build.0 = Release|x64
{79A2C0A6-B8BB-406F-A732-C6300A611EC8}.Release|x86.ActiveCfg = Release|Win32
{79A2C0A6-B8BB-406F-A732-C6300A611EC8}.Release|x86.Build.0 = Release|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x64.ActiveCfg = Debug|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x64.Build.0 = Debug|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x86.ActiveCfg = Debug|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Debug|x86.Build.0 = Debug|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x64.ActiveCfg = Release|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x64.Build.0 = Release|x64
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x86.ActiveCfg = Release|Win32
{CA7812A3-9E48-4A94-B39A-32EED587E38A}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{155F525A-FA2F-471F-A2DF-9B77E7CCCFA5} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{CA7812A3-9E48-4A94-B39A-32EED587E38A} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{A4B1CDB2-7325-4E22-AD0A-1D2907924CDB} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{B12702AD-ABFB-343A-A199-8E24837244A3} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
{8A39D7AF-50AF-43BD-8CC6-DA20B6349F03} = {21DC893D-AB0B-48E1-9E23-069A025218D9}
......@@ -380,6 +366,7 @@ Global
{16CAD8DD-EF99-4A38-B5AA-BF86FC7A07AB} = {F118E1C9-F461-4CAA-A0F1-75F5A5C8ADF3}
{904EC99B-A012-4134-AE6F-E21635FB602F} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{79A2C0A6-B8BB-406F-A732-C6300A611EC8} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
{CA7812A3-9E48-4A94-B39A-32EED587E38A} = {0E6598D3-602D-4552-97F7-DC5AB458D553}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A8EBEA58-739C-4DED-99C0-239779F57D5D}
......
#include <jlib/win32/DeviceUniqueIdentifier.h>
#include <stdio.h>
#include <algorithm>
#include <locale>
int main()
{
std::locale::global(std::locale(""));
using namespace jlib::DeviceUniqueIdentifier;
std::vector<std::wstring> results;
/*query(RecommendedQueryTypes, results);
auto str = join_result(results, L"\n");
std::wcout << str << std::endl;*/
results.clear();
query(AllQueryTypes, results);
std::wstring str;
std::vector<std::wstring> types = {
L"MAC_ADDR 网卡MAC地址",
L"MAC_ADDR_REAL 网卡原生MAC地址",
L"HARDDISK_SERIAL 主硬盘序列号",
L"MOTHERBOARD_UUID 主板序列号",
L"MOTHERBOARD_MODEL 主板型号",
L"CPU_ID 处理器序列号",
L"BIOS_SERIAL BIOS序列号",
L"WINDOWS_PRODUCT_ID Windows产品ID",
L"WINDOWS_MACHINE_GUID Windows机器码",
};
for (size_t i = 0; i < std::min(types.size(), results.size()); i++) {
printf("%ls:\n%ls\n\n", types[i].c_str(), results[i].c_str());
}
//auto str = join_result(results, L"\n");
//std::wcout << std::endl << str << std::endl;
system("pause");
}
\ No newline at end of file
#include <jlib/win32/DeviceUniqueIdentifierHeaderOnly.h>
#include <jlib/win32/DeviceUniqueIdentifier.h>
#include <stdio.h>
#include <algorithm>
#include <locale.h>
......
......@@ -29,14 +29,14 @@
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
......@@ -120,11 +120,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\jlib\win32\DeviceUniqueIdentifier.cpp" />
<ClCompile Include="test.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\jlib\win32\DeviceUniqueIdentifier.h" />
<ClCompile Include="testDeviceUniqueIdentifier.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
......
......@@ -15,16 +15,8 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\jlib\win32\DeviceUniqueIdentifier.cpp">
<ClCompile Include="testDeviceUniqueIdentifier.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\jlib\win32\DeviceUniqueIdentifier.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{1E6D1113-2EDE-4E7E-BF17-A3663101C3AE}</ProjectGuid>
<RootNamespace>testDeviceUniqueIdentifierHeaderOnly</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS)/Global;$(BOOST);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(DEVLIBS)/jlib;$(BOOST);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(BOOST);$(DEVLIBS)\jlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="testDeviceUniqueIdentifierHeaderOnly.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="testDeviceUniqueIdentifierHeaderOnly.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment