user32: Move unpack_message call to User32CallWindowProc.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-03-31 15:36:15 +02:00 committed by Alexandre Julliard
parent e72d463072
commit 2656d667a8
4 changed files with 511 additions and 390 deletions

View File

@ -290,14 +290,6 @@ static inline void push_string( struct packed_message *data, LPCWSTR str )
push_data( data, str, (lstrlenW(str) + 1) * sizeof(WCHAR) );
}
/* make sure that the buffer contains a valid null-terminated Unicode string */
static inline BOOL check_string( LPCWSTR str, size_t size )
{
for (size /= sizeof(WCHAR); size; size--, str++)
if (!*str) return TRUE;
return FALSE;
}
/* pack a pointer into a 32/64 portable format */
static inline ULONGLONG pack_ptr( const void *ptr )
{
@ -311,22 +303,6 @@ static inline void *unpack_ptr( ULONGLONG ptr64 )
return (void *)(ULONG_PTR)ptr64;
}
/* make sure that there is space for 'size' bytes in buffer, growing it if needed */
static inline void *get_buffer_space( void **buffer, size_t size )
{
void *ret;
if (*buffer)
{
if (!(ret = HeapReAlloc( GetProcessHeap(), 0, *buffer, size )))
HeapFree( GetProcessHeap(), 0, *buffer );
}
else ret = HeapAlloc( GetProcessHeap(), 0, size );
*buffer = ret;
return ret;
}
/* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
static inline BOOL combobox_has_strings( HWND hwnd )
{
@ -938,7 +914,7 @@ static size_t pack_message( HWND hwnd, UINT message, WPARAM wparam, LPARAM lpara
/***********************************************************************
* unpack_message
* unpack_message
*
* Unpack a message received from another process.
*/
@ -950,116 +926,6 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
switch(message)
{
case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCTW cs;
WCHAR *str = (WCHAR *)(&ps->cs + 1);
if (size < sizeof(ps->cs)) return FALSE;
size -= sizeof(ps->cs);
cs.lpCreateParams = unpack_ptr( ps->cs.lpCreateParams );
cs.hInstance = unpack_ptr( ps->cs.hInstance );
cs.hMenu = wine_server_ptr_handle( ps->cs.hMenu );
cs.hwndParent = wine_server_ptr_handle( ps->cs.hwndParent );
cs.cy = ps->cs.cy;
cs.cx = ps->cs.cx;
cs.y = ps->cs.y;
cs.x = ps->cs.x;
cs.style = ps->cs.style;
cs.dwExStyle = ps->cs.dwExStyle;
cs.lpszName = unpack_ptr( ps->cs.lpszName );
cs.lpszClass = unpack_ptr( ps->cs.lpszClass );
if (ps->cs.lpszName >> 16)
{
if (!check_string( str, size )) return FALSE;
cs.lpszName = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
}
if (ps->cs.lpszClass >> 16)
{
if (!check_string( str, size )) return FALSE;
cs.lpszClass = str;
}
memcpy( &ps->cs, &cs, sizeof(cs) );
break;
}
case WM_GETTEXT:
case WM_ASKCBFORMATNAME:
if (!get_buffer_space( buffer, (*wparam * sizeof(WCHAR)) )) return FALSE;
break;
case WM_WININICHANGE:
if (!*lparam) return TRUE;
/* fall through */
case WM_SETTEXT:
case WM_DEVMODECHANGE:
case CB_DIR:
case LB_DIR:
case LB_ADDFILE:
case EM_REPLACESEL:
if (!check_string( *buffer, size )) return FALSE;
break;
case WM_GETMINMAXINFO:
minsize = sizeof(MINMAXINFO);
break;
case WM_DRAWITEM:
{
DRAWITEMSTRUCT dis;
if (size < sizeof(ps->dis)) return FALSE;
dis.CtlType = ps->dis.CtlType;
dis.CtlID = ps->dis.CtlID;
dis.itemID = ps->dis.itemID;
dis.itemAction = ps->dis.itemAction;
dis.itemState = ps->dis.itemState;
dis.hwndItem = wine_server_ptr_handle( ps->dis.hwndItem );
dis.hDC = wine_server_ptr_handle( ps->dis.hDC );
dis.rcItem = ps->dis.rcItem;
dis.itemData = (ULONG_PTR)unpack_ptr( ps->dis.itemData );
memcpy( &ps->dis, &dis, sizeof(dis) );
break;
}
case WM_MEASUREITEM:
{
MEASUREITEMSTRUCT mis;
if (size < sizeof(ps->mis)) return FALSE;
mis.CtlType = ps->mis.CtlType;
mis.CtlID = ps->mis.CtlID;
mis.itemID = ps->mis.itemID;
mis.itemWidth = ps->mis.itemWidth;
mis.itemHeight = ps->mis.itemHeight;
mis.itemData = (ULONG_PTR)unpack_ptr( ps->mis.itemData );
memcpy( &ps->mis, &mis, sizeof(mis) );
break;
}
case WM_DELETEITEM:
{
DELETEITEMSTRUCT dls;
if (size < sizeof(ps->dls)) return FALSE;
dls.CtlType = ps->dls.CtlType;
dls.CtlID = ps->dls.CtlID;
dls.itemID = ps->dls.itemID;
dls.hwndItem = wine_server_ptr_handle( ps->dls.hwndItem );
dls.itemData = (ULONG_PTR)unpack_ptr( ps->dls.itemData );
memcpy( &ps->dls, &dls, sizeof(dls) );
break;
}
case WM_COMPAREITEM:
{
COMPAREITEMSTRUCT cis;
if (size < sizeof(ps->cis)) return FALSE;
cis.CtlType = ps->cis.CtlType;
cis.CtlID = ps->cis.CtlID;
cis.hwndItem = wine_server_ptr_handle( ps->cis.hwndItem );
cis.itemID1 = ps->cis.itemID1;
cis.itemData1 = (ULONG_PTR)unpack_ptr( ps->cis.itemData1 );
cis.itemID2 = ps->cis.itemID2;
cis.itemData2 = (ULONG_PTR)unpack_ptr( ps->cis.itemData2 );
cis.dwLocaleId = ps->cis.dwLocaleId;
memcpy( &ps->cis, &cis, sizeof(cis) );
break;
}
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
case WM_WINE_SETWINDOWPOS:
{
WINDOWPOS wp;
@ -1074,210 +940,6 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
memcpy( &ps->wp, &wp, sizeof(wp) );
break;
}
case WM_COPYDATA:
{
COPYDATASTRUCT cds;
if (size < sizeof(ps->cds)) return FALSE;
cds.dwData = (ULONG_PTR)unpack_ptr( ps->cds.dwData );
if (ps->cds.lpData)
{
cds.cbData = ps->cds.cbData;
cds.lpData = &ps->cds + 1;
minsize = sizeof(ps->cds) + cds.cbData;
}
else
{
cds.cbData = 0;
cds.lpData = 0;
}
memcpy( &ps->cds, &cds, sizeof(cds) );
break;
}
case WM_NOTIFY:
/* WM_NOTIFY cannot be sent across processes (MSDN) */
return FALSE;
case WM_HELP:
{
HELPINFO hi;
if (size < sizeof(ps->hi)) return FALSE;
hi.cbSize = sizeof(hi);
hi.iContextType = ps->hi.iContextType;
hi.iCtrlId = ps->hi.iCtrlId;
hi.hItemHandle = wine_server_ptr_handle( ps->hi.hItemHandle );
hi.dwContextId = (ULONG_PTR)unpack_ptr( ps->hi.dwContextId );
hi.MousePos = ps->hi.MousePos;
memcpy( &ps->hi, &hi, sizeof(hi) );
break;
}
case WM_STYLECHANGING:
case WM_STYLECHANGED:
minsize = sizeof(STYLESTRUCT);
break;
case WM_NCCALCSIZE:
if (!*wparam) minsize = sizeof(RECT);
else
{
NCCALCSIZE_PARAMS ncp;
WINDOWPOS wp;
if (size < sizeof(ps->ncp)) return FALSE;
ncp.rgrc[0] = ps->ncp.rgrc[0];
ncp.rgrc[1] = ps->ncp.rgrc[1];
ncp.rgrc[2] = ps->ncp.rgrc[2];
wp.hwnd = wine_server_ptr_handle( ps->ncp.hwnd );
wp.hwndInsertAfter = wine_server_ptr_handle( ps->ncp.hwndInsertAfter );
wp.x = ps->ncp.x;
wp.y = ps->ncp.y;
wp.cx = ps->ncp.cx;
wp.cy = ps->ncp.cy;
wp.flags = ps->ncp.flags;
ncp.lppos = (WINDOWPOS *)((NCCALCSIZE_PARAMS *)&ps->ncp + 1);
memcpy( &ps->ncp, &ncp, sizeof(ncp) );
*ncp.lppos = wp;
}
break;
case WM_GETDLGCODE:
if (*lparam)
{
MSG msg;
if (size < sizeof(ps->msg)) return FALSE;
msg.hwnd = wine_server_ptr_handle( ps->msg.hwnd );
msg.message = ps->msg.message;
msg.wParam = (ULONG_PTR)unpack_ptr( ps->msg.wParam );
msg.lParam = (ULONG_PTR)unpack_ptr( ps->msg.lParam );
msg.time = ps->msg.time;
msg.pt = ps->msg.pt;
memcpy( &ps->msg, &msg, sizeof(msg) );
break;
}
return TRUE;
case SBM_SETSCROLLINFO:
minsize = sizeof(SCROLLINFO);
break;
case SBM_GETSCROLLINFO:
if (!get_buffer_space( buffer, sizeof(SCROLLINFO ))) return FALSE;
break;
case SBM_GETSCROLLBARINFO:
if (!get_buffer_space( buffer, sizeof(SCROLLBARINFO ))) return FALSE;
break;
case EM_GETSEL:
case SBM_GETRANGE:
case CB_GETEDITSEL:
if (*wparam || *lparam)
{
if (!get_buffer_space( buffer, 2*sizeof(DWORD) )) return FALSE;
if (*wparam) *wparam = (WPARAM)*buffer;
if (*lparam) *lparam = (LPARAM)((DWORD *)*buffer + 1);
}
return TRUE;
case EM_GETRECT:
case LB_GETITEMRECT:
case CB_GETDROPPEDCONTROLRECT:
if (!get_buffer_space( buffer, sizeof(RECT) )) return FALSE;
break;
case EM_SETRECT:
case EM_SETRECTNP:
minsize = sizeof(RECT);
break;
case EM_GETLINE:
{
WORD len;
if (size < sizeof(WORD)) return FALSE;
len = *(WORD *)*buffer;
if (!get_buffer_space( buffer, (len + 1) * sizeof(WCHAR) )) return FALSE;
*lparam = (LPARAM)*buffer + sizeof(WORD); /* don't erase WORD at start of buffer */
return TRUE;
}
case EM_SETTABSTOPS:
case LB_SETTABSTOPS:
if (!*wparam) return TRUE;
minsize = *wparam * sizeof(UINT);
break;
case CB_ADDSTRING:
case CB_INSERTSTRING:
case CB_FINDSTRING:
case CB_FINDSTRINGEXACT:
case CB_SELECTSTRING:
case LB_ADDSTRING:
case LB_INSERTSTRING:
case LB_FINDSTRING:
case LB_FINDSTRINGEXACT:
case LB_SELECTSTRING:
if (!*buffer) return TRUE;
if (!check_string( *buffer, size )) return FALSE;
break;
case CB_GETLBTEXT:
{
size = sizeof(ULONG_PTR);
if (combobox_has_strings( hwnd ))
size = (SendMessageW( hwnd, CB_GETLBTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
if (!get_buffer_space( buffer, size )) return FALSE;
break;
}
case LB_GETTEXT:
{
size = sizeof(ULONG_PTR);
if (listbox_has_strings( hwnd ))
size = (SendMessageW( hwnd, LB_GETTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
if (!get_buffer_space( buffer, size )) return FALSE;
break;
}
case LB_GETSELITEMS:
if (!get_buffer_space( buffer, *wparam * sizeof(UINT) )) return FALSE;
break;
case WM_NEXTMENU:
{
MDINEXTMENU mnm;
if (size < sizeof(ps->mnm)) return FALSE;
mnm.hmenuIn = wine_server_ptr_handle( ps->mnm.hmenuIn );
mnm.hmenuNext = wine_server_ptr_handle( ps->mnm.hmenuNext );
mnm.hwndNext = wine_server_ptr_handle( ps->mnm.hwndNext );
memcpy( &ps->mnm, &mnm, sizeof(mnm) );
break;
}
case WM_SIZING:
case WM_MOVING:
minsize = sizeof(RECT);
if (!get_buffer_space( buffer, sizeof(RECT) )) return FALSE;
break;
case WM_MDICREATE:
{
MDICREATESTRUCTW mcs;
WCHAR *str = (WCHAR *)(&ps->mcs + 1);
if (size < sizeof(ps->mcs)) return FALSE;
size -= sizeof(ps->mcs);
mcs.szClass = unpack_ptr( ps->mcs.szClass );
mcs.szTitle = unpack_ptr( ps->mcs.szTitle );
mcs.hOwner = unpack_ptr( ps->mcs.hOwner );
mcs.x = ps->mcs.x;
mcs.y = ps->mcs.y;
mcs.cx = ps->mcs.cx;
mcs.cy = ps->mcs.cy;
mcs.style = ps->mcs.style;
mcs.lParam = (LPARAM)unpack_ptr( ps->mcs.lParam );
if (ps->mcs.szClass >> 16)
{
if (!check_string( str, size )) return FALSE;
mcs.szClass = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
}
if (ps->mcs.szTitle >> 16)
{
if (!check_string( str, size )) return FALSE;
mcs.szTitle = str;
}
memcpy( &ps->mcs, &mcs, sizeof(mcs) );
break;
}
case WM_MDIGETACTIVE:
if (!*lparam) return TRUE;
if (!get_buffer_space( buffer, sizeof(BOOL) )) return FALSE;
break;
case WM_DEVICECHANGE:
if (!(*wparam & 0x8000)) return TRUE;
minsize = sizeof(DEV_BROADCAST_HDR);
break;
case WM_WINE_KEYBOARD_LL_HOOK:
case WM_WINE_MOUSE_LL_HOOK:
{
@ -1291,48 +953,8 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
memcpy( &ps->hook, &h_extra, sizeof(h_extra) );
break;
}
case WM_NCPAINT:
if (*wparam <= 1) return TRUE;
FIXME( "WM_NCPAINT hdc unpacking not supported\n" );
return FALSE;
case WM_PAINT:
if (!*wparam) return TRUE;
/* fall through */
/* these contain an HFONT */
case WM_SETFONT:
case WM_GETFONT:
/* these contain an HDC */
case WM_ERASEBKGND:
case WM_ICONERASEBKGND:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
case WM_PRINT:
case WM_PRINTCLIENT:
/* these contain an HGLOBAL */
case WM_PAINTCLIPBOARD:
case WM_SIZECLIPBOARD:
/* these contain HICON */
case WM_GETICON:
case WM_SETICON:
case WM_QUERYDRAGICON:
case WM_QUERYPARKICON:
/* these contain pointers */
case WM_DROPOBJECT:
case WM_QUERYDROPOBJECT:
case WM_DRAGLOOP:
case WM_DRAGSELECT:
case WM_DRAGMOVE:
FIXME( "msg %x (%s) not supported yet\n", message, SPY_GetMsgName(message, hwnd) );
return FALSE;
default:
return TRUE; /* message doesn't need any unpacking */
return TRUE; /* message doesn't need any unpacking */
}
/* default exit for most messages: check minsize and store buffer in lparam */
@ -2043,10 +1665,11 @@ static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd,
* Call a window procedure and the corresponding hooks.
*/
static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
BOOL unicode, BOOL same_thread, enum wm_char_mapping mapping )
BOOL unicode, BOOL same_thread, enum wm_char_mapping mapping,
BOOL needs_unpack, void *buffer, size_t size )
{
struct user_thread_info *thread_info = get_user_thread_info();
struct win_proc_params params;
struct win_proc_params p, *params = &p;
LRESULT result = 0;
CWPSTRUCT cwp;
CWPRETSTRUCT cwpret;
@ -2054,15 +1677,23 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
if (msg & 0x80000000)
return handle_internal_message( hwnd, msg, wparam, lparam );
if (!needs_unpack) size = 0;
if (!WIN_IsCurrentThread( hwnd )) return 0;
if (!init_window_call_params( &params, hwnd, msg, wparam, lparam, &result, !unicode, mapping ))
if (size && !(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + size ))) return 0;
if (!init_window_call_params( params, hwnd, msg, wparam, lparam, &result, !unicode, mapping ))
{
if (params != &p) HeapFree( GetProcessHeap(), 0, params );
return 0;
}
params->needs_unpack = needs_unpack;
if (size) memcpy( params + 1, buffer, size );
/* first the WH_CALLWNDPROC hook */
cwp.lParam = lparam;
cwp.wParam = wparam;
cwp.message = msg;
cwp.hwnd = params.hwnd;
cwp.hwnd = params->hwnd;
HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, same_thread, (LPARAM)&cwp, unicode );
if (thread_info->recursion_count <= MAX_WINPROC_RECURSION)
@ -2070,17 +1701,19 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
thread_info->recursion_count++;
/* now call the window procedure */
User32CallWindowProc( &params, sizeof(params) );
User32CallWindowProc( params, sizeof(*params) + size );
thread_info->recursion_count--;
}
if (params != &p) HeapFree( GetProcessHeap(), 0, params );
/* and finally the WH_CALLWNDPROCRET hook */
cwpret.lResult = result;
cwpret.lParam = lparam;
cwpret.wParam = wparam;
cwpret.message = msg;
cwpret.hwnd = params.hwnd;
cwpret.hwnd = params->hwnd;
HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, same_thread, (LPARAM)&cwpret, unicode );
return result;
}
@ -2521,6 +2154,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
NTSTATUS res;
size_t size = 0;
const message_data_t *msg_data = buffer;
BOOL needs_unpack = FALSE;
thread_info->msg_source = prev_source;
@ -2586,6 +2220,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
if (!unpack_message( info.msg.hwnd, info.msg.message, &info.msg.wParam,
&info.msg.lParam, &buffer, size ))
continue;
needs_unpack = TRUE;
break;
case MSG_CALLBACK:
info.flags = ISMEX_CALLBACK;
@ -2662,6 +2297,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
reply_message( &info, 0, &info.msg );
continue;
}
needs_unpack = TRUE;
break;
case MSG_HARDWARE:
if (size >= sizeof(msg_data->hardware))
@ -2724,7 +2360,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
thread_info->msg_source = msg_source_unavailable;
result = call_window_proc( info.msg.hwnd, info.msg.message, info.msg.wParam,
info.msg.lParam, (info.type != MSG_ASCII), FALSE,
WMCHAR_MAP_RECVMESSAGE );
WMCHAR_MAP_RECVMESSAGE, needs_unpack, buffer, size );
if (thread_info->receive_info == &info )
NtUserCallTwoParam( result, (UINT_PTR)&info.msg, NtUserReplyMessage );
@ -3038,7 +2674,7 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO
if (info->dest_tid == GetCurrentThreadId())
{
result = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam,
unicode, TRUE, info->wm_char );
unicode, TRUE, info->wm_char, FALSE, NULL, 0 );
if (info->type == MSG_CALLBACK)
call_sendmsg_callback( info->callback, info->hwnd, info->msg, info->data, result );
ret = TRUE;

View File

@ -29,15 +29,32 @@
#include "wingdi.h"
#include "controls.h"
#include "win.h"
#include "dbt.h"
#include "user_private.h"
#include "wine/asm.h"
#include "wine/debug.h"
WINE_DECLARE_DEBUG_CHANNEL(msg);
WINE_DEFAULT_DEBUG_CHANNEL(msg);
WINE_DECLARE_DEBUG_CHANNEL(relay);
#define WINPROC_PROC16 ((void *)1) /* placeholder for 16-bit window procs */
union packed_structs
{
struct packed_CREATESTRUCTW cs;
struct packed_DRAWITEMSTRUCT dis;
struct packed_MEASUREITEMSTRUCT mis;
struct packed_DELETEITEMSTRUCT dls;
struct packed_COMPAREITEMSTRUCT cis;
struct packed_WINDOWPOS wp;
struct packed_COPYDATASTRUCT cds;
struct packed_HELPINFO hi;
struct packed_NCCALCSIZE_PARAMS ncp;
struct packed_MSG msg;
struct packed_MDINEXTMENU mnm;
struct packed_MDICREATESTRUCTW mcs;
};
static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
{
if (size >= need) return static_buffer;
@ -788,9 +805,474 @@ static void dispatch_win_proc_params( struct win_proc_params *params )
SetThreadDpiAwarenessContext( context );
}
/* make sure that there is space for 'size' bytes in buffer, growing it if needed */
static inline void *get_buffer_space( void **buffer, size_t size, size_t prev_size )
{
if (prev_size > size && !(*buffer = HeapAlloc( GetProcessHeap(), 0, size ))) return NULL;
return *buffer;
}
/* check whether a combobox expects strings or ids in CB_ADDSTRING/CB_INSERTSTRING */
static inline BOOL combobox_has_strings( HWND hwnd )
{
DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
}
/* check whether a listbox expects strings or ids in LB_ADDSTRING/LB_INSERTSTRING */
static inline BOOL listbox_has_strings( HWND hwnd )
{
DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
}
/* unpack a potentially 64-bit pointer, returning 0 when truncated */
static inline void *unpack_ptr( ULONGLONG ptr64 )
{
if ((ULONG_PTR)ptr64 != ptr64) return 0;
return (void *)(ULONG_PTR)ptr64;
}
/* convert a server handle to a generic handle */
static inline HANDLE unpack_handle( UINT handle )
{
return (HANDLE)(INT_PTR)(int)handle;
}
/* make sure that the buffer contains a valid null-terminated Unicode string */
static inline BOOL check_string( LPCWSTR str, size_t size )
{
for (size /= sizeof(WCHAR); size; size--, str++)
if (!*str) return TRUE;
return FALSE;
}
/***********************************************************************
* unpack_message
*
* Unpack a message received from another process.
*/
static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam,
void **buffer, size_t size )
{
size_t minsize = 0, prev_size = size;
union packed_structs *ps = *buffer;
switch(message)
{
case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCTW cs;
WCHAR *str = (WCHAR *)(&ps->cs + 1);
if (size < sizeof(ps->cs)) return FALSE;
size -= sizeof(ps->cs);
cs.lpCreateParams = unpack_ptr( ps->cs.lpCreateParams );
cs.hInstance = unpack_ptr( ps->cs.hInstance );
cs.hMenu = unpack_handle( ps->cs.hMenu );
cs.hwndParent = unpack_handle( ps->cs.hwndParent );
cs.cy = ps->cs.cy;
cs.cx = ps->cs.cx;
cs.y = ps->cs.y;
cs.x = ps->cs.x;
cs.style = ps->cs.style;
cs.dwExStyle = ps->cs.dwExStyle;
cs.lpszName = unpack_ptr( ps->cs.lpszName );
cs.lpszClass = unpack_ptr( ps->cs.lpszClass );
if (ps->cs.lpszName >> 16)
{
if (!check_string( str, size )) return FALSE;
cs.lpszName = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
}
if (ps->cs.lpszClass >> 16)
{
if (!check_string( str, size )) return FALSE;
cs.lpszClass = str;
}
memcpy( &ps->cs, &cs, sizeof(cs) );
break;
}
case WM_GETTEXT:
case WM_ASKCBFORMATNAME:
if (!get_buffer_space( buffer, (*wparam * sizeof(WCHAR)), size )) return FALSE;
break;
case WM_WININICHANGE:
if (!*lparam) return TRUE;
/* fall through */
case WM_SETTEXT:
case WM_DEVMODECHANGE:
case CB_DIR:
case LB_DIR:
case LB_ADDFILE:
case EM_REPLACESEL:
if (!check_string( *buffer, size )) return FALSE;
break;
case WM_GETMINMAXINFO:
minsize = sizeof(MINMAXINFO);
break;
case WM_DRAWITEM:
{
DRAWITEMSTRUCT dis;
if (size < sizeof(ps->dis)) return FALSE;
dis.CtlType = ps->dis.CtlType;
dis.CtlID = ps->dis.CtlID;
dis.itemID = ps->dis.itemID;
dis.itemAction = ps->dis.itemAction;
dis.itemState = ps->dis.itemState;
dis.hwndItem = unpack_handle( ps->dis.hwndItem );
dis.hDC = unpack_handle( ps->dis.hDC );
dis.rcItem = ps->dis.rcItem;
dis.itemData = (ULONG_PTR)unpack_ptr( ps->dis.itemData );
memcpy( &ps->dis, &dis, sizeof(dis) );
break;
}
case WM_MEASUREITEM:
{
MEASUREITEMSTRUCT mis;
if (size < sizeof(ps->mis)) return FALSE;
mis.CtlType = ps->mis.CtlType;
mis.CtlID = ps->mis.CtlID;
mis.itemID = ps->mis.itemID;
mis.itemWidth = ps->mis.itemWidth;
mis.itemHeight = ps->mis.itemHeight;
mis.itemData = (ULONG_PTR)unpack_ptr( ps->mis.itemData );
memcpy( &ps->mis, &mis, sizeof(mis) );
break;
}
case WM_DELETEITEM:
{
DELETEITEMSTRUCT dls;
if (size < sizeof(ps->dls)) return FALSE;
dls.CtlType = ps->dls.CtlType;
dls.CtlID = ps->dls.CtlID;
dls.itemID = ps->dls.itemID;
dls.hwndItem = unpack_handle( ps->dls.hwndItem );
dls.itemData = (ULONG_PTR)unpack_ptr( ps->dls.itemData );
memcpy( &ps->dls, &dls, sizeof(dls) );
break;
}
case WM_COMPAREITEM:
{
COMPAREITEMSTRUCT cis;
if (size < sizeof(ps->cis)) return FALSE;
cis.CtlType = ps->cis.CtlType;
cis.CtlID = ps->cis.CtlID;
cis.hwndItem = unpack_handle( ps->cis.hwndItem );
cis.itemID1 = ps->cis.itemID1;
cis.itemData1 = (ULONG_PTR)unpack_ptr( ps->cis.itemData1 );
cis.itemID2 = ps->cis.itemID2;
cis.itemData2 = (ULONG_PTR)unpack_ptr( ps->cis.itemData2 );
cis.dwLocaleId = ps->cis.dwLocaleId;
memcpy( &ps->cis, &cis, sizeof(cis) );
break;
}
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
{
WINDOWPOS wp;
if (size < sizeof(ps->wp)) return FALSE;
wp.hwnd = unpack_handle( ps->wp.hwnd );
wp.hwndInsertAfter = unpack_handle( ps->wp.hwndInsertAfter );
wp.x = ps->wp.x;
wp.y = ps->wp.y;
wp.cx = ps->wp.cx;
wp.cy = ps->wp.cy;
wp.flags = ps->wp.flags;
memcpy( &ps->wp, &wp, sizeof(wp) );
break;
}
case WM_COPYDATA:
{
COPYDATASTRUCT cds;
if (size < sizeof(ps->cds)) return FALSE;
cds.dwData = (ULONG_PTR)unpack_ptr( ps->cds.dwData );
if (ps->cds.lpData)
{
cds.cbData = ps->cds.cbData;
cds.lpData = &ps->cds + 1;
minsize = sizeof(ps->cds) + cds.cbData;
}
else
{
cds.cbData = 0;
cds.lpData = 0;
}
memcpy( &ps->cds, &cds, sizeof(cds) );
break;
}
case WM_NOTIFY:
/* WM_NOTIFY cannot be sent across processes (MSDN) */
return FALSE;
case WM_HELP:
{
HELPINFO hi;
if (size < sizeof(ps->hi)) return FALSE;
hi.cbSize = sizeof(hi);
hi.iContextType = ps->hi.iContextType;
hi.iCtrlId = ps->hi.iCtrlId;
hi.hItemHandle = unpack_handle( ps->hi.hItemHandle );
hi.dwContextId = (ULONG_PTR)unpack_ptr( ps->hi.dwContextId );
hi.MousePos = ps->hi.MousePos;
memcpy( &ps->hi, &hi, sizeof(hi) );
break;
}
case WM_STYLECHANGING:
case WM_STYLECHANGED:
minsize = sizeof(STYLESTRUCT);
break;
case WM_NCCALCSIZE:
if (!*wparam) minsize = sizeof(RECT);
else
{
NCCALCSIZE_PARAMS ncp;
WINDOWPOS wp;
if (size < sizeof(ps->ncp)) return FALSE;
ncp.rgrc[0] = ps->ncp.rgrc[0];
ncp.rgrc[1] = ps->ncp.rgrc[1];
ncp.rgrc[2] = ps->ncp.rgrc[2];
wp.hwnd = unpack_handle( ps->ncp.hwnd );
wp.hwndInsertAfter = unpack_handle( ps->ncp.hwndInsertAfter );
wp.x = ps->ncp.x;
wp.y = ps->ncp.y;
wp.cx = ps->ncp.cx;
wp.cy = ps->ncp.cy;
wp.flags = ps->ncp.flags;
ncp.lppos = (WINDOWPOS *)((NCCALCSIZE_PARAMS *)&ps->ncp + 1);
memcpy( &ps->ncp, &ncp, sizeof(ncp) );
*ncp.lppos = wp;
}
break;
case WM_GETDLGCODE:
if (*lparam)
{
MSG msg;
if (size < sizeof(ps->msg)) return FALSE;
msg.hwnd = unpack_handle( ps->msg.hwnd );
msg.message = ps->msg.message;
msg.wParam = (ULONG_PTR)unpack_ptr( ps->msg.wParam );
msg.lParam = (ULONG_PTR)unpack_ptr( ps->msg.lParam );
msg.time = ps->msg.time;
msg.pt = ps->msg.pt;
memcpy( &ps->msg, &msg, sizeof(msg) );
break;
}
return TRUE;
case SBM_SETSCROLLINFO:
minsize = sizeof(SCROLLINFO);
break;
case SBM_GETSCROLLINFO:
if (!get_buffer_space( buffer, sizeof(SCROLLINFO), size )) return FALSE;
break;
case SBM_GETSCROLLBARINFO:
if (!get_buffer_space( buffer, sizeof(SCROLLBARINFO), size )) return FALSE;
break;
case EM_GETSEL:
case SBM_GETRANGE:
case CB_GETEDITSEL:
if (*wparam || *lparam)
{
if (!get_buffer_space( buffer, 2*sizeof(DWORD), size )) return FALSE;
if (*wparam) *wparam = (WPARAM)*buffer;
if (*lparam) *lparam = (LPARAM)((DWORD *)*buffer + 1);
}
return TRUE;
case EM_GETRECT:
case LB_GETITEMRECT:
case CB_GETDROPPEDCONTROLRECT:
if (!get_buffer_space( buffer, sizeof(RECT), size )) return FALSE;
break;
case EM_SETRECT:
case EM_SETRECTNP:
minsize = sizeof(RECT);
break;
case EM_GETLINE:
{
WORD len;
if (size < sizeof(WORD)) return FALSE;
len = *(WORD *)*buffer;
if (!get_buffer_space( buffer, (len + 1) * sizeof(WCHAR), size )) return FALSE;
*lparam = (LPARAM)*buffer + sizeof(WORD); /* don't erase WORD at start of buffer */
return TRUE;
}
case EM_SETTABSTOPS:
case LB_SETTABSTOPS:
if (!*wparam) return TRUE;
minsize = *wparam * sizeof(UINT);
break;
case CB_ADDSTRING:
case CB_INSERTSTRING:
case CB_FINDSTRING:
case CB_FINDSTRINGEXACT:
case CB_SELECTSTRING:
case LB_ADDSTRING:
case LB_INSERTSTRING:
case LB_FINDSTRING:
case LB_FINDSTRINGEXACT:
case LB_SELECTSTRING:
if (!*buffer) return TRUE;
if (!check_string( *buffer, size )) return FALSE;
break;
case CB_GETLBTEXT:
{
size = sizeof(ULONG_PTR);
if (combobox_has_strings( hwnd ))
size = (SendMessageW( hwnd, CB_GETLBTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
if (!get_buffer_space( buffer, size, prev_size )) return FALSE;
break;
}
case LB_GETTEXT:
{
size = sizeof(ULONG_PTR);
if (listbox_has_strings( hwnd ))
size = (SendMessageW( hwnd, LB_GETTEXTLEN, *wparam, 0 ) + 1) * sizeof(WCHAR);
if (!get_buffer_space( buffer, size, prev_size )) return FALSE;
break;
}
case LB_GETSELITEMS:
if (!get_buffer_space( buffer, *wparam * sizeof(UINT), size )) return FALSE;
break;
case WM_NEXTMENU:
{
MDINEXTMENU mnm;
if (size < sizeof(ps->mnm)) return FALSE;
mnm.hmenuIn = unpack_handle( ps->mnm.hmenuIn );
mnm.hmenuNext = unpack_handle( ps->mnm.hmenuNext );
mnm.hwndNext = unpack_handle( ps->mnm.hwndNext );
memcpy( &ps->mnm, &mnm, sizeof(mnm) );
break;
}
case WM_SIZING:
case WM_MOVING:
minsize = sizeof(RECT);
if (!get_buffer_space( buffer, sizeof(RECT), size )) return FALSE;
break;
case WM_MDICREATE:
{
MDICREATESTRUCTW mcs;
WCHAR *str = (WCHAR *)(&ps->mcs + 1);
if (size < sizeof(ps->mcs)) return FALSE;
size -= sizeof(ps->mcs);
mcs.szClass = unpack_ptr( ps->mcs.szClass );
mcs.szTitle = unpack_ptr( ps->mcs.szTitle );
mcs.hOwner = unpack_ptr( ps->mcs.hOwner );
mcs.x = ps->mcs.x;
mcs.y = ps->mcs.y;
mcs.cx = ps->mcs.cx;
mcs.cy = ps->mcs.cy;
mcs.style = ps->mcs.style;
mcs.lParam = (LPARAM)unpack_ptr( ps->mcs.lParam );
if (ps->mcs.szClass >> 16)
{
if (!check_string( str, size )) return FALSE;
mcs.szClass = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
}
if (ps->mcs.szTitle >> 16)
{
if (!check_string( str, size )) return FALSE;
mcs.szTitle = str;
}
memcpy( &ps->mcs, &mcs, sizeof(mcs) );
break;
}
case WM_MDIGETACTIVE:
if (!*lparam) return TRUE;
if (!get_buffer_space( buffer, sizeof(BOOL), size )) return FALSE;
break;
case WM_DEVICECHANGE:
if (!(*wparam & 0x8000)) return TRUE;
minsize = sizeof(DEV_BROADCAST_HDR);
break;
case WM_NCPAINT:
if (*wparam <= 1) return TRUE;
FIXME( "WM_NCPAINT hdc unpacking not supported\n" );
return FALSE;
case WM_PAINT:
if (!*wparam) return TRUE;
/* fall through */
/* these contain an HFONT */
case WM_SETFONT:
case WM_GETFONT:
/* these contain an HDC */
case WM_ERASEBKGND:
case WM_ICONERASEBKGND:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
case WM_PRINT:
case WM_PRINTCLIENT:
/* these contain an HGLOBAL */
case WM_PAINTCLIPBOARD:
case WM_SIZECLIPBOARD:
/* these contain HICON */
case WM_GETICON:
case WM_SETICON:
case WM_QUERYDRAGICON:
case WM_QUERYPARKICON:
/* these contain pointers */
case WM_DROPOBJECT:
case WM_QUERYDROPOBJECT:
case WM_DRAGLOOP:
case WM_DRAGSELECT:
case WM_DRAGMOVE:
FIXME( "msg %x (%s) not supported yet\n", message, SPY_GetMsgName(message, hwnd) );
return FALSE;
default:
return TRUE; /* message doesn't need any unpacking */
}
/* default exit for most messages: check minsize and store buffer in lparam */
if (size < minsize) return FALSE;
*lparam = (LPARAM)*buffer;
return TRUE;
}
BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size )
{
dispatch_win_proc_params( params );
if (params->needs_unpack)
{
char stack_buffer[128];
void *buffer;
LRESULT result;
MSG msg;
if (size > sizeof(*params))
{
size -= sizeof(*params);
buffer = params + 1;
}
else
{
size = sizeof(stack_buffer);
buffer = stack_buffer;
}
if (!unpack_message( params->hwnd, params->msg, &params->wparam,
&params->lparam, &buffer, size ))
return 0;
params->result = &result;
msg.hwnd = params->hwnd;
msg.message = params->msg;
msg.wParam = params->wparam;
msg.lParam = params->lparam;
dispatch_win_proc_params( params );
NtUserCallTwoParam( result, (UINT_PTR)&msg, NtUserReplyMessage );
if (buffer != stack_buffer && buffer != params + 1)
HeapFree( GetProcessHeap(), 0, buffer );
}
else dispatch_win_proc_params( params );
return TRUE;
}

View File

@ -96,6 +96,7 @@ static BOOL init_win_proc_params( struct win_proc_params *params, HWND hwnd, UIN
params->lparam = lparam;
params->ansi = params->ansi_dst = ansi;
params->is_dialog = FALSE;
params->needs_unpack = FALSE;
params->mapping = WMCHAR_MAP_CALLWINDOWPROC;
params->dpi_awareness = get_window_dpi_awareness_context( params->hwnd );
get_winproc_params( params );
@ -129,6 +130,7 @@ static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd,
params->lparam = lParam;
params->result = result;
params->ansi = ansi;
params->needs_unpack = FALSE;
params->mapping = mapping;
params->dpi_awareness = get_window_dpi_awareness_context( params->hwnd );
return TRUE;

View File

@ -89,6 +89,7 @@ struct win_proc_params
BOOL ansi;
BOOL ansi_dst;
BOOL is_dialog;
BOOL needs_unpack;
enum wm_char_mapping mapping;
DPI_AWARENESS_CONTEXT dpi_awareness;
WNDPROC procA;