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