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