WoW64サブシステムとARM64 ♯2

前回の投稿で、WoW64の説明と関連するAPIのテストツールについて説明しました。今回は、各APIの振る舞を各Windows上で確認します。

WoW64に関するテストツールと動作環境

前回の投稿で説明した、WoW64に関連する5つのAPIを確認するテストツールを使って、APIの振る舞いを確認します。このテストツールは、このサイトのツールのページで公開しています。

WoW64 Test App (x64) on Windows 11 (x64)

前回に説明したようにx86 / x64 / ARM32 / ARM64 のCPUアーキテクチャーでビルドしたアプリの各Windowsシステムでの動作可否は以下のようになります。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
可 (Native)
64ビットWindows 10
on x64 CPU
可 (Native)
64ビットWindows 11
on x64 CPU
可 (Native)
64ビットWindows 10
on ARM64 CPU
可 (Native)
64ビットWindows 11
on ARM64 CPU
可 (Native)
各CPUアーキテクチャーでビルドしたアプリの動作の可否

「可」の部分のリンクは、実行したアプリのスクリーンショットへのリンクとなります。実行画面を確認したい場合はリンクをクリックしてください。


これらの動作可能なパターンの各APIの挙動を確認します。

GetSystemInfo()

VOID
GetSystemInfo(
    _Out_ LPSYSTEM_INFO lpSystemInfo);

GetSystemInfo()は、実行中のプロセスがどのシステム上で動作しているかを確認することができます。WindowsのNativeのシステム情報ではなく、あくまで実行中のプロセスがどのシステム(または、サブシステム)で動作しているかの情報です。WoW64サブシステム上で動作している場合は、そのサブシステムの情報となります。

lpSystemInfo->wProcessorArchitecture や lpSystemInfo->dwProcessorType でCPUアーキテクチャが確認できます。

実行結果は以下の通りとなりました。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
INTEL (0)
INTEL_PENTIUM (586)
64ビットWindows 10
on x64 CPU
INTEL (0)
INTEL_PENTIUM (586)
AMD64 (9)
AMD_X8664 (8664)
64ビットWindows 11
on x64 CPU
INTEL (0)
INTEL_PENTIUM (586)
AMD64 (9)
AMD_X8664 (8664)
64ビットWindows 10
on ARM64 CPU
INTEL (0)
INTEL_PENTIUM (586)
ARM (5)
unknown (0)
ARM64 (12)
unknown (0)
64ビットWindows 11
on ARM64 CPU
INTEL (0)
INTEL_PENTIUM (586)
AMD64 (9)
AMD_X8664 (8664)
ARM (5)
unknown (0)
ARM64 (12)
unknown (0)
GetSystemInfo()の実行結果(wProcessorArchitecture と dwProcessorType)

現在実行しているプロセスの情報であるため、Windowsの種類が異なっても、各アプリが取得できる情報は同じとなりました。

これらの振る舞いは、APIリファレンスに記載されている振舞と同じです。

GetNativeSystemInfo()

VOID
GetNativeSystemInfo(
    _Out_ LPSYSTEM_INFO lpSystemInfo);

GetNativeSystemInfo()は、Windowsがどのシステム上で動作しているかを確認することができます。プロセスのシステム情報ではなく、Windowsのシステム情報です。実行中のプロセスがWoW64サブシステム上で動作していたとしても、Windowsのシステム情報が取得できます。ただし、完全に系統が異なるCPUアーキテクチャー上のWoW64サブシステム上でアプリが動作している場合(たとえば、ARM64のWindowsシステム上でx86アプリやx64アプリが動作している場合)は、アプリの実行サブシステムと同じ情報が返されます。

lpSystemInfo->wProcessorArchitecture や lpSystemInfo->dwProcessorType でCPUアーキテクチャが確認できます。

実行結果は以下の通りとなりました。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
INTEL (0)
INTEL_PENTIUM (586)
64ビットWindows 10
on x64 CPU
AMD64 (9)
AMD_X8664 (8664)
AMD64 (9)
AMD_X8664 (8664)
64ビットWindows 11
on x64 CPU
AMD64 (9)
AMD_X8664 (8664)
AMD64 (9)
AMD_X8664 (8664)
64ビットWindows 10
on ARM64 CPU
INTEL (0)
INTEL_PENTIUM (586)
ARM64 (12)
unknown (0)
ARM64 (12)
unknown (0)
64ビットWindows 11
on ARM64 CPU
AMD64 (9)
INTEL_PENTIUM (586)
AMD64 (9)
AMD_X8664 (8664)
ARM64 (12)
unknown (0)
ARM64 (12)
unknown (0)
GetNativeSystemInfo()の実行結果(wProcessorArchitecture と dwProcessorType)

プロセスの実行をホストしているWindowsの情報であるため、アプリの種類が異なっても、各アプリが取得できる情報は、WindowsのCPUアーキテクチャーがアプリのCPUアーキテクチャーが同系の場合は同じとなりました。CPUアーキテクチャーが異なる場合は、アプリのCPUアーキテクチャーと同じ値が取得できます。

これらの振る舞いは、APIリファレンスに記載されている振舞と同じです。

IsWow64Process()

BOOL
IsWow64Process(
    _In_ HANDLE hProcess,
    _Out_ PBOOL Wow64Process);

IsWow64Process()は、実行中のプロセスが、WoW64サブシステム上で動作しているかを確認することができます。ただし、系統が異なるCPUアーキテクチャー上のWoW64サブシステム上でアプリが動作している場合(たとえば、ARM64のWindowsシステム上でx86アプリやx64アプリが動作している場合)は、FALSEが返ります。

そのため、Windowsとアプリで系統が異なるCPUアーキテクチャーの場合は、WoW64サブシステム上で動作しているかどうかは、正しく判定できません。

実行結果は以下の通りとなりました。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
FALSE
64ビットWindows 10
on x64 CPU
TRUEFALSE
64ビットWindows 11
on x64 CPU
TRUEFALSE
64ビットWindows 10
on ARM64 CPU
FALSEFALSEFALSE
64ビットWindows 11
on ARM64 CPU
TRUEFALSETRUEFALSE
IsWow64Process()の実行結果

各環境上での挙動は、ほぼAPIリファレンスと同じです。

[out] PBOOL Wow64Process
A pointer to a value that is set to TRUE if the process is running under WOW64 on an Intel64 or x64 processor. If the process is running under 32-bit Windows, the value is set to FALSE. If the process is a 32-bit application running under 64-bit Windows 10 on ARM, the value is set to FALSE. If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE.

IsWow64Process() の Parameters (Microsoftのサイトより、2022/06/12時点の情報)

と書かれています。

[out] PBOOL Wow64Process
値を保存する変数へのポインタ。プロセスがIntel64またはx64プロセッサ上のWOW64で動作している場合、この値はTRUEに設定される。プロセスが32ビットWindowsの下で実行されている場合、この値はFALSEに設定される。プロセスがARM上の64ビットWindows 10で実行されている32ビットアプリの場合、この値はFALSEに設定されます。プロセスが64ビットWindowsの下で実行されている64ビットアプリである場合、この値もFALSEに設定されます。

実行結果は、「64ビットWindows 11 on ARM64 CPU」以外については、APIリファレンス通りとなります。

しかし、Windows 11 on ARM64の挙動がWindows 10と異なるようです。アプリがx86かARM32であるかは問わず32ビットアプリの場合は、TRUEが返るようになっています。APIリファレンスにはWindows 11での挙動が記載されていないため、この値が正常な値なのかどうかは、わかりません。

IsWow64Process2()

BOOL
IsWow64Process2(
    _In_ HANDLE hProcess,
    _Out_ USHORT* pProcessMachine,
    _Out_opt_ USHORT* pNativeMachine);

IsWow64Process2()は、IsWow64Process()の機能を改善し、IsWow64Process()を置き換えるために設計されています。実行中のプロセスが、どのWoW64サブシステム上で動作しているかとWindowsがどのシステムで動作しているかを確認することができます。

WoW64サブシステム上で動作している場合は、サブシステムの情報がpProcessMachineに得られます。WoW64サブシステム上で動作していないときは、0x0000 (UNKNOWN) が得られます。

Windowsのシステム情報は、WoW64サブシステム上で動作しているかどうかにかかわらず、pNativeMachineに得られます。

GetNativeSystemInfo()とは異なり、Windowsとアプリで系統が異なるCPUアーキテクチャであっても正しい情報が取得できます。

実行結果は以下の通りとなりました。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
0x0000 (UNKNOWN)
0x014c (I386)
64ビットWindows 10
on x64 CPU
0x014c (I386)
0x8664 (AMD64)
0x0000 (UNKNOWN)
0x8664 (AMD64)
64ビットWindows 11
on x64 CPU
0x014c (I386)
0x8664 (AMD64)
0x0000 (UNKNOWN)
0x8664 (AMD64)
64ビットWindows 10
on ARM64 CPU
0x014c (I386)
0xaa64 (ARM64)
0x01c4 (ARMNT)
0xaa64 (ARM64)
0x0000 (UNKNOWN)
0xaa64 (ARM64)
64ビットWindows 11
on ARM64 CPU
0x014c (I386)
0xaa64 (ARM64)
0x0000 (UNKNOWN)
0xaa64 (ARM64)
0x01c4 (ARMNT)
0xaa64 (ARM64)
0x0000 (UNKNOWN)
0xaa64 (ARM64)
IsWow64Process2()の実行結果

この結果から分かることは、pProcessMachineの値は、Nativeアプリ以外はすべて0x0000 (UNKNOWN)以外の値が設定されており、エミュレーション実行されているものはすべてWoW64サブシステムで動作していることを表す値となっています。

このことから、WoW64は当初は「Windows 32-bit on Windows 64-bit」であったものが、「Windows on Windows 64-bit」に定義を変えたことを示しているのかもしれません。

結果として、このAPIは、どのCPUアーキテクチャーでビルドしたアプリであったとしても、また、どのWindowsシステム上で実行されたとしても、プロセスの情報とシステムの情報を一番正しく返すAPIであることがわかります。

IsWow64GuestMachineSupported()

HRESULT
IsWow64GuestMachineSupported(
    _In_ USHORT WowGuestMachine,
    _Out_ BOOL* MachineIsSupported);

IsWow64GuestMachineSupported()は、実行中のプロセスの動作環境に関係なく、WindowsのWoW64サブシステムがどのCPUアーキテクチャーをサポートしているかを確認することができます。

WowGuestMachineで指定したゲストマシン(アプリのアーキテクチャ)のWoW64サブシステム上での実行(エミュレーション実行)がサポートされているかどうかが、MachineIsSupportedに得られます。

実行結果は以下の通りとなりました。

x86アプリx64アプリARM32アプリARM64アプリ
32ビットWindows 10
on x64 CPU
none
64ビットWindows 10
on x64 CPU
0x014c (I386)0x014c (I386)
64ビットWindows 11
on x64 CPU
0x014c (I386)0x014c (I386)
64ビットWindows 10
on ARM64 CPU
0x014c (I386)
0x01c4 (ARMNT)
0x014c (I386)
0x01c4 (ARMNT)
0x014c (I386)
0x01c4 (ARMNT)
64ビットWindows 11
on ARM64 CPU
0x014c (I386)
0x01c4 (ARMNT)
0x014c (I386)
0x01c4 (ARMNT)
0x014c (I386)
0x01c4 (ARMNT)
0x014c (I386)
0x01c4 (ARMNT)
IsWow64GuestMachineSupported()の実行結果

このAPIが返す値は、実行中のプロセスのアーキテクチャには依存しない情報なので、同じWindowsであれば、すべてのアプリで同じ値となります。実際に、表の横方向の値は同じ値になっています。

ただし、気になる点が一つあります。Windows 11 on ARM64では、x64アプリもエミュレーション実行できるにもかかわらず、このAPIでは、x64アプリのエミュレーション実行はサポートしていないと値が返されることです。

これは、仕様なのかバグなのかはよくわかりません。


以上、今回の投稿では、WoW64に関連するAPIを、各CPUアーキテクチャーでビルドしたアプリを使い、各CPUアーキテクチャーのWindows上での振る舞いを確認しました。

一部、仕様なのかバグなのかわからない挙動もありましたが、現時点(2022/06/12)での挙動はわかりました。

“WoW64サブシステムとARM64 ♯2” への1件の返信

コメントを残す