A set of tools and technologies that enable developers to build, optimize, and deploy applications and services within the Windows ecosystem.
The supported practical workaround is to run the debugger as x86 or move the suspend/context operation into an ARM64-native component; the documented API contract provides no separate x64-emulated-on-ARM64 suspension API.
This appears to violate the documented contract
Your target is an x86 process running under WOW64 on ARM64. Microsoft documents that:
- WOW64 supports 32-bit x86 applications on ARM64 Windows.^1^
-
Wow64SuspendThreadsuspends a WOW64 thread, is intended for 64-bit applications, and requires a thread handle withTHREAD_SUSPEND_RESUMEaccess.^2^ -
Wow64GetThreadContextrequires the WOW64 thread to be suspended withWow64SuspendThread; otherwise, a valid context cannot be obtained.^3^
Your CreateProcess thread handle has the required access, the target is genuinely x86/WOW64, and the same operation succeeds from ARM64. Therefore, ERROR_INVALID_PARAMETER from the emulated x64 build is not explained by a documented caller, target, or access restriction.
No public issue or Microsoft document in the available material confirms the particular RtlWow64SuspendThread/ARM64EC callback failure or lists build 26300.9711 as affected. The internal offsets and callback behavior you identified are undocumented implementation details and should not be used as a production workaround.
Supported implementation options
1. Build the debugger as x86
For x86 user-mode applications on ARM64, Microsoft recommends using the x86 version of the debugger. An x86 caller can use ordinary SuspendThread and GetThreadContext; the documentation states that calls to the WOW64 variants from a 32-bit application have the same result as those ordinary APIs.^4^
This is the cleanest choice if the debugger only handles x86 targets.
2. Build the debugger or an out-of-process helper as ARM64
If one debugger must handle several architectures, keep the main x64 application if necessary but delegate the x86 thread suspend/context operation to an ARM64-native helper. Your test already establishes that this path works on the affected build.
The helper should:
- Receive the target PID/TID over IPC.
- Open the thread with at least
THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT. - Call
Wow64SuspendThread. - Initialize
WOW64_CONTEXT.ContextFlags. - Call
Wow64GetThreadContext. - Call
ResumeThread. - Return the captured context to the main process.
For example:
HANDLE thread = OpenThread(
THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT,
FALSE, threadId);
DWORD previous = Wow64SuspendThread(thread);
if (previous == (DWORD)-1)
return GetLastError();
WOW64_CONTEXT context{};
context.ContextFlags = WOW64_CONTEXT_ALL;
BOOL captured = Wow64GetThreadContext(thread, &context);
DWORD error = captured ? ERROR_SUCCESS : GetLastError();
ResumeThread(thread);
CloseHandle(thread);
return error;
Suspending arbitrary threads can deadlock a process if they own synchronization objects, so this mechanism should remain debugger-only.^2^
Do not silently replace it with SuspendThread in the x64 build
SuspendThread does suspend a specified thread and requires the same suspend/resume access.^5^ However, Microsoft explicitly directs 64-bit callers to Wow64SuspendThread for WOW64 threads, and Wow64GetThreadContext specifically says to suspend with that function. Consequently, this sequence is not a documented equivalent:
SuspendThread(thread);
Wow64GetThreadContext(thread, &context);
It may be useful as a diagnostic experiment, but it should not be treated as a supported workaround for obtaining a reliable x86 context.
Report the Windows defect
Submit a Feedback Hub recording and, for a debugger product, open a Microsoft support case. Include:
- Windows edition and full build number.
- Native machine type and caller/target machine types from
IsWow64Process2. - The minimal x64 and ARM64 binaries.
- Return values from
Wow64SuspendThreadandGetLastError. - Confirmation that the identical target succeeds from ARM64.
- A trace or dump captured during the failed call.
- Your observed ARM64EC/native divergence, clearly identified as analysis of undocumented internals.
Microsoft’s support guidance asks for the application/component topology, relevant logs, and exact reproduction steps.^6^
References