Timeout 0 means infinite wait for SendMessageTimeout.
Remove the message from the receiver queue if it times out before being received.
This commit is contained in:
parent
23152a664c
commit
127127fd3b
|
@ -2426,7 +2426,7 @@ LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l
|
|||
LRESULT WINAPI SendMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||
{
|
||||
DWORD_PTR res = 0;
|
||||
SendMessageTimeoutW( hwnd, msg, wparam, lparam, SMTO_NORMAL, INFINITE, &res );
|
||||
SendMessageTimeoutW( hwnd, msg, wparam, lparam, SMTO_NORMAL, 0, &res );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -2437,7 +2437,7 @@ LRESULT WINAPI SendMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
|||
LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
||||
{
|
||||
DWORD_PTR res = 0;
|
||||
SendMessageTimeoutA( hwnd, msg, wparam, lparam, SMTO_NORMAL, INFINITE, &res );
|
||||
SendMessageTimeoutA( hwnd, msg, wparam, lparam, SMTO_NORMAL, 0, &res );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -5835,6 +5835,113 @@ static void test_DispatchMessage(void)
|
|||
}
|
||||
|
||||
|
||||
static const struct message WmUser[] = {
|
||||
{ WM_USER, sent },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
struct thread_info
|
||||
{
|
||||
HWND hwnd;
|
||||
DWORD timeout;
|
||||
DWORD ret;
|
||||
};
|
||||
|
||||
static DWORD CALLBACK send_msg_thread( LPVOID arg )
|
||||
{
|
||||
struct thread_info *info = arg;
|
||||
info->ret = SendMessageTimeoutA( info->hwnd, WM_USER, 0, 0, 0, info->timeout, NULL );
|
||||
if (!info->ret) ok( GetLastError() == ERROR_TIMEOUT, "unexpected error %ld\n", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wait_for_thread( HANDLE thread )
|
||||
{
|
||||
while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_SENDMESSAGE) != WAIT_OBJECT_0)
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT WINAPI send_msg_delay_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_USER) Sleep(200);
|
||||
return MsgCheckProcA( hwnd, message, wParam, lParam );
|
||||
}
|
||||
|
||||
static void test_SendMessageTimeout(void)
|
||||
{
|
||||
MSG msg;
|
||||
HANDLE thread;
|
||||
struct thread_info info;
|
||||
|
||||
info.hwnd = CreateWindowA( "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
|
||||
100, 100, 200, 200, 0, 0, 0, NULL);
|
||||
while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
|
||||
flush_sequence();
|
||||
|
||||
info.timeout = 1000;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
ok( info.ret == 1, "SendMessageTimeout failed\n" );
|
||||
ok_sequence( WmUser, "WmUser", FALSE );
|
||||
|
||||
info.timeout = 1;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
Sleep(100); /* SendMessageTimeout should timeout here */
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
|
||||
ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
|
||||
|
||||
/* 0 means infinite timeout */
|
||||
info.timeout = 0;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
Sleep(100);
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
ok( info.ret == 1, "SendMessageTimeout failed\n" );
|
||||
ok_sequence( WmUser, "WmUser", FALSE );
|
||||
|
||||
/* timeout is treated as signed despite the prototype */
|
||||
info.timeout = 0x7fffffff;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
Sleep(100);
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
ok( info.ret == 1, "SendMessageTimeout failed\n" );
|
||||
ok_sequence( WmUser, "WmUser", FALSE );
|
||||
|
||||
info.timeout = 0x80000000;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
Sleep(100);
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
ok( info.ret == 0, "SendMessageTimeout succeeded\n" );
|
||||
ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
|
||||
|
||||
/* now check for timeout during message processing */
|
||||
SetWindowLongPtrA( info.hwnd, GWLP_WNDPROC, (LONG_PTR)send_msg_delay_proc );
|
||||
info.timeout = 100;
|
||||
info.ret = 0xdeadbeef;
|
||||
thread = CreateThread( NULL, 0, send_msg_thread, &info, 0, NULL );
|
||||
wait_for_thread( thread );
|
||||
CloseHandle( thread );
|
||||
/* we should timeout but still get the message */
|
||||
ok( info.ret == 0, "SendMessageTimeout failed\n" );
|
||||
ok_sequence( WmUser, "WmUser", FALSE );
|
||||
|
||||
DestroyWindow( info.hwnd );
|
||||
}
|
||||
|
||||
|
||||
START_TEST(msg)
|
||||
{
|
||||
BOOL ret;
|
||||
|
@ -5888,6 +5995,7 @@ START_TEST(msg)
|
|||
test_set_hook();
|
||||
test_DestroyWindow();
|
||||
test_DispatchMessage();
|
||||
test_SendMessageTimeout();
|
||||
|
||||
UnhookWindowsHookEx(hCBT_hook);
|
||||
if (pUnhookWinEvent)
|
||||
|
|
|
@ -48,6 +48,7 @@ enum message_kind { SEND_MESSAGE, POST_MESSAGE };
|
|||
struct message_result
|
||||
{
|
||||
struct list sender_entry; /* entry in sender list */
|
||||
struct message *msg; /* message the result is for */
|
||||
struct message_result *recv_next; /* next in receiver list */
|
||||
struct msg_queue *sender; /* sender queue */
|
||||
struct msg_queue *receiver; /* receiver queue */
|
||||
|
@ -447,6 +448,7 @@ static void free_message( struct message *msg )
|
|||
struct message_result *result = msg->result;
|
||||
if (result)
|
||||
{
|
||||
result->msg = NULL;
|
||||
if (result->sender)
|
||||
{
|
||||
result->receiver = NULL;
|
||||
|
@ -483,18 +485,35 @@ static void result_timeout( void *private )
|
|||
assert( !result->replied );
|
||||
|
||||
result->timeout = NULL;
|
||||
|
||||
if (result->msg) /* not received yet */
|
||||
{
|
||||
struct message *msg = result->msg;
|
||||
|
||||
result->msg = NULL;
|
||||
msg->result = NULL;
|
||||
remove_queue_message( result->receiver, msg, SEND_MESSAGE );
|
||||
result->receiver = NULL;
|
||||
if (!result->sender)
|
||||
{
|
||||
free_result( result );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
store_message_result( result, 0, STATUS_TIMEOUT );
|
||||
}
|
||||
|
||||
/* allocate and fill a message result structure */
|
||||
static struct message_result *alloc_message_result( struct msg_queue *send_queue,
|
||||
struct msg_queue *recv_queue,
|
||||
struct message *msg, unsigned int timeout,
|
||||
struct message *msg, int timeout,
|
||||
void *callback, unsigned int callback_data )
|
||||
{
|
||||
struct message_result *result = mem_alloc( sizeof(*result) );
|
||||
if (result)
|
||||
{
|
||||
result->msg = msg;
|
||||
result->sender = send_queue;
|
||||
result->receiver = recv_queue;
|
||||
result->replied = 0;
|
||||
|
@ -534,7 +553,7 @@ static struct message_result *alloc_message_result( struct msg_queue *send_queue
|
|||
list_add_head( &send_queue->send_result, &result->sender_entry );
|
||||
}
|
||||
|
||||
if (timeout != -1)
|
||||
if (timeout)
|
||||
{
|
||||
struct timeval when;
|
||||
gettimeofday( &when, NULL );
|
||||
|
@ -575,6 +594,7 @@ static void receive_message( struct msg_queue *queue, struct message *msg,
|
|||
/* put the result on the receiver result stack */
|
||||
if (result)
|
||||
{
|
||||
result->msg = NULL;
|
||||
result->recv_next = queue->recv_result;
|
||||
queue->recv_result = result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue