diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp')
-rw-r--r-- | Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp | 551 |
1 files changed, 551 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp b/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp new file mode 100644 index 00000000..b86d768a --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/misc/mptOS.cpp @@ -0,0 +1,551 @@ +/* + * 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 |