Commit 2d8b65c2 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Use CREATESTRUCTW struct layout to pass WM_CREATE message params to client.

parent eac34b9c
......@@ -789,13 +789,18 @@ static inline BOOL check_string( LPCWSTR str, size_t size )
return FALSE;
}
static size_t string_size( const void *str, BOOL ansi )
{
return ansi ? strlen( str ) + 1 : (wcslen( str ) + 1) * sizeof(WCHAR);
}
/***********************************************************************
* 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 )
void **buffer, size_t size, BOOL ansi )
{
size_t minsize = 0, prev_size = size;
union packed_structs *ps = *buffer;
......@@ -805,35 +810,18 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
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)
CREATESTRUCTA *cs = *buffer;
char *str = (char *)(cs + 1);
if (!IS_INTRESOURCE(cs->lpszName))
{
if (!check_string( str, size )) return FALSE;
cs.lpszName = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
cs->lpszName = str;
str += string_size( str, ansi );
}
if (ps->cs.lpszClass >> 16)
if (!IS_INTRESOURCE(cs->lpszClass))
{
if (!check_string( str, size )) return FALSE;
cs.lpszClass = str;
cs->lpszClass = str;
}
memcpy( *buffer, &cs, sizeof(cs) );
break;
}
case WM_GETTEXT:
......@@ -1186,6 +1174,7 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size )
if (params->needs_unpack)
{
char stack_buffer[128];
size_t msg_size = size - sizeof(*params);
void *buffer;
if (size > sizeof(*params))
......@@ -1199,11 +1188,22 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size )
buffer = stack_buffer;
}
if (!unpack_message( params->hwnd, params->msg, &params->wparam,
&params->lparam, &buffer, size ))
&params->lparam, &buffer, size, params->ansi ))
return 0;
result = dispatch_win_proc_params( params );
switch (params->msg)
{
case WM_NCCREATE:
case WM_CREATE:
{
LRESULT *result_ptr = (LRESULT *)buffer - 1;
*result_ptr = result;
return NtCallbackReturn( result_ptr, sizeof(*result_ptr) + msg_size, TRUE );
}
}
NtUserMessageCall( params->hwnd, params->msg, params->wparam, params->lparam,
(void *)result, NtUserWinProcResult, FALSE );
if (buffer != stack_buffer && buffer != params + 1)
......
......@@ -255,7 +255,8 @@ static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd,
return TRUE;
}
static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t size )
static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t size,
void **client_ret, size_t *client_ret_size )
{
struct ntuser_thread_info *thread_info = NtUserGetThreadInfo();
LRESULT result = 0;
......@@ -264,11 +265,19 @@ static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t
if (thread_info->recursion_count > MAX_WINPROC_RECURSION) return 0;
thread_info->recursion_count++;
KeUserModeCallback( NtUserCallWinProc, params, size, &ret_ptr, &ret_len );
if (ret_len == sizeof(result)) result = *(LRESULT *)ret_ptr;
thread_info->recursion_count--;
if (ret_len >= sizeof(result))
{
result = *(LRESULT *)ret_ptr;
if (client_ret)
{
*client_ret = (LRESULT *)ret_ptr + 1;
*client_ret_size = ret_len - sizeof(result);
}
}
return result;
}
......@@ -346,6 +355,38 @@ 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)
{
cs.lpszName = str;
size -= (lstrlenW(str) + 1) * sizeof(WCHAR);
str += lstrlenW(str) + 1;
}
if (ps->cs.lpszClass >> 16)
{
cs.lpszClass = str;
}
memcpy( *buffer, &cs, sizeof(cs) );
break;
}
case WM_WINE_SETWINDOWPOS:
{
WINDOWPOS wp;
......@@ -1076,23 +1117,100 @@ static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
}
}
static size_t string_size( const void *str, BOOL ansi )
{
return ansi ? strlen( str ) + 1 : (wcslen( str ) + 1) * sizeof(WCHAR);
}
static size_t copy_string( void *ptr, const void *str, BOOL ansi )
{
size_t size = string_size( str, ansi );
memcpy( ptr, str, size );
return size;
}
/***********************************************************************
* copy_reply
* user_message_size
*
* Copy a message reply received from client.
* Calculate size of packed message buffer.
*/
static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
WPARAM wparam_src, LPARAM lparam_src )
static size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi )
{
size_t copy_size = 0;
const void *lparam_ptr = (const void *)lparam;
size_t size = 0;
switch(message)
switch (message)
{
case WM_NCCREATE:
case WM_CREATE:
{
const CREATESTRUCTW *cs = lparam_ptr;
size = sizeof(*cs);
if (!IS_INTRESOURCE(cs->lpszName)) size += string_size( cs->lpszName, ansi );
if (!IS_INTRESOURCE(cs->lpszClass)) size += string_size( cs->lpszClass, ansi );
break;
}
}
return size;
}
/***********************************************************************
* pack_user_message
*
* Copy message to a buffer for passing to client.
*/
static void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, BOOL ansi )
{
const void *lparam_ptr = (const void *)lparam;
void const *inline_ptr = (void *)0xffffffff;
if (!size) return;
switch (message)
{
case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCTW *cs = buffer;
char *ptr = (char *)(cs + 1);
memcpy( cs, lparam_ptr, sizeof(*cs) );
if (!IS_INTRESOURCE(cs->lpszName))
{
ptr += copy_string( ptr, cs->lpszName, ansi );
cs->lpszName = inline_ptr;
}
if (!IS_INTRESOURCE(cs->lpszClass))
{
CREATESTRUCTW *dst = (CREATESTRUCTW *)lparam;
CREATESTRUCTW *src = (CREATESTRUCTW *)lparam_src;
copy_string( ptr, cs->lpszClass, ansi );
cs->lpszClass = inline_ptr;
}
return;
}
}
}
/***********************************************************************
* copy_user_result
*
* Copy a message result received from client.
*/
static void copy_user_result( void *buffer, size_t size, UINT message, WPARAM wparam, LPARAM lparam )
{
void *lparam_ptr = (void *)lparam;
if (!size) return;
switch (message)
{
case WM_NCCREATE:
case WM_CREATE:
if (size >= sizeof(CREATESTRUCTW))
{
CREATESTRUCTW *dst = lparam_ptr;
const CREATESTRUCTW *src = buffer;
dst->lpCreateParams = src->lpCreateParams;
dst->hInstance = src->hInstance;
dst->hMenu = src->hMenu;
......@@ -1106,6 +1224,23 @@ static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam,
/* don't allow changing name and class pointers */
}
return;
default:
return;
}
}
/***********************************************************************
* 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_GETTEXT:
case CB_GETLBTEXT:
case LB_GETTEXT:
......@@ -1373,9 +1508,13 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
BOOL needs_unpack, void *buffer, size_t size )
{
struct win_proc_params p, *params = &p;
BOOL ansi = !unicode && !needs_unpack;
LRESULT result = 0;
CWPSTRUCT cwp;
CWPRETSTRUCT cwpret;
size_t packed_size = 0;
void *ret_ptr;
size_t ret_len = 0;
if (msg & 0x80000000)
return handle_internal_message( hwnd, msg, wparam, lparam );
......@@ -1383,6 +1522,9 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
if (!needs_unpack) size = 0;
if (!is_current_thread_window( hwnd )) return 0;
packed_size = user_message_size( msg, lparam, ansi );
if (packed_size) size = packed_size;
/* first the WH_CALLWNDPROC hook */
cwp.lParam = lparam;
cwp.wParam = wparam;
......@@ -1397,15 +1539,18 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
return 0;
}
if (needs_unpack)
{
params->needs_unpack = TRUE;
params->ansi = FALSE;
if (size) memcpy( params + 1, buffer, size );
}
result = dispatch_win_proc_params( params, sizeof(*params) + size );
if (needs_unpack) params->ansi = FALSE;
params->needs_unpack = needs_unpack || packed_size;
if (packed_size)
pack_user_message( params + 1, packed_size, msg, lparam, ansi );
else if (size)
memcpy( params + 1, buffer, size );
result = dispatch_win_proc_params( params, sizeof(*params) + size, &ret_ptr, &ret_len );
if (params != &p) free( params );
copy_user_result( ret_ptr, min( ret_len, packed_size ), msg, wparam, lparam );
/* and finally the WH_CALLWNDPROCRET hook */
cwpret.lResult = result;
cwpret.lParam = lparam;
......@@ -2750,7 +2895,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
if (!init_win_proc_params( &params, msg->hwnd, msg->message,
msg->wParam, NtGetTickCount(), FALSE ))
return 0;
return dispatch_win_proc_params( &params, sizeof(params) );
return dispatch_win_proc_params( &params, sizeof(params), NULL, NULL );
}
if (msg->message == WM_SYSTIMER)
{
......@@ -2772,7 +2917,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
if (init_window_call_params( &params, msg->hwnd, msg->message, msg->wParam, msg->lParam,
FALSE, WMCHAR_MAP_DISPATCHMESSAGE ))
retval = dispatch_win_proc_params( &params, sizeof(params) );
retval = dispatch_win_proc_params( &params, sizeof(params), NULL, NULL );
else if (!is_window( msg->hwnd )) RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE );
else RtlSetLastWin32Error( ERROR_MESSAGE_SYNC_ONLY );
......
......@@ -614,10 +614,66 @@ static NTSTATUS WINAPI wow64_NtUserCallWinEventHook( void *arg, ULONG size )
FIELD_OFFSET( struct win_event_hook_params32, module ) + size);
}
static size_t packed_message_64to32( UINT message, const void *params64, void *params32, size_t size )
{
if (!size) return 0;
switch (message)
{
case WM_NCCREATE:
case WM_CREATE:
{
CREATESTRUCT32 *cs32 = params32;
const CREATESTRUCTW *cs64 = params64;
createstruct_64to32( cs64, cs32 );
size -= sizeof(*cs64);
if (size) memmove( cs32 + 1, cs64 + 1, size );
return sizeof(*cs32) + size;
}
}
memmove( params32, params64, size );
return size;
}
static size_t packed_result_32to64( UINT message, const void *params32, size_t size, void *params64 )
{
switch (message)
{
case WM_NCCREATE:
case WM_CREATE:
if (size >= sizeof(CREATESTRUCT32))
{
const CREATESTRUCT32 *cs32 = params32;
CREATESTRUCTW *cs64 = params64;
cs64->lpCreateParams = UlongToPtr( cs32->lpCreateParams );
cs64->hInstance = UlongToPtr( cs32->hInstance );
cs64->hMenu = LongToHandle( cs32->hMenu );
cs64->hwndParent = LongToHandle( cs32->hwndParent );
cs64->cy = cs32->cy;
cs64->cx = cs32->cx;
cs64->y = cs32->y;
cs64->x = cs32->x;
cs64->style = cs32->style;
cs64->dwExStyle = cs32->dwExStyle;
return sizeof(*cs64);
}
default:
return 0;
}
if (size) memcpy( params64, params32, size );
return size;
}
static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size )
{
struct win_proc_params *params = arg;
struct win_proc_params32 *params32 = arg;
size_t lparam_size = 0;
LRESULT result = 0;
void *ret_ptr;
ULONG ret_len;
......@@ -625,13 +681,23 @@ static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size )
win_proc_params_64to32( params, params32 );
if (size > sizeof(*params))
memmove( params32 + 1, params + 1, size - sizeof(*params) );
lparam_size = packed_message_64to32( params32->msg, params + 1, params32 + 1,
size - sizeof(*params) );
status = Wow64KiUserCallbackDispatcher( NtUserCallWinProc, params32,
size - sizeof(*params) + sizeof(*params32),
sizeof(*params32) + lparam_size,
&ret_ptr, &ret_len );
if (ret_len == sizeof(LONG)) result = *(LONG *)ret_ptr;
if (ret_len >= sizeof(LONG))
{
LRESULT *result_ptr = arg;
result = *(LONG *)ret_ptr;
ret_len = packed_result_32to64( params32->msg, (LONG *)ret_ptr + 1,
ret_len - sizeof(LONG), result_ptr + 1 );
*result_ptr = result;
return NtCallbackReturn( result_ptr, sizeof(*result_ptr) + ret_len, status );
}
return NtCallbackReturn( &result, sizeof(result), status );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment