2018-02-19 01:25:43 -03:00
/*
* 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
2020-09-22 01:54:24 -03:00
# if defined(MODPLUG_TRACKER)
# if !MPT_OS_WINDOWS
# include <sys/utsname.h>
# endif // !MPT_OS_WINDOWS
# endif // MODPLUG_TRACKER
2018-02-19 01:25:43 -03:00
OPENMPT_NAMESPACE_BEGIN
2020-09-22 01:54:24 -03:00
# 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
2018-02-19 01:25:43 -03:00
namespace mpt
{
namespace Windows
{
# if MPT_OS_WINDOWS
2019-01-23 23:16:37 -03:00
static mpt : : Windows : : Version VersionFromNTDDI_VERSION ( ) noexcept
2018-02-19 01:25:43 -03:00
{
// Initialize to used SDK version
2019-01-23 23:16:37 -03:00
mpt : : Windows : : Version : : System System =
2018-02-19 01:25:43 -03:00
# 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
;
2020-09-22 01:54:24 -03:00
return mpt : : Windows : : Version ( System , mpt : : Windows : : Version : : ServicePack ( ( ( NTDDI_VERSION & 0xffffu ) > > 8 ) & 0xffu , ( ( NTDDI_VERSION & 0xffffu ) > > 0 ) & 0xffu ) , 0 , 0 ) ;
2019-01-23 23:16:37 -03:00
}
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
2018-02-19 01:25:43 -03:00
OSVERSIONINFOEXW versioninfoex ;
MemsetZero ( versioninfoex ) ;
versioninfoex . dwOSVersionInfoSize = sizeof ( versioninfoex ) ;
# if MPT_COMPILER_MSVC
# pragma warning(push)
# pragma warning(disable:4996) // 'GetVersionExW': was declared deprecated
2020-09-22 01:54:24 -03:00
# pragma warning(disable:28159) // Consider using 'IsWindows*' instead of 'GetVersionExW'. Reason: Deprecated. Use VerifyVersionInfo* or IsWindows* macros from VersionHelpers.
2018-02-19 01:25:43 -03:00
# endif // MPT_COMPILER_MSVC
2019-01-23 23:16:37 -03:00
# if MPT_COMPILER_CLANG
2018-02-19 01:25:43 -03:00
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
# endif // MPT_COMPILER_CLANG
2019-01-23 23:16:37 -03:00
if ( GetVersionExW ( ( LPOSVERSIONINFOW ) & versioninfoex ) = = FALSE )
{
return VersionFromNTDDI_VERSION ( ) ;
}
2018-02-19 01:25:43 -03:00
# if MPT_COMPILER_MSVC
# pragma warning(pop)
# endif // MPT_COMPILER_MSVC
2019-01-23 23:16:37 -03:00
# if MPT_COMPILER_CLANG
2018-02-19 01:25:43 -03:00
# pragma clang diagnostic pop
# endif // MPT_COMPILER_CLANG
2019-01-23 23:16:37 -03:00
if ( versioninfoex . dwPlatformId ! = VER_PLATFORM_WIN32_NT )
{
return VersionFromNTDDI_VERSION ( ) ;
}
2020-09-22 01:54:24 -03:00
DWORD dwProductType = 0 ;
dwProductType = PRODUCT_UNDEFINED ;
if ( GetProductInfo ( versioninfoex . dwMajorVersion , versioninfoex . dwMinorVersion , versioninfoex . wServicePackMajor , versioninfoex . wServicePackMinor , & dwProductType ) = = FALSE )
{
dwProductType = PRODUCT_UNDEFINED ;
}
2019-01-23 23:16:37 -03:00
return mpt : : Windows : : Version (
mpt : : Windows : : Version : : System ( versioninfoex . dwMajorVersion , versioninfoex . dwMinorVersion ) ,
mpt : : Windows : : Version : : ServicePack ( versioninfoex . wServicePackMajor , versioninfoex . wServicePackMinor ) ,
2020-09-22 01:54:24 -03:00
versioninfoex . dwBuildNumber ,
dwProductType
2019-01-23 23:16:37 -03:00
) ;
# endif // MPT_OS_WINDOWS_WINRT
2018-02-19 01:25:43 -03:00
}
# ifdef MODPLUG_TRACKER
namespace {
struct WindowsVersionCache
{
2019-01-23 23:16:37 -03:00
mpt : : Windows : : Version version ;
WindowsVersionCache ( ) noexcept
: version ( GatherWindowsVersion ( ) )
2018-02-19 01:25:43 -03:00
{
}
} ;
}
2019-01-23 23:16:37 -03:00
static mpt : : Windows : : Version GatherWindowsVersionFromCache ( ) noexcept
2018-02-19 01:25:43 -03:00
{
static WindowsVersionCache gs_WindowsVersionCache ;
2019-01-23 23:16:37 -03:00
return gs_WindowsVersionCache . version ;
2018-02-19 01:25:43 -03:00
}
# endif // MODPLUG_TRACKER
# endif // MPT_OS_WINDOWS
2019-01-23 23:16:37 -03:00
Version : : Version ( ) noexcept
: m_SystemIsWindows ( false )
, m_System ( )
, m_ServicePack ( )
, m_Build ( )
2020-09-22 01:54:24 -03:00
, m_Type ( )
2018-02-19 01:25:43 -03:00
{
}
2019-01-23 23:16:37 -03:00
Version Version : : NoWindows ( ) noexcept
{
return Version ( ) ;
}
2020-09-22 01:54:24 -03:00
Version : : Version ( mpt : : Windows : : Version : : System system , mpt : : Windows : : Version : : ServicePack servicePack , mpt : : Windows : : Version : : Build build , mpt : : Windows : : Version : : TypeId type ) noexcept
2019-01-23 23:16:37 -03:00
: m_SystemIsWindows ( true )
, m_System ( system )
, m_ServicePack ( servicePack )
, m_Build ( build )
2020-09-22 01:54:24 -03:00
, m_Type ( type )
2019-01-23 23:16:37 -03:00
{
}
mpt : : Windows : : Version Version : : Current ( ) noexcept
2018-02-19 01:25:43 -03:00
{
# if MPT_OS_WINDOWS
# ifdef MODPLUG_TRACKER
2019-01-23 23:16:37 -03:00
return GatherWindowsVersionFromCache ( ) ;
2018-02-19 01:25:43 -03:00
# else // !MODPLUG_TRACKER
2019-01-23 23:16:37 -03:00
return GatherWindowsVersion ( ) ;
2018-02-19 01:25:43 -03:00
# endif // MODPLUG_TRACKER
2019-01-23 23:16:37 -03:00
# else // !MPT_OS_WINDOWS
return mpt : : Windows : : Version : : NoWindows ( ) ;
2018-02-19 01:25:43 -03:00
# endif // MPT_OS_WINDOWS
}
2019-01-23 23:16:37 -03:00
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
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
if ( ! m_SystemIsWindows )
{
return false ;
}
if ( m_System > version )
{
return false ;
}
if ( m_System < version )
{
return true ;
}
return m_Build < build ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
bool Version : : IsAtLeast ( mpt : : Windows : : Version : : System version ) const noexcept
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
if ( ! m_SystemIsWindows )
2018-02-19 01:25:43 -03:00
{
return false ;
}
2019-01-23 23:16:37 -03:00
return m_System > = version ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
bool Version : : IsAtLeast ( mpt : : Windows : : Version : : System version , mpt : : Windows : : Version : : ServicePack servicePack ) const noexcept
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
if ( ! m_SystemIsWindows )
{
return false ;
}
if ( m_System < version )
2018-02-19 01:25:43 -03:00
{
return false ;
}
2019-01-23 23:16:37 -03:00
if ( m_System > version )
{
return true ;
}
return m_ServicePack > = servicePack ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
bool Version : : IsAtLeast ( mpt : : Windows : : Version : : System version , mpt : : Windows : : Version : : Build build ) const noexcept
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
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 ;
}
2020-09-22 01:54:24 -03:00
mpt : : Windows : : Version : : TypeId Version : : GetTypeId ( ) const noexcept
{
return m_Type ;
}
static constexpr struct { Version : : System version ; const mpt : : uchar * name ; bool showDetails ; } versionMap [ ] =
2019-01-23 23:16:37 -03:00
{
{ 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 }
2018-02-19 01:25:43 -03:00
} ;
2019-01-23 23:16:37 -03:00
mpt : : ustring Version : : VersionToString ( mpt : : Windows : : Version : : System version )
2018-02-19 01:25:43 -03:00
{
mpt : : ustring result ;
for ( const auto & v : versionMap )
{
if ( version > v . version )
{
2019-01-23 23:16:37 -03:00
result = U_ ( " > " ) + v . name ;
2018-02-19 01:25:43 -03:00
break ;
} else if ( version = = v . version )
{
result = v . name ;
break ;
}
}
if ( result . empty ( ) )
{
2019-01-23 23:16:37 -03:00
result = mpt : : format ( U_ ( " 0x%1 " ) ) ( mpt : : ufmt : : hex0 < 16 > ( static_cast < uint64 > ( version ) ) ) ;
2018-02-19 01:25:43 -03:00
}
return result ;
}
mpt : : ustring Version : : GetName ( ) const
{
2019-01-23 23:16:37 -03:00
mpt : : ustring name = U_ ( " Generic Windows NT " ) ;
bool showDetails = false ;
2018-02-19 01:25:43 -03:00
for ( const auto & v : versionMap )
{
2019-01-23 23:16:37 -03:00
if ( IsAtLeast ( v . version ) )
2018-02-19 01:25:43 -03:00
{
name = v . name ;
2019-01-23 23:16:37 -03:00
showDetails = v . showDetails ;
2018-02-19 01:25:43 -03:00
break ;
}
}
2019-01-23 23:16:37 -03:00
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_ ( " ) " ) ;
2018-02-19 01:25:43 -03:00
mpt : : ustring result = name ;
# if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
if ( mpt : : Windows : : IsWine ( ) )
{
mpt : : Wine : : VersionContext v ;
if ( v . Version ( ) . IsValid ( ) )
{
2019-01-23 23:16:37 -03:00
result = mpt : : format ( U_ ( " Wine %1 (%2) " ) ) (
2018-02-19 01:25:43 -03:00
v . Version ( ) . AsString ( )
, name
) ;
} else
{
2019-01-23 23:16:37 -03:00
result = mpt : : format ( U_ ( " Wine (unknown version: '%1') (%2) " ) ) (
2020-09-22 01:54:24 -03:00
mpt : : ToUnicode ( mpt : : Charset : : UTF8 , v . RawVersion ( ) )
2018-02-19 01:25:43 -03:00
, 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 ( ) )
{
2019-01-23 23:16:37 -03:00
name = mpt : : format ( U_ ( " wine-%1 " ) ) ( v . Version ( ) . AsString ( ) ) ;
2018-02-19 01:25:43 -03:00
} else if ( v . RawVersion ( ) . length ( ) > 0 )
{
2019-01-23 23:16:37 -03:00
name = U_ ( " wine- " ) + Util : : BinToHex ( mpt : : as_span ( v . RawVersion ( ) ) ) ;
2018-02-19 01:25:43 -03:00
} else
{
2019-01-23 23:16:37 -03:00
name = U_ ( " wine- " ) ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
name + = U_ ( " - " ) + Util : : BinToHex ( mpt : : as_span ( v . RawHostSysName ( ) ) ) ;
2018-02-19 01:25:43 -03:00
} else
{
2019-01-23 23:16:37 -03:00
name = mpt : : format ( U_ ( " %1.%2 " ) ) ( mpt : : ufmt : : dec ( m_System . Major ) , mpt : : ufmt : : dec0 < 2 > ( m_System . Minor ) ) ;
2018-02-19 01:25:43 -03:00
}
return name ;
}
# endif // MODPLUG_TRACKER
2019-01-23 23:16:37 -03:00
mpt : : Windows : : Version : : System Version : : GetMinimumKernelLevel ( ) noexcept
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
uint64 minimumKernelVersion = 0 ;
2018-02-19 01:25:43 -03:00
# if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
2020-09-22 01:54:24 -03:00
minimumKernelVersion = std : : max ( minimumKernelVersion , static_cast < uint64 > ( mpt : : Windows : : Version : : WinVista ) ) ;
2018-02-19 01:25:43 -03:00
# endif
2019-01-23 23:16:37 -03:00
return mpt : : Windows : : Version : : System ( minimumKernelVersion ) ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
mpt : : Windows : : Version : : System Version : : GetMinimumAPILevel ( ) noexcept
2018-02-19 01:25:43 -03:00
{
2019-01-23 23:16:37 -03:00
# 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 ;
2020-09-22 01:54:24 -03:00
const mpt : : uchar * Name ;
2019-01-23 23:16:37 -03:00
} ;
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 ;
2018-02-19 01:25:43 -03:00
}
2019-01-23 23:16:37 -03:00
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
2018-02-19 01:25:43 -03:00
# if defined(MODPLUG_TRACKER)
# if MPT_OS_WINDOWS
static bool GatherSystemIsWine ( )
{
bool SystemIsWine = false ;
2019-01-23 23:16:37 -03:00
HMODULE hNTDLL = LoadLibrary ( TEXT ( " ntdll.dll " ) ) ;
2018-02-19 01:25:43 -03:00
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 ;
}
} ;
}
2019-01-23 23:16:37 -03:00
# endif // MPT_OS_WINDOWS
2018-02-19 01:25:43 -03:00
static bool SystemIsWine ( bool allowDetection = true )
{
2019-01-23 23:16:37 -03:00
# if MPT_OS_WINDOWS
2018-02-19 01:25:43 -03:00
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 ;
}
2019-01-23 23:16:37 -03:00
std : : vector < uint8 > version = mpt : : String : : Split < uint8 > ( rawVersion , U_ ( " . " ) ) ;
2018-02-19 01:25:43 -03:00
if ( version . size ( ) < 2 )
{
return ;
}
2019-01-23 23:16:37 -03:00
mpt : : ustring parsedVersion = mpt : : String : : Combine ( version , U_ ( " . " ) ) ;
2018-02-19 01:25:43 -03:00
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
{
2019-01-23 23:16:37 -03:00
return mpt : : ufmt : : dec ( vmajor ) + U_ ( " . " ) + mpt : : ufmt : : dec ( vminor ) + U_ ( " . " ) + mpt : : ufmt : : dec ( vupdate ) ;
2018-02-19 01:25:43 -03:00
}
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 ( ) ) ;
}
2019-01-23 23:16:37 -03:00
uint8 Version : : GetMajor ( ) const
{
return vmajor ;
}
uint8 Version : : GetMinor ( ) const
{
return vminor ;
}
uint8 Version : : GetUpdate ( ) const
{
return vupdate ;
}
2018-02-19 01:25:43 -03:00
mpt : : Wine : : Version GetMinimumWineVersion ( )
{
mpt : : Wine : : Version minimumWineVersion = mpt : : Wine : : Version ( 0 , 0 , 0 ) ;
# if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
2019-01-23 23:16:37 -03:00
minimumWineVersion = mpt : : Wine : : Version ( 1 , 8 , 0 ) ;
2018-02-19 01:25:43 -03:00
# endif
return minimumWineVersion ;
}
VersionContext : : VersionContext ( )
: m_IsWine ( false )
2020-09-22 01:54:24 -03:00
, m_HostClass ( mpt : : OS : : Class : : Unknown )
2018-02-19 01:25:43 -03:00
{
# if MPT_OS_WINDOWS
m_IsWine = mpt : : Windows : : IsWine ( ) ;
if ( ! m_IsWine )
{
return ;
}
2019-01-23 23:16:37 -03:00
m_NTDLL = mpt : : Library ( mpt : : LibraryPath : : FullPath ( P_ ( " ntdll.dll " ) ) ) ;
2018-02-19 01:25:43 -03:00
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 : " " ;
}
2020-09-22 01:54:24 -03:00
m_Version = mpt : : Wine : : Version ( mpt : : ToUnicode ( mpt : : Charset : : UTF8 , m_RawVersion ) ) ;
m_HostClass = mpt : : OS : : GetClassFromSysname ( mpt : : ToUnicode ( mpt : : Charset : : UTF8 , m_RawHostSysName ) ) ;
2018-02-19 01:25:43 -03:00
# endif // MPT_OS_WINDOWS
}
} // namespace Wine
} // namespace mpt
# endif // MODPLUG_TRACKER
OPENMPT_NAMESPACE_END