From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/winproc.c | 16 ++++++++--- dlls/win32u/message.c | 1 + dlls/wow64win/user.c | 66 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 77 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index ab28eecb67c..a22262b037b 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -1176,12 +1176,13 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) { + LRESULT result, *result_ptr = params->result; + params->result = &result;
if (params->needs_unpack) { char stack_buffer[128]; void *buffer; - LRESULT result;
if (size > sizeof(*params)) { @@ -1196,8 +1197,6 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) if (!unpack_message( params->hwnd, params->msg, ¶ms->wparam, ¶ms->lparam, &buffer, size )) return 0; - params->result = &result; -
dispatch_win_proc_params( params );
@@ -1206,7 +1205,16 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) if (buffer != stack_buffer && buffer != params + 1) HeapFree( GetProcessHeap(), 0, buffer ); } - else dispatch_win_proc_params( params ); + else + { + dispatch_win_proc_params( params ); + if (result_ptr) + { + *result_ptr = result; + return TRUE; + } + NtCallbackReturn( &result, sizeof(result), TRUE ); + } return TRUE; }
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 55b67a08d8f..7fde0867462 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -265,6 +265,7 @@ static BOOL dispatch_win_proc_params( struct win_proc_params *params, size_t siz thread_info->recursion_count++;
KeUserModeCallback( NtUserCallWinProc, params, size, &ret_ptr, &ret_len ); + if (ret_len == sizeof(*params->result)) *params->result = *(LRESULT *)ret_ptr;
thread_info->recursion_count--; return TRUE; diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 6aecdacda39..8e0ab7bc68d 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -152,6 +152,23 @@ struct client_menu_name32 ULONG nameUS; };
+struct win_proc_params32 +{ + ULONG func; + ULONG hwnd; + UINT msg; + ULONG wparam; + ULONG lparam; + ULONG result; + BOOL ansi; + BOOL ansi_dst; + BOOL needs_unpack; + enum wm_char_mapping mapping; + ULONG dpi_awareness; + ULONG procA; + ULONG procW; +}; + static MSG *msg_32to64( MSG *msg, const MSG32 *msg32 ) { if (!msg32) return NULL; @@ -200,6 +217,25 @@ static struct client_menu_name32 *client_menu_name_64to32( const struct client_m return name32; }
+static void win_proc_params_64to32( const struct win_proc_params *src, struct win_proc_params32 *dst, + ULONG *result ) +{ + + dst->func = PtrToUlong( src->func ); + dst->hwnd = HandleToUlong( src->hwnd ); + dst->msg = src->msg; + dst->wparam = src->wparam; + dst->lparam = src->lparam; + dst->result = PtrToUlong( result ); + dst->ansi = src->ansi; + dst->ansi_dst = src->ansi_dst; + dst->needs_unpack = src->needs_unpack; + dst->mapping = src->mapping; + dst->dpi_awareness = HandleToUlong( src->dpi_awareness ); + dst->procA = PtrToUlong( src->procA ); + dst->procW = PtrToUlong( src->procW ); +} + static NTSTATUS dispatch_callback( ULONG id, void *args, ULONG len ) { void *ret_ptr; @@ -256,8 +292,34 @@ static NTSTATUS WINAPI wow64_NtUserCallWinEventHook( void *arg, ULONG size )
static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size ) { - FIXME( "\n" ); - return 0; + struct win_proc_params *params = arg; + struct win_proc_params32 params32_buf, *params32 = ¶ms32_buf; + LONG result32 = 0; + LRESULT result; + void *ret_ptr; + ULONG ret_len; + NTSTATUS status; + + if (size > sizeof(*params)) + { + if (!(params32 = Wow64AllocateTemp( size - sizeof(*params) + sizeof(*params32) ))) + return 0; + memcpy( params32 + 1, params + 1, size - sizeof(*params) ); + } + win_proc_params_64to32( params, params32, NULL ); + + status = Wow64KiUserCallbackDispatcher( NtUserCallWinProc, params32, + size - sizeof(*params) + sizeof(*params32), + &ret_ptr, &ret_len ); + if (ret_len == sizeof(result32)) result32 = *(LONG *)ret_ptr; + result = result32; + + if (params->result) + { + *params->result = result; + return status; + } + return NtCallbackReturn( &result, sizeof(result), status ); }
static NTSTATUS WINAPI wow64_NtUserCallWindowsHook( void *arg, ULONG size )