diff --git a/Common/OSVersion.cpp b/Common/OSVersion.cpp index ee35ef7c4e..973dc4ce5d 100644 --- a/Common/OSVersion.cpp +++ b/Common/OSVersion.cpp @@ -93,7 +93,7 @@ bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, u #endif } -bool DoesVersionMatchWindows(WindowsReleaseInfo release) { +bool DoesVersionMatchWindows(WindowsReleaseInfo release, uint64_t version, uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild) { if (release.spMajor == 0 && release.spMinor == 0) { // Compare Info uint32_t major = release.major; @@ -101,25 +101,29 @@ bool DoesVersionMatchWindows(WindowsReleaseInfo release) { uint32_t build = release.build; bool greater = release.greater; - OSVERSIONINFOEX osvi; - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - GetVersionEx((LPOSVERSIONINFO)&osvi); + // System Info + uint32_t osMajor = 0, osMinor = 0, osBuild = 0, osRevision = 0; - // OS Info - uint32_t osMajor = osvi.dwMajorVersion; - uint32_t osMinor = osvi.dwMinorVersion; - uint32_t osBuild = osvi.dwBuildNumber; - -#if !PPSSPP_PLATFORM(UWP) - // "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); -#endif + if (version > 0) { + // Extract the major, minor, build, and revision numbers + // UWP take this path + osMajor = static_cast((version & 0xFFFF000000000000L) >> 48); + osMinor = static_cast((version & 0x0000FFFF00000000L) >> 32); + osBuild = static_cast((version & 0x00000000FFFF0000L) >> 16); + osRevision = static_cast((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); + } if (major == osMajor) { // To detect Windows 11 we must check build number if (osMinor >= minor && osBuild >= build) { + outMajor = osMajor; + outMinor = osMinor; + outBuild = osBuild; return true; } } @@ -142,6 +146,20 @@ bool IsWin7OrHigher() { } std::string GetWindowsVersion() { + 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) { std::vector> windowsReleases = { /* { "Preview text", { major, minor, spMajor, spMinor, build, greater } }, */ { "Microsoft Windows XP, Service Pack 2", { 5, 1, 2, 0 } }, @@ -160,7 +178,7 @@ std::string GetWindowsVersion() { // Start from higher to lower for (auto release = rbegin(windowsReleases); release != rend(windowsReleases); ++release) { WindowsReleaseInfo releaseInfo = release->second; - bool buildMatch = DoesVersionMatchWindows(releaseInfo); + bool buildMatch = DoesVersionMatchWindows(releaseInfo, versionInfo, outMajor, outMinor, outBuild); if (buildMatch) { std::string previewText = release->first; return previewText; diff --git a/Common/OSVersion.h b/Common/OSVersion.h index 262cba05ac..9701d23295 100644 --- a/Common/OSVersion.h +++ b/Common/OSVersion.h @@ -7,7 +7,16 @@ bool IsVistaOrHigher(); bool IsWin7OrHigher(); bool DoesVersionMatchWindows(uint32_t major, uint32_t minor, uint32_t spMajor, uint32_t spMinor, bool acceptGreater); + std::string GetWindowsVersion(); + +// Platforms like UWP has their own API, +// so we use versionInfo to pass version info from outside +// on Win32 it will use kernel (normal behavior) when versionInfo is 0 +std::string GetWindowsVersion(uint64_t versionInfo); +std::string GetWindowsVersion(uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild); +std::string GetWindowsVersion(uint64_t versionInfo, uint32_t& outMajor, uint32_t& outMinor, uint32_t& outBuild); + std::string GetWindowsSystemArchitecture(); #endif diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 56cda92067..afd1850fa8 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -489,6 +489,11 @@ void SystemInfoScreen::CreateTabs() { systemInfo->Add(new InfoItem(si->T("System Name", "Name"), System_GetProperty(SYSPROP_NAME))); #if PPSSPP_PLATFORM(ANDROID) systemInfo->Add(new InfoItem(si->T("System Version"), StringFromInt(System_GetPropertyInt(SYSPROP_SYSTEMVERSION)))); +#elif PPSSPP_PLATFORM(WINDOWS) + std::string sysVersion = System_GetProperty(SYSPROP_SYSTEMVERSION); + if (!sysVersion.empty()) { + systemInfo->Add(new InfoItem(si->T("OS Build"), sysVersion)); + } #endif systemInfo->Add(new InfoItem(si->T("Lang/Region"), System_GetProperty(SYSPROP_LANGREGION))); std::string board = System_GetProperty(SYSPROP_BOARDNAME); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 719d342821..648044d724 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -314,7 +314,21 @@ std::string System_GetProperty(SystemProperty prop) { static bool hasCheckedGPUDriverVersion = false; switch (prop) { case SYSPROP_NAME: - return GetWindowsVersion(); + { + uint64_t versionInfo = GetWindowsVersionInfo(); + std::string osName; + if (IsXBox()) { + osName = "Xbox OS"; + } + else { + osName = GetWindowsVersion(versionInfo); + } + + osName += " " + GetWindowsSystemArchitecture(); + return osName; + } + case SYSPROP_SYSTEMVERSION: + return GetWindowsVersionInfoPreview(); case SYSPROP_LANGREGION: return GetLangRegion(); case SYSPROP_CLIPBOARD_TEXT: diff --git a/UWP/UWPHelpers/InputHelpers.cpp b/UWP/UWPHelpers/InputHelpers.cpp index 485998a044..2b9858b2c9 100644 --- a/UWP/UWPHelpers/InputHelpers.cpp +++ b/UWP/UWPHelpers/InputHelpers.cpp @@ -238,4 +238,26 @@ bool IsMobile() { auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo; return deviceInfo->DeviceFamily == "Windows.Mobile"; } + +uint64_t GetWindowsVersionInfo() { + Platform::String^ deviceFamilyVersion = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamilyVersion; + return std::stoull(deviceFamilyVersion->Data()); +} + +void ParseVersionInfo(uint64_t version, uint32_t& major, uint32_t& minor, uint32_t& build, uint32_t& revision) { + major = static_cast((version & 0xFFFF000000000000L) >> 48); + minor = static_cast((version & 0x0000FFFF00000000L) >> 32); + build = static_cast((version & 0x00000000FFFF0000L) >> 16); + revision = static_cast(version & 0x000000000000FFFFL); +} + +std::string GetWindowsVersionInfoPreview() { + uint64_t version = GetWindowsVersionInfo(); + uint32_t major = 0, minor = 0, build = 0, revision = 0; + ParseVersionInfo(version, major, minor, build, revision); + + char buffer[50]; + sprintf_s(buffer, sizeof(buffer), "%u.%u.%u", major, minor, build); + return std::string(buffer); +} #pragma endregion diff --git a/UWP/UWPHelpers/InputHelpers.h b/UWP/UWPHelpers/InputHelpers.h index d5656e81fc..76f362dd79 100644 --- a/UWP/UWPHelpers/InputHelpers.h +++ b/UWP/UWPHelpers/InputHelpers.h @@ -47,3 +47,10 @@ bool IsCtrlOnHold(); std::string GetLangRegion(); bool IsXBox(); bool IsMobile(); + +// Get windows version info +uint64_t GetWindowsVersionInfo(); +// Parse data from GetWindowsVersionInfo to major, minor, build, revision +void ParseVersionInfo(uint64_t version, uint32_t& major, uint32_t& minor, uint32_t& build, uint32_t& revision); +// Get formatted windows version as string (for preview) +std::string GetWindowsVersionInfoPreview(); diff --git a/Windows/main.cpp b/Windows/main.cpp index bd763a0908..6d78b18114 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -106,6 +106,7 @@ CVFPUDlg *vfpudlg = nullptr; static std::string langRegion; static std::string osName; +static std::string osVersion; static std::string gpuDriverVersion; static std::string restartArgs; @@ -203,6 +204,8 @@ std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: return osName; + case SYSPROP_SYSTEMVERSION: + return osVersion; case SYSPROP_LANGREGION: return langRegion; case SYSPROP_CLIPBOARD_TEXT: @@ -903,7 +906,15 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin g_VFS.Register("", new DirectoryReader(exePath)); langRegion = GetDefaultLangRegion(); - osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); + + uint32_t outMajor = 0, outMinor = 0, outBuild = 0; + osName = GetWindowsVersion(outMajor, outMinor, outBuild) + " " + GetWindowsSystemArchitecture(); + if (outMajor > 0) { + // Builds with (service pack) don't show OS Version for now + char buffer[50]; + sprintf_s(buffer, sizeof(buffer), "%u.%u.%u", outMajor, outMinor, outBuild); + osVersion = std::string(buffer); + } std::string configFilename = ""; const std::wstring configOption = L"--config=";