From: Huw Davies Subject: [PATCH 5/5] user32: Use the desktop shared data for GetCursorPos(). Message-Id: <20201119130931.89653-5-huw@codeweavers.com> Date: Thu, 19 Nov 2020 13:09:31 +0000 Signed-off-by: Huw Davies --- dlls/user32/input.c | 20 ++++++------- dlls/user32/user_private.h | 23 +++++++++++++++ dlls/user32/winstation.c | 60 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/dlls/user32/input.c b/dlls/user32/input.c index e06f8b4413e..efe9922e62a 100644 --- a/dlls/user32/input.c +++ b/dlls/user32/input.c @@ -246,25 +246,23 @@ void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy, */ BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt ) { - BOOL ret; + BOOL ret = TRUE; DWORD last_change; UINT dpi; + volatile struct desktop_shared_memory *shared = get_desktop_shared_memory(); - if (!pt) return FALSE; + if (!pt || !shared) return FALSE; - SERVER_START_REQ( set_cursor ) + SHARED_READ_BEGIN( &shared->seq ) { - if ((ret = !wine_server_call( req ))) - { - pt->x = reply->new_x; - pt->y = reply->new_y; - last_change = reply->last_change; - } + pt->x = shared->cursor.x; + pt->y = shared->cursor.y; + last_change = shared->cursor.last_change; } - SERVER_END_REQ; + SHARED_READ_END( &shared->seq ); /* query new position from graphics driver if we haven't updated recently */ - if (ret && GetTickCount() - last_change > 100) ret = USER_Driver->pGetCursorPos( pt ); + if (GetTickCount() - last_change > 100) ret = USER_Driver->pGetCursorPos( pt ); if (ret && (dpi = get_thread_dpi())) { DPI_AWARENESS_CONTEXT context; diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 7761a1ceb4f..2cff12c2275 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -202,6 +202,8 @@ struct user_thread_info HWND top_window; /* Desktop window */ HWND msg_window; /* HWND_MESSAGE parent window */ struct rawinput_thread_data *rawinput; /* RawInput thread local data / buffer */ + HANDLE desktop_shared_map; /* HANDLE to server's desktop shared memory */ + struct desktop_shared_memory *shared_memory; /* Ptr to server's desktop shared memory */ }; C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) ); @@ -293,6 +295,7 @@ extern BOOL WINPROC_call_window( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar extern const WCHAR *CLASS_GetVersionedName(const WCHAR *classname, UINT *basename_offset, WCHAR *combined, BOOL register_class) DECLSPEC_HIDDEN; +extern volatile struct desktop_shared_memory *get_desktop_shared_memory( void ) DECLSPEC_HIDDEN; /* message spy definitions */ @@ -391,4 +394,24 @@ static inline WCHAR *heap_strdupW(const WCHAR *src) return dst; } +#if defined(__i386__) || defined(__x86_64__) +#define __SHARED_READ_SEQ( x ) (*(x)) +#define __SHARED_READ_FENCE do {} while(0) +#else +#define __SHARED_READ_SEQ( x ) __atomic_load_n( x, __ATOMIC_RELAXED ) +#define __SHARED_READ_FENCE __atomic_thread_fence( __ATOMIC_ACQUIRE ) +#endif + +#define SHARED_READ_BEGIN( x ) \ + do { \ + unsigned int __seq; \ + do { \ + while ((__seq = __SHARED_READ_SEQ( x )) & SEQUENCE_MASK) NtYieldExecution(); \ + __SHARED_READ_FENCE; + +#define SHARED_READ_END( x ) \ + __SHARED_READ_FENCE; \ + } while (__SHARED_READ_SEQ( x ) != __seq); \ + } while(0) + #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/user32/winstation.c b/dlls/user32/winstation.c index 95a9eb85099..821c04608e7 100644 --- a/dlls/user32/winstation.c +++ b/dlls/user32/winstation.c @@ -100,6 +100,60 @@ static const WCHAR *get_winstation_default_name( void ) return ret ? default_name : NULL; } + +volatile struct desktop_shared_memory *get_desktop_shared_memory( void ) +{ + static const WCHAR dir_desktop_mapsW[] = {'_','_','w','i','n','e','_','d','e','s','k','t','o','p','_','m','a','p','p','i','n','g','s','\\'}; + struct user_thread_info *thread_info = get_user_thread_info(); + HANDLE root = get_winstations_dir_handle(), handles[2]; + WCHAR buf[MAX_PATH], *ptr; + DWORD i, needed; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING section_str; + NTSTATUS status; + SIZE_T size; + + if (thread_info->shared_memory) return thread_info->shared_memory; + + handles[0] = GetProcessWindowStation(); + handles[1] = GetThreadDesktop( GetCurrentThreadId() ); + + memcpy( buf, dir_desktop_mapsW, sizeof(dir_desktop_mapsW) ); + ptr = buf + ARRAY_SIZE(dir_desktop_mapsW); + + for (i = 0; i < 2; i++) + { + GetUserObjectInformationW( handles[i], UOI_NAME, (void *)ptr, sizeof(buf) - (ptr - buf) * sizeof(WCHAR), &needed ); + ptr += needed / sizeof(WCHAR); + if (i == 0) *(ptr - 1) = '\\'; + } + + RtlInitUnicodeString( §ion_str, buf ); + InitializeObjectAttributes( &attr, §ion_str, 0, root, NULL ); + status = NtOpenSection( &handles[0], SECTION_ALL_ACCESS, &attr ); + if (status) + { + ERR( "failed to open the desktop section: %08x\n", status ); + return NULL; + } + + ptr = NULL; + size = sizeof(struct desktop_shared_memory); + status = NtMapViewOfSection( handles[0], GetCurrentProcess(), (void *)&ptr, 0, 0, NULL, + &size, ViewUnmap, 0, PAGE_READONLY ); + if (status) + { + ERR( "failed to map view of the desktop section: %08x\n", status ); + CloseHandle( handles[0] ); + return NULL; + } + + thread_info->desktop_shared_map = handles[0]; + thread_info->shared_memory = (struct desktop_shared_memory *)ptr; + return thread_info->shared_memory; +} + + /*********************************************************************** * CreateWindowStationA (USER32.@) */ @@ -460,6 +514,12 @@ BOOL WINAPI SetThreadDesktop( HDESK handle ) thread_info->top_window = 0; thread_info->msg_window = 0; if (key_state_info) key_state_info->time = 0; + if (thread_info->desktop_shared_map) + { + CloseHandle( thread_info->desktop_shared_map ); + thread_info->desktop_shared_map = NULL; + thread_info->shared_memory = NULL; + } } return ret; } -- 2.23.0