Level 0 · Chapter 4
WOW64 and cross-architecture compatibility
How 32-bit user-mode applications keep running on a 64-bit kernel, two decades after 64-bit Windows shipped.
The DLL loader assumed a process is either fully 32-bit or fully 64-bit, loading only DLLs that match. WOW64 — "Windows on Windows 64" — is the layer that makes that assumption safe to make, even when a 32-bit program runs on a machine whose kernel, drivers, and most other processes are all native 64-bit code.
Why this had to exist
When 64-bit Windows shipped, the practical reality was that almost no software existed for it yet. Microsoft's answer wasn't "recompile everything" — it was "make the existing 32-bit binaries work, unmodified, as a first-class experience." Two decades later, WOW64 is still there, still actively maintained, and still the reason a 32-bit installer from 2009 can run today on a machine whose kernel has never been 32-bit.
The core design decision: the kernel itself stays entirely native 64-bit. There is no 32-bit kernel mode on 64-bit Windows. All the translation work happens in user mode, which keeps the kernel simple and means a 32-bit process can't accidentally rely on any 32-bit kernel behavior that doesn't exist.
What actually runs where
A 32-bit process on 64-bit Windows has:
- A 32-bit image (the EXE), loaded and relocated exactly as described in the DLL loader chapter — but only ever linked against 32-bit DLLs, from a parallel
System32-equivalent directory (confusingly namedSysWOW64— the "native" 64-bitSystem32is off-limits to it). - A WOW64 support layer —
wow64.dll,wow64win.dll,wow64cpu.dll— loaded alongside the 32-bit runtime, invisible to the 32-bit code itself. - Address space limited to the low 2 GB (or up to 4 GB, if the image opts in) by default, since 32-bit pointers can only address that much regardless of what the underlying 64-bit hardware could support.
The actual translation: what happens at a syscall
The interesting mechanics happen exactly at the point Ntdll & the user/kernel boundary describes: the transition from user mode into the kernel. A 32-bit program still calls what looks like an ordinary 32-bit Nt* function in its own 32-bit ntdll.dll. But instead of executing a 32-bit syscall/sysenter instruction directly, that call is redirected into wow64cpu.dll, which:
- Marshals the arguments. 32-bit calling conventions and structure layouts don't match 64-bit ones — pointers are half the size, some structures have different alignment. Every argument has to be widened and repacked into the layout the native 64-bit kernel expects.
- Switches processor mode. The thread transitions from 32-bit (compatibility) mode to full 64-bit mode for the duration of the kernel call.
- Issues the real, native 64-bit system call, using the exact same kernel entry point a native 64-bit process would use — the kernel has no idea it's servicing a translated call; from its point of view this is an ordinary 64-bit request.
- Marshals the results back into 32-bit-shaped output on return, and switches the processor back to 32-bit mode before returning control to the caller.
This is why WOW64 is accurately described as a thunk layer, not an emulator in the traditional sense: it doesn't reinterpret 32-bit machine instructions one by one (that would be far too slow for routine syscalls) — it lets 32-bit user-mode code run directly on the CPU at full speed, and only intervenes at the narrow, well-defined boundary where a mode transition into the kernel would otherwise happen.
Keeping two worlds from colliding
Because 32-bit and 64-bit code can't share pointers or structure layouts, Windows goes out of its way to keep them from mixing by accident:
- File system redirection: a 32-bit process reading from
%windir%\System32is transparently redirected to%windir%\SysWOW64, so it never sees native 64-bit binaries it couldn't load anyway. (Sysnativeis the explicit escape hatch for a 32-bit process that deliberately needs to reach the realSystem32.) - Registry redirection: similarly,
HKLM\Softwarereads and writes for a 32-bit process are redirected toHKLM\Software\WOW6432Node, so 32-bit and 64-bit installations of the same product don't stomp on each other's settings. - Separate module lists: the loader mechanisms from the previous chapter run entirely within one architecture's world at a time — a 32-bit process's
PEB_LDR_DATAonly ever lists 32-bit modules.
A common mistake
It's tempting to imagine WOW64 as "a whole emulated 32-bit operating system living inside the real one." It isn't — there's exactly one kernel, and it's always native. WOW64 is a translation and redirection layer that lets 32-bit user-mode code coexist with a 64-bit kernel and 64-bit siblings, not an independent OS-within-an-OS. Everything privileged — scheduling, memory management, security checks — is still handled by the same 64-bit Executive every other process on the machine uses.
Where this connects
- The mode switch this chapter describes happens at exactly the boundary Ntdll & the user/kernel boundary covers for native processes — WOW64 adds one more hop before that same boundary, not a different one.
- ARM64 Windows uses a conceptually similar mechanism (and a genuine instruction-level emulator, for x86 code specifically) to run both 32-bit and 64-bit x86 applications on ARM hardware — the marshaling problem is the same, even though the underlying translation technique differs.