From: Drew Ronneberg Subject: [PATCH 2/2] Do not call SendMessage() to hide a window that is already hidden (try 3) Message-Id: <1699489382.2543918.1416404101294.JavaMail.yahoo@jws106144.mail.bf1.yahoo.com> Date: Wed, 19 Nov 2014 13:35:01 +0000 (UTC)

From 059e42248ecf4e411816999118ad67d8e8f66d8d Mon Sep 17 00:00:00 2001 From: Drew Ronneberg Date: Tue, 18 Nov 2014 22:30:37 -0500 Subject: [PATCH 2/2] Do not call SendMessage() to hide a window that is already hidden (try 3) Two real applications (Macromedia Flash 5 Trial and Macromedia FreeHand 9) uses a software protection scheme whereby 1) Thread A creates a toolwindow 2) Thread A hides the toolwindow 3) Thread A creates Thread B 4) Thread A sleeps 5) Thread B calls ShowWindow() with the SW_HIDE flag 6) Wine's ShowWindow() calls SendMessage() 7) Thread B blocks waiting for SendMessage() to return 8) Thread A wakes up but doesn't process any messages to the toolwindow. Instead, it checks the child process handle, which it expects to be initialized. It isn't, because Thread B initializes this information after calling SendMessage() 9) Thread A goes into a busy loop and livelocks. AF's complete analysis can be found in bug #11582. The multi-threaded test confirms that SendMessage() should not be called to hide an already hidden window. --- dlls/user32/tests/msg.c | 3 --- dlls/user32/winpos.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index d829c5f..28bb35e 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -4673,8 +4673,6 @@ static void test_messages(void) flush_events(); ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); - if (0) - { /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */ hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid); ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError()); @@ -4682,7 +4680,6 @@ static void test_messages(void) CloseHandle(hthread); flush_events(); ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE); - } ShowWindow(hwnd, SW_SHOW); flush_events(); diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 5373733..12d3ffa 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1219,6 +1219,9 @@ BOOL WINAPI ShowWindow( HWND hwnd, INT cmd ) if ((full_handle = WIN_IsCurrentThread( hwnd ))) return show_window( full_handle, cmd ); + if ((cmd == SW_HIDE) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) + return FALSE; + return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); } -- 1.9.1