diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h
index 73c3f22ae3b80bf8f44972c22db904c8e4cfb04b..3ed5f67a1a51f07e4ae7027b74db6076d42541fc 100644
--- a/dlls/kernel/kernel_private.h
+++ b/dlls/kernel/kernel_private.h
@@ -146,4 +146,7 @@ extern struct winedos_exports
     void (* BiosTick)(WORD timer);
 } winedos;
 
+/* returns directory handle for named objects */
+extern HANDLE get_BaseNamedObjects_handle(void);
+
 #endif
diff --git a/dlls/kernel/sync.c b/dlls/kernel/sync.c
index fafdc335eb46141396f08bbc691859576d3d3b0d..659ee3035c6ff5f741efc32a97f92401b489e51e 100644
--- a/dlls/kernel/sync.c
+++ b/dlls/kernel/sync.c
@@ -52,6 +52,7 @@
 #include "winnls.h"
 #include "winternl.h"
 #include "winioctl.h"
+#include "ddk/wdm.h"
 
 #include "wine/server.h"
 #include "wine/unicode.h"
@@ -68,6 +69,31 @@ inline static int is_version_nt(void)
     return !(GetVersion() & 0x80000000);
 }
 
+/* returns directory handle to \\BaseNamedObjects */
+HANDLE get_BaseNamedObjects_handle(void)
+{
+    static HANDLE handle = NULL;
+    static const WCHAR basenameW[] =
+        {'\\','B','a','s','e','N','a','m','e','d','O','b','j','e','c','t','s',0};
+    UNICODE_STRING str;
+    OBJECT_ATTRIBUTES attr;
+
+    if (!handle)
+    {
+        HANDLE dir;
+
+        RtlInitUnicodeString(&str, basenameW);
+        InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
+        NtOpenDirectoryObject(&dir, DIRECTORY_CREATE_OBJECT|DIRECTORY_TRAVERSE,
+                              &attr);
+        if (InterlockedCompareExchangePointer( (PVOID)&handle, dir, 0 ) != 0)
+        {
+            /* someone beat us here... */
+            CloseHandle( dir );
+        }
+    }
+    return handle;
+}
 
 /***********************************************************************
  *              Sleep  (KERNEL32.@)
@@ -454,6 +480,7 @@ HANDLE WINAPI CreateEventW( SECURITY_ATTRIBUTES *sa, BOOL manual_reset,
     {
         RtlInitUnicodeString( &nameW, name );
         attr.ObjectName = &nameW;
+        attr.RootDirectory = get_BaseNamedObjects_handle();
     }
 
     status = NtCreateEvent( &ret, EVENT_ALL_ACCESS, &attr, manual_reset, initial_state );
@@ -514,6 +541,7 @@ HANDLE WINAPI OpenEventW( DWORD access, BOOL inherit, LPCWSTR name )
     {
         RtlInitUnicodeString( &nameW, name );
         attr.ObjectName = &nameW;
+        attr.RootDirectory = get_BaseNamedObjects_handle();
     }
 
     status = NtOpenEvent( &ret, access, &attr );
@@ -652,6 +680,7 @@ HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, LPCWSTR name )
     {
         RtlInitUnicodeString( &nameW, name );
         attr.ObjectName = &nameW;
+        attr.RootDirectory = get_BaseNamedObjects_handle();
     }
 
     status = NtCreateMutant( &ret, MUTEX_ALL_ACCESS, &attr, owner );
@@ -703,6 +732,7 @@ HANDLE WINAPI OpenMutexW( DWORD access, BOOL inherit, LPCWSTR name )
     {
         RtlInitUnicodeString( &nameW, name );
         attr.ObjectName = &nameW;
+        attr.RootDirectory = get_BaseNamedObjects_handle();
     }
 
     status = NtOpenMutant( &ret, access, &attr );
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 7ed706054138edf4954df2840c8b7735aff8a392..f5d85aec1d20917d13c51e9c90aa53f154a61f40 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -177,6 +177,7 @@ NTSTATUS WINAPI NtCreateEvent(
     {
         req->access = DesiredAccess;
         req->attributes = (attr) ? attr->Attributes : 0;
+        req->rootdir = attr ? attr->RootDirectory : 0;
         req->manual_reset = ManualReset;
         req->initial_state = InitialState;
         if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
@@ -205,6 +206,7 @@ NTSTATUS WINAPI NtOpenEvent(
     {
         req->access  = DesiredAccess;
         req->attributes = (attr) ? attr->Attributes : 0;
+        req->rootdir = attr ? attr->RootDirectory : 0;
         if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
         ret = wine_server_call( req );
         *EventHandle = reply->handle;
@@ -324,6 +326,7 @@ NTSTATUS WINAPI NtCreateMutant(OUT HANDLE* MutantHandle,
     {
         req->access  = access;
         req->attributes = (attr) ? attr->Attributes : 0;
+        req->rootdir = attr ? attr->RootDirectory : 0;
         req->owned   = InitialOwner;
         if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
         status = wine_server_call( req );
@@ -350,6 +353,7 @@ NTSTATUS WINAPI NtOpenMutant(OUT HANDLE* MutantHandle,
     {
         req->access  = access;
         req->attributes = (attr) ? attr->Attributes : 0;
+        req->rootdir = attr ? attr->RootDirectory : 0;
         if (len) wine_server_add_data( req, attr->ObjectName->Buffer, len );
         status = wine_server_call( req );
         *MutantHandle = reply->handle;
diff --git a/dlls/ntdll/tests/om.c b/dlls/ntdll/tests/om.c
index 79bd6b66fcfc47bc2c29da6e995f1801da566f67..492033d31c01fd3de672b74f5e7d0539bed628dc 100644
--- a/dlls/ntdll/tests/om.c
+++ b/dlls/ntdll/tests/om.c
@@ -90,7 +90,7 @@ void test_case_sensitive (void)
 
     attr.Attributes = 0;
     status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
+    ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
 
     pNtClose(Event);
@@ -191,13 +191,13 @@ static void test_name_collisions(void)
     DIR_TEST_CREATE_FAILURE(&h, STATUS_OBJECT_NAME_EXISTS)
     pNtClose(h);
     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH,
+    ok(status == STATUS_OBJECT_TYPE_MISMATCH,
         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
     pRtlFreeUnicodeString(&str);
 
     pRtlCreateUnicodeStringFromAsciiz(&str, "\\??\\PIPE\\om.c-mutant");
     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
+    ok(status == STATUS_OBJECT_TYPE_MISMATCH || status == STATUS_OBJECT_PATH_NOT_FOUND,
         "NtCreateMutant should have failed with STATUS_OBJECT_TYPE_MISMATCH got(%08lx)\n", status);
     pRtlFreeUnicodeString(&str);
 
@@ -420,18 +420,18 @@ void test_directory(void)
     /* Test inavalid paths */
     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant");
     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
+    ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08lx)\n", status);
     pRtlFreeUnicodeString(&str);
     pRtlCreateUnicodeStringFromAsciiz(&str, "\\om.c-mutant\\");
     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
+    ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD,
         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_SYNTAX_BAD got(%08lx)\n", status);
     pRtlFreeUnicodeString(&str);
 
     pRtlCreateUnicodeStringFromAsciiz(&str, "om.c\\-mutant");
     status = pNtCreateMutant(&h, GENERIC_ALL, &attr, FALSE);
-    todo_wine ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
+    ok(status == STATUS_OBJECT_PATH_NOT_FOUND,
         "NtCreateMutant should have failed with STATUS_OBJECT_PATH_NOT_FOUND got(%08lx)\n", status);
     pRtlFreeUnicodeString(&str);
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index fcbf8b0ab34116fc5d7d166221f25496af942462..18188467bceb3e0010956ab324dba2ce67de592c 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -614,6 +614,7 @@ struct create_event_request
     struct request_header __header;
     unsigned int access;
     unsigned int attributes;
+    obj_handle_t rootdir;
     int          manual_reset;
     int          initial_state;
     /* VARARG(name,unicode_str); */
@@ -644,6 +645,7 @@ struct open_event_request
     struct request_header __header;
     unsigned int access;
     unsigned int attributes;
+    obj_handle_t rootdir;
     /* VARARG(name,unicode_str); */
 };
 struct open_event_reply
@@ -659,6 +661,7 @@ struct create_mutex_request
     struct request_header __header;
     unsigned int access;
     unsigned int attributes;
+    obj_handle_t rootdir;
     int          owned;
     /* VARARG(name,unicode_str); */
 };
@@ -688,6 +691,7 @@ struct open_mutex_request
     struct request_header __header;
     unsigned int access;
     unsigned int attributes;
+    obj_handle_t rootdir;
     /* VARARG(name,unicode_str); */
 };
 struct open_mutex_reply
@@ -4302,6 +4306,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 201
+#define SERVER_PROTOCOL_VERSION 202
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/console.c b/server/console.c
index d13c7de4259151dc2ddccd960c988a83f4349d01..e567d60cbe8690dc0764fd1db26db2358eb0b6e4 100644
--- a/server/console.c
+++ b/server/console.c
@@ -233,7 +233,7 @@ static struct object *create_console_input( struct thread* renderer )
     console_input->history_index = 0;
     console_input->history_mode  = 0;
     console_input->edition_mode  = 0;
-    console_input->event         = create_event( NULL, 0, 1, 0 );
+    console_input->event         = create_event( NULL, NULL, 0, 1, 0 );
 
     if (!console_input->history || !console_input->evt)
     {
diff --git a/server/event.c b/server/event.c
index bd73b88605447d426e8c4f5a1eb3277e721fd644..844383761039a9be1842c5c5ae1c08550d2c9b4e 100644
--- a/server/event.c
+++ b/server/event.c
@@ -63,12 +63,12 @@ static const struct object_ops event_ops =
 };
 
 
-struct event *create_event( const struct unicode_str *name, unsigned int attr,
-                            int manual_reset, int initial_state )
+struct event *create_event( struct directory *root, const struct unicode_str *name,
+                            unsigned int attr, int manual_reset, int initial_state )
 {
     struct event *event;
 
-    if ((event = create_named_object( sync_namespace, &event_ops, name, attr )))
+    if ((event = create_named_object_dir( root, name, attr, &event_ops )))
     {
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
@@ -150,24 +150,36 @@ DECL_HANDLER(create_event)
 {
     struct event *event;
     struct unicode_str name;
+    struct directory *root = NULL;
 
     reply->handle = 0;
     get_req_unicode_str( &name );
-    if ((event = create_event( &name, req->attributes, req->manual_reset, req->initial_state )))
+    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+        return;
+
+    if ((event = create_event( root, &name, req->attributes, req->manual_reset, req->initial_state )))
     {
         reply->handle = alloc_handle( current->process, event, req->access,
                                       req->attributes & OBJ_INHERIT );
         release_object( event );
     }
+
+    if (root) release_object( root );
 }
 
 /* open a handle to an event */
 DECL_HANDLER(open_event)
 {
     struct unicode_str name;
+    struct directory *root = NULL;
 
     get_req_unicode_str( &name );
-    reply->handle = open_object( sync_namespace, &name, &event_ops, req->access, req->attributes );
+    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+        return;
+
+    reply->handle = open_object_dir( root, &name, req->attributes, &event_ops, req->access );
+
+    if (root) release_object( root );
 }
 
 /* do an event operation */
diff --git a/server/mutex.c b/server/mutex.c
index 0953f3f4007774e5076d068c559f20c5578879f4..9e3bdc342e49fdd3b62670969af3f296a89241da 100644
--- a/server/mutex.c
+++ b/server/mutex.c
@@ -66,11 +66,12 @@ static const struct object_ops mutex_ops =
 };
 
 
-static struct mutex *create_mutex( const struct unicode_str *name, unsigned int attr, int owned )
+static struct mutex *create_mutex( struct directory *root, const struct unicode_str *name,
+                                   unsigned int attr, int owned )
 {
     struct mutex *mutex;
 
-    if ((mutex = create_named_object( sync_namespace, &mutex_ops, name, attr )))
+    if ((mutex = create_named_object_dir( root, name, attr, &mutex_ops )))
     {
         if (get_error() != STATUS_OBJECT_NAME_EXISTS)
         {
@@ -175,24 +176,36 @@ DECL_HANDLER(create_mutex)
 {
     struct mutex *mutex;
     struct unicode_str name;
+    struct directory *root = NULL;
 
     reply->handle = 0;
     get_req_unicode_str( &name );
-    if ((mutex = create_mutex( &name, req->attributes, req->owned )))
+    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+        return;
+
+    if ((mutex = create_mutex( root, &name, req->attributes, req->owned )))
     {
         reply->handle = alloc_handle( current->process, mutex, req->access,
                                       req->attributes & OBJ_INHERIT );
         release_object( mutex );
     }
+
+    if (root) release_object( root );
 }
 
 /* open a handle to a mutex */
 DECL_HANDLER(open_mutex)
 {
     struct unicode_str name;
+    struct directory *root = NULL;
 
     get_req_unicode_str( &name );
-    reply->handle = open_object( sync_namespace, &name, &mutex_ops, req->access, req->attributes );
+    if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
+        return;
+
+    reply->handle = open_object_dir( root, &name, req->attributes, &mutex_ops, req->access );
+
+    if (root) release_object( root );
 }
 
 /* release a mutex */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 37eaf2c43761b90ac391f2a5c9ba541224001db1..0aa57336c3f7582e61fb89fd492817c48e3b429a 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -402,7 +402,7 @@ static int pipe_server_flush( struct fd *fd, struct event **event )
 
         /* this kind of sux - 
            there's no unix way to be alerted when a pipe becomes empty */
-        server->event = create_event( NULL, 0, 0, 0 );
+        server->event = create_event( NULL, NULL, 0, 0, 0 );
         if (!server->event)
             return 0;
         gettimeofday( &tv, NULL );
diff --git a/server/object.h b/server/object.h
index c30c1378647c2e30d4f66decc779ab0bf7059f8f..d138729679a7e40c04400684d7a56c860efcc283 100644
--- a/server/object.h
+++ b/server/object.h
@@ -129,8 +129,8 @@ extern void dump_objects(void);
 
 struct event;
 
-extern struct event *create_event( const struct unicode_str *name, unsigned int attr,
-                                   int manual_reset, int initial_state );
+extern struct event *create_event( struct directory *root, const struct unicode_str *name,
+                                   unsigned int attr, int manual_reset, int initial_state );
 extern struct event *get_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
 extern void pulse_event( struct event *event );
 extern void set_event( struct event *event );
diff --git a/server/process.c b/server/process.c
index fab6761a3ea13c45b50a4481ff4b8ebc577f9e63..6e65da52d933304db7e11dc77ef86110144aa4b0 100644
--- a/server/process.c
+++ b/server/process.c
@@ -997,7 +997,7 @@ DECL_HANDLER(init_process_done)
     generate_startup_debug_events( process, req->entry );
     set_process_startup_state( process, STARTUP_DONE );
 
-    if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
+    if (req->gui) process->idle_event = create_event( NULL, NULL, 0, 1, 0 );
     if (current->suspend + process->suspend > 0) stop_thread( current );
     if (process->debugger) set_process_debug_flag( process, 1 );
 }
diff --git a/server/protocol.def b/server/protocol.def
index 91256e5ab0c36f24176dae80b7527a2ac4434f9b..934ae42c5737085819324c07c7699a86723a38f7 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -496,6 +496,7 @@ enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
 @REQ(create_event)
     unsigned int access;        /* wanted access rights */
     unsigned int attributes;    /* object attributes */
+    obj_handle_t rootdir;       /* root directory */
     int          manual_reset;  /* manual reset event */
     int          initial_state; /* initial state of the event */
     VARARG(name,unicode_str);   /* object name */
@@ -515,6 +516,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
 @REQ(open_event)
     unsigned int access;        /* wanted access rights */
     unsigned int attributes;    /* object attributes */
+    obj_handle_t rootdir;       /* root directory */
     VARARG(name,unicode_str);   /* object name */
 @REPLY
     obj_handle_t handle;        /* handle to the event */
@@ -525,6 +527,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
 @REQ(create_mutex)
     unsigned int access;        /* wanted access rights */
     unsigned int attributes;    /* object attributes */
+    obj_handle_t rootdir;       /* root directory */
     int          owned;         /* initially owned? */
     VARARG(name,unicode_str);   /* object name */
 @REPLY
@@ -544,6 +547,7 @@ enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT };
 @REQ(open_mutex)
     unsigned int access;        /* wanted access rights */
     unsigned int attributes;    /* object attributes */
+    obj_handle_t rootdir;       /* root directory */
     VARARG(name,unicode_str);   /* object name */
 @REPLY
     obj_handle_t handle;        /* handle to the mutex */
diff --git a/server/trace.c b/server/trace.c
index 2237e7c5f0a27c8ab0d1fa50b8d0f17ba5eba867..04c4bb40e397649aabd1fd223ed0c88089b49d75 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -893,6 +893,7 @@ static void dump_create_event_request( const struct create_event_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " rootdir=%p,", req->rootdir );
     fprintf( stderr, " manual_reset=%d,", req->manual_reset );
     fprintf( stderr, " initial_state=%d,", req->initial_state );
     fprintf( stderr, " name=" );
@@ -914,6 +915,7 @@ static void dump_open_event_request( const struct open_event_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " rootdir=%p,", req->rootdir );
     fprintf( stderr, " name=" );
     dump_varargs_unicode_str( cur_size );
 }
@@ -927,6 +929,7 @@ static void dump_create_mutex_request( const struct create_mutex_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " rootdir=%p,", req->rootdir );
     fprintf( stderr, " owned=%d,", req->owned );
     fprintf( stderr, " name=" );
     dump_varargs_unicode_str( cur_size );
@@ -951,6 +954,7 @@ static void dump_open_mutex_request( const struct open_mutex_request *req )
 {
     fprintf( stderr, " access=%08x,", req->access );
     fprintf( stderr, " attributes=%08x,", req->attributes );
+    fprintf( stderr, " rootdir=%p,", req->rootdir );
     fprintf( stderr, " name=" );
     dump_varargs_unicode_str( cur_size );
 }