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