| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 | using System;using System.IO;using System.Reflection;using System.Runtime.InteropServices;using MonoMod.Utils;namespace BepInEx.Preloader.Core{	internal static class PlatformUtils	{		[StructLayout(LayoutKind.Sequential, Pack = 1)]		public struct utsname_osx		{			private const int osx_utslen = 256;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]			public string sysname;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]			public string nodename;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]			public string release;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]			public string version;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = osx_utslen)]			public string machine;		}		[StructLayout(LayoutKind.Sequential, Pack = 1)]		public struct utsname_linux		{			private const int linux_utslen = 65;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string sysname;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string nodename;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string release;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string version;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string machine;			[MarshalAs(UnmanagedType.ByValTStr, SizeConst = linux_utslen)]			public string domainname;		}		[DllImport("libc.so.6", EntryPoint = "uname", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]		private static extern IntPtr uname_linux(ref utsname_linux utsname);		[DllImport("/usr/lib/libSystem.dylib", EntryPoint = "uname", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]		private static extern IntPtr uname_osx(ref utsname_osx utsname);		/// <summary>		/// Recreation of MonoMod's PlatformHelper.DeterminePlatform method, but with libc calls instead of creating processes.		/// </summary>		public static void SetPlatform()		{			var current = Platform.Unknown;			// For old Mono, get from a private property to accurately get the platform.			// static extern PlatformID Platform			PropertyInfo p_Platform = typeof(Environment).GetProperty("Platform", BindingFlags.NonPublic | BindingFlags.Static);			string platID;			if (p_Platform != null)			{				platID = p_Platform.GetValue(null, new object[0]).ToString();			}			else			{				// For .NET and newer Mono, use the usual value.				platID = Environment.OSVersion.Platform.ToString();			}			platID = platID.ToLowerInvariant();			if (platID.Contains("win"))			{				current = Platform.Windows;			}			else if (platID.Contains("mac") || platID.Contains("osx"))			{				current = Platform.MacOS;			}			else if (platID.Contains("lin") || platID.Contains("unix"))			{				current = Platform.Linux;			}			if (Is(current, Platform.Linux) && Directory.Exists("/data") && File.Exists("/system/build.prop"))			{				current = Platform.Android;			}			else if (Is(current, Platform.Unix) && Directory.Exists("/System/Library/AccessibilityBundles"))			{				current = Platform.iOS;			}			// Is64BitOperatingSystem has been added in .NET Framework 4.0			MethodInfo m_get_Is64BitOperatingSystem = typeof(Environment).GetProperty("Is64BitOperatingSystem")?.GetGetMethod();			if (m_get_Is64BitOperatingSystem != null)				current |= (((bool)m_get_Is64BitOperatingSystem.Invoke(null, new object[0])) ? Platform.Bits64 : 0);			else				current |= (IntPtr.Size >= 8 ? Platform.Bits64 : 0);			if ((Is(current, Platform.MacOS) || Is(current, Platform.Linux)) && Type.GetType("Mono.Runtime") != null)			{				string arch;				IntPtr result;				if (Is(current, Platform.MacOS))				{					utsname_osx utsname_osx = new utsname_osx();					result = uname_osx(ref utsname_osx);					arch = utsname_osx.machine;				}				else				{					// Linux					utsname_linux utsname_linux = new utsname_linux();					result = uname_linux(ref utsname_linux);					arch = utsname_linux.machine;				}				if (result == IntPtr.Zero && (arch.StartsWith("aarch") || arch.StartsWith("arm")))					current |= Platform.ARM;			}			else			{				// Detect ARM based on PE info or uname.				typeof(object).Module.GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine);				if (machine == (ImageFileMachine)0x01C4 /* ARM, .NET Framework 4.5 */)					current |= Platform.ARM;			}			PlatformHelper.Current = current;		}		private static bool Is(Platform current, Platform expected)		{			return (current & expected) == expected;		}	}}
 |