[PATCH 5/5] user32: Use the desktop shared data for GetCursorPos().
Huw Davies
huw at codeweavers.com
Thu Nov 19 07:09:31 CST 2020
Signed-off-by: Huw Davies <huw at codeweavers.com>
---
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
More information about the wine-devel
mailing list