Move mailslot devices into directory name space.

Vitaliy Margolen wine-patch at kievinfo.com
Fri Dec 2 14:09:22 CST 2005


ChangeLog:
Move mailslot devices into directory name space.

 dlls/ntdll/file.c   |   20 +++---
 server/directory.c  |    3 +
 server/mailslot.c   |  167 +++++++++++++++++++++++++++++++++++++++++----------
 server/object.h     |    1 
 server/protocol.def |    2 +
 5 files changed, 151 insertions(+), 42 deletions(-)
-------------- next part --------------
c6bc057e89b8fc5e382053267c379d7dc5b0a65c
diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c
index 6b6df2c..21838bc 100644
--- a/dlls/ntdll/file.c
+++ b/dlls/ntdll/file.c
@@ -173,11 +173,6 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
         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) &&
@@ -187,9 +182,10 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
         {
             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;
         }
@@ -197,6 +193,11 @@ NTSTATUS WINAPI NtCreateFile( PHANDLE ha
         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) );
 
@@ -2064,10 +2065,11 @@ NTSTATUS WINAPI NtCreateMailslotFile(PHA
     {
         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/server/directory.c b/server/directory.c
index e7c392e..bf860b3 100644
--- a/server/directory.c
+++ b/server/directory.c
@@ -301,6 +301,7 @@ obj_handle_t open_object_dir( struct dir
 static struct directory *dir_driver, *dir_device;
 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)
 {
@@ -340,6 +341,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 );
@@ -350,6 +352,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 2c04fe2..979b0bb 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_f
     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,20 +242,103 @@ static void mailslot_queue_async( struct
     fd_queue_async_timeout( fd, apc, user, iosb, type, count, timeout );
 }
 
-static struct mailslot *create_mailslot( const struct unicode_str *name, unsigned int attr,
-                                         int max_msgsize, int read_timeout )
+static void mailslot_device_dump( struct object *obj, int verbose )
 {
-    struct mailslot *mailslot;
-    int fds[2];
-    static const WCHAR slot[] = {'m','a','i','l','s','l','o','t','\\'};
+    assert( obj->ops == &mailslot_device_ops );
+    fprintf( stderr, "Mail slot device\n" );
+}
 
-    if ((name->len <= sizeof(slot)) || strncmpiW( slot, name->str, sizeof(slot)/sizeof(WCHAR) ))
+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 );
+    assert( device->mailslots );
+
+    if (!name || !name->len) return NULL;
+
+    if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE )))
     {
-        set_error( STATUS_OBJECT_NAME_INVALID );
-        return NULL;
+        name->str = NULL;
+        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 );
+}
 
-    mailslot = create_named_object( sync_namespace, &mailslot_ops, name, attr );
+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_helper( struct directory *root,
+                const struct unicode_str *name, unsigned int attr )
+{
+    struct object *obj;
+    struct mailslot *mailslot = NULL;
+    struct unicode_str new_name;
+
+    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)
+    {
+        if (attr & OBJ_OPENIF && obj->ops == &mailslot_ops)
+            set_error( STATUS_OBJECT_NAME_EXISTS );
+        else
+        {
+            release_object( obj );
+            obj = NULL;
+            if (attr & OBJ_OPENIF)
+                set_error( STATUS_OBJECT_TYPE_MISMATCH );
+            else
+                set_error( STATUS_OBJECT_NAME_COLLISION );
+        }
+        return (struct mailslot *)obj;
+    }
+
+    if (obj->ops != &mailslot_device_ops)
+        set_error( STATUS_OBJECT_TYPE_MISMATCH );
+    else
+    {
+        struct mailslot_device *dev = (struct mailslot_device *)obj;
+        if ((mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL )))
+            clear_error();
+    }
+
+    release_object( obj );
+    return mailslot;
+}
+
+static struct mailslot *create_mailslot( struct directory *root,
+                const struct unicode_str *name, unsigned int attr,
+                int max_msgsize, int read_timeout )
+{
+    struct mailslot *mailslot;
+    int fds[2];
+
+    mailslot = create_mailslot_helper( root, name, attr );
     if (!mailslot)
         return NULL;
 
@@ -262,24 +371,6 @@ static struct mailslot *create_mailslot(
     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 +434,7 @@ static struct mail_writer *create_mail_w
 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 +443,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 +467,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 +478,12 @@ 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 = (struct mailslot*)reference_by_name( 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 ade820e..298160c 100644
--- a/server/object.h
+++ b/server/object.h
@@ -202,6 +202,7 @@ extern struct symlink *create_symlink( s
 
 /* 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 905e0ff..dc302b0 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


More information about the wine-patches mailing list