How to detect if your x86 application runs on Windows 10 on ARM?

How to detect if your x86 application runs on Windows 10 on ARM?

Windows 10 on ARM (in fact running on ARM64) will be released soon but no needs to worry, your x86 application has 99.9% of chance to run without problems on it if you don’t use drivers or advanced shell extensions.

How to and why detect if your application is running on ARM64?

For many reasons, it can interesting for a developer to know if the application runs on x86, x64 or ARM. Some example:
– install the correct driver
– disable some features on ARM
– analytics
– et…

If you are familiar with IsWowProcess, you already know how to detect if your x86 app runs on x64, but what about ARM64? If tested on a ARM64 device, this function will return True, not exactly what we expect.

In fact, it’s a common mistake, IsWowProcess doesn’t detect if your app runs on x64, but instead, it detects if your app uses WoW (Windows on Windows 64). The mistake was to think that WoW was only used for x64 architecture, it was mainly true but not fully, even if very rare, IA-64 architecture (Intel Itanium CPUs) was also supported (via a full emulation contrary to x64). In the case of Windows on ARM, Microsoft simply added a third version of WoW, “emulating” x86 on to top of ARM64.

IsWowProcess2

To detect the architecture, we will use a new function: IsWowProcess2.

Contrary to IsWowProcess this one doesn’t return a boolean but 2 unsigned shorts giving us more details about the architecture used and describing the physical processor and the emulated one.

Here is a sample application showing how to use IsWowProcess2 in your app!

#include "stdafx.h"
#include <windows.h>

typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS2)(HANDLE, PUSHORT, PUSHORT);


bool IsUsingWoW()
{
	BOOL isUsingWoW = FALSE;

	// We check if the OS is 64 Bit
	LPFN_ISWOW64PROCESS
		fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
			GetModuleHandle(L"kernel32"), "IsWow64Process");

	if (NULL != fnIsWow64Process)
	{
		if (!fnIsWow64Process(GetCurrentProcess(), &isUsingWoW))
		{
			throw "IsWow64Process is not available";
		}
	}
	return isUsingWoW;
}

bool IsRunningOnARM64()
{
	USHORT processMachine = 0;
	USHORT nativeMachine = 0;

	LPFN_ISWOW64PROCESS2 fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress(
			GetModuleHandle(L"kernel32"), "IsWow64Process2");

	if (NULL != fnIsWow64Process2)
	{
		if (!fnIsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine))
		{
			throw "IsWow64Process2 isn't available";
		}
	}
	return nativeMachine == 0xaa64;
}


int main()
{
	if (IsUsingWoW())
		printf("Is using WoW\n");
	else
		printf("Don't use WoW\n");

	if (IsRunningOnARM64())
		printf("Is ARM64 device\n");
	else
		printf("Not an ARM64 device\n");

	return 0;
}

Warning

The documentation of IsWow64Process2 says that this function is avalaible since Windows 10 1511 (TH2).

https://msdn.microsoft.com/en-us/library/windows/desktop/mt804318(v=vs.85).aspx

This is only partially true, the function header exists in it but the implementation is not available is only available since RS3, so be careful when you use it.

Comments are closed.