From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/winstation.c | 86 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/winstation.c b/dlls/win32u/winstation.c index b187b246941..7537ce944d5 100644 --- a/dlls/win32u/winstation.c +++ b/dlls/win32u/winstation.c @@ -22,9 +22,12 @@ #pragma makedep unix #endif
+#include <stdarg.h> +#include <stddef.h> +#include <pthread.h> + #include "ntstatus.h" #define WIN32_NO_STATUS -#include <stdarg.h> #include "windef.h" #include "winbase.h" #include "ntuser.h" @@ -40,6 +43,85 @@ WINE_DECLARE_DEBUG_CHANNEL(win);
#define DESKTOP_ALL_ACCESS 0x01ff
+static pthread_mutex_t session_lock = PTHREAD_MUTEX_INITIALIZER; +static struct shared_session *shared_session; + +struct shared_session +{ + LONG ref; + const session_shm_t *shared; +}; + +static struct shared_session *shared_session_acquire( struct shared_session *session ) +{ + InterlockedIncrement( &session->ref ); + return session; +} + +static void shared_session_release( struct shared_session *session ) +{ + if (!InterlockedDecrement( &session->ref )) + { + NtUnmapViewOfSection( GetCurrentProcess(), (void *)session->shared ); + free( session ); + } +} + +static struct shared_session *get_shared_session( BOOL force ) +{ + struct shared_session *session; + + pthread_mutex_lock( &session_lock ); + + if (!shared_session) force = TRUE; + if (force && (session = calloc( 1, sizeof(*session) ))) + { + static const WCHAR nameW[] = + { + '\','K','e','r','n','e','l','O','b','j','e','c','t','s','\', + '_','_','w','i','n','e','_','s','e','s','s','i','o','n',0 + }; + UNICODE_STRING name = RTL_CONSTANT_STRING( nameW ); + OBJECT_ATTRIBUTES attr; + unsigned int status; + HANDLE handle; + + session->ref = 1; + + InitializeObjectAttributes( &attr, &name, 0, NULL, NULL ); + if (!(status = NtOpenSection( &handle, SECTION_MAP_READ | SECTION_QUERY, &attr ))) + { + SECTION_BASIC_INFORMATION info; + + if (!(status = NtQuerySection( handle, SectionBasicInformation, &info, sizeof(info), NULL ))) + { + SIZE_T size = info.Size.QuadPart; + status = NtMapViewOfSection( handle, GetCurrentProcess(), (void **)&session->shared, + 0, 0, NULL, &size, ViewUnmap, 0, PAGE_READONLY ); + } + + NtClose( handle ); + } + + if (status) + { + ERR( "Failed to map session mapping, status %#x\n", status ); + free( session ); + } + else + { + if (shared_session) shared_session_release( shared_session ); + shared_session = session; + } + } + + session = shared_session_acquire( shared_session ); + + pthread_mutex_unlock( &session_lock ); + + return session; +} + BOOL is_virtual_desktop(void) { HANDLE desktop = NtUserGetThreadDesktop( GetCurrentThreadId() ); @@ -622,6 +704,8 @@ void winstation_init(void)
static const WCHAR winsta0[] = {'W','i','n','S','t','a','0',0};
+ shared_session = get_shared_session( FALSE ); + if (params->Desktop.Length) { buffer = malloc( params->Desktop.Length + sizeof(WCHAR) );