cog/Frameworks/OpenMPT.old/OpenMPT/common/mptOS.cpp

958 lines
22 KiB
C++

/*
* 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"
#if MPT_OS_WINDOWS
#include <windows.h>
#endif
#if defined(MODPLUG_TRACKER)
#if !MPT_OS_WINDOWS
#include <sys/utsname.h>
#endif // !MPT_OS_WINDOWS
#endif // MODPLUG_TRACKER
OPENMPT_NAMESPACE_BEGIN
#if defined(MODPLUG_TRACKER)
namespace mpt
{
namespace OS
{
mpt::OS::Class GetClassFromSysname(mpt::ustring sysname)
{
mpt::OS::Class result = mpt::OS::Class::Unknown;
if(sysname == U_(""))
{
result = mpt::OS::Class::Unknown;
} else if(sysname == U_("Windows") || sysname == U_("WindowsNT") || sysname == U_("Windows_NT"))
{
result = mpt::OS::Class::Windows;
} else if(sysname == U_("Linux"))
{
result = mpt::OS::Class::Linux;
} else if(sysname == U_("Darwin"))
{
result = mpt::OS::Class::Darwin;
} else if(sysname == U_("FreeBSD") || sysname == U_("DragonFly") || sysname == U_("NetBSD") || sysname == U_("OpenBSD") || sysname == U_("MidnightBSD"))
{
result = mpt::OS::Class::BSD;
} else if(sysname == U_("Haiku"))
{
result = mpt::OS::Class::Haiku;
} else if(sysname == U_("MS-DOS"))
{
result = mpt::OS::Class::DOS;
}
return result;
}
mpt::OS::Class GetClass()
{
#if MPT_OS_WINDOWS
return mpt::OS::Class::Windows;
#else // !MPT_OS_WINDOWS
utsname uname_result;
if(uname(&uname_result) != 0)
{
return mpt::OS::Class::Unknown;
}
return mpt::OS::GetClassFromSysname(mpt::ToUnicode(mpt::Charset::ASCII, mpt::String::ReadAutoBuf(uname_result.sysname)));
#endif // MPT_OS_WINDOWS
}
} // namespace OS
} // namespace mpt
#endif // MODPLUG_TRACKER
namespace mpt
{
namespace Windows
{
#if MPT_OS_WINDOWS
static mpt::Windows::Version VersionFromNTDDI_VERSION() noexcept
{
// Initialize to used SDK version
mpt::Windows::Version::System System =
#if NTDDI_VERSION >= 0x0A000000 // NTDDI_WIN10
mpt::Windows::Version::Win10
#elif NTDDI_VERSION >= 0x06030000 // NTDDI_WINBLUE
mpt::Windows::Version::Win81
#elif NTDDI_VERSION >= 0x06020000 // NTDDI_WIN8
mpt::Windows::Version::Win8
#elif NTDDI_VERSION >= 0x06010000 // NTDDI_WIN7
mpt::Windows::Version::Win7
#elif NTDDI_VERSION >= 0x06000000 // NTDDI_VISTA
mpt::Windows::Version::WinVista
#elif NTDDI_VERSION >= 0x05020000 // NTDDI_WS03
mpt::Windows::Version::WinXP64
#elif NTDDI_VERSION >= NTDDI_WINXP
mpt::Windows::Version::WinXP
#elif NTDDI_VERSION >= NTDDI_WIN2K
mpt::Windows::Version::Win2000
#else
mpt::Windows::Version::WinNT4
#endif
;
return mpt::Windows::Version(System, mpt::Windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0);
}
static mpt::Windows::Version::System SystemVersionFrom_WIN32_WINNT() noexcept
{
#if defined(_WIN32_WINNT)
return mpt::Windows::Version::System((static_cast<uint64>(_WIN32_WINNT) & 0xff00u) >> 8, (static_cast<uint64>(_WIN32_WINNT) & 0x00ffu) >> 0);
#else
return mpt::Windows::Version::System();
#endif
}
static mpt::Windows::Version GatherWindowsVersion() noexcept
{
#if MPT_OS_WINDOWS_WINRT
return VersionFromNTDDI_VERSION();
#else // !MPT_OS_WINDOWS_WINRT
OSVERSIONINFOEXW versioninfoex;
MemsetZero(versioninfoex);
versioninfoex.dwOSVersionInfoSize = sizeof(versioninfoex);
#if MPT_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable:4996) // 'GetVersionExW': was declared deprecated
#pragma warning(disable:28159) // Consider using 'IsWindows*' instead of 'GetVersionExW'. Reason: Deprecated. Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers.
#endif // MPT_COMPILER_MSVC
#if MPT_COMPILER_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#endif // MPT_COMPILER_CLANG
if(GetVersionExW((LPOSVERSIONINFOW)&versioninfoex) == FALSE)
{
return VersionFromNTDDI_VERSION();
}
#if MPT_COMPILER_MSVC
#pragma warning(pop)
#endif // MPT_COMPILER_MSVC
#if MPT_COMPILER_CLANG
#pragma clang diagnostic pop
#endif // MPT_COMPILER_CLANG
if(versioninfoex.dwPlatformId != VER_PLATFORM_WIN32_NT)
{
return VersionFromNTDDI_VERSION();
}
DWORD dwProductType = 0;
dwProductType = PRODUCT_UNDEFINED;
if(GetProductInfo(versioninfoex.dwMajorVersion, versioninfoex.dwMinorVersion, versioninfoex.wServicePackMajor, versioninfoex.wServicePackMinor, &dwProductType) == FALSE)
{
dwProductType = PRODUCT_UNDEFINED;
}
return mpt::Windows::Version(
mpt::Windows::Version::System(versioninfoex.dwMajorVersion, versioninfoex.dwMinorVersion),
mpt::Windows::Version::ServicePack(versioninfoex.wServicePackMajor, versioninfoex.wServicePackMinor),
versioninfoex.dwBuildNumber,
dwProductType
);
#endif // MPT_OS_WINDOWS_WINRT
}
#ifdef MODPLUG_TRACKER
namespace {
struct WindowsVersionCache
{
mpt::Windows::Version version;
WindowsVersionCache() noexcept
: version(GatherWindowsVersion())
{
}
};
}
static mpt::Windows::Version GatherWindowsVersionFromCache() noexcept
{
static WindowsVersionCache gs_WindowsVersionCache;
return gs_WindowsVersionCache.version;
}
#endif // MODPLUG_TRACKER
#endif // MPT_OS_WINDOWS
Version::Version() noexcept
: m_SystemIsWindows(false)
, m_System()
, m_ServicePack()
, m_Build()
, m_Type()
{
}
Version Version::NoWindows() noexcept
{
return Version();
}
Version::Version(mpt::Windows::Version::System system, mpt::Windows::Version::ServicePack servicePack, mpt::Windows::Version::Build build, mpt::Windows::Version::TypeId type) noexcept
: m_SystemIsWindows(true)
, m_System(system)
, m_ServicePack(servicePack)
, m_Build(build)
, m_Type(type)
{
}
mpt::Windows::Version Version::Current() noexcept
{
#if MPT_OS_WINDOWS
#ifdef MODPLUG_TRACKER
return GatherWindowsVersionFromCache();
#else // !MODPLUG_TRACKER
return GatherWindowsVersion();
#endif // MODPLUG_TRACKER
#else // !MPT_OS_WINDOWS
return mpt::Windows::Version::NoWindows();
#endif // MPT_OS_WINDOWS
}
bool Version::IsWindows() const noexcept
{
return m_SystemIsWindows;
}
bool Version::IsBefore(mpt::Windows::Version::System version) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
return m_System < version;
}
bool Version::IsBefore(mpt::Windows::Version::System version, mpt::Windows::Version::ServicePack servicePack) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
if(m_System > version)
{
return false;
}
if(m_System < version)
{
return true;
}
return m_ServicePack < servicePack;
}
bool Version::IsBefore(mpt::Windows::Version::System version, mpt::Windows::Version::Build build) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
if(m_System > version)
{
return false;
}
if(m_System < version)
{
return true;
}
return m_Build < build;
}
bool Version::IsAtLeast(mpt::Windows::Version::System version) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
return m_System >= version;
}
bool Version::IsAtLeast(mpt::Windows::Version::System version, mpt::Windows::Version::ServicePack servicePack) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
if(m_System < version)
{
return false;
}
if(m_System > version)
{
return true;
}
return m_ServicePack >= servicePack;
}
bool Version::IsAtLeast(mpt::Windows::Version::System version, mpt::Windows::Version::Build build) const noexcept
{
if(!m_SystemIsWindows)
{
return false;
}
if(m_System < version)
{
return false;
}
if(m_System > version)
{
return true;
}
return m_Build >= build;
}
mpt::Windows::Version::System Version::GetSystem() const noexcept
{
return m_System;
}
mpt::Windows::Version::ServicePack Version::GetServicePack() const noexcept
{
return m_ServicePack;
}
mpt::Windows::Version::Build Version::GetBuild() const noexcept
{
return m_Build;
}
mpt::Windows::Version::TypeId Version::GetTypeId() const noexcept
{
return m_Type;
}
static constexpr struct { Version::System version; const mpt::uchar * name; bool showDetails; } versionMap[] =
{
{ mpt::Windows::Version::WinNewer, UL_("Windows 10 (or newer)"), false },
{ mpt::Windows::Version::Win10, UL_("Windows 10"), true },
{ mpt::Windows::Version::Win81, UL_("Windows 8.1"), true },
{ mpt::Windows::Version::Win8, UL_("Windows 8"), true },
{ mpt::Windows::Version::Win7, UL_("Windows 7"), true },
{ mpt::Windows::Version::WinVista, UL_("Windows Vista"), true },
{ mpt::Windows::Version::WinXP64, UL_("Windows XP x64 / Windows Server 2003"), true },
{ mpt::Windows::Version::WinXP, UL_("Windows XP"), true },
{ mpt::Windows::Version::Win2000, UL_("Windows 2000"), true },
{ mpt::Windows::Version::WinNT4, UL_("Windows NT4"), true }
};
mpt::ustring Version::VersionToString(mpt::Windows::Version::System version)
{
mpt::ustring result;
for(const auto &v : versionMap)
{
if(version > v.version)
{
result = U_("> ") + v.name;
break;
} else if(version == v.version)
{
result = v.name;
break;
}
}
if(result.empty())
{
result = mpt::format(U_("0x%1"))(mpt::ufmt::hex0<16>(static_cast<uint64>(version)));
}
return result;
}
mpt::ustring Version::GetName() const
{
mpt::ustring name = U_("Generic Windows NT");
bool showDetails = false;
for(const auto &v : versionMap)
{
if(IsAtLeast(v.version))
{
name = v.name;
showDetails = v.showDetails;
break;
}
}
name += U_(" (");
name += mpt::format(U_("Version %1.%2"))(m_System.Major, m_System.Minor);
if(showDetails)
{
if(m_ServicePack.HasServicePack())
{
if(m_ServicePack.Minor)
{
name += mpt::format(U_(" Service Pack %1.%2"))(m_ServicePack.Major, m_ServicePack.Minor);
} else
{
name += mpt::format(U_(" Service Pack %1"))(m_ServicePack.Major);
}
}
if(m_Build != 0)
{
name += mpt::format(U_(" (Build %1)"))(m_Build);
}
}
name += U_(")");
mpt::ustring result = name;
#if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
if(mpt::Windows::IsWine())
{
mpt::Wine::VersionContext v;
if(v.Version().IsValid())
{
result = mpt::format(U_("Wine %1 (%2)"))(
v.Version().AsString()
, name
);
} else
{
result = mpt::format(U_("Wine (unknown version: '%1') (%2)"))(
mpt::ToUnicode(mpt::Charset::UTF8, v.RawVersion())
, name
);
}
}
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
return result;
}
#ifdef MODPLUG_TRACKER
mpt::ustring Version::GetNameShort() const
{
mpt::ustring name;
if(mpt::Windows::IsWine())
{
mpt::Wine::VersionContext v;
if(v.Version().IsValid())
{
name = mpt::format(U_("wine-%1"))(v.Version().AsString());
} else if(v.RawVersion().length() > 0)
{
name = U_("wine-") + Util::BinToHex(mpt::as_span(v.RawVersion()));
} else
{
name = U_("wine-");
}
name += U_("-") + Util::BinToHex(mpt::as_span(v.RawHostSysName()));
} else
{
name = mpt::format(U_("%1.%2"))(mpt::ufmt::dec(m_System.Major), mpt::ufmt::dec0<2>(m_System.Minor));
}
return name;
}
#endif // MODPLUG_TRACKER
mpt::Windows::Version::System Version::GetMinimumKernelLevel() noexcept
{
uint64 minimumKernelVersion = 0;
#if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::Windows::Version::WinVista));
#endif
return mpt::Windows::Version::System(minimumKernelVersion);
}
mpt::Windows::Version::System Version::GetMinimumAPILevel() noexcept
{
#if MPT_OS_WINDOWS
return SystemVersionFrom_WIN32_WINNT();
#else // !MPT_OS_WINDOWS
return mpt::Windows::Version::System();
#endif // MPT_OS_WINDOWS
}
#if defined(MODPLUG_TRACKER) && 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::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;
MemsetZero(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;
MemsetZero(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;
MemsetZero(memoryStatus);
memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
if(GlobalMemoryStatusEx(&memoryStatus) == 0)
{
return 0;
}
return memoryStatus.ullTotalPhys;
}
#endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
#if defined(MODPLUG_TRACKER)
#if MPT_OS_WINDOWS
static bool GatherSystemIsWine()
{
bool SystemIsWine = false;
HMODULE hNTDLL = LoadLibrary(TEXT("ntdll.dll"));
if(hNTDLL)
{
SystemIsWine = (GetProcAddress(hNTDLL, "wine_get_version") != NULL);
FreeLibrary(hNTDLL);
hNTDLL = NULL;
}
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::Windows::Version::Current().IsWindows() && !SystemIsWine();
}
bool IsWine()
{
return mpt::Windows::Version::Current().IsWindows() && SystemIsWine();
}
#endif // MODPLUG_TRACKER
} // namespace Windows
} // namespace mpt
#if defined(MODPLUG_TRACKER)
namespace mpt
{
namespace Wine
{
Version::Version()
: valid(false)
, vmajor(0)
, vminor(0)
, vupdate(0)
{
return;
}
Version::Version(const mpt::ustring &rawVersion)
: valid(false)
, vmajor(0)
, vminor(0)
, vupdate(0)
{
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)
: valid((vmajor > 0) || (vminor > 0) || (vupdate > 0))
, vmajor(vmajor)
, vminor(vminor)
, vupdate(vupdate)
{
return;
}
mpt::Wine::Version Version::FromInteger(uint32 version)
{
mpt::Wine::Version result;
result.valid = (version <= 0xffffff);
result.vmajor = static_cast<uint8>(version >> 16);
result.vminor = static_cast<uint8>(version >> 8);
result.vupdate = static_cast<uint8>(version >> 0);
return result;
}
bool Version::IsValid() const
{
return valid;
}
mpt::ustring Version::AsString() const
{
return mpt::ufmt::dec(vmajor) + U_(".") + mpt::ufmt::dec(vminor) + U_(".") + mpt::ufmt::dec(vupdate);
}
uint32 Version::AsInteger() const
{
uint32 version = 0;
version |= static_cast<uint32>(vmajor) << 16;
version |= static_cast<uint32>(vminor) << 8;
version |= static_cast<uint32>(vupdate) << 0;
return version;
}
bool Version::IsBefore(mpt::Wine::Version other) const
{
if(!IsValid())
{
return false;
}
return (AsInteger() < other.AsInteger());
}
bool Version::IsAtLeast(mpt::Wine::Version other) const
{
if(!IsValid())
{
return false;
}
return (AsInteger() >= other.AsInteger());
}
uint8 Version::GetMajor() const
{
return vmajor;
}
uint8 Version::GetMinor() const
{
return vminor;
}
uint8 Version::GetUpdate() const
{
return vupdate;
}
mpt::Wine::Version GetMinimumWineVersion()
{
mpt::Wine::Version minimumWineVersion = mpt::Wine::Version(0,0,0);
#if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
minimumWineVersion = mpt::Wine::Version(1,8,0);
#endif
return minimumWineVersion;
}
VersionContext::VersionContext()
: m_IsWine(false)
, m_HostClass(mpt::OS::Class::Unknown)
{
#if MPT_OS_WINDOWS
m_IsWine = mpt::Windows::IsWine();
if(!m_IsWine)
{
return;
}
m_NTDLL = mpt::Library(mpt::LibraryPath::FullPath(P_("ntdll.dll")));
if(m_NTDLL.IsValid())
{
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;
m_NTDLL.Bind(wine_get_version, "wine_get_version");
m_NTDLL.Bind(wine_get_build_id, "wine_get_build_id");
m_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::Wine::Version(mpt::ToUnicode(mpt::Charset::UTF8, m_RawVersion));
m_HostClass = mpt::OS::GetClassFromSysname(mpt::ToUnicode(mpt::Charset::UTF8, m_RawHostSysName));
#endif // MPT_OS_WINDOWS
}
} // namespace Wine
} // namespace mpt
#endif // MODPLUG_TRACKER
OPENMPT_NAMESPACE_END