diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 606b39f9c55..660ba1bd1c3 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -173,12 +173,6 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB return io->u.Status; } - if (attr->RootDirectory) - { - FIXME( "RootDirectory %p not supported\n", attr->RootDirectory ); - return STATUS_OBJECT_NAME_NOT_FOUND; - } - /* check for mailslot */ if (attr->ObjectName->Length > sizeof(mailslotW) && @@ -188,9 +182,10 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB { req->access = access & GENERIC_WRITE; req->attributes = (attr) ? attr->Attributes : 0; + req->rootdir = attr ? attr->RootDirectory : 0; req->sharing = sharing; - wine_server_add_data( req, attr->ObjectName->Buffer + 4, - attr->ObjectName->Length - 4*sizeof(WCHAR) ); + wine_server_add_data( req, attr->ObjectName->Buffer, + attr->ObjectName->Length ); io->u.Status = wine_server_call( req ); *handle = reply->handle; } @@ -198,6 +193,12 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE handle, ACCESS_MASK access, POBJECT_ATTRIB return io->u.Status; } + if (attr->RootDirectory) + { + FIXME( "RootDirectory %p not supported\n", attr->RootDirectory ); + return STATUS_OBJECT_NAME_NOT_FOUND; + } + io->u.Status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, disposition, !(attr->Attributes & OBJ_CASE_INSENSITIVE) ); @@ -2065,10 +2066,11 @@ NTSTATUS WINAPI NtCreateMailslotFile(PHANDLE pHandle, ULONG DesiredAccess, { req->access = DesiredAccess; req->attributes = (attr) ? attr->Attributes : 0; + req->rootdir = attr ? attr->RootDirectory : 0; req->max_msgsize = MaxMessageSize; req->read_timeout = (TimeOut->QuadPart <= 0) ? TimeOut->QuadPart / -10000 : -1; - wine_server_add_data( req, attr->ObjectName->Buffer + 4, - attr->ObjectName->Length - 4*sizeof(WCHAR) ); + wine_server_add_data( req, attr->ObjectName->Buffer, + attr->ObjectName->Length ); ret = wine_server_call( req ); if( ret == STATUS_SUCCESS ) *pHandle = reply->handle; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 429fcdf1ab4..b81cc6cc6df 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3543,6 +3543,7 @@ struct create_mailslot_request struct request_header __header; unsigned int access; unsigned int attributes; + obj_handle_t rootdir; unsigned int max_msgsize; int read_timeout; /* VARARG(name,unicode_str); */ @@ -3560,6 +3561,7 @@ struct open_mailslot_request struct request_header __header; unsigned int access; unsigned int attributes; + obj_handle_t rootdir; unsigned int sharing; /* VARARG(name,unicode_str); */ }; @@ -4314,6 +4316,6 @@ union generic_reply struct query_symlink_reply query_symlink_reply; }; -#define SERVER_PROTOCOL_VERSION 206 +#define SERVER_PROTOCOL_VERSION 207 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/directory.c b/server/directory.c index e8088a42454..14ed4ccf859 100644 --- a/server/directory.c +++ b/server/directory.c @@ -286,6 +286,7 @@ void *open_object_dir( struct directory *root, const struct unicode_str *name, static struct directory *dir_driver; static struct symlink *link_dosdev, *link_global1, *link_global2, *link_local; static struct named_pipe_device *dev_named_pipe; +static struct mailslot_device *dev_mailslot; void init_directories(void) { @@ -325,6 +326,7 @@ void init_directories(void) /* devices */ dev_named_pipe = create_named_pipe_device(); + dev_mailslot = create_mailslot_device(); /* the symlinks or devices hold references so we can release these */ release_object( dir_device ); @@ -335,6 +337,7 @@ void init_directories(void) void close_directories(void) { release_object( dev_named_pipe ); + release_object( dev_mailslot ); release_object( link_dosdev ); release_object( link_global1 ); diff --git a/server/mailslot.c b/server/mailslot.c index 2c04fe2b895..7d2d0b00d56 100644 --- a/server/mailslot.c +++ b/server/mailslot.c @@ -62,6 +62,12 @@ struct mailslot struct list writers; }; +struct mailslot_device +{ + struct object obj; /* object header */ + struct namespace *mailslots; /* mailslot namespace */ +}; + /* mailslot functions */ static void mailslot_dump( struct object*, int ); static struct fd *mailslot_get_fd( struct object * ); @@ -135,6 +141,26 @@ static const struct fd_ops mail_writer_fd_ops = NULL /* cancel_async */ }; +static void mailslot_device_dump( struct object *obj, int verbose ); +static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr ); +static void mailslot_device_destroy( struct object *obj ); + +static const struct object_ops mailslot_device_ops = +{ + sizeof(struct mailslot_device), /* size */ + mailslot_device_dump, /* dump */ + no_add_queue, /* add_queue */ + NULL, /* remove_queue */ + NULL, /* signaled */ + no_satisfied, /* satisfied */ + no_signal, /* signal */ + no_get_fd, /* get_fd */ + mailslot_device_lookup_name, /* lookup_name */ + no_close_handle, /* close_handle */ + mailslot_device_destroy /* destroy */ +}; + static void mailslot_destroy( struct object *obj) { struct mailslot *mailslot = (struct mailslot *) obj; @@ -216,30 +242,91 @@ static void mailslot_queue_async( struct fd *fd, void *apc, void *user, fd_queue_async_timeout( fd, apc, user, iosb, type, count, timeout ); } -static struct mailslot *create_mailslot( const struct unicode_str *name, unsigned int attr, +static void mailslot_device_dump( struct object *obj, int verbose ) +{ + assert( obj->ops == &mailslot_device_ops ); + fprintf( stderr, "Mail slot device\n" ); +} + +static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name, + unsigned int attr ) +{ + struct mailslot_device *device = (struct mailslot_device*)obj; + struct object *found; + + assert( obj->ops == &mailslot_device_ops ); + + if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE ))) + name->len = 0; + + return found; +} + +static void mailslot_device_destroy( struct object *obj ) +{ + struct mailslot_device *device = (struct mailslot_device*)obj; + assert( obj->ops == &mailslot_device_ops ); + free( device->mailslots ); +} + +struct mailslot_device *create_mailslot_device( void ) +{ + static const WCHAR mailslotW[] = {'\\','?','?','\\','M','A','I','L','S','L','O','T'}; + static struct unicode_str mailslot = {mailslotW, sizeof(mailslotW)}; + struct mailslot_device *dev; + + if ((dev = create_named_object_dir( NULL, &mailslot, 0, &mailslot_device_ops )) && + get_error() != STATUS_OBJECT_NAME_EXISTS) + { + if (!(dev->mailslots = create_namespace( 7 ))) + { + release_object( dev ); + dev = NULL; + } + } + return dev; +} + +static struct mailslot *create_mailslot( struct directory *root, + const struct unicode_str *name, unsigned int attr, int max_msgsize, int read_timeout ) { + struct object *obj; + struct unicode_str new_name; + struct mailslot_device *dev; struct mailslot *mailslot; int fds[2]; - static const WCHAR slot[] = {'m','a','i','l','s','l','o','t','\\'}; - if ((name->len <= sizeof(slot)) || strncmpiW( slot, name->str, sizeof(slot)/sizeof(WCHAR) )) + if (!name || !name->len) return alloc_object( &mailslot_ops ); + + if (!(obj = find_object_dir( root, name, attr, &new_name ))) return NULL; + + if (!new_name.len) { - set_error( STATUS_OBJECT_NAME_INVALID ); + if (attr & OBJ_OPENIF && obj->ops == &mailslot_ops) + /* it already exists - there can only be one mailslot to read from */ + set_error( STATUS_OBJECT_NAME_EXISTS ); + else if (attr & OBJ_OPENIF) + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + else + set_error( STATUS_OBJECT_NAME_COLLISION ); + release_object( obj ); return NULL; } - mailslot = create_named_object( sync_namespace, &mailslot_ops, name, attr ); - if (!mailslot) - return NULL; - - /* it already exists - there can only be one mailslot to read from */ - if (get_error() == STATUS_OBJECT_NAME_EXISTS) + if (obj->ops != &mailslot_device_ops) { - release_object( mailslot ); + set_error( STATUS_OBJECT_TYPE_MISMATCH ); + release_object( obj ); return NULL; } + dev = (struct mailslot_device *)obj; + mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL ); + release_object( dev ); + + if (!mailslot) return NULL; + mailslot->fd = NULL; mailslot->write_fd = NULL; mailslot->max_msgsize = max_msgsize; @@ -262,24 +349,6 @@ static struct mailslot *create_mailslot( const struct unicode_str *name, unsigne return NULL; } -static struct mailslot *open_mailslot( const struct unicode_str *name, unsigned int attr ) -{ - struct object *obj; - - obj = find_object( sync_namespace, name, attr ); - if (obj) - { - if (obj->ops == &mailslot_ops) - return (struct mailslot *)obj; - release_object( obj ); - set_error( STATUS_OBJECT_TYPE_MISMATCH ); - } - else - set_error( STATUS_OBJECT_NAME_NOT_FOUND ); - - return NULL; -} - static void mail_writer_dump( struct object *obj, int verbose ) { fprintf( stderr, "Mailslot writer\n" ); @@ -343,9 +412,7 @@ static struct mail_writer *create_mail_writer( struct mailslot *mailslot, unsign static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle, unsigned int access ) { - struct object *obj; - obj = get_handle_obj( process, handle, access, &mailslot_ops ); - return (struct mailslot *) obj; + return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops ); } @@ -354,16 +421,22 @@ DECL_HANDLER(create_mailslot) { struct mailslot *mailslot; struct unicode_str name; + struct directory *root = NULL; reply->handle = 0; get_req_unicode_str( &name ); - mailslot = create_mailslot( &name, req->attributes, req->max_msgsize, req->read_timeout ); - if (mailslot) + if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) + return; + + if ((mailslot = create_mailslot( root, &name, req->attributes, req->max_msgsize, + req->read_timeout ))) { reply->handle = alloc_handle( current->process, mailslot, req->access, req->attributes & OBJ_INHERIT ); release_object( mailslot ); } + + if (root) release_object( root ); } @@ -372,6 +445,7 @@ DECL_HANDLER(open_mailslot) { struct mailslot *mailslot; struct unicode_str name; + struct directory *root = NULL; reply->handle = 0; get_req_unicode_str( &name ); @@ -382,7 +456,11 @@ DECL_HANDLER(open_mailslot) return; } - mailslot = open_mailslot( &name, req->attributes ); + if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 ))) + return; + mailslot = open_object_dir( root, &name, req->attributes, &mailslot_ops ); + if (root) release_object( root ); + if (mailslot) { struct mail_writer *writer; diff --git a/server/object.h b/server/object.h index 66cd357f57c..06ce443eb06 100644 --- a/server/object.h +++ b/server/object.h @@ -199,6 +199,7 @@ extern struct symlink *create_symlink( struct directory *root, const struct unic /* devices */ extern struct named_pipe_device *create_named_pipe_device( void ); +extern struct mailslot_device *create_mailslot_device( void ); /* global variables */ diff --git a/server/protocol.def b/server/protocol.def index 905e0ff82ec..dc302b03ffa 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2486,6 +2486,7 @@ enum message_type @REQ(create_mailslot) unsigned int access; /* wanted access rights */ unsigned int attributes; /* object attributes */ + obj_handle_t rootdir; /* root directory */ unsigned int max_msgsize; int read_timeout; VARARG(name,unicode_str); /* mailslot name */ @@ -2498,6 +2499,7 @@ enum message_type @REQ(open_mailslot) unsigned int access; unsigned int attributes; /* object attributes */ + obj_handle_t rootdir; /* root directory */ unsigned int sharing; /* sharing mode */ VARARG(name,unicode_str); /* mailslot name */ @REPLY diff --git a/server/trace.c b/server/trace.c index 3618f6ed7dc..53199122619 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3065,6 +3065,7 @@ static void dump_create_mailslot_request( const struct create_mailslot_request * { fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " attributes=%08x,", req->attributes ); + fprintf( stderr, " rootdir=%p,", req->rootdir ); fprintf( stderr, " max_msgsize=%08x,", req->max_msgsize ); fprintf( stderr, " read_timeout=%d,", req->read_timeout ); fprintf( stderr, " name=" ); @@ -3080,6 +3081,7 @@ static void dump_open_mailslot_request( const struct open_mailslot_request *req { fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " attributes=%08x,", req->attributes ); + fprintf( stderr, " rootdir=%p,", req->rootdir ); fprintf( stderr, " sharing=%08x,", req->sharing ); fprintf( stderr, " name=" ); dump_varargs_unicode_str( cur_size );