#47

wow64win: preserve class atoms in NtUserCreateWindowEx

Openalantangokwants to merge intofrom

Problem and change

On Madeira's nonzero WOW64 guest window, the final class argument of NtUserCreateWindowEx can be a 16-bit class atom. get_ptr() rebases it as a string pointer: the observed dialog atom 0x8002 became 0x400008002, and the host faulted while formatting/reading it in wine_dbgstr_wn during Age of Empires II: Forgotten Empires 2.2 startup.

Use the existing get_str_or_atom() helper, already used for window properties, for this argument. NULL stays NULL, atoms remain atoms, and real guest string pointers retain the existing conversion. This is specific to this fork's guest-address rebasing and is not an upstream Wine identity-mapping change.

Validation

  • python3 tools/tests/wow64win-create-window-atom.py: compiles the actual thunk and pointer helpers with a stubbed host call; covers NULL, atom boundaries, built-in/custom atoms, string pointers, and zero/nonzero guest bases. It fails the class-value assertion with the old get_ptr() call and passes with this change.
  • git diff --check passes.
  • On an M1 iPad Air, Madeira 0.1.3: an equivalent hash-guarded ARM64 binary edit to the bundled wow64win DLL removed the 0x8002 class-pointer crash. With separate game-specific DirectPlay/DirectDraw workarounds and intro skipping, FE reached a playable match, trained a villager, saved, and cold-loaded the saved match with Chinese text.
  • The source tree/IPA for this PR has not been fully rebuilt or device-tested. The host test isolates the conversion, not the entire Wine runtime. The game needs additional workarounds, so this one-line fix alone is not a claim of full game compatibility.

No game binaries, saves, IPAs, or proprietary DLLs are included. Implementation and test were AI-assisted; reviewed against this fork's existing helper and the observed fault. Submitted under LGPL-2.1-or-later with DCO sign-off.