First part of Proton shared memory series. The full branch can be seen at https://gitlab.winehq.org/rbernon/wine/-/commits/mr/shared-memories.
-- v16: user32: Use the desktop shared data for GetCursorPos(). server: Expose the desktop shared mapping to clients. server: Add a sequence number to the shared data. server: Move the cursor position and last change time to the shared data. 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/mapping.c | 17 +++++++++++++++++ server/protocol.def | 6 ++++++ server/user.h | 2 ++ server/winstation.c | 12 ++++++++++++ 5 files changed, 38 insertions(+)
diff --git a/server/file.h b/server/file.h index 7f2d1637863..e953120ef80 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/mapping.c b/server/mapping.c index 6b0de1b8b94..90b9c3bbe57 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1256,6 +1256,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 const 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, size, PROT_READ | 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 8b51618ebe0..531dace749e 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -879,6 +879,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..cedda7d5470 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 @@ -240,6 +241,15 @@ 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 ))) + { + release_object( desktop ); + return NULL; + } } else { @@ -298,6 +308,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/protocol.def | 9 ++++- server/queue.c | 90 ++++++++++++++++++++++++++++----------------- server/user.h | 3 -- 3 files changed, 65 insertions(+), 37 deletions(-)
diff --git a/server/protocol.def b/server/protocol.def index 531dace749e..7c39a1ba0b0 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -879,9 +879,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 6f38227aa84..f822826a8dd 100644 --- a/server/queue.c +++ b/server/queue.c @@ -233,6 +233,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 );
@@ -424,8 +434,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 ); } @@ -464,13 +474,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(); + + SHARED_WRITE_BEGIN( desktop, desktop_shm_t ) + { + updated = shared->cursor.x != x || shared->cursor.y != y; + 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 ); @@ -516,8 +532,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(); }
@@ -541,9 +557,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 ); @@ -1696,8 +1712,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 ))) { @@ -1996,7 +2012,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons struct rawinput_message raw_msg; struct message *msg; struct thread *foreground; - unsigned int i, time, flags; + unsigned int i, time = get_tick_count(), flags; struct hw_msg_source source = { IMDT_MOUSE, origin }; int wait = 0, x, y;
@@ -2017,10 +2033,15 @@ 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(); + SHARED_WRITE_BEGIN( desktop, desktop_shm_t ) + { + shared->cursor.last_change = time; + } + SHARED_WRITE_END; + 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) { @@ -2029,23 +2050,26 @@ 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 ))) { + int raw_x, raw_y; + raw_x = x - desktop->shared->cursor.x; + raw_y = y - desktop->shared->cursor.y; memset( &raw_msg, 0, sizeof(raw_msg) ); raw_msg.foreground = foreground; raw_msg.desktop = desktop; @@ -2053,7 +2077,7 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.time = time; raw_msg.message = WM_INPUT; raw_msg.flags = flags; - rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y, + rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, raw_x, raw_y, raw_msg.flags, input->mouse.data, input->mouse.info );
enum_processes( queue_rawinput_message, &raw_msg ); @@ -2263,8 +2287,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 ); } @@ -2785,8 +2809,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) { @@ -2804,8 +2828,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 ); }
@@ -3497,8 +3521,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) { @@ -3521,10 +3545,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. --- 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 7c39a1ba0b0..88666a8ca41 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -888,6 +888,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 f822826a8dd..8067e1b0f31 100644 --- a/server/queue.c +++ b/server/queue.c @@ -233,14 +233,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
Through a generic object mapping mechanism using __wine_mapping name. --- server/async.c | 2 ++ server/atom.c | 1 + server/change.c | 1 + server/clipboard.c | 1 + server/completion.c | 1 + server/console.c | 7 +++++++ server/debugger.c | 2 ++ server/device.c | 9 +++++++++ server/directory.c | 2 ++ server/event.c | 2 ++ server/fd.c | 4 ++++ server/file.c | 1 + server/handle.c | 1 + server/hook.c | 1 + server/mailslot.c | 4 ++++ server/mapping.c | 28 ++++++++++++++++++++++++++++ server/mutex.c | 1 + server/named_pipe.c | 5 +++++ server/object.h | 3 +++ server/process.c | 3 +++ server/queue.c | 2 ++ server/registry.c | 1 + server/request.c | 1 + server/semaphore.c | 1 + server/serial.c | 1 + server/signal.c | 1 + server/sock.c | 3 +++ server/symlink.c | 1 + server/thread.c | 3 +++ server/timer.c | 1 + server/token.c | 1 + server/window.c | 1 + server/winstation.c | 10 ++++++++++ 33 files changed, 106 insertions(+)
diff --git a/server/async.c b/server/async.c index 80129ac0ac3..dcc45973c64 100644 --- a/server/async.c +++ b/server/async.c @@ -89,6 +89,7 @@ static const struct object_ops async_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ async_destroy /* destroy */ }; @@ -698,6 +699,7 @@ static const struct object_ops iosb_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ iosb_destroy /* destroy */ }; diff --git a/server/atom.c b/server/atom.c index ff0799f5880..b2f3105138f 100644 --- a/server/atom.c +++ b/server/atom.c @@ -91,6 +91,7 @@ static const struct object_ops atom_table_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ atom_table_destroy /* destroy */ }; diff --git a/server/change.c b/server/change.c index 843e495411c..8cf3c960bf3 100644 --- a/server/change.c +++ b/server/change.c @@ -124,6 +124,7 @@ static const struct object_ops dir_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; diff --git a/server/clipboard.c b/server/clipboard.c index 8118a467dd8..bc12a150cd7 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -88,6 +88,7 @@ static const struct object_ops clipboard_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ clipboard_destroy /* destroy */ }; diff --git a/server/completion.c b/server/completion.c index 6933195e72d..8a67a1cbfd8 100644 --- a/server/completion.c +++ b/server/completion.c @@ -87,6 +87,7 @@ static const struct object_ops completion_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ completion_destroy /* destroy */ }; diff --git a/server/console.c b/server/console.c index b64283baf4a..b9837c169aa 100644 --- a/server/console.c +++ b/server/console.c @@ -93,6 +93,7 @@ static const struct object_ops console_ops = NULL, /* unlink_name */ console_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ console_destroy /* destroy */ }; @@ -170,6 +171,7 @@ static const struct object_ops console_server_ops = NULL, /* unlink_name */ console_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ console_server_destroy /* destroy */ }; @@ -239,6 +241,7 @@ static const struct object_ops screen_buffer_ops = NULL, /* unlink_name */ screen_buffer_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ screen_buffer_destroy /* destroy */ }; @@ -288,6 +291,7 @@ static const struct object_ops console_device_ops = default_unlink_name, /* unlink_name */ console_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -325,6 +329,7 @@ static const struct object_ops console_input_ops = default_unlink_name, /* unlink_name */ console_input_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ console_input_destroy /* destroy */ }; @@ -382,6 +387,7 @@ static const struct object_ops console_output_ops = default_unlink_name, /* unlink_name */ console_output_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ console_output_destroy /* destroy */ }; @@ -440,6 +446,7 @@ static const struct object_ops console_connection_ops = default_unlink_name, /* unlink_name */ console_connection_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ console_connection_close_handle, /* close_handle */ console_connection_destroy /* destroy */ }; diff --git a/server/debugger.c b/server/debugger.c index c59a0abea77..7ca3d5722a4 100644 --- a/server/debugger.c +++ b/server/debugger.c @@ -98,6 +98,7 @@ static const struct object_ops debug_event_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ debug_event_destroy /* destroy */ }; @@ -126,6 +127,7 @@ static const struct object_ops debug_obj_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ debug_obj_destroy /* destroy */ }; diff --git a/server/device.c b/server/device.c index 436dac6bfe9..2730d457816 100644 --- a/server/device.c +++ b/server/device.c @@ -78,6 +78,7 @@ static const struct object_ops irp_call_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ irp_call_destroy /* destroy */ }; @@ -118,6 +119,7 @@ static const struct object_ops device_manager_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ device_manager_destroy /* destroy */ }; @@ -175,6 +177,7 @@ static const struct object_ops device_ops = default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ device_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -227,6 +230,7 @@ static const struct object_ops device_file_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ device_file_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ device_file_close_handle, /* close_handle */ device_file_destroy /* destroy */ }; @@ -253,6 +257,11 @@ struct list *no_kernel_obj_list( struct object *obj ) return NULL; }
+struct mapping *no_object_mapping( struct object *obj ) +{ + return NULL; +} + struct kernel_object { struct device_manager *manager; diff --git a/server/directory.c b/server/directory.c index 23d7eb0a2b7..b16527cee3b 100644 --- a/server/directory.c +++ b/server/directory.c @@ -81,6 +81,7 @@ static const struct object_ops object_type_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -131,6 +132,7 @@ static const struct object_ops directory_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ }; diff --git a/server/event.c b/server/event.c index f1b79b1b35e..ce1adb5a9c5 100644 --- a/server/event.c +++ b/server/event.c @@ -84,6 +84,7 @@ static const struct object_ops event_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ event_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -131,6 +132,7 @@ static const struct object_ops keyed_event_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/fd.c b/server/fd.c index 8576882aaa9..85683ced951 100644 --- a/server/fd.c +++ b/server/fd.c @@ -181,6 +181,7 @@ static const struct object_ops fd_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ fd_destroy /* destroy */ }; @@ -222,6 +223,7 @@ static const struct object_ops device_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ device_destroy /* destroy */ }; @@ -262,6 +264,7 @@ static const struct object_ops inode_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ inode_destroy /* destroy */ }; @@ -304,6 +307,7 @@ static const struct object_ops file_lock_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/file.c b/server/file.c index 76c687833c9..d93b47a0b97 100644 --- a/server/file.c +++ b/server/file.c @@ -106,6 +106,7 @@ static const struct object_ops file_ops = NULL, /* unlink_name */ file_open_file, /* open_file */ file_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ file_destroy /* destroy */ }; diff --git a/server/handle.c b/server/handle.c index 71cdd2e328c..e66ab994a11 100644 --- a/server/handle.c +++ b/server/handle.c @@ -138,6 +138,7 @@ static const struct object_ops handle_table_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ handle_table_destroy /* destroy */ }; diff --git a/server/hook.c b/server/hook.c index 5abdf39ad37..fd4f5a01224 100644 --- a/server/hook.c +++ b/server/hook.c @@ -92,6 +92,7 @@ static const struct object_ops hook_table_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ hook_table_destroy /* destroy */ }; diff --git a/server/mailslot.c b/server/mailslot.c index 2d8697ec9bd..9b856513fcf 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -86,6 +86,7 @@ static const struct object_ops mailslot_ops = default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mailslot_destroy /* destroy */ }; @@ -145,6 +146,7 @@ static const struct object_ops mail_writer_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mail_writer_destroy /* destroy */ }; @@ -208,6 +210,7 @@ static const struct object_ops mailslot_device_ops = default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ }; @@ -238,6 +241,7 @@ static const struct object_ops mailslot_device_file_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mailslot_device_file_destroy /* destroy */ }; diff --git a/server/mapping.c b/server/mapping.c index 90b9c3bbe57..e06b94b2ffe 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -79,6 +79,7 @@ static const struct object_ops ranges_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ ranges_destroy /* destroy */ }; @@ -115,6 +116,7 @@ static const struct object_ops shared_map_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ shared_map_destroy /* destroy */ }; @@ -188,6 +190,7 @@ static const struct object_ops mapping_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mapping_destroy /* destroy */ }; @@ -1315,10 +1318,35 @@ DECL_HANDLER(create_mapping) if (root) release_object( root ); }
+static struct mapping *open_object_mapping( user_handle_t handle, struct unicode_str *name ) +{ + static const WCHAR object_mappingW[] = {'_','_','w','i','n','e','_','m','a','p','p','i','n','g'}; + struct mapping *mapping; + struct object *object; + + if (name->len != sizeof(object_mappingW) || memcmp( name->str, object_mappingW, name->len )) return NULL; + if (!(object = get_handle_obj( current->process, handle, 0, NULL ))) + { + clear_error(); + return NULL; + } + mapping = object->ops->get_object_mapping( object ); + release_object( object ); + return mapping; +} + /* open a handle to a mapping */ DECL_HANDLER(open_mapping) { struct unicode_str name = get_req_unicode_str(); + struct mapping *mapping; + + if (req->rootdir && (mapping = open_object_mapping( req->rootdir, &name ))) + { + reply->handle = alloc_handle( current->process, &mapping->obj, req->access, req->attributes ); + release_object( mapping ); + return; + }
reply->handle = open_object( current->process, req->rootdir, req->access, &mapping_ops, &name, req->attributes ); diff --git a/server/mutex.c b/server/mutex.c index af0efe72132..7d48fe9064e 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -85,6 +85,7 @@ static const struct object_ops mutex_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ }; diff --git a/server/named_pipe.c b/server/named_pipe.c index f3404a33c3b..ffb6347cbd1 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -131,6 +131,7 @@ static const struct object_ops named_pipe_ops = default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ }; @@ -179,6 +180,7 @@ static const struct object_ops pipe_server_ops = NULL, /* unlink_name */ pipe_server_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ async_close_obj_handle, /* close_handle */ pipe_server_destroy /* destroy */ }; @@ -223,6 +225,7 @@ static const struct object_ops pipe_client_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ async_close_obj_handle, /* close_handle */ pipe_end_destroy /* destroy */ }; @@ -270,6 +273,7 @@ static const struct object_ops named_pipe_device_ops = default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ }; @@ -301,6 +305,7 @@ static const struct object_ops named_pipe_device_file_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ named_pipe_device_file_destroy /* destroy */ }; diff --git a/server/object.h b/server/object.h index d4d66536b81..d94a1a2d734 100644 --- a/server/object.h +++ b/server/object.h @@ -103,6 +103,8 @@ struct object_ops unsigned int options); /* return list of kernel objects */ struct list *(*get_kernel_obj_list)(struct object *); + /* return the memory mapping for the object */ + struct mapping *(*get_object_mapping)(struct object *); /* close a handle to this object */ int (*close_handle)(struct object *,struct process *,obj_handle_t); /* destroy on refcount == 0 */ @@ -181,6 +183,7 @@ extern void default_unlink_name( struct object *obj, struct object_name *name ); extern struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); extern struct list *no_kernel_obj_list( struct object *obj ); +extern struct mapping *no_object_mapping( struct object *obj ); extern int no_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); extern void no_destroy( struct object *obj ); #ifdef DEBUG_OBJECTS diff --git a/server/process.c b/server/process.c index 3651696f505..eceefc2b274 100644 --- a/server/process.c +++ b/server/process.c @@ -117,6 +117,7 @@ static const struct object_ops process_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ process_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ process_destroy /* destroy */ }; @@ -168,6 +169,7 @@ static const struct object_ops startup_info_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ startup_info_destroy /* destroy */ }; @@ -229,6 +231,7 @@ static const struct object_ops job_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ job_close_handle, /* close_handle */ job_destroy /* destroy */ }; diff --git a/server/queue.c b/server/queue.c index 8067e1b0f31..c4d2fa540b9 100644 --- a/server/queue.c +++ b/server/queue.c @@ -186,6 +186,7 @@ static const struct object_ops msg_queue_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ msg_queue_destroy /* destroy */ }; @@ -223,6 +224,7 @@ static const struct object_ops thread_input_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ thread_input_destroy /* destroy */ }; diff --git a/server/registry.c b/server/registry.c index e88bed1e72e..4af5b8563ec 100644 --- a/server/registry.c +++ b/server/registry.c @@ -192,6 +192,7 @@ static const struct object_ops key_ops = key_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ key_close_handle, /* close_handle */ key_destroy /* destroy */ }; diff --git a/server/request.c b/server/request.c index 7021741c765..d93e86e3eed 100644 --- a/server/request.c +++ b/server/request.c @@ -102,6 +102,7 @@ static const struct object_ops master_socket_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ master_socket_destroy /* destroy */ }; diff --git a/server/semaphore.c b/server/semaphore.c index 53b42a886df..eaf909aa551 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -82,6 +82,7 @@ static const struct object_ops semaphore_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/serial.c b/server/serial.c index d665eb7fa35..64af16d6a51 100644 --- a/server/serial.c +++ b/server/serial.c @@ -97,6 +97,7 @@ static const struct object_ops serial_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ serial_destroy /* destroy */ }; diff --git a/server/signal.c b/server/signal.c index 19b76d44c16..45c6d77f552 100644 --- a/server/signal.c +++ b/server/signal.c @@ -74,6 +74,7 @@ static const struct object_ops handler_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ handler_destroy /* destroy */ }; diff --git a/server/sock.c b/server/sock.c index 3ad1ce39194..614c6871e96 100644 --- a/server/sock.c +++ b/server/sock.c @@ -465,6 +465,7 @@ static const struct object_ops sock_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ sock_close_handle, /* close_handle */ sock_destroy /* destroy */ }; @@ -3566,6 +3567,7 @@ static const struct object_ops ifchange_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ ifchange_destroy /* destroy */ }; @@ -3787,6 +3789,7 @@ static const struct object_ops socket_device_ops = default_unlink_name, /* unlink_name */ socket_device_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; diff --git a/server/symlink.c b/server/symlink.c index dd28efd3a75..0492b83172a 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -83,6 +83,7 @@ static const struct object_ops symlink_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ }; diff --git a/server/thread.c b/server/thread.c index 56f57cefd8f..5673c9d4809 100644 --- a/server/thread.c +++ b/server/thread.c @@ -108,6 +108,7 @@ static const struct object_ops thread_apc_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ thread_apc_destroy /* destroy */ }; @@ -150,6 +151,7 @@ static const struct object_ops context_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ no_destroy /* destroy */ }; @@ -199,6 +201,7 @@ static const struct object_ops thread_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ thread_get_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ destroy_thread /* destroy */ }; diff --git a/server/timer.c b/server/timer.c index 96dc9d00ca1..3f083db56b8 100644 --- a/server/timer.c +++ b/server/timer.c @@ -88,6 +88,7 @@ static const struct object_ops timer_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ }; diff --git a/server/token.c b/server/token.c index 4df8d2e0c6e..94e3fd0b121 100644 --- a/server/token.c +++ b/server/token.c @@ -155,6 +155,7 @@ static const struct object_ops token_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ token_destroy /* destroy */ }; diff --git a/server/window.c b/server/window.c index 242e93f303a..8fb4162f9f4 100644 --- a/server/window.c +++ b/server/window.c @@ -119,6 +119,7 @@ static const struct object_ops window_ops = NULL, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ no_close_handle, /* close_handle */ window_destroy /* destroy */ }; diff --git a/server/winstation.c b/server/winstation.c index cedda7d5470..905a560d8d6 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -52,6 +52,7 @@ static struct object *winstation_lookup_name( struct object *obj, struct unicode static void winstation_destroy( struct object *obj ); static void desktop_dump( struct object *obj, int verbose ); static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ); +static struct mapping *desktop_get_object_mapping( struct object *obj ); static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void desktop_destroy( struct object *obj );
@@ -89,6 +90,7 @@ static const struct object_ops winstation_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + no_object_mapping, /* get_object_mapping */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ }; @@ -129,6 +131,7 @@ static const struct object_ops desktop_ops = default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_kernel_obj_list, /* get_kernel_obj_list */ + desktop_get_object_mapping, /* get_object_mapping */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ }; @@ -286,6 +289,13 @@ static int desktop_link_name( struct object *obj, struct object_name *name, stru return 1; }
+static struct mapping *desktop_get_object_mapping( struct object *obj ) +{ + struct desktop *desktop = (struct desktop *)obj; + assert( obj->ops == &desktop_ops ); + return (struct mapping *)grab_object( desktop->shared_mapping ); +} + static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) { struct thread *thread;
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 | 55 ++++++++++++++++++++++++++++++++++++ 5 files changed, 91 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 3b6cab5bdc9..11fc1a19850 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -127,6 +127,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 673082056b1..03deb0a224d 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..9012c377f99 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -40,6 +40,60 @@ 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 object_mappingW[] = + { + '_','_','w','i','n','e','_','m','a','p','p','i','n','g',0 + }; + UNICODE_STRING section_str = RTL_CONSTANT_STRING( object_mappingW ); + OBJECT_ATTRIBUTES attr; + HANDLE handle; + UINT status; + void *ptr; + + InitializeObjectAttributes( &attr, §ion_str, 0, object, NULL ); + if (!(status = NtOpenSection( &handle, SECTION_MAP_READ, &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(); + + if (!thread_info->desktop_shm) + { + HANDLE 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 +319,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; }
Only rebased (please ignore db2b6c49, I messed it up), will address the comments next.