[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( &section_str, buf );
+    InitializeObjectAttributes( &attr, &section_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