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
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); }