user: Fix WM_QUIT message ordering from PostQuitMessage.
Added a new server call as PostQuitMessage should set a flag in the message queue to return the WM_QUIT message when there are no other pending messages, rather than posting a message to the thread queue as it does at the moment.
This commit is contained in:
parent
2e32a425db
commit
a40ce39340
|
@ -2668,10 +2668,30 @@ BOOL WINAPI PostThreadMessageW( DWORD thread, UINT msg, WPARAM wparam, LPARAM lp
|
|||
|
||||
/***********************************************************************
|
||||
* PostQuitMessage (USER32.@)
|
||||
*
|
||||
* Posts a quit message to the current thread's message queue.
|
||||
*
|
||||
* PARAMS
|
||||
* exit_code [I] Exit code to return from message loop.
|
||||
*
|
||||
* RETURNS
|
||||
* Nothing.
|
||||
*
|
||||
* NOTES
|
||||
* This function is not the same as calling:
|
||||
*|PostThreadMessage(GetCurrentThreadId(), WM_QUIT, exit_code, 0);
|
||||
* It instead sets a flag in the message queue that signals it to generate
|
||||
* a WM_QUIT message when there are no other pending sent or posted messages
|
||||
* in the queue.
|
||||
*/
|
||||
void WINAPI PostQuitMessage( INT exitCode )
|
||||
void WINAPI PostQuitMessage( INT exit_code )
|
||||
{
|
||||
PostThreadMessageW( GetCurrentThreadId(), WM_QUIT, exitCode, 0 );
|
||||
SERVER_START_REQ( post_quit_message )
|
||||
{
|
||||
req->exit_code = exit_code;
|
||||
wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6958,6 +6958,57 @@ todo_wine {
|
|||
}
|
||||
|
||||
|
||||
static void test_quit_message(void)
|
||||
{
|
||||
MSG msg;
|
||||
BOOL ret;
|
||||
|
||||
/* test using PostQuitMessage */
|
||||
PostQuitMessage(0xbeef);
|
||||
|
||||
ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
|
||||
ok(ret, "PeekMessage failed with error %ld\n", GetLastError());
|
||||
ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
|
||||
ok(msg.wParam == 0xbeef, "wParam was 0x%x instead of 0xbeef\n", msg.wParam);
|
||||
|
||||
ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
|
||||
ok(ret, "PostMessage failed with error %ld\n", GetLastError());
|
||||
|
||||
ret = GetMessage(&msg, NULL, 0, 0);
|
||||
ok(ret > 0, "GetMessage failed with error %ld\n", GetLastError());
|
||||
ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
|
||||
|
||||
/* note: WM_QUIT message received after WM_USER message */
|
||||
ret = GetMessage(&msg, NULL, 0, 0);
|
||||
ok(!ret, "GetMessage return %d with error %ld instead of FALSE\n", ret, GetLastError());
|
||||
ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
|
||||
ok(msg.wParam == 0xbeef, "wParam was 0x%x instead of 0xbeef\n", msg.wParam);
|
||||
|
||||
ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
|
||||
ok( !ret || msg.message != WM_QUIT, "Received WM_QUIT again\n" );
|
||||
|
||||
/* now test with PostThreadMessage - different behaviour! */
|
||||
PostThreadMessage(GetCurrentThreadId(), WM_QUIT, 0xdead, 0);
|
||||
|
||||
ret = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
|
||||
ok(ret, "PeekMessage failed with error %ld\n", GetLastError());
|
||||
ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
|
||||
ok(msg.wParam == 0xdead, "wParam was 0x%x instead of 0xdead\n", msg.wParam);
|
||||
|
||||
ret = PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0);
|
||||
ok(ret, "PostMessage failed with error %ld\n", GetLastError());
|
||||
|
||||
/* note: we receive the WM_QUIT message first this time */
|
||||
ret = GetMessage(&msg, NULL, 0, 0);
|
||||
ok(!ret, "GetMessage return %d with error %ld instead of FALSE\n", ret, GetLastError());
|
||||
ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
|
||||
ok(msg.wParam == 0xdead, "wParam was 0x%x instead of 0xdead\n", msg.wParam);
|
||||
|
||||
ret = GetMessage(&msg, NULL, 0, 0);
|
||||
ok(ret > 0, "GetMessage failed with error %ld\n", GetLastError());
|
||||
ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message);
|
||||
}
|
||||
|
||||
START_TEST(msg)
|
||||
{
|
||||
BOOL ret;
|
||||
|
@ -7016,6 +7067,7 @@ START_TEST(msg)
|
|||
test_DispatchMessage();
|
||||
test_SendMessageTimeout();
|
||||
test_edit_messages();
|
||||
test_quit_message();
|
||||
|
||||
UnhookWindowsHookEx(hCBT_hook);
|
||||
if (pUnhookWinEvent)
|
||||
|
|
|
@ -2205,6 +2205,16 @@ struct send_message_reply
|
|||
struct reply_header __header;
|
||||
};
|
||||
|
||||
struct post_quit_message_request
|
||||
{
|
||||
struct request_header __header;
|
||||
int exit_code;
|
||||
};
|
||||
struct post_quit_message_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
enum message_type
|
||||
{
|
||||
MSG_ASCII,
|
||||
|
@ -3824,6 +3834,7 @@ enum request
|
|||
REQ_get_queue_status,
|
||||
REQ_wait_input_idle,
|
||||
REQ_send_message,
|
||||
REQ_post_quit_message,
|
||||
REQ_get_message,
|
||||
REQ_reply_message,
|
||||
REQ_accept_hardware_message,
|
||||
|
@ -4042,6 +4053,7 @@ union generic_request
|
|||
struct get_queue_status_request get_queue_status_request;
|
||||
struct wait_input_idle_request wait_input_idle_request;
|
||||
struct send_message_request send_message_request;
|
||||
struct post_quit_message_request post_quit_message_request;
|
||||
struct get_message_request get_message_request;
|
||||
struct reply_message_request reply_message_request;
|
||||
struct accept_hardware_message_request accept_hardware_message_request;
|
||||
|
@ -4258,6 +4270,7 @@ union generic_reply
|
|||
struct get_queue_status_reply get_queue_status_reply;
|
||||
struct wait_input_idle_reply wait_input_idle_reply;
|
||||
struct send_message_reply send_message_reply;
|
||||
struct post_quit_message_reply post_quit_message_reply;
|
||||
struct get_message_reply get_message_reply;
|
||||
struct reply_message_reply reply_message_reply;
|
||||
struct accept_hardware_message_reply accept_hardware_message_reply;
|
||||
|
@ -4349,6 +4362,6 @@ union generic_reply
|
|||
struct query_symlink_reply query_symlink_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 220
|
||||
#define SERVER_PROTOCOL_VERSION 221
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1573,6 +1573,10 @@ enum char_info_mode
|
|||
VARARG(data,bytes); /* message data for sent messages */
|
||||
@END
|
||||
|
||||
@REQ(post_quit_message)
|
||||
int exit_code; /* exit code to return */
|
||||
@END
|
||||
|
||||
enum message_type
|
||||
{
|
||||
MSG_ASCII, /* Ascii message (from SendMessageA) */
|
||||
|
|
|
@ -120,6 +120,8 @@ struct msg_queue
|
|||
unsigned int changed_bits; /* changed wakeup bits */
|
||||
unsigned int changed_mask; /* changed wakeup mask */
|
||||
int paint_count; /* pending paint messages count */
|
||||
int quit_message; /* is there a pending quit message? */
|
||||
int exit_code; /* exit code of pending quit message */
|
||||
struct list msg_list[NB_MSG_KINDS]; /* lists of messages */
|
||||
struct list send_result; /* stack of sent messages waiting for result */
|
||||
struct list callback_result; /* list of callback messages waiting for result */
|
||||
|
@ -244,6 +246,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
|||
queue->changed_bits = 0;
|
||||
queue->changed_mask = 0;
|
||||
queue->paint_count = 0;
|
||||
queue->quit_message = 0;
|
||||
queue->recv_result = NULL;
|
||||
queue->next_timer_id = 1;
|
||||
queue->timeout = NULL;
|
||||
|
@ -642,7 +645,6 @@ static int get_posted_message( struct msg_queue *queue, user_handle_t win,
|
|||
/* check against the filters */
|
||||
LIST_FOR_EACH_ENTRY( msg, &queue->msg_list[POST_MESSAGE], struct message, entry )
|
||||
{
|
||||
if (msg->msg == WM_QUIT) goto found; /* WM_QUIT is never filtered */
|
||||
if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue;
|
||||
if (!check_msg_filter( msg->msg, first, last )) continue;
|
||||
goto found; /* found one */
|
||||
|
@ -682,6 +684,31 @@ found:
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int get_quit_message( struct msg_queue *queue, unsigned int flags,
|
||||
struct get_message_reply *reply )
|
||||
{
|
||||
if (queue->quit_message)
|
||||
{
|
||||
reply->total = 0;
|
||||
reply->type = MSG_POSTED;
|
||||
reply->win = NULL;
|
||||
reply->msg = WM_QUIT;
|
||||
reply->wparam = queue->exit_code;
|
||||
reply->lparam = 0;
|
||||
reply->x = 0;
|
||||
reply->y = 0;
|
||||
reply->time = get_tick_count();
|
||||
reply->info = 0;
|
||||
|
||||
if (flags & GET_MSG_REMOVE)
|
||||
queue->quit_message = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* empty a message list and free all the messages */
|
||||
static void empty_msg_list( struct list *list )
|
||||
{
|
||||
|
@ -1614,6 +1641,18 @@ DECL_HANDLER(send_message)
|
|||
if (thread) release_object( thread );
|
||||
}
|
||||
|
||||
/* post a quit message to the current queue */
|
||||
DECL_HANDLER(post_quit_message)
|
||||
{
|
||||
struct msg_queue *queue = get_current_queue();
|
||||
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
queue->quit_message = 1;
|
||||
queue->exit_code = req->exit_code;
|
||||
set_queue_bits( queue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE );
|
||||
}
|
||||
|
||||
/* get a message from the current queue */
|
||||
DECL_HANDLER(get_message)
|
||||
|
@ -1645,6 +1684,11 @@ DECL_HANDLER(get_message)
|
|||
if (get_posted_message( queue, get_win, req->get_first, req->get_last, req->flags, reply ))
|
||||
return;
|
||||
|
||||
/* only check for quit messages if not posted messages pending.
|
||||
* note: the quit message isn't filtered */
|
||||
if (get_quit_message( queue, req->flags, reply ))
|
||||
return;
|
||||
|
||||
/* then check for any raw hardware message */
|
||||
if (filter_contains_hw_range( req->get_first, req->get_last ) &&
|
||||
get_hardware_message( current, req->hw_id, get_win, req->get_first, req->get_last, reply ))
|
||||
|
|
|
@ -232,6 +232,7 @@ DECL_HANDLER(set_queue_mask);
|
|||
DECL_HANDLER(get_queue_status);
|
||||
DECL_HANDLER(wait_input_idle);
|
||||
DECL_HANDLER(send_message);
|
||||
DECL_HANDLER(post_quit_message);
|
||||
DECL_HANDLER(get_message);
|
||||
DECL_HANDLER(reply_message);
|
||||
DECL_HANDLER(accept_hardware_message);
|
||||
|
@ -449,6 +450,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_get_queue_status,
|
||||
(req_handler)req_wait_input_idle,
|
||||
(req_handler)req_send_message,
|
||||
(req_handler)req_post_quit_message,
|
||||
(req_handler)req_get_message,
|
||||
(req_handler)req_reply_message,
|
||||
(req_handler)req_accept_hardware_message,
|
||||
|
|
|
@ -2058,6 +2058,11 @@ static void dump_send_message_request( const struct send_message_request *req )
|
|||
dump_varargs_bytes( cur_size );
|
||||
}
|
||||
|
||||
static void dump_post_quit_message_request( const struct post_quit_message_request *req )
|
||||
{
|
||||
fprintf( stderr, " exit_code=%d", req->exit_code );
|
||||
}
|
||||
|
||||
static void dump_get_message_request( const struct get_message_request *req )
|
||||
{
|
||||
fprintf( stderr, " flags=%d,", req->flags );
|
||||
|
@ -3333,6 +3338,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_queue_status_request,
|
||||
(dump_func)dump_wait_input_idle_request,
|
||||
(dump_func)dump_send_message_request,
|
||||
(dump_func)dump_post_quit_message_request,
|
||||
(dump_func)dump_get_message_request,
|
||||
(dump_func)dump_reply_message_request,
|
||||
(dump_func)dump_accept_hardware_message_request,
|
||||
|
@ -3547,6 +3553,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_get_queue_status_reply,
|
||||
(dump_func)dump_wait_input_idle_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_get_message_reply,
|
||||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
|
@ -3761,6 +3768,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"get_queue_status",
|
||||
"wait_input_idle",
|
||||
"send_message",
|
||||
"post_quit_message",
|
||||
"get_message",
|
||||
"reply_message",
|
||||
"accept_hardware_message",
|
||||
|
|
Loading…
Reference in New Issue