From b21a3240705fdaf9f70a0eb1d2ff4736efcd35c9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 4 Feb 2016 21:08:02 +0900 Subject: [PATCH] server: Use the link_name operation to create named objects. Signed-off-by: Alexandre Julliard --- dlls/ntdll/tests/om.c | 1 - server/completion.c | 4 +-- server/device.c | 4 +-- server/directory.c | 32 ++++++++++------- server/event.c | 8 ++--- server/mailslot.c | 36 +++++++++++-------- server/mapping.c | 4 +-- server/mutex.c | 4 +-- server/named_pipe.c | 33 ++++++++++------- server/object.c | 84 +++++++++++++++++++++---------------------- server/object.h | 18 ++++++++-- server/process.c | 4 +-- server/semaphore.c | 4 +-- server/symlink.c | 4 +-- server/timer.c | 4 +-- server/winstation.c | 36 ++++++++++++------- 16 files changed, 161 insertions(+), 119 deletions(-) diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c index 1884e3fa415..3d0487c2f3f 100644 --- a/dlls/ntdll/tests/om.c +++ b/dlls/ntdll/tests/om.c @@ -1389,7 +1389,6 @@ static void test_query_object(void) expected_len = sizeof(UNICODE_STRING) + str->Length + sizeof(WCHAR); ok( len == expected_len || broken(len == expected_len - sizeof(WCHAR)), /* NT4 */ "unexpected len %u\n", len ); - todo_wine ok( len > sizeof(UNICODE_STRING) + sizeof("\\test_mailslot") * sizeof(WCHAR), "name too short %s\n", wine_dbgstr_w(str->Buffer) ); trace( "got %s len %u\n", wine_dbgstr_w(str->Buffer), len ); diff --git a/server/completion.c b/server/completion.c index 072bc0a16a6..759c6e2f5d5 100644 --- a/server/completion.c +++ b/server/completion.c @@ -72,8 +72,8 @@ static const struct object_ops completion_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ completion_destroy /* destroy */ diff --git a/server/device.c b/server/device.c index c6e95b1a10c..a8f6f5d97b6 100644 --- a/server/device.c +++ b/server/device.c @@ -155,8 +155,8 @@ static const struct object_ops device_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ device_open_file, /* open_file */ no_close_handle, /* close_handle */ device_destroy /* destroy */ diff --git a/server/directory.c b/server/directory.c index 56c5bf102a7..45683b9aa6a 100644 --- a/server/directory.c +++ b/server/directory.c @@ -64,8 +64,8 @@ static const struct object_ops object_type_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ no_destroy /* destroy */ @@ -99,8 +99,8 @@ static const struct object_ops directory_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ directory_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ directory_destroy /* destroy */ @@ -177,6 +177,20 @@ static struct object *directory_lookup_name( struct object *obj, struct unicode_ return NULL; } +int directory_link_name( struct object *obj, struct object_name *name, struct object *parent ) +{ + struct directory *dir = (struct directory *)parent; + + if (parent->ops != &directory_ops) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return 0; + } + namespace_add( dir->entries, name ); + name->parent = grab_object( parent ); + return 1; +} + static void directory_destroy( struct object *obj ) { struct directory *dir = (struct directory *)obj; @@ -309,15 +323,7 @@ void *create_named_object_dir( struct directory *root, const struct unicode_str return obj; } - /* ATM we can't insert objects into anything else but directories */ - if (obj->ops != &directory_ops) - set_error( STATUS_OBJECT_TYPE_MISMATCH ); - else - { - struct directory *dir = (struct directory *)obj; - if ((new_obj = create_object( dir->entries, ops, &new_name, &dir->obj ))) - clear_error(); - } + if ((new_obj = create_object( obj, ops, &new_name ))) clear_error(); release_object( obj ); return new_obj; diff --git a/server/event.c b/server/event.c index cc4ef4fb343..c9a0ebbe319 100644 --- a/server/event.c +++ b/server/event.c @@ -65,8 +65,8 @@ static const struct object_ops event_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ no_destroy /* destroy */ @@ -98,8 +98,8 @@ static const struct object_ops keyed_event_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ no_destroy /* destroy */ diff --git a/server/mailslot.c b/server/mailslot.c index 9f180833705..a0fa6e27015 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -66,6 +66,7 @@ struct mailslot static void mailslot_dump( struct object*, int ); static struct fd *mailslot_get_fd( struct object * ); static unsigned int mailslot_map_access( struct object *obj, unsigned int access ); +static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent ); static struct object *mailslot_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static void mailslot_destroy( struct object * ); @@ -85,8 +86,8 @@ static const struct object_ops mailslot_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + mailslot_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ mailslot_open_file, /* open_file */ fd_close_handle, /* close_handle */ mailslot_destroy /* destroy */ @@ -196,8 +197,8 @@ static const struct object_ops mailslot_device_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ mailslot_device_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ mailslot_device_open_file, /* open_file */ fd_close_handle, /* close_handle */ mailslot_device_destroy /* destroy */ @@ -260,6 +261,20 @@ static unsigned int mailslot_map_access( struct object *obj, unsigned int access return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL); } +static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent ) +{ + struct mailslot_device *dev = (struct mailslot_device *)parent; + + if (parent->ops != &mailslot_device_ops) + { + set_error( STATUS_OBJECT_NAME_INVALID ); + return 0; + } + namespace_add( dev->mailslots, name ); + name->parent = grab_object( parent ); + return 1; +} + static struct object *mailslot_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { @@ -405,7 +420,6 @@ static struct mailslot *create_mailslot( struct directory *root, { struct object *obj; struct unicode_str new_name; - struct mailslot_device *dev; struct mailslot *mailslot; int fds[2]; @@ -434,16 +448,8 @@ static struct mailslot *create_mailslot( struct directory *root, return NULL; } - if (obj->ops != &mailslot_device_ops) - { - set_error( STATUS_OBJECT_NAME_INVALID ); - release_object( obj ); - return NULL; - } - - dev = (struct mailslot_device *)obj; - mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL ); - release_object( dev ); + mailslot = create_object( obj, &mailslot_ops, &new_name ); + release_object( obj ); init: if (!mailslot) return NULL; diff --git a/server/mapping.c b/server/mapping.c index 9504996ed9a..4384cecd0a9 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -91,8 +91,8 @@ static const struct object_ops mapping_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ fd_close_handle, /* close_handle */ mapping_destroy /* destroy */ diff --git a/server/mutex.c b/server/mutex.c index 08a24774184..ca0da593f17 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -68,8 +68,8 @@ static const struct object_ops mutex_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ mutex_destroy /* destroy */ diff --git a/server/named_pipe.c b/server/named_pipe.c index 0bd6064ed8f..1e4169d9925 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -112,6 +112,7 @@ struct named_pipe_device static void named_pipe_dump( struct object *obj, int verbose ); static unsigned int named_pipe_map_access( struct object *obj, unsigned int access ); +static int named_pipe_link_name( struct object *obj, struct object_name *name, struct object *parent ); static struct object *named_pipe_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ); static void named_pipe_destroy( struct object *obj ); @@ -131,8 +132,8 @@ static const struct object_ops named_pipe_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + named_pipe_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ named_pipe_open_file, /* open_file */ no_close_handle, /* close_handle */ named_pipe_destroy /* destroy */ @@ -254,8 +255,8 @@ static const struct object_ops named_pipe_device_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ named_pipe_device_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ named_pipe_device_open_file, /* open_file */ fd_close_handle, /* close_handle */ named_pipe_device_destroy /* destroy */ @@ -701,14 +702,8 @@ static struct named_pipe *create_named_pipe( struct directory *root, const struc return (struct named_pipe *)obj; } - if (obj->ops != &named_pipe_device_ops) - set_error( STATUS_OBJECT_NAME_INVALID ); - else - { - struct named_pipe_device *dev = (struct named_pipe_device *)obj; - if ((pipe = create_object( dev->pipes, &named_pipe_ops, &new_name, NULL ))) - clear_error(); - } + if ((pipe = create_object( obj, &named_pipe_ops, &new_name ))) + clear_error(); release_object( obj ); return pipe; @@ -786,6 +781,20 @@ static struct pipe_server *find_available_server( struct named_pipe *pipe ) return NULL; } +static int named_pipe_link_name( struct object *obj, struct object_name *name, struct object *parent ) +{ + struct named_pipe_device *dev = (struct named_pipe_device *)parent; + + if (parent->ops != &named_pipe_device_ops) + { + set_error( STATUS_OBJECT_NAME_INVALID ); + return 0; + } + namespace_add( dev->pipes, name ); + name->parent = grab_object( parent ); + return 1; +} + static struct object *named_pipe_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { diff --git a/server/object.c b/server/object.c index 4f23e0ce540..c8098ca0af5 100644 --- a/server/object.c +++ b/server/object.c @@ -40,15 +40,6 @@ #include "security.h" -struct object_name -{ - struct list entry; /* entry in the hash list */ - struct object *obj; /* object owning this name */ - struct object *parent; /* parent object */ - data_size_t len; /* name length in bytes */ - WCHAR name[1]; -}; - struct namespace { unsigned int hash_size; /* size of hash table */ @@ -130,6 +121,13 @@ static int get_name_hash( const struct namespace *namespace, const WCHAR *name, return hash % namespace->hash_size; } +void namespace_add( struct namespace *namespace, struct object_name *ptr ) +{ + int hash = get_name_hash( namespace, ptr->name, ptr->len ); + + list_add_head( &namespace->names[hash], &ptr->entry ); +} + /* allocate a name for an object */ static struct object_name *alloc_name( const struct unicode_str *name ) { @@ -144,26 +142,6 @@ static struct object_name *alloc_name( const struct unicode_str *name ) return ptr; } -/* free the name of an object */ -static void free_name( struct object *obj ) -{ - struct object_name *ptr = obj->name; - list_remove( &ptr->entry ); - if (ptr->parent) release_object( ptr->parent ); - free( ptr ); -} - -/* set the name of an existing object */ -static void set_object_name( struct namespace *namespace, - struct object *obj, struct object_name *ptr ) -{ - int hash = get_name_hash( namespace, ptr->name, ptr->len ); - - list_add_head( &namespace->names[hash], &ptr->entry ); - ptr->obj = obj; - obj->name = ptr; -} - /* get the name of an existing object */ const WCHAR *get_object_name( struct object *obj, data_size_t *len ) { @@ -222,8 +200,18 @@ void *alloc_object( const struct object_ops *ops ) return NULL; } -void *create_object( struct namespace *namespace, const struct object_ops *ops, - const struct unicode_str *name, struct object *parent ) +/* free an object once it has been destroyed */ +void free_object( struct object *obj ) +{ + free( obj->sd ); +#ifdef DEBUG_OBJECTS + list_remove( &obj->obj_list ); + memset( obj, 0xaa, obj->ops->size ); +#endif + free( obj ); +} + +void *create_object( struct object *parent, const struct object_ops *ops, const struct unicode_str *name ) { struct object *obj; struct object_name *name_ptr; @@ -231,15 +219,20 @@ void *create_object( struct namespace *namespace, const struct object_ops *ops, if (!(name_ptr = alloc_name( name ))) return NULL; if ((obj = alloc_object( ops ))) { - set_object_name( namespace, obj, name_ptr ); - if (parent) name_ptr->parent = grab_object( parent ); + if (!obj->ops->link_name( obj, name_ptr, parent )) + { + free_object( obj ); + return NULL; + } + name_ptr->obj = obj; + obj->name = name_ptr; } else free( name_ptr ); return obj; } -void *create_named_object( struct namespace *namespace, const struct object_ops *ops, +void *create_named_object( struct object *parent, struct namespace *namespace, const struct object_ops *ops, const struct unicode_str *name, unsigned int attributes ) { struct object *obj; @@ -265,7 +258,7 @@ void *create_named_object( struct namespace *namespace, const struct object_ops } return obj; } - if ((obj = create_object( namespace, ops, name, NULL ))) clear_error(); + if ((obj = create_object( parent, ops, name ))) clear_error(); return obj; } @@ -292,8 +285,13 @@ void dump_object_name( struct object *obj ) /* unlink a named object from its namespace, without freeing the object itself */ void unlink_named_object( struct object *obj ) { - if (obj->name) free_name( obj ); + struct object_name *name_ptr = obj->name; + + if (!name_ptr) return; obj->name = NULL; + obj->ops->unlink_name( obj, name_ptr ); + if (name_ptr->parent) release_object( name_ptr->parent ); + free( name_ptr ); } /* mark an object as being stored statically, i.e. only released at shutdown */ @@ -324,14 +322,9 @@ void release_object( void *ptr ) assert( !obj->handle_count ); /* if the refcount is 0, nobody can be in the wait queue */ assert( list_empty( &obj->wait_queue )); + unlink_named_object( obj ); obj->ops->destroy( obj ); - if (obj->name) free_name( obj ); - free( obj->sd ); -#ifdef DEBUG_OBJECTS - list_remove( &obj->obj_list ); - memset( obj, 0xaa, obj->ops->size ); -#endif - free( obj ); + free_object( obj ); } } @@ -557,6 +550,11 @@ int no_link_name( struct object *obj, struct object_name *name, struct object *p return 0; } +void default_unlink_name( struct object *obj, struct object_name *name ) +{ + list_remove( &name->entry ); +} + struct object *no_open_file( struct object *obj, unsigned int access, unsigned int sharing, unsigned int options ) { diff --git a/server/object.h b/server/object.h index 3d6ba8ab33f..c4bc40b8122 100644 --- a/server/object.h +++ b/server/object.h @@ -109,6 +109,15 @@ struct object #endif }; +struct object_name +{ + struct list entry; /* entry in the hash list */ + struct object *obj; /* object owning this name */ + struct object *parent; /* parent object */ + data_size_t len; /* name length in bytes */ + WCHAR name[1]; +}; + struct wait_queue_entry { struct list entry; @@ -119,12 +128,13 @@ struct wait_queue_entry extern void *mem_alloc( size_t size ); /* malloc wrapper */ extern void *memdup( const void *data, size_t len ); extern void *alloc_object( const struct object_ops *ops ); +extern void namespace_add( struct namespace *namespace, struct object_name *ptr ); extern const WCHAR *get_object_name( struct object *obj, data_size_t *len ); extern WCHAR *get_object_full_name( struct object *obj, data_size_t *ret_len ); extern void dump_object_name( struct object *obj ); -extern void *create_object( struct namespace *namespace, const struct object_ops *ops, - const struct unicode_str *name, struct object *parent ); -extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops, +extern void *create_object( struct object *parent, const struct object_ops *ops, + const struct unicode_str *name ); +extern void *create_named_object( struct object *parent, struct namespace *namespace, const struct object_ops *ops, const struct unicode_str *name, unsigned int attributes ); extern void unlink_named_object( struct object *obj ); extern void make_object_static( struct object *obj ); @@ -148,6 +158,7 @@ extern int set_sd_defaults_from_token( struct object *obj, const struct security unsigned int set_info, struct token *token ); extern struct object *no_lookup_name( struct object *obj, struct unicode_str *name, unsigned int attributes ); extern int no_link_name( struct object *obj, struct object_name *name, struct object *parent ); +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 int no_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); @@ -222,6 +233,7 @@ extern void *create_named_object_dir( struct directory *root, const struct unico extern void *open_object_dir( struct directory *root, const struct unicode_str *name, unsigned int attr, const struct object_ops *ops ); extern struct object_type *get_object_type( const struct unicode_str *name ); +extern int directory_link_name( struct object *obj, struct object_name *name, struct object *parent ); extern void init_directories(void); /* symbolic link functions */ diff --git a/server/process.c b/server/process.c index d51c8847b94..c9bcabb3a3d 100644 --- a/server/process.c +++ b/server/process.c @@ -174,8 +174,8 @@ static const struct object_ops job_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ job_close_handle, /* close_handle */ job_destroy /* destroy */ diff --git a/server/semaphore.c b/server/semaphore.c index 515f49e4c06..c77bd581652 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -65,8 +65,8 @@ static const struct object_ops semaphore_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ no_destroy /* destroy */ diff --git a/server/symlink.c b/server/symlink.c index 09443b82607..bd09d34a8c4 100644 --- a/server/symlink.c +++ b/server/symlink.c @@ -67,8 +67,8 @@ static const struct object_ops symlink_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ symlink_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ symlink_destroy /* destroy */ diff --git a/server/timer.c b/server/timer.c index ef9aa08760d..0d81d90f362 100644 --- a/server/timer.c +++ b/server/timer.c @@ -72,8 +72,8 @@ static const struct object_ops timer_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ no_close_handle, /* close_handle */ timer_destroy /* destroy */ diff --git a/server/winstation.c b/server/winstation.c index 6e1c7547521..9dc348dc2bc 100644 --- a/server/winstation.c +++ b/server/winstation.c @@ -50,6 +50,7 @@ static void winstation_destroy( struct object *obj ); static unsigned int winstation_map_access( struct object *obj, unsigned int access ); static void desktop_dump( struct object *obj, int verbose ); static struct object_type *desktop_get_type( struct object *obj ); +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 ); static unsigned int desktop_map_access( struct object *obj, unsigned int access ); @@ -69,8 +70,8 @@ static const struct object_ops winstation_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + directory_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ winstation_close_handle, /* close_handle */ winstation_destroy /* destroy */ @@ -92,8 +93,8 @@ static const struct object_ops desktop_ops = default_get_sd, /* get_sd */ default_set_sd, /* set_sd */ no_lookup_name, /* lookup_name */ - no_link_name, /* link_name */ - NULL, /* unlink_name */ + desktop_link_name, /* link_name */ + default_unlink_name, /* unlink_name */ no_open_file, /* open_file */ desktop_close_handle, /* close_handle */ desktop_destroy /* destroy */ @@ -194,13 +195,7 @@ static struct desktop *create_desktop( const struct unicode_str *name, unsigned { struct desktop *desktop; - if (memchrW( name->str, '\\', name->len / sizeof(WCHAR) )) /* no backslash allowed in name */ - { - set_error( STATUS_OBJECT_PATH_SYNTAX_BAD ); - return NULL; - } - - if ((desktop = create_named_object( winstation->desktop_names, &desktop_ops, name, attr ))) + if ((desktop = create_named_object( &winstation->obj, winstation->desktop_names, &desktop_ops, name, attr ))) { if (get_error() != STATUS_OBJECT_NAME_EXISTS) { @@ -238,6 +233,24 @@ static struct object_type *desktop_get_type( struct object *obj ) return get_object_type( &str ); } +static int desktop_link_name( struct object *obj, struct object_name *name, struct object *parent ) +{ + struct winstation *winstation = (struct winstation *)parent; + + if (parent->ops != &winstation_ops) + { + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + return 0; + } + if (memchrW( name->name, '\\', name->len / sizeof(WCHAR) )) /* no backslash allowed in name */ + { + set_error( STATUS_OBJECT_PATH_SYNTAX_BAD ); + return 0; + } + namespace_add( winstation->desktop_names, name ); + return 1; +} + static int desktop_close_handle( struct object *obj, struct process *process, obj_handle_t handle ) { struct thread *thread; @@ -259,7 +272,6 @@ static void desktop_destroy( struct object *obj ) if (desktop->global_hooks) release_object( desktop->global_hooks ); if (desktop->close_timeout) remove_timeout_user( desktop->close_timeout ); list_remove( &desktop->entry ); - unlink_named_object( obj ); release_object( desktop->winstation ); }