Named pipe patch 2 (supercedes 1)

Mike McCormack mike at codeweavers.com
Mon May 5 00:09:59 CDT 2003


Hi,

This patch lets us make it all the way though the first part of Dan's 
test code at http://www.kegel.com/pipe.c

Mike


ChangeLog:
* allow pipe to be opened without the server calling ConnectNamedPipe
* distinguish between a newly opened pipe and a disconnected pipe

-------------- next part --------------
Index: server/named_pipe.c
===================================================================
RCS file: /home/wine/wine/server/named_pipe.c,v
retrieving revision 1.23
diff -u -r1.23 named_pipe.c
--- server/named_pipe.c	17 Apr 2003 02:14:04 -0000	1.23
+++ server/named_pipe.c	5 May 2003 05:05:43 -0000
@@ -53,7 +53,9 @@
     ps_wait_connect,
     ps_connected_server,
     ps_connected_client,
-    ps_disconnected
+    ps_wait_disconnect,
+    ps_disconnected_server,
+    ps_disconnected_client
 };
 
 struct named_pipe;
@@ -163,8 +165,22 @@
 static struct fd *pipe_user_get_fd( struct object *obj )
 {
     struct pipe_user *user = (struct pipe_user *)obj;
-    if (user->fd) return (struct fd *)grab_object( user->fd );
-    set_error( STATUS_PIPE_DISCONNECTED );
+    if (user->fd)
+    {
+        assert( (user->state == ps_connected_server ) ||
+                (user->state == ps_connected_client ) );
+        return (struct fd *)grab_object( user->fd );
+    }
+    switch(user->state)
+    {
+    case ps_wait_open:
+    case ps_idle_server:
+        set_error( STATUS_PIPE_LISTENING );
+        break;
+    case ps_disconnected_server:
+    default:
+        set_error( STATUS_PIPE_DISCONNECTED );
+    }
     return NULL;
 }
 
@@ -184,10 +200,10 @@
         switch(user->other->state)
         {
         case ps_connected_server:
-            user->other->state = ps_idle_server;
+            user->other->state = ps_wait_disconnect;
             break;
         case ps_connected_client:
-            user->other->state = ps_disconnected;
+            user->other->state = ps_disconnected_client;
             break;
         default:
             fprintf(stderr,"connected pipe has strange state %d!\n",
@@ -343,43 +359,53 @@
 {
     struct pipe_user *user, *partner;
     struct named_pipe *pipe;
+    int fds[2];
 
     reply->handle = 0;
 
-    if (!(pipe = open_named_pipe( get_req_data(), get_req_data_size() )))
+    pipe = open_named_pipe( get_req_data(), get_req_data_size() );
+    if ( !pipe )
     {
         set_error( STATUS_NO_SUCH_FILE );
         return;
     }
-    if (!(partner = find_partner(pipe, ps_wait_open)))
+
+    for( partner = pipe->users; partner; partner=partner->next)
+        if( (partner->state==ps_idle_server) ||
+            (partner->state==ps_disconnected_server) ||
+            (partner->state==ps_wait_open) )
+            break;
+
+    if ( !partner )
     {
         release_object(pipe);
         set_error( STATUS_PIPE_NOT_AVAILABLE );
         return;
     }
-    if ((user = create_pipe_user( pipe )))
+
+    if(0>socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
     {
-        int fds[2];
+        file_set_error();
+        return;
+    }
 
-        if(!socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
+    user = create_pipe_user( pipe );
+    if( user )
+    {
+        user->fd = create_anonymous_fd( &pipe_user_fd_ops, fds[1], &user->obj );
+        partner->fd = create_anonymous_fd( &pipe_user_fd_ops, fds[0], &partner->obj );
+        if (user->fd && partner->fd)
         {
-            user->fd = create_anonymous_fd( &pipe_user_fd_ops, fds[1], &user->obj );
-            partner->fd = create_anonymous_fd( &pipe_user_fd_ops, fds[0], &partner->obj );
-            if (user->fd && partner->fd)
-            {
-                notify_waiter(partner,STATUS_SUCCESS);
-                partner->state = ps_connected_server;
-                partner->other = user;
-                user->state = ps_connected_client;
-                user->other = partner;
-                reply->handle = alloc_handle( current->process, user, req->access, 0 );
-            }
+            notify_waiter(partner,STATUS_SUCCESS);
+            partner->state = ps_connected_server;
+            partner->other = user;
+            user->state = ps_connected_client;
+            user->other = partner;
+            reply->handle = alloc_handle( current->process, user, req->access, 0 );
         }
-        else file_set_error();
-
         release_object( user );
     }
-    release_object( partner );
+
     release_object( pipe );
 }
 
@@ -391,12 +417,10 @@
     if(!user)
         return;
 
-    if( user->state != ps_idle_server )
-    {
-        set_error(STATUS_PORT_ALREADY_SET);
-    }
-    else
+    switch( user->state )
     {
+    case ps_disconnected_server:
+    case ps_idle_server:
         user->state = ps_wait_open;
         user->thread = (struct thread *)grab_object(current);
         user->func = req->func;
@@ -408,6 +432,16 @@
             notify_waiter(partner,STATUS_SUCCESS);
             release_object(partner);
         }
+        break;
+    case ps_connected_server:
+        set_error( STATUS_PIPE_CONNECTED );
+        break;
+    case ps_wait_disconnect:
+        set_error( STATUS_NO_DATA_DETECTED );
+        break;
+    default:
+        set_error( STATUS_INVALID_HANDLE );
+        break;
     }
 
     release_object(user);
@@ -454,18 +488,30 @@
     user = get_pipe_user_obj(current->process, req->handle, 0);
     if(!user)
         return;
-    if( (user->state == ps_connected_server) &&
-        (user->other->state == ps_connected_client) )
+    switch( user->state )
     {
+    case ps_connected_server:
+        assert (user->other->state == ps_connected_client);
+        assert (user->fd);
+        assert (user->other->fd);
+
         release_object( user->other->fd );
         user->other->fd = NULL;
-        user->other->state = ps_disconnected;
+        user->other->state = ps_disconnected_client;
         user->other->other = NULL;
 
         release_object( user->fd );
         user->fd = NULL;
-        user->state = ps_idle_server;
+        user->state = ps_disconnected_server;
         user->other = NULL;
+        break;
+    case ps_wait_disconnect:
+        assert (!user->fd);
+        assert (!user->other);
+        user->state = ps_disconnected_server;
+        break;
+    default:
+        set_error( STATUS_PIPE_DISCONNECTED );
     }
     release_object(user);
 }


More information about the wine-patches mailing list