/* * 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 #endif #if defined(MODPLUG_TRACKER) #if !MPT_OS_WINDOWS #include #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(_WIN32_WINNT) & 0xff00u) >> 8, (static_cast(_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(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(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 GetSupportedProcessArchitectures(Architecture host) { std::vector 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 version = mpt::String::Split(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(version >> 16); result.vminor = static_cast(version >> 8); result.vupdate = static_cast(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(vmajor) << 16; version |= static_cast(vminor) << 8; version |= static_cast(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