mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 05:31:39 +00:00
user32: Use NtUserMessageCall for SendMessageCallbackA implementation.
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:
parent
b99778a531
commit
37de5d24a8
|
@ -45,7 +45,6 @@
|
|||
#include "wine/exception.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msg);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(relay);
|
||||
WINE_DECLARE_DEBUG_CHANNEL(key);
|
||||
|
||||
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
|
||||
|
@ -119,9 +118,6 @@ struct send_message_info
|
|||
enum wm_char_mapping wm_char;
|
||||
};
|
||||
|
||||
static const INPUT_MESSAGE_SOURCE msg_source_unavailable = { IMDT_UNAVAILABLE, IMO_UNAVAILABLE };
|
||||
|
||||
|
||||
/* Message class descriptor */
|
||||
const struct builtin_class_descr MESSAGE_builtin_class =
|
||||
{
|
||||
|
@ -201,64 +197,6 @@ static const unsigned int message_pointer_flags[] =
|
|||
SET(WM_ASKCBFORMATNAME)
|
||||
};
|
||||
|
||||
/* flags for messages that contain Unicode strings */
|
||||
static const unsigned int message_unicode_flags[] =
|
||||
{
|
||||
/* 0x00 - 0x1f */
|
||||
SET(WM_CREATE) | SET(WM_SETTEXT) | SET(WM_GETTEXT) | SET(WM_GETTEXTLENGTH) |
|
||||
SET(WM_WININICHANGE) | SET(WM_DEVMODECHANGE),
|
||||
/* 0x20 - 0x3f */
|
||||
SET(WM_CHARTOITEM),
|
||||
/* 0x40 - 0x5f */
|
||||
0,
|
||||
/* 0x60 - 0x7f */
|
||||
0,
|
||||
/* 0x80 - 0x9f */
|
||||
SET(WM_NCCREATE),
|
||||
/* 0xa0 - 0xbf */
|
||||
0,
|
||||
/* 0xc0 - 0xdf */
|
||||
SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETPASSWORDCHAR),
|
||||
/* 0xe0 - 0xff */
|
||||
0,
|
||||
/* 0x100 - 0x11f */
|
||||
SET(WM_CHAR) | SET(WM_DEADCHAR) | SET(WM_SYSCHAR) | SET(WM_SYSDEADCHAR),
|
||||
/* 0x120 - 0x13f */
|
||||
SET(WM_MENUCHAR),
|
||||
/* 0x140 - 0x15f */
|
||||
SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) | SET(CB_GETLBTEXTLEN) |
|
||||
SET(CB_INSERTSTRING) | SET(CB_FINDSTRING) | SET(CB_SELECTSTRING) | SET(CB_FINDSTRINGEXACT),
|
||||
/* 0x160 - 0x17f */
|
||||
0,
|
||||
/* 0x180 - 0x19f */
|
||||
SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_GETTEXTLEN) |
|
||||
SET(LB_SELECTSTRING) | SET(LB_DIR) | SET(LB_FINDSTRING) | SET(LB_ADDFILE),
|
||||
/* 0x1a0 - 0x1bf */
|
||||
SET(LB_FINDSTRINGEXACT),
|
||||
/* 0x1c0 - 0x1df */
|
||||
0,
|
||||
/* 0x1e0 - 0x1ff */
|
||||
0,
|
||||
/* 0x200 - 0x21f */
|
||||
0,
|
||||
/* 0x220 - 0x23f */
|
||||
SET(WM_MDICREATE),
|
||||
/* 0x240 - 0x25f */
|
||||
0,
|
||||
/* 0x260 - 0x27f */
|
||||
0,
|
||||
/* 0x280 - 0x29f */
|
||||
SET(WM_IME_CHAR),
|
||||
/* 0x2a0 - 0x2bf */
|
||||
0,
|
||||
/* 0x2c0 - 0x2df */
|
||||
0,
|
||||
/* 0x2e0 - 0x2ff */
|
||||
0,
|
||||
/* 0x300 - 0x31f */
|
||||
SET(WM_PAINTCLIPBOARD) | SET(WM_SIZECLIPBOARD) | SET(WM_ASKCBFORMATNAME)
|
||||
};
|
||||
|
||||
/* check whether a given message type includes pointers */
|
||||
static inline BOOL is_pointer_message( UINT message, WPARAM wparam )
|
||||
{
|
||||
|
@ -267,13 +205,6 @@ static inline BOOL is_pointer_message( UINT message, WPARAM wparam )
|
|||
return (message_pointer_flags[message / 32] & SET(message)) != 0;
|
||||
}
|
||||
|
||||
/* check whether a given message type contains Unicode (or ASCII) chars */
|
||||
static inline BOOL is_unicode_message( UINT message )
|
||||
{
|
||||
if (message >= 8*sizeof(message_unicode_flags)) return FALSE;
|
||||
return (message_unicode_flags[message / 32] & SET(message)) != 0;
|
||||
}
|
||||
|
||||
#undef SET
|
||||
|
||||
/* add a data field to a packed message */
|
||||
|
@ -913,168 +844,6 @@ static size_t pack_message( HWND hwnd, UINT message, WPARAM wparam, LPARAM lpara
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* unpack_reply
|
||||
*
|
||||
* Unpack a message reply received from another process.
|
||||
*/
|
||||
static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
|
||||
void *buffer, size_t size )
|
||||
{
|
||||
union packed_structs *ps = buffer;
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
case WM_CREATE:
|
||||
if (size >= sizeof(ps->cs))
|
||||
{
|
||||
CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
|
||||
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;
|
||||
/* don't allow changing name and class pointers */
|
||||
}
|
||||
break;
|
||||
case WM_GETTEXT:
|
||||
case WM_ASKCBFORMATNAME:
|
||||
memcpy( (WCHAR *)lparam, buffer, min( wparam*sizeof(WCHAR), size ));
|
||||
break;
|
||||
case WM_GETMINMAXINFO:
|
||||
memcpy( (MINMAXINFO *)lparam, buffer, min( sizeof(MINMAXINFO), size ));
|
||||
break;
|
||||
case WM_MEASUREITEM:
|
||||
if (size >= sizeof(ps->mis))
|
||||
{
|
||||
MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lparam;
|
||||
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 );
|
||||
}
|
||||
break;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
if (size >= sizeof(ps->wp))
|
||||
{
|
||||
WINDOWPOS *wp = (WINDOWPOS *)lparam;
|
||||
wp->hwnd = wine_server_ptr_handle( ps->wp.hwnd );
|
||||
wp->hwndInsertAfter = wine_server_ptr_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;
|
||||
}
|
||||
break;
|
||||
case WM_GETDLGCODE:
|
||||
if (lparam && size >= sizeof(ps->msg))
|
||||
{
|
||||
MSG *msg = (MSG *)lparam;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case SBM_GETSCROLLINFO:
|
||||
memcpy( (SCROLLINFO *)lparam, buffer, min( sizeof(SCROLLINFO), size ));
|
||||
break;
|
||||
case SBM_GETSCROLLBARINFO:
|
||||
memcpy( (SCROLLBARINFO *)lparam, buffer, min( sizeof(SCROLLBARINFO), size ));
|
||||
break;
|
||||
case EM_GETRECT:
|
||||
case CB_GETDROPPEDCONTROLRECT:
|
||||
case LB_GETITEMRECT:
|
||||
case WM_SIZING:
|
||||
case WM_MOVING:
|
||||
memcpy( (RECT *)lparam, buffer, min( sizeof(RECT), size ));
|
||||
break;
|
||||
case EM_GETLINE:
|
||||
size = min( size, (size_t)*(WORD *)lparam );
|
||||
memcpy( (WCHAR *)lparam, buffer, size );
|
||||
break;
|
||||
case LB_GETSELITEMS:
|
||||
memcpy( (UINT *)lparam, buffer, min( wparam*sizeof(UINT), size ));
|
||||
break;
|
||||
case LB_GETTEXT:
|
||||
case CB_GETLBTEXT:
|
||||
memcpy( (WCHAR *)lparam, buffer, size );
|
||||
break;
|
||||
case WM_NEXTMENU:
|
||||
if (size >= sizeof(ps->mnm))
|
||||
{
|
||||
MDINEXTMENU *mnm = (MDINEXTMENU *)lparam;
|
||||
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 );
|
||||
}
|
||||
break;
|
||||
case WM_MDIGETACTIVE:
|
||||
if (lparam) memcpy( (BOOL *)lparam, buffer, min( sizeof(BOOL), size ));
|
||||
break;
|
||||
case WM_NCCALCSIZE:
|
||||
if (!wparam)
|
||||
memcpy( (RECT *)lparam, buffer, min( sizeof(RECT), size ));
|
||||
else if (size >= sizeof(ps->ncp))
|
||||
{
|
||||
NCCALCSIZE_PARAMS *ncp = (NCCALCSIZE_PARAMS *)lparam;
|
||||
ncp->rgrc[0] = ps->ncp.rgrc[0];
|
||||
ncp->rgrc[1] = ps->ncp.rgrc[1];
|
||||
ncp->rgrc[2] = ps->ncp.rgrc[2];
|
||||
ncp->lppos->hwnd = wine_server_ptr_handle( ps->ncp.hwnd );
|
||||
ncp->lppos->hwndInsertAfter = wine_server_ptr_handle( ps->ncp.hwndInsertAfter );
|
||||
ncp->lppos->x = ps->ncp.x;
|
||||
ncp->lppos->y = ps->ncp.y;
|
||||
ncp->lppos->cx = ps->ncp.cx;
|
||||
ncp->lppos->cy = ps->ncp.cy;
|
||||
ncp->lppos->flags = ps->ncp.flags;
|
||||
}
|
||||
break;
|
||||
case EM_GETSEL:
|
||||
case SBM_GETRANGE:
|
||||
case CB_GETEDITSEL:
|
||||
if (wparam)
|
||||
{
|
||||
memcpy( (DWORD *)wparam, buffer, min( sizeof(DWORD), size ));
|
||||
if (size <= sizeof(DWORD)) break;
|
||||
size -= sizeof(DWORD);
|
||||
buffer = (DWORD *)buffer + 1;
|
||||
}
|
||||
if (lparam) memcpy( (DWORD *)lparam, buffer, min( sizeof(DWORD), size ));
|
||||
break;
|
||||
case WM_MDICREATE:
|
||||
if (size >= sizeof(ps->mcs))
|
||||
{
|
||||
MDICREATESTRUCTW *mcs = (MDICREATESTRUCTW *)lparam;
|
||||
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 );
|
||||
/* don't allow changing class and title pointers */
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERR( "should not happen: unexpected message %x\n", message );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* handle_internal_message
|
||||
*
|
||||
|
@ -1383,98 +1152,6 @@ BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam, LRESULT *result, BOOL ansi,
|
||||
enum wm_char_mapping mapping )
|
||||
{
|
||||
WND *win;
|
||||
|
||||
USER_CheckNotLock();
|
||||
|
||||
if (!(win = WIN_GetPtr( hwnd ))) return FALSE;
|
||||
if (win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE;
|
||||
if (win->tid != GetCurrentThreadId())
|
||||
{
|
||||
WIN_ReleasePtr( win );
|
||||
return FALSE;
|
||||
}
|
||||
params->func = win->winproc;
|
||||
params->ansi_dst = !(win->flags & WIN_ISUNICODE);
|
||||
params->is_dialog = win->dlgInfo != NULL;
|
||||
WIN_ReleasePtr( win );
|
||||
|
||||
params->hwnd = WIN_GetFullHandle( hwnd );
|
||||
get_winproc_params( params );
|
||||
params->msg = msg;
|
||||
params->wparam = wParam;
|
||||
params->lparam = lParam;
|
||||
params->result = result;
|
||||
params->ansi = ansi;
|
||||
params->mapping = mapping;
|
||||
params->dpi_awareness = GetWindowDpiAwarenessContext( params->hwnd );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* call_window_proc
|
||||
*
|
||||
* 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 needs_unpack, void *buffer, size_t size )
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
struct win_proc_params p, *params = &p;
|
||||
LRESULT result = 0;
|
||||
CWPSTRUCT cwp;
|
||||
CWPRETSTRUCT cwpret;
|
||||
|
||||
if (msg & 0x80000000)
|
||||
return handle_internal_message( hwnd, msg, wparam, lparam );
|
||||
|
||||
if (!needs_unpack) size = 0;
|
||||
if (!WIN_IsCurrentThread( hwnd )) return 0;
|
||||
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;
|
||||
HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, same_thread, (LPARAM)&cwp, unicode );
|
||||
|
||||
if (thread_info->recursion_count <= MAX_WINPROC_RECURSION)
|
||||
{
|
||||
thread_info->recursion_count++;
|
||||
|
||||
/* now call the window procedure */
|
||||
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;
|
||||
HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, same_thread, (LPARAM)&cwpret, unicode );
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* send_parent_notify
|
||||
*
|
||||
|
@ -1865,99 +1542,6 @@ BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardware_msg_d
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_sendmsg_callback
|
||||
*
|
||||
* Call the callback function of SendMessageCallback.
|
||||
*/
|
||||
static inline void call_sendmsg_callback( SENDASYNCPROC callback, HWND hwnd, UINT msg,
|
||||
ULONG_PTR data, LRESULT result )
|
||||
{
|
||||
if (!callback) return;
|
||||
|
||||
TRACE_(relay)( "\1Call message callback %p (hwnd=%p,msg=%s,data=%08lx,result=%08lx)\n",
|
||||
callback, hwnd, SPY_GetMsgName( msg, hwnd ), data, result );
|
||||
callback( hwnd, msg, data, result );
|
||||
TRACE_(relay)( "\1Ret message callback %p (hwnd=%p,msg=%s,data=%08lx,result=%08lx)\n",
|
||||
callback, hwnd, SPY_GetMsgName( msg, hwnd ), data, result );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* process_sent_messages
|
||||
*
|
||||
* Process all pending sent messages.
|
||||
*/
|
||||
static inline void process_sent_messages(void)
|
||||
{
|
||||
NtUserCallNoParam( NtUserProcessSentMessages );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_server_queue_handle
|
||||
*
|
||||
* Get a handle to the server message queue for the current thread.
|
||||
*/
|
||||
static HANDLE get_server_queue_handle(void)
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
HANDLE ret;
|
||||
|
||||
if (!(ret = thread_info->server_queue))
|
||||
{
|
||||
SERVER_START_REQ( get_msg_queue )
|
||||
{
|
||||
wine_server_call( req );
|
||||
ret = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
thread_info->server_queue = ret;
|
||||
if (!ret) ERR( "Cannot get server thread queue\n" );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wait_message_reply
|
||||
*
|
||||
* Wait until a sent message gets replied to.
|
||||
*/
|
||||
static void wait_message_reply( UINT flags )
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
HANDLE server_queue = get_server_queue_handle();
|
||||
unsigned int wake_mask = QS_SMRESULT | ((flags & SMTO_BLOCK) ? 0 : QS_SENDMESSAGE);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
unsigned int wake_bits = 0;
|
||||
|
||||
SERVER_START_REQ( set_queue_mask )
|
||||
{
|
||||
req->wake_mask = wake_mask;
|
||||
req->changed_mask = wake_mask;
|
||||
req->skip_wait = 1;
|
||||
if (!wine_server_call( req )) wake_bits = reply->wake_bits & wake_mask;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
||||
thread_info->wake_mask = thread_info->changed_mask = 0;
|
||||
|
||||
if (wake_bits & QS_SMRESULT) return; /* got a result */
|
||||
if (wake_bits & QS_SENDMESSAGE)
|
||||
{
|
||||
/* Process the sent message immediately */
|
||||
process_sent_messages();
|
||||
continue;
|
||||
}
|
||||
|
||||
wow_handlers.wait_message( 1, &server_queue, INFINITE, wake_mask, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* put_message_in_queue
|
||||
*
|
||||
|
@ -2037,146 +1621,11 @@ static BOOL put_message_in_queue( const struct send_message_info *info, size_t *
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* retrieve_reply
|
||||
*
|
||||
* Retrieve a message reply from the server.
|
||||
*/
|
||||
static LRESULT retrieve_reply( const struct send_message_info *info,
|
||||
size_t reply_size, LRESULT *result )
|
||||
{
|
||||
NTSTATUS status;
|
||||
void *reply_data = NULL;
|
||||
|
||||
if (reply_size)
|
||||
{
|
||||
if (!(reply_data = HeapAlloc( GetProcessHeap(), 0, reply_size )))
|
||||
{
|
||||
WARN( "no memory for reply, will be truncated\n" );
|
||||
reply_size = 0;
|
||||
}
|
||||
}
|
||||
SERVER_START_REQ( get_message_reply )
|
||||
{
|
||||
req->cancel = 1;
|
||||
if (reply_size) wine_server_set_reply( req, reply_data, reply_size );
|
||||
if (!(status = wine_server_call( req ))) *result = reply->result;
|
||||
reply_size = wine_server_reply_size( reply );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!status && reply_size)
|
||||
unpack_reply( info->hwnd, info->msg, info->wparam, info->lparam, reply_data, reply_size );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, reply_data );
|
||||
|
||||
TRACE( "hwnd %p msg %x (%s) wp %lx lp %lx got reply %lx (err=%d)\n",
|
||||
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam,
|
||||
info->lparam, *result, status );
|
||||
|
||||
/* MSDN states that last error is 0 on timeout, but at least NT4 returns ERROR_TIMEOUT */
|
||||
if (status) SetLastError( RtlNtStatusToDosError(status) );
|
||||
return !status;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* send_inter_thread_message
|
||||
*/
|
||||
static LRESULT send_inter_thread_message( const struct send_message_info *info, LRESULT *res_ptr )
|
||||
{
|
||||
size_t reply_size = 0;
|
||||
|
||||
TRACE( "hwnd %p msg %x (%s) wp %lx lp %lx\n",
|
||||
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam, info->lparam );
|
||||
|
||||
USER_CheckNotLock();
|
||||
|
||||
if (!put_message_in_queue( info, &reply_size )) return 0;
|
||||
|
||||
/* there's no reply to wait for on notify/callback messages */
|
||||
if (info->type == MSG_NOTIFY || info->type == MSG_CALLBACK) return 1;
|
||||
|
||||
wait_message_reply( info->flags );
|
||||
return retrieve_reply( info, reply_size, res_ptr );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* send_inter_thread_callback
|
||||
*/
|
||||
static LRESULT send_inter_thread_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
|
||||
LRESULT *result, void *arg )
|
||||
{
|
||||
struct send_message_info *info = arg;
|
||||
info->hwnd = hwnd;
|
||||
info->msg = msg;
|
||||
info->wparam = wp;
|
||||
info->lparam = lp;
|
||||
return send_inter_thread_message( info, result );
|
||||
}
|
||||
|
||||
static BOOL is_message_broadcastable(UINT msg)
|
||||
{
|
||||
return msg < WM_USER || msg >= 0xc000;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* send_message
|
||||
*
|
||||
* Backend implementation of the various SendMessage functions.
|
||||
*/
|
||||
static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BOOL unicode )
|
||||
{
|
||||
struct user_thread_info *thread_info = get_user_thread_info();
|
||||
INPUT_MESSAGE_SOURCE prev_source = thread_info->msg_source;
|
||||
DWORD dest_pid;
|
||||
BOOL ret;
|
||||
LRESULT result;
|
||||
|
||||
if (is_broadcast(info->hwnd))
|
||||
{
|
||||
if (is_message_broadcastable( info->msg ))
|
||||
EnumWindows( broadcast_message_callback, (LPARAM)info );
|
||||
if (res_ptr) *res_ptr = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!(info->dest_tid = GetWindowThreadProcessId( info->hwnd, &dest_pid ))) return FALSE;
|
||||
|
||||
if (USER_IsExitingThread( info->dest_tid )) return FALSE;
|
||||
|
||||
thread_info->msg_source = msg_source_unavailable;
|
||||
SPY_EnterMessage( SPY_SENDMESSAGE, info->hwnd, info->msg, info->wparam, info->lparam );
|
||||
|
||||
if (info->dest_tid == GetCurrentThreadId())
|
||||
{
|
||||
result = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam,
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE))
|
||||
info->type = MSG_OTHER_PROCESS;
|
||||
|
||||
/* MSG_ASCII can be sent unconverted except for WM_CHAR; everything else needs to be Unicode */
|
||||
if (!unicode && is_unicode_message( info->msg ) &&
|
||||
(info->type != MSG_ASCII || info->msg == WM_CHAR))
|
||||
ret = WINPROC_CallProcAtoW( send_inter_thread_callback, info->hwnd, info->msg,
|
||||
info->wparam, info->lparam, &result, info, info->wm_char );
|
||||
else
|
||||
ret = send_inter_thread_message( info, &result );
|
||||
}
|
||||
|
||||
SPY_ExitMessage( SPY_RESULT_OK, info->hwnd, info->msg, result, info->wparam, info->lparam );
|
||||
thread_info->msg_source = prev_source;
|
||||
if (ret && res_ptr) *res_ptr = result;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* SendMessageTimeoutW (USER32.@)
|
||||
*/
|
||||
|
@ -2268,25 +1717,12 @@ BOOL WINAPI SendNotifyMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpara
|
|||
BOOL WINAPI SendMessageCallbackA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
|
||||
SENDASYNCPROC callback, ULONG_PTR data )
|
||||
{
|
||||
struct send_message_info info;
|
||||
struct send_message_callback_params params = { .callback = callback, .data = data };
|
||||
|
||||
if (is_pointer_message( msg, wparam ))
|
||||
{
|
||||
SetLastError( ERROR_MESSAGE_SYNC_ONLY );
|
||||
if (!WIN_IsCurrentThread( hwnd ) && !map_wparam_AtoW( msg, &wparam, WMCHAR_MAP_SENDMESSAGE ))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
info.type = MSG_CALLBACK;
|
||||
info.hwnd = hwnd;
|
||||
info.msg = msg;
|
||||
info.wparam = wparam;
|
||||
info.lparam = lparam;
|
||||
info.callback = callback;
|
||||
info.data = data;
|
||||
info.flags = 0;
|
||||
info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT;
|
||||
|
||||
return send_message( &info, NULL, FALSE );
|
||||
return NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, FNID_SENDMESSAGECALLBACK, TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1474,7 +1474,7 @@ static int peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags,
|
|||
*
|
||||
* Process all pending sent messages.
|
||||
*/
|
||||
void process_sent_messages(void)
|
||||
static void process_sent_messages(void)
|
||||
{
|
||||
MSG msg;
|
||||
peek_message( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE, 0 );
|
||||
|
|
|
@ -4643,9 +4643,6 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
|
|||
/* temporary exports */
|
||||
case NtUserExitingThread:
|
||||
exiting_thread_id = GetCurrentThreadId();
|
||||
case NtUserProcessSentMessages:
|
||||
process_sent_messages();
|
||||
return 0;
|
||||
case NtUserThreadDetach:
|
||||
thread_detach();
|
||||
return 0;
|
||||
|
|
|
@ -350,7 +350,6 @@ extern HMENU get_menu( HWND hwnd ) DECLSPEC_HIDDEN;
|
|||
/* message.c */
|
||||
extern LRESULT dispatch_message( const MSG *msg, BOOL ansi ) DECLSPEC_HIDDEN;
|
||||
extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id ) DECLSPEC_HIDDEN;
|
||||
extern void process_sent_messages(void) DECLSPEC_HIDDEN;
|
||||
extern BOOL reply_message_result( LRESULT result, MSG *msg ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *rawinput,
|
||||
UINT flags ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -140,7 +140,6 @@ enum
|
|||
NtUserReleaseCapture,
|
||||
/* temporary exports */
|
||||
NtUserExitingThread,
|
||||
NtUserProcessSentMessages,
|
||||
NtUserThreadDetach,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue