From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 4 ++++ dlls/win32u/winstation.c | 38 +++++++++++++++++++++++++++++++++++- server/protocol.def | 25 ++++++++++++++++-------- server/window.c | 26 ++++++++++++++++++++++-- 5 files changed, 83 insertions(+), 11 deletions(-)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index b4738ed6b16..3bdfa47b439 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -222,6 +222,7 @@ struct object_lock extern NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ); extern NTSTATUS get_shared_queue( struct object_lock *lock, const queue_shm_t **queue_shm ); extern NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t **input_shm ); +extern void set_shared_user_object( HANDLE handle, struct obj_locator locator );
extern BOOL is_virtual_desktop(void);
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 1cea6d25a4b..6dbfaebb497 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -5305,6 +5305,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, UINT dpi_context = get_thread_dpi_awareness_context(); HWND handle = 0, full_parent = 0, full_owner = 0; struct tagCLASS *class = NULL; + struct obj_locator locator; int extra_bytes = 0; WND *win;
@@ -5320,6 +5321,7 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, wine_server_add_data( req, name->Buffer, name->Length ); if (!wine_server_call_err( req )) { + locator = reply->locator; handle = wine_server_ptr_handle( reply->handle ); full_parent = wine_server_ptr_handle( reply->parent ); full_owner = wine_server_ptr_handle( reply->owner ); @@ -5348,6 +5350,8 @@ static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name, return NULL; }
+ set_shared_user_object( handle, locator ); + if (!parent) /* if parent is 0 we don't have a desktop window yet */ { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b350b706454..5850f1121f0 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -52,6 +52,12 @@ struct shared_input_cache DWORD tid; };
+struct shared_user_object_cache +{ + const shared_object_t *object; + UINT64 id; +}; + struct session_thread_data { const shared_object_t *shared_desktop; /* thread desktop shared session cached object */ @@ -328,6 +334,26 @@ NTSTATUS get_shared_input( UINT tid, struct object_lock *lock, const input_shm_t return status; }
+#define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1) +#define USER_HANDLE_TO_INDEX(handle) ((LOWORD(handle) - FIRST_USER_HANDLE) >> 1) + +static struct shared_user_object_cache user_objects[NB_USER_HANDLES]; +static pthread_mutex_t user_objects_lock = PTHREAD_MUTEX_INITIALIZER; + +void set_shared_user_object( HANDLE handle, struct obj_locator locator ) +{ + WORD index = USER_HANDLE_TO_INDEX( handle ); + struct shared_user_object_cache *cache; + + if (index >= NB_USER_HANDLES) return; + cache = user_objects + index; + + pthread_mutex_lock( &user_objects_lock ); + cache->id = locator.id; + cache->object = find_shared_session_object( locator ); + pthread_mutex_unlock( &user_objects_lock ); +} + BOOL is_virtual_desktop(void) { struct object_lock lock = OBJECT_LOCK_INIT; @@ -777,6 +803,7 @@ HWND get_desktop_window(void) static const WCHAR wine_service_station_name[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n',0}; struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); + struct obj_locator top_locator, msg_locator; WCHAR name[MAX_PATH]; BOOL is_service;
@@ -796,6 +823,8 @@ HWND get_desktop_window(void) { thread_info->top_window = reply->top_window; thread_info->msg_window = reply->msg_window; + top_locator = reply->top_locator; + msg_locator = reply->msg_locator; } } SERVER_END_REQ; @@ -878,13 +907,20 @@ HWND get_desktop_window(void) { thread_info->top_window = reply->top_window; thread_info->msg_window = reply->msg_window; + top_locator = reply->top_locator; + msg_locator = reply->msg_locator; } } SERVER_END_REQ; }
if (!thread_info->top_window) ERR_(win)( "failed to create desktop window\n" ); - else user_driver->pSetDesktopWindow( UlongToHandle( thread_info->top_window )); + else + { + set_shared_user_object( UlongToHandle( thread_info->top_window ), top_locator ); + set_shared_user_object( UlongToHandle( thread_info->msg_window ), msg_locator ); + user_driver->pSetDesktopWindow( UlongToHandle( thread_info->top_window )); + }
register_builtin_classes(); return UlongToHandle( thread_info->top_window ); diff --git a/server/protocol.def b/server/protocol.def index cc658915da0..44e952ecc91 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1007,11 +1007,17 @@ typedef volatile struct int keystate_lock; /* keystate is locked */ } input_shm_t;
+typedef volatile struct +{ + int placeholder; +} window_shm_t; + typedef volatile union { desktop_shm_t desktop; queue_shm_t queue; input_shm_t input; + window_shm_t window; } object_shm_t;
typedef volatile struct @@ -2531,12 +2537,13 @@ enum message_type unsigned int ex_style; /* window extended style */ VARARG(class,unicode_str); /* class name */ @REPLY - user_handle_t handle; /* created window */ - user_handle_t parent; /* full handle of parent */ - user_handle_t owner; /* full handle of owner */ - int extra; /* number of extra bytes */ - client_ptr_t class_ptr; /* pointer to class in client address space */ - unsigned int dpi_context; /* window DPI context */ + struct obj_locator locator; /* locator for the shared session object */ + user_handle_t handle; /* created window */ + user_handle_t parent; /* full handle of parent */ + user_handle_t owner; /* full handle of owner */ + int extra; /* number of extra bytes */ + client_ptr_t class_ptr; /* pointer to class in client address space */ + unsigned int dpi_context; /* window DPI context */ @END
@@ -2550,8 +2557,10 @@ enum message_type @REQ(get_desktop_window) int force; /* force creation if it doesn't exist */ @REPLY - user_handle_t top_window; /* handle to the desktop window */ - user_handle_t msg_window; /* handle to the top-level HWND_MESSAGE parent */ + user_handle_t top_window; /* handle to the desktop window */ + user_handle_t msg_window; /* handle to the top-level HWND_MESSAGE parent */ + struct obj_locator top_locator; /* locator for the desktop window shared session object */ + struct obj_locator msg_locator; /* locator for the message window shared session object */ @END
diff --git a/server/window.c b/server/window.c index afd4564e206..1fe681b5d56 100644 --- a/server/window.c +++ b/server/window.c @@ -29,6 +29,7 @@ #include "winbase.h" #include "ntuser.h"
+#include "file.h" #include "object.h" #include "request.h" #include "thread.h" @@ -94,6 +95,7 @@ struct window struct property *properties; /* window properties array */ int nb_extra_bytes; /* number of extra bytes */ char *extra_bytes; /* extra bytes storage */ + const window_shm_t *shared; /* window in session shared memory */ };
static void window_dump( struct object *obj, int verbose ); @@ -180,6 +182,8 @@ static void window_destroy( struct object *obj ) memset( win->extra_bytes, 0x55, win->nb_extra_bytes ); free( win->extra_bytes ); } + + if (win->shared) free_shared_object( win->shared ); }
/* retrieve a pointer to a window from its handle */ @@ -662,10 +666,18 @@ static struct window *create_window( struct window *parent, struct window *owner win->properties = NULL; win->nb_extra_bytes = 0; win->extra_bytes = NULL; + win->shared = NULL; win->window_rect = win->visible_rect = win->surface_rect = win->client_rect = empty_rect; list_init( &win->children ); list_init( &win->unlinked );
+ if (!(win->shared = alloc_shared_object())) goto failed; + SHARED_WRITE_BEGIN( win->shared, window_shm_t ) + { + shared->placeholder = 0; + } + SHARED_WRITE_END; + if (extra_bytes) { if (!(win->extra_bytes = mem_alloc( extra_bytes ))) goto failed; @@ -2204,6 +2216,7 @@ DECL_HANDLER(create_window) win->style = req->style; win->ex_style = req->ex_style;
+ reply->locator = get_shared_object_locator( win->shared ); reply->handle = win->handle; reply->parent = win->parent ? win->parent->handle : 0; reply->owner = win->owner; @@ -2255,6 +2268,7 @@ DECL_HANDLER(destroy_window) DECL_HANDLER(get_desktop_window) { struct desktop *desktop = get_thread_desktop( current, 0 ); + struct window *win;
if (!desktop) return;
@@ -2279,8 +2293,16 @@ DECL_HANDLER(get_desktop_window) } }
- reply->top_window = desktop->top_window ? desktop->top_window->handle : 0; - reply->msg_window = desktop->msg_window ? desktop->msg_window->handle : 0; + if ((win = desktop->top_window)) + { + reply->top_window = win->handle; + reply->top_locator = get_shared_object_locator( win->shared ); + } + if ((win = desktop->msg_window)) + { + reply->msg_window = win->handle; + reply->msg_locator = get_shared_object_locator( win->shared ); + } release_object( desktop ); }