2017-02-24 17:59:41 +00:00
|
|
|
#include "ppsspp_config.h"
|
2017-02-14 09:33:42 +00:00
|
|
|
|
2018-03-23 02:18:13 +00:00
|
|
|
#ifdef _WIN32
|
2017-02-14 09:33:42 +00:00
|
|
|
|
2018-09-30 07:00:40 +00:00
|
|
|
#if !PPSSPP_PLATFORM(UWP)
|
|
|
|
#pragma comment(lib, "version.lib")
|
|
|
|
#endif
|
|
|
|
|
2017-02-14 09:33:42 +00:00
|
|
|
#include <cstdint>
|
2018-10-30 22:57:54 +00:00
|
|
|
#include <vector>
|
2017-02-14 09:33:42 +00:00
|
|
|
#include "OSVersion.h"
|
|
|
|
#include "Common/CommonWindows.h"
|
|
|
|
|
2023-08-15 19:17:13 +00:00
|
|
|
struct WindowsReleaseInfo
|
|
|
|
{
|
2023-08-17 14:45:58 +00:00
|
|
|
uint32_t major;
|
|
|
|
uint32_t minor;
|
|
|
|
uint32_t spMajor;
|
|
|
|
uint32_t spMinor;
|
|
|
|
uint32_t build;
|
2023-08-15 19:17:13 +00:00
|
|
|
bool greater = false;
|
|
|
|
};
|
|
|
|
|
2018-09-30 07:00:40 +00:00
|
|
|
bool GetVersionFromKernel32(uint32_t &major, uint32_t &minor, uint32_t &build) {
|
|
|
|
#if PPSSPP_PLATFORM(UWP)
|
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
DWORD handle = 0;
|
|
|
|
DWORD verSize = GetFileVersionInfoSizeA("kernel32.dll", &handle);
|
|
|
|
if (verSize == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
std::vector<char> verData(verSize);
|
|
|
|
if (GetFileVersionInfoW(L"kernel32.dll", 0, verSize, &verData[0]) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
VS_FIXEDFILEINFO *buf = nullptr;
|
|
|
|
uint32_t sz = 0;
|
|
|
|
if (VerQueryValueW(&verData[0], L"\\", (void **)&buf, &sz) == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
major = buf->dwProductVersionMS >> 16;
|
|
|
|
minor = buf->dwProductVersionMS & 0xFFFF;
|
|
|
|
build = buf->dwProductVersionLS >> 16;
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-02-23 09:40:55 +00:00
|
|
|
bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool greater) {
|
2023-08-15 19:17:13 +00:00
|
|
|
#if !PPSSPP_PLATFORM(UWP)
|
2023-08-15 19:42:37 +00:00
|
|
|
if (spMajor == 0 && spMinor == 0) {
|
|
|
|
// "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)."
|
|
|
|
// Try to use kernel32.dll instead, for Windows 10+. Doesn't do SP versions.
|
|
|
|
uint32_t actualMajor, actualMinor, actualBuild;
|
|
|
|
if (GetVersionFromKernel32(actualMajor, actualMinor, actualBuild)) {
|
|
|
|
if (greater)
|
|
|
|
return actualMajor > major || (major == actualMajor && actualMinor >= minor);
|
|
|
|
return major == actualMajor && minor == actualMinor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-14 09:33:42 +00:00
|
|
|
uint64_t conditionMask = 0;
|
|
|
|
OSVERSIONINFOEX osvi;
|
|
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
|
|
|
|
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
|
|
osvi.dwMajorVersion = major;
|
|
|
|
osvi.dwMinorVersion = minor;
|
|
|
|
osvi.wServicePackMajor = spMajor;
|
|
|
|
osvi.wServicePackMinor = spMinor;
|
2017-02-23 09:40:55 +00:00
|
|
|
uint32_t op = greater ? VER_GREATER_EQUAL : VER_EQUAL;
|
2017-02-14 09:33:42 +00:00
|
|
|
|
|
|
|
VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, op);
|
|
|
|
VER_SET_CONDITION(conditionMask, VER_MINORVERSION, op);
|
2023-08-15 19:17:13 +00:00
|
|
|
uint32_t typeMask = VER_MAJORVERSION | VER_MINORVERSION;
|
2017-02-14 09:33:42 +00:00
|
|
|
|
2023-08-15 19:17:13 +00:00
|
|
|
if (spMajor > 0) {
|
|
|
|
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMAJOR, op);
|
|
|
|
typeMask |= VER_SERVICEPACKMAJOR;
|
|
|
|
}
|
|
|
|
if (spMinor > 0) {
|
|
|
|
VER_SET_CONDITION(conditionMask, VER_SERVICEPACKMINOR, op);
|
|
|
|
typeMask |= VER_SERVICEPACKMINOR;
|
|
|
|
}
|
2017-02-14 09:33:42 +00:00
|
|
|
|
|
|
|
return VerifyVersionInfo(&osvi, typeMask, conditionMask) != FALSE;
|
2023-08-15 19:17:13 +00:00
|
|
|
|
|
|
|
#else
|
2023-08-15 19:42:37 +00:00
|
|
|
if (greater) {
|
|
|
|
return true;
|
|
|
|
}
|
2023-08-15 19:17:13 +00:00
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-09-03 11:58:35 +00:00
|
|
|
bool DoesVersionMatchWindows(WindowsReleaseInfo release, uint64_t version, uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild) {
|
2023-08-15 19:17:13 +00:00
|
|
|
if (release.spMajor == 0 && release.spMinor == 0) {
|
|
|
|
// Compare Info
|
2023-08-17 14:45:58 +00:00
|
|
|
uint32_t major = release.major;
|
|
|
|
uint32_t minor = release.minor;
|
|
|
|
uint32_t build = release.build;
|
2023-08-15 19:17:13 +00:00
|
|
|
bool greater = release.greater;
|
|
|
|
|
2024-09-03 11:58:35 +00:00
|
|
|
// System Info
|
|
|
|
uint32_t osMajor = 0, osMinor = 0, osBuild = 0, osRevision = 0;
|
2023-08-15 19:17:13 +00:00
|
|
|
|
2024-09-03 11:58:35 +00:00
|
|
|
if (version > 0) {
|
|
|
|
// Extract the major, minor, build, and revision numbers
|
|
|
|
// UWP take this path
|
|
|
|
osMajor = static_cast<uint32_t>((version & 0xFFFF000000000000L) >> 48);
|
|
|
|
osMinor = static_cast<uint32_t>((version & 0x0000FFFF00000000L) >> 32);
|
|
|
|
osBuild = static_cast<uint32_t>((version & 0x00000000FFFF0000L) >> 16);
|
|
|
|
osRevision = static_cast<uint32_t>((version & 0x000000000000FFFFL));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// "Applications not manifested for Windows 10 will return the Windows 8 OS version value (6.2)."
|
|
|
|
// Try to use kernel32.dll instead, for Windows 10+.
|
|
|
|
GetVersionFromKernel32(osMajor, osMinor, osBuild);
|
|
|
|
}
|
2023-08-15 19:17:13 +00:00
|
|
|
|
|
|
|
if (major == osMajor) {
|
|
|
|
// To detect Windows 11 we must check build number
|
|
|
|
if (osMinor >= minor && osBuild >= build) {
|
2024-09-03 11:58:35 +00:00
|
|
|
outMajor = osMajor;
|
|
|
|
outMinor = osMinor;
|
|
|
|
outBuild = osBuild;
|
2023-08-15 19:17:13 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-17 14:45:58 +00:00
|
|
|
else {
|
|
|
|
return DoesVersionMatchWindows(release.major, release.minor, release.spMajor, release.spMinor, release.greater);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2017-02-14 09:33:42 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 19:50:27 +00:00
|
|
|
bool IsVistaOrHigher() {
|
2023-08-15 19:17:13 +00:00
|
|
|
// Vista is 6.0
|
|
|
|
return DoesVersionMatchWindows(6, 0, 0, 0, true);
|
2020-01-14 09:15:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsWin7OrHigher() {
|
2023-08-15 19:17:13 +00:00
|
|
|
// Win7 is 6.1
|
2023-08-15 22:35:54 +00:00
|
|
|
return DoesVersionMatchWindows(6, 1, 0, 0, true);
|
2017-02-24 19:50:27 +00:00
|
|
|
}
|
|
|
|
|
2017-02-14 09:33:42 +00:00
|
|
|
std::string GetWindowsVersion() {
|
2024-09-03 11:58:35 +00:00
|
|
|
uint32_t outMajor = 0, outMinor = 0, outBuild = 0; // Dummy
|
|
|
|
return GetWindowsVersion(0, outMajor, outMinor, outBuild);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetWindowsVersion(uint64_t versionInfo) {
|
|
|
|
uint32_t outMajor = 0, outMinor = 0, outBuild = 0; // Dummy
|
|
|
|
return GetWindowsVersion(versionInfo, outMajor, outMinor, outBuild);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetWindowsVersion(uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild) {
|
|
|
|
return GetWindowsVersion(0, outMajor, outMinor, outBuild);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetWindowsVersion(uint64_t versionInfo, uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild) {
|
2023-08-15 19:17:13 +00:00
|
|
|
std::vector<std::pair<std::string, WindowsReleaseInfo>> windowsReleases = {
|
|
|
|
/* { "Preview text", { major, minor, spMajor, spMinor, build, greater } }, */
|
|
|
|
{ "Microsoft Windows XP, Service Pack 2", { 5, 1, 2, 0 } },
|
|
|
|
{ "Microsoft Windows XP, Service Pack 3", { 5, 1, 3, 0 } },
|
|
|
|
{ "Microsoft Windows Vista", { 6, 0, 0, 0 } },
|
|
|
|
{ "Microsoft Windows Vista, Service Pack 1", { 6, 0, 1, 0 } },
|
|
|
|
{ "Microsoft Windows Vista, Service Pack 2", { 6, 0, 2, 0 } },
|
|
|
|
{ "Microsoft Windows 7", { 6, 1, 0, 0 } },
|
|
|
|
{ "Microsoft Windows 7, Service Pack 1", { 6, 1, 1, 0 } },
|
|
|
|
{ "Microsoft Windows 8", { 6, 2, 0, 0 } },
|
|
|
|
{ "Microsoft Windows 8.1", { 6, 3, 0, 0 } },
|
|
|
|
{ "Microsoft Windows 10", { 10, 0, 0, 0 } },
|
|
|
|
{ "Microsoft Windows 11", { 10, 0, 0, 0, 22000 } },
|
|
|
|
};
|
|
|
|
|
|
|
|
// Start from higher to lower
|
|
|
|
for (auto release = rbegin(windowsReleases); release != rend(windowsReleases); ++release) {
|
|
|
|
WindowsReleaseInfo releaseInfo = release->second;
|
2024-09-03 11:58:35 +00:00
|
|
|
bool buildMatch = DoesVersionMatchWindows(releaseInfo, versionInfo, outMajor, outMinor, outBuild);
|
2023-08-15 19:17:13 +00:00
|
|
|
if (buildMatch) {
|
2023-12-20 09:33:56 +00:00
|
|
|
std::string previewText = release->first;
|
2023-08-15 19:17:13 +00:00
|
|
|
return previewText;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Unknown version of Microsoft Windows.";
|
2017-02-14 09:33:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string GetWindowsSystemArchitecture() {
|
|
|
|
SYSTEM_INFO sysinfo;
|
|
|
|
ZeroMemory(&sysinfo, sizeof(SYSTEM_INFO));
|
|
|
|
GetNativeSystemInfo(&sysinfo);
|
|
|
|
|
2019-05-03 21:40:27 +00:00
|
|
|
switch (sysinfo.wProcessorArchitecture) {
|
|
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
2017-02-14 09:33:42 +00:00
|
|
|
return "(x86)";
|
2019-05-03 21:40:27 +00:00
|
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|
|
|
return "(x64)";
|
|
|
|
case PROCESSOR_ARCHITECTURE_ARM:
|
2017-02-14 09:33:42 +00:00
|
|
|
return "(ARM)";
|
2019-05-14 02:39:14 +00:00
|
|
|
#ifdef PROCESSOR_ARCHITECTURE_ARM64
|
2019-05-03 21:40:27 +00:00
|
|
|
case PROCESSOR_ARCHITECTURE_ARM64:
|
|
|
|
return "(ARM64)";
|
2019-05-14 02:39:14 +00:00
|
|
|
#endif
|
2019-05-03 21:40:27 +00:00
|
|
|
default:
|
2017-02-14 09:33:42 +00:00
|
|
|
return "(Unknown)";
|
2019-05-03 21:40:27 +00:00
|
|
|
}
|
2017-02-14 09:33:42 +00:00
|
|
|
}
|
|
|
|
|
2018-03-23 02:18:13 +00:00
|
|
|
#endif
|