First part of Proton shared memory series. The full branch can be seen at https://gitlab.winehq.org/rbernon/wine/-/commits/mr/shared-memories.
-- v13: 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 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/mapping.c b/server/mapping.c index f754078acf7..785feb87cf4 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 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, mapping->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 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..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 | 89 ++++++++++++++++++++++++++++----------------- server/user.h | 3 -- 3 files changed, 63 insertions(+), 38 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 cd913ae03e5..4090ca833bb 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(); + + 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 ); @@ -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 ))) { @@ -1866,7 +1882,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;
@@ -1887,10 +1903,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) { @@ -1899,19 +1920,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 ))) @@ -1928,8 +1949,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 ); @@ -2156,8 +2177,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 ); } @@ -2678,8 +2699,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) { @@ -2697,8 +2718,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 ); }
@@ -3390,8 +3411,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) { @@ -3414,10 +3435,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 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 4090ca833bb..831c16c93ed 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
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 9cb251df5ce..84504dfdf9e 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 */ }; @@ -688,6 +689,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 48adb244b09..9ce6bbd94cc 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 0595fdb403b..3319d3b2b9c 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 785feb87cf4..ecdedf9475e 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 */ }; @@ -1281,10 +1284,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 dfdd691601f..05f593fca85 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 a0d5ea64d97..a203bef0544 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 831c16c93ed..5e79a52a83b 100644 --- a/server/queue.c +++ b/server/queue.c @@ -185,6 +185,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 */ }; @@ -222,6 +223,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 da6a6d0982e..4e80af2d2ba 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 c34fd3eb5eb..c9ea380e26f 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 | 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..1f860819ce8 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_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 +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 Mon Jan 29 19:06:34 2024 +0000, Rémi Bernon wrote:
changed this line in [version 13 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96513&start_sha=02f3db777425418f9a5da96713d355027b7e6bbd#2b37d5dc1c3bb6a637f043480c038caea64531bb_1235_1235)
Indeed.
On Mon Jan 29 19:06:32 2024 +0000, Rémi Bernon wrote:
changed this line in [version 13 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96513&start_sha=02f3db777425418f9a5da96713d355027b7e6bbd#65b3cab82e46519733db1b5e9ec0bae066630154_252_252)
Actually I think instead it should be removed. As I understand it the code in wineserver explicitly avoids clearing memory if not necessary, though I don't know if that's for efficiency or to avoid implicit initialization.
As we're mmapping new pages now it should be zeroed already and this was unnecessary. It was more like a leftover from a time where the code allowed mappings to be reused somehow.
On Mon Jan 29 15:58:18 2024 +0000, Jinoh Kang wrote:
If `desktop->cursor.win` became invisible or transparent since the last cursor update, `update_desktop_cursor_pos` may set another window, which will cause `update_desktop_cursor_window` to emit `WM_WINE_SETCURSOR` (previously, it didn't).
- Is this actually possible? (If not, is there anything that eagerly
switches the cursor window once the old window becomes invisible or transparent?) 2. If this is the case, could this lead to some kind of deadlock? 3. Are such side effects tolerable?
The message is going to be sent, sooner or later, when the hardware message is queued. Though this is currently *after* ll-hooks have been called, and this indeed changes things a bit.
I don't think it's too much trouble, `WM_WINE_SETCURSOR` is for the user driver internal purpose only and should not trigger any kind of loopback. It's maybe even more correct that way, I don't think ll-hooks are able to prevent the desktop cursor from being physically moved.
Then I'll just drop this for now, and instead update the time alone for now using the shared writes, I think this was historically using the helper mostly for convenience.
On Mon Jan 29 19:06:35 2024 +0000, Rémi Bernon wrote:
changed this line in [version 13 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96513&start_sha=02f3db777425418f9a5da96713d355027b7e6bbd#14b74bf2d7f44f52a31e4ee1baa51371f14df769_492_492)
Sure, I don't think reading data from within a write block is an issue as long as it's small enough. Done.
On Mon Jan 29 19:08:13 2024 +0000, Jinoh Kang wrote:
Can `get_object_mapping` ever fail (except `no_object_mapping`)? If we allow it to fail, should we distinguish this case by making `open_object_mapping` return a boolean instead and returning the mapping via some pass-by-ref out pointer?
I don't think it's worth adding error paths, it's only meant for Wine internal usage, and we should be able to consider that it's either supposed to return a mapping, or not, but never "fail".
On Mon Jan 29 19:08:14 2024 +0000, Jinoh Kang wrote:
`open_object_mapping` might have set an error, which might be returned by this function unmodified.
if ((mapping = open_object_mapping( req->rootdir, &name ))) { reply->handle = alloc_handle( current->process, &mapping->obj, req->access, req->attributes ); release_object( mapping ); return; } clear_error();
I've cleared the error inside the helper and also added a check to make sure we only call it with a root object.
On Mon Jan 29 19:06:39 2024 +0000, Rémi Bernon wrote:
changed this line in [version 13 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96513&start_sha=02f3db777425418f9a5da96713d355027b7e6bbd)
LGTM, done.
On Mon Jan 29 19:06:38 2024 +0000, Rémi Bernon wrote:
changed this line in [version 13 of the diff](/wine/wine/-/merge_requests/3103/diffs?diff_id=96513&start_sha=02f3db777425418f9a5da96713d355027b7e6bbd#35a0b3c4868b938764504464c7e3891ad9581e77_57_57)
Thanks.
Jinoh Kang (@iamahuman) commented about dlls/win32u/winstation.c:
#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 );
(super nit)
```suggestion:-0+0 section_str = RTL_CONSTANT_STRING( mapping_nameW ); ```
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 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, mapping->size, PROT_READ | PROT_WRITE, MAP_SHARED, get_unix_fd( mapping->fd ), 0 )) == MAP_FAILED)
If the host and guest page sizes don't match, I think we should prefer the original size for mmap(2). Note that we also use original size for munmap(2).
```suggestion:-0+0 if ((tmp = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, get_unix_fd( mapping->fd ), 0 )) == MAP_FAILED) ```
Jinoh Kang (@iamahuman) commented about dlls/win32u/winstation.c:
- 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_MAP_READ, &attr )))
- {
ptr = NULL;
status = NtMapViewOfSection( handle, GetCurrentProcess(), &ptr, 0, 0, NULL,
`NtMapViewOfSection` uses 64k granularity. This means that no two shared mapping views can share the same 64k. Are we sure this doesn't result in excessive address fragmentation (4k alloc, 60k feee, 4k alloc, ...)
On Wed Jan 31 16:33:02 2024 +0000, Jinoh Kang wrote:
`NtMapViewOfSection` uses 64k granularity. This means that no two shared mapping views can share the same 64k. Are we sure this doesn't result in excessive address fragmentation (4k alloc, 60k feee, 4k alloc, ...)
Is this something we should be worried about already? Fwiw this mechanism has been in Proton for a while and I don't think there's been issues because of that.
I don't think we can do much about it and if that only means pooling mapping, I would prefer to only pay the price of the increased complexity if truly necessary.