Implemented the SMTO_ABORTIFHUNG flag of SendMessageTimeout.
This commit is contained in:
parent
17c69c65aa
commit
09029b2878
|
@ -69,8 +69,9 @@ ULONG WINAPI RtlNtStatusToDosError( NTSTATUS status )
|
|||
|
||||
/* conversion tables */
|
||||
|
||||
static const DWORD table_00000103[31] =
|
||||
static const DWORD table_00000102[32] =
|
||||
{
|
||||
ERROR_TIMEOUT, /* 00000102 (STATUS_TIMEOUT) */
|
||||
ERROR_IO_PENDING, /* 00000103 (STATUS_PENDING) */
|
||||
ERROR_MR_MID_NOT_FOUND, /* 00000104 */
|
||||
ERROR_MORE_DATA, /* 00000105 (STATUS_MORE_ENTRIES) */
|
||||
|
@ -1333,7 +1334,7 @@ static const DWORD table_c0150001[14] =
|
|||
|
||||
static const struct error_table error_table[] =
|
||||
{
|
||||
{ 0x00000103, 0x00000122, table_00000103 },
|
||||
{ 0x00000102, 0x00000122, table_00000102 },
|
||||
{ 0x40000002, 0x4000000e, table_40000002 },
|
||||
{ 0x40000370, 0x40000371, table_40000370 },
|
||||
{ 0x40020056, 0x40020057, table_40020056 },
|
||||
|
|
|
@ -1663,12 +1663,14 @@ static BOOL put_message_in_queue( DWORD dest_tid, const struct send_message_info
|
|||
{
|
||||
req->id = dest_tid;
|
||||
req->type = info->type;
|
||||
req->flags = 0;
|
||||
req->win = info->hwnd;
|
||||
req->msg = info->msg;
|
||||
req->wparam = info->wparam;
|
||||
req->lparam = info->lparam;
|
||||
req->time = GetCurrentTime();
|
||||
req->timeout = timeout;
|
||||
if (info->flags & SMTO_ABORTIFHUNG) req->flags |= SEND_MSG_ABORT_IF_HUNG;
|
||||
for (i = 0; i < data.count; i++) wine_server_add_data( req, data.data[i], data.size[i] );
|
||||
if ((res = wine_server_call( req )))
|
||||
{
|
||||
|
@ -1720,10 +1722,9 @@ static LRESULT retrieve_reply( const struct send_message_info *info,
|
|||
info->hwnd, info->msg, SPY_GetMsgName(info->msg, info->hwnd), info->wparam,
|
||||
info->lparam, *result, status );
|
||||
|
||||
if (!status) return 1;
|
||||
if (status == STATUS_TIMEOUT) SetLastError(0); /* timeout */
|
||||
else SetLastError( RtlNtStatusToDosError(status) );
|
||||
return 0;
|
||||
/* MSDN states that last error is 0 on timeout, but at least NT4 returns ERROR_TIMEOUT */
|
||||
if (status) SetLastError( RtlNtStatusToDosError(status) );
|
||||
return !status;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2204,6 +2204,7 @@ struct send_message_request
|
|||
struct request_header __header;
|
||||
thread_id_t id;
|
||||
int type;
|
||||
int flags;
|
||||
user_handle_t win;
|
||||
unsigned int msg;
|
||||
unsigned int wparam;
|
||||
|
@ -2230,6 +2231,7 @@ enum message_type
|
|||
MSG_POSTED,
|
||||
MSG_HARDWARE
|
||||
};
|
||||
#define SEND_MSG_ABORT_IF_HUNG 0x01
|
||||
|
||||
|
||||
|
||||
|
@ -3620,6 +3622,6 @@ union generic_reply
|
|||
struct set_clipboard_info_reply set_clipboard_info_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 114
|
||||
#define SERVER_PROTOCOL_VERSION 115
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1564,6 +1564,7 @@ enum char_info_mode
|
|||
@REQ(send_message)
|
||||
thread_id_t id; /* thread id */
|
||||
int type; /* message type (see below) */
|
||||
int flags; /* message flags (see below) */
|
||||
user_handle_t win; /* window handle */
|
||||
unsigned int msg; /* message code */
|
||||
unsigned int wparam; /* parameters */
|
||||
|
@ -1586,6 +1587,7 @@ enum message_type
|
|||
MSG_POSTED, /* posted message (from PostMessageW), always Unicode */
|
||||
MSG_HARDWARE /* hardware message */
|
||||
};
|
||||
#define SEND_MSG_ABORT_IF_HUNG 0x01
|
||||
|
||||
|
||||
/* Get a message from the current queue */
|
||||
|
|
|
@ -125,6 +125,7 @@ struct msg_queue
|
|||
struct timeout_user *timeout; /* timeout for next timer to expire */
|
||||
struct thread_input *input; /* thread input descriptor */
|
||||
struct hook_table *hooks; /* hook table */
|
||||
struct timeval last_get_msg; /* time of last get message call */
|
||||
};
|
||||
|
||||
static void msg_queue_dump( struct object *obj, int verbose );
|
||||
|
@ -221,6 +222,7 @@ static struct msg_queue *create_msg_queue( struct thread *thread, struct thread_
|
|||
queue->timeout = NULL;
|
||||
queue->input = (struct thread_input *)grab_object( input );
|
||||
queue->hooks = NULL;
|
||||
gettimeofday( &queue->last_get_msg, NULL );
|
||||
for (i = 0; i < NB_MSG_KINDS; i++)
|
||||
queue->msg_list[i].first = queue->msg_list[i].last = NULL;
|
||||
|
||||
|
@ -589,6 +591,24 @@ static void cleanup_results( struct msg_queue *queue )
|
|||
reply_message( queue, 0, STATUS_ACCESS_DENIED /*FIXME*/, 1, NULL, 0 );
|
||||
}
|
||||
|
||||
/* check if the thread owning the queue is hung (not checking for messages) */
|
||||
static int is_queue_hung( struct msg_queue *queue )
|
||||
{
|
||||
struct timeval now;
|
||||
struct wait_queue_entry *entry;
|
||||
|
||||
gettimeofday( &now, NULL );
|
||||
if (now.tv_sec - queue->last_get_msg.tv_sec <= 5)
|
||||
return 0; /* less than 5 seconds since last get message -> not hung */
|
||||
|
||||
for (entry = queue->obj.head; entry; entry = entry->next)
|
||||
{
|
||||
if (entry->thread->queue == queue)
|
||||
return 0; /* thread is waiting on queue -> not hung */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int msg_queue_add_queue( struct object *obj, struct wait_queue_entry *entry )
|
||||
{
|
||||
struct msg_queue *queue = (struct msg_queue *)obj;
|
||||
|
@ -1253,6 +1273,12 @@ DECL_HANDLER(send_message)
|
|||
release_object( thread );
|
||||
return;
|
||||
}
|
||||
if (recv_queue && (req->flags & SEND_MSG_ABORT_IF_HUNG) && is_queue_hung(recv_queue))
|
||||
{
|
||||
set_error( STATUS_TIMEOUT );
|
||||
release_object( thread );
|
||||
return;
|
||||
}
|
||||
|
||||
if ((msg = mem_alloc( sizeof(*msg) )))
|
||||
{
|
||||
|
@ -1326,6 +1352,7 @@ DECL_HANDLER(get_message)
|
|||
user_handle_t get_win = get_user_full_handle( req->get_win );
|
||||
|
||||
if (!queue) return;
|
||||
gettimeofday( &queue->last_get_msg, NULL );
|
||||
|
||||
/* first of all release the hardware input lock if we own it */
|
||||
/* we'll grab it again if we find a hardware message */
|
||||
|
|
|
@ -1834,6 +1834,7 @@ static void dump_send_message_request( const struct send_message_request *req )
|
|||
{
|
||||
fprintf( stderr, " id=%04x,", req->id );
|
||||
fprintf( stderr, " type=%d,", req->type );
|
||||
fprintf( stderr, " flags=%d,", req->flags );
|
||||
fprintf( stderr, " win=%p,", req->win );
|
||||
fprintf( stderr, " msg=%08x,", req->msg );
|
||||
fprintf( stderr, " wparam=%08x,", req->wparam );
|
||||
|
|
Loading…
Reference in New Issue