Make ConnectNamedPipe work in overlapped mode.

This commit is contained in:
Mike McCormack 2001-11-07 20:14:45 +00:00 committed by Alexandre Julliard
parent 37f61c45de
commit 309ed4e1f1
6 changed files with 162 additions and 66 deletions

View File

@ -601,38 +601,72 @@ BOOL WINAPI PeekNamedPipe( HANDLE hPipe, LPVOID lpvBuffer, DWORD cbBuffer,
return FALSE;
}
/***********************************************************************
* SYNC_CompletePipeOverlapped (Internal)
*/
static void SYNC_CompletePipeOverlapped (LPOVERLAPPED overlapped, DWORD result)
{
TRACE("for %p result %08lx\n",overlapped,result);
if(!overlapped)
return;
overlapped->Internal = result;
SetEvent(overlapped->hEvent);
}
/***********************************************************************
* WaitNamedPipeA (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
static BOOL SYNC_WaitNamedPipeA (LPCSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
{
DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
HANDLE event;
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;
req->overlapped = overlapped;
req->func = SYNC_CompletePipeOverlapped;
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);
return ret;
}
CloseHandle(event);
/***********************************************************************
* WaitNamedPipeA (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
{
BOOL ret;
OVERLAPPED ov;
TRACE("%s 0x%08lx\n",debugstr_a(name),nTimeOut);
memset(&ov,0,sizeof ov);
ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
if (!ov.hEvent)
return FALSE;
/* expect to fail with STATUS_PENDING */
ret = SYNC_WaitNamedPipeA(name, nTimeOut, &ov);
if(ret)
{
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
{
SetLastError(ov.Internal);
ret = (ov.Internal==STATUS_SUCCESS);
}
}
CloseHandle(ov.hEvent);
return ret;
}
@ -640,68 +674,115 @@ BOOL WINAPI WaitNamedPipeA (LPCSTR name, DWORD nTimeOut)
/***********************************************************************
* WaitNamedPipeW (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
static BOOL SYNC_WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut, LPOVERLAPPED overlapped)
{
DWORD len = name ? strlenW(name) : 0;
HANDLE event;
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;
req->overlapped = overlapped;
req->func = SYNC_CompletePipeOverlapped;
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;
}
/***********************************************************************
* WaitNamedPipeW (KERNEL32.@)
*/
BOOL WINAPI WaitNamedPipeW (LPCWSTR name, DWORD nTimeOut)
{
BOOL ret;
OVERLAPPED ov;
TRACE("%s 0x%08lx\n",debugstr_w(name),nTimeOut);
memset(&ov,0,sizeof ov);
ov.hEvent = CreateEventA( NULL, 0, 0, NULL );
if (!ov.hEvent)
return FALSE;
ret = SYNC_WaitNamedPipeW(name, nTimeOut, &ov);
if(ret)
{
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
{
SetLastError(ov.Internal);
ret = (ov.Internal==STATUS_SUCCESS);
}
}
CloseHandle(ov.hEvent);
return ret;
}
/***********************************************************************
* SYNC_ConnectNamedPipe (Internal)
*/
static BOOL SYNC_ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
{
BOOL ret;
if(!overlapped)
return FALSE;
overlapped->Internal = STATUS_PENDING;
SERVER_START_REQ( connect_named_pipe )
{
req->handle = hPipe;
req->overlapped = overlapped;
req->func = SYNC_CompletePipeOverlapped;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* ConnectNamedPipe (KERNEL32.@)
*/
BOOL WINAPI ConnectNamedPipe(HANDLE hPipe, LPOVERLAPPED overlapped)
{
OVERLAPPED ov;
BOOL ret;
HANDLE event;
TRACE("(%d,%p)\n",hPipe, overlapped);
if(overlapped)
{
FIXME("overlapped operation not supported\n");
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return SYNC_ConnectNamedPipe(hPipe,overlapped);
memset(&ov,0,sizeof ov);
ov.hEvent = CreateEventA(NULL,0,0,NULL);
if (!ov.hEvent)
return FALSE;
}
if (!(event = CreateEventA(NULL,0,0,NULL))) return FALSE;
SERVER_START_REQ( connect_named_pipe )
ret=SYNC_ConnectNamedPipe(hPipe, &ov);
if(ret)
{
req->handle = hPipe;
req->event = event;
ret = !SERVER_CALL_ERR();
if (WAIT_OBJECT_0==WaitForSingleObject(ov.hEvent,INFINITE))
{
SetLastError(ov.Internal);
ret = (ov.Internal==STATUS_SUCCESS);
}
}
SERVER_END_REQ;
if (ret) WaitForSingleObject(event,INFINITE);
CloseHandle(ov.hEvent);
CloseHandle(event);
return ret;
}

View File

@ -1552,7 +1552,8 @@ struct connect_named_pipe_request
{
struct request_header __header;
handle_t handle;
handle_t event;
void* overlapped;
void* func;
};
@ -1561,7 +1562,8 @@ struct wait_named_pipe_request
{
struct request_header __header;
unsigned int timeout;
handle_t event;
void* overlapped;
void* func;
/* VARARG(filename,string); */
};
@ -2056,6 +2058,6 @@ union generic_request
struct get_window_properties_request get_window_properties;
};
#define SERVER_PROTOCOL_VERSION 62
#define SERVER_PROTOCOL_VERSION 63
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -243,6 +243,7 @@ static void call_apcs( BOOL alertable )
case APC_NONE:
return; /* no more APCs */
case APC_ASYNC:
proc( args[0], args[1]);
break;
case APC_USER:
proc( args[0] );

View File

@ -48,7 +48,9 @@ struct pipe_user
struct named_pipe *pipe;
struct pipe_user *next;
struct pipe_user *prev;
struct event *event;
void *thread;
void *func;
void *overlapped;
};
struct named_pipe
@ -122,18 +124,28 @@ static void named_pipe_destroy( struct object *obj)
assert( !pipe->users );
}
static void notify_waiter( struct pipe_user *user, unsigned int status)
{
if(user->thread && user->func && user->overlapped)
{
/* queue a system APC, to notify a waiting thread */
thread_queue_apc(user->thread,NULL,user->func,
APC_ASYNC,1,2,user->overlapped,status);
}
user->thread = NULL;
user->func = NULL;
user->overlapped=NULL;
}
static void pipe_user_destroy( struct object *obj)
{
struct pipe_user *user = (struct pipe_user *)obj;
assert( obj->ops == &pipe_user_ops );
if(user->event)
{
/* FIXME: signal waiter of failure */
release_object(user->event);
user->event = NULL;
}
if(user->overlapped)
notify_waiter(user,STATUS_HANDLES_CLOSED);
if(user->other)
{
close(user->other->obj.fd);
@ -217,8 +229,10 @@ static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd )
user->pipe = pipe;
user->state = ps_none;
user->event = NULL; /* thread wait on this pipe */
user->other = NULL;
user->thread = NULL;
user->func = NULL;
user->overlapped = NULL;
/* add to list of pipe users */
if ((user->next = pipe->users)) user->next->prev = user;
@ -301,9 +315,7 @@ DECL_HANDLER(open_named_pipe)
if( (user = create_pipe_user (pipe, fds[1])) )
{
partner->obj.fd = fds[0];
set_event(partner->event);
release_object(partner->event);
partner->event = NULL;
notify_waiter(partner,STATUS_SUCCESS);
partner->state = ps_connected_server;
partner->other = user;
user->state = ps_connected_client;
@ -334,7 +346,6 @@ DECL_HANDLER(open_named_pipe)
DECL_HANDLER(connect_named_pipe)
{
struct pipe_user *user, *partner;
struct event *event;
user = get_pipe_user_obj(current->process, req->handle, 0);
if(!user)
@ -347,16 +358,14 @@ DECL_HANDLER(connect_named_pipe)
else
{
user->state = ps_wait_open;
event = get_event_obj(current->process, req->event, 0);
if(event)
user->event = event;
user->thread = current;
user->func = req->func;
user->overlapped = req->overlapped;
/* 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;
notify_waiter(partner,STATUS_SUCCESS);
release_object(partner);
release_object(partner);
}
@ -367,13 +376,8 @@ DECL_HANDLER(connect_named_pipe)
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 )
{
@ -385,7 +389,10 @@ DECL_HANDLER(wait_named_pipe)
set_error(STATUS_SUCCESS);
if( (partner = find_partner(pipe,ps_wait_open)) )
{
set_event(event);
/* this should use notify_waiter,
but no pipe_user object exists now... */
thread_queue_apc(current,NULL,req->func,
APC_ASYNC,1,2,req->overlapped,STATUS_SUCCESS);
release_object(partner);
}
else
@ -394,8 +401,10 @@ DECL_HANDLER(wait_named_pipe)
if( (user = create_pipe_user (pipe, -1)) )
{
user->event = (struct event *)grab_object( event );
user->state = ps_wait_connect;
user->thread = current;
user->func = req->func;
user->overlapped = req->overlapped;
/* don't release it */
}
}
@ -406,7 +415,6 @@ DECL_HANDLER(wait_named_pipe)
}
release_object(pipe);
}
release_object(event);
}
DECL_HANDLER(disconnect_named_pipe)

View File

@ -1392,14 +1392,16 @@ enum message_type
/* Connect to a named pipe */
@REQ(connect_named_pipe)
handle_t handle;
handle_t event; /* set this event when it's ready */
void* overlapped;
void* func;
@END
/* Wait for a named pipe */
@REQ(wait_named_pipe)
unsigned int timeout;
handle_t event; /* set this event when it's ready */
void* overlapped;
void* func;
VARARG(filename,string); /* pipe name */
@END

View File

@ -1661,13 +1661,15 @@ static void dump_open_named_pipe_reply( const struct open_named_pipe_request *re
static void dump_connect_named_pipe_request( const struct connect_named_pipe_request *req )
{
fprintf( stderr, " handle=%d,", req->handle );
fprintf( stderr, " event=%d", req->event );
fprintf( stderr, " overlapped=%p,", req->overlapped );
fprintf( stderr, " func=%p", req->func );
}
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, " overlapped=%p,", req->overlapped );
fprintf( stderr, " func=%p,", req->func );
fprintf( stderr, " filename=" );
cur_pos += dump_varargs_string( req );
}