From: Rémi Bernon rbernon@codeweavers.com
Based on a patch by Huw Davies huw@codeweavers.com. --- server/file.h | 1 + server/handle.c | 5 ++++- server/mapping.c | 17 +++++++++++++++++ server/protocol.def | 6 ++++++ server/user.h | 2 ++ server/winstation.c | 40 +++++++++++++++++++++++++++++++++++++++- 6 files changed, 69 insertions(+), 2 deletions(-)
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/handle.c b/server/handle.c index 0595fdb403b..10803c0e0ea 100644 --- a/server/handle.c +++ b/server/handle.c @@ -620,6 +620,7 @@ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned const struct object_ops *ops, const struct unicode_str *name, unsigned int attributes ) { + static const WCHAR object_mappingW[] = {'_','_','w','i','n','e','_','m','a','p','p','i','n','g'}; obj_handle_t handle = 0; struct object *obj, *root = NULL;
@@ -631,7 +632,9 @@ obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned
if (parent) { - if (name->len) + if (name->len == sizeof(object_mappingW) && !memcmp( name->str, object_mappingW, name->len )) + root = get_handle_obj( process, parent, 0, NULL ); + else if (name->len) root = get_directory_obj( process, parent ); else /* opening the object itself can work for non-directories too */ root = get_handle_obj( process, parent, 0, NULL ); diff --git a/server/mapping.c b/server/mapping.c index f754078acf7..242f12ce1a5 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 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_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..e7ab1a63b83 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 @@ -50,6 +51,8 @@ static struct object *winstation_lookup_name( struct object *obj, struct unicode unsigned int attr, struct object *root ); static void winstation_destroy( struct object *obj ); static void desktop_dump( struct object *obj, int verbose ); +static struct object *desktop_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr, struct object *root ); static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ); static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void desktop_destroy( struct object *obj ); @@ -123,7 +126,7 @@ static const struct object_ops desktop_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ default_get_full_name, /* get_full_name */ - no_lookup_name, /* lookup_name */ + desktop_lookup_name, /* lookup_name */ desktop_link_name, /* link_name */ default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ @@ -240,6 +243,17 @@ 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 ))) + memset( (void *)desktop->shared, 0, sizeof(*desktop->shared) ); + else + { + release_object( desktop ); + return NULL; + } } else { @@ -258,6 +272,28 @@ static void desktop_dump( struct object *obj, int verbose ) desktop->flags, desktop->winstation, desktop->top_window, desktop->global_hooks ); }
+static struct object *desktop_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr, struct object *root ) +{ + static const WCHAR object_mappingW[] = {'_','_','w','i','n','e','_','m','a','p','p','i','n','g'}; + struct desktop *desktop = (struct desktop *)obj; + assert( obj->ops == &desktop_ops ); + + if (!name) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return NULL; + } + + if (name->len == sizeof(object_mappingW) && !memcmp( name->str, object_mappingW, name->len )) + { + name->len = 0; + return grab_object( desktop->shared_mapping ); + } + + return NULL; +} + static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ) { struct winstation *winstation = (struct winstation *)parent; @@ -298,6 +334,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 */