Implement WaitNamedPipe and DisconnectNamedPipe.
Add a state for each pipe handle in the server. Create a socket on when the pipe is opened, not before.
This commit is contained in:
parent
c86517fcb6
commit
bf55457f24
|
@ -605,24 +605,73 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* WaitNamedPipeA (KERNEL32.@)
|
* WaitNamedPipeA (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI WaitNamedPipeA (LPCSTR lpNamedPipeName, DWORD nTimeOut)
|
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
|
||||||
{
|
{
|
||||||
FIXME("%s 0x%08lx\n",lpNamedPipeName,nTimeOut);
|
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
|
||||||
SetLastError(ERROR_PIPE_NOT_CONNECTED);
|
HANDLE event;
|
||||||
return FALSE;
|
BOOL ret;
|
||||||
|
|
||||||
|
TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
|
||||||
|
|
||||||
|
if (len >= MAX_PATH)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(event = CreateEventA( NULL, 0, 0, NULL ))) return FALSE;
|
||||||
|
|
||||||
|
SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
|
||||||
|
{
|
||||||
|
req->timeout = nTimeOut;
|
||||||
|
req->event = event;
|
||||||
|
if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
if (ret) WaitForSingleObject(event,INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(event);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* WaitNamedPipeW (KERNEL32.@)
|
* WaitNamedPipeW (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI WaitNamedPipeW (LPCWSTR lpNamedPipeName, DWORD nTimeOut)
|
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
|
||||||
{
|
{
|
||||||
FIXME("%s 0x%08lx\n",debugstr_w(lpNamedPipeName),nTimeOut);
|
DWORD len = name ? strlenW(name) : 0;
|
||||||
SetLastError(ERROR_PIPE_NOT_CONNECTED);
|
HANDLE event;
|
||||||
return FALSE;
|
BOOL ret;
|
||||||
|
|
||||||
|
TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
|
||||||
|
|
||||||
|
if (len >= MAX_PATH)
|
||||||
|
{
|
||||||
|
SetLastError( ERROR_FILENAME_EXCED_RANGE );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(event = CreateEventA( NULL, 0, 0, NULL ))) return FALSE;
|
||||||
|
|
||||||
|
SERVER_START_VAR_REQ( wait_named_pipe, len * sizeof(WCHAR) )
|
||||||
|
{
|
||||||
|
req->timeout = nTimeOut;
|
||||||
|
req->event = event;
|
||||||
|
memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
if (ret) WaitForSingleObject(event,INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(event);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* ConnectNamedPipe (KERNEL32.@)
|
* ConnectNamedPipe (KERNEL32.@)
|
||||||
*/
|
*/
|
||||||
|
@ -631,7 +680,7 @@ BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
|
|
||||||
TRACE("(%d,%p):stub\n",hPipe, overlapped);
|
TRACE("(%d,%p)\n",hPipe, overlapped);
|
||||||
|
|
||||||
if(overlapped)
|
if(overlapped)
|
||||||
{
|
{
|
||||||
|
@ -640,29 +689,20 @@ BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
event = CreateEventA(NULL,0,0,NULL);
|
if (!(event = CreateEventA(NULL,0,0,NULL))) return FALSE;
|
||||||
if(event==INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
ERR("create event failed!\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SERVER_START_REQ( connect_named_pipe )
|
SERVER_START_REQ( connect_named_pipe )
|
||||||
{
|
{
|
||||||
req->handle = hPipe;
|
req->handle = hPipe;
|
||||||
req->event = event;
|
req->event = event;
|
||||||
ret = SERVER_CALL_ERR();
|
ret = !SERVER_CALL_ERR();
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
|
||||||
if(ret) {
|
if (ret) WaitForSingleObject(event,INFINITE);
|
||||||
ERR("server returned status %08lx\n",GetLastError());
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
WaitForSingleObject(event,INFINITE);
|
CloseHandle(event);
|
||||||
|
return ret;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
@ -670,8 +710,17 @@ BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
|
BOOL WINAPI DisconnectNamedPipe(HANDLE hPipe)
|
||||||
{
|
{
|
||||||
FIXME("(%d):stub\n",hPipe);
|
BOOL ret;
|
||||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
||||||
return FALSE;
|
TRACE("(%d)\n",hPipe);
|
||||||
|
|
||||||
|
SERVER_START_REQ( disconnect_named_pipe )
|
||||||
|
{
|
||||||
|
req->handle = hPipe;
|
||||||
|
ret = !SERVER_CALL_ERR();
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1532,6 +1532,24 @@ struct connect_named_pipe_request
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct wait_named_pipe_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
unsigned int timeout;
|
||||||
|
handle_t event;
|
||||||
|
/* VARARG(filename,string); */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct disconnect_named_pipe_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
handle_t handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enum request
|
enum request
|
||||||
{
|
{
|
||||||
REQ_new_process,
|
REQ_new_process,
|
||||||
|
@ -1654,6 +1672,8 @@ enum request
|
||||||
REQ_create_named_pipe,
|
REQ_create_named_pipe,
|
||||||
REQ_open_named_pipe,
|
REQ_open_named_pipe,
|
||||||
REQ_connect_named_pipe,
|
REQ_connect_named_pipe,
|
||||||
|
REQ_wait_named_pipe,
|
||||||
|
REQ_disconnect_named_pipe,
|
||||||
REQ_NB_REQUESTS
|
REQ_NB_REQUESTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1781,8 +1801,10 @@ union generic_request
|
||||||
struct create_named_pipe_request create_named_pipe;
|
struct create_named_pipe_request create_named_pipe;
|
||||||
struct open_named_pipe_request open_named_pipe;
|
struct open_named_pipe_request open_named_pipe;
|
||||||
struct connect_named_pipe_request connect_named_pipe;
|
struct connect_named_pipe_request connect_named_pipe;
|
||||||
|
struct wait_named_pipe_request wait_named_pipe;
|
||||||
|
struct disconnect_named_pipe_request disconnect_named_pipe;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 49
|
#define SERVER_PROTOCOL_VERSION 50
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
* Server-side pipe management
|
* Server-side pipe management
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 Alexandre Julliard
|
* Copyright (C) 1998 Alexandre Julliard
|
||||||
|
* Copyright (C) 2001 Mike McCormack
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* improve error handling
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -23,12 +27,24 @@
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
|
|
||||||
|
enum pipe_state
|
||||||
|
{
|
||||||
|
ps_none,
|
||||||
|
ps_idle_server,
|
||||||
|
ps_wait_open,
|
||||||
|
ps_wait_connect,
|
||||||
|
ps_connected_server,
|
||||||
|
ps_connected_client,
|
||||||
|
ps_disconnected
|
||||||
|
};
|
||||||
|
|
||||||
struct named_pipe;
|
struct named_pipe;
|
||||||
|
|
||||||
struct pipe_user
|
struct pipe_user
|
||||||
{
|
{
|
||||||
struct object obj;
|
struct object obj;
|
||||||
int other_fd;
|
enum pipe_state state;
|
||||||
|
struct pipe_user *other;
|
||||||
struct named_pipe *pipe;
|
struct named_pipe *pipe;
|
||||||
struct pipe_user *next;
|
struct pipe_user *next;
|
||||||
struct pipe_user *prev;
|
struct pipe_user *prev;
|
||||||
|
@ -96,8 +112,7 @@ static void pipe_user_dump( struct object *obj, int verbose )
|
||||||
{
|
{
|
||||||
struct pipe_user *user = (struct pipe_user *)obj;
|
struct pipe_user *user = (struct pipe_user *)obj;
|
||||||
assert( obj->ops == &pipe_user_ops );
|
assert( obj->ops == &pipe_user_ops );
|
||||||
fprintf( stderr, "named pipe user %p (%s)\n", user,
|
fprintf( stderr, "named pipe user %p (state %d)\n", user, user->state );
|
||||||
(user->other_fd != -1) ? "server" : "client" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void named_pipe_destroy( struct object *obj)
|
static void named_pipe_destroy( struct object *obj)
|
||||||
|
@ -118,6 +133,25 @@ static void pipe_user_destroy( struct object *obj)
|
||||||
release_object(user->event);
|
release_object(user->event);
|
||||||
user->event = NULL;
|
user->event = NULL;
|
||||||
}
|
}
|
||||||
|
if(user->other)
|
||||||
|
{
|
||||||
|
close(user->other->obj.fd);
|
||||||
|
user->other->obj.fd = -1;
|
||||||
|
switch(user->other->state)
|
||||||
|
{
|
||||||
|
case ps_connected_server:
|
||||||
|
user->other->state = ps_idle_server;
|
||||||
|
break;
|
||||||
|
case ps_connected_client:
|
||||||
|
user->other->state = ps_disconnected;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"connected pipe has strange state %d!\n",
|
||||||
|
user->other->state);
|
||||||
|
}
|
||||||
|
user->other->other=NULL;
|
||||||
|
user->other = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* remove user from pipe's user list */
|
/* remove user from pipe's user list */
|
||||||
if (user->next) user->next->prev = user->prev;
|
if (user->next) user->next->prev = user->prev;
|
||||||
|
@ -157,29 +191,15 @@ static struct pipe_user *get_pipe_user_obj( struct process *process, handle_t ha
|
||||||
static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd )
|
static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd )
|
||||||
{
|
{
|
||||||
struct pipe_user *user;
|
struct pipe_user *user;
|
||||||
int fds[2];
|
|
||||||
|
|
||||||
if(fd == -1)
|
user = alloc_object( &pipe_user_ops, fd );
|
||||||
{
|
|
||||||
/* FIXME: what about messages? */
|
|
||||||
|
|
||||||
if(0>socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) goto error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((fds[0] = dup(fd)) == -1) goto error;
|
|
||||||
fds[1] = -1;
|
|
||||||
}
|
|
||||||
user = alloc_object( &pipe_user_ops, fds[0] );
|
|
||||||
if(!user)
|
if(!user)
|
||||||
{
|
|
||||||
if (fds[1] != -1) close( fds[1] );
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
user->pipe = pipe;
|
user->pipe = pipe;
|
||||||
user->other_fd = fds[1];
|
user->state = ps_none;
|
||||||
user->event = NULL; /* thread wait on this pipe */
|
user->event = NULL; /* thread wait on this pipe */
|
||||||
|
user->other = NULL;
|
||||||
|
|
||||||
/* add to list of pipe users */
|
/* add to list of pipe users */
|
||||||
if ((user->next = pipe->users)) user->next->prev = user;
|
if ((user->next = pipe->users)) user->next->prev = user;
|
||||||
|
@ -189,29 +209,21 @@ static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd )
|
||||||
grab_object(pipe);
|
grab_object(pipe);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
|
|
||||||
error:
|
|
||||||
file_set_error();
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pipe_user *find_partner(struct named_pipe *pipe)
|
static struct pipe_user *find_partner(struct named_pipe *pipe, enum pipe_state state)
|
||||||
{
|
{
|
||||||
struct pipe_user *x;
|
struct pipe_user *x;
|
||||||
|
|
||||||
for(x = pipe->users; x; x=x->next)
|
for(x = pipe->users; x; x=x->next)
|
||||||
{
|
{
|
||||||
/* only pair threads that are waiting */
|
if(x->state==state)
|
||||||
if(!x->event)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* only pair with pipes that haven't been connected */
|
|
||||||
if(x->other_fd == -1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!x)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return (struct pipe_user *)grab_object( x );
|
return (struct pipe_user *)grab_object( x );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +241,7 @@ DECL_HANDLER(create_named_pipe)
|
||||||
|
|
||||||
if(user)
|
if(user)
|
||||||
{
|
{
|
||||||
|
user->state = ps_idle_server;
|
||||||
req->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
|
req->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 );
|
||||||
release_object( user );
|
release_object( user );
|
||||||
}
|
}
|
||||||
|
@ -239,7 +252,6 @@ DECL_HANDLER(create_named_pipe)
|
||||||
DECL_HANDLER(open_named_pipe)
|
DECL_HANDLER(open_named_pipe)
|
||||||
{
|
{
|
||||||
struct named_pipe *pipe;
|
struct named_pipe *pipe;
|
||||||
struct pipe_user *user,*partner;
|
|
||||||
|
|
||||||
req->handle = 0;
|
req->handle = 0;
|
||||||
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
||||||
|
@ -248,26 +260,43 @@ DECL_HANDLER(open_named_pipe)
|
||||||
|
|
||||||
if (get_error() == STATUS_OBJECT_NAME_COLLISION)
|
if (get_error() == STATUS_OBJECT_NAME_COLLISION)
|
||||||
{
|
{
|
||||||
if ((partner = find_partner(pipe)))
|
struct pipe_user *partner;
|
||||||
|
|
||||||
|
if ((partner = find_partner(pipe, ps_wait_open)))
|
||||||
{
|
{
|
||||||
user = create_pipe_user (pipe, partner->other_fd);
|
int fds[2];
|
||||||
if(user)
|
|
||||||
|
if(!socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
|
||||||
{
|
{
|
||||||
set_event(partner->event);
|
struct pipe_user *user;
|
||||||
release_object(partner->event);
|
|
||||||
partner->event = NULL;
|
if( (user = create_pipe_user (pipe, fds[1])) )
|
||||||
close( partner->other_fd );
|
{
|
||||||
partner->other_fd = -1;
|
partner->obj.fd = fds[0];
|
||||||
req->handle = alloc_handle( current->process, user, req->access, 0 );
|
set_event(partner->event);
|
||||||
release_object(user);
|
release_object(partner->event);
|
||||||
|
partner->event = NULL;
|
||||||
|
partner->state = ps_connected_server;
|
||||||
|
partner->other = user;
|
||||||
|
user->state = ps_connected_client;
|
||||||
|
user->other = partner;
|
||||||
|
req->handle = alloc_handle( current->process, user, req->access, 0 );
|
||||||
|
release_object(user);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fds[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
release_object( partner );
|
release_object( partner );
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
set_error(STATUS_PIPE_NOT_AVAILABLE);
|
set_error(STATUS_PIPE_NOT_AVAILABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
set_error(STATUS_NO_SUCH_FILE);
|
set_error(STATUS_NO_SUCH_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,24 +305,101 @@ DECL_HANDLER(open_named_pipe)
|
||||||
|
|
||||||
DECL_HANDLER(connect_named_pipe)
|
DECL_HANDLER(connect_named_pipe)
|
||||||
{
|
{
|
||||||
struct pipe_user *user;
|
struct pipe_user *user, *partner;
|
||||||
struct event *event;
|
struct event *event;
|
||||||
|
|
||||||
user = get_pipe_user_obj(current->process, req->handle, 0);
|
user = get_pipe_user_obj(current->process, req->handle, 0);
|
||||||
if(!user)
|
if(!user)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( user->event || user->other_fd == -1)
|
if( user->state != ps_idle_server )
|
||||||
{
|
{
|
||||||
/* fprintf(stderr,"fd = %x event = %p\n",user->obj.fd,user->event);*/
|
|
||||||
set_error(STATUS_PORT_ALREADY_SET);
|
set_error(STATUS_PORT_ALREADY_SET);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
user->state = ps_wait_open;
|
||||||
event = get_event_obj(current->process, req->event, 0);
|
event = get_event_obj(current->process, req->event, 0);
|
||||||
if(event)
|
if(event)
|
||||||
user->event = event;
|
user->event = event;
|
||||||
|
|
||||||
|
/* notify all waiters that a pipe just became available */
|
||||||
|
while( (partner = find_partner(user->pipe,ps_wait_connect)) )
|
||||||
|
{
|
||||||
|
set_event(partner->event);
|
||||||
|
release_object(partner->event);
|
||||||
|
partner->event = NULL;
|
||||||
|
release_object(partner);
|
||||||
|
release_object(partner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release_object(user);
|
release_object(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DECL_HANDLER(wait_named_pipe)
|
||||||
|
{
|
||||||
|
struct event *event;
|
||||||
|
struct named_pipe *pipe;
|
||||||
|
|
||||||
|
event = get_event_obj(current->process, req->event, 0);
|
||||||
|
if(!event)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pipe = create_named_pipe( get_req_data(req), get_req_data_size(req) );
|
||||||
|
if( pipe )
|
||||||
|
{
|
||||||
|
/* only wait if the pipe already exists */
|
||||||
|
if(get_error() == STATUS_OBJECT_NAME_COLLISION)
|
||||||
|
{
|
||||||
|
struct pipe_user *partner;
|
||||||
|
|
||||||
|
set_error(STATUS_SUCCESS);
|
||||||
|
if( (partner = find_partner(pipe,ps_wait_open)) )
|
||||||
|
{
|
||||||
|
set_event(event);
|
||||||
|
release_object(partner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct pipe_user *user;
|
||||||
|
|
||||||
|
if( (user = create_pipe_user (pipe, -1)) )
|
||||||
|
{
|
||||||
|
user->event = (struct event *)grab_object( event );
|
||||||
|
user->state = ps_wait_connect;
|
||||||
|
/* don't release it */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_error(STATUS_PIPE_NOT_AVAILABLE);
|
||||||
|
}
|
||||||
|
release_object(pipe);
|
||||||
|
}
|
||||||
|
release_object(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_HANDLER(disconnect_named_pipe)
|
||||||
|
{
|
||||||
|
struct pipe_user *user;
|
||||||
|
|
||||||
|
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) )
|
||||||
|
{
|
||||||
|
close(user->other->obj.fd);
|
||||||
|
user->other->obj.fd = -1;
|
||||||
|
user->other->state = ps_disconnected;
|
||||||
|
user->other->other = NULL;
|
||||||
|
|
||||||
|
close(user->obj.fd);
|
||||||
|
user->obj.fd = -1;
|
||||||
|
user->state = ps_idle_server;
|
||||||
|
user->other = NULL;
|
||||||
|
}
|
||||||
|
release_object(user);
|
||||||
|
}
|
||||||
|
|
|
@ -1368,3 +1368,17 @@ enum message_type
|
||||||
handle_t handle;
|
handle_t handle;
|
||||||
handle_t event; /* set this event when it's ready */
|
handle_t event; /* set this event when it's ready */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* Wait for a named pipe */
|
||||||
|
@REQ(wait_named_pipe)
|
||||||
|
unsigned int timeout;
|
||||||
|
handle_t event; /* set this event when it's ready */
|
||||||
|
VARARG(filename,string); /* pipe name */
|
||||||
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* Disconnect a named pipe */
|
||||||
|
@REQ(disconnect_named_pipe)
|
||||||
|
handle_t handle;
|
||||||
|
@END
|
||||||
|
|
|
@ -185,6 +185,8 @@ DECL_HANDLER(create_async);
|
||||||
DECL_HANDLER(create_named_pipe);
|
DECL_HANDLER(create_named_pipe);
|
||||||
DECL_HANDLER(open_named_pipe);
|
DECL_HANDLER(open_named_pipe);
|
||||||
DECL_HANDLER(connect_named_pipe);
|
DECL_HANDLER(connect_named_pipe);
|
||||||
|
DECL_HANDLER(wait_named_pipe);
|
||||||
|
DECL_HANDLER(disconnect_named_pipe);
|
||||||
|
|
||||||
#ifdef WANT_REQUEST_HANDLERS
|
#ifdef WANT_REQUEST_HANDLERS
|
||||||
|
|
||||||
|
@ -311,6 +313,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_create_named_pipe,
|
(req_handler)req_create_named_pipe,
|
||||||
(req_handler)req_open_named_pipe,
|
(req_handler)req_open_named_pipe,
|
||||||
(req_handler)req_connect_named_pipe,
|
(req_handler)req_connect_named_pipe,
|
||||||
|
(req_handler)req_wait_named_pipe,
|
||||||
|
(req_handler)req_disconnect_named_pipe,
|
||||||
};
|
};
|
||||||
#endif /* WANT_REQUEST_HANDLERS */
|
#endif /* WANT_REQUEST_HANDLERS */
|
||||||
|
|
||||||
|
|
|
@ -1626,6 +1626,19 @@ static void dump_connect_named_pipe_request( const struct connect_named_pipe_req
|
||||||
fprintf( stderr, " event=%d", req->event );
|
fprintf( stderr, " event=%d", req->event );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_wait_named_pipe_request( const struct wait_named_pipe_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " timeout=%08x,", req->timeout );
|
||||||
|
fprintf( stderr, " event=%d,", req->event );
|
||||||
|
fprintf( stderr, " filename=" );
|
||||||
|
cur_pos += dump_varargs_string( req );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_disconnect_named_pipe_request( const struct disconnect_named_pipe_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%d", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_new_process_request,
|
(dump_func)dump_new_process_request,
|
||||||
(dump_func)dump_get_new_process_info_request,
|
(dump_func)dump_get_new_process_info_request,
|
||||||
|
@ -1747,6 +1760,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_create_named_pipe_request,
|
(dump_func)dump_create_named_pipe_request,
|
||||||
(dump_func)dump_open_named_pipe_request,
|
(dump_func)dump_open_named_pipe_request,
|
||||||
(dump_func)dump_connect_named_pipe_request,
|
(dump_func)dump_connect_named_pipe_request,
|
||||||
|
(dump_func)dump_wait_named_pipe_request,
|
||||||
|
(dump_func)dump_disconnect_named_pipe_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
|
@ -1870,6 +1885,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_create_named_pipe_reply,
|
(dump_func)dump_create_named_pipe_reply,
|
||||||
(dump_func)dump_open_named_pipe_reply,
|
(dump_func)dump_open_named_pipe_reply,
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
|
(dump_func)0,
|
||||||
|
(dump_func)0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
|
@ -1993,6 +2010,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"create_named_pipe",
|
"create_named_pipe",
|
||||||
"open_named_pipe",
|
"open_named_pipe",
|
||||||
"connect_named_pipe",
|
"connect_named_pipe",
|
||||||
|
"wait_named_pipe",
|
||||||
|
"disconnect_named_pipe",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ### make_requests end ### */
|
/* ### make_requests end ### */
|
||||||
|
|
Loading…
Reference in New Issue