Skip to content

Commit

Permalink
[svrplus] svrplus.c: On ARM64 Windows 11, install for i386, arm64, an…
Browse files Browse the repository at this point in the history
…d arm64ec.

On Windows 10, only install for amd64 if using build 21277 or later,
since that's when amd64 emulation was added.

Fixes #398: Installing on ARM64 shows an error that the AMD64 version of
the DLL couldn't be registered
Reported by @kristibektashi.
  • Loading branch information
GerbilSoft committed Dec 3, 2023
1 parent 7f0811a commit 92393c3
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 4 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@
overhead for both code and RAM, but it significantly simplifies the code.
* Windows: The "xattr" tab now respects the LC_ALL and/or LC_MESSAGES
environment variable to allow for easier multi-language testing.
* Windows: On ARM64 Windows 11, register for i386, arm64, and arm64ec.
* On ARM64 Windows 10, only register amd64 if using build 21277 or later.
* Fixes Fixes #398: Installing on ARM64 shows an error that the AMD64 version of the DLL couldn't be registered
* Reported by @kristibektashi.

## v2.2.1 (released 2023/07/30)

Expand Down
21 changes: 21 additions & 0 deletions src/libwin32common/rp_versionhelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,27 @@ VERSIONHELPERAPI IsWindows10OrGreater(void) {
return IsWindowsThresholdOrGreater();
}

VERSIONHELPERAPI IsWindowsVersionOrGreater_BuildNumberCheck(WORD major, WORD minor, DWORD buildnumber)
{
OSVERSIONINFOEXW vi = {sizeof(vi),major,minor,buildnumber,0,{0},0};
return VerifyVersionInfoW(&vi, VER_MAJORVERSION|VER_MINORVERSION|VER_BUILDNUMBER,
VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0,
VER_MAJORVERSION,VER_GREATER_EQUAL),
VER_MINORVERSION,VER_GREATER_EQUAL),
VER_BUILDNUMBER, VER_GREATER_EQUAL));
}

VERSIONHELPERAPI IsWindows10Build21277OrGreater(void) {
// Windows 10 Build 21277 on ARM added amd64 emulation.
// https://blogs.windows.com/windows-insider/2020/12/10/introducing-x64-emulation-in-preview-for-windows-10-on-arm-pcs-to-the-windows-insider-program/
IsWindowsVersionOrGreater_BuildNumberCheck(HIBYTE(0x0A00), LOBYTE(0x0A00), 21277);
}

VERSIONHELPERAPI IsWindows11OrGreater(void) {
// Windows 11 shows up as "Windows 10 build 22000".
IsWindowsVersionOrGreater_BuildNumberCheck(HIBYTE(0x0A00), LOBYTE(0x0A00), 22000);
}

VERSIONHELPERAPI IsWindowsServer(void) {
OSVERSIONINFOEXW vi = {sizeof(vi),0,0,0,0,{0},0,0,0,VER_NT_WORKSTATION};
return !VerifyVersionInfoW(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL));
Expand Down
30 changes: 26 additions & 4 deletions src/svrplus/svrplus.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
#ifndef IMAGE_FILE_MACHINE_ARM64
# define IMAGE_FILE_MACHINE_ARM64 0xAA64
#endif
#ifndef IMAGE_FILE_MACHINE_ARM64EC
# define IMAGE_FILE_MACHINE_ARM64EC 0xA641
#endif

// Application resources.
#include "resource.h"
Expand Down Expand Up @@ -95,6 +98,7 @@ typedef enum {
CPU_ia64 = 3,
CPU_arm = 4,
CPU_arm64 = 5,
CPU_arm64ec = 6,

CPU_MAX
} SysArch;
Expand All @@ -111,6 +115,7 @@ static const s_arch_tbl_t s_arch_tbl[] = {
{_T("ia64"), NULL}, // CPU_ia64
{_T("arm"), NULL}, // CPU_arm
{_T("arm64"), _T("arm64")}, // CPU_arm64
{_T("arm64ec"), _T("arm64ec")}, // CPU_arm64ec
};

// Array of architectures to check
Expand Down Expand Up @@ -277,6 +282,7 @@ static int GetSystemDirFilePath(TCHAR *pszPath, size_t cchPath, const TCHAR *fil
HOST_ARCH_DIR(_T("Sysnative"), _T("System32")), // CPU_ia64
HOST_ARCH_DIR(_T("System32"), _T("SysWOW64")), // CPU_arm [TODO: Verify]
HOST_ARCH_DIR(_T("Sysnative"), _T("System32")), // CPU_arm64 [TODO: Verify]
HOST_ARCH_DIR(_T("Sysnative"), _T("System32")), // CPU_arm64ec [TODO: Verify]
};
static_assert(ARRAY_SIZE(system32_dir_tbl) == CPU_MAX, "system32_dir_tbl[] is out of sync with g_archs[]!");
system32_dir = system32_dir_tbl[arch];
Expand Down Expand Up @@ -1057,6 +1063,7 @@ static SysArch ifm_to_SysArch(USHORT ifm)
{IMAGE_FILE_MACHINE_THUMB, CPU_arm}, // TODO: Verify
{IMAGE_FILE_MACHINE_ARMNT, CPU_arm}, // TODO: Verify
{IMAGE_FILE_MACHINE_ARM64, CPU_arm64},
{IMAGE_FILE_MACHINE_ARM64EC, CPU_arm64ec},
};
static const ifm_to_cpu_tbl_t *const p_end = &ifm_to_cpu_tbl[ARRAY_SIZE(ifm_to_cpu_tbl)];
for (const ifm_to_cpu_tbl_t *p = ifm_to_cpu_tbl; p < p_end; p++) {
Expand Down Expand Up @@ -1134,11 +1141,26 @@ static int check_system_architectures(void)
g_archs[g_arch_count++] = CPU_arm;
break;
case CPU_arm64:
// NOTE: amd64 was added starting with Windows 10 Build 21277.
// Windows 10 on ARM RTM only supports i386 emulation.
// - Build 21277: Added amd64 emulation.
// - Build 22000 (Win11): Added arm64ec.
// https://blogs.windows.com/windows-insider/2020/12/10/introducing-x64-emulation-in-preview-for-windows-10-on-arm-pcs-to-the-windows-insider-program/
// TODO: Check for it!
g_archs[g_arch_count++] = CPU_amd64;
g_archs[g_arch_count++] = CPU_arm64;
if (IsWindows11OrGreater()) {
// Add arm64 and arm64ec.
g_archs[g_arch_count++] = CPU_arm64;
g_archs[g_arch_count++] = CPU_arm64ec;
} else if (IsWindows10Build21277OrGreater()) {
// Add amd64 and arm64.
g_archs[g_arch_count++] = CPU_amd64;
g_archs[g_arch_count++] = CPU_arm64;
} else {
// Just add arm64.
g_archs[g_arch_count++] = CPU_arm64;
}
break;
case CPU_arm64ec:
// Should not happen...
assert(!"System native architecture cannot be ARM64EC.");
break;
}
return 0;
Expand Down

1 comment on commit 92393c3

@kristibektashi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I was using build 22621 when I saw the error. The AMD64 version shouldn't be registered at all on ARM64 because the ARM64EC version substitutes it entirely (https://learn.microsoft.com/en-us/windows/arm/arm64ec). I also believe that build 21262 (a leaked build) first added ARM64EC support alongside x64 emulation, not 22000 or 21277.

On that note: ARM32 support was removed in build 25905, so the ARM32 DLL shouldn't be registered from that build onwards.

Please sign in to comment.