Commit 127127fd authored by Alexandre Julliard's avatar Alexandre Julliard

Timeout 0 means infinite wait for SendMessageTimeout.

Remove the message from the receiver queue if it times out before being received.
parent 23152a66
......@@ -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;
}
......
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