Commit 9f55ae6f authored by Alexandre Julliard's avatar Alexandre Julliard

- Remove cooked hardware messages when they are dropped (reported by

Gerard Patel). - Convert all posted 32-bit messages to Unicode before storing them in the queue. - Faster implementation of MSG_IsPointerMessage. - Moved a couple of functions from queue.c to message.c.
parent ed2f19a6
...@@ -14,21 +14,6 @@ ...@@ -14,21 +14,6 @@
#include "thread.h" #include "thread.h"
/* Message as stored in the queue (contains the extraInfo field) */
typedef struct tagQMSG
{
int kind; /* message kind (sent,posted,hardware) */
int type;
MSG msg;
DWORD extraInfo; /* Only in 3.1 */
} QMSG;
#define QMSG_WIN16 0
#define QMSG_WIN32A 1
#define QMSG_WIN32W 2
#define QMSG_HARDWARE 3
/* Per-queue data for the message queue /* Per-queue data for the message queue
* Note that we currently only store the current values for * Note that we currently only store the current values for
* Active, Capture and Focus windows currently. * Active, Capture and Focus windows currently.
...@@ -82,10 +67,8 @@ extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue ); ...@@ -82,10 +67,8 @@ extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
extern void QUEUE_Unlock( MESSAGEQUEUE *queue ); extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue ); extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue ); extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
extern int QUEUE_WaitBits( WORD bits, DWORD timeout );
extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ); extern BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue );
extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue ); extern HTASK16 QUEUE_GetQueueTask( HQUEUE16 hQueue );
extern BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg );
extern void QUEUE_CleanupWindow( HWND hwnd ); extern void QUEUE_CleanupWindow( HWND hwnd );
extern HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags ); extern HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags );
......
...@@ -1379,7 +1379,7 @@ struct get_message_request ...@@ -1379,7 +1379,7 @@ struct get_message_request
}; };
#define GET_MSG_REMOVE 1 /* remove the message */ #define GET_MSG_REMOVE 1 /* remove the message */
#define GET_MSG_SENT_ONLY 2 /* only get sent messages */ #define GET_MSG_SENT_ONLY 2 /* only get sent messages */
#define GET_MSG_REMOVE_LAST 4 /* remove last message returned before checking for a new one */
/* Reply to a sent message */ /* Reply to a sent message */
struct reply_message_request struct reply_message_request
......
...@@ -73,6 +73,8 @@ struct msg_queue ...@@ -73,6 +73,8 @@ struct msg_queue
struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */ struct message_list msg_list[NB_MSG_KINDS]; /* lists of messages */
struct message_result *send_result; /* stack of sent messages waiting for result */ struct message_result *send_result; /* stack of sent messages waiting for result */
struct message_result *recv_result; /* stack of received messages waiting for result */ struct message_result *recv_result; /* stack of received messages waiting for result */
struct message *last_msg; /* last msg returned to the app and not removed */
enum message_kind last_msg_kind; /* message kind of last_msg */
struct timer *first_timer; /* head of timer list */ struct timer *first_timer; /* head of timer list */
struct timer *last_timer; /* tail of timer list */ struct timer *last_timer; /* tail of timer list */
struct timer *next_timer; /* next timer to expire */ struct timer *next_timer; /* next timer to expire */
...@@ -118,6 +120,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread ) ...@@ -118,6 +120,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread )
queue->paint_count = 0; queue->paint_count = 0;
queue->send_result = NULL; queue->send_result = NULL;
queue->recv_result = NULL; queue->recv_result = NULL;
queue->last_msg = NULL;
queue->first_timer = NULL; queue->first_timer = NULL;
queue->last_timer = NULL; queue->last_timer = NULL;
queue->next_timer = NULL; queue->next_timer = NULL;
...@@ -208,6 +211,7 @@ static void remove_queue_message( struct msg_queue *queue, struct message *msg, ...@@ -208,6 +211,7 @@ static void remove_queue_message( struct msg_queue *queue, struct message *msg,
int clr_bit; int clr_bit;
struct message *other; struct message *other;
if (queue->last_msg == msg) queue->last_msg = NULL;
unlink_message( &queue->msg_list[kind], msg ); unlink_message( &queue->msg_list[kind], msg );
switch(kind) switch(kind)
{ {
...@@ -708,6 +712,26 @@ inline static void put_req_message( struct get_message_request *req, const struc ...@@ -708,6 +712,26 @@ inline static void put_req_message( struct get_message_request *req, const struc
req->info = msg->info; req->info = msg->info;
} }
/* return a message to the application, removing it from the queue if needed */
static void return_message_to_app( struct msg_queue *queue, struct get_message_request *req,
struct message *msg, enum message_kind kind )
{
req->kind = kind;
put_req_message( req, msg );
/* raw messages always get removed */
if ((kind == RAW_HW_MESSAGE) || (req->flags & GET_MSG_REMOVE))
{
queue->last_msg = NULL;
remove_queue_message( queue, msg, kind );
}
else /* remember it as the last returned message */
{
queue->last_msg = msg;
queue->last_msg_kind = kind;
}
}
inline static struct message *find_matching_message( const struct message_list *list, handle_t win, inline static struct message *find_matching_message( const struct message_list *list, handle_t win,
unsigned int first, unsigned int last ) unsigned int first, unsigned int last )
{ {
...@@ -716,6 +740,7 @@ inline static struct message *find_matching_message( const struct message_list * ...@@ -716,6 +740,7 @@ inline static struct message *find_matching_message( const struct message_list *
for (msg = list->first; msg; msg = msg->next) for (msg = list->first; msg; msg = msg->next)
{ {
/* check against the filters */ /* check against the filters */
if (msg->msg == WM_QUIT) break; /* WM_QUIT is never filtered */
if (win && msg->win && msg->win != win) continue; if (win && msg->win && msg->win != win) continue;
if (msg->msg < first) continue; if (msg->msg < first) continue;
if (msg->msg > last) continue; if (msg->msg > last) continue;
...@@ -744,13 +769,19 @@ DECL_HANDLER(get_message) ...@@ -744,13 +769,19 @@ DECL_HANDLER(get_message)
} }
if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */ if (req->flags & GET_MSG_SENT_ONLY) goto done; /* nothing else to check */
/* if requested, remove the last returned but not yet removed message */
if ((req->flags & GET_MSG_REMOVE_LAST) && queue->last_msg)
remove_queue_message( queue, queue->last_msg, queue->last_msg_kind );
queue->last_msg = NULL;
/* clear changed bits so we can wait on them if we don't find a message */
queue->changed_bits = 0;
/* then check for posted messages */ /* then check for posted messages */
if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win, if ((msg = find_matching_message( &queue->msg_list[POST_MESSAGE], req->get_win,
req->get_first, req->get_last ))) req->get_first, req->get_last )))
{ {
req->kind = POST_MESSAGE; return_message_to_app( queue, req, msg, POST_MESSAGE );
put_req_message( req, msg );
if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, POST_MESSAGE );
return; return;
} }
...@@ -758,19 +789,14 @@ DECL_HANDLER(get_message) ...@@ -758,19 +789,14 @@ DECL_HANDLER(get_message)
if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win, if ((msg = find_matching_message( &queue->msg_list[COOKED_HW_MESSAGE], req->get_win,
req->get_first, req->get_last ))) req->get_first, req->get_last )))
{ {
req->kind = COOKED_HW_MESSAGE; return_message_to_app( queue, req, msg, COOKED_HW_MESSAGE );
put_req_message( req, msg );
if (req->flags & GET_MSG_REMOVE) remove_queue_message( queue, msg, COOKED_HW_MESSAGE );
return; return;
} }
/* then check for any raw hardware message */ /* then check for any raw hardware message */
if ((msg = queue->msg_list[RAW_HW_MESSAGE].first)) if ((msg = queue->msg_list[RAW_HW_MESSAGE].first))
{ {
req->kind = RAW_HW_MESSAGE; return_message_to_app( queue, req, msg, RAW_HW_MESSAGE );
put_req_message( req, msg );
/* raw messages always get removed */
remove_queue_message( queue, msg, RAW_HW_MESSAGE );
return; return;
} }
......
...@@ -88,7 +88,7 @@ static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lPar ...@@ -88,7 +88,7 @@ static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lPar
{ {
req->kind = RAW_HW_MESSAGE; req->kind = RAW_HW_MESSAGE;
req->id = (void *)GetCurrentThreadId(); req->id = (void *)GetCurrentThreadId();
req->type = QMSG_HARDWARE; req->type = 0;
req->win = 0; req->win = 0;
req->msg = message; req->msg = message;
req->wparam = wParam; req->wparam = wParam;
......
...@@ -36,8 +36,109 @@ DECLARE_DEBUG_CHANNEL(key); ...@@ -36,8 +36,109 @@ DECLARE_DEBUG_CHANNEL(key);
#define WM_NCMOUSEFIRST WM_NCMOUSEMOVE #define WM_NCMOUSEFIRST WM_NCMOUSEMOVE
#define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK #define WM_NCMOUSELAST WM_NCMBUTTONDBLCLK
#define QMSG_WIN16 1
#define QMSG_WIN32A 2
#define QMSG_WIN32W 3
static UINT doubleClickSpeed = 452; static UINT doubleClickSpeed = 452;
static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType );
/* flag for messages that contain pointers */
/* 16 messages per entry, messages 0..15 map to bits 0..15 */
#define SET(msg) (1 << ((msg) & 15))
static const unsigned short message_pointer_flags[] =
{
/* 0x00 - 0x0f */
SET(WM_CREATE) | SET(WM_GETTEXT) | SET(WM_SETTEXT),
/* 0x10 - 0x1f */
SET(WM_WININICHANGE),
/* 0x20 - 0x2f */
SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM),
/* 0x30 - 0x3f */
SET(WM_COMPAREITEM),
/* 0x40 - 0x4f */
SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) | SET(WM_NOTIFY),
/* 0x50 - 0x5f */
SET(WM_HELP),
/* 0x60 - 0x6f */
0,
/* 0x70 - 0x7f */
SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED),
/* 0x80 - 0x8f */
SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE),
/* 0x90 - 0x9f */
0,
/* 0xa0 - 0xaf */
0,
/* 0xb0 - 0xbf */
SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP),
/* 0xc0 - 0xcf */
SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS),
/* 0xd0 - 0xdf */
0,
/* 0xe0 - 0xef */
0,
/* 0xf0 - 0xff */
0,
/* 0x100 - 0x10f */
0,
/* 0x110 - 0x11f */
0,
/* 0x120 - 0x12f */
0,
/* 0x130 - 0x13f */
0,
/* 0x140 - 0x14f */
SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) | SET(CB_INSERTSTRING) |
SET(CB_FINDSTRING) | SET(CB_SELECTSTRING),
/* 0x150 - 0x15f */
SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT),
/* 0x160 - 0x16f */
0,
/* 0x170 - 0x17f */
0,
/* 0x180 - 0x18f */
SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) |
SET(LB_DIR) | SET(LB_FINDSTRING),
/* 0x190 - 0x19f */
SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT),
/* 0x1a0 - 0x1af */
SET(LB_FINDSTRINGEXACT),
/* 0x1b0 - 0x1bf */
0,
/* 0x1c0 - 0x1cf */
0,
/* 0x1d0 - 0x1df */
0,
/* 0x1e0 - 0x1ef */
0,
/* 0x1f0 - 0x1ff */
0,
/* 0x200 - 0x20f */
0,
/* 0x210 - 0x21f */
0,
/* 0x220 - 0x22f */
SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) |
SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE)
};
#undef SET
/***********************************************************************
* is_pointer_message
*/
inline static int is_pointer_message( UINT message )
{
if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
return (message_pointer_flags[message / 16] & (1 << (message & 15))) != 0;
}
/*********************************************************************** /***********************************************************************
* is_keyboard_message * is_keyboard_message
...@@ -76,6 +177,54 @@ inline static BOOL check_message_filter( const MSG *msg, HWND hwnd, UINT first, ...@@ -76,6 +177,54 @@ inline static BOOL check_message_filter( const MSG *msg, HWND hwnd, UINT first,
/*********************************************************************** /***********************************************************************
* map_wparam_AtoW
*
* Convert the wparam of an ASCII message to Unicode.
*/
static WPARAM map_wparam_AtoW( UINT message, WPARAM wparam )
{
if (message == WM_CHARTOITEM ||
message == EM_SETPASSWORDCHAR ||
message == WM_CHAR ||
message == WM_DEADCHAR ||
message == WM_SYSCHAR ||
message == WM_SYSDEADCHAR ||
message == WM_MENUCHAR)
{
char ch = LOWORD(wparam);
WCHAR wch;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
wparam = MAKEWPARAM( wch, HIWORD(wparam) );
}
return wparam;
}
/***********************************************************************
* map_wparam_WtoA
*
* Convert the wparam of a Unicode message to ASCII.
*/
static WPARAM map_wparam_WtoA( UINT message, WPARAM wparam )
{
if (message == WM_CHARTOITEM ||
message == EM_SETPASSWORDCHAR ||
message == WM_CHAR ||
message == WM_DEADCHAR ||
message == WM_SYSCHAR ||
message == WM_SYSDEADCHAR ||
message == WM_MENUCHAR)
{
WCHAR wch = LOWORD(wparam);
char ch;
WideCharToMultiByte( CP_ACP, 0, &wch, 1, &ch, 1, NULL, NULL );
wparam = MAKEWPARAM( ch, HIWORD(wparam) );
}
return wparam;
}
/***********************************************************************
* queue_hardware_message * queue_hardware_message
* *
* store a hardware message in the thread queue * store a hardware message in the thread queue
...@@ -86,7 +235,7 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message ...@@ -86,7 +235,7 @@ static void queue_hardware_message( MSG *msg, ULONG_PTR extra_info, enum message
{ {
req->kind = kind; req->kind = kind;
req->id = (void *)GetWindowThreadProcessId( msg->hwnd, NULL ); req->id = (void *)GetWindowThreadProcessId( msg->hwnd, NULL );
req->type = QMSG_HARDWARE; req->type = 0;
req->win = msg->hwnd; req->win = msg->hwnd;
req->msg = msg->message; req->msg = msg->message;
req->wparam = msg->wParam; req->wparam = msg->wParam;
...@@ -476,47 +625,294 @@ static BOOL process_cooked_mouse_message( MSG *msg, BOOL remove ) ...@@ -476,47 +625,294 @@ static BOOL process_cooked_mouse_message( MSG *msg, BOOL remove )
* *
* returns TRUE if the contents of 'msg' should be passed to the application * returns TRUE if the contents of 'msg' should be passed to the application
*/ */
static BOOL process_hardware_message( QMSG *qmsg, HWND hwnd_filter, static BOOL process_raw_hardware_message( MSG *msg, ULONG_PTR extra_info, HWND hwnd_filter,
UINT first, UINT last, BOOL remove ) UINT first, UINT last, BOOL remove )
{ {
if (qmsg->kind == RAW_HW_MESSAGE) if (is_keyboard_message( msg->message ))
{ {
/* if it is raw, try to cook it first */ if (!process_raw_keyboard_message( msg, extra_info )) return FALSE;
if (is_keyboard_message( qmsg->msg.message )) }
else if (is_mouse_message( msg->message ))
{ {
if (!process_raw_keyboard_message( &qmsg->msg, qmsg->extraInfo )) return FALSE; if (!process_raw_mouse_message( msg, extra_info )) return FALSE;
} }
else if (is_mouse_message( qmsg->msg.message )) else
{ {
if (!process_raw_mouse_message( &qmsg->msg, qmsg->extraInfo )) return FALSE; ERR( "unknown message type %x\n", msg->message );
return FALSE;
} }
else goto invalid;
/* check destination thread and filters */ /* check destination thread and filters */
if (!check_message_filter( &qmsg->msg, hwnd_filter, first, last ) || if (!check_message_filter( msg, hwnd_filter, first, last ) ||
GetWindowThreadProcessId( qmsg->msg.hwnd, NULL ) != GetCurrentThreadId()) GetWindowThreadProcessId( msg->hwnd, NULL ) != GetCurrentThreadId())
{ {
/* queue it for later, or for another thread */ /* queue it for later, or for another thread */
queue_hardware_message( &qmsg->msg, qmsg->extraInfo, COOKED_HW_MESSAGE ); queue_hardware_message( msg, extra_info, COOKED_HW_MESSAGE );
return FALSE; return FALSE;
} }
/* save the message in the cooked queue if we didn't want to remove it */ /* save the message in the cooked queue if we didn't want to remove it */
if (!remove) queue_hardware_message( &qmsg->msg, qmsg->extraInfo, COOKED_HW_MESSAGE ); if (!remove) queue_hardware_message( msg, extra_info, COOKED_HW_MESSAGE );
} return TRUE;
}
if (is_keyboard_message( qmsg->msg.message )) /***********************************************************************
return process_cooked_keyboard_message( &qmsg->msg, remove ); * process_cooked_hardware_message
*
* returns TRUE if the contents of 'msg' should be passed to the application
*/
static BOOL process_cooked_hardware_message( MSG *msg, BOOL remove )
{
if (is_keyboard_message( msg->message ))
return process_cooked_keyboard_message( msg, remove );
if (is_mouse_message( qmsg->msg.message )) if (is_mouse_message( msg->message ))
return process_cooked_mouse_message( &qmsg->msg, remove ); return process_cooked_mouse_message( msg, remove );
invalid: ERR( "unknown message type %x\n", msg->message );
ERR( "unknown message type %x\n", qmsg->msg.message );
return FALSE; return FALSE;
} }
/***********************************************************************
* handle_sent_message
*
* Handle the reception of a sent message by calling the corresponding window proc
*/
static void handle_sent_message( MSG *msg, int type, ULONG_PTR extra_info )
{
LRESULT result = 0;
MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
ULONG_PTR old_extra_info = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
WND *wndPtr = WIN_FindWndPtr( msg->hwnd );
TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
msg->hwnd, msg->message, SPY_GetMsgName(msg->message),
msg->wParam, msg->lParam );
queue->GetMessageExtraInfoVal = extra_info;
/* call the right version of CallWindowProcXX */
switch(type)
{
case QMSG_WIN16:
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
(HWND16) msg->hwnd,
(UINT16) msg->message,
LOWORD(msg->wParam),
msg->lParam );
break;
case QMSG_WIN32A:
result = CallWindowProcA( wndPtr->winproc, msg->hwnd, msg->message,
msg->wParam, msg->lParam );
break;
case QMSG_WIN32W:
result = CallWindowProcW( wndPtr->winproc, msg->hwnd, msg->message,
msg->wParam, msg->lParam );
break;
}
queue->GetMessageExtraInfoVal = old_extra_info; /* Restore extra info */
WIN_ReleaseWndPtr(wndPtr);
QUEUE_Unlock( queue );
SERVER_START_REQ( reply_message )
{
req->result = result;
req->remove = 1;
SERVER_CALL();
}
SERVER_END_REQ;
}
/***********************************************************************
* process_sent_messages
*
* Process all pending sent messages
*/
static void process_sent_messages(void)
{
MSG msg;
int type;
unsigned int res;
ULONG_PTR extra_info;
for (;;)
{
SERVER_START_REQ( get_message )
{
req->flags = GET_MSG_REMOVE | GET_MSG_SENT_ONLY;
req->get_win = 0;
req->get_first = 0;
req->get_last = ~0;
if (!(res = SERVER_CALL()))
{
type = req->type;
msg.hwnd = req->win;
msg.message = req->msg;
msg.wParam = req->wparam;
msg.lParam = req->lparam;
msg.time = req->time;
msg.pt.x = req->x;
msg.pt.y = req->y;
extra_info = req->info;
}
}
SERVER_END_REQ;
if (res) break;
handle_sent_message( &msg, type, extra_info );
}
}
/***********************************************************************
* peek_message
*
* Peek for a message matching the given parameters. Return FALSE if none available.
*/
static BOOL peek_message( HWND hwnd, UINT first, UINT last, int flags, int type,
MSG *msg, ULONG_PTR *extra_info )
{
BOOL ret = FALSE;
enum message_kind kind;
int msg_type;
if (!first && !last) last = ~0;
for (;;)
{
SERVER_START_REQ( get_message )
{
req->flags = flags;
req->get_win = hwnd;
req->get_first = first;
req->get_last = last;
if ((ret = !SERVER_CALL()))
{
kind = req->kind;
msg_type = req->type;
msg->hwnd = req->win;
msg->message = req->msg;
msg->wParam = req->wparam;
msg->lParam = req->lparam;
msg->time = req->time;
msg->pt.x = req->x;
msg->pt.y = req->y;
*extra_info = req->info;
}
}
SERVER_END_REQ;
if (!ret) return FALSE;
switch(kind)
{
case SEND_MESSAGE:
handle_sent_message( msg, msg_type, *extra_info );
continue;
case POST_MESSAGE:
/* try to convert message to requested type */
if (!MSG_ConvertMsg( msg, msg_type, type ))
{
ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
SPY_GetMsgName(msg->message));
/* remove it */
flags |= GET_MSG_REMOVE_LAST;
continue;
}
break;
case RAW_HW_MESSAGE:
if (!process_raw_hardware_message( msg, *extra_info,
hwnd, first, last, flags & GET_MSG_REMOVE ))
continue;
/* fall through */
case COOKED_HW_MESSAGE:
if (!process_cooked_hardware_message( msg, flags & GET_MSG_REMOVE ))
{
flags |= GET_MSG_REMOVE_LAST;
continue;
}
break;
}
/* now we got something */
TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
msg->hwnd, msg->message, SPY_GetMsgName(msg->message),
msg->wParam, msg->lParam );
return TRUE;
}
}
/***********************************************************************
* wait_queue_bits
*
* See "Windows Internals", p.447
*
* return values:
* 0 if exit with timeout
* 1 otherwise
*/
static int wait_queue_bits( WORD bits, DWORD timeout )
{
MESSAGEQUEUE *queue;
HQUEUE16 hQueue;
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
hQueue = GetFastQueue16();
if (!(queue = QUEUE_Lock( hQueue ))) return 0;
for (;;)
{
unsigned int wake_bits = 0, changed_bits = 0;
DWORD dwlc;
SERVER_START_REQ( set_queue_mask )
{
req->wake_mask = QS_SENDMESSAGE;
req->changed_mask = bits | QS_SENDMESSAGE;
req->skip_wait = 1;
if (!SERVER_CALL())
{
wake_bits = req->wake_bits;
changed_bits = req->changed_bits;
}
}
SERVER_END_REQ;
if (changed_bits & bits)
{
/* One of the bits is set; we can return */
QUEUE_Unlock( queue );
return 1;
}
if (wake_bits & QS_SENDMESSAGE)
{
/* Process the sent message immediately */
process_sent_messages();
continue; /* nested sm crux */
}
TRACE_(msg)("(%04x) mask=%08x, bits=%08x, changed=%08x, waiting\n",
queue->self, bits, wake_bits, changed_bits );
ReleaseThunkLock( &dwlc );
if (dwlc) TRACE_(msg)("had win16 lock\n");
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, timeout, 0, 0 );
else
WaitForSingleObject( queue->server_queue, timeout );
if (dwlc) RestoreThunkLock( dwlc );
}
}
/********************************************************************** /**********************************************************************
* SetDoubleClickTime (USER.20) * SetDoubleClickTime (USER.20)
*/ */
...@@ -594,7 +990,7 @@ static LRESULT MSG_SendMessageInterThread( DWORD dest_tid, HWND hwnd, UINT msg, ...@@ -594,7 +990,7 @@ static LRESULT MSG_SendMessageInterThread( DWORD dest_tid, HWND hwnd, UINT msg,
iWndsLocks = WIN_SuspendWndsLock(); iWndsLocks = WIN_SuspendWndsLock();
/* wait for the result */ /* wait for the result */
QUEUE_WaitBits( QS_SMRESULT, timeout ); wait_queue_bits( QS_SMRESULT, timeout );
SERVER_START_REQ( get_message_reply ) SERVER_START_REQ( get_message_reply )
{ {
...@@ -648,30 +1044,20 @@ BOOL WINAPI ReplyMessage( LRESULT result ) ...@@ -648,30 +1044,20 @@ BOOL WINAPI ReplyMessage( LRESULT result )
*/ */
static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType ) static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType )
{ {
UINT16 msg16; if (srcType == QMSG_WIN32A || dstType == QMSG_WIN32A)
MSGPARAM16 mp16;
switch ( MAKELONG( srcType, dstType ) )
{
case MAKELONG( QMSG_WIN16, QMSG_WIN16 ):
case MAKELONG( QMSG_WIN32A, QMSG_WIN32A ):
case MAKELONG( QMSG_WIN32W, QMSG_WIN32W ):
return TRUE;
case MAKELONG( QMSG_WIN16, QMSG_WIN32A ):
switch ( WINPROC_MapMsg16To32A( msg->message, msg->wParam,
&msg->message, &msg->wParam, &msg->lParam ) )
{ {
case 0: /* posted messages are always either Win16 or Unicode Win32,
return TRUE; * QMSG_WIN32A is only for sent messages */
case 1: ERR( "invalid type %d/%d\n", srcType, dstType );
/* Pointer messages were mapped --> need to free allocated memory and fail */
WINPROC_UnmapMsg16To32A( msg->hwnd, msg->message, msg->wParam, msg->lParam, 0 );
default:
return FALSE; return FALSE;
} }
case MAKELONG( QMSG_WIN16, QMSG_WIN32W ): if (!srcType || srcType == dstType) return TRUE;
if (srcType == QMSG_WIN16)
{
if (dstType == QMSG_WIN32W)
{
switch ( WINPROC_MapMsg16To32W( msg->hwnd, msg->message, msg->wParam, switch ( WINPROC_MapMsg16To32W( msg->hwnd, msg->message, msg->wParam,
&msg->message, &msg->wParam, &msg->lParam ) ) &msg->message, &msg->wParam, &msg->lParam ) )
{ {
...@@ -683,25 +1069,15 @@ static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType ) ...@@ -683,25 +1069,15 @@ static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType )
default: default:
return FALSE; return FALSE;
} }
case MAKELONG( QMSG_WIN32A, QMSG_WIN16 ):
mp16.lParam = msg->lParam;
switch ( WINPROC_MapMsg32ATo16( msg->hwnd, msg->message, msg->wParam,
&msg16, &mp16.wParam, &mp16.lParam ) )
{
case 0:
msg->message = msg16;
msg->wParam = mp16.wParam;
msg->lParam = mp16.lParam;
return TRUE;
case 1:
/* Pointer messages were mapped --> need to free allocated memory and fail */
WINPROC_UnmapMsg32ATo16( msg->hwnd, msg->message, msg->wParam, msg->lParam, &mp16 );
default:
return FALSE;
} }
}
else if (srcType == QMSG_WIN32W)
{
if (dstType == QMSG_WIN16)
{
UINT16 msg16;
MSGPARAM16 mp16;
case MAKELONG( QMSG_WIN32W, QMSG_WIN16 ):
mp16.lParam = msg->lParam; mp16.lParam = msg->lParam;
switch ( WINPROC_MapMsg32WTo16( msg->hwnd, msg->message, msg->wParam, switch ( WINPROC_MapMsg32WTo16( msg->hwnd, msg->message, msg->wParam,
&msg16, &mp16.wParam, &mp16.lParam ) ) &msg16, &mp16.wParam, &mp16.lParam ) )
...@@ -717,47 +1093,25 @@ static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType ) ...@@ -717,47 +1093,25 @@ static BOOL MSG_ConvertMsg( MSG *msg, int srcType, int dstType )
default: default:
return FALSE; return FALSE;
} }
case MAKELONG( QMSG_WIN32A, QMSG_WIN32W ):
switch ( WINPROC_MapMsg32ATo32W( msg->hwnd, msg->message, &msg->wParam, &msg->lParam ) )
{
case 0:
return TRUE;
case 1:
/* Pointer messages were mapped --> need to free allocated memory and fail */
WINPROC_UnmapMsg32ATo32W( msg->hwnd, msg->message, msg->wParam, msg->lParam );
default:
return FALSE;
} }
case MAKELONG( QMSG_WIN32W, QMSG_WIN32A ):
switch ( WINPROC_MapMsg32WTo32A( msg->hwnd, msg->message, &msg->wParam, &msg->lParam ) )
{
case 0:
return TRUE;
case 1:
/* Pointer messages were mapped --> need to free allocated memory and fail */
WINPROC_UnmapMsg32WTo32A( msg->hwnd, msg->message, msg->wParam, msg->lParam );
default:
return FALSE;
} }
default:
FIXME( "Invalid message type(s): %d / %d\n", srcType, dstType ); FIXME( "Invalid message type(s): %d / %d\n", srcType, dstType );
return FALSE; return FALSE;
}
} }
/*********************************************************************** /***********************************************************************
* MSG_PeekMessage * MSG_PeekMessage
*/ */
static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd, static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
DWORD first, DWORD last, WORD flags, BOOL peek ) DWORD first, DWORD last, WORD flags, BOOL peek )
{ {
int mask; int mask, msg_flags = 0;
MESSAGEQUEUE *msgQueue; MESSAGEQUEUE *msgQueue;
int iWndsLocks; int iWndsLocks;
QMSG qmsg; MSG msg;
ULONG_PTR extra_info;
mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */ mask = QS_POSTMESSAGE | QS_SENDMESSAGE; /* Always selected */
if (first || last) if (first || last)
...@@ -779,46 +1133,26 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd, ...@@ -779,46 +1133,26 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
if (USER_Driver.pMsgWaitForMultipleObjectsEx) if (USER_Driver.pMsgWaitForMultipleObjectsEx)
USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 ); USER_Driver.pMsgWaitForMultipleObjectsEx( 0, NULL, 0, 0, 0 );
while(1) if (flags & PM_REMOVE) msg_flags |= GET_MSG_REMOVE;
{
/* FIXME: should remove this */
WORD wakeBits = HIWORD(GetQueueStatus( mask ));
retry: while(1)
if (QUEUE_FindMsg( hwnd, first, last, flags & PM_REMOVE, &qmsg ))
{
if (qmsg.kind == RAW_HW_MESSAGE || qmsg.kind == COOKED_HW_MESSAGE)
{
if (!process_hardware_message( &qmsg, hwnd, first, last, flags & PM_REMOVE ))
goto retry;
}
else
{ {
/* Try to convert message to requested type */ if (peek_message( hwnd, first, last, msg_flags, type, &msg, &extra_info ))
if ( !MSG_ConvertMsg( &qmsg.msg, qmsg.type, type ) )
{ {
ERR( "Message %s of wrong type contains pointer parameters. Skipped!\n",
SPY_GetMsgName(qmsg.msg.message));
/* remove it (FIXME) */
if (!(flags & PM_REMOVE)) QUEUE_FindMsg( hwnd, first, last, TRUE, &qmsg );
goto retry;
}
}
/* need to fill the window handle for WM_PAINT message */ /* need to fill the window handle for WM_PAINT message */
if (qmsg.msg.message == WM_PAINT) if (msg.message == WM_PAINT)
{ {
if ((qmsg.msg.hwnd = WIN_FindWinToRepaint( hwnd ))) if ((msg.hwnd = WIN_FindWinToRepaint( hwnd )))
{ {
if (IsIconic( qmsg.msg.hwnd ) && GetClassLongA( qmsg.msg.hwnd, GCL_HICON )) if (IsIconic( msg.hwnd ) && GetClassLongA( msg.hwnd, GCL_HICON ))
{ {
qmsg.msg.message = WM_PAINTICON; msg.message = WM_PAINTICON;
qmsg.msg.wParam = 1; msg.wParam = 1;
} }
if( !hwnd || qmsg.msg.hwnd == hwnd || IsChild(hwnd,qmsg.msg.hwnd) ) if( !hwnd || msg.hwnd == hwnd || IsChild(hwnd,msg.hwnd) )
{ {
/* clear internal paint flag */ /* clear internal paint flag */
RedrawWindow( qmsg.msg.hwnd, NULL, 0, RedrawWindow( msg.hwnd, NULL, 0,
RDW_NOINTERNALPAINT | RDW_NOCHILDREN ); RDW_NOINTERNALPAINT | RDW_NOCHILDREN );
break; break;
} }
...@@ -839,46 +1173,44 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd, ...@@ -839,46 +1173,44 @@ static BOOL MSG_PeekMessage( int type, LPMSG msg_out, HWND hwnd,
return FALSE; return FALSE;
} }
QUEUE_WaitBits( mask, INFINITE ); wait_queue_bits( mask, INFINITE );
} }
WIN_RestoreWndsLock(iWndsLocks); WIN_RestoreWndsLock(iWndsLocks);
if ((msgQueue = QUEUE_Lock( GetFastQueue16() ))) if ((msgQueue = QUEUE_Lock( GetFastQueue16() )))
{ {
msgQueue->GetMessageTimeVal = qmsg.msg.time; msgQueue->GetMessageTimeVal = msg.time;
msgQueue->GetMessagePosVal = MAKELONG( qmsg.msg.pt.x, qmsg.msg.pt.y ); msgQueue->GetMessagePosVal = MAKELONG( msg.pt.x, msg.pt.y );
msgQueue->GetMessageExtraInfoVal = qmsg.extraInfo; msgQueue->GetMessageExtraInfoVal = extra_info;
QUEUE_Unlock( msgQueue ); QUEUE_Unlock( msgQueue );
} }
/* We got a message */ /* We got a message */
if (flags & PM_REMOVE) if (flags & PM_REMOVE)
{ {
WORD message = qmsg.msg.message; if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
{ {
BYTE *p = &QueueKeyStateTable[qmsg.msg.wParam & 0xff]; BYTE *p = &QueueKeyStateTable[msg.wParam & 0xff];
if (!(*p & 0x80)) if (!(*p & 0x80))
*p ^= 0x01; *p ^= 0x01;
*p |= 0x80; *p |= 0x80;
} }
else if (message == WM_KEYUP || message == WM_SYSKEYUP) else if (msg.message == WM_KEYUP || msg.message == WM_SYSKEYUP)
QueueKeyStateTable[qmsg.msg.wParam & 0xff] &= ~0x80; QueueKeyStateTable[msg.wParam & 0xff] &= ~0x80;
} }
/* copy back our internal safe copy of message data to msg_out. /* copy back our internal safe copy of message data to msg_out.
* msg_out is a variable from the *program*, so it can't be used * msg_out is a variable from the *program*, so it can't be used
* internally as it can get "corrupted" by our use of SendMessage() * internally as it can get "corrupted" by our use of SendMessage()
* (back to the program) inside the message handling itself. */ * (back to the program) inside the message handling itself. */
*msg_out = qmsg.msg; *msg_out = msg;
if (peek) if (peek)
return TRUE; return TRUE;
else else
return (qmsg.msg.message != WM_QUIT); return (msg.message != WM_QUIT);
} }
/*********************************************************************** /***********************************************************************
...@@ -896,7 +1228,7 @@ BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd, HWND hwndOwner, UINT first, UI ...@@ -896,7 +1228,7 @@ BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd, HWND hwndOwner, UINT first, UI
{ {
if (sendIdle) if (sendIdle)
{ {
if (!MSG_PeekMessage( QMSG_WIN32A, msg, 0, first, last, flags, TRUE )) if (!MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, TRUE ))
{ {
/* No message present -> send ENTERIDLE and wait */ /* No message present -> send ENTERIDLE and wait */
if (IsWindow(hwndOwner)) if (IsWindow(hwndOwner))
...@@ -907,38 +1239,29 @@ BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd, HWND hwndOwner, UINT first, UI ...@@ -907,38 +1239,29 @@ BOOL MSG_InternalGetMessage( MSG *msg, HWND hwnd, HWND hwndOwner, UINT first, UI
if (idleSent!=NULL) if (idleSent!=NULL)
*idleSent=TRUE; *idleSent=TRUE;
} }
MSG_PeekMessage( QMSG_WIN32A, msg, 0, first, last, flags, FALSE ); MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, FALSE );
} }
} }
else /* Always wait for a message */ else /* Always wait for a message */
MSG_PeekMessage( QMSG_WIN32A, msg, 0, first, last, flags, FALSE ); MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, flags, FALSE );
/* Call message filters */ /* Call message filters */
if (HOOK_IsHooked( WH_SYSMSGFILTER ) || HOOK_IsHooked( WH_MSGFILTER )) if (HOOK_IsHooked( WH_SYSMSGFILTER ) || HOOK_IsHooked( WH_MSGFILTER ))
{ {
MSG *pmsg = HeapAlloc( GetProcessHeap(), 0, sizeof(MSG) ); MSG tmp_msg = *msg;
if (pmsg)
{
BOOL ret;
*pmsg = *msg;
ret = (HOOK_CallHooksA( WH_SYSMSGFILTER, code, 0,
(LPARAM) pmsg ) ||
HOOK_CallHooksA( WH_MSGFILTER, code, 0,
(LPARAM) pmsg ));
HeapFree( GetProcessHeap(), 0, pmsg ); if (HOOK_CallHooksW( WH_SYSMSGFILTER, code, 0, (LPARAM)&tmp_msg ) ||
if (ret) HOOK_CallHooksW( WH_MSGFILTER, code, 0, (LPARAM)&tmp_msg ))
{ {
/* Message filtered -> remove it from the queue */ /* Message filtered -> remove it from the queue if it's still there. */
/* if it's still there. */
if (!(flags & PM_REMOVE)) if (!(flags & PM_REMOVE))
MSG_PeekMessage( QMSG_WIN32A, msg, 0, first, last, PM_REMOVE, TRUE ); MSG_PeekMessage( QMSG_WIN32W, msg, 0, first, last, PM_REMOVE, TRUE );
continue; continue;
} }
} }
} /* need to return an ASCII message (FIXME) */
msg->wParam = map_wparam_WtoA( msg->message, msg->wParam );
return (msg->message != WM_QUIT); return (msg->message != WM_QUIT);
} }
} }
...@@ -984,16 +1307,10 @@ BOOL16 WINAPI PeekMessage16( SEGPTR msg, HWND16 hwnd, ...@@ -984,16 +1307,10 @@ BOOL16 WINAPI PeekMessage16( SEGPTR msg, HWND16 hwnd,
/*********************************************************************** /***********************************************************************
* PeekMessageA (USER32.@) * PeekMessageA (USER32.@)
*/ */
BOOL WINAPI PeekMessageA( LPMSG lpmsg, HWND hwnd, BOOL WINAPI PeekMessageA( LPMSG lpmsg, HWND hwnd, UINT min, UINT max, UINT flags )
UINT min, UINT max, UINT wRemoveMsg)
{ {
BOOL ret = MSG_PeekMessage( QMSG_WIN32A, lpmsg, hwnd, min, max, wRemoveMsg, TRUE ); BOOL ret = PeekMessageW( lpmsg, hwnd, min, max, flags );
if (ret) lpmsg->wParam = map_wparam_WtoA( lpmsg->message, lpmsg->wParam );
TRACE( "peekmessage %04x, hwnd %04x, filter(%04x - %04x)\n",
lpmsg->message, hwnd, min, max );
if (ret) HOOK_CallHooksA( WH_GETMESSAGE, HC_ACTION,
wRemoveMsg & PM_REMOVE, (LPARAM)lpmsg );
return ret; return ret;
} }
...@@ -1081,12 +1398,8 @@ BOOL16 WINAPI GetMessage16( SEGPTR msg, HWND16 hwnd, UINT16 first, UINT16 last) ...@@ -1081,12 +1398,8 @@ BOOL16 WINAPI GetMessage16( SEGPTR msg, HWND16 hwnd, UINT16 first, UINT16 last)
*/ */
BOOL WINAPI GetMessageA( MSG *lpmsg, HWND hwnd, UINT min, UINT max ) BOOL WINAPI GetMessageA( MSG *lpmsg, HWND hwnd, UINT min, UINT max )
{ {
MSG_PeekMessage( QMSG_WIN32A, lpmsg, hwnd, min, max, PM_REMOVE, FALSE ); GetMessageW( lpmsg, hwnd, min, max );
lpmsg->wParam = map_wparam_WtoA( lpmsg->message, lpmsg->wParam );
TRACE( "message %04x, hwnd %04x, filter(%04x - %04x)\n",
lpmsg->message, hwnd, min, max );
HOOK_CallHooksA( WH_GETMESSAGE, HC_ACTION, PM_REMOVE, (LPARAM)lpmsg );
return lpmsg->message != WM_QUIT; return lpmsg->message != WM_QUIT;
} }
...@@ -1172,79 +1485,6 @@ static BOOL MSG_PostToQueue( DWORD tid, int type, HWND hwnd, ...@@ -1172,79 +1485,6 @@ static BOOL MSG_PostToQueue( DWORD tid, int type, HWND hwnd,
/*********************************************************************** /***********************************************************************
* MSG_IsPointerMessage
*
* Check whether this message (may) contain pointers.
* Those messages may not be PostMessage()d or GetMessage()d, but are dropped.
*
* FIXME: list of pointer messages might be incomplete.
*
* (We could do a generic !IsBadWritePtr() check, but this would cause too
* much slow down I think. MM20010206)
*/
static BOOL MSG_IsPointerMessage(UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE:
case WM_NCCREATE:
case WM_COMPAREITEM:
case WM_DELETEITEM:
case WM_MEASUREITEM:
case WM_DRAWITEM:
case WM_GETMINMAXINFO:
case WM_GETTEXT:
case WM_SETTEXT:
case WM_MDICREATE:
case WM_MDIGETACTIVE:
case WM_NCCALCSIZE:
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
case WM_NOTIFY:
case WM_GETDLGCODE:
case WM_WININICHANGE:
case WM_HELP:
case WM_COPYDATA:
case WM_STYLECHANGING:
case WM_STYLECHANGED:
case WM_DROPOBJECT:
case WM_DRAGMOVE:
case WM_DRAGSELECT:
case WM_QUERYDROPOBJECT:
case CB_DIR:
case CB_ADDSTRING:
case CB_INSERTSTRING:
case CB_FINDSTRING:
case CB_FINDSTRINGEXACT:
case CB_SELECTSTRING:
case CB_GETLBTEXT:
case CB_GETDROPPEDCONTROLRECT:
case LB_DIR:
case LB_ADDFILE:
case LB_ADDSTRING:
case LB_INSERTSTRING:
case LB_GETTEXT:
case LB_GETITEMRECT:
case LB_FINDSTRING:
case LB_FINDSTRINGEXACT:
case LB_SELECTSTRING:
case LB_GETSELITEMS:
case LB_SETTABSTOPS:
case EM_REPLACESEL:
case EM_GETSEL:
case EM_GETRECT:
case EM_SETRECT:
case EM_SETRECTNP:
case EM_GETLINE:
case EM_SETTABSTOPS:
return TRUE;
default:
return FALSE;
}
}
/***********************************************************************
* MSG_PostMessage * MSG_PostMessage
*/ */
static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message, static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
...@@ -1252,20 +1492,6 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message, ...@@ -1252,20 +1492,6 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
{ {
WND *wndPtr; WND *wndPtr;
/* See thread on wine-devel around 6.2.2001. Basically posted messages
* that are known to contain pointers are dropped by the Windows 32bit
* PostMessage() with return FALSE; and invalid parameter last error.
* (tested against NT4 by Gerard Patel)
* 16 bit does not care, so we don't either.
*/
if ( (type!=QMSG_WIN16) && MSG_IsPointerMessage(message,wParam,lParam)) {
FIXME("Ignoring posted pointer message 0x%04x to hwnd 0x%04x.\n",
message,hwnd
);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (hwnd == HWND_BROADCAST) if (hwnd == HWND_BROADCAST)
{ {
WND *pDesktop = WIN_GetDesktop(); WND *pDesktop = WIN_GetDesktop();
...@@ -1290,6 +1516,7 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message, ...@@ -1290,6 +1516,7 @@ static BOOL MSG_PostMessage( int type, HWND hwnd, UINT message,
type, hwnd, message, wParam, lParam ); type, hwnd, message, wParam, lParam );
} }
/*********************************************************************** /***********************************************************************
* PostMessage (USER.110) * PostMessage (USER.110)
*/ */
...@@ -1305,7 +1532,7 @@ BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 message, WPARAM16 wParam, ...@@ -1305,7 +1532,7 @@ BOOL16 WINAPI PostMessage16( HWND16 hwnd, UINT16 message, WPARAM16 wParam,
BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam, BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam ) LPARAM lParam )
{ {
return MSG_PostMessage( QMSG_WIN32A, hwnd, message, wParam, lParam ); return PostMessageW( hwnd, message, map_wparam_AtoW( message, wParam ), lParam );
} }
/*********************************************************************** /***********************************************************************
...@@ -1314,6 +1541,16 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam, ...@@ -1314,6 +1541,16 @@ BOOL WINAPI PostMessageA( HWND hwnd, UINT message, WPARAM wParam,
BOOL WINAPI PostMessageW( HWND hwnd, UINT message, WPARAM wParam, BOOL WINAPI PostMessageW( HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam ) LPARAM lParam )
{ {
/* See thread on wine-devel around 6.2.2001. Basically posted messages
* that are known to contain pointers are dropped by the Windows 32bit
* PostMessage() with return FALSE; and invalid parameter last error.
* (tested against NT4 by Gerard Patel)
*/
if (is_pointer_message(message))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return MSG_PostMessage( QMSG_WIN32W, hwnd, message, wParam, lParam ); return MSG_PostMessage( QMSG_WIN32W, hwnd, message, wParam, lParam );
} }
...@@ -1335,7 +1572,7 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message, ...@@ -1335,7 +1572,7 @@ BOOL16 WINAPI PostAppMessage16( HTASK16 hTask, UINT16 message,
BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message, BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
WPARAM wParam, LPARAM lParam ) WPARAM wParam, LPARAM lParam )
{ {
return MSG_PostToQueue( idThread, QMSG_WIN32A, 0, message, wParam, lParam ); return PostThreadMessageW( idThread, message, map_wparam_AtoW( message, wParam ), lParam );
} }
/********************************************************************** /**********************************************************************
...@@ -1344,6 +1581,11 @@ BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message, ...@@ -1344,6 +1581,11 @@ BOOL WINAPI PostThreadMessageA( DWORD idThread, UINT message,
BOOL WINAPI PostThreadMessageW( DWORD idThread, UINT message, BOOL WINAPI PostThreadMessageW( DWORD idThread, UINT message,
WPARAM wParam, LPARAM lParam ) WPARAM wParam, LPARAM lParam )
{ {
if (is_pointer_message( message ))
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return MSG_PostToQueue( idThread, QMSG_WIN32W, 0, message, wParam, lParam ); return MSG_PostToQueue( idThread, QMSG_WIN32W, 0, message, wParam, lParam );
} }
...@@ -1702,6 +1944,68 @@ DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles, ...@@ -1702,6 +1944,68 @@ DWORD WINAPI MsgWaitForMultipleObjects16( DWORD count, CONST HANDLE *handles,
} }
/***********************************************************************
* WaitForInputIdle (USER32.@)
*/
DWORD WINAPI WaitForInputIdle( HANDLE hProcess, DWORD dwTimeOut )
{
DWORD cur_time, ret;
HANDLE idle_event = -1;
SERVER_START_REQ( wait_input_idle )
{
req->handle = hProcess;
req->timeout = dwTimeOut;
if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
}
SERVER_END_REQ;
if (ret) return 0xffffffff; /* error */
if (!idle_event) return 0; /* no event to wait on */
cur_time = GetTickCount();
TRACE("waiting for %x\n", idle_event );
while ( dwTimeOut > GetTickCount() - cur_time || dwTimeOut == INFINITE )
{
ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
if ( ret == ( WAIT_OBJECT_0 + 1 ))
{
process_sent_messages();
continue;
}
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
{
TRACE("timeout or error\n");
return ret;
}
else
{
TRACE("finished\n");
return 0;
}
}
return WAIT_TIMEOUT;
}
/***********************************************************************
* UserYield (USER.332)
* UserYield16 (USER32.@)
*/
void WINAPI UserYield16(void)
{
/* Handle sent messages */
process_sent_messages();
/* Yield */
OldYield16();
/* Handle sent messages again */
process_sent_messages();
}
struct accent_char struct accent_char
{ {
BYTE ac_accent; BYTE ac_accent;
......
...@@ -417,210 +417,6 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue ) ...@@ -417,210 +417,6 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
/*********************************************************************** /***********************************************************************
* handle_sent_message
*
* Handle the reception of a sent message by calling the corresponding window proc
*/
static void handle_sent_message( QMSG *msg )
{
LRESULT result = 0;
MESSAGEQUEUE *queue = QUEUE_Lock( GetFastQueue16() );
DWORD extraInfo = queue->GetMessageExtraInfoVal; /* save ExtraInfo */
WND *wndPtr = WIN_FindWndPtr( msg->msg.hwnd );
TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
msg->msg.hwnd, msg->msg.message, SPY_GetMsgName(msg->msg.message),
msg->msg.wParam, msg->msg.lParam );
queue->GetMessageExtraInfoVal = msg->extraInfo;
/* call the right version of CallWindowProcXX */
switch(msg->type)
{
case QMSG_WIN16:
result = CallWindowProc16( (WNDPROC16)wndPtr->winproc,
(HWND16) msg->msg.hwnd,
(UINT16) msg->msg.message,
LOWORD(msg->msg.wParam),
msg->msg.lParam );
break;
case QMSG_WIN32A:
result = CallWindowProcA( wndPtr->winproc, msg->msg.hwnd, msg->msg.message,
msg->msg.wParam, msg->msg.lParam );
break;
case QMSG_WIN32W:
result = CallWindowProcW( wndPtr->winproc, msg->msg.hwnd, msg->msg.message,
msg->msg.wParam, msg->msg.lParam );
break;
}
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
WIN_ReleaseWndPtr(wndPtr);
QUEUE_Unlock( queue );
SERVER_START_REQ( reply_message )
{
req->result = result;
req->remove = 1;
SERVER_CALL();
}
SERVER_END_REQ;
}
/***********************************************************************
* process_sent_messages
*
* Process all pending sent messages
*/
static void process_sent_messages(void)
{
QMSG msg;
unsigned int res;
for (;;)
{
SERVER_START_REQ( get_message )
{
req->flags = GET_MSG_REMOVE | GET_MSG_SENT_ONLY;
req->get_win = 0;
req->get_first = 0;
req->get_last = ~0;
if (!(res = SERVER_CALL()))
{
msg.type = req->type;
msg.msg.hwnd = req->win;
msg.msg.message = req->msg;
msg.msg.wParam = req->wparam;
msg.msg.lParam = req->lparam;
msg.msg.time = req->time;
msg.msg.pt.x = req->x;
msg.msg.pt.y = req->y;
msg.extraInfo = req->info;
}
}
SERVER_END_REQ;
if (res) break;
handle_sent_message( &msg );
}
}
/***********************************************************************
* QUEUE_WaitBits
*
* See "Windows Internals", p.447
*
* return values:
* 0 if exit with timeout
* 1 otherwise
*/
int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
MESSAGEQUEUE *queue;
HQUEUE16 hQueue;
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
hQueue = GetFastQueue16();
if (!(queue = QUEUE_Lock( hQueue ))) return 0;
for (;;)
{
unsigned int wake_bits = 0, changed_bits = 0;
DWORD dwlc;
SERVER_START_REQ( set_queue_mask )
{
req->wake_mask = QS_SENDMESSAGE;
req->changed_mask = bits | QS_SENDMESSAGE;
req->skip_wait = 1;
if (!SERVER_CALL())
{
wake_bits = req->wake_bits;
changed_bits = req->changed_bits;
}
}
SERVER_END_REQ;
if (changed_bits & bits)
{
/* One of the bits is set; we can return */
QUEUE_Unlock( queue );
return 1;
}
if (wake_bits & QS_SENDMESSAGE)
{
/* Process the sent message immediately */
process_sent_messages();
continue; /* nested sm crux */
}
TRACE_(msg)("(%04x) mask=%08x, bits=%08x, changed=%08x, waiting\n",
queue->self, bits, wake_bits, changed_bits );
ReleaseThunkLock( &dwlc );
if (dwlc) TRACE_(msg)("had win16 lock\n");
if (USER_Driver.pMsgWaitForMultipleObjectsEx)
USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, timeout, 0, 0 );
else
WaitForSingleObject( queue->server_queue, timeout );
if (dwlc) RestoreThunkLock( dwlc );
}
}
/***********************************************************************
* QUEUE_FindMsg
*
* Find a message matching the given parameters. Return FALSE if none available.
*/
BOOL QUEUE_FindMsg( HWND hwnd, UINT first, UINT last, BOOL remove, QMSG *msg )
{
BOOL ret = FALSE;
if (!first && !last) last = ~0;
for (;;)
{
SERVER_START_REQ( get_message )
{
req->flags = remove ? GET_MSG_REMOVE : 0;
req->get_win = hwnd;
req->get_first = first;
req->get_last = last;
if ((ret = !SERVER_CALL()))
{
msg->kind = req->kind;
msg->type = req->type;
msg->msg.hwnd = req->win;
msg->msg.message = req->msg;
msg->msg.wParam = req->wparam;
msg->msg.lParam = req->lparam;
msg->msg.time = req->time;
msg->msg.pt.x = req->x;
msg->msg.pt.y = req->y;
msg->extraInfo = req->info;
}
}
SERVER_END_REQ;
if (!ret || (msg->kind != SEND_MESSAGE)) break;
handle_sent_message( msg );
}
if (ret) TRACE( "got hwnd %x msg %x (%s) wp %x lp %lx\n",
msg->msg.hwnd, msg->msg.message, SPY_GetMsgName(msg->msg.message),
msg->msg.wParam, msg->msg.lParam );
return ret;
}
/***********************************************************************
* QUEUE_CleanupWindow * QUEUE_CleanupWindow
* *
* Cleanup the queue to account for a window being deleted. * Cleanup the queue to account for a window being deleted.
...@@ -836,66 +632,6 @@ BOOL WINAPI GetInputState(void) ...@@ -836,66 +632,6 @@ BOOL WINAPI GetInputState(void)
} }
/*********************************************************************** /***********************************************************************
* WaitForInputIdle (USER32.@)
*/
DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
{
DWORD cur_time, ret;
HANDLE idle_event = -1;
SERVER_START_REQ( wait_input_idle )
{
req->handle = hProcess;
req->timeout = dwTimeOut;
if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
}
SERVER_END_REQ;
if (ret) return 0xffffffff; /* error */
if (!idle_event) return 0; /* no event to wait on */
cur_time = GetTickCount();
TRACE_(msg)("waiting for %x\n", idle_event );
while ( dwTimeOut > GetTickCount() - cur_time || dwTimeOut == INFINITE )
{
ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
if ( ret == ( WAIT_OBJECT_0 + 1 ))
{
process_sent_messages();
continue;
}
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
{
TRACE_(msg)("timeout or error\n");
return ret;
}
else
{
TRACE_(msg)("finished\n");
return 0;
}
}
return WAIT_TIMEOUT;
}
/***********************************************************************
* UserYield (USER.332)
* UserYield16 (USER32.@)
*/
void WINAPI UserYield16(void)
{
/* Handle sent messages */
process_sent_messages();
/* Yield */
OldYield16();
/* Handle sent messages again */
process_sent_messages();
}
/***********************************************************************
* GetMessagePos (USER.119) (USER32.@) * GetMessagePos (USER.119) (USER32.@)
* *
* The GetMessagePos() function returns a long value representing a * The GetMessagePos() function returns a long value representing a
......
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