123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- /*
- * mptOS.cpp
- * ---------
- * Purpose: Operating system version information.
- * Notes : (currently none)
- * Authors: OpenMPT Devs
- * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
- */
- #include "stdafx.h"
- #include "mptOS.h"
- #include "mpt/binary/hex.hpp"
- #if MPT_OS_WINDOWS
- #include <windows.h>
- #endif
- OPENMPT_NAMESPACE_BEGIN
- namespace mpt
- {
- namespace OS
- {
- namespace Windows
- {
- #if MPT_OS_WINDOWS
- namespace {
- struct WindowsVersionCache
- {
- mpt::osinfo::windows::Version version;
- WindowsVersionCache() noexcept
- : version(mpt::osinfo::windows::Version::Current())
- {
- }
- };
- }
- static mpt::osinfo::windows::Version GatherWindowsVersionFromCache() noexcept
- {
- static WindowsVersionCache gs_WindowsVersionCache;
- return gs_WindowsVersionCache.version;
- }
- #endif // MPT_OS_WINDOWS
- mpt::osinfo::windows::Version Version::Current() noexcept
- {
- #if MPT_OS_WINDOWS
- #ifdef MODPLUG_TRACKER
- return GatherWindowsVersionFromCache();
- #else // !MODPLUG_TRACKER
- return mpt::osinfo::windows::Version::Current();
- #endif // MODPLUG_TRACKER
- #else // !MPT_OS_WINDOWS
- return mpt::osinfo::windows::Version::NoWindows();
- #endif // MPT_OS_WINDOWS
- }
- static constexpr struct { mpt::osinfo::windows::Version version; const mpt::uchar * name; bool showDetails; } versionMap[] =
- {
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNewer, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11 (or newer)"), false },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19044, 0 }, UL_("Windows 10 21H2"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19043, 0 }, UL_("Windows 10 21H1"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19042, 0 }, UL_("Windows 10 20H2"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19041, 0 }, UL_("Windows 10 2004"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18363, 0 }, UL_("Windows 10 1909"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18362, 0 }, UL_("Windows 10 1903"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17763, 0 }, UL_("Windows 10 1809"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17134, 0 }, UL_("Windows 10 1803"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 16299, 0 }, UL_("Windows 10 1709"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 15063, 0 }, UL_("Windows 10 1703"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 14393, 0 }, UL_("Windows 10 1607"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10586, 0 }, UL_("Windows 10 1511"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10240, 0 }, UL_("Windows 10 1507"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8.1"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win8, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win7, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 7"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinVista, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows Vista"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinXP64, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows XP x64 / Windows Server 2003"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinXP, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows XP"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win2000, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 2000"), true },
- { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNT4, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows NT4"), true }
- };
- mpt::ustring Version::GetName(mpt::osinfo::windows::Version version)
- {
- mpt::ustring name = U_("Generic Windows NT");
- bool showDetails = false;
- for(const auto &v : versionMap)
- {
- if(version.IsAtLeast(v.version))
- {
- name = v.name;
- showDetails = v.showDetails;
- break;
- }
- }
- name += U_(" (");
- name += MPT_UFORMAT("Version {}.{}")(version.GetSystem().Major, version.GetSystem().Minor);
- if(showDetails)
- {
- if(version.GetServicePack().HasServicePack())
- {
- if(version.GetServicePack().Minor)
- {
- name += MPT_UFORMAT(" Service Pack {}.{}")(version.GetServicePack().Major, version.GetServicePack().Minor);
- } else
- {
- name += MPT_UFORMAT(" Service Pack {}")(version.GetServicePack().Major);
- }
- }
- if(version.GetBuild() != 0)
- {
- name += MPT_UFORMAT(" (Build {})")(version.GetBuild());
- }
- }
- name += U_(")");
- mpt::ustring result = name;
- #if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
- if(mpt::OS::Windows::IsWine())
- {
- mpt::OS::Wine::VersionContext v;
- if(v.Version().IsValid())
- {
- result = MPT_UFORMAT("Wine {} ({})")(
- v.Version().AsString()
- , name
- );
- } else
- {
- result = MPT_UFORMAT("Wine (unknown version: '{}') ({})")(
- mpt::ToUnicode(mpt::Charset::UTF8, v.RawVersion())
- , name
- );
- }
- }
- #endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
- return result;
- }
- mpt::osinfo::windows::Version Version::GetMinimumKernelLevel() noexcept
- {
- uint64 minimumKernelVersion = 0;
- #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
- #if defined(MPT_BUILD_RETRO)
- minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinXP));
- #else
- minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinVista));
- #endif
- #endif
- return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::System(minimumKernelVersion), mpt::osinfo::windows::Version::ServicePack(0, 0), 0, 0);
- }
- mpt::osinfo::windows::Version Version::GetMinimumAPILevel() noexcept
- {
- #if MPT_OS_WINDOWS
- return mpt::osinfo::windows::Version::FromSDK();
- #else // !MPT_OS_WINDOWS
- return mpt::osinfo::windows::Version::NoWindows();
- #endif // MPT_OS_WINDOWS
- }
- #if MPT_OS_WINDOWS
- #ifndef PROCESSOR_ARCHITECTURE_NEUTRAL
- #define PROCESSOR_ARCHITECTURE_NEUTRAL 11
- #endif
- #ifndef PROCESSOR_ARCHITECTURE_ARM64
- #define PROCESSOR_ARCHITECTURE_ARM64 12
- #endif
- #ifndef PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64
- #define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
- #endif
- #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_ARM64
- #define PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 14
- #endif
- struct OSArchitecture
- {
- uint16 ProcessorArchitectur;
- Architecture Host;
- Architecture Process;
- };
- static constexpr OSArchitecture architectures [] = {
- { PROCESSOR_ARCHITECTURE_INTEL , Architecture::x86 , Architecture::x86 },
- { PROCESSOR_ARCHITECTURE_AMD64 , Architecture::amd64 , Architecture::amd64 },
- { PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 , Architecture::amd64 , Architecture::x86 },
- { PROCESSOR_ARCHITECTURE_ARM , Architecture::arm , Architecture::arm },
- { PROCESSOR_ARCHITECTURE_ARM64 , Architecture::arm64 , Architecture::arm64 },
- { PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64, Architecture::arm64 , Architecture::arm },
- { PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 , Architecture::arm64 , Architecture::x86 },
- { PROCESSOR_ARCHITECTURE_MIPS , Architecture::mips , Architecture::mips },
- { PROCESSOR_ARCHITECTURE_PPC , Architecture::ppc , Architecture::ppc },
- { PROCESSOR_ARCHITECTURE_SHX , Architecture::shx , Architecture::shx },
- { PROCESSOR_ARCHITECTURE_ALPHA , Architecture::alpha , Architecture::alpha },
- { PROCESSOR_ARCHITECTURE_ALPHA64 , Architecture::alpha64, Architecture::alpha64 },
- { PROCESSOR_ARCHITECTURE_IA64 , Architecture::ia64 , Architecture::ia64 },
- { PROCESSOR_ARCHITECTURE_MSIL , Architecture::unknown, Architecture::unknown },
- { PROCESSOR_ARCHITECTURE_NEUTRAL , Architecture::unknown, Architecture::unknown },
- { PROCESSOR_ARCHITECTURE_UNKNOWN , Architecture::unknown, Architecture::unknown }
- };
- struct HostArchitecture
- {
- Architecture Host;
- Architecture Process;
- EmulationLevel Emulation;
- };
- static constexpr HostArchitecture hostArchitectureCanRun [] = {
- { Architecture::x86 , Architecture::x86 , EmulationLevel::Native },
- { Architecture::amd64 , Architecture::amd64 , EmulationLevel::Native },
- { Architecture::amd64 , Architecture::x86 , EmulationLevel::Virtual },
- { Architecture::arm , Architecture::arm , EmulationLevel::Native },
- { Architecture::arm64 , Architecture::arm64 , EmulationLevel::Native },
- { Architecture::arm64 , Architecture::arm , EmulationLevel::Virtual },
- { Architecture::arm64 , Architecture::x86 , EmulationLevel::Software },
- { Architecture::arm64 , Architecture::amd64 , EmulationLevel::Software },
- { Architecture::mips , Architecture::mips , EmulationLevel::Native },
- { Architecture::ppc , Architecture::ppc , EmulationLevel::Native },
- { Architecture::shx , Architecture::shx , EmulationLevel::Native },
- { Architecture::alpha , Architecture::alpha , EmulationLevel::Native },
- { Architecture::alpha64, Architecture::alpha64, EmulationLevel::Native },
- { Architecture::alpha64, Architecture::alpha , EmulationLevel::Virtual },
- { Architecture::ia64 , Architecture::ia64 , EmulationLevel::Native },
- { Architecture::ia64 , Architecture::x86 , EmulationLevel::Hardware }
- };
- struct ArchitectureInfo
- {
- Architecture Arch;
- int Bitness;
- const mpt::uchar * Name;
- };
- static constexpr ArchitectureInfo architectureInfo [] = {
- { Architecture::x86 , 32, UL_("x86") },
- { Architecture::amd64 , 64, UL_("amd64") },
- { Architecture::arm , 32, UL_("arm") },
- { Architecture::arm64 , 64, UL_("arm64") },
- { Architecture::mips , 32, UL_("mips") },
- { Architecture::ppc , 32, UL_("ppc") },
- { Architecture::shx , 32, UL_("shx") },
- { Architecture::alpha , 32, UL_("alpha") },
- { Architecture::alpha64, 64, UL_("alpha64") },
- { Architecture::ia64 , 64, UL_("ia64") }
- };
- int Bitness(Architecture arch) noexcept
- {
- for(const auto &info : architectureInfo)
- {
- if(arch == info.Arch)
- {
- return info.Bitness;
- }
- }
- return 0;
- }
- mpt::ustring Name(Architecture arch)
- {
- for(const auto &info : architectureInfo)
- {
- if(arch == info.Arch)
- {
- return info.Name;
- }
- }
- return mpt::ustring();
- }
- Architecture GetHostArchitecture() noexcept
- {
- SYSTEM_INFO systemInfo = {};
- GetNativeSystemInfo(&systemInfo);
- for(const auto &arch : architectures)
- {
- if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
- {
- return arch.Host;
- }
- }
- return Architecture::unknown;
- }
- Architecture GetProcessArchitecture() noexcept
- {
- SYSTEM_INFO systemInfo = {};
- GetSystemInfo(&systemInfo);
- for(const auto &arch : architectures)
- {
- if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
- {
- return arch.Process;
- }
- }
- return Architecture::unknown;
- }
- EmulationLevel HostCanRun(Architecture host, Architecture process) noexcept
- {
- for(const auto & can : hostArchitectureCanRun)
- {
- if(can.Host == host && can.Process == process)
- {
- return can.Emulation;
- }
- }
- return EmulationLevel::NA;
- }
- std::vector<Architecture> GetSupportedProcessArchitectures(Architecture host)
- {
- std::vector<Architecture> result;
- for(const auto & entry : hostArchitectureCanRun)
- {
- if(entry.Host == host)
- {
- result.push_back(entry.Process);
- }
- }
- return result;
- }
- uint64 GetSystemMemorySize()
- {
- MEMORYSTATUSEX memoryStatus = {};
- memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
- if(GlobalMemoryStatusEx(&memoryStatus) == 0)
- {
- return 0;
- }
- return memoryStatus.ullTotalPhys;
- }
- #endif // MPT_OS_WINDOWS
- #if defined(MODPLUG_TRACKER)
- #if MPT_OS_WINDOWS
- static bool GatherSystemIsWine()
- {
- bool SystemIsWine = false;
- std::optional<mpt::library> NTDLL = mpt::library::load({ mpt::library::path_search::system, mpt::library::path_prefix::none, MPT_PATH("ntdll.dll"), mpt::library::path_suffix::none });
- if(NTDLL)
- {
- SystemIsWine = (NTDLL->get_address("wine_get_version") != nullptr);
- }
- return SystemIsWine;
- }
- namespace {
- struct SystemIsWineCache
- {
- bool SystemIsWine;
- SystemIsWineCache()
- : SystemIsWine(GatherSystemIsWine())
- {
- return;
- }
- SystemIsWineCache(bool isWine)
- : SystemIsWine(isWine)
- {
- return;
- }
- };
- }
- #endif // MPT_OS_WINDOWS
- static bool SystemIsWine(bool allowDetection = true)
- {
- #if MPT_OS_WINDOWS
- static SystemIsWineCache gs_SystemIsWineCache = allowDetection ? SystemIsWineCache() : SystemIsWineCache(false);
- if(!allowDetection)
- { // catch too late calls of PreventWineDetection
- MPT_ASSERT(!gs_SystemIsWineCache.SystemIsWine);
- }
- return gs_SystemIsWineCache.SystemIsWine;
- #else
- MPT_UNREFERENCED_PARAMETER(allowDetection);
- return false;
- #endif
- }
- void PreventWineDetection()
- {
- SystemIsWine(false);
- }
- bool IsOriginal()
- {
- return mpt::OS::Windows::Version::Current().IsWindows() && !SystemIsWine();
- }
- bool IsWine()
- {
- return mpt::OS::Windows::Version::Current().IsWindows() && SystemIsWine();
- }
- #endif // MODPLUG_TRACKER
- } // namespace Windows
- } // namespace OS
- } // namespace mpt
- namespace mpt
- {
- namespace OS
- {
- namespace Wine
- {
- Version::Version()
- {
- return;
- }
- Version::Version(const mpt::ustring &rawVersion)
- : mpt::osinfo::windows::wine::version()
- {
- if(rawVersion.empty())
- {
- return;
- }
- std::vector<uint8> version = mpt::String::Split<uint8>(rawVersion, U_("."));
- if(version.size() < 2)
- {
- return;
- }
- mpt::ustring parsedVersion = mpt::String::Combine(version, U_("."));
- std::size_t len = std::min(parsedVersion.length(), rawVersion.length());
- if(len == 0)
- {
- return;
- }
- if(parsedVersion.substr(0, len) != rawVersion.substr(0, len))
- {
- return;
- }
- valid = true;
- vmajor = version[0];
- vminor = version[1];
- vupdate = (version.size() >= 3) ? version[2] : 0;
- }
- Version::Version(uint8 vmajor, uint8 vminor, uint8 vupdate)
- : mpt::osinfo::windows::wine::version(vmajor, vminor, vupdate)
- {
- return;
- }
- mpt::ustring Version::AsString() const
- {
- return mpt::ufmt::dec(GetMajor()) + U_(".") + mpt::ufmt::dec(GetMinor()) + U_(".") + mpt::ufmt::dec(GetUpdate());
- }
- mpt::OS::Wine::Version GetMinimumWineVersion()
- {
- mpt::OS::Wine::Version minimumWineVersion = mpt::OS::Wine::Version(0,0,0);
- #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
- minimumWineVersion = mpt::OS::Wine::Version(1,8,0);
- #endif
- return minimumWineVersion;
- }
- VersionContext::VersionContext()
- : m_IsWine(false)
- , m_HostClass(mpt::osinfo::osclass::Unknown)
- {
- #if MPT_OS_WINDOWS
- m_IsWine = mpt::OS::Windows::IsWine();
- if(!m_IsWine)
- {
- return;
- }
- std::optional<mpt::library> NTDLL = mpt::library::load({mpt::library::path_search::system, mpt::library::path_prefix::none, MPT_PATH("ntdll.dll"), mpt::library::path_suffix::none});
- if(NTDLL)
- {
- const char * (__cdecl * wine_get_version)(void) = nullptr;
- const char * (__cdecl * wine_get_build_id)(void) = nullptr;
- void (__cdecl * wine_get_host_version)(const char * *, const char * *) = nullptr;
- NTDLL->bind(wine_get_version, "wine_get_version");
- NTDLL->bind(wine_get_build_id, "wine_get_build_id");
- NTDLL->bind(wine_get_host_version, "wine_get_host_version");
- const char * wine_version = nullptr;
- const char * wine_build_id = nullptr;
- const char * wine_host_sysname = nullptr;
- const char * wine_host_release = nullptr;
- wine_version = wine_get_version ? wine_get_version() : "";
- wine_build_id = wine_get_build_id ? wine_get_build_id() : "";
- if(wine_get_host_version)
- {
- wine_get_host_version(&wine_host_sysname, &wine_host_release);
- }
- m_RawVersion = wine_version ? wine_version : "";
- m_RawBuildID = wine_build_id ? wine_build_id : "";
- m_RawHostSysName = wine_host_sysname ? wine_host_sysname : "";
- m_RawHostRelease = wine_host_release ? wine_host_release : "";
- }
- m_Version = mpt::OS::Wine::Version(mpt::ToUnicode(mpt::Charset::UTF8, m_RawVersion));
- m_HostClass = mpt::osinfo::get_class_from_sysname(m_RawHostSysName);
- #endif // MPT_OS_WINDOWS
- }
- } // namespace Wine
- } // namespace OS
- } // namespace mpt
- OPENMPT_NAMESPACE_END
|