From df1f4b6a69c240616defc01cb02f0f13e60c7a8e Mon Sep 17 00:00:00 2001 From: wdp <544209413@qq.com> Date: Mon, 20 Jan 2025 22:30:11 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E4=BF=A1=E6=81=AF=E8=8E=B7=E5=8F=96=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/util/DeviceInfo.cpp | 257 ++++++++++++++++++++++++++++++++++++++++ src/util/DeviceInfo.h | 30 +++++ src/util/Singleton.h | 19 +++ 3 files changed, 306 insertions(+) create mode 100644 src/util/DeviceInfo.cpp create mode 100644 src/util/DeviceInfo.h create mode 100644 src/util/Singleton.h diff --git a/src/util/DeviceInfo.cpp b/src/util/DeviceInfo.cpp new file mode 100644 index 0000000..9b4df62 --- /dev/null +++ b/src/util/DeviceInfo.cpp @@ -0,0 +1,257 @@ +#include "DeviceInfo.h" +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#include +// #include +// #include +#pragma comment(lib, "wbemuuid.lib") +#pragma comment(lib, "iphlpapi.lib") +// #pragma comment(lib, "ws2_32.lib") +#elif defined(__linux__) +#include +#include +#include +#include +#include +#include +#include +#include +#elif defined(__ANDROID__) +#include +#include +#include +#include +#include +#include +#include +#endif + +/// @brief 格式化mac地址,删除:或者- 和空格 并且转成大写 +static std::string& FormatMac(std::string& mac) { + for (auto &c : mac) { + if (c == ':' || c == '-') { + c = ' '; + } + } + std::transform(mac.begin(), mac.end(), mac.begin(), [ ](unsigned char c) { return std::toupper(c); }); + // 删除空格 + mac.erase(std::remove(mac.begin(), mac.end(), ' '), mac.end()); + return mac; +} +std::vector DeviceInfo::GetMacAddress() { + m_macs.clear(); +#ifdef _WIN32 + IP_ADAPTER_INFO adapterInfo[16]; + DWORD bufLen = sizeof(adapterInfo); + DWORD status = GetAdaptersInfo(adapterInfo, &bufLen); + if (status == ERROR_SUCCESS) { + PIP_ADAPTER_INFO pAdapterInfo = adapterInfo; + while (pAdapterInfo) { + std::ostringstream os; + os << std::hex << std::setfill('0'); + for (UINT i = 0; i < pAdapterInfo->AddressLength; i++) { + os << std::setw(2) << static_cast(pAdapterInfo->Address[i]); + if (i < pAdapterInfo->AddressLength - 1) { + os << ":"; + } + } + m_macs.push_back(os.str()); + pAdapterInfo = pAdapterInfo->Next; + } + } +#endif + +#ifdef __linux__ + DIR *dir; + struct dirent *entry; + dir = opendir("/sys/class/net/"); + if (dir == nullptr) { + goto end; + } + + while ((entry = readdir(dir)) != nullptr) { + std::string path = "/sys/class/net/" + std::string(entry->d_name) + "/address"; + struct stat statbuf; + if (stat(path.c_str(), &statbuf) == 0 && S_ISREG(statbuf.st_mode)) { + int fd = open(path.c_str(), O_RDONLY); + if (fd != -1) { + char buffer[18]; + if (read(fd, buffer, sizeof(buffer) - 1) > 0) { + buffer[17] = '\0'; + m_macs.push_back(buffer); + } + close(fd); + } + } + } + closedir(dir); +#endif + +end: + /// 地址统一转成大写 并且去掉:或者- + for (auto &mac : m_macs) { + FormatMac(mac); + } + return m_macs; +} + +std::string DeviceInfo::GetBoardInfo() { + m_board = ""; +#ifdef _WIN32 + HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED); + if (FAILED(hres)) { + return m_board; + } + + // Initialize Security. + 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 m_board; + } + + // Obtain the initial locator to WMI. + IWbemLocator *pLoc = NULL; + + hres = CoCreateInstance( + CLSID_WbemLocator, + 0, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, (LPVOID *)&pLoc); + + if (FAILED(hres)) { + CoUninitialize(); + return m_board; + } + + IWbemServices *pSvc = NULL; + + hres = pLoc->ConnectServer( + _bstr_t(L"ROOT\\CIMV2"), + NULL, + NULL, + 0, + NULL, + 0, + 0, + &pSvc + ); + + if (FAILED(hres)) { + pLoc->Release(); + CoUninitialize(); + return m_board; + } + + // Set security levels on the proxy. + 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 m_board; + } + + // Use the IWbemServices pointer to make requests of WMI. + IEnumWbemClassObject* pEnumerator = NULL; + hres = pSvc->ExecQuery( + bstr_t("WQL"), + bstr_t("SELECT * FROM Win32_BaseBoard"), + WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, + NULL, + &pEnumerator); + + if (FAILED(hres)) { + std::cerr << "WMI query for Win32_BaseBoard failed. Error code = 0x" << std::hex << hres << std::endl; + pSvc->Release(); + pLoc->Release(); + CoUninitialize(); + return m_board; + } + + // Get the data from the query. + IWbemClassObject *pclsObj; + ULONG uReturn = 0; + + while (pEnumerator) { + HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); + + if (0 == uReturn) { + break; + } + + VARIANT vtProp; + + // Get the value of the m_board property. + hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0); + if (SUCCEEDED(hr)) { + m_board = std::string(_bstr_t(vtProp.bstrVal)); + VariantClear(&vtProp); + } + + pclsObj->Release(); + } + + // Cleanup + pSvc->Release(); + pLoc->Release(); + pEnumerator->Release(); + CoUninitialize(); +#endif + +#ifdef __linux__ + std::ifstream file("/sys/class/dmi/id/product_serial"); + if (file.is_open()) { + std::getline(file, serialNumber); + file.close(); + } +#endif + +#ifdef __ANDROID__ + m_board = "andirod_0000"; +#endif + return m_board; +} + +bool DeviceInfo::VerifyMac(std::string mac) { + FormatMac(mac); + for (auto& m : m_macs) { + if(m.compare(mac) == 0) { + return true; + } + } + return false; +} + +bool DeviceInfo::VerifyBoard(std::string board) { + return board.compare(m_board) == 0; +} diff --git a/src/util/DeviceInfo.h b/src/util/DeviceInfo.h new file mode 100644 index 0000000..3e4cfac --- /dev/null +++ b/src/util/DeviceInfo.h @@ -0,0 +1,30 @@ +#ifndef DEVICE_INFO_H +#define DEVICE_INFO_H +#include +#include +#include "util/Singleton.h" + +/// @file 这个文件定义了一些跨平台的接口用于获取设备的mac、cpu、主板等信息 +class DeviceInfo : public Singleton { + public: + std::vector m_macs; + std::string m_board; + + /// @brief 获取设备的mac地址 + /// @return 设备的mac地址 + std::vector GetMacAddress(); + + /// @brief 获取设备的主板信息 + /// @return 设备的主板信息 + std::string GetBoardInfo(); + + /// @brief mac地址验证 + bool VerifyMac(std::string mac); + + /// @brief 主板序列号验证 + bool VerifyBoard(std::string board); + +}; + + +#endif \ No newline at end of file diff --git a/src/util/Singleton.h b/src/util/Singleton.h new file mode 100644 index 0000000..78743bb --- /dev/null +++ b/src/util/Singleton.h @@ -0,0 +1,19 @@ +#ifndef SINGLETON_H +#define SINGLETON_H + +template +class Singleton { +public: + static T& GetInstance() { + static T instance; + return instance; + } + Singleton(const Singleton&) = delete; + Singleton& operator=(const Singleton&) = delete; + +protected: + Singleton() {} + ~Singleton() {} +}; + +#endif \ No newline at end of file