Properly cope with get_message being called recursively while

processing a hardware message.
oldstable
Alexandre Julliard 2005-03-10 11:52:25 +00:00
parent d574e9a2db
commit 99615021fb
5 changed files with 14 additions and 7 deletions

View File

@ -1585,6 +1585,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
ULONG_PTR extra_info = 0;
MESSAGEQUEUE *queue = QUEUE_Current();
struct received_message_info info, *old_info;
int get_next_hw = 0; /* set when the previous message was a rejected hardware message */
if (!first && !last) last = ~0;
@ -1604,6 +1605,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
req->get_win = hwnd;
req->get_first = first;
req->get_last = last;
req->get_next_hw = get_next_hw;
if (buffer_size) wine_server_set_reply( req, buffer, buffer_size );
if (!(res = wine_server_call( req )))
{
@ -1630,6 +1632,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
} while (res == STATUS_BUFFER_OVERFLOW);
if (res) return FALSE;
get_next_hw = 0;
TRACE( "got type %d msg %x (%s) hwnd %p wp %x lp %lx\n",
info.type, info.msg.message,
@ -1694,6 +1697,7 @@ BOOL MSG_peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, int flags )
}
break;
case MSG_HARDWARE:
get_next_hw = 1;
if (!process_hardware_message( &info.msg, extra_info,
hwnd, first, last, flags & GET_MSG_REMOVE ))
{

View File

@ -2156,6 +2156,7 @@ struct get_message_request
user_handle_t get_win;
unsigned int get_first;
unsigned int get_last;
int get_next_hw;
};
struct get_message_reply
{
@ -3781,6 +3782,6 @@ union generic_reply
struct duplicate_token_reply duplicate_token_reply;
};
#define SERVER_PROTOCOL_VERSION 158
#define SERVER_PROTOCOL_VERSION 159
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -1531,6 +1531,7 @@ enum message_type
user_handle_t get_win; /* window handle to get */
unsigned int get_first; /* first message code to get */
unsigned int get_last; /* last message code to get */
int get_next_hw; /* do we want the get the next hardware msg? */
@REPLY
int type; /* message type */
user_handle_t win; /* window handle */

View File

@ -1121,7 +1121,7 @@ static void queue_hardware_message( struct msg_queue *queue, struct message *msg
}
/* find a hardware message for the given queue */
static int get_hardware_message( struct thread *thread, struct message *first,
static int get_hardware_message( struct thread *thread, int get_next_hw, struct message *first,
user_handle_t filter_win, struct get_message_reply *reply )
{
struct thread_input *input = thread->queue->input;
@ -1131,8 +1131,8 @@ static int get_hardware_message( struct thread *thread, struct message *first,
int clear_bits, got_one = 0;
unsigned int msg_code;
if (input->msg_thread && input->msg_thread != thread)
return 0; /* locked by another thread */
if (input->msg_thread && ((input->msg_thread != thread) || !get_next_hw))
return 0; /* locked by another thread, or another recursion level of the same thread */
if (!first)
{
@ -1492,7 +1492,7 @@ DECL_HANDLER(get_message)
/* first of all release the hardware input lock if we own it */
/* we'll grab it again if we find a hardware message */
if (queue->input->msg_thread == current)
if (queue->input->msg_thread == current && req->get_next_hw)
{
first_hw_msg = queue->input->msg;
release_hardware_message( current, 0 );
@ -1515,7 +1515,7 @@ DECL_HANDLER(get_message)
return;
/* then check for any raw hardware message */
if (get_hardware_message( current, first_hw_msg, get_win, reply ))
if (get_hardware_message( current, req->get_next_hw, first_hw_msg, get_win, reply ))
return;
/* now check for WM_PAINT */

View File

@ -1871,7 +1871,8 @@ static void dump_get_message_request( const struct get_message_request *req )
fprintf( stderr, " flags=%d,", req->flags );
fprintf( stderr, " get_win=%p,", req->get_win );
fprintf( stderr, " get_first=%08x,", req->get_first );
fprintf( stderr, " get_last=%08x", req->get_last );
fprintf( stderr, " get_last=%08x,", req->get_last );
fprintf( stderr, " get_next_hw=%d", req->get_next_hw );
}
static void dump_get_message_reply( const struct get_message_reply *req )