I've tried implementing this before but importing user32 from ntdll isn't a reliable thing (so I recently rewrote it using the ntdll equivalents of LoadLibrary() and GetProcAddress())
Note: This is a weird way to implement this function (Windows implements this in ntdll instead) but that would probably require a user32/ntdll rewrite (so this is the next best tning to get the application working)
From: Aida Jonikienė aidas957@gmail.com
The Crinkler linker redirects the DefWindowProcA calls to the NtdllDefWindowProc_A function (which doesn't exist on Wine) and so it picks the first export in ntdll (which is A_SHAFinal right now) which obviously causes a segfault (this is problematic for the application listed in the bug report).
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53321 --- dlls/ntdll/misc.c | 32 ++++++++++++++++++++++++++++++++ dlls/ntdll/ntdll.spec | 1 + 2 files changed, 33 insertions(+)
diff --git a/dlls/ntdll/misc.c b/dlls/ntdll/misc.c index ab01c77531c..b5286fefd13 100644 --- a/dlls/ntdll/misc.c +++ b/dlls/ntdll/misc.c @@ -501,3 +501,35 @@ ULONG WINAPIV EtwTraceMessage( TRACEHANDLE handle, ULONG flags, LPGUID guid, /*U va_end( valist ); return ret; } + +/****************************************************************************** + * NtdllDefWindowProc_A (NTDLL.@) + */ +LRESULT WINAPI NtdllDefWindowProc_A( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + static LPARAM (WINAPI *pDefWindowProcA)(HWND,UINT,WPARAM,LPARAM); /* DefWindowProcA */ + + UNICODE_STRING name; + NTSTATUS status; + HMODULE module; + + if (pDefWindowProcA) return pDefWindowProcA( hwnd, msg, wParam, lParam ); + + RtlCreateUnicodeString( &name, L"user32.dll" ); + if (( status = LdrLoadDll( NULL, 0, &name, &module ))) + { + ERR("Failed to load user32.dll, status %ld\n", status); + if (name.Buffer) RtlFreeUnicodeString( &name ); + return 1; /* FIXME: Is this a good way to indicate failure? */ + } + + if (name.Buffer) RtlFreeUnicodeString( &name ); + pDefWindowProcA = RtlFindExportedRoutineByName( module, "DefWindowProcA" ); + if (!pDefWindowProcA) + { + ERR("Failed to load the function\n"); + return 1; + } + + return pDefWindowProcA( hwnd, msg, wParam, lParam ); +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 66995346e57..7dde0c91297 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -209,6 +209,7 @@ @ stdcall -syscall NtDeleteValueKey(long ptr) @ stdcall -syscall NtDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) @ stdcall -syscall NtDisplayString(ptr) +@ stdcall NtdllDefWindowProc_A(long long long long) @ stdcall -syscall NtDuplicateObject(long long long ptr long long long) @ stdcall -syscall NtDuplicateToken(long long ptr long long ptr) # @ stub NtEnumerateBootEntries
Jinoh Kang (@iamahuman) commented about dlls/ntdll/ntdll.spec:
@ stdcall -syscall NtDeleteValueKey(long ptr) @ stdcall -syscall NtDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) @ stdcall -syscall NtDisplayString(ptr) +@ stdcall NtdllDefWindowProc_A(long long long long)
Instead of implementing it as a stub, you can scrub the implementation and just use forwarders instead.[^1][^2]
```suggestion:-0+0 @ stdcall NtdllDefWindowProc_A(long long long long) user32.DefWindowProcA ```
[^1]: [Exported functions that are really forwarders - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20060719-24/?p=30473) [^2]: [DLL forwarding is not the same as delay-loading - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20080204-00/?p=23593)
Jinoh Kang (@iamahuman) commented about dlls/ntdll/ntdll.spec:
@ stdcall -syscall NtDeleteValueKey(long ptr) @ stdcall -syscall NtDeviceIoControlFile(long long ptr ptr ptr long ptr long ptr long) @ stdcall -syscall NtDisplayString(ptr) +@ stdcall NtdllDefWindowProc_A(long long long long)
Export symbols are case-sensitive: `Nta` goes after `NtZ` in lexicographical ordering.
This should go after `NtYieldExecution`, before `PfxFindPrefix`.
On Tue Mar 5 14:58:50 2024 +0000, Jinoh Kang wrote:
Export symbols are case-sensitive: `Nta` goes after `NtZ` in lexicographical ordering. This should go after `NtYieldExecution`, before `PfxFindPrefix`.
This will be fixed when the MR gets updated
On Tue Mar 5 14:55:56 2024 +0000, Jinoh Kang wrote:
Instead of implementing it as a stub, you can scrub the implementation and just use forwarders instead.[^1][^2]
@ stdcall NtdllDefWindowProc_A(long long long long) user32.DefWindowProcA
[^1]: [Exported functions that are really forwarders - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20060719-24/?p=30473) [^2]: [DLL forwarding is not the same as delay-loading - The Old New Thing](https://devblogs.microsoft.com/oldnewthing/20080204-00/?p=23593)
Unfortunately using this method doesn't work in this case (I get `0158:err:seh:dispatch_user_callback ignoring exception c0000005` when that function gets called)