Comment by cyberax

5 days ago

This approach was used in the ATL/WTL (Active Template Library, Windows Template Library) in the early 2000-s. It was a bad idea, because you need to generate executable code, interfering with NX-bit memory protection.

Windows actually had a workaround in its NX-bit implementation that recognized the byte patterns of these trampolines from the fault handler: https://web.archive.org/web/20090123222148/http://support.mi...

I'm genuinely surprised Microsoft's attitude towards "wndprocs don't have a context pointer" was "let's JIT compile a trampoline to hold the context pointer" and not to add support for a five-parameter wndproc into USER.dll, or have a wrapper that grabs GWLP_USERDATA and copies it to the register this lives in.

  • > I'm genuinely surprised Microsoft's attitude towards "wndprocs don't have a context pointer"

    They designed windows classes to be reusable, and assumed many developers going to reuse windows classes across windows.

    Consider the following use case. Programmer creates a window class for a custom control, registers the class. Designs a dialog template with multiple of these custom controls in a single dialog. Then creates the dialog by calling DialogBoxW or similar.

    These custom controls are created automatically multiple at once, hard to provide context pointers for each control.

  • Doesn't x32 only have four registers available in the calling convention, AX-DX?

    • The stdcall calling convention used APIs and API callbacks on Windows x86 doesn't use registers at all, all parameters are passed on the stack. MSVC does support thiscall/fastcall/vectorcall conventions that pass some values in registers, but the system APIs and COM interfaces all use stdcall.

      Windows x64 and ARM64 do use register passing, with 4 registers for x64 (rcx/rdx/r8/r9) and 8 registers for ARM64 (x0-x7). Passing an additional parameter on the stack would be cheap compared to the workarounds that everyone has to do now.

    • The x32 ABI uses the same fastcall convention as the regular x86-64 ABI. It's mostly syscall numbers that are affected by the shrunk pointers.