From: Drew Ronneberg Subject: [PATCH] Do not call SendMessage() to hide a window that is already hidden Message-Id: <1415575114.24164.YahooMailNeo@web162801.mail.bf1.yahoo.com> Date: Sun, 9 Nov 2014 15:18:34 -0800
From 4499cc760bdedbc6d8b7cf99d7ba6aba94aa100a Mon Sep 17 00:00:00 2001 From: Drew Ronneberg Date: Wed, 15 Jan 2014 19:21:45 -0500 Subject: Do not call SendMessage() to hide a window that is already hidden Two real appications (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. Because hiding an already hidden window is a no-op, the solution is to return from ShowWindow() before it calls SendMessage(). The patch also corrects the same issue in ShowWindowAsync(). I don't see how a test which mimics this behavior can be incorporated into the test suite, because a test failure will hang the test. --- dlls/user32/winpos.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 5373733..6c51ca9 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1200,6 +1200,9 @@ BOOL WINAPI ShowWindowAsync( 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 SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 ); } @@ -1219,6 +1222,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