commit 4972fabba208c3715b31dd32a7f9d4e9a175cb55
parent 3a4d0071b6d1e3aad1bca0fc8b0f0a59d1c9ba79
Author: JohnMcPMS <johnmcp@microsoft.com>
Date: Wed, 8 Sep 2021 11:17:49 -0700
Support for x64 on ARM64 (#1441)
This change fixes #666 by implementing dynamic loading of the API and invoking it specifically for x64 when the machine is ARM64. The API can replace our current use of `IsWow64GuestMachineSupported`, but there is no need to take the additional risk of that change at this time.
Diffstat:
2 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
@@ -130,6 +130,7 @@ hhx
HINSTANCE
hkey
hlocal
+hmodule
hre
hresults
htm
@@ -246,6 +247,7 @@ pkindex
PMS
positionals
powertoys
+processthreads
productcode
pseudocode
pvk
diff --git a/src/AppInstallerCommonCore/Architecture.cpp b/src/AppInstallerCommonCore/Architecture.cpp
@@ -21,6 +21,60 @@ namespace AppInstaller::Utility
}
}
+ // These types are defined in a future SDK and can be removed when we actually have them available.
+ // The exception is that None was added (and this is an enum class).
+ enum class MACHINE_ATTRIBUTES {
+ None = 0,
+ UserEnabled = 0x00000001,
+ KernelEnabled = 0x00000002,
+ Wow64Container = 0x00000004
+ };
+
+ DEFINE_ENUM_FLAG_OPERATORS(MACHINE_ATTRIBUTES);
+
+ using GetMachineTypeAttributesPtr = HRESULT(WINAPI*)(USHORT Machine, MACHINE_ATTRIBUTES* MachineTypeAttributes);
+
+ // GetMachineTypeAttributes can apparently replace IsWow64GuestMachineSupported, but no reason to do so right now.
+ struct GetMachineTypeAttributesHelper
+ {
+ GetMachineTypeAttributesHelper()
+ {
+ m_module.reset(LoadLibraryEx(L"api-ms-win-core-processthreads-l1-1-7.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32));
+ if (!m_module)
+ {
+ AICLI_LOG(Core, Verbose, << "Could not load api-ms-win-core-processthreads-l1-1-7.dll");
+ return;
+ }
+
+ m_getMachineTypeAttributes =
+ reinterpret_cast<GetMachineTypeAttributesPtr>(GetProcAddress(m_module.get(), "GetMachineTypeAttributes"));
+ if (!m_getMachineTypeAttributes)
+ {
+ AICLI_LOG(Core, Verbose, << "Could not get proc address of GetMachineTypeAttributes");
+ return;
+ }
+ }
+
+ void AddArchitectureIfMachineTypeAttributesUserEnabled(std::vector<Architecture>& target, Architecture architecture, USHORT guestMachine)
+ {
+ if (m_getMachineTypeAttributes)
+ {
+ MACHINE_ATTRIBUTES attributes = MACHINE_ATTRIBUTES::None;
+ if (SUCCEEDED_LOG(m_getMachineTypeAttributes(guestMachine, &attributes)))
+ {
+ if (WI_IsFlagSet(attributes, MACHINE_ATTRIBUTES::UserEnabled))
+ {
+ target.push_back(architecture);
+ }
+ }
+ }
+ }
+
+ private:
+ wil::unique_hmodule m_module;
+ GetMachineTypeAttributesPtr m_getMachineTypeAttributes = nullptr;
+ };
+
// Gets the applicable architectures for the current machine.
std::vector<Architecture> CreateApplicableArchitecturesVector()
{
@@ -29,10 +83,15 @@ namespace AppInstaller::Utility
switch (GetSystemArchitecture())
{
case Architecture::Arm64:
+ {
+ GetMachineTypeAttributesHelper helper;
+
applicableArchs.push_back(Architecture::Arm64);
AddArchitectureIfGuestMachineSupported(applicableArchs, Architecture::Arm, IMAGE_FILE_MACHINE_ARMNT);
+ helper.AddArchitectureIfMachineTypeAttributesUserEnabled(applicableArchs, Architecture::X64, IMAGE_FILE_MACHINE_AMD64);
AddArchitectureIfGuestMachineSupported(applicableArchs, Architecture::X86, IMAGE_FILE_MACHINE_I386);
applicableArchs.push_back(Architecture::Neutral);
+ }
break;
case Architecture::Arm:
applicableArchs.push_back(Architecture::Arm);