fixes for Windows's SystemInfo
This commit is contained in:
@@ -24,7 +24,7 @@ namespace OpenVulkano
|
||||
|
||||
enum class DeviceOrientation { Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, FaceUp, FaceDown, Unknown };
|
||||
|
||||
enum class InterfaceOrientation { Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, Landscape = LandscapeLeft, Unknown };
|
||||
enum class InterfaceOrientation { Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight, Landscape = LandscapeLeft };
|
||||
|
||||
class SystemInfo
|
||||
{
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#define _WIN32_DCOM
|
||||
|
||||
#include "Host/SystemInfo.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#include <iostream>
|
||||
#include <utf8.h>
|
||||
#include <Windows.h>
|
||||
#include <Psapi.h>
|
||||
#include <Lmcons.h>
|
||||
@@ -14,7 +17,8 @@
|
||||
#include <Winbase.h>
|
||||
#include <powersetting.h>
|
||||
#include <guiddef.h>
|
||||
#include <VersionHelpers.h>
|
||||
#include <comdef.h>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
// NOTE(vb): Windows defines macros like GetUserName that are used to automatically select the appropriate function version (GetUserNameA for ANSI and GetUserNameW for Unicode)
|
||||
// based on whether the _UNICODE macro is defined, so we manually undefine these macros to avoid naming collisions.
|
||||
@@ -22,6 +26,7 @@
|
||||
|
||||
// link this for power settings
|
||||
#pragma comment(lib, "PowrProf.lib")
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
@@ -84,6 +89,170 @@ namespace OpenVulkano
|
||||
Logger::PERF->error("Failed to get system commit limit");
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::optional<std::string> GetWMIProperty(const std::string& propName)
|
||||
{
|
||||
std::optional<std::string> res;
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/wmisdk/example-creating-a-wmi-application?redirectedfrom=MSDN
|
||||
HRESULT hres;
|
||||
|
||||
// Initialize COM.
|
||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Failed to initialize COM library. Error code = 0x{}", hres);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Initialize
|
||||
hres = CoInitializeSecurity(NULL,
|
||||
-1, // COM negotiates service
|
||||
NULL, // Authentication services
|
||||
NULL, // Reserved
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT, // authentication
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation
|
||||
NULL, // Authentication info
|
||||
EOAC_NONE, // Additional capabilities
|
||||
NULL // Reserved
|
||||
);
|
||||
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Failed to initialize security. Error code = 0x{}", hres);
|
||||
CoUninitialize();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Obtain the initial locator to Windows Management
|
||||
// on a particular host computer.
|
||||
IWbemLocator* pLoc = 0;
|
||||
|
||||
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*) &pLoc);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Failed to create IWbemLocator object. Error code = 0x{}", hres);
|
||||
CoUninitialize();
|
||||
return {};
|
||||
}
|
||||
|
||||
IWbemServices* pSvc = 0;
|
||||
|
||||
// Connect to the root\cimv2 namespace with the
|
||||
// current user and obtain pointer pSvc
|
||||
// to make IWbemServices calls.
|
||||
|
||||
hres = pLoc->ConnectServer(
|
||||
_bstr_t(L"ROOT\\CIMV2"), // WMI namespace
|
||||
NULL, // User name
|
||||
NULL, // User password
|
||||
0, // Locale
|
||||
NULL, // Security flags
|
||||
0, // Authority
|
||||
0, // Context object
|
||||
&pSvc // IWbemServices proxy
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Could not connect. Error code = 0x{}", hres);
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Set the IWbemServices proxy so that impersonation
|
||||
// of the user (client) occurs.
|
||||
hres = CoSetProxyBlanket(
|
||||
pSvc, // the proxy to set
|
||||
RPC_C_AUTHN_WINNT, // authentication service
|
||||
RPC_C_AUTHZ_NONE, // authorization service
|
||||
NULL, // Server principal name
|
||||
RPC_C_AUTHN_LEVEL_CALL, // authentication level
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
|
||||
NULL, // client identity
|
||||
EOAC_NONE // proxy capabilities
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Could not set proxy blanket. Error code = 0x{}", hres);
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return {};
|
||||
}
|
||||
|
||||
// Use the IWbemServices pointer to make requests of WMI.
|
||||
// Make requests here:
|
||||
|
||||
// For example, query for all the running processes
|
||||
IEnumWbemClassObject* pEnumerator = NULL;
|
||||
hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_ComputerSystem"),
|
||||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Query for processes failed. Error code = 0x{}", hres);
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
CoUninitialize();
|
||||
return {};
|
||||
}
|
||||
else
|
||||
{
|
||||
IWbemClassObject* pclsObj;
|
||||
ULONG uReturn = 0;
|
||||
|
||||
while (pEnumerator)
|
||||
{
|
||||
hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
|
||||
|
||||
if (0 == uReturn)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
VARIANT vtProp;
|
||||
ZeroMemory(&vtProp, sizeof(vtProp));
|
||||
|
||||
std::wstring propNameUtf16;
|
||||
utf8::utf8to16(propName.begin(), propName.end(), std::back_inserter(propNameUtf16));
|
||||
|
||||
// Get the value of the specified property
|
||||
hres = pclsObj->Get(propNameUtf16.data(), 0, &vtProp, 0, 0);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
Logger::APP->error("Failed to get property {}. Error code = 0x{}", propName, hres);
|
||||
}
|
||||
else
|
||||
{
|
||||
// init optional
|
||||
res = "";
|
||||
std::wstring propValue = vtProp.bstrVal;
|
||||
utf8::utf16to8(propValue.begin(), propValue.end(), std::back_inserter(*res));
|
||||
}
|
||||
VariantClear(&vtProp);
|
||||
pclsObj->Release();
|
||||
pclsObj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
// ========
|
||||
|
||||
pSvc->Release();
|
||||
pLoc->Release();
|
||||
pEnumerator->Release();
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
size_t SystemInfo::GetSystemRam()
|
||||
@@ -141,12 +310,14 @@ namespace OpenVulkano
|
||||
|
||||
std::string SystemInfo::GetDeviceVendorName()
|
||||
{
|
||||
return "Microsoft"; //TODO
|
||||
std::optional<std::string> res = GetWMIProperty("Manufacturer");
|
||||
return res ? *res : "Unknown";
|
||||
}
|
||||
|
||||
std::string SystemInfo::GetDeviceModelName()
|
||||
{
|
||||
return "Unknown"; //TODO
|
||||
std::optional<std::string> res = GetWMIProperty("Model");
|
||||
return res ? *res : "Unknown";
|
||||
}
|
||||
|
||||
std::string SystemInfo::GetOsName()
|
||||
@@ -156,10 +327,11 @@ namespace OpenVulkano
|
||||
|
||||
OsVersion SystemInfo::GetOsVersion()
|
||||
{
|
||||
OSVERSIONINFOA info;
|
||||
ZeroMemory(&info, sizeof(OSVERSIONINFOA));
|
||||
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
||||
GetVersionExA(&info);
|
||||
NTSTATUS(WINAPI * RtlGetVersion)(LPOSVERSIONINFOEXW);
|
||||
OSVERSIONINFOEXW info;
|
||||
*(FARPROC*) &RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
RtlGetVersion(&info);
|
||||
return { (int)info.dwMajorVersion, (int)info.dwMinorVersion, 0, (int)info.dwBuildNumber };
|
||||
}
|
||||
|
||||
@@ -245,13 +417,26 @@ namespace OpenVulkano
|
||||
|
||||
size_t SystemInfo::GetCpuCoreCount()
|
||||
{
|
||||
SYSTEM_INFO info;
|
||||
ZeroMemory(&info, sizeof(SYSTEM_INFO));
|
||||
GetSystemInfo(&info);
|
||||
return info.dwNumberOfProcessors;
|
||||
DWORD bufferSize = 0;
|
||||
GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP::RelationProcessorCore, nullptr, &bufferSize);
|
||||
|
||||
std::vector<BYTE> buf(bufferSize);
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* info = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(buf.data());
|
||||
GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP::RelationProcessorCore, info, &bufferSize);
|
||||
|
||||
size_t physProcessorCount = 0;
|
||||
BYTE* start = buf.data();
|
||||
BYTE* end = buf.data() + bufferSize;
|
||||
while (start < end)
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* current = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(start);
|
||||
physProcessorCount++;
|
||||
start += current->Size;
|
||||
}
|
||||
return physProcessorCount;
|
||||
}
|
||||
|
||||
size_t SystemInfo::GetCpuThreadCount()
|
||||
size_t SystemInfo::GetCpuThreadCount()
|
||||
{
|
||||
return std::thread::hardware_concurrency();
|
||||
}
|
||||
@@ -272,7 +457,7 @@ namespace OpenVulkano
|
||||
bool res = false;
|
||||
if(PowerGetActiveScheme(0, &activePowerMode) == 0)
|
||||
{
|
||||
res = IsEqualGUID(*activePowerMode, GUID_MIN_POWER_SAVINGS);
|
||||
res = IsEqualGUID(*activePowerMode, GUID_MAX_POWER_SAVINGS);
|
||||
}
|
||||
LocalFree(activePowerMode);
|
||||
return res;
|
||||
@@ -289,7 +474,7 @@ namespace OpenVulkano
|
||||
return BatteryState::ChargingFull;
|
||||
return BatteryState::Charging;
|
||||
}
|
||||
else if (batteryFlag >= BatteryChargeStatus::MEDIUM && batteryFlag <= BatteryChargeStatus::CRITICAL)
|
||||
else if (batteryFlag < BatteryChargeStatus::CHARGING)
|
||||
{
|
||||
return BatteryState::Unplugged;
|
||||
}
|
||||
@@ -302,7 +487,7 @@ namespace OpenVulkano
|
||||
{
|
||||
SYSTEM_POWER_STATUS info;
|
||||
GetSystemPowerStatus(&info);
|
||||
return info.BatteryLifePercent != 255 ? static_cast<float>(info.BatteryLifePercent) : 0;
|
||||
return info.BatteryLifePercent != 255 ? (static_cast<float>(info.BatteryLifePercent / 100.f)) : -1.f;
|
||||
}
|
||||
|
||||
void SystemInfo::EnableEnergyEvents()
|
||||
@@ -356,7 +541,7 @@ namespace OpenVulkano
|
||||
case OpenVulkano::DeviceOrientation::LandscapeRight:
|
||||
return InterfaceOrientation::LandscapeLeft;
|
||||
default:
|
||||
return InterfaceOrientation::Unknown;
|
||||
return InterfaceOrientation::Landscape;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user