? server/directory.c ? server/directory.h ? server/om.c ? server/om.h Index: server/Makefile.in =================================================================== RCS file: /home/wine/wine/server/Makefile.in,v retrieving revision 1.55 diff -u -p -r1.55 Makefile.in --- server/Makefile.in 8 Jun 2005 18:44:50 -0000 1.55 +++ server/Makefile.in 18 Sep 2005 18:16:25 -0000 @@ -16,6 +16,7 @@ C_SRCS = \ context_powerpc.c \ context_sparc.c \ debugger.c \ + directory.c \ event.c \ fd.c \ file.c \ @@ -27,6 +28,7 @@ C_SRCS = \ mutex.c \ named_pipe.c \ object.c \ + om.c \ process.c \ ptrace.c \ queue.c \ Index: server/atom.c =================================================================== RCS file: /home/wine/wine/server/atom.c,v retrieving revision 1.25 diff -u -p -r1.25 atom.c --- server/atom.c 11 Jul 2005 10:55:53 -0000 1.25 +++ server/atom.c 18 Sep 2005 18:16:26 -0000 @@ -70,6 +70,7 @@ static void atom_table_destroy( struct o static const struct object_ops atom_table_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct atom_table), /* size */ atom_table_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/change.c =================================================================== RCS file: /home/wine/wine/server/change.c,v retrieving revision 1.25 diff -u -p -r1.25 change.c --- server/change.c 8 Aug 2005 15:11:03 -0000 1.25 +++ server/change.c 18 Sep 2005 18:16:26 -0000 @@ -65,6 +65,7 @@ static void change_destroy( struct objec static const struct object_ops change_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct change), /* size */ change_dump, /* dump */ add_queue, /* add_queue */ Index: server/clipboard.c =================================================================== RCS file: /home/wine/wine/server/clipboard.c,v retrieving revision 1.7 diff -u -p -r1.7 clipboard.c --- server/clipboard.c 11 Jul 2005 10:55:53 -0000 1.7 +++ server/clipboard.c 18 Sep 2005 18:16:26 -0000 @@ -47,6 +47,7 @@ static void clipboard_dump( struct objec static const struct object_ops clipboard_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct clipboard), /* size */ clipboard_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/console.c =================================================================== RCS file: /home/wine/wine/server/console.c,v retrieving revision 1.59 diff -u -p -r1.59 console.c --- server/console.c 12 Jul 2005 20:27:09 -0000 1.59 +++ server/console.c 18 Sep 2005 18:16:26 -0000 @@ -40,6 +40,7 @@ static void console_input_destroy( struc static const struct object_ops console_input_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct console_input), /* size */ console_input_dump, /* dump */ no_add_queue, /* add_queue */ @@ -66,6 +67,7 @@ struct console_input_events static const struct object_ops console_input_events_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct console_input_events), /* size */ console_input_events_dump, /* dump */ add_queue, /* add_queue */ @@ -103,6 +105,7 @@ static void screen_buffer_destroy( struc static const struct object_ops screen_buffer_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct screen_buffer), /* size */ screen_buffer_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/context_i386.c =================================================================== RCS file: /home/wine/wine/server/context_i386.c,v retrieving revision 1.31 Index: server/debugger.c =================================================================== RCS file: /home/wine/wine/server/debugger.c,v retrieving revision 1.58 diff -u -p -r1.58 debugger.c --- server/debugger.c 21 Jun 2005 09:46:15 -0000 1.58 +++ server/debugger.c 18 Sep 2005 18:16:26 -0000 @@ -65,6 +65,7 @@ static void debug_event_destroy( struct static const struct object_ops debug_event_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct debug_event), /* size */ debug_event_dump, /* dump */ add_queue, /* add_queue */ @@ -83,6 +84,7 @@ static void debug_ctx_destroy( struct ob static const struct object_ops debug_ctx_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct debug_ctx), /* size */ debug_ctx_dump, /* dump */ add_queue, /* add_queue */ Index: server/event.c =================================================================== RCS file: /home/wine/wine/server/event.c,v retrieving revision 1.31 diff -u -p -r1.31 event.c --- server/event.c 9 Jun 2005 15:39:52 -0000 1.31 +++ server/event.c 18 Sep 2005 18:16:26 -0000 @@ -45,6 +45,7 @@ static int event_signal( struct object * static const struct object_ops event_ops = { + OB_TYPE_EVENT, /* object type */ sizeof(struct event), /* size */ event_dump, /* dump */ add_queue, /* add_queue */ @@ -63,7 +64,7 @@ struct event *create_event( const WCHAR { struct event *event; - if ((event = create_named_object( sync_namespace, &event_ops, name, len ))) + if ((event = create_named_object( root_directory, &event_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -157,8 +158,8 @@ DECL_HANDLER(create_event) /* open a handle to an event */ DECL_HANDLER(open_event) { - reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(), - &event_ops, req->access, req->inherit ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &event_ops, req->access, req->inherit, TRUE ); } /* do an event operation */ Index: server/fd.c =================================================================== RCS file: /home/wine/wine/server/fd.c,v retrieving revision 1.49 diff -u -p -r1.49 fd.c --- server/fd.c 24 Aug 2005 18:33:51 -0000 1.49 +++ server/fd.c 18 Sep 2005 18:16:27 -0000 @@ -154,6 +154,7 @@ static void fd_destroy( struct object *o static const struct object_ops fd_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct fd), /* size */ fd_dump, /* dump */ no_add_queue, /* add_queue */ @@ -185,6 +186,7 @@ static void device_destroy( struct objec static const struct object_ops device_ops = { + OB_TYPE_DEVICE, /* object type */ sizeof(struct device), /* size */ device_dump, /* dump */ no_add_queue, /* add_queue */ @@ -215,6 +217,7 @@ static void inode_destroy( struct object static const struct object_ops inode_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct inode), /* size */ inode_dump, /* dump */ no_add_queue, /* add_queue */ @@ -247,6 +250,7 @@ static int file_lock_signaled( struct ob static const struct object_ops file_lock_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct file_lock), /* size */ file_lock_dump, /* dump */ add_queue, /* add_queue */ Index: server/file.c =================================================================== RCS file: /home/wine/wine/server/file.c,v retrieving revision 1.100 diff -u -p -r1.100 file.c --- server/file.c 8 Aug 2005 15:11:03 -0000 1.100 +++ server/file.c 18 Sep 2005 18:16:27 -0000 @@ -69,6 +69,7 @@ static int file_get_info( struct fd *fd static const struct object_ops file_ops = { + OB_TYPE_FILE, /* object type */ sizeof(struct file), /* size */ file_dump, /* dump */ default_fd_add_queue, /* add_queue */ Index: server/handle.c =================================================================== RCS file: /home/wine/wine/server/handle.c,v retrieving revision 1.38 diff -u -p -r1.38 handle.c --- server/handle.c 24 Aug 2005 18:33:50 -0000 1.38 +++ server/handle.c 18 Sep 2005 18:16:27 -0000 @@ -99,6 +99,7 @@ static void handle_table_destroy( struct static const struct object_ops handle_table_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct handle_table), /* size */ handle_table_dump, /* dump */ no_add_queue, /* add_queue */ @@ -520,11 +521,12 @@ obj_handle_t duplicate_handle( struct pr } /* open a new handle to an existing object */ -obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len, - const struct object_ops *ops, unsigned int access, int inherit ) +obj_handle_t open_object( const struct directory *root, const WCHAR *name, size_t len, + const struct object_ops *ops, unsigned int access, int inherit, + int case_sensitive ) { obj_handle_t handle = 0; - struct object *obj = find_object( namespace, name, len ); + struct object *obj = find_object( root, name, len, case_sensitive ); if (obj) { if (ops && obj->ops != ops) Index: server/handle.h =================================================================== RCS file: /home/wine/wine/server/handle.h,v retrieving revision 1.17 diff -u -p -r1.17 handle.h --- server/handle.h 24 Aug 2005 18:33:50 -0000 1.17 +++ server/handle.h 18 Sep 2005 18:16:27 -0000 @@ -27,7 +27,7 @@ struct process; struct object_ops; -struct namespace; +struct directory; /* handle functions */ @@ -43,8 +43,9 @@ extern int get_handle_unix_fd( struct pr extern int set_handle_unix_fd( struct process *process, obj_handle_t handle, int fd ); extern obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst, unsigned int access, int inherit, int options ); -extern obj_handle_t open_object( const struct namespace *namespace, const WCHAR *name, size_t len, - const struct object_ops *ops, unsigned int access, int inherit ); +extern obj_handle_t open_object( const struct directory *root, const WCHAR *name, size_t len, + const struct object_ops *ops, unsigned int access, int inherit, + int case_sensitive ); extern obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops ); extern struct handle_table *alloc_handle_table( struct process *process, int count ); extern struct handle_table *copy_handle_table( struct process *process, struct process *parent ); Index: server/hook.c =================================================================== RCS file: /home/wine/wine/server/hook.c,v retrieving revision 1.17 diff -u -p -r1.17 hook.c --- server/hook.c 11 Jul 2005 18:05:50 -0000 1.17 +++ server/hook.c 18 Sep 2005 18:16:27 -0000 @@ -72,6 +72,7 @@ static void hook_table_destroy( struct o static const struct object_ops hook_table_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct hook_table), /* size */ hook_table_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/mailslot.c =================================================================== RCS file: /home/wine/wine/server/mailslot.c,v retrieving revision 1.9 diff -u -p -r1.9 mailslot.c --- server/mailslot.c 14 Jul 2005 12:18:05 -0000 1.9 +++ server/mailslot.c 18 Sep 2005 18:16:27 -0000 @@ -66,6 +66,7 @@ static void mailslot_destroy( struct obj static const struct object_ops mailslot_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct mailslot), /* size */ mailslot_dump, /* dump */ default_fd_add_queue, /* add_queue */ @@ -106,6 +107,7 @@ static void mail_writer_destroy( struct static const struct object_ops mail_writer_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct mail_writer), /* size */ mail_writer_dump, /* dump */ no_add_queue, /* add_queue */ @@ -217,7 +219,7 @@ static struct mailslot *create_mailslot( { struct mailslot *mailslot; int fds[2]; - static const WCHAR slot[] = {'m','a','i','l','s','l','o','t','\\',0}; + static const WCHAR slot[] = {'M','A','I','L','S','L','O','T','\\',0}; if (( len <= strlenW( slot )) || strncmpiW( slot, name, strlenW( slot ) )) { @@ -225,7 +227,7 @@ static struct mailslot *create_mailslot( return NULL; } - mailslot = create_named_object( sync_namespace, &mailslot_ops, name, len ); + mailslot = create_named_object( root_directory, &mailslot_ops, name, len ); if (!mailslot) return NULL; @@ -262,7 +264,7 @@ static struct mailslot *open_mailslot( c { struct object *obj; - obj = find_object( sync_namespace, name, len ); + obj = find_object( root_directory, name, len, TRUE ); if (obj) { if (obj->ops == &mailslot_ops) Index: server/main.c =================================================================== RCS file: /home/wine/wine/server/main.c,v retrieving revision 1.34 diff -u -p -r1.34 main.c --- server/main.c 25 May 2005 18:41:09 -0000 1.34 +++ server/main.c 18 Sep 2005 18:16:27 -0000 @@ -41,7 +41,7 @@ int foreground = 0; const char *server_argv0; /* name space for synchronization objects */ -struct namespace *sync_namespace; +struct directory *root_directory; /* parse-line args */ /* FIXME: should probably use getopt, and add a (more complete?) help option */ @@ -128,9 +128,9 @@ int main( int argc, char *argv[] ) signal( SIGTERM, sigterm_handler ); signal( SIGABRT, sigterm_handler ); + init_namespace(); sock_init(); open_master_socket(); - sync_namespace = create_namespace( 37, TRUE ); setvbuf( stderr, NULL, _IOLBF, 0 ); if (debug_level) fprintf( stderr, "wineserver: starting (pid=%ld)\n", (long) getpid() ); Index: server/mapping.c =================================================================== RCS file: /home/wine/wine/server/mapping.c,v retrieving revision 1.56 diff -u -p -r1.56 mapping.c --- server/mapping.c 15 Aug 2005 14:50:06 -0000 1.56 +++ server/mapping.c 18 Sep 2005 18:16:27 -0000 @@ -54,6 +54,7 @@ static void mapping_destroy( struct obje static const struct object_ops mapping_ops = { + OB_TYPE_SECTION, /* object type */ sizeof(struct mapping), /* size */ mapping_dump, /* dump */ no_add_queue, /* add_queue */ @@ -277,7 +278,7 @@ static struct object *create_mapping( fi if (!page_mask) init_page_size(); - if (!(mapping = create_named_object( sync_namespace, &mapping_ops, name, len ))) + if (!(mapping = create_named_object( root_directory, &mapping_ops, name, len ))) return NULL; if (get_error() == STATUS_OBJECT_NAME_COLLISION) return &mapping->obj; /* Nothing else to do */ @@ -387,8 +388,8 @@ DECL_HANDLER(create_mapping) /* open a handle to a mapping */ DECL_HANDLER(open_mapping) { - reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(), - &mapping_ops, req->access, req->inherit ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &mapping_ops, req->access, req->inherit, TRUE ); } /* get a mapping information */ Index: server/mutex.c =================================================================== RCS file: /home/wine/wine/server/mutex.c,v retrieving revision 1.29 diff -u -p -r1.29 mutex.c --- server/mutex.c 9 Jun 2005 15:39:52 -0000 1.29 +++ server/mutex.c 18 Sep 2005 18:16:27 -0000 @@ -48,6 +48,7 @@ static int mutex_signal( struct object * static const struct object_ops mutex_ops = { + OB_TYPE_MUTANT, /* object type */ sizeof(struct mutex), /* size */ mutex_dump, /* dump */ add_queue, /* add_queue */ @@ -65,7 +66,7 @@ static struct mutex *create_mutex( const { struct mutex *mutex; - if ((mutex = create_named_object( sync_namespace, &mutex_ops, name, len ))) + if ((mutex = create_named_object( root_directory, &mutex_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -181,8 +182,8 @@ DECL_HANDLER(create_mutex) /* open a handle to a mutex */ DECL_HANDLER(open_mutex) { - reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(), - &mutex_ops, req->access, req->inherit ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &mutex_ops, req->access, req->inherit, TRUE ); } /* release a mutex */ Index: server/named_pipe.c =================================================================== RCS file: /home/wine/wine/server/named_pipe.c,v retrieving revision 1.47 diff -u -p -r1.47 named_pipe.c --- server/named_pipe.c 6 Sep 2005 14:10:53 -0000 1.47 +++ server/named_pipe.c 18 Sep 2005 18:16:27 -0000 @@ -49,6 +49,7 @@ #include "handle.h" #include "thread.h" #include "request.h" +#include "unicode.h" enum pipe_state { @@ -102,6 +103,7 @@ static void named_pipe_destroy( struct o static const struct object_ops named_pipe_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct named_pipe), /* size */ named_pipe_dump, /* dump */ no_add_queue, /* add_queue */ @@ -123,6 +125,7 @@ static int pipe_server_get_info( struct static const struct object_ops pipe_server_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct pipe_server), /* size */ pipe_server_dump, /* dump */ default_fd_add_queue, /* add_queue */ @@ -154,6 +157,7 @@ static int pipe_client_get_info( struct static const struct object_ops pipe_client_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct pipe_client), /* size */ pipe_client_dump, /* dump */ default_fd_add_queue, /* add_queue */ @@ -444,7 +448,7 @@ static struct named_pipe *create_named_p { struct named_pipe *pipe; - pipe = create_named_object( sync_namespace, &named_pipe_ops, name, len ); + pipe = create_named_object( root_directory, &named_pipe_ops, name, len ); if (pipe) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) @@ -462,7 +466,7 @@ static struct named_pipe *open_named_pip { struct object *obj; - if ((obj = find_object( sync_namespace, name, len ))) + if ((obj = find_object( root_directory, name, len, FALSE ))) { if (obj->ops == &named_pipe_ops) return (struct named_pipe *)obj; release_object( obj ); Index: server/object.c =================================================================== RCS file: /home/wine/wine/server/object.c,v retrieving revision 1.33 diff -u -p -r1.33 object.c --- server/object.c 9 Jun 2005 15:39:52 -0000 1.33 +++ server/object.c 18 Sep 2005 18:16:27 -0000 @@ -32,22 +32,7 @@ #include "thread.h" #include "unicode.h" - -struct object_name -{ - struct list entry; /* entry in the hash list */ - struct object *obj; - size_t len; - WCHAR name[1]; -}; - -struct namespace -{ - unsigned int hash_size; /* size of hash table */ - int case_sensitive; /* are names case sensitive? */ - struct list names[1]; /* array of hash entry lists */ -}; - +#define IS_PERMANENT(o) ((o)->flags & OBJ_PERMANENT) #ifdef DEBUG_OBJECTS static struct list object_list = LIST_INIT(object_list); @@ -88,17 +73,8 @@ void *memdup( const void *data, size_t l /*****************************************************************/ -static int get_name_hash( const struct namespace *namespace, const WCHAR *name, size_t len ) -{ - WCHAR hash = 0; - len /= sizeof(WCHAR); - if (namespace->case_sensitive) while (len--) hash ^= *name++; - else while (len--) hash ^= tolowerW(*name++); - return hash % namespace->hash_size; -} - /* allocate a name for an object */ -static struct object_name *alloc_name( const WCHAR *name, size_t len ) +struct object_name *alloc_name( const WCHAR *name, size_t len ) { struct object_name *ptr; @@ -115,20 +91,10 @@ static void free_name( struct object *ob { 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, size_t *len ) { @@ -145,6 +111,8 @@ void *alloc_object( const struct object_ if (obj) { obj->refcount = 1; + obj->handlecount = 0; + obj->flags = 0; obj->ops = ops; obj->name = NULL; list_init( &obj->wait_queue ); @@ -156,32 +124,10 @@ void *alloc_object( const struct object_ return NULL; } -void *create_named_object( struct namespace *namespace, const struct object_ops *ops, +void *create_named_object( struct directory *root, const struct object_ops *ops, const WCHAR *name, size_t len ) { - struct object *obj; - struct object_name *name_ptr; - - if (!name || !len) return alloc_object( ops ); - - if ((obj = find_object( namespace, name, len ))) - { - if (obj->ops == ops) - { - set_error( STATUS_OBJECT_NAME_COLLISION ); - return obj; - } - set_error( STATUS_OBJECT_TYPE_MISMATCH ); - return NULL; - } - if (!(name_ptr = alloc_name( name, len ))) return NULL; - if ((obj = alloc_object( ops ))) - { - set_object_name( namespace, obj, name_ptr ); - clear_error(); - } - else free( name_ptr ); - return obj; + return create_named_object_ex( root, ops, name, len, 0, 0); } /* dump the name of an object to stderr */ @@ -224,49 +170,22 @@ void release_object( void *ptr ) } } -/* find an object by its name; the refcount is incremented */ -struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len ) +/* find an object by its name in a root directory; the refcount is incremented + * name is fully qualified name */ +struct object * find_object( const struct directory *root, const WCHAR *name, size_t len, + int case_sensitive ) { - const struct list *list, *p; - - if (!name || !len) return NULL; - - list = &namespace->names[ get_name_hash( namespace, name, len ) ]; - if (namespace->case_sensitive) - { - LIST_FOR_EACH( p, list ) - { - const struct object_name *ptr = LIST_ENTRY( p, const struct object_name, entry ); - if (ptr->len != len) continue; - if (!memcmp( ptr->name, name, len )) return grab_object( ptr->obj ); - } - } - else - { - LIST_FOR_EACH( p, list ) - { - const struct object_name *ptr = LIST_ENTRY( p, const struct object_name, entry ); - if (ptr->len != len) continue; - if (!strncmpiW( ptr->name, name, len/sizeof(WCHAR) )) return grab_object( ptr->obj ); - } - } - return NULL; + return find_object_ex( root, name, len, case_sensitive, NULL, NULL, NULL ); } -/* allocate a namespace */ -struct namespace *create_namespace( unsigned int hash_size, int case_sensitive ) +/* if object is permanent make it temporary */ +void make_temporary_obj( struct object *obj ) { - struct namespace *namespace; - unsigned int i; - - namespace = mem_alloc( sizeof(*namespace) + (hash_size - 1) * sizeof(namespace->names[0]) ); - if (namespace) + if (obj && IS_PERMANENT( obj )) { - namespace->hash_size = hash_size; - namespace->case_sensitive = case_sensitive; - for (i = 0; i < hash_size; i++) list_init( &namespace->names[i] ); + obj->flags &= ~OBJ_PERMANENT; + release_object( obj ); } - return namespace; } /* functions for unimplemented/default object operations */ Index: server/object.h =================================================================== RCS file: /home/wine/wine/server/object.h,v retrieving revision 1.66 diff -u -p -r1.66 object.h --- server/object.h 19 Aug 2005 14:01:43 -0000 1.66 +++ server/object.h 18 Sep 2005 18:16:27 -0000 @@ -33,9 +33,7 @@ /* kernel objects */ -struct namespace; struct object; -struct object_name; struct thread; struct process; struct token; @@ -48,6 +46,8 @@ struct winstation; /* operations valid on all objects */ struct object_ops { + /* object type - one of OB_TYPE_x */ + unsigned short type; /* size of this object type */ size_t size; /* dump the object (for debugging) */ @@ -70,9 +70,21 @@ struct object_ops void (*destroy)(struct object *); }; +struct object_name +{ + struct list entry; /* entry in the directory list */ + struct directory *parent; /* parent directory */ + struct object *obj; + size_t len; + WCHAR name[1]; +}; + struct object { unsigned int refcount; /* reference count */ + unsigned int handlecount; /* handle count */ + unsigned int access; /* object access mask */ + unsigned int flags; /* object flags */ const struct object_ops *ops; struct list wait_queue; struct object_name *name; @@ -89,18 +101,20 @@ struct wait_queue_entry }; extern void *mem_alloc( size_t size ); /* malloc wrapper */ +extern struct object_name *alloc_name( const WCHAR *name, size_t len ); extern void *memdup( const void *data, size_t len ); extern void *alloc_object( const struct object_ops *ops ); extern const WCHAR *get_object_name( struct object *obj, size_t *len ); extern void dump_object_name( struct object *obj ); -extern void *create_named_object( struct namespace *namespace, const struct object_ops *ops, +extern void *create_named_object( struct directory *root, const struct object_ops *ops, const WCHAR *name, size_t len ); -extern struct namespace *create_namespace( unsigned int hash_size, int case_sensitive ); /* grab/release_object can take any pointer, but you better make sure */ /* that the thing pointed to starts with a struct object... */ extern struct object *grab_object( void *obj ); extern void release_object( void *obj ); -extern struct object *find_object( const struct namespace *namespace, const WCHAR *name, size_t len ); +extern struct object *find_object( const struct directory *root, const WCHAR *name, size_t len, + int case_sensitive ); +extern void make_temporary_obj( struct object *obj ); extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry ); extern int no_satisfied( struct object *obj, struct thread *thread ); extern int no_signal( struct object *obj, unsigned int access ); @@ -166,6 +180,24 @@ extern atom_t find_global_atom( struct w extern int grab_global_atom( struct winstation *winstation, atom_t atom ); extern void release_global_atom( struct winstation *winstation, atom_t atom ); +/* object management functions */ + +extern void init_namespace(void); +extern void close_namespace(void); + +/* directory object functions */ + +extern struct directory *create_root( void ); +extern struct object *find_object_ex( const struct directory *root, const WCHAR *name, size_t len, + int case_sensitive, WCHAR **new_name, size_t *new_len, + struct directory **parent ); +extern struct object *find_object_in_dir( struct directory *dir, const WCHAR *name, size_t len, + int case_sensitive ); +extern void *create_named_object_ex( struct directory *root, const struct object_ops *ops, + const WCHAR *name, size_t len, + unsigned long attributes, unsigned long access_mask ); +extern void delete_directory ( struct directory *dir ); + /* global variables */ /* command-line options */ @@ -178,6 +210,46 @@ extern const char *server_argv0; extern time_t server_start_time; /* name space for synchronization objects */ -extern struct namespace *sync_namespace; +extern struct directory *root_directory; + +/* common directories */ +extern struct directory *dir_Windows_WindowStations; +extern struct directory *dir_BaseNamedObjects; + +#define OBJ_INHERIT 0x00000002L +#define OBJ_PERMANENT 0x00000010L +#define OBJ_EXCLUSIVE 0x00000020L +#define OBJ_CASE_INSENSITIVE 0x00000040L +#define OBJ_OPENIF 0x00000080L +#define OBJ_OPENLINK 0x00000100L +#define OBJ_KERNEL_HANDLE 0x00000200L +#define OBJ_VALID_ATTRIBUTES 0x000003F2L + +#define IS_CASE_SENSITIVE(a) (((a) & OBJ_CASE_INSENSITIVE)==0) + +#define OB_TYPE_NONE 0 +#define OB_TYPE_TYPE 1 +#define OB_TYPE_DIRECTORY 2 +#define OB_TYPE_SYMBOLIC_LINK 3 +#define OB_TYPE_TOKEN 4 +#define OB_TYPE_PROCESS 5 +#define OB_TYPE_THREAD 6 +#define OB_TYPE_EVENT 7 +#define OB_TYPE_EVENT_PAIR 8 +#define OB_TYPE_MUTANT 9 +#define OB_TYPE_SEMAPHORE 10 +#define OB_TYPE_TIMER 11 +#define OB_TYPE_PROFILE 12 +#define OB_TYPE_WINDOW_STATION 13 +#define OB_TYPE_DESKTOP 14 +#define OB_TYPE_SECTION 15 +#define OB_TYPE_KEY 16 +#define OB_TYPE_PORT 17 +#define OB_TYPE_ADAPTER 18 +#define OB_TYPE_CONTROLLER 19 +#define OB_TYPE_DEVICE 20 +#define OB_TYPE_DRIVER 21 +#define OB_TYPE_IO_COMPLETION 22 +#define OB_TYPE_FILE 23 #endif /* __WINE_SERVER_OBJECT_H */ Index: server/process.c =================================================================== RCS file: /home/wine/wine/server/process.c,v retrieving revision 1.140 diff -u -p -r1.140 process.c --- server/process.c 6 Sep 2005 10:25:11 -0000 1.140 +++ server/process.c 18 Sep 2005 18:16:27 -0000 @@ -62,6 +62,7 @@ static void process_destroy( struct obje static const struct object_ops process_ops = { + OB_TYPE_PROCESS, /* object type */ sizeof(struct process), /* size */ process_dump, /* dump */ add_queue, /* add_queue */ @@ -110,6 +111,7 @@ static void startup_info_destroy( struct static const struct object_ops startup_info_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct startup_info), /* size */ startup_info_dump, /* dump */ add_queue, /* add_queue */ Index: server/queue.c =================================================================== RCS file: /home/wine/wine/server/queue.c,v retrieving revision 1.70 diff -u -p -r1.70 queue.c --- server/queue.c 13 Sep 2005 14:46:46 -0000 1.70 +++ server/queue.c 18 Sep 2005 18:16:28 -0000 @@ -142,6 +142,7 @@ static void timer_callback( void *privat static const struct object_ops msg_queue_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct msg_queue), /* size */ msg_queue_dump, /* dump */ msg_queue_add_queue, /* add_queue */ @@ -157,6 +158,7 @@ static const struct object_ops msg_queue static const struct object_ops thread_input_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct thread_input), /* size */ thread_input_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/registry.c =================================================================== RCS file: /home/wine/wine/server/registry.c,v retrieving revision 1.81 diff -u -p -r1.81 registry.c --- server/registry.c 9 Aug 2005 10:37:50 -0000 1.81 +++ server/registry.c 18 Sep 2005 18:16:28 -0000 @@ -133,6 +133,7 @@ static void key_destroy( struct object * static const struct object_ops key_ops = { + OB_TYPE_KEY, /* object type */ sizeof(struct key), /* size */ key_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/request.c =================================================================== RCS file: /home/wine/wine/server/request.c,v retrieving revision 1.93 diff -u -p -r1.93 request.c --- server/request.c 9 Aug 2005 10:37:50 -0000 1.93 +++ server/request.c 18 Sep 2005 18:16:28 -0000 @@ -87,6 +87,7 @@ static void master_socket_poll_event( st static const struct object_ops master_socket_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct master_socket), /* size */ master_socket_dump, /* dump */ no_add_queue, /* add_queue */ @@ -797,6 +798,7 @@ static void close_socket_timeout( void * close_signals(); close_global_handles(); close_registry(); + close_namespace(); dump_objects(); /* dump any remaining objects */ #else exit(0); Index: server/semaphore.c =================================================================== RCS file: /home/wine/wine/server/semaphore.c,v retrieving revision 1.29 diff -u -p -r1.29 semaphore.c --- server/semaphore.c 9 Jun 2005 15:39:52 -0000 1.29 +++ server/semaphore.c 18 Sep 2005 18:16:28 -0000 @@ -45,6 +45,7 @@ static int semaphore_signal( struct obje static const struct object_ops semaphore_ops = { + OB_TYPE_SEMAPHORE, /* object type */ sizeof(struct semaphore), /* size */ semaphore_dump, /* dump */ add_queue, /* add_queue */ @@ -68,7 +69,7 @@ static struct semaphore *create_semaphor set_error( STATUS_INVALID_PARAMETER ); return NULL; } - if ((sem = create_named_object( sync_namespace, &semaphore_ops, name, len ))) + if ((sem = create_named_object( root_directory, &semaphore_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -157,8 +158,8 @@ DECL_HANDLER(create_semaphore) /* open a handle to a semaphore */ DECL_HANDLER(open_semaphore) { - reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(), - &semaphore_ops, req->access, req->inherit ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &semaphore_ops, req->access, req->inherit, TRUE ); } /* release a semaphore */ Index: server/serial.c =================================================================== RCS file: /home/wine/wine/server/serial.c,v retrieving revision 1.43 diff -u -p -r1.43 serial.c --- server/serial.c 21 Jun 2005 09:46:15 -0000 1.43 +++ server/serial.c 18 Sep 2005 18:16:28 -0000 @@ -92,6 +92,7 @@ struct serial static const struct object_ops serial_ops = { + OB_TYPE_DEVICE, /* object type */ sizeof(struct serial), /* size */ serial_dump, /* dump */ default_fd_add_queue, /* add_queue */ Index: server/signal.c =================================================================== RCS file: /home/wine/wine/server/signal.c,v retrieving revision 1.13 diff -u -p -r1.13 signal.c --- server/signal.c 19 Aug 2005 14:01:43 -0000 1.13 +++ server/signal.c 18 Sep 2005 18:16:28 -0000 @@ -56,6 +56,7 @@ static void handler_destroy( struct obje static const struct object_ops handler_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct handler), /* size */ handler_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/snapshot.c =================================================================== RCS file: /home/wine/wine/server/snapshot.c,v retrieving revision 1.25 diff -u -p -r1.25 snapshot.c --- server/snapshot.c 9 Jun 2005 15:39:52 -0000 1.25 +++ server/snapshot.c 18 Sep 2005 18:16:28 -0000 @@ -55,6 +55,7 @@ static void snapshot_destroy( struct obj static const struct object_ops snapshot_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct snapshot), /* size */ snapshot_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/sock.c =================================================================== RCS file: /home/wine/wine/server/sock.c,v retrieving revision 1.58 diff -u -p -r1.58 sock.c --- server/sock.c 9 Aug 2005 10:37:50 -0000 1.58 +++ server/sock.c 18 Sep 2005 18:16:28 -0000 @@ -100,6 +100,7 @@ static void sock_set_error(void); static const struct object_ops sock_ops = { + OB_TYPE_NONE, /* object type */ sizeof(struct sock), /* size */ sock_dump, /* dump */ add_queue, /* add_queue */ Index: server/thread.c =================================================================== RCS file: /home/wine/wine/server/thread.c,v retrieving revision 1.127 diff -u -p -r1.127 thread.c --- server/thread.c 14 Sep 2005 15:44:12 -0000 1.127 +++ server/thread.c 18 Sep 2005 18:16:28 -0000 @@ -86,6 +86,7 @@ static struct thread_apc *thread_dequeue static const struct object_ops thread_ops = { + OB_TYPE_THREAD, /* object type */ sizeof(struct thread), /* size */ dump_thread, /* dump */ add_queue, /* add_queue */ Index: server/timer.c =================================================================== RCS file: /home/wine/wine/server/timer.c,v retrieving revision 1.28 diff -u -p -r1.28 timer.c --- server/timer.c 9 Jun 2005 15:39:52 -0000 1.28 +++ server/timer.c 18 Sep 2005 18:16:28 -0000 @@ -53,6 +53,7 @@ static void timer_destroy( struct object static const struct object_ops timer_ops = { + OB_TYPE_TIMER, /* object type */ sizeof(struct timer), /* size */ timer_dump, /* dump */ add_queue, /* add_queue */ @@ -71,7 +72,7 @@ static struct timer *create_timer( const { struct timer *timer; - if ((timer = create_named_object( sync_namespace, &timer_ops, name, len ))) + if ((timer = create_named_object( root_directory, &timer_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -214,8 +215,8 @@ DECL_HANDLER(create_timer) /* open a handle to a timer */ DECL_HANDLER(open_timer) { - reply->handle = open_object( sync_namespace, get_req_data(), get_req_data_size(), - &timer_ops, req->access, req->inherit ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &timer_ops, req->access, req->inherit, TRUE ); } /* set a waitable timer */ Index: server/token.c =================================================================== RCS file: /home/wine/wine/server/token.c,v retrieving revision 1.15 diff -u -p -r1.15 token.c --- server/token.c 18 Jul 2005 13:22:55 -0000 1.15 +++ server/token.c 18 Sep 2005 18:16:28 -0000 @@ -106,6 +106,7 @@ static void token_destroy( struct object static const struct object_ops token_ops = { + OB_TYPE_TOKEN, /* object type */ sizeof(struct token), /* size */ token_dump, /* dump */ no_add_queue, /* add_queue */ Index: server/user.h =================================================================== RCS file: /home/wine/wine/server/user.h,v retrieving revision 1.37 diff -u -p -r1.37 user.h --- server/user.h 11 Jul 2005 18:05:50 -0000 1.37 +++ server/user.h 18 Sep 2005 18:16:29 -0000 @@ -45,7 +45,7 @@ struct winstation struct object obj; /* object header */ unsigned int flags; /* winstation flags */ struct list entry; /* entry in global winstation list */ - struct list desktops; /* list of desktops of this winstation */ + struct directory *desktops; /* list of desktops of this winstation */ struct clipboard *clipboard; /* clipboard information */ struct atom_table *atom_table; /* global atom table */ }; Index: server/winstation.c =================================================================== RCS file: /home/wine/wine/server/winstation.c,v retrieving revision 1.10 diff -u -p -r1.10 winstation.c --- server/winstation.c 11 Jul 2005 18:05:50 -0000 1.10 +++ server/winstation.c 18 Sep 2005 18:16:29 -0000 @@ -38,7 +38,6 @@ static struct list winstation_list = LIST_INIT(winstation_list); static struct winstation *interactive_winstation; -static struct namespace *winstation_namespace; static void winstation_dump( struct object *obj, int verbose ); static int winstation_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); @@ -49,6 +48,7 @@ static void desktop_destroy( struct obje static const struct object_ops winstation_ops = { + OB_TYPE_WINDOW_STATION, /* object type */ sizeof(struct winstation), /* size */ winstation_dump, /* dump */ no_add_queue, /* add_queue */ @@ -64,6 +64,7 @@ static const struct object_ops winstatio static const struct object_ops desktop_ops = { + OB_TYPE_DESKTOP, /* object type */ sizeof(struct desktop), /* size */ desktop_dump, /* dump */ no_add_queue, /* add_queue */ @@ -83,16 +84,13 @@ static struct winstation *create_winstat { struct winstation *winstation; - if (!winstation_namespace && !(winstation_namespace = create_namespace( 7, FALSE ))) - return NULL; - if (memchrW( name, '\\', len / sizeof(WCHAR) )) /* no backslash allowed in name */ { set_error( STATUS_INVALID_PARAMETER ); return NULL; } - if ((winstation = create_named_object( winstation_namespace, &winstation_ops, name, len ))) + if ((winstation = create_named_object( dir_Windows_WindowStations, &winstation_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -101,7 +99,7 @@ static struct winstation *create_winstat winstation->clipboard = NULL; winstation->atom_table = NULL; list_add_tail( &winstation_list, &winstation->entry ); - list_init( &winstation->desktops ); + winstation->desktops = create_root(); } } return winstation; @@ -130,6 +128,7 @@ static void winstation_destroy( struct o list_remove( &winstation->entry ); if (winstation->clipboard) release_object( winstation->clipboard ); if (winstation->atom_table) release_object( winstation->atom_table ); + if (winstation->desktops) release_object( winstation->desktops ); } /* retrieve the process window station, checking the handle access rights */ @@ -139,31 +138,6 @@ struct winstation *get_process_winstatio access, &winstation_ops ); } -/* build the full name of a desktop object */ -static WCHAR *build_desktop_name( const WCHAR *name, size_t len, - struct winstation *winstation, size_t *res_len ) -{ - const WCHAR *winstation_name; - WCHAR *full_name; - size_t winstation_len; - - if (memchrW( name, '\\', len / sizeof(WCHAR) )) - { - set_error( STATUS_INVALID_PARAMETER ); - return NULL; - } - - if (!(winstation_name = get_object_name( &winstation->obj, &winstation_len ))) - winstation_len = 0; - - *res_len = winstation_len + len + sizeof(WCHAR); - if (!(full_name = mem_alloc( *res_len ))) return NULL; - memcpy( full_name, winstation_name, winstation_len ); - full_name[winstation_len / sizeof(WCHAR)] = '\\'; - memcpy( full_name + winstation_len / sizeof(WCHAR) + 1, name, len ); - return full_name; -} - /* retrieve a pointer to a desktop object */ inline static struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle, unsigned int access ) @@ -176,12 +150,13 @@ static struct desktop *create_desktop( c struct winstation *winstation ) { struct desktop *desktop; - WCHAR *full_name; - size_t full_len; - - if (!(full_name = build_desktop_name( name, len, winstation, &full_len ))) return NULL; - if ((desktop = create_named_object( winstation_namespace, &desktop_ops, full_name, full_len ))) + if (memchrW( name, '\\', len / sizeof(WCHAR) )) + { + set_error( STATUS_INVALID_PARAMETER ); + return NULL; + } + if ((desktop = create_named_object( winstation->desktops, &desktop_ops, name, len ))) { if (get_error() != STATUS_OBJECT_NAME_COLLISION) { @@ -190,10 +165,8 @@ static struct desktop *create_desktop( c desktop->winstation = (struct winstation *)grab_object( winstation ); desktop->top_window = NULL; desktop->global_hooks = NULL; - list_add_tail( &winstation->desktops, &desktop->entry ); } } - free( full_name ); return desktop; } @@ -224,7 +197,6 @@ static void desktop_destroy( struct obje if (desktop->top_window) destroy_window( desktop->top_window ); if (desktop->global_hooks) release_object( desktop->global_hooks ); - list_remove( &desktop->entry ); release_object( desktop->winstation ); } @@ -320,11 +292,8 @@ DECL_HANDLER(create_winstation) /* open a handle to a window station */ DECL_HANDLER(open_winstation) { - if (winstation_namespace) - reply->handle = open_object( winstation_namespace, get_req_data(), get_req_data_size(), - &winstation_ops, req->access, req->inherit ); - else - set_error( STATUS_OBJECT_NAME_NOT_FOUND ); + reply->handle = open_object( root_directory, get_req_data(), get_req_data_size(), + &winstation_ops, req->access, req->inherit, FALSE ); } @@ -389,16 +358,8 @@ DECL_HANDLER(open_desktop) if ((winstation = get_process_winstation( current->process, 0 /* FIXME: access rights? */ ))) { - size_t full_len; - WCHAR *full_name; - - if ((full_name = build_desktop_name( get_req_data(), get_req_data_size(), - winstation, &full_len ))) - { - reply->handle = open_object( winstation_namespace, full_name, full_len, - &desktop_ops, req->access, req->inherit ); - free( full_name ); - } + reply->handle = open_object( winstation->desktops, get_req_data(), get_req_data_size(), + &desktop_ops, req->access, req->inherit, FALSE ); release_object( winstation ); } } --- /dev/null 2005-03-19 12:36:14.000000000 -0700 +++ server/directory.c 2005-09-18 12:23:40.000000000 -0600 @@ -0,0 +1,349 @@ +/* + * Server-side directory object management + * + * Copyright (C) 2005 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include + +#include "windef.h" +#include "winternl.h" + +#include "handle.h" +#include "request.h" +#include "process.h" +#include "unicode.h" +#include "wine/list.h" +#include "object.h" +#include "directory.h" +#include "om.h" +#include "user.h" + +#define IS_PERMANENT(o) ((o)->flags & OBJ_PERMANENT) + +static void directory_dump( struct object *obj, int verbose ); +static void directory_destroy( struct object *obj ); +static const struct object_ops directory_ops = +{ + OB_TYPE_DIRECTORY, /* object type */ + sizeof(struct directory), /* size */ + directory_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ + directory_destroy /* destroy */ +}; + +static void directory_dump( struct object *obj, int verbose ) +{ + struct directory *dir = (struct directory *)obj; + + fputs( "Directory ", stderr ); + dump_object_name( obj ); + if (verbose) + { + struct object_name *ptr; + + assert( obj->ops == &directory_ops ); + fputs( " entries:\n", stderr ); + LIST_FOR_EACH_ENTRY(ptr, &dir->entries, struct object_name, entry) + { + fputs( " ", stderr ); + dump_strW( type_names[ptr->obj->ops->type], strlenW(type_names[ptr->obj->ops->type]), stderr, "\"\"" ); + fputs( " object ", stderr ); + dump_object_name( ptr->obj ); + fputc( '\n', stderr ); + } + } + else + fputc( '\n', stderr ); +} + +static void directory_destroy( struct object *obj ) +{ + struct object_name *ptr, *next; + struct directory *dir = (struct directory *)obj; + assert( obj->ops == &directory_ops ); + + LIST_FOR_EACH_ENTRY_SAFE( ptr, next, &dir->entries, struct object_name, entry ) + { + release_object( ptr->obj ); + } +} + +/******************************************************************************/ + +/* find an object by its name in a given directory; the refcount is incremented + * name - is a relative name */ +struct object *find_object_in_dir( struct directory *dir, const WCHAR *name, size_t len, + int case_sensitive ) +{ + const struct list *p; + + if (!name || !len) return NULL; + + if (!dir->obj.access & DIRECTORY_TRAVERSE) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } + + LIST_FOR_EACH( p, &dir->entries ) + { + const struct object_name *ptr = LIST_ENTRY( p, const struct object_name, entry ); + if (ptr->len != len) continue; + if (case_sensitive) + { + if (!memcmp( ptr->name, name, len )) return grab_object( ptr->obj ); + } + else + { + if (!strncmpiW( ptr->name, name, len/sizeof(WCHAR) )) return grab_object( ptr->obj ); + } + } + return NULL; +} + +/* + * find an object by its name in a given directory; the refcount is incremented + * name is a fully qualified name + * new_name - is a name leftover if object is not found + * new_len - length of the above + * parent - last found parent directory + */ +struct object * find_object_ex( const struct directory *root, const WCHAR *name, + size_t len, int case_sensitive, + WCHAR **new_name, size_t *new_len, struct directory **parent ) +{ + struct object *obj = NULL; + struct directory *dir = (struct directory *)root; + WCHAR *name_l = (WCHAR*)name; + size_t len_l = len; + + /* Sanity check */ + if (!name || !len) return NULL; + + /* Skip leading \\ */ + if (len_l && *name_l == '\\') + { + name_l++; + len_l -= sizeof(WCHAR); + /* It is the root itself */ + if (!len_l) + { + obj = grab_object( dir ); + dir = dir->obj.name->parent; + goto done; + } + } + do + { + WCHAR *p = memchrW(name_l, '\\', len_l/sizeof(WCHAR)); + if (!p) p = name_l + len_l/sizeof(WCHAR); + + /* FIXME: when we have devices handle their namespace, remove second find */ + if (!(obj = find_object_in_dir( dir, name_l, (p - name_l)*sizeof(WCHAR), case_sensitive )) && + !(obj = find_object_in_dir( dir, name_l, len_l, case_sensitive )) ) + break; + + /* move to the next element */ + len_l -= (p - name_l)*sizeof(WCHAR); + name_l = p; + + if (len_l && *name_l == '\\') + { + name_l++; + len_l -= sizeof(WCHAR); + } + + if (obj->ops->type == OB_TYPE_SYMBOLIC_LINK) + obj = get_symlink_target_obj( obj, case_sensitive ); + + /* found the object */ + if (!len_l) break; + + if (obj->ops->type == OB_TYPE_WINDOW_STATION) + { + dir = ((struct winstation *)obj)->desktops; + release_object( obj ); + } + if (obj->ops->type == OB_TYPE_DIRECTORY) + { + dir = (struct directory *) obj; + release_object( obj ); + } + else break; + } while (len_l > 0); + + done: + if (new_name) *new_name = name_l; + if (new_len) *new_len = len_l; + if (parent) *parent = dir; + + return obj; +} + +void *create_named_object_ex( struct directory *root, const struct object_ops *ops, + const WCHAR *name, size_t len, + unsigned long attributes, unsigned long access_mask ) +{ + struct object *obj; + struct directory *dir; + size_t new_len; + WCHAR *new_name; + struct object_name *name_ptr; + + if (!name || !len) return alloc_object( ops ); + + if ((obj = find_object_ex( root, name, len, IS_CASE_SENSITIVE(attributes), + &new_name, &new_len, &dir ))) + { + if (obj->ops == ops) + { + set_error( STATUS_OBJECT_NAME_COLLISION ); + return obj; + } + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + release_object( obj ); + return NULL; + } + + if (dir->obj.ops->type == OB_TYPE_DIRECTORY) + { + if ((ops->type == OB_TYPE_DIRECTORY && + !(dir->obj.access & DIRECTORY_CREATE_SUBDIRECTORY)) + || + !(dir->obj.access & DIRECTORY_CREATE_OBJECT)) + { + set_error( STATUS_ACCESS_DENIED ); + return NULL; + } + } + + if (!(name_ptr = alloc_name( new_name, new_len ))) return NULL; + if ((obj = alloc_object( ops ))) + { + grab_object( dir );; + obj->name = name_ptr; + name_ptr->obj = obj; + if (dir->obj.ops->type == OB_TYPE_DIRECTORY) + { + list_add_head( &dir->entries, &name_ptr->entry ); + obj->name->parent = dir; + } + else + obj->name->parent = NULL; + obj->flags = attributes; + obj->access = access_mask; + + if (IS_PERMANENT( obj )) + grab_object( obj ); + clear_error(); + } + else free( name_ptr ); + + return obj; +} + +/******************************************************************************/ + +/* create root directory */ +struct directory *create_root( void ) +{ + static const WCHAR rootW[]={'\\'}; + struct object *obj; + struct object_name *name_ptr; + + if (!(name_ptr = alloc_name( rootW, sizeof(rootW) ))) return NULL; + if ((obj = alloc_object( &directory_ops ))) + { + grab_object( obj ); + obj->name = name_ptr; + name_ptr->obj = obj; + name_ptr->parent = NULL; + obj->flags = OBJ_PERMANENT; + obj->access = DIRECTORY_ALL_ACCESS; + list_init( &((struct directory *)obj)->entries ); + } + else free( name_ptr ); + return (struct directory *)obj; +} + +struct directory *create_directory( const WCHAR *name, size_t len, + unsigned long attributes, + unsigned long access_mask ) +{ + struct directory *dir = (struct directory *) + create_named_object_ex( root_directory, &directory_ops, name, len, + attributes, access_mask ); + if (!dir) return NULL; + list_init(&dir->entries); + + return dir; +} + +void delete_directory ( struct directory *dir ) +{ + if (dir) + { + struct object_name *ptr, *next; + + LIST_FOR_EACH_ENTRY_SAFE( ptr, next, &dir->entries, struct object_name, entry ) + { + if (ptr->obj->ops == &directory_ops) + delete_directory( (struct directory *)ptr->obj ); + else + release_object( ptr->obj ); + } + release_object( dir ); + } +} + +/******************************************************************************/ +struct directory *dir_Windows_WindowStations; + +void init_namespace_dirs(void) +{ + /* Directories */ + const WCHAR ntspaceW[]={'\\','?','?'}; + const WCHAR driverW[]={'\\','D','r','i','v','e','r'}; + const WCHAR deviceW[]={'\\','D','e','v','i','c','e'}; + const WCHAR windowsW[]={'\\','W','i','n','d','o','w','s'}; + const WCHAR windstaW[]={'\\','W','i','n','d','o','w','s','\\','W','i','n','d','o','w','S','t','a','t','i','o','n','s'}; + const WCHAR basenameW[]={'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s'}; + + root_directory = create_root( ); + release_object( create_directory(windowsW, sizeof(windowsW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS) ); + dir_Windows_WindowStations = create_directory( windstaW, sizeof(windstaW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS ); + release_object( dir_Windows_WindowStations ); + release_object( create_directory( basenameW, sizeof(basenameW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS )); + release_object( create_directory( deviceW, sizeof(deviceW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS )); + release_object( create_directory( driverW, sizeof(driverW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS )); + release_object( create_directory( ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, DIRECTORY_ALL_ACCESS )); +} + --- /dev/null 2005-03-19 12:36:14.000000000 -0700 +++ server/directory.h 2005-09-16 13:29:28.000000000 -0600 @@ -0,0 +1,36 @@ +/* + * Copyright 2005 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SERVER_DIRECTORY_H +#define __WINE_SERVER_DIRECTORY_H + +#define DIRECTORY_QUERY (0x0001) +#define DIRECTORY_TRAVERSE (0x0002) +#define DIRECTORY_CREATE_OBJECT (0x0004) +#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008) +#define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0xF) + +struct directory +{ + struct object obj; /* object header */ + struct list entries; /* objects in this directory */ +}; + +extern void init_namespace_dirs(void); + +#endif /* __WINE_SERVER_DIRECTORY_H */ --- /dev/null 2005-03-19 12:36:14.000000000 -0700 +++ server/om.c 2005-09-18 12:24:22.000000000 -0600 @@ -0,0 +1,316 @@ +/* + * Server-side object management + * + * Copyright (C) 2005 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#ifdef HAVE_POLL_H +#include +#endif + +#include "windef.h" +#include "winternl.h" +#include "om.h" + +#include "file.h" +#include "handle.h" +#include "request.h" +#include "process.h" +#include "unicode.h" +#include "wine/list.h" +#include "directory.h" + +static const WCHAR STR_NONE []={'u','n','k','n','o','w','n',0}; +static const WCHAR STR_TYPE []={'T','y','p','e',0}; +static const WCHAR STR_DIRECTORY []={'D','i','r','e','c','t','o','r','y',0}; +static const WCHAR STR_SYMBOLIC_LINK []={'S','y','m','b','o','l','i','c','L','i','n','k',0}; +static const WCHAR STR_TOKEN []={'T','o','k','e','n',0}; +static const WCHAR STR_PROCESS []={'P','r','o','c','e','s','s',0}; +static const WCHAR STR_THREAD []={'T','h','r','e','a','d',0}; +static const WCHAR STR_EVENT []={'E','v','e','n','t',0}; +static const WCHAR STR_EVENT_PAIR []={'E','v','e','n','t','P','a','i','r',0}; +static const WCHAR STR_MUTANT []={'M','u','t','a','n','t',0}; +static const WCHAR STR_SEMAPHORE []={'S','e','m','a','p','h','o','r','e',0}; +static const WCHAR STR_TIMER []={'T','i','m','e','r',0}; +static const WCHAR STR_PROFILE []={'P','r','o','f','i','l','e',0}; +static const WCHAR STR_WINDOW_STATION[]={'W','i','n','d','o','w','S','t','a','t','i','o','n',0}; +static const WCHAR STR_DESKTOP []={'D','e','s','k','t','o','p',0}; +static const WCHAR STR_SECTION []={'S','e','c','t','i','o','n',0}; +static const WCHAR STR_KEY []={'K','e','y',0}; +static const WCHAR STR_PORT []={'P','o','r','t',0}; +static const WCHAR STR_ADAPTER []={'A','d','a','p','t','e','r',0}; +static const WCHAR STR_CONTROLLER []={'C','o','n','t','r','o','l','l','e','r',0}; +static const WCHAR STR_DEVICE []={'D','e','v','i','c','e',0}; +static const WCHAR STR_DRIVER []={'D','r','i','v','e','r',0}; +static const WCHAR STR_IO_COMPLETION []={'I','o','C','o','m','p','l','e','t','i','o','n',0}; +static const WCHAR STR_FILE []={'F','i','l','e',0}; + +const WCHAR *type_names [24] = +{ + STR_NONE, + STR_TYPE, + STR_DIRECTORY, + STR_SYMBOLIC_LINK, + STR_TOKEN, + STR_PROCESS, + STR_THREAD, + STR_EVENT, + STR_EVENT_PAIR, + STR_MUTANT, + STR_SEMAPHORE, + STR_TIMER, + STR_PROFILE, + STR_WINDOW_STATION, + STR_DESKTOP, + STR_SECTION, + STR_KEY, + STR_PORT, + STR_ADAPTER, + STR_CONTROLLER, + STR_DEVICE, + STR_DRIVER, + STR_IO_COMPLETION, + STR_FILE +}; + +/* list of created devices */ +static struct list devices_list = LIST_INIT(devices_list); + +struct ob_symlink +{ + struct object obj; /* object header */ + WCHAR *target_name; /* target of the symlink */ + size_t target_name_len; /* length of the target name */ +}; + +struct ob_device +{ + struct object obj; /* object header */ + struct list entry; /* entry in devices_list */ + void *device_object; /* pointer to DEVICE_OBJECT */ +}; + +static void ob_symlink_dump( struct object *obj, int verbose ); +static void ob_symlink_destroy( struct object *obj ); +static const struct object_ops ob_symlink_ops = +{ + OB_TYPE_SYMBOLIC_LINK, /* object type */ + sizeof(struct ob_symlink), /* size */ + ob_symlink_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ + ob_symlink_destroy /* destroy */ +}; + +static void ob_device_dump( struct object *obj, int verbose ); +static void ob_device_destroy( struct object *obj ); +static const struct object_ops ob_device_ops = +{ + OB_TYPE_DEVICE, /* object type */ + sizeof(struct ob_device), /* size */ + ob_device_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + NULL, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + no_close_handle, /* close_handle */ + ob_device_destroy /* destroy */ +}; + +static void ob_symlink_dump( struct object *obj, int verbose ) +{ + struct ob_symlink *symlink = (struct ob_symlink *)obj; + fputs( "Symbolic Link ", stderr ); + dump_object_name( obj ); + fprintf( stderr, " -> L\"" ); + dump_strW( symlink->target_name, symlink->target_name_len / sizeof(WCHAR), stderr, "\"\"" ); + fputs( "\"\n", stderr ); +} + +static void ob_symlink_destroy( struct object *obj ) +{ + assert( obj->ops == &ob_symlink_ops ); + free( ((struct ob_symlink *)obj)->target_name ); +} + +static void ob_device_dump( struct object *obj, int verbose ) +{ + struct ob_device *device = (struct ob_device *) obj; + assert( obj->ops == &ob_device_ops ); + fprintf( stderr, "Device " ); + dump_object_name( obj ); + if (verbose) + { + fprintf( stderr, " device_obj=%p", device->device_object ); + } + fputc( '\n', stderr ); +} + +static void ob_device_destroy( struct object *obj ) +{ + assert( obj->ops == &ob_device_ops ); +} + +/******************************************************************************/ + +static struct object * find_symlink( const struct directory *root, const WCHAR *name, + size_t len, int case_sensitive ) +{ + struct object *obj = NULL; + struct directory *dir = (struct directory *)root; + WCHAR *name_l = (WCHAR*)name; + size_t len_l = len; + + /* Sanity check */ + if (!name || !len) return NULL; + + /* Skip leading \\ */ + if (len_l && *name_l == '\\') + { + name_l++; + len_l -= sizeof(WCHAR); + if (!len_l) + { + obj = grab_object( dir ); + dir = dir->obj.name->parent; + return obj; + } + } + do + { + WCHAR *p = memchrW(name_l, '\\', len_l/sizeof(WCHAR)); + + if (!p) p = name_l + len_l/sizeof(WCHAR); + if (!(obj = find_object_in_dir( dir, name_l, (p - name_l)*sizeof(WCHAR), case_sensitive ))) + break; + + /* move to the next element */ + len_l -= (p - name_l)*sizeof(WCHAR); + name_l = p; + + if (len_l && *name_l == '\\') + { + name_l++; + len_l -= sizeof(WCHAR); + } + /* found the object */ + if (!len_l) break; + + if (obj->ops->type == OB_TYPE_DIRECTORY) + { + dir = (struct directory *) obj; + release_object( obj ); + } + else break; + } while (len_l > 0); + + return obj; +} + +/******************************************************************************/ + +struct object *get_symlink_target_obj( const struct object *obj, int case_sensitive ) +{ + struct ob_symlink *symlink = (struct ob_symlink *)obj; + struct object *target; + + /* symlinks could be nested */ + while ((target = find_object( root_directory, symlink->target_name, + symlink->target_name_len, case_sensitive ))) + { + release_object( symlink ); + if (target->ops != &ob_symlink_ops) break; + symlink = (struct ob_symlink *)target; + } + + return target; +} + +static struct ob_symlink *create_symlink( const WCHAR *symlink_name, size_t symlink_len, + const WCHAR *target_name, size_t target_len, + unsigned long attributes, unsigned long access_mask) +{ + struct ob_symlink *symlink = (struct ob_symlink *) + create_named_object_ex( root_directory, &ob_symlink_ops, symlink_name, + symlink_len, attributes, access_mask ); + + if (!symlink) return NULL; + symlink->target_name = memdup(target_name, target_len); + symlink->target_name_len = target_len; + return symlink; +} + +/******************************************************************************/ + +static struct ob_device *create_device( const WCHAR *name, size_t len, unsigned long attributes, + unsigned long access_mask, void *dev ) +{ + struct ob_device *device = (struct ob_device *) + create_named_object_ex( root_directory, &ob_device_ops, name, len, + attributes, access_mask ); + + if (!device) return NULL; + device->device_object = dev; + list_add_tail(&devices_list, &device->entry); + return device; +} + +/******************************************************************************/ + +/* Create default entries */ +void init_namespace(void) +{ + /* Directories */ + static const WCHAR ntspaceW[]={'\\','?','?'}; + /* Symlinks */ + static const WCHAR dosdevW[]={'\\','D','o','s','D','e','v','i','c','e','s'}; + static const WCHAR globalW[]={'\\','D','o','s','D','e','v','i','c','e','s','\\','G','l','o','b','a','l'}; + + init_namespace_dirs(); + + release_object( create_symlink(dosdevW, sizeof(dosdevW), ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, SYMBOLIC_LINK_ALL_ACCESS) ); + release_object( create_symlink(globalW, sizeof(globalW), ntspaceW, sizeof(ntspaceW), OBJ_PERMANENT, SYMBOLIC_LINK_ALL_ACCESS) ); +} + +void close_namespace(void) +{ + delete_directory( root_directory ); + release_object( root_directory ); +} + --- /dev/null 2005-03-19 12:36:14.000000000 -0700 +++ server/om.h 2005-09-16 17:11:06.000000000 -0600 @@ -0,0 +1,29 @@ +/* + * Copyright 2005 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WINE_SERVER_OM_H +#define __WINE_SERVER_OM_H + +#define SYMBOLIC_LINK_QUERY 0x0001 +#define SYMBOLIC_LINK_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | 0x1) + +extern const WCHAR *type_names [24]; + +extern struct object *get_symlink_target_obj( const struct object *obj, int case_sensitive ); + +#endif /* __WINE_SERVER_OM_H */