Files
OpenVulkano/openVulkanoCpp/Host/Windows/SystemInfo.cpp
2024-12-16 10:24:49 +02:00

362 lines
8.8 KiB
C++

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "Host/SystemInfo.hpp"
#include "Base/Logger.hpp"
#include <iostream>
#include <Windows.h>
#include <Psapi.h>
#include <Lmcons.h>
#include <Winsock.h>
#include <Winbase.h>
#include <powersetting.h>
#include <guiddef.h>
#include <VersionHelpers.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.
#undef GetUserName
// link this for power settings
#pragma comment(lib, "PowrProf.lib")
namespace OpenVulkano
{
namespace
{
enum class SYS_MEM_TYPE { TOTAL_PHYS, AVAIL_PHYS };
enum BatteryChargeStatus
{
MEDIUM = 0, // [low, high]
HIGH = 1, // > 66%
LOW = 2, // < 33%
CRITICAL = 4, // <5%
CHARGING = 8,
NO_SYSTEM_BATTERY = 128,
UNKNOWN = 255
};
size_t ReadSystemMemInfo(SYS_MEM_TYPE type)
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
if (GlobalMemoryStatusEx(&status))
{
switch (type)
{
case SYS_MEM_TYPE::TOTAL_PHYS: return status.ullTotalPhys;
case SYS_MEM_TYPE::AVAIL_PHYS: return status.ullAvailPhys;
}
}
Logger::PERF->error("Failed to get system RAM info");
return 0;
}
enum class APP_MEM_TYPE { VM_MAX, USED };
size_t ReadAppMemInfo(APP_MEM_TYPE type)
{
PROCESS_MEMORY_COUNTERS_EX counters;
if (GetProcessMemoryInfo(GetCurrentProcess(), reinterpret_cast<PROCESS_MEMORY_COUNTERS*>(&counters), sizeof(counters)))
{
switch(type)
{
case APP_MEM_TYPE::VM_MAX: return counters.PeakPagefileUsage;
case APP_MEM_TYPE::USED: return counters.PrivateUsage;
}
}
Logger::PERF->error("Failed to get process memory info");
return 0;
}
size_t GetCommitLimit()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
if(GlobalMemoryStatusEx(&status))
{
return status.ullTotalPageFile;
}
Logger::PERF->error("Failed to get system commit limit");
return 0;
}
}
size_t SystemInfo::GetSystemRam()
{
return ReadSystemMemInfo(SYS_MEM_TYPE::TOTAL_PHYS);
}
size_t SystemInfo::GetSystemRamAvailable()
{
return ReadSystemMemInfo(SYS_MEM_TYPE::AVAIL_PHYS);
}
size_t SystemInfo::GetAppRamMax()
{
return std::min(GetSystemRam(), GetCommitLimit());
}
size_t SystemInfo::GetAppRamAvailable()
{
return std::min(GetSystemRamAvailable(), GetCommitLimit() - GetAppRamUsed());
}
size_t SystemInfo::GetAppRamUsed()
{
return ReadAppMemInfo(APP_MEM_TYPE::USED);
}
size_t SystemInfo::GetAppVirtualMemoryMax()
{
return ReadAppMemInfo(APP_MEM_TYPE::VM_MAX);
}
std::string SystemInfo::GetUserName()
{
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
::GetUserNameA(username, &username_len);
return username;
}
std::string SystemInfo::GetHostName()
{
char hostname[UNLEN+1];
gethostname(hostname, UNLEN+1);
return hostname;
}
std::string SystemInfo::GetDeviceName()
{
char computerName[UNLEN+1];
DWORD computerName_len = UNLEN+1;
GetComputerNameA(computerName, &computerName_len);
return computerName;
}
std::string SystemInfo::GetDeviceVendorName()
{
return "Microsoft"; //TODO
}
std::string SystemInfo::GetDeviceModelName()
{
return "Unknown"; //TODO
}
std::string SystemInfo::GetOsName()
{
return "Windows";
}
OsVersion SystemInfo::GetOsVersion()
{
OSVERSIONINFOA info;
ZeroMemory(&info, sizeof(OSVERSIONINFOA));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&info);
return { (int)info.dwMajorVersion, (int)info.dwMinorVersion, 0, (int)info.dwBuildNumber };
}
std::string SystemInfo::GetOsNameHumanReadable()
{
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
OSVERSIONINFOEXW info;
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
info.dwOSVersionInfoSize = sizeof(info);
RtlGetVersion(&info);
if (info.wProductType == VER_NT_WORKSTATION)
{
if (info.dwMajorVersion == 10)
{
if (info.dwBuildNumber >= 22000)
return "Windows 11";
return "Windows 10";
}
else if (info.dwMajorVersion == 6)
{
switch (info.dwMinorVersion)
{
case 0: return "Windows Vista";
case 1: return "Windows 7";
case 2: return "Windows 8";
case 3: return "Windows 8.1";
}
}
return "Windows " + std::to_string(info.dwMajorVersion) + "." + std::to_string(info.dwMinorVersion);
}
else
{
if (info.dwMajorVersion == 10)
{
switch (info.dwBuildNumber)
{
case 14393:
return "Windows Server 2016";
case 16299:
return "Windows Server 1709";
case 17134:
return "Windows Server 1803";
case 17763:
return "Windows Server 2019";
case 18362:
return "Windows Server 1903";
case 18363:
return "Windows Server 1909";
case 19041:
return "Windows Server 2004";
case 19042:
return "Windows Server 20H2";
case 20348:
return "Windows Server 2022";
case 25398:
return "Windows Server 23H2";
case 26100:
return "Windows Server 2025";
default:
return "Windows Server";
}
}
else if (info.dwMajorVersion == 6)
{
switch (info.dwMinorVersion)
{
case 0: return "Windows Server 2008";
case 1: return "Windows Server 2008 R2";
case 2: return "Windows Server 2012";
case 3: return "Windows Server 2012 R2";
}
}
return "Windows Server " + std::to_string(info.dwMajorVersion) + "." + std::to_string(info.dwMinorVersion);
}
}
DeviceType SystemInfo::GetDeviceType()
{
return DeviceType::PC;
}
size_t SystemInfo::GetCpuCoreCount()
{
SYSTEM_INFO info;
ZeroMemory(&info, sizeof(SYSTEM_INFO));
GetSystemInfo(&info);
return info.dwNumberOfProcessors;
}
size_t SystemInfo::GetCpuThreadCount()
{
return std::thread::hardware_concurrency();
}
int32_t SystemInfo::GetCpuTemperature()
{
return 0; //TODO
}
CpuThermalState SystemInfo::GetCpuThermalState()
{
return CpuThermalState::Normal; // TODO
}
bool SystemInfo::IsDeviceInLowPowerMode()
{
GUID* activePowerMode;
bool res = false;
if(PowerGetActiveScheme(0, &activePowerMode) == 0)
{
res = IsEqualGUID(*activePowerMode, GUID_MIN_POWER_SAVINGS);
}
LocalFree(activePowerMode);
return res;
}
BatteryState SystemInfo::GetDeviceBatteryState()
{
SYSTEM_POWER_STATUS info;
GetSystemPowerStatus(&info);
BYTE batteryFlag = info.BatteryFlag;
if (batteryFlag & BatteryChargeStatus::CHARGING)
{
if (info.BatteryLifePercent == 100)
return BatteryState::ChargingFull;
return BatteryState::Charging;
}
else if (batteryFlag >= BatteryChargeStatus::MEDIUM && batteryFlag <= BatteryChargeStatus::CRITICAL)
{
return BatteryState::Unplugged;
}
// BatteryState::NotCharging is impossible to distinguish
// NO_SYSTEM_BATTERY or UNKNOWN
return BatteryState::Unavailable;
}
float SystemInfo::GetDeviceBatteryLevel()
{
SYSTEM_POWER_STATUS info;
GetSystemPowerStatus(&info);
return info.BatteryLifePercent != 255 ? static_cast<float>(info.BatteryLifePercent) : 0;
}
void SystemInfo::EnableEnergyEvents()
{
//TODO
}
bool SystemInfo::IsMultitaskingSupported()
{
return true;
}
DeviceOrientation SystemInfo::GetDeviceOrientation()
{
DEVMODEA devmode;
ZeroMemory(&devmode, sizeof(devmode));
devmode.dmSize = sizeof(DEVMODE);
if (EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &devmode))
{
DWORD width = devmode.dmPelsWidth;
DWORD height = devmode.dmPelsHeight;
if (width > height)
{
// landscape
return devmode.dmDisplayOrientation == DMDO_180 ? DeviceOrientation::LandscapeLeft :
DeviceOrientation::LandscapeRight;
}
// portrait
return devmode.dmDisplayOrientation == DMDO_180 ? DeviceOrientation::PortraitUpsideDown :
DeviceOrientation::Portrait;
}
return DeviceOrientation::Unknown;
}
void SystemInfo::EnableDeviceOrientationEvents()
{
//TODO
}
InterfaceOrientation SystemInfo::GetInterfaceOrientation()
{
DeviceOrientation devOrient = GetDeviceOrientation();
switch (devOrient)
{
case OpenVulkano::DeviceOrientation::Portrait:
return InterfaceOrientation::Portrait;
case OpenVulkano::DeviceOrientation::PortraitUpsideDown:
return InterfaceOrientation::PortraitUpsideDown;
case OpenVulkano::DeviceOrientation::LandscapeLeft:
return InterfaceOrientation::LandscapeRight;
case OpenVulkano::DeviceOrientation::LandscapeRight:
return InterfaceOrientation::LandscapeLeft;
default:
return InterfaceOrientation::Unknown;
}
}
}