diff --git a/README.md b/README.md index 2e33c66b..6dd76b31 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [8]:** +**Bugfixes and features included in the next upcoming release [9]:** * Add stub for PowerCreateRequest * Fix caps lock state issues with multiple processes ([Wine Bug #35907](https://bugs.winehq.org/show_bug.cgi?id=35907)) @@ -47,6 +47,7 @@ Included bug fixes and improvements * Fix wrong version of ID3DXEffect interface for d3dx9_25 * GetMessage should remove already seen messages with higher priority ([Wine Bug #28884](https://bugs.winehq.org/show_bug.cgi?id=28884)) * Implement locking and synchronization of key states ([Wine Bug #31899](https://bugs.winehq.org/show_bug.cgi?id=31899)) +* Invalidate key state cache globally after calling LL hooks ([Wine Bug #29871](https://bugs.winehq.org/show_bug.cgi?id=29871)) * Python PIP needs better NtQueryInformationJobObject stub diff --git a/debian/changelog b/debian/changelog index d9958289..927cd090 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,7 @@ wine-staging (1.7.39) UNRELEASED; urgency=low * Added patch to modify GetMessage to return already seen messages with higher priority. * Added patch to silence repeated 'Unhandled blend factor 0' FIXME messages. * Added patch for stub of PowerCreateRequest. + * Added patch to invalidate key state cache globally after calling LL hooks. * Removed patch to avoid hardcoded values for sizeof(GUID) (accepted upstream). * Removed patches for SLGetWindowsInformationDWORD (accepted upstream). -- Sebastian Lackner Mon, 09 Mar 2015 16:52:35 +0100 diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index efe304f5..f7123621 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -192,6 +192,7 @@ patch_enable_all () enable_user32_GetRawInputDeviceList="$1" enable_user32_GetSystemMetrics="$1" enable_user32_GetTipText="$1" + enable_user32_Key_State="$1" enable_user32_Mouse_Message_Hwnd="$1" enable_user32_Painting="$1" enable_user32_ScrollWindowEx="$1" @@ -625,6 +626,9 @@ patch_enable () user32-GetTipText) enable_user32_GetTipText="$2" ;; + user32-Key_State) + enable_user32_Key_State="$2" + ;; user32-Mouse_Message_Hwnd) enable_user32_Mouse_Message_Hwnd="$2" ;; @@ -3939,6 +3943,21 @@ if test "$enable_user32_GetTipText" -eq 1; then ) >> "$patchlist" fi +# Patchset user32-Key_State +# | +# | This patchset fixes the following Wine bugs: +# | * [#29871] Invalidate key state cache globally after calling LL hooks +# | +# | Modified files: +# | * dlls/user32/hook.c, dlls/user32/input.c, dlls/user32/message.c, dlls/user32/user_private.h +# | +if test "$enable_user32_Key_State" -eq 1; then + patch_apply user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch + ( + echo '+ { "Sebastian Lackner", "user32: After calling LL hooks the key state cache has to be invalidated globally.", 1 },'; + ) >> "$patchlist" +fi + # Patchset user32-Mouse_Message_Hwnd # | # | This patchset fixes the following Wine bugs: diff --git a/patches/user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch b/patches/user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch new file mode 100644 index 00000000..5eac4caf --- /dev/null +++ b/patches/user32-Key_State/0001-user32-After-calling-LL-hooks-the-key-state-cache-ha.patch @@ -0,0 +1,115 @@ +From 96c4389fb6f0799c218394dce61e204c5a03dc8f Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 14 Jul 2014 05:06:40 +0200 +Subject: user32: After calling LL hooks the key state cache has to be + invalidated globally. + +--- + dlls/user32/hook.c | 2 +- + dlls/user32/input.c | 8 ++++++-- + dlls/user32/message.c | 7 ++++++- + dlls/user32/user_private.h | 3 +++ + 4 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c +index 2f6b42c..0c6a059 100644 +--- a/dlls/user32/hook.c ++++ b/dlls/user32/hook.c +@@ -437,7 +437,7 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA + } + + if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL) +- get_user_thread_info()->key_state_time = 0; /* force refreshing the key state cache */ ++ interlocked_xchg_add(&global_key_state_epoch, 1); /* force refreshing the key state cache */ + + return ret; + } +diff --git a/dlls/user32/input.c b/dlls/user32/input.c +index 1f05f34..5671285 100644 +--- a/dlls/user32/input.c ++++ b/dlls/user32/input.c +@@ -52,6 +52,7 @@ + WINE_DEFAULT_DEBUG_CHANNEL(win); + WINE_DECLARE_DEBUG_CHANNEL(keyboard); + ++INT global_key_state_epoch = 0; + + /*********************************************************************** + * get_key_state +@@ -369,6 +370,7 @@ static void check_for_events( UINT flags ) + SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState( INT key ) + { + struct user_thread_info *thread_info = get_user_thread_info(); ++ INT epoch = global_key_state_epoch; + SHORT ret; + + if (key < 0 || key >= 256) return 0; +@@ -379,7 +381,8 @@ SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState( INT key ) + { + if (thread_info->key_state && + !(thread_info->key_state[key] & 0xc0) && +- GetTickCount() - thread_info->key_state_time < 50) ++ GetTickCount() - thread_info->key_state_time < 50 && ++ thread_info->key_state_epoch == epoch) + return 0; + + if (!thread_info->key_state) thread_info->key_state = HeapAlloc( GetProcessHeap(), 0, 256 ); +@@ -394,7 +397,8 @@ SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState( INT key ) + { + if (reply->state & 0x40) ret |= 0x0001; + if (reply->state & 0x80) ret |= 0x8000; +- thread_info->key_state_time = GetTickCount(); ++ thread_info->key_state_time = GetTickCount(); ++ thread_info->key_state_epoch = epoch; + } + } + SERVER_END_REQ; +diff --git a/dlls/user32/message.c b/dlls/user32/message.c +index eac4e4d..d59e342 100644 +--- a/dlls/user32/message.c ++++ b/dlls/user32/message.c +@@ -3294,6 +3294,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) + struct send_message_info info; + int prev_x, prev_y, new_x, new_y; + NTSTATUS ret; ++ INT epoch = global_key_state_epoch; + BOOL wait; + + info.type = MSG_HARDWARE; +@@ -3341,7 +3342,11 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, UINT flags ) + + if (!ret) + { +- if (thread_info->key_state) thread_info->key_state_time = GetTickCount(); ++ if (thread_info->key_state) ++ { ++ thread_info->key_state_time = GetTickCount(); ++ thread_info->key_state_epoch = epoch; ++ } + if ((flags & SEND_HWMSG_INJECTED) && (prev_x != new_x || prev_y != new_y)) + USER_Driver->pSetCursorPos( new_x, new_y ); + } +diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h +index adf3f7d..7afe48b 100644 +--- a/dlls/user32/user_private.h ++++ b/dlls/user32/user_private.h +@@ -184,6 +184,7 @@ struct user_thread_info + DWORD GetMessagePosVal; /* Value for GetMessagePos */ + ULONG_PTR GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */ + UINT active_hooks; /* Bitmap of active hooks */ ++ INT key_state_epoch; /* Counter to invalidate the key state */ + UINT key_state_time; /* Time of last key state refresh */ + BYTE *key_state; /* Cache of global key state */ + HWND top_window; /* Desktop window */ +@@ -193,6 +194,8 @@ struct user_thread_info + ULONG pad[6]; /* Available for more data */ + }; + ++extern INT global_key_state_epoch DECLSPEC_HIDDEN; ++ + struct hook_extra_info + { + HHOOK handle; +-- +2.3.2 + diff --git a/patches/user32-Key_State/definition b/patches/user32-Key_State/definition new file mode 100644 index 00000000..84dbc4b2 --- /dev/null +++ b/patches/user32-Key_State/definition @@ -0,0 +1 @@ +Fixes: [29871] Invalidate key state cache globally after calling LL hooks