Named pipe patch 3 (supercedes 2)

Mike McCormack mike at codeweavers.com
Mon May 5 00:55:29 CDT 2003


Hi,

This patch gets us past sections 1 and 2 of Dan's pipe test program 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
* limit number of pipe servers to MaxInstances
* don't create incompatable pipe servers

-------------- next part --------------
Index: dlls/kernel/sync.c
===================================================================
RCS file: /home/wine/wine/dlls/kernel/sync.c,v
retrieving revision 1.27
diff -u -r1.27 sync.c
--- dlls/kernel/sync.c	19 Feb 2003 22:06:36 -0000	1.27
+++ dlls/kernel/sync.c	5 May 2003 05:52:28 -0000
@@ -508,6 +508,7 @@
 {
     HANDLE ret;
     DWORD len;
+    NTSTATUS status;
     static const WCHAR leadin[] = {'\\','\\','.','\\','P','I','P','E','\\'};
 
     TRACE("(%s, %#08lx, %#08lx, %ld, %ld, %ld, %ld, %p)\n",
@@ -540,10 +541,14 @@
         req->timeout = nDefaultTimeOut;
         wine_server_add_data( req, name, len * sizeof(WCHAR) );
         SetLastError(0);
-        wine_server_call_err( req );
-        ret = reply->handle;
+        status = wine_server_call_err( req );
+        if( !status )
+            ret = reply->handle;
+        else
+            ret = INVALID_HANDLE_VALUE;
     }
     SERVER_END_REQ;
+    if (status) SetLastError( RtlNtStatusToDosError(status) );
     return ret;
 }
 
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:52:28 -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;
@@ -80,6 +82,7 @@
     unsigned int        outsize;
     unsigned int        insize;
     unsigned int        timeout;
+    unsigned int        instances;
     struct pipe_user   *users;
 };
 
@@ -144,6 +147,7 @@
 {
     struct named_pipe *pipe = (struct named_pipe *)obj;
     assert( !pipe->users );
+    assert( !pipe->instances );
 }
 
 static void notify_waiter( struct pipe_user *user, unsigned int status)
@@ -163,8 +167,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;
 }
 
@@ -177,6 +195,20 @@
     if(user->overlapped)
         notify_waiter(user,STATUS_HANDLES_CLOSED);
 
+    assert( user->pipe->instances );
+
+    switch( user->state )
+    {
+    case ps_connected_server:
+    case ps_idle_server:
+    case ps_wait_open:
+    case ps_wait_disconnect:
+    case ps_disconnected_server:
+        user->pipe->instances--;
+    default:
+        break;
+    }
+
     if(user->other)
     {
         release_object( user->other->fd );
@@ -184,10 +216,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",
@@ -240,6 +272,7 @@
         {
             /* initialize it if it didn't already exist */
             pipe->users = 0;
+            pipe->instances = 0;
         }
     }
     return pipe;
@@ -326,14 +359,32 @@
         pipe->timeout = req->timeout;
         pipe->pipemode = req->pipemode;
     }
+    else
+    {
+        set_error( 0 );  /* clear the name collision */
+        if( pipe->maxinstances <= pipe->instances )
+        {
+            set_error( STATUS_PIPE_BUSY );
+            release_object( pipe );
+            return;
+        }
+        if( ( pipe->maxinstances != req->maxinstances ) ||
+            ( pipe->timeout != req->timeout ) ||
+            ( pipe->pipemode != req->pipemode ) )
+        {
+            set_error( STATUS_ACCESS_DENIED );
+            release_object( pipe );
+            return;
+        }
+    }
 
     user = create_pipe_user( pipe );
-
     if(user)
     {
         user->state = ps_idle_server;
         reply->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
         release_object( user );
+        user->pipe->instances++;
     }
 
     release_object( pipe );
@@ -343,43 +394,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 +452,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 +467,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 +523,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