From: Lev Stipakov Date: Fri, 4 Nov 2022 09:02:47 +0000 (+0200) Subject: win32: detect arm64 architecture and emulations X-Git-Tag: v2.6_beta1~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99af056fad3cd0aef4af68d0eacc1fb9ef9b50c7;p=thirdparty%2Fopenvpn.git win32: detect arm64 architecture and emulations Properly detect process architecture and machine architecture, including arm64. Print process architecture and, if machine architecture is different (we are running in emulation), print that too. Signed-off-by: Lev Stipakov Acked-by: Gert Doering Message-Id: <20221104090247.167-1-lstipakov@gmail.com> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25476.html Signed-off-by: Gert Doering --- diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c index 82f0c73ff..cfe4dbded 100644 --- a/src/openvpn/win32.c +++ b/src/openvpn/win32.c @@ -1345,18 +1345,106 @@ win32_version_info(void) return WIN_10; } -bool -win32_is_64bit(void) +typedef enum { + ARCH_X86, + ARCH_AMD64, + ARCH_ARM64, + ARCH_NATIVE, /* means no emulation, makes sense for host arch */ + ARCH_UNKNOWN +} arch_t; + +static void +win32_get_arch(arch_t *process_arch, arch_t *host_arch) { -#if defined(_WIN64) - return true; /* 64-bit programs run only on Win64 */ + *process_arch = ARCH_UNKNOWN; + *host_arch = ARCH_NATIVE; + + typedef BOOL (__stdcall *is_wow64_process2_t)(HANDLE, USHORT *, USHORT *); + is_wow64_process2_t is_wow64_process2 = (is_wow64_process2_t) + GetProcAddress(GetModuleHandle("Kernel32.dll"), "IsWow64Process2"); + + USHORT process_machine = 0; + USHORT native_machine = 0; + BOOL is_wow64 = FALSE; + +#ifdef _ARM64_ + *process_arch = ARCH_ARM64; +#elif defined(_WIN64) + *process_arch = ARCH_AMD64; + if (is_wow64_process2) + { + /* this could be amd64 on arm64 */ + BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), + &process_machine, &native_machine); + if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64) + { + *host_arch = ARCH_ARM64; + } + } #elif defined(_WIN32) - /* 32-bit programs run on both 32-bit and 64-bit Windows */ - BOOL f64 = FALSE; - return IsWow64Process(GetCurrentProcess(), &f64) && f64; -#else /* if defined(_WIN64) */ - return false; /* Win64 does not support Win16 */ -#endif + *process_arch = ARCH_X86; + + if (is_wow64_process2) + { + /* check if we're running on arm64 or amd64 machine */ + is_wow64 = is_wow64_process2(GetCurrentProcess(), + &process_machine, &native_machine); + if (is_wow64) + { + switch (native_machine) + { + case IMAGE_FILE_MACHINE_ARM64: + *host_arch = ARCH_ARM64; + break; + + case IMAGE_FILE_MACHINE_AMD64: + *host_arch = ARCH_AMD64; + break; + + default: + *host_arch = ARCH_UNKNOWN; + break; + } + } + } + else + { + BOOL w64 = FALSE; + is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64; + if (is_wow64) + { + /* we are unable to differentiate between arm64 and amd64 + * machines here, so assume we are running on amd64 */ + *host_arch = ARCH_AMD64; + } + } +#endif /* _ARM64_ */ +} + +static void +win32_print_arch(arch_t arch, struct buffer *out) +{ + switch (arch) + { + case ARCH_X86: + buf_printf(out, "x86"); + break; + + case ARCH_AMD64: + buf_printf(out, "amd64"); + break; + + case ARCH_ARM64: + buf_printf(out, "arm64"); + break; + + case ARCH_UNKNOWN: + buf_printf(out, "(unknown)"); + break; + + default: + break; + } } const char * @@ -1397,7 +1485,20 @@ win32_version_string(struct gc_arena *gc, bool add_name) break; } - buf_printf(&out, win32_is_64bit() ? " 64bit" : " 32bit"); + buf_printf(&out, ", "); + + arch_t process_arch, host_arch; + win32_get_arch(&process_arch, &host_arch); + win32_print_arch(process_arch, &out); + + buf_printf(&out, " executable"); + + if (host_arch != ARCH_NATIVE) + { + buf_printf(&out, " running on "); + win32_print_arch(host_arch, &out); + buf_printf(&out, " host"); + } return (const char *)out.data; }