c++通过SMBIOS获取电脑品牌、型号等相关信息
smbios.h
#pragma once #include <windows.h> class SMBIOS { private: SMBIOS(); void initialization(void); UINT MajorVersion; UINT MinorVersion; DWORD DMIRevision; private: // for Type 0 PWCHAR m_wszBIOSVendor; PWCHAR m_wszBIOSVersion; PWCHAR m_wszBIOSReleaseDate; DWORD m_BIOSSysVersion; DWORD m_BIOSECVersion; // for Type 1 PWCHAR m_wszSysManufactor; PWCHAR m_wszSysProductName; PWCHAR m_wszSysVersion; PWCHAR m_wszSysSerialNumber; UUID m_SysUUID; PWCHAR m_wszSysSKU; PWCHAR m_wszSysFamily; // for Type 2 PWCHAR m_wszBoardManufactor; PWCHAR m_wszBoardProductName; PWCHAR m_wszBoardVersion; PWCHAR m_wszBoardSerialNumber; PWCHAR m_wszBoardAssetTag; PWCHAR m_wszBoardLocation; public: virtual ~SMBIOS(); static const SMBIOS& getInstance(void); public: // Type 0 const PWCHAR BIOSVendor(void) const { return m_wszBIOSVendor; } const PWCHAR BIOSVersion(void) const { return m_wszBIOSVersion; } const PWCHAR BIOSReleaseDate(void) const { return m_wszBIOSReleaseDate; } const DWORD BIOSSysVersion(void) const { return m_BIOSSysVersion; } const DWORD BIOSECVersion(void) const { return m_BIOSECVersion; } // Type 1 const PWCHAR SysManufactor(void) const { return m_wszSysManufactor; } const PWCHAR SysProductName(void) const { return m_wszSysProductName; } const PWCHAR SysVersion(void) const { return m_wszSysVersion; } const PWCHAR SysSerialNumber(void) const { return m_wszSysSerialNumber; } const UUID& SysUUID(void) const { return m_SysUUID; } const PWCHAR SysSKU(void) const { return m_wszSysSKU; } const PWCHAR SysFamily(void) const { return m_wszSysFamily; } // Type 2 const PWCHAR BoardManufactor(void) const { return m_wszBoardManufactor; } const PWCHAR BoardProductName(void) const { return m_wszBoardProductName; } const PWCHAR BoardVersion(void) const { return m_wszBoardVersion; } const PWCHAR BoardSerialNumber(void) const { return m_wszBoardSerialNumber; } const PWCHAR BoardAssetTag(void) const { return m_wszBoardAssetTag; } const PWCHAR BoardLocation(void) const { return m_wszBoardLocation; } private: // helper function static bool ProcBIOSInfo(SMBIOS* T, void* p); static bool ProcSysInfo(SMBIOS* T, void* p); static bool ProcBoardInfo(SMBIOS* T, void* p); void ParseSMBIOSStruct(void* Addr, UINT Len); bool DispatchStructType(void* pHdr); bool getWmiSmbios(BYTE ** data, UINT * length); };
smbios.cpp
#include "smbios.h" #include <wbemidl.h> #include <sstream> #include <comdef.h> #pragma comment(lib, "Wbemuuid.lib") typedef UINT(WINAPI *GET_SYSTEM_FIRMWARE_TABLE) (DWORD, DWORD, PVOID, DWORD); #pragma pack(push) #pragma pack(1) typedef struct _RawSMBIOSData { BYTE Used20CallingMethod; BYTE MajorVersion; BYTE MinorVersion; BYTE DmiRevision; DWORD Length; PBYTE SMBIOSTableData; } RawSMBIOSData, *PRawSMBIOSData; typedef struct _SMBIOSHEADER_ { BYTE Type; BYTE Length; WORD Handle; } SMBIOSHEADER, *PSMBIOSHEADER; typedef struct _TYPE_0_ { SMBIOSHEADER Header; UCHAR Vendor; UCHAR Version; UINT16 StartingAddrSeg; UCHAR ReleaseDate; UCHAR ROMSize; ULONG64 Characteristics; UCHAR Extension[2]; // spec. 2.3 UCHAR MajorRelease; UCHAR MinorRelease; UCHAR ECFirmwareMajor; UCHAR ECFirmwareMinor; } BIOSInfo, *PBIOSInfo; typedef struct _TYPE_1_ { SMBIOSHEADER Header; UCHAR Manufacturer; UCHAR ProductName; UCHAR Version; UCHAR SN; UCHAR UUID[16]; UCHAR WakeUpType; UCHAR SKUNumber; UCHAR Family; } SystemInfo, *PSystemInfo; typedef struct _TYPE_2_ { SMBIOSHEADER Header; UCHAR Manufacturer; UCHAR Product; UCHAR Version; UCHAR SN; UCHAR AssetTag; UCHAR FeatureFlags; UCHAR LocationInChassis; UINT16 ChassisHandle; UCHAR Type; UCHAR NumObjHandle; UINT16 *pObjHandle; } BoardInfo, *PBoardInfo; #pragma pack(pop) static const char* LocateStringA(const char* str, UINT i) { static const char strNull[] = ""; if (0 == i || 0 == *str) return strNull; while (--i) { str += strlen((char*)str) + 1; } return str; } static const char* toPointString(void* p) { return (char*)p + ((PSMBIOSHEADER)p)->Length; } bool SMBIOS::ProcBIOSInfo(SMBIOS* T, void* p) { PBIOSInfo pBIOS = (PBIOSInfo)p; const char* str = toPointString(p); const char* Vendor = LocateStringA(str, pBIOS->Vendor); const char* Version = LocateStringA(str, pBIOS->Version); const char* Date = LocateStringA(str, pBIOS->ReleaseDate); const int nVendor = (int) strlen(Vendor); const int nVersion = (int) strlen(Version); const int nDate = (int) strlen(Date); T->m_wszBIOSVendor = new WCHAR[nVendor + 1]; T->m_wszBIOSVersion = new WCHAR[nVersion + 1]; T->m_wszBIOSReleaseDate = new WCHAR[nDate + 1]; if (T->m_wszBIOSVendor) { ::SecureZeroMemory(T->m_wszBIOSVendor, sizeof(WCHAR) * (nVendor + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Vendor, nVendor, T->m_wszBIOSVendor, nVendor + 1); } if (T->m_wszBIOSVersion) { ::SecureZeroMemory(T->m_wszBIOSVersion, sizeof(WCHAR) * (nVersion + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Version, nVersion, T->m_wszBIOSVersion, nVersion + 1); } if (T->m_wszBIOSReleaseDate) { ::SecureZeroMemory(T->m_wszBIOSReleaseDate, sizeof(WCHAR) * (nDate + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Date, nDate, T->m_wszBIOSReleaseDate, nDate + 1); } if (pBIOS->Header.Length > 0x14) { T->m_BIOSSysVersion = pBIOS->MajorRelease << 16 | pBIOS->MinorRelease; T->m_BIOSECVersion = pBIOS->ECFirmwareMajor << 16 | pBIOS->ECFirmwareMinor; } return true; } bool SMBIOS::ProcSysInfo(SMBIOS* T, void* p) { PSystemInfo pSystem = (PSystemInfo)p; const char* str = toPointString(p); const char* Manufactor = LocateStringA(str, pSystem->Manufacturer); const char* ProductName = LocateStringA(str, pSystem->ProductName); const char* Version = LocateStringA(str, pSystem->Version); const char* SerialNumber = LocateStringA(str, pSystem->SN); const int nManufactor = (int) strlen(Manufactor); const int nProductName = (int) strlen(ProductName); const int nVersion = (int) strlen(Version); const int nSerialNumber = (int) strlen(SerialNumber); T->m_wszSysManufactor = new WCHAR[nManufactor + 1]; T->m_wszSysProductName = new WCHAR[nProductName + 1]; T->m_wszSysVersion = new WCHAR[nVersion + 1]; T->m_wszSysSerialNumber = new WCHAR[nSerialNumber + 1]; if (T->m_wszSysManufactor) { ::SecureZeroMemory(T->m_wszSysManufactor, sizeof(WCHAR)*(nManufactor + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Manufactor, nManufactor, T->m_wszSysManufactor, nManufactor + 1); } if (T->m_wszSysProductName) { ::SecureZeroMemory(T->m_wszSysProductName, sizeof(WCHAR)*(nProductName + 1)); ::MultiByteToWideChar(CP_ACP, NULL, ProductName, nProductName, T->m_wszSysProductName, nProductName + 1); } if (T->m_wszSysVersion) { ::SecureZeroMemory(T->m_wszSysVersion, sizeof(WCHAR)*(nVersion + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Version, nVersion, T->m_wszSysVersion, nVersion + 1); } if (T->m_wszSysSerialNumber) { ::SecureZeroMemory(T->m_wszSysSerialNumber, sizeof(WCHAR)*(nSerialNumber + 1)); ::MultiByteToWideChar(CP_ACP, NULL, SerialNumber, nSerialNumber, T->m_wszSysSerialNumber, nSerialNumber + 1); } if (pSystem->Header.Length > 0x08) { memcpy_s(&(T->m_SysUUID), sizeof(UUID), pSystem->UUID, 16); } if (pSystem->Header.Length > 0x19) { const char* SKU = LocateStringA(str, pSystem->SKUNumber); const char* Family = LocateStringA(str, pSystem->Family); const int nSKU = (int) strlen(SKU); const int nFamily = (int) strlen(Family); T->m_wszSysSKU = new WCHAR[nSKU + 1]; T->m_wszSysFamily = new WCHAR[nFamily + 1]; if (T->m_wszSysSKU) { ::SecureZeroMemory(T->m_wszSysSKU, sizeof(WCHAR)*(nSKU + 1)); ::MultiByteToWideChar(CP_ACP, NULL, SKU, nSKU, T->m_wszSysSKU, nSKU + 1); } if (T->m_wszSysFamily) { ::SecureZeroMemory(T->m_wszSysFamily, sizeof(WCHAR)*(nFamily + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Family, nFamily, T->m_wszSysFamily, nFamily + 1); } } return true; } bool SMBIOS::ProcBoardInfo(SMBIOS* T, void* p) { PBoardInfo pBoard = (PBoardInfo)p; const char* str = toPointString(p); const char* Manufactor = LocateStringA(str, pBoard->Manufacturer); const char* ProductName = LocateStringA(str, pBoard->Product); const char* Version = LocateStringA(str, pBoard->Version); const char* SerialNumber = LocateStringA(str, pBoard->SN); const char* AssetTag = LocateStringA(str, pBoard->AssetTag); const int nManufactor = (int) strlen(Manufactor); const int nProductName = (int) strlen(ProductName); const int nVersion = (int) strlen(Version); const int nSerialNumber = (int) strlen(SerialNumber); const int nAssetTag = (int) strlen(AssetTag); T->m_wszBoardManufactor = new WCHAR[nManufactor + 1]; T->m_wszBoardProductName = new WCHAR[nProductName + 1]; T->m_wszBoardVersion = new WCHAR[nVersion + 1]; T->m_wszBoardSerialNumber = new WCHAR[nSerialNumber + 1]; T->m_wszBoardAssetTag = new WCHAR[nAssetTag + 1]; if (T->m_wszBoardManufactor) { ::SecureZeroMemory(T->m_wszBoardManufactor, sizeof(WCHAR)*(nManufactor + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Manufactor, nManufactor, T->m_wszBoardManufactor, nManufactor); } if (T->m_wszBoardProductName) { ::SecureZeroMemory(T->m_wszBoardProductName, sizeof(WCHAR)*(nProductName + 1)); ::MultiByteToWideChar(CP_ACP, NULL, ProductName, nProductName, T->m_wszBoardProductName, nProductName); } if (T->m_wszBoardVersion) { ::SecureZeroMemory(T->m_wszBoardVersion, sizeof(WCHAR)*(nVersion + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Version, nVersion, T->m_wszBoardVersion, nVersion); } if (T->m_wszBoardSerialNumber) { ::SecureZeroMemory(T->m_wszBoardSerialNumber, sizeof(WCHAR)*(nSerialNumber + 1)); ::MultiByteToWideChar(CP_ACP, NULL, SerialNumber, nSerialNumber, T->m_wszBoardSerialNumber, nSerialNumber); } if (T->m_wszBoardAssetTag) { ::SecureZeroMemory(T->m_wszBoardAssetTag, sizeof(WCHAR)*(nAssetTag + 1)); ::MultiByteToWideChar(CP_ACP, NULL, AssetTag, nAssetTag, T->m_wszBoardAssetTag, nAssetTag); } if (pBoard->Header.Length > 0x08) { const char* Location = LocateStringA(str, pBoard->LocationInChassis); const int nLocation = (int) strlen(Location); T->m_wszBoardLocation = new WCHAR[nLocation + 1]; if (T->m_wszBoardLocation) { ::SecureZeroMemory(T->m_wszBoardLocation, sizeof(WCHAR)*(nLocation + 1)); ::MultiByteToWideChar(CP_ACP, NULL, Location, nLocation, T->m_wszBoardLocation, nLocation); } } return true; } bool SMBIOS::DispatchStructType(void* pHdr) { typedef struct { BYTE t; bool(*Proc)(SMBIOS* T, void* p); } TPFUNC; const TPFUNC tpfunc[] = { { 0, ProcBIOSInfo }, { 1, ProcSysInfo }, { 2, ProcBoardInfo }, }; PSMBIOSHEADER hdr = (PSMBIOSHEADER)pHdr; for (UINT i = 0; i < sizeof(tpfunc) / sizeof(TPFUNC); i++) { if (tpfunc[i].t == hdr->Type) { tpfunc[i].Proc(this, (void*)hdr); return true; } } return false; } void SMBIOS::ParseSMBIOSStruct(void* Addr, UINT Len) { LPBYTE p = (LPBYTE)(Addr); const LPBYTE lastAddress = p + Len; PSMBIOSHEADER pHeader; for (;;) { pHeader = (PSMBIOSHEADER)p; if (pHeader->Type == 127 && pHeader->Length == 4) break; // last avaiable table DispatchStructType((void*)p); LPBYTE nt = p + pHeader->Length; // point to struct end while (0 != (*nt | *(nt + 1))) { nt++; // skip string area if (nt >= lastAddress) break; // avoid infinite loop when got bad structure of SMBIOS } nt += 2; if (nt >= lastAddress) break; p = nt; } } SMBIOS::SMBIOS() : m_BIOSSysVersion(0UL), m_BIOSECVersion(0UL), m_wszBIOSVendor(NULL), m_wszBIOSVersion(NULL), m_wszBIOSReleaseDate(NULL), m_wszSysManufactor(NULL), m_wszSysProductName(NULL), m_wszSysVersion(NULL), m_wszSysSerialNumber(NULL), m_SysUUID(GUID_NULL), m_wszSysSKU(NULL), m_wszSysFamily(NULL), m_wszBoardManufactor(NULL), m_wszBoardProductName(NULL), m_wszBoardVersion(NULL), m_wszBoardSerialNumber(NULL), m_wszBoardAssetTag(NULL), m_wszBoardLocation(NULL) { } SMBIOS::~SMBIOS() { if (m_wszBIOSVendor) delete m_wszBIOSVendor; if (m_wszBIOSVersion) delete m_wszBIOSVersion; if (m_wszBIOSReleaseDate) delete m_wszBIOSReleaseDate; if (m_wszSysManufactor) delete m_wszSysManufactor; if (m_wszSysProductName) delete m_wszSysProductName; if (m_wszSysVersion) delete m_wszSysVersion; if (m_wszSysSerialNumber) delete m_wszSysSerialNumber; if (m_wszSysSKU) delete m_wszSysSKU; if (m_wszSysFamily) delete m_wszSysFamily; if (m_wszBoardManufactor) delete m_wszBoardManufactor; if (m_wszBoardProductName) delete m_wszBoardProductName; if (m_wszBoardVersion) delete m_wszBoardVersion; if (m_wszBoardSerialNumber) delete m_wszBoardSerialNumber; if (m_wszBoardAssetTag) delete m_wszBoardAssetTag; if (m_wszBoardLocation) delete m_wszBoardLocation; } const SMBIOS& SMBIOS::getInstance(void) { static SMBIOS* pInstance = NULL; if (pInstance == NULL) { // need entry a mutex for thread safe if (pInstance == NULL) { pInstance = new SMBIOS(); pInstance->initialization(); } } const SMBIOS& ref = (*pInstance); return ref; } void SMBIOS::initialization(void) { GET_SYSTEM_FIRMWARE_TABLE pGetSystemFirmwareTable = (GET_SYSTEM_FIRMWARE_TABLE)GetProcAddress(GetModuleHandle(L"kernel32"), "GetSystemFirmwareTable"); LPBYTE pBuff = NULL; PBYTE tableStart = nullptr; UINT nTableLength = 0; DWORD needBufferSize = 0; if (pGetSystemFirmwareTable) { const DWORD Signature = 'RSMB'; #if 0 DWORD Signature = 'R'; Signature = (Signature << 8) + 'S'; Signature = (Signature << 8) + 'M'; Signature = (Signature << 8) + 'B'; #endif needBufferSize = pGetSystemFirmwareTable(Signature, 0, NULL, 0); pBuff = new BYTE[needBufferSize]; needBufferSize = pGetSystemFirmwareTable(Signature, 0, pBuff,needBufferSize); if (needBufferSize > 0) { const PRawSMBIOSData pDMIData = (PRawSMBIOSData)pBuff; MajorVersion = pDMIData->MajorVersion; MinorVersion = pDMIData->MinorVersion; DMIRevision = pDMIData->DmiRevision; tableStart = (PBYTE) & (pDMIData->SMBIOSTableData); nTableLength = pDMIData->Length; } } if ((0 == needBufferSize) || (nTableLength > needBufferSize)) { if (getWmiSmbios(&pBuff, &nTableLength)) tableStart = pBuff; } if (tableStart) ParseSMBIOSStruct(tableStart, nTableLength); if (pBuff) delete[] pBuff; } bool SMBIOS::getWmiSmbios(BYTE ** data, UINT * length) { IWbemServices * pSvc = NULL; IWbemServices * pSvcSmbios = NULL; IWbemLocator * pLoc = NULL; HRESULT result; IEnumWbemClassObject * pEnumerator = NULL; std::wostringstream query; std::wstring q; IWbemClassObject * pInstance = NULL; VARIANT vtProp; ULONG uReturn = 0; CIMTYPE pvtType; result = CoInitialize(NULL); if (!SUCCEEDED(result)) return false; result = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if (!SUCCEEDED(result)) { CoUninitialize(); return false; } result = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc); if (!SUCCEEDED(result)) { CoUninitialize(); return false; } result = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); if (!SUCCEEDED(result)) { pLoc->Release(); CoUninitialize(); return false; } result = 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 (!SUCCEEDED(result)) { pLoc->Release(); CoUninitialize(); return false; } result = pLoc->ConnectServer(_bstr_t(L"ROOT\\WMI"), NULL, NULL, 0, NULL, 0, 0, &pSvcSmbios); if (!SUCCEEDED(result)) { pLoc->Release(); CoUninitialize(); return false; } result = CoSetProxyBlanket(pSvcSmbios, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (!SUCCEEDED(result)) { pSvcSmbios->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); } result = pSvcSmbios->CreateInstanceEnum((BSTR)L"MSSMBios_RawSMBiosTables", 0, NULL, &pEnumerator); if (SUCCEEDED(result)) { while (pEnumerator) { result = pEnumerator->Next(WBEM_INFINITE, 1, &pInstance, &uReturn); if (!uReturn) { break; } VariantInit(&vtProp); result = pInstance->Get(bstr_t("SMBiosData"), 0, &vtProp, &pvtType, NULL); if (SUCCEEDED(result)) { SAFEARRAY * array = V_ARRAY(&vtProp); *length = array->rgsabound[0].cElements; *data = new BYTE[*length]; memcpy(*data, (BYTE*)array->pvData, *length); VariantClear(&vtProp); } } pEnumerator->Release(); if (pInstance) pInstance->Release(); } if (pSvcSmbios) pSvcSmbios->Release(); if (pSvc) pSvc->Release(); if (pLoc) pLoc->Release(); CoUninitialize(); return true; }
main.cpp
#include <iostream> #include "smbios.h" int main(int argc, char* argv[]) { const SMBIOS& SmBios = SMBIOS::getInstance(); std::wcout << "制造商:" << SmBios.SysManufactor() << std::endl; std::wcout << "型号:" << SmBios.SysProductName() << std::endl; std::wcout << "版本:" << SmBios.SysVersion() << std::endl; system("pause"); return 0; }