Created
July 24, 2018 07:24
-
-
Save dkw72n/b041a28091ec04a7086f307aac9ecf7c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "stdafx.h" | |
| #include <comdef.h> | |
| #include <Wbemidl.h> | |
| # pragma comment(lib, "wbemuuid.lib") | |
| #pragma warning( disable : 4503 ) | |
| typedef std::map<std::wstring, std::wstring> HWINFO; | |
| typedef std::map<std::wstring, std::vector<HWINFO>> SYSINFO; | |
| static std::string WideToUTF8(const std::wstring &wide) { | |
| if (wide.length() == 0) { | |
| return std::string(); | |
| } | |
| // compute the length of the buffer we'll need | |
| int charcount = WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, | |
| //int charcount = WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1,//因为dump采用gbk | |
| NULL, 0, NULL, NULL); | |
| if (charcount == 0) { | |
| return std::string(); | |
| } | |
| // convert | |
| char *buf = new char[charcount]; | |
| WideCharToMultiByte(CP_UTF8, 0, wide.c_str(), -1, buf, charcount, | |
| //WideCharToMultiByte(CP_ACP, 0, wide.c_str(), -1, buf, charcount, | |
| NULL, NULL); | |
| std::string result(buf); | |
| delete[] buf; | |
| return result; | |
| } | |
| const std::wstring StrAdapterRam = L"AdapterRAM"; | |
| static HWINFO GetHwInfo(CComPtr<IWbemClassObject>& pClassObject){ | |
| HWINFO ret; | |
| SAFEARRAY *pvNames = NULL; | |
| if( pClassObject->GetNames(NULL, WBEM_FLAG_ALWAYS|WBEM_MASK_CONDITION_ORIGIN, NULL, &pvNames) != S_OK ) | |
| { | |
| printf("GetHwInfo error\n"); | |
| return ret; | |
| } | |
| long vbl, vbu; | |
| SafeArrayGetLBound(pvNames, 1, &vbl); | |
| SafeArrayGetUBound(pvNames, 1, &vbu); | |
| for(long i = vbl ; i<= vbu; i++ ) | |
| { | |
| long index = i ; | |
| WCHAR *wsName = NULL ; | |
| CComVariant varValue ; | |
| SafeArrayGetElement( pvNames, &index , &wsName ) ; | |
| CComBSTR bstrName ( wsName ) ; | |
| if( pClassObject->Get( bstrName , 0 , &varValue , NULL , 0 ) != S_OK ){ | |
| continue; | |
| } | |
| std::wstring str ; | |
| if( varValue.vt == VT_BSTR ) | |
| { | |
| // wprintf(L"%s = %s\n", wsName, varValue.bstrVal); | |
| str = varValue.bstrVal ; | |
| } | |
| else if( varValue.vt == VT_ARRAY ) | |
| { | |
| long iLowBound = 0 , iUpBound = 0 ; | |
| SafeArrayGetLBound( varValue.parray , 1 , &iLowBound ) ; | |
| SafeArrayGetUBound( varValue.parray , 1 , &iUpBound ) ; | |
| for( long j = iLowBound ; j <= iUpBound ; j ++ ) | |
| { | |
| VARIANT *pvar = NULL ; | |
| long temp = j ; | |
| if(SafeArrayGetElement( varValue.parray , &temp , pvar ) == S_OK && pvar) | |
| { | |
| CComVariant varTemp ; | |
| if( varTemp.ChangeType( VT_BSTR , pvar ) == S_OK ) | |
| { | |
| if( !str.empty() ) | |
| str += _T(",") ; | |
| str += varTemp.bstrVal ; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (StrAdapterRam == wsName){ | |
| // see: https://www.reddit.com/r/Windows10/comments/5vjkof/so_microsoft_when_will_you_fix_this_god_damn/ | |
| varValue.ChangeType(VT_UI4); | |
| } | |
| if( varValue.ChangeType( VT_BSTR ) == S_OK ) | |
| str = varValue.bstrVal ; | |
| } | |
| // 打印出硬件信息 | |
| // TRACE( "%s=%s/n" , CString(bstrName) , str ) ; | |
| // wcout << wsName << L"=" << str << endl; | |
| // wprintf(L"%s = %s\n", wsName, str.c_str()); | |
| ret[wsName] = str; | |
| } | |
| Exit0: | |
| if(pvNames) | |
| { | |
| SafeArrayDestroy(pvNames); | |
| } | |
| return ret ; | |
| } | |
| class CoGuard{ | |
| CComPtr<IWbemServices> m_pWbemServices; | |
| public: | |
| CoGuard(){ | |
| CoInitialize(NULL); | |
| } | |
| bool Init(){ | |
| HRESULT hresult; | |
| CComPtr<IWbemLocator> spWbemLocator ; | |
| CComPtr<IWbemServices> spWbemServices ; | |
| hresult = CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE,NULL, EOAC_NONE, 0); | |
| if(hresult != S_OK && hresult != RPC_E_TOO_LATE){ | |
| return false; | |
| } | |
| if(spWbemLocator.CoCreateInstance( CLSID_WbemAdministrativeLocator, 0, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER ) != S_OK){ | |
| return false; | |
| } | |
| if( spWbemLocator->ConnectServer( L"\\\\.\\root\\CIMV2", NULL, NULL, NULL, 0, NULL, NULL, &spWbemServices ) != S_OK ){ | |
| return false; | |
| } | |
| m_pWbemServices = spWbemServices; | |
| return true; | |
| } | |
| bool IsInit(){ | |
| return m_pWbemServices != nullptr; | |
| } | |
| const CComPtr<IWbemServices>& GetService(){ | |
| return m_pWbemServices; | |
| } | |
| bool QueryWmic(std::wstring query, std::vector<HWINFO>& ret, std::string& errmsg){ | |
| if (m_pWbemServices == nullptr){ | |
| errmsg = "CoGuard not inited"; | |
| return false; | |
| } | |
| auto spWbemServices = m_pWbemServices; | |
| CComBSTR q(query.data()); | |
| CComPtr<IEnumWbemClassObject> spEnumWbemClassObject ; | |
| if( spWbemServices->ExecQuery( L"WQL" , q , WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &spEnumWbemClassObject ) == S_OK ){ | |
| ULONG uCount = 1, uReturned; | |
| CComPtr<IWbemClassObject> spClassObject ; | |
| if( spEnumWbemClassObject->Reset() == S_OK ) | |
| { | |
| while( spEnumWbemClassObject->Next( WBEM_INFINITE, uCount, &spClassObject, &uReturned) == S_OK ) | |
| { | |
| ret.push_back(GetHwInfo( spClassObject )); | |
| spClassObject.Release() ; | |
| } | |
| } else { | |
| errmsg = "spEnumWbemClassObject->Reset() FAILED"; | |
| return false; | |
| } | |
| } else { | |
| errmsg = "spWbemServices->ExecQuery() FAILED"; | |
| return false; | |
| } | |
| return true; | |
| } | |
| ~CoGuard(){ | |
| m_pWbemServices = nullptr; | |
| CoUninitialize(); | |
| } | |
| }; | |
| /* | |
| bool QueryWmic(std::wstring query, std::vector<HWINFO>& ret, std::string& errmsg){ | |
| if (!s_coguard){ | |
| errmsg = "s_coguard not inited"; | |
| return false; | |
| } | |
| auto spWbemServices = s_coguard->GetService(); | |
| CComBSTR q(query.data()); | |
| CComPtr<IEnumWbemClassObject> spEnumWbemClassObject ; | |
| if( spWbemServices->ExecQuery( L"WQL" , q , WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &spEnumWbemClassObject ) == S_OK ){ | |
| ULONG uCount = 1, uReturned; | |
| CComPtr<IWbemClassObject> spClassObject ; | |
| if( spEnumWbemClassObject->Reset() == S_OK ) | |
| { | |
| while( spEnumWbemClassObject->Next( WBEM_INFINITE, uCount, &spClassObject, &uReturned) == S_OK ) | |
| { | |
| ret.push_back(GetHwInfo( spClassObject )); | |
| spClassObject.Release() ; | |
| } | |
| } else { | |
| errmsg = "spEnumWbemClassObject->Reset() FAILED"; | |
| return false; | |
| } | |
| } else { | |
| errmsg = "spWbemServices->ExecQuery() FAILED"; | |
| return false; | |
| } | |
| return true; | |
| } | |
| */ | |
| static bool GetSysInfo(SYSINFO& ret, std::string& err){ | |
| auto coguard = CoGuard(); | |
| if (!coguard.Init()){ | |
| err = "coguard.Init() FAILED"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT Name,Manufacturer,MaxClockSpeed,NumberOfCores,NumberOfLogicalProcessors,ProcessorId,Revision,SerialNumber,UniqueId FROM win32_Processor", ret[L"CPU"], err)){ | |
| err += "(CPU)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT SerialNumber,Caption,Manufacturer,Product,Version FROM win32_BaseBoard", ret[L"Board"], err)){ | |
| err += "(Board)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT Capacity,Manufacturer,SerialNumber,PartNumber FROM win32_PhysicalMemory", ret[L"Memory"], err)){ | |
| err += "(Memory)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT MACAddress,GUID,Caption,PNPDeviceID,PhysicalAdapter FROM win32_NetworkAdapter", ret[L"Network"], err)){ | |
| err += "(Network)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT SerialNumber,Size,Name,Signature,Model,Caption,FirmwareRevision FROM win32_DiskDrive", ret[L"Disk"], err)){ | |
| err += "(Disk)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT AdapterRAM,DriverVersion,InstalledDisplayDrivers,Name,Caption FROM win32_VideoController", ret[L"Graphic"], err)){ | |
| err += "(Graphic)"; | |
| return false; | |
| } | |
| if (!coguard.QueryWmic(L"SELECT Caption,Name,Description,FreeSpace,Size,VolumeSerialNumber FROM win32_LogicalDisk", ret[L"Partition"], err)){ | |
| err += "(Partition)"; | |
| return false; | |
| } | |
| return true; | |
| } | |
| static std::string JsonEscape(std::string str){ | |
| std::string ret; | |
| for(auto c:str){ | |
| switch(c){ | |
| case '\\': | |
| case '"': | |
| case '/': | |
| ret += "\\"; | |
| ret += c; | |
| break; | |
| case '\b': | |
| ret += "\\b"; | |
| break; | |
| case '\f': | |
| ret += "\\f"; | |
| break; | |
| case '\t': | |
| ret += "\\t"; | |
| break; | |
| case '\n': | |
| ret += "\\n"; | |
| break; | |
| case '\r': | |
| ret += "\\r"; | |
| break; | |
| default: | |
| if (c >=0 && c < ' ') { | |
| char buf[10]; | |
| sprintf_s(buf, "\\u%04x", c); | |
| ret += c; | |
| } else { | |
| ret += c; | |
| } | |
| } | |
| } | |
| return ret; | |
| } | |
| static std::string SysInfoToJson(SYSINFO sysinfo){ | |
| std::string ret; | |
| int syscnt = 0; | |
| ret += "{\n"; | |
| for(auto p: sysinfo){ | |
| if (syscnt++){ | |
| ret += ",\n"; | |
| } | |
| ret += " \""; | |
| ret += JsonEscape(WideToUTF8(p.first)); | |
| ret += "\": [\n"; | |
| int hwcnt = 0; | |
| for (auto hw: p.second){ | |
| if (hwcnt++){ | |
| ret += ",\n"; | |
| } | |
| ret += " {\n"; | |
| int propcnt = 0; | |
| for (auto pp: hw){ | |
| if (propcnt++){ | |
| ret += ",\n"; | |
| } | |
| ret += " \""; | |
| ret += JsonEscape(WideToUTF8(pp.first)); | |
| ret += "\": \""; | |
| ret += JsonEscape(WideToUTF8(pp.second)); | |
| ret += "\""; | |
| } | |
| ret += "\n }"; | |
| } | |
| ret += "\n ]"; | |
| } | |
| ret += "\n}\n"; | |
| return ret; | |
| } | |
| bool GetSysInfoJson(std::string& result, std::string& errmsg){ | |
| SYSINFO info; | |
| if (!GetSysInfo(info, errmsg)){ | |
| return false; | |
| } | |
| result = SysInfoToJson(info); | |
| return true; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment