using System;
using System.Globalization;
using System.Management;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Ryujinx.Common.Logging;
namespace Ryujinx.Common.SystemInfo
{
[SupportedOSPlatform("windows")]
class WindowsSystemInfo : SystemInfo
internal WindowsSystemInfo()
CpuName = $"{GetCpuidCpuName() ?? GetCpuNameWMI()} ; {LogicalCoreCount} logical"; // WMI is very slow
(RamTotal, RamAvailable) = GetMemoryStats();
}
private static (ulong Total, ulong Available) GetMemoryStats()
MemoryStatusEx memStatus = new MemoryStatusEx();
if (GlobalMemoryStatusEx(memStatus))
return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes
else
Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}");
return (0, 0);
private static string GetCpuNameWMI()
ManagementObjectCollection cpuObjs = GetWMIObjects("root\\CIMV2", "SELECT * FROM Win32_Processor");
if (cpuObjs != null)
foreach (var cpuObj in cpuObjs)
return cpuObj["Name"].ToString().Trim();
return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim();
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private class MemoryStatusEx
public uint Length;
public uint MemoryLoad;
public ulong TotalPhys;
public ulong AvailPhys;
public ulong TotalPageFile;
public ulong AvailPageFile;
public ulong TotalVirtual;
public ulong AvailVirtual;
public ulong AvailExtendedVirtual;
public MemoryStatusEx()
Length = (uint)Marshal.SizeOf(typeof(MemoryStatusEx));
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GlobalMemoryStatusEx([In, Out] MemoryStatusEx lpBuffer);
private static ManagementObjectCollection GetWMIObjects(string scope, string query)
try
return new ManagementObjectSearcher(scope, query).Get();
catch (PlatformNotSupportedException ex)
Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
catch (COMException ex)
return null;