From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/win32u_private.h | 1 + dlls/win32u/winstation.c | 46 ++++++++++++++++++++++++++++++++---- server/protocol.def | 14 ++++++++--- server/user.c | 23 ++++++++++++++++++ server/user.h | 1 + server/winstation.c | 6 +++-- 6 files changed, 82 insertions(+), 9 deletions(-)
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index b4738ed6b16..128a95b5bf5 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -219,6 +219,7 @@ struct object_lock * The data read from the objects may be transient and no logic should be executed based * on it, within the loop, or after, unless the function has returned STATUS_SUCCESS. */ +extern NTSTATUS get_shared_session( struct object_lock *lock, const session_shm_t **session_shm ); 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 ); diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b350b706454..a14dc0a01ee 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -54,6 +54,7 @@ struct shared_input_cache
struct session_thread_data { + const shared_object_t *shared_session; /* shared session cached object */ const shared_object_t *shared_desktop; /* thread desktop shared session cached object */ const shared_object_t *shared_queue; /* thread message queue shared session cached object */ struct shared_input_cache shared_input; /* current thread input shared session cached object */ @@ -195,6 +196,41 @@ static const shared_object_t *find_shared_session_object( struct obj_locator loc return NULL; }
+NTSTATUS get_shared_session( struct object_lock *lock, const session_shm_t **session_shm ) +{ + struct session_thread_data *data = get_session_thread_data(); + const shared_object_t *object; + + TRACE( "lock %p, session_shm %p\n", lock, session_shm ); + + if (!(object = data->shared_session)) + { + struct obj_locator locator; + + SERVER_START_REQ( get_thread_desktop ) + { + req->tid = GetCurrentThreadId(); + wine_server_call( req ); + locator = reply->session_locator; + } + SERVER_END_REQ; + + data->shared_session = find_shared_session_object( locator ); + if (!(object = data->shared_session)) return STATUS_INVALID_HANDLE; + memset( lock, 0, sizeof(*lock) ); + } + + if (!lock->id || !shared_object_release_seqlock( object, lock->seq )) + { + shared_object_acquire_seqlock( object, &lock->seq ); + *session_shm = &object->shm.session; + lock->id = object->id; + return STATUS_PENDING; + } + + return STATUS_SUCCESS; +} + NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **desktop_shm ) { struct session_thread_data *data = get_session_thread_data(); @@ -210,7 +246,7 @@ NTSTATUS get_shared_desktop( struct object_lock *lock, const desktop_shm_t **des { req->tid = GetCurrentThreadId(); wine_server_call( req ); - locator = reply->locator; + locator = reply->desktop_locator; } SERVER_END_REQ;
@@ -547,13 +583,14 @@ HDESK WINAPI NtUserGetThreadDesktop( DWORD thread ) BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ) { BOOL ret, was_virtual_desktop = is_virtual_desktop(); - struct obj_locator locator; + struct obj_locator session_locator, desktop_locator;
SERVER_START_REQ( set_thread_desktop ) { req->handle = wine_server_obj_handle( handle ); ret = !wine_server_call_err( req ); - locator = reply->locator; + session_locator = reply->session_locator; + desktop_locator = reply->desktop_locator; } SERVER_END_REQ;
@@ -561,7 +598,8 @@ BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ) { struct user_thread_info *thread_info = get_user_thread_info(); struct session_thread_data *data = get_session_thread_data(); - data->shared_desktop = find_shared_session_object( locator ); + data->shared_session = find_shared_session_object( session_locator ); + data->shared_desktop = find_shared_session_object( desktop_locator ); memset( &data->shared_foreground, 0, sizeof(data->shared_foreground) ); thread_info->client_info.top_window = 0; thread_info->client_info.msg_window = 0; diff --git a/server/protocol.def b/server/protocol.def index 871c3909e8c..9ce2257e821 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -976,6 +976,11 @@ struct shared_cursor struct rectangle clip; /* cursor clip rectangle */ };
+typedef volatile struct +{ + int placeholder; +} session_shm_t; + typedef volatile struct { unsigned int flags; /* desktop flags */ @@ -1011,6 +1016,7 @@ typedef volatile struct
typedef volatile union { + session_shm_t session; desktop_shm_t desktop; queue_shm_t queue; input_shm_t input; @@ -2963,8 +2969,9 @@ enum coords_relative @REQ(get_thread_desktop) thread_id_t tid; /* thread id */ @REPLY - struct obj_locator locator; /* locator for the shared session object */ - obj_handle_t handle; /* handle to the desktop */ + struct obj_locator session_locator; /* locator for the shared session object */ + struct obj_locator desktop_locator; /* locator for the shared session desktop object */ + obj_handle_t handle; /* handle to the desktop */ @END
@@ -2972,7 +2979,8 @@ enum coords_relative @REQ(set_thread_desktop) obj_handle_t handle; /* handle to the desktop */ @REPLY - struct obj_locator locator; /* locator for the shared session object */ + struct obj_locator session_locator; /* locator for the shared session object */ + struct obj_locator desktop_locator; /* locator for the shared session desktop object */ @END
diff --git a/server/user.c b/server/user.c index 2d038a6ddbf..86f5c810933 100644 --- a/server/user.c +++ b/server/user.c @@ -18,7 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winternl.h" + #include "thread.h" +#include "file.h" #include "user.h" #include "request.h"
@@ -34,6 +40,23 @@ static struct user_handle *freelist; static int nb_handles; static int allocated_handles;
+const session_shm_t *get_session_shm(void) +{ + static const session_shm_t *session; + C_ASSERT( sizeof(*session) <= 1024 * 1024 ); + + if (!session && (session = alloc_shared_object())) + { + SHARED_WRITE_BEGIN( session, session_shm_t ) + { + shared->placeholder = 0; + } + SHARED_WRITE_END; + } + + return session; +} + static struct user_handle *handle_to_entry( user_handle_t handle ) { unsigned short generation; diff --git a/server/user.h b/server/user.h index ce463b9395d..c77bc030fad 100644 --- a/server/user.h +++ b/server/user.h @@ -99,6 +99,7 @@ struct desktop
/* user handles functions */
+extern const session_shm_t *get_session_shm(void); extern user_handle_t alloc_user_handle( void *ptr, enum user_object type ); extern void *get_user_object( user_handle_t handle, enum user_object type ); extern void *get_user_object_handle( user_handle_t *handle, enum user_object type ); diff --git a/server/winstation.c b/server/winstation.c index b3746090ccf..19eab070d4d 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -816,7 +816,8 @@ DECL_HANDLER(get_thread_desktop) if (!(desktop = get_thread_desktop( thread, 0 ))) clear_error(); else { - if (desktop->shared) reply->locator = get_shared_object_locator( desktop->shared ); + reply->session_locator = get_shared_object_locator( get_session_shm() ); + if (desktop->shared) reply->desktop_locator = get_shared_object_locator( desktop->shared ); release_object( desktop ); }
@@ -862,7 +863,8 @@ DECL_HANDLER(set_thread_desktop) if (old_desktop) remove_desktop_thread( old_desktop, current ); add_desktop_thread( new_desktop, current ); } - reply->locator = get_shared_object_locator( new_desktop->shared ); + reply->session_locator = get_shared_object_locator( get_session_shm() ); + reply->desktop_locator = get_shared_object_locator( new_desktop->shared ); }
if (!current->process->desktop)