Make ConnectNamedPipe work in overlapped mode.
This commit is contained in:
parent
37f61c45de
commit
309ed4e1f1
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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] );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue