552 lines
17 KiB
C++
552 lines
17 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"
|
||
|
|
||
|
#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
|