From: Jacek Caban jacek@codeweavers.com
Instead of leaking kernel pointers. --- dlls/win32u/message.c | 218 +++++++++++++++++++++++++++++++++-- dlls/win32u/ntuser_private.h | 9 -- 2 files changed, 209 insertions(+), 18 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index f1ff3da2cd6..d41b68122bb 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -47,6 +47,18 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
#define MAX_PACK_COUNT 4
+/* info about the message currently being received by the current thread */ +struct received_message_info +{ + UINT type; + MSG msg; + UINT flags; /* InSendMessageEx return flags */ + LRESULT result; + struct received_message_info *prev; +}; + +#define MSG_CLIENT_MESSAGE 0xff + struct packed_hook_extra_info { user_handle_t handle; @@ -1029,6 +1041,117 @@ static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, } }
+/*********************************************************************** + * copy_reply + * + * Copy a message reply received from client. + */ +static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, + WPARAM wparam_src, LPARAM lparam_src ) +{ + size_t copy_size = 0; + + switch(message) + { + case WM_NCCREATE: + case WM_CREATE: + { + CREATESTRUCTW *dst = (CREATESTRUCTW *)lparam; + CREATESTRUCTW *src = (CREATESTRUCTW *)lparam_src; + dst->lpCreateParams = src->lpCreateParams; + dst->hInstance = src->hInstance; + dst->hMenu = src->hMenu; + dst->hwndParent = src->hwndParent; + dst->cy = src->cy; + dst->cx = src->cx; + dst->y = src->y; + dst->x = src->x; + dst->style = src->style; + dst->dwExStyle = src->dwExStyle; + /* don't allow changing name and class pointers */ + } + return; + case WM_GETTEXT: + case CB_GETLBTEXT: + case LB_GETTEXT: + copy_size = (result + 1) * sizeof(WCHAR); + break; + case WM_GETMINMAXINFO: + copy_size = sizeof(MINMAXINFO); + break; + case WM_MEASUREITEM: + copy_size = sizeof(MEASUREITEMSTRUCT); + break; + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + copy_size = sizeof(WINDOWPOS); + break; + case WM_STYLECHANGING: + copy_size = sizeof(STYLESTRUCT); + break; + case WM_GETDLGCODE: + if (lparam) copy_size = sizeof(MSG); + break; + case SBM_GETSCROLLINFO: + copy_size = sizeof(SCROLLINFO); + break; + case SBM_GETSCROLLBARINFO: + copy_size = sizeof(SCROLLBARINFO); + break; + case EM_GETRECT: + case LB_GETITEMRECT: + case CB_GETDROPPEDCONTROLRECT: + case WM_SIZING: + case WM_MOVING: + copy_size = sizeof(RECT); + break; + case EM_GETLINE: + { + WORD *ptr = (WORD *)lparam; + copy_size = ptr[-1] * sizeof(WCHAR); + break; + } + case LB_GETSELITEMS: + copy_size = wparam * sizeof(UINT); + break; + case WM_MDIGETACTIVE: + if (lparam) copy_size = sizeof(BOOL); + break; + case WM_NCCALCSIZE: + if (wparam) + { + NCCALCSIZE_PARAMS *dst = (NCCALCSIZE_PARAMS *)lparam; + NCCALCSIZE_PARAMS *src = (NCCALCSIZE_PARAMS *)lparam_src; + dst->rgrc[0] = src->rgrc[0]; + dst->rgrc[1] = src->rgrc[1]; + dst->rgrc[2] = src->rgrc[2]; + *dst->lppos = *src->lppos; + return; + } + copy_size = sizeof(RECT); + break; + case EM_GETSEL: + case SBM_GETRANGE: + case CB_GETEDITSEL: + if (wparam) *(DWORD *)wparam = *(DWORD *)wparam_src; + if (lparam) copy_size = sizeof(DWORD); + break; + case WM_NEXTMENU: + copy_size = sizeof(MDINEXTMENU); + break; + case WM_MDICREATE: + copy_size = sizeof(MDICREATESTRUCTW); + break; + case WM_ASKCBFORMATNAME: + copy_size = (lstrlenW((WCHAR *)lparam) + 1) * sizeof(WCHAR); + break; + default: + return; + } + + if (copy_size) memcpy( (void *)lparam, (void *)lparam_src, copy_size ); +} + /*********************************************************************** * reply_message * @@ -1074,6 +1197,7 @@ BOOL reply_message_result( LRESULT result ) struct user_thread_info *thread_info = get_user_thread_info(); struct received_message_info *info = thread_info->receive_info;
+ while (info && info->type == MSG_CLIENT_MESSAGE) info = info->prev; if (!info) return FALSE; reply_message( info, result, NULL ); return TRUE; @@ -1092,6 +1216,13 @@ static BOOL reply_winproc_result( LRESULT result, HWND hwnd, UINT message, WPARA
if (!info) return FALSE;
+ if (info->type == MSG_CLIENT_MESSAGE) + { + copy_reply( result, hwnd, message, info->msg.wParam, info->msg.lParam, wparam, lparam ); + info->result = result; + return TRUE; + } + msg.hwnd = hwnd; msg.message = message; msg.wParam = wparam; @@ -1221,8 +1352,12 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar return 0; }
- params->needs_unpack = needs_unpack; - if (size) memcpy( params + 1, buffer, size ); + if (needs_unpack) + { + params->needs_unpack = TRUE; + params->ansi = FALSE; + if (size) memcpy( params + 1, buffer, size ); + }
/* first the WH_CALLWNDPROC hook */ cwp.lParam = lparam; @@ -2608,6 +2743,7 @@ static BOOL broadcast_message( struct send_message_info *info, DWORD_PTR *res_pt switch(info->type) { case MSG_UNICODE: + case MSG_OTHER_PROCESS: send_message_timeout( list[i], info->msg, info->wparam, info->lparam, info->flags, info->timeout, FALSE ); break; @@ -2641,6 +2777,48 @@ static BOOL broadcast_message( struct send_message_info *info, DWORD_PTR *res_pt return TRUE; }
+static BOOL process_packed_message( struct send_message_info *info, LRESULT *res_ptr, BOOL ansi ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + struct received_message_info receive_info; + struct packed_message data; + size_t buffer_size = 0, i; + void *buffer = NULL; + char *ptr; + + pack_message( info->hwnd, info->msg, info->wparam, info->lparam, &data ); + if (data.count == -1) return FALSE; + + for (i = 0; i < data.count; i++) buffer_size += data.size[i]; + if (!(buffer = malloc( buffer_size ))) return FALSE; + for (ptr = buffer, i = 0; i < data.count; i++) + { + memcpy( ptr, data.data[i], data.size[i] ); + ptr += data.size[i]; + } + + receive_info.type = MSG_CLIENT_MESSAGE; + receive_info.msg.hwnd = info->hwnd; + receive_info.msg.message = info->msg; + receive_info.msg.wParam = info->wparam; + receive_info.msg.lParam = info->lparam; + receive_info.flags = 0; + receive_info.prev = thread_info->receive_info; + receive_info.result = 0; + thread_info->receive_info = &receive_info; + + *res_ptr = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam, + !ansi, TRUE, info->wm_char, TRUE, buffer, buffer_size ); + if (thread_info->receive_info == &receive_info) + { + thread_info->receive_info = receive_info.prev; + *res_ptr = receive_info.result; + } + free( buffer ); + return TRUE; +} + + /*********************************************************************** * process_message * @@ -2652,7 +2830,7 @@ static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr, INPUT_MESSAGE_SOURCE prev_source = thread_info->msg_source; DWORD dest_pid; BOOL ret; - LRESULT result; + LRESULT result = 0;
if (is_broadcast( info->hwnd )) return broadcast_message( info, res_ptr );
@@ -2672,7 +2850,13 @@ static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr, thread_info->msg_source = msg_source_unavailable; spy_enter_message( SPY_SENDMESSAGE, info->hwnd, info->msg, info->wparam, info->lparam );
- if (info->dest_tid == GetCurrentThreadId()) + if (info->dest_tid != GetCurrentThreadId()) + { + if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE)) + info->type = MSG_OTHER_PROCESS; + ret = send_inter_thread_message( info, &result ); + } + else if (info->type != MSG_OTHER_PROCESS) { result = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam, !ansi, TRUE, info->wm_char, FALSE, NULL, 0 ); @@ -2682,9 +2866,7 @@ static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr, } else { - if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE)) - info->type = MSG_OTHER_PROCESS; - ret = send_inter_thread_message( info, &result ); + ret = process_packed_message( info, &result, ansi ); }
spy_exit_message( SPY_RESULT_OK, info->hwnd, info->msg, result, info->wparam, info->lparam ); @@ -2831,8 +3013,26 @@ static LRESULT send_client_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, BOOL ansi ) { - DWORD_PTR res = 0; - send_client_message( hwnd, msg, wparam, lparam, flags, timeout, &res, ansi ); + struct send_message_info info; + DWORD_PTR res; + + if (!is_pointer_message( msg, wparam )) + { + send_client_message( hwnd, msg, wparam, lparam, flags, timeout, &res, ansi ); + return res; + } + + info.type = MSG_OTHER_PROCESS; + info.hwnd = hwnd; + info.msg = msg; + info.wparam = wparam; + info.lparam = lparam; + info.flags = flags; + info.timeout = timeout; + info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + info.params = NULL; + + process_message( &info, &res, ansi ); return res; }
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index c8ba7522278..9f93feea407 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -209,15 +209,6 @@ struct scroll_bar_win_data #define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771) /* WinSwitch */ #define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772) /* IconTitle */
-/* info about the message currently being received by the current thread */ -struct received_message_info -{ - UINT type; - MSG msg; - UINT flags; /* InSendMessageEx return flags */ - struct received_message_info *prev; -}; - extern const char *debugstr_msg_name( UINT msg, HWND hwnd ) DECLSPEC_HIDDEN; extern const char *debugstr_vkey_name( WPARAM wParam ) DECLSPEC_HIDDEN; extern void spy_enter_message( INT flag, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;