diff --git a/dlls/kernel/kernel_private.h b/dlls/kernel/kernel_private.h index 73c3f22ae3b..3ed5f67a1a5 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 fafdc335eb4..659ee3035c6 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 7ed70605413..f5d85aec1d2 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 79bd6b66fcf..492033d31c0 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 fcbf8b0ab34..18188467bce 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 d13c7de4259..e567d60cbe8 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 bd73b886054..84438376103 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 0953f3f4007..9e3bdc342e4 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 37eaf2c4376..0aa57336c3f 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 c30c1378647..d138729679a 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 fab6761a3ea..6e65da52d93 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 91256e5ab0c..934ae42c573 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 2237e7c5f0a..04c4bb40e39 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 ); }