1
0

mptOS.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. * mptOS.cpp
  3. * ---------
  4. * Purpose: Operating system version information.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "stdafx.h"
  10. #include "mptOS.h"
  11. #include "mpt/binary/hex.hpp"
  12. #if MPT_OS_WINDOWS
  13. #include <windows.h>
  14. #endif
  15. OPENMPT_NAMESPACE_BEGIN
  16. namespace mpt
  17. {
  18. namespace OS
  19. {
  20. namespace Windows
  21. {
  22. #if MPT_OS_WINDOWS
  23. namespace {
  24. struct WindowsVersionCache
  25. {
  26. mpt::osinfo::windows::Version version;
  27. WindowsVersionCache() noexcept
  28. : version(mpt::osinfo::windows::Version::Current())
  29. {
  30. }
  31. };
  32. }
  33. static mpt::osinfo::windows::Version GatherWindowsVersionFromCache() noexcept
  34. {
  35. static WindowsVersionCache gs_WindowsVersionCache;
  36. return gs_WindowsVersionCache.version;
  37. }
  38. #endif // MPT_OS_WINDOWS
  39. mpt::osinfo::windows::Version Version::Current() noexcept
  40. {
  41. #if MPT_OS_WINDOWS
  42. #ifdef MODPLUG_TRACKER
  43. return GatherWindowsVersionFromCache();
  44. #else // !MODPLUG_TRACKER
  45. return mpt::osinfo::windows::Version::Current();
  46. #endif // MODPLUG_TRACKER
  47. #else // !MPT_OS_WINDOWS
  48. return mpt::osinfo::windows::Version::NoWindows();
  49. #endif // MPT_OS_WINDOWS
  50. }
  51. static constexpr struct { mpt::osinfo::windows::Version version; const mpt::uchar * name; bool showDetails; } versionMap[] =
  52. {
  53. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNewer, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11 (or newer)"), false },
  54. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 22000, 0 }, UL_("Windows 11"), true },
  55. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19044, 0 }, UL_("Windows 10 21H2"), true },
  56. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19043, 0 }, UL_("Windows 10 21H1"), true },
  57. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19042, 0 }, UL_("Windows 10 20H2"), true },
  58. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 19041, 0 }, UL_("Windows 10 2004"), true },
  59. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18363, 0 }, UL_("Windows 10 1909"), true },
  60. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 18362, 0 }, UL_("Windows 10 1903"), true },
  61. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17763, 0 }, UL_("Windows 10 1809"), true },
  62. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 17134, 0 }, UL_("Windows 10 1803"), true },
  63. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 16299, 0 }, UL_("Windows 10 1709"), true },
  64. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 15063, 0 }, UL_("Windows 10 1703"), true },
  65. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 14393, 0 }, UL_("Windows 10 1607"), true },
  66. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10586, 0 }, UL_("Windows 10 1511"), true },
  67. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10240, 0 }, UL_("Windows 10 1507"), true },
  68. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8.1"), true },
  69. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win8, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8"), true },
  70. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win7, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 7"), true },
  71. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinVista, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows Vista"), true },
  72. { 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 },
  73. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinXP, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows XP"), true },
  74. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win2000, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 2000"), true },
  75. { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::WinNT4, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows NT4"), true }
  76. };
  77. mpt::ustring Version::GetName(mpt::osinfo::windows::Version version)
  78. {
  79. mpt::ustring name = U_("Generic Windows NT");
  80. bool showDetails = false;
  81. for(const auto &v : versionMap)
  82. {
  83. if(version.IsAtLeast(v.version))
  84. {
  85. name = v.name;
  86. showDetails = v.showDetails;
  87. break;
  88. }
  89. }
  90. name += U_(" (");
  91. name += MPT_UFORMAT("Version {}.{}")(version.GetSystem().Major, version.GetSystem().Minor);
  92. if(showDetails)
  93. {
  94. if(version.GetServicePack().HasServicePack())
  95. {
  96. if(version.GetServicePack().Minor)
  97. {
  98. name += MPT_UFORMAT(" Service Pack {}.{}")(version.GetServicePack().Major, version.GetServicePack().Minor);
  99. } else
  100. {
  101. name += MPT_UFORMAT(" Service Pack {}")(version.GetServicePack().Major);
  102. }
  103. }
  104. if(version.GetBuild() != 0)
  105. {
  106. name += MPT_UFORMAT(" (Build {})")(version.GetBuild());
  107. }
  108. }
  109. name += U_(")");
  110. mpt::ustring result = name;
  111. #if defined(MODPLUG_TRACKER) && MPT_OS_WINDOWS
  112. if(mpt::OS::Windows::IsWine())
  113. {
  114. mpt::OS::Wine::VersionContext v;
  115. if(v.Version().IsValid())
  116. {
  117. result = MPT_UFORMAT("Wine {} ({})")(
  118. v.Version().AsString()
  119. , name
  120. );
  121. } else
  122. {
  123. result = MPT_UFORMAT("Wine (unknown version: '{}') ({})")(
  124. mpt::ToUnicode(mpt::Charset::UTF8, v.RawVersion())
  125. , name
  126. );
  127. }
  128. }
  129. #endif // MODPLUG_TRACKER && MPT_OS_WINDOWS
  130. return result;
  131. }
  132. mpt::osinfo::windows::Version Version::GetMinimumKernelLevel() noexcept
  133. {
  134. uint64 minimumKernelVersion = 0;
  135. #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
  136. #if defined(MPT_BUILD_RETRO)
  137. minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinXP));
  138. #else
  139. minimumKernelVersion = std::max(minimumKernelVersion, static_cast<uint64>(mpt::osinfo::windows::Version::WinVista));
  140. #endif
  141. #endif
  142. return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::System(minimumKernelVersion), mpt::osinfo::windows::Version::ServicePack(0, 0), 0, 0);
  143. }
  144. mpt::osinfo::windows::Version Version::GetMinimumAPILevel() noexcept
  145. {
  146. #if MPT_OS_WINDOWS
  147. return mpt::osinfo::windows::Version::FromSDK();
  148. #else // !MPT_OS_WINDOWS
  149. return mpt::osinfo::windows::Version::NoWindows();
  150. #endif // MPT_OS_WINDOWS
  151. }
  152. #if MPT_OS_WINDOWS
  153. #ifndef PROCESSOR_ARCHITECTURE_NEUTRAL
  154. #define PROCESSOR_ARCHITECTURE_NEUTRAL 11
  155. #endif
  156. #ifndef PROCESSOR_ARCHITECTURE_ARM64
  157. #define PROCESSOR_ARCHITECTURE_ARM64 12
  158. #endif
  159. #ifndef PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64
  160. #define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
  161. #endif
  162. #ifndef PROCESSOR_ARCHITECTURE_IA32_ON_ARM64
  163. #define PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 14
  164. #endif
  165. struct OSArchitecture
  166. {
  167. uint16 ProcessorArchitectur;
  168. Architecture Host;
  169. Architecture Process;
  170. };
  171. static constexpr OSArchitecture architectures [] = {
  172. { PROCESSOR_ARCHITECTURE_INTEL , Architecture::x86 , Architecture::x86 },
  173. { PROCESSOR_ARCHITECTURE_AMD64 , Architecture::amd64 , Architecture::amd64 },
  174. { PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 , Architecture::amd64 , Architecture::x86 },
  175. { PROCESSOR_ARCHITECTURE_ARM , Architecture::arm , Architecture::arm },
  176. { PROCESSOR_ARCHITECTURE_ARM64 , Architecture::arm64 , Architecture::arm64 },
  177. { PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64, Architecture::arm64 , Architecture::arm },
  178. { PROCESSOR_ARCHITECTURE_IA32_ON_ARM64 , Architecture::arm64 , Architecture::x86 },
  179. { PROCESSOR_ARCHITECTURE_MIPS , Architecture::mips , Architecture::mips },
  180. { PROCESSOR_ARCHITECTURE_PPC , Architecture::ppc , Architecture::ppc },
  181. { PROCESSOR_ARCHITECTURE_SHX , Architecture::shx , Architecture::shx },
  182. { PROCESSOR_ARCHITECTURE_ALPHA , Architecture::alpha , Architecture::alpha },
  183. { PROCESSOR_ARCHITECTURE_ALPHA64 , Architecture::alpha64, Architecture::alpha64 },
  184. { PROCESSOR_ARCHITECTURE_IA64 , Architecture::ia64 , Architecture::ia64 },
  185. { PROCESSOR_ARCHITECTURE_MSIL , Architecture::unknown, Architecture::unknown },
  186. { PROCESSOR_ARCHITECTURE_NEUTRAL , Architecture::unknown, Architecture::unknown },
  187. { PROCESSOR_ARCHITECTURE_UNKNOWN , Architecture::unknown, Architecture::unknown }
  188. };
  189. struct HostArchitecture
  190. {
  191. Architecture Host;
  192. Architecture Process;
  193. EmulationLevel Emulation;
  194. };
  195. static constexpr HostArchitecture hostArchitectureCanRun [] = {
  196. { Architecture::x86 , Architecture::x86 , EmulationLevel::Native },
  197. { Architecture::amd64 , Architecture::amd64 , EmulationLevel::Native },
  198. { Architecture::amd64 , Architecture::x86 , EmulationLevel::Virtual },
  199. { Architecture::arm , Architecture::arm , EmulationLevel::Native },
  200. { Architecture::arm64 , Architecture::arm64 , EmulationLevel::Native },
  201. { Architecture::arm64 , Architecture::arm , EmulationLevel::Virtual },
  202. { Architecture::arm64 , Architecture::x86 , EmulationLevel::Software },
  203. { Architecture::arm64 , Architecture::amd64 , EmulationLevel::Software },
  204. { Architecture::mips , Architecture::mips , EmulationLevel::Native },
  205. { Architecture::ppc , Architecture::ppc , EmulationLevel::Native },
  206. { Architecture::shx , Architecture::shx , EmulationLevel::Native },
  207. { Architecture::alpha , Architecture::alpha , EmulationLevel::Native },
  208. { Architecture::alpha64, Architecture::alpha64, EmulationLevel::Native },
  209. { Architecture::alpha64, Architecture::alpha , EmulationLevel::Virtual },
  210. { Architecture::ia64 , Architecture::ia64 , EmulationLevel::Native },
  211. { Architecture::ia64 , Architecture::x86 , EmulationLevel::Hardware }
  212. };
  213. struct ArchitectureInfo
  214. {
  215. Architecture Arch;
  216. int Bitness;
  217. const mpt::uchar * Name;
  218. };
  219. static constexpr ArchitectureInfo architectureInfo [] = {
  220. { Architecture::x86 , 32, UL_("x86") },
  221. { Architecture::amd64 , 64, UL_("amd64") },
  222. { Architecture::arm , 32, UL_("arm") },
  223. { Architecture::arm64 , 64, UL_("arm64") },
  224. { Architecture::mips , 32, UL_("mips") },
  225. { Architecture::ppc , 32, UL_("ppc") },
  226. { Architecture::shx , 32, UL_("shx") },
  227. { Architecture::alpha , 32, UL_("alpha") },
  228. { Architecture::alpha64, 64, UL_("alpha64") },
  229. { Architecture::ia64 , 64, UL_("ia64") }
  230. };
  231. int Bitness(Architecture arch) noexcept
  232. {
  233. for(const auto &info : architectureInfo)
  234. {
  235. if(arch == info.Arch)
  236. {
  237. return info.Bitness;
  238. }
  239. }
  240. return 0;
  241. }
  242. mpt::ustring Name(Architecture arch)
  243. {
  244. for(const auto &info : architectureInfo)
  245. {
  246. if(arch == info.Arch)
  247. {
  248. return info.Name;
  249. }
  250. }
  251. return mpt::ustring();
  252. }
  253. Architecture GetHostArchitecture() noexcept
  254. {
  255. SYSTEM_INFO systemInfo = {};
  256. GetNativeSystemInfo(&systemInfo);
  257. for(const auto &arch : architectures)
  258. {
  259. if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
  260. {
  261. return arch.Host;
  262. }
  263. }
  264. return Architecture::unknown;
  265. }
  266. Architecture GetProcessArchitecture() noexcept
  267. {
  268. SYSTEM_INFO systemInfo = {};
  269. GetSystemInfo(&systemInfo);
  270. for(const auto &arch : architectures)
  271. {
  272. if(systemInfo.wProcessorArchitecture == arch.ProcessorArchitectur)
  273. {
  274. return arch.Process;
  275. }
  276. }
  277. return Architecture::unknown;
  278. }
  279. EmulationLevel HostCanRun(Architecture host, Architecture process) noexcept
  280. {
  281. for(const auto & can : hostArchitectureCanRun)
  282. {
  283. if(can.Host == host && can.Process == process)
  284. {
  285. return can.Emulation;
  286. }
  287. }
  288. return EmulationLevel::NA;
  289. }
  290. std::vector<Architecture> GetSupportedProcessArchitectures(Architecture host)
  291. {
  292. std::vector<Architecture> result;
  293. for(const auto & entry : hostArchitectureCanRun)
  294. {
  295. if(entry.Host == host)
  296. {
  297. result.push_back(entry.Process);
  298. }
  299. }
  300. return result;
  301. }
  302. uint64 GetSystemMemorySize()
  303. {
  304. MEMORYSTATUSEX memoryStatus = {};
  305. memoryStatus.dwLength = sizeof(MEMORYSTATUSEX);
  306. if(GlobalMemoryStatusEx(&memoryStatus) == 0)
  307. {
  308. return 0;
  309. }
  310. return memoryStatus.ullTotalPhys;
  311. }
  312. #endif // MPT_OS_WINDOWS
  313. #if defined(MODPLUG_TRACKER)
  314. #if MPT_OS_WINDOWS
  315. static bool GatherSystemIsWine()
  316. {
  317. bool SystemIsWine = false;
  318. 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 });
  319. if(NTDLL)
  320. {
  321. SystemIsWine = (NTDLL->get_address("wine_get_version") != nullptr);
  322. }
  323. return SystemIsWine;
  324. }
  325. namespace {
  326. struct SystemIsWineCache
  327. {
  328. bool SystemIsWine;
  329. SystemIsWineCache()
  330. : SystemIsWine(GatherSystemIsWine())
  331. {
  332. return;
  333. }
  334. SystemIsWineCache(bool isWine)
  335. : SystemIsWine(isWine)
  336. {
  337. return;
  338. }
  339. };
  340. }
  341. #endif // MPT_OS_WINDOWS
  342. static bool SystemIsWine(bool allowDetection = true)
  343. {
  344. #if MPT_OS_WINDOWS
  345. static SystemIsWineCache gs_SystemIsWineCache = allowDetection ? SystemIsWineCache() : SystemIsWineCache(false);
  346. if(!allowDetection)
  347. { // catch too late calls of PreventWineDetection
  348. MPT_ASSERT(!gs_SystemIsWineCache.SystemIsWine);
  349. }
  350. return gs_SystemIsWineCache.SystemIsWine;
  351. #else
  352. MPT_UNREFERENCED_PARAMETER(allowDetection);
  353. return false;
  354. #endif
  355. }
  356. void PreventWineDetection()
  357. {
  358. SystemIsWine(false);
  359. }
  360. bool IsOriginal()
  361. {
  362. return mpt::OS::Windows::Version::Current().IsWindows() && !SystemIsWine();
  363. }
  364. bool IsWine()
  365. {
  366. return mpt::OS::Windows::Version::Current().IsWindows() && SystemIsWine();
  367. }
  368. #endif // MODPLUG_TRACKER
  369. } // namespace Windows
  370. } // namespace OS
  371. } // namespace mpt
  372. namespace mpt
  373. {
  374. namespace OS
  375. {
  376. namespace Wine
  377. {
  378. Version::Version()
  379. {
  380. return;
  381. }
  382. Version::Version(const mpt::ustring &rawVersion)
  383. : mpt::osinfo::windows::wine::version()
  384. {
  385. if(rawVersion.empty())
  386. {
  387. return;
  388. }
  389. std::vector<uint8> version = mpt::String::Split<uint8>(rawVersion, U_("."));
  390. if(version.size() < 2)
  391. {
  392. return;
  393. }
  394. mpt::ustring parsedVersion = mpt::String::Combine(version, U_("."));
  395. std::size_t len = std::min(parsedVersion.length(), rawVersion.length());
  396. if(len == 0)
  397. {
  398. return;
  399. }
  400. if(parsedVersion.substr(0, len) != rawVersion.substr(0, len))
  401. {
  402. return;
  403. }
  404. valid = true;
  405. vmajor = version[0];
  406. vminor = version[1];
  407. vupdate = (version.size() >= 3) ? version[2] : 0;
  408. }
  409. Version::Version(uint8 vmajor, uint8 vminor, uint8 vupdate)
  410. : mpt::osinfo::windows::wine::version(vmajor, vminor, vupdate)
  411. {
  412. return;
  413. }
  414. mpt::ustring Version::AsString() const
  415. {
  416. return mpt::ufmt::dec(GetMajor()) + U_(".") + mpt::ufmt::dec(GetMinor()) + U_(".") + mpt::ufmt::dec(GetUpdate());
  417. }
  418. mpt::OS::Wine::Version GetMinimumWineVersion()
  419. {
  420. mpt::OS::Wine::Version minimumWineVersion = mpt::OS::Wine::Version(0,0,0);
  421. #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC
  422. minimumWineVersion = mpt::OS::Wine::Version(1,8,0);
  423. #endif
  424. return minimumWineVersion;
  425. }
  426. VersionContext::VersionContext()
  427. : m_IsWine(false)
  428. , m_HostClass(mpt::osinfo::osclass::Unknown)
  429. {
  430. #if MPT_OS_WINDOWS
  431. m_IsWine = mpt::OS::Windows::IsWine();
  432. if(!m_IsWine)
  433. {
  434. return;
  435. }
  436. 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});
  437. if(NTDLL)
  438. {
  439. const char * (__cdecl * wine_get_version)(void) = nullptr;
  440. const char * (__cdecl * wine_get_build_id)(void) = nullptr;
  441. void (__cdecl * wine_get_host_version)(const char * *, const char * *) = nullptr;
  442. NTDLL->bind(wine_get_version, "wine_get_version");
  443. NTDLL->bind(wine_get_build_id, "wine_get_build_id");
  444. NTDLL->bind(wine_get_host_version, "wine_get_host_version");
  445. const char * wine_version = nullptr;
  446. const char * wine_build_id = nullptr;
  447. const char * wine_host_sysname = nullptr;
  448. const char * wine_host_release = nullptr;
  449. wine_version = wine_get_version ? wine_get_version() : "";
  450. wine_build_id = wine_get_build_id ? wine_get_build_id() : "";
  451. if(wine_get_host_version)
  452. {
  453. wine_get_host_version(&wine_host_sysname, &wine_host_release);
  454. }
  455. m_RawVersion = wine_version ? wine_version : "";
  456. m_RawBuildID = wine_build_id ? wine_build_id : "";
  457. m_RawHostSysName = wine_host_sysname ? wine_host_sysname : "";
  458. m_RawHostRelease = wine_host_release ? wine_host_release : "";
  459. }
  460. m_Version = mpt::OS::Wine::Version(mpt::ToUnicode(mpt::Charset::UTF8, m_RawVersion));
  461. m_HostClass = mpt::osinfo::get_class_from_sysname(m_RawHostSysName);
  462. #endif // MPT_OS_WINDOWS
  463. }
  464. } // namespace Wine
  465. } // namespace OS
  466. } // namespace mpt
  467. OPENMPT_NAMESPACE_END