server: reimplement namespace as a directory object.

Vitaliy Margolen wine-devel at kievinfo.com
Sun Sep 18 13:38:45 CDT 2005


This a first look at implementing name space inside wineserver as a directory
object. Some things are scatchy, like dealing with dices that should have files
inside them - ex: named pipes. You could look at how I done this with
winstation. Is this is a correct approach to this? Or should I do something
else?

I also added few extra flags to objects, that will have to be used where
appropriate. Also added object type filed to ops. There are few places that
needs this especially directory query function, that has to return type name.

As always, all suggestions comments are appreciated.

Vitaliy Margolen

-------------- next part --------------
? 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 <assert.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#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 <assert.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#include <time.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#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 */


More information about the wine-devel mailing list