First part of Proton shared memory series. The full branch can be seen at https://gitlab.winehq.org/rbernon/wine/-/commits/mr/shared-memories.
-- v11: user32: Use the desktop shared data for GetCursorPos(). server: Add a sequence number to the shared data. server: Move the cursor position and last change time to the shared data. server: Use the helper to update the cursor last change time. server: Create a desktop shared mapping.
From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- server/file.h | 1 + server/handle.c | 5 ++++- server/mapping.c | 17 +++++++++++++++++ server/protocol.def | 6 ++++++ server/user.h | 2 ++ server/winstation.c | 40 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/server/file.h b/server/file.h index 39a833cd105..9dc9740c85f 100644 --- a/server/file.h +++ b/server/file.h @@ -188,6 +188,7 @@ extern struct mapping *create_fd_mapping( struct object *root, const struct unic unsigned int attr, const struct security_descriptor *sd ); extern struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, const struct security_descriptor *sd ); +extern struct object *create_object_mapping( struct object *object, mem_size_t size, void **ptr );
/* device functions */
diff --git a/server/handle.c b/server/handle.c index 0595fdb403b..10803c0e0ea 100644 --- a/server/handle.c +++ b/server/handle.c @@ -620,6 +620,7 @@ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned const struct object_ops *ops, const struct unicode_str *name, unsigned int attributes ) { + static const WCHAR object_mappingW[] = {'_','_','w','i','n','e','_','m','a','p','p','i','n','g'}; obj_handle_t handle = 0; struct object *obj, *root = NULL;
@@ -631,7 +632,9 @@ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned
if (parent) { - if (name->len) + if (name->len == sizeof(object_mappingW) && !memcmp( name->str, object_mappingW, name->len )) + root = get_handle_obj( process, parent, 0, NULL ); + else if (name->len) root = get_directory_obj( process, parent ); else /* opening the object itself can work for non-directories too */ root = get_handle_obj( process, parent, 0, NULL ); diff --git a/server/mapping.c b/server/mapping.c index f754078acf7..242f12ce1a5 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1222,6 +1222,23 @@ int get_page_size(void) return page_mask + 1; }
+struct object *create_object_mapping( struct object *object, mem_size_t size, void **ptr ) +{ + static unsigned int access = FILE_READ_DATA | FILE_WRITE_DATA; + struct mapping *mapping; + void *tmp; + + if (!(mapping = create_mapping( object, NULL, 0, size, SEC_COMMIT, 0, access, NULL ))) return NULL; + if ((tmp = mmap( NULL, mapping->size, PROT_WRITE, MAP_SHARED, get_unix_fd( mapping->fd ), 0 )) == MAP_FAILED) + { + release_object( &mapping->obj ); + return NULL; + } + + *ptr = tmp; + return &mapping->obj; +} + struct object *create_user_data_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, const struct security_descriptor *sd ) { diff --git a/server/protocol.def b/server/protocol.def index 5d60e7fcda3..db039f45255 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -893,6 +893,12 @@ typedef struct lparam_t info; } cursor_pos_t;
+struct desktop_shared_memory +{ + int placeholder; +}; +typedef volatile struct desktop_shared_memory desktop_shm_t; + /****************************************************************/ /* Request declarations */
diff --git a/server/user.h b/server/user.h index 8fa55e09b0f..446e06ebb0c 100644 --- a/server/user.h +++ b/server/user.h @@ -76,6 +76,8 @@ struct desktop unsigned int users; /* processes and threads using this desktop */ struct global_cursor cursor; /* global cursor information */ unsigned char keystate[256]; /* asynchronous key state */ + struct object *shared_mapping; /* desktop shared memory mapping */ + const desktop_shm_t *shared; /* desktop shared memory */ };
/* user handles functions */ diff --git a/server/winstation.c b/server/winstation.c index 5903497d61e..e7ab1a63b83 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -23,6 +23,7 @@ #include <stdio.h> #include <stdarg.h> #include <sys/types.h> +#include <sys/mman.h>
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -50,6 +51,8 @@ static struct object *winstation_lookup_name( struct object *obj, struct unicode unsigned int attr, struct object *root ); static void winstation_destroy( struct object *obj ); static void desktop_dump( struct object *obj, int verbose ); +static struct object *desktop_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr, struct object *root ); static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ); static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void desktop_destroy( struct object *obj ); @@ -123,7 +126,7 @@ static const struct object_ops desktop_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ + desktop_lookup_name, /* lookup_name */ desktop_link_name, /* link_name */ default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ @@ -240,6 +243,17 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned memset( desktop->keystate, 0, sizeof(desktop->keystate) ); list_add_tail( &winstation->desktops, &desktop->entry ); list_init( &desktop->hotkeys ); + desktop->shared_mapping = NULL; + desktop->shared = NULL; + + if ((desktop->shared_mapping = create_object_mapping( &desktop->obj, sizeof(*desktop->shared), + (void **)&desktop->shared ))) + memset( (void *)desktop->shared, 0, sizeof(*desktop->shared) ); + else + { + release_object( desktop ); + return NULL; + } } else { @@ -258,6 +272,28 @@ static void desktop_dump( struct object *obj, int verbose ) desktop->flags, desktop->winstation, desktop->top_window, desktop->global_hooks ); }
+static struct object *desktop_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr, struct object *root ) +{ + static const WCHAR object_mappingW[] = {'_','_','w','i','n','e','_','m','a','p','p','i','n','g'}; + struct desktop *desktop = (struct desktop *)obj; + assert( obj->ops == &desktop_ops ); + + if (!name) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; + } + + if (name->len == sizeof(object_mappingW) && !memcmp( name->str, object_mappingW, name->len )) + { + name->len = 0; + return grab_object( desktop->shared_mapping ); + } + + return NULL; +} + static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ) { struct winstation *winstation = (struct winstation *)parent; @@ -298,6 +334,8 @@ static void desktop_destroy( struct object *obj ) if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout ); list_remove( &desktop->entry ); release_object( desktop->winstation ); + if (desktop->shared_mapping) release_object( desktop->shared_mapping ); + if (desktop->shared) munmap( (void *)desktop->shared, sizeof(*desktop->shared) ); }
/* retrieve the thread desktop, checking the handle access rights */
From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- server/queue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/queue.c b/server/queue.c index cd913ae03e5..eaeb5d15492 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1887,7 +1887,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons WM_MOUSEHWHEEL /* 0x1000 = MOUSEEVENTF_HWHEEL */ };
- desktop->cursor.last_change = get_tick_count(); + /* update last desktop cursor change time */ + update_desktop_cursor_pos( desktop, desktop->cursor.win, desktop->cursor.x, desktop->cursor.y ); + flags = input->mouse.flags; time = input->mouse.time; if (!time) time = desktop->cursor.last_change;
From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- server/protocol.def | 1 + server/queue.c | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 1f56b8f0bf7..a82ffe90e5e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -902,6 +902,7 @@ struct shared_cursor
struct desktop_shared_memory { + unsigned int seq; /* sequence number - server updating if (seq & 1) != 0 */ struct shared_cursor cursor; /* global cursor information */ }; typedef volatile struct desktop_shared_memory desktop_shm_t; diff --git a/server/queue.c b/server/queue.c index 7ee96c9325e..8f7c74724e8 100644 --- a/server/queue.c +++ b/server/queue.c @@ -232,14 +232,24 @@ static unsigned int last_input_time; static cursor_pos_t cursor_history[64]; static unsigned int cursor_history_latest;
-#define SHARED_WRITE_BEGIN( object, type ) \ - do { \ - const type *__shared = (object)->shared; \ - type *shared = (type *)__shared; \ +#if defined(__i386__) || defined(__x86_64__) +#define __SHARED_INCREMENT_SEQ( x ) ++(x) +#else +#define __SHARED_INCREMENT_SEQ( x ) __atomic_add_fetch( &(x), 1, __ATOMIC_RELEASE ) +#endif + +#define SHARED_WRITE_BEGIN( object, type ) \ + do { \ + const type *__shared = (object)->shared; \ + type *shared = (type *)__shared; \ + unsigned int __seq = __SHARED_INCREMENT_SEQ( shared->seq ); \ + assert( (__seq & 1) != 0 ); \ do
-#define SHARED_WRITE_END \ - while(0); \ +#define SHARED_WRITE_END \ + while(0); \ + __seq = __SHARED_INCREMENT_SEQ( shared->seq ) - __seq; \ + assert( __seq == 1 ); \ } while(0)
static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue );
From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- server/protocol.def | 9 ++++- server/queue.c | 82 +++++++++++++++++++++++++++------------------ server/user.h | 3 -- 3 files changed, 57 insertions(+), 37 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index db039f45255..1f56b8f0bf7 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -893,9 +893,16 @@ typedef struct lparam_t info; } cursor_pos_t;
+struct shared_cursor +{ + int x; /* cursor position */ + int y; + unsigned int last_change; /* time of last position change */ +}; + struct desktop_shared_memory { - int placeholder; + struct shared_cursor cursor; /* global cursor information */ }; typedef volatile struct desktop_shared_memory desktop_shm_t;
diff --git a/server/queue.c b/server/queue.c index eaeb5d15492..7ee96c9325e 100644 --- a/server/queue.c +++ b/server/queue.c @@ -232,6 +232,16 @@ static unsigned int last_input_time; static cursor_pos_t cursor_history[64]; static unsigned int cursor_history_latest;
+#define SHARED_WRITE_BEGIN( object, type ) \ + do { \ + const type *__shared = (object)->shared; \ + type *shared = (type *)__shared; \ + do + +#define SHARED_WRITE_END \ + while(0); \ + } while(0) + static void queue_hardware_message( struct desktop *desktop, struct message *msg, int always_queue ); static void free_message( struct message *msg );
@@ -423,8 +433,8 @@ static void queue_cursor_message( struct desktop *desktop, user_handle_t win, un msg->msg = message; msg->wparam = wparam; msg->lparam = lparam; - msg->x = desktop->cursor.x; - msg->y = desktop->cursor.y; + msg->x = desktop->shared->cursor.x; + msg->y = desktop->shared->cursor.y; if (!(msg->win = win) && (input = desktop->foreground_input)) msg->win = input->active; queue_hardware_message( desktop, msg, 1 ); } @@ -463,13 +473,19 @@ static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win, int x, int y ) { int updated; + unsigned int time = get_tick_count();
x = max( min( x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left ); y = max( min( y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top ); - updated = (desktop->cursor.x != x || desktop->cursor.y != y); - desktop->cursor.x = x; - desktop->cursor.y = y; - desktop->cursor.last_change = get_tick_count(); + updated = (desktop->shared->cursor.x != x || desktop->shared->cursor.y != y); + + SHARED_WRITE_BEGIN( desktop, desktop_shm_t ) + { + shared->cursor.x = x; + shared->cursor.y = y; + shared->cursor.last_change = time; + } + SHARED_WRITE_END;
if (!win || !is_window_visible( win ) || is_window_transparent( win )) win = shallow_window_from_point( desktop, x, y ); @@ -515,8 +531,8 @@ static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsig { struct desktop *desktop = queue->input->desktop;
- *x = desktop->cursor.x; - *y = desktop->cursor.y; + *x = desktop->shared->cursor.x; + *y = desktop->shared->cursor.y; *time = get_tick_count(); }
@@ -540,9 +556,9 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig else desktop->cursor.clip = top_rect;
/* warp the mouse to be inside the clip rect */ - x = max( min( desktop->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left ); - y = max( min( desktop->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top ); - if (x != desktop->cursor.x || y != desktop->cursor.y) set_cursor_pos( desktop, x, y ); + x = max( min( desktop->shared->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left ); + y = max( min( desktop->shared->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top ); + if (x != desktop->shared->cursor.x || y != desktop->shared->cursor.y) set_cursor_pos( desktop, x, y );
/* request clip cursor rectangle reset to the desktop thread */ if (reset) post_desktop_message( desktop, WM_WINE_CLIPCURSOR, flags, FALSE ); @@ -1695,8 +1711,8 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg if (desktop->keystate[VK_XBUTTON2] & 0x80) msg->wparam |= MK_XBUTTON2; break; } - msg->x = desktop->cursor.x; - msg->y = desktop->cursor.y; + msg->x = desktop->shared->cursor.x; + msg->y = desktop->shared->cursor.y;
if (msg->win && (thread = get_window_thread( msg->win ))) { @@ -1888,11 +1904,11 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons };
/* update last desktop cursor change time */ - update_desktop_cursor_pos( desktop, desktop->cursor.win, desktop->cursor.x, desktop->cursor.y ); + update_desktop_cursor_pos( desktop, desktop->cursor.win, desktop->shared->cursor.x, desktop->shared->cursor.y );
flags = input->mouse.flags; time = input->mouse.time; - if (!time) time = desktop->cursor.last_change; + if (!time) time = desktop->shared->cursor.last_change;
if (flags & MOUSEEVENTF_MOVE) { @@ -1901,19 +1917,19 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons x = input->mouse.x; y = input->mouse.y; if (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE) && - x == desktop->cursor.x && y == desktop->cursor.y) + x == desktop->shared->cursor.x && y == desktop->shared->cursor.y) flags &= ~MOUSEEVENTF_MOVE; } else { - x = desktop->cursor.x + input->mouse.x; - y = desktop->cursor.y + input->mouse.y; + x = desktop->shared->cursor.x + input->mouse.x; + y = desktop->shared->cursor.y + input->mouse.y; } } else { - x = desktop->cursor.x; - y = desktop->cursor.y; + x = desktop->shared->cursor.x; + y = desktop->shared->cursor.y; }
if ((foreground = get_foreground_thread( desktop, win ))) @@ -1930,8 +1946,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons msg_data->size = sizeof(*msg_data); msg_data->flags = flags; msg_data->rawinput.type = RIM_TYPEMOUSE; - msg_data->rawinput.mouse.x = x - desktop->cursor.x; - msg_data->rawinput.mouse.y = y - desktop->cursor.y; + msg_data->rawinput.mouse.x = x - desktop->shared->cursor.x; + msg_data->rawinput.mouse.y = y - desktop->shared->cursor.y; msg_data->rawinput.mouse.data = input->mouse.data;
enum_processes( queue_rawinput_message, &raw_msg ); @@ -2158,8 +2174,8 @@ static void queue_custom_hardware_message( struct desktop *desktop, user_handle_ msg->msg = input->hw.msg; msg->wparam = 0; msg->lparam = input->hw.lparam; - msg->x = desktop->cursor.x; - msg->y = desktop->cursor.y; + msg->x = desktop->shared->cursor.x; + msg->y = desktop->shared->cursor.y;
queue_hardware_message( desktop, msg, 1 ); } @@ -2680,8 +2696,8 @@ DECL_HANDLER(send_hardware_message) } }
- reply->prev_x = desktop->cursor.x; - reply->prev_y = desktop->cursor.y; + reply->prev_x = desktop->shared->cursor.x; + reply->prev_y = desktop->shared->cursor.y;
switch (req->input.type) { @@ -2699,8 +2715,8 @@ DECL_HANDLER(send_hardware_message) } if (thread) release_object( thread );
- reply->new_x = desktop->cursor.x; - reply->new_y = desktop->cursor.y; + reply->new_x = desktop->shared->cursor.x; + reply->new_y = desktop->shared->cursor.y; release_object( desktop ); }
@@ -3392,8 +3408,8 @@ DECL_HANDLER(set_cursor)
reply->prev_handle = input->cursor; reply->prev_count = input->cursor_count; - reply->prev_x = desktop->cursor.x; - reply->prev_y = desktop->cursor.y; + reply->prev_x = desktop->shared->cursor.x; + reply->prev_y = desktop->shared->cursor.y;
if (req->flags & SET_CURSOR_HANDLE) { @@ -3416,10 +3432,10 @@ DECL_HANDLER(set_cursor) if (req->flags & (SET_CURSOR_HANDLE | SET_CURSOR_COUNT)) update_desktop_cursor_handle( desktop, input );
- reply->new_x = desktop->cursor.x; - reply->new_y = desktop->cursor.y; + reply->new_x = desktop->shared->cursor.x; + reply->new_y = desktop->shared->cursor.y; reply->new_clip = desktop->cursor.clip; - reply->last_change = desktop->cursor.last_change; + reply->last_change = desktop->shared->cursor.last_change; }
/* Get the history of the 64 last cursor positions */ diff --git a/server/user.h b/server/user.h index 446e06ebb0c..6a0e3d65ab7 100644 --- a/server/user.h +++ b/server/user.h @@ -54,10 +54,7 @@ struct winstation
struct global_cursor { - int x; /* cursor position */ - int y; rectangle_t clip; /* cursor clip rectangle */ - unsigned int last_change; /* time of last position change */ user_handle_t win; /* window that contains the cursor */ };
From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- dlls/win32u/input.c | 20 ++++++------- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/sysparams.c | 1 + dlls/win32u/win32u_private.h | 25 ++++++++++++++++ dlls/win32u/winstation.c | 56 ++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index ef8d564c264..d793ac103e4 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -749,25 +749,23 @@ BOOL WINAPI NtUserSetCursorPos( INT x, INT y ) */ BOOL get_cursor_pos( POINT *pt ) { - BOOL ret; + const desktop_shm_t *shared; DWORD last_change; + BOOL ret = TRUE; UINT dpi;
- if (!pt) return FALSE; + if (!pt || !(shared = get_desktop_shared_memory())) return FALSE;
- SERVER_START_REQ( set_cursor ) + SHARED_READ_BEGIN( shared, desktop_shm_t ) { - 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;
/* query new position from graphics driver if we haven't updated recently */ - if (ret && NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt ); + if (NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt ); if (ret && (dpi = get_thread_dpi())) { HMONITOR monitor = monitor_from_point( *pt, MONITOR_DEFAULTTOPRIMARY, 0 ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 11bb7f4baf6..a027d99babe 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -137,6 +137,7 @@ struct user_thread_info UINT spy_indent; /* Current spy indent */ BOOL clipping_cursor; /* thread is currently clipping */ DWORD clipping_reset; /* time when clipping was last reset */ + const desktop_shm_t *desktop_shm; /* ptr to server's desktop shared memory */ };
C_ASSERT( sizeof(struct user_thread_info) <= sizeof(((TEB *)0)->Win32ClientInfo) ); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index e2c5b10da9e..bdf8ed70262 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -6204,6 +6204,7 @@ static void thread_detach(void) destroy_thread_windows(); cleanup_imm_thread(); NtClose( thread_info->server_queue ); + cleanup_thread_desktop();
exiting_thread_id = 0; } diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d5f010a8249..edcf45a032e 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -194,6 +194,8 @@ extern void user_unlock(void); extern void user_check_not_lock(void);
/* winstation.c */ +extern const desktop_shm_t *get_desktop_shared_memory(void); +extern void cleanup_thread_desktop(void); extern BOOL is_virtual_desktop(void);
/* window.c */ @@ -362,4 +364,27 @@ static inline BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 return !IsRectEmpty( 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( ptr, type ) \ + do { \ + const type *__shared = (ptr); \ + unsigned int __seq; \ + do { \ + while ((__seq = __SHARED_READ_SEQ( __shared->seq )) & 1) YieldProcessor(); \ + __SHARED_READ_FENCE; \ + do + +#define SHARED_READ_END \ + while (0); \ + __SHARED_READ_FENCE; \ + } while (__SHARED_READ_SEQ( __shared->seq ) != __seq); \ + } while(0) + #endif /* __WINE_WIN32U_PRIVATE */ diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b187b246941..2791aa0f72f 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -40,6 +40,61 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
#define DESKTOP_ALL_ACCESS 0x01ff
+static volatile void *map_object_shared_memory( HANDLE object, SIZE_T size ) +{ + static const WCHAR mapping_nameW[] = + { + '_','_','w','i','n','e','_','m','a','p','p','i','n','g',0 + }; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING section_str; + HANDLE handle; + UINT status; + void *ptr; + + RtlInitUnicodeString( §ion_str, mapping_nameW ); + InitializeObjectAttributes( &attr, §ion_str, 0, object, NULL ); + if (!(status = NtOpenSection( &handle, SECTION_ALL_ACCESS, &attr ))) + { + ptr = NULL; + status = NtMapViewOfSection( handle, GetCurrentProcess(), &ptr, 0, 0, NULL, + &size, ViewUnmap, 0, PAGE_READONLY ); + NtClose( handle ); + } + + if (status) + { + ERR( "Failed to map object %p mapping, status %#x\n", object, status ); + return NULL; + } + + return ptr; +} + +const desktop_shm_t *get_desktop_shared_memory(void) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + HANDLE desktop; + + if (thread_info->desktop_shm) return thread_info->desktop_shm; + + desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); + thread_info->desktop_shm = map_object_shared_memory( desktop, sizeof(*thread_info->desktop_shm) ); + + return thread_info->desktop_shm; +} + +void cleanup_thread_desktop(void) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + + if (thread_info->desktop_shm) + { + NtUnmapViewOfSection( GetCurrentProcess(), (void *)thread_info->desktop_shm ); + thread_info->desktop_shm = NULL; + } +} + BOOL is_virtual_desktop(void) { HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); @@ -265,6 +320,7 @@ BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ) thread_info->client_info.msg_window = 0; if (key_state_info) key_state_info->time = 0; if (was_virtual_desktop != is_virtual_desktop()) update_display_cache( TRUE ); + cleanup_thread_desktop(); } return ret; }
On Fri Jan 26 13:53:24 2024 +0000, Huw Davies wrote:
We should update the commit message to remove the reference to `SEQUENCE_MASK_BITS`.
Thanks, done.
On Fri Jan 26 13:53:11 2024 +0000, Rémi Bernon wrote:
changed this line in [version 11 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96142&start_sha=78e974f45e9b9277428d3fec078c188f93a43e1c#65b3cab82e46519733db1b5e9ec0bae066630154_288_288)
Done
Jinoh Kang (@iamahuman) commented about server/mapping.c:
return page_mask + 1;
}
+struct object *create_object_mapping( struct object *object, mem_size_t size, void **ptr ) +{
- static unsigned int access = FILE_READ_DATA | FILE_WRITE_DATA;
(nit) use `const`
```suggestion:-0+0 static const unsigned int access = FILE_READ_DATA | FILE_WRITE_DATA; ```
Intermediate review (I ran out of time)
Open questions:
- We probably don't need `SHARED_READ_BEGIN` from the server side, but why is this the case? - Is it a good idea to disable root object type check completely if the name is `__wine_mapping`? What if we open-coded in `DECL_HANDLER(open_mapping)` instead? Would that hurt readability much?