ws2_32: Make certain winsock functions generate i/o completion messages.
This commit is contained in:
parent
c702a91a3c
commit
27cb7c7274
|
@ -2562,6 +2562,22 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* helper to send completion messages for client-only i/o operation case */
|
||||||
|
static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG_PTR Information )
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
SERVER_START_REQ( add_fd_completion )
|
||||||
|
{
|
||||||
|
req->handle = SOCKET2HANDLE(sock);
|
||||||
|
req->cvalue = CompletionValue;
|
||||||
|
req->status = CompletionStatus;
|
||||||
|
req->information = Information;
|
||||||
|
status = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* send (WS2_32.19)
|
* send (WS2_32.19)
|
||||||
|
@ -2613,6 +2629,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
unsigned int i, options;
|
unsigned int i, options;
|
||||||
int n, fd, err;
|
int n, fd, err;
|
||||||
struct iovec iovec[WS_MSG_MAXIOVLEN];
|
struct iovec iovec[WS_MSG_MAXIOVLEN];
|
||||||
|
ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
|
||||||
|
|
||||||
TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
|
TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, to %p, tolen %d, ovl %p, func %p\n",
|
||||||
s, lpBuffers, dwBufferCount, dwFlags,
|
s, lpBuffers, dwBufferCount, dwFlags,
|
||||||
|
@ -2649,6 +2666,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
if (n == -1 && errno != EAGAIN)
|
if (n == -1 && errno != EAGAIN)
|
||||||
{
|
{
|
||||||
err = wsaErrno();
|
err = wsaErrno();
|
||||||
|
if (cvalue) WS_AddCompletion( s, cvalue, err, 0 );
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2689,7 +2707,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
req->async.arg = wsa;
|
req->async.arg = wsa;
|
||||||
req->async.apc = ws2_async_apc;
|
req->async.apc = ws2_async_apc;
|
||||||
req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
|
req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
|
||||||
req->async.cvalue = 0;
|
req->async.cvalue = cvalue;
|
||||||
err = wine_server_call( req );
|
err = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -2704,6 +2722,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
*lpNumberOfBytesSent = n;
|
*lpNumberOfBytesSent = n;
|
||||||
if (!wsa->completion_func)
|
if (!wsa->completion_func)
|
||||||
{
|
{
|
||||||
|
if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
|
||||||
SetEvent( lpOverlapped->hEvent );
|
SetEvent( lpOverlapped->hEvent );
|
||||||
HeapFree( GetProcessHeap(), 0, wsa );
|
HeapFree( GetProcessHeap(), 0, wsa );
|
||||||
}
|
}
|
||||||
|
@ -4127,6 +4146,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
int n, fd, err;
|
int n, fd, err;
|
||||||
DWORD timeout_start = GetTickCount();
|
DWORD timeout_start = GetTickCount();
|
||||||
struct iovec iovec[WS_MSG_MAXIOVLEN];
|
struct iovec iovec[WS_MSG_MAXIOVLEN];
|
||||||
|
ULONG_PTR cvalue = (lpOverlapped && ((ULONG_PTR)lpOverlapped->hEvent & 1) == 0) ? (ULONG_PTR)lpOverlapped : 0;
|
||||||
|
|
||||||
TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
|
TRACE("socket %04lx, wsabuf %p, nbufs %d, flags %d, from %p, fromlen %d, ovl %p, func %p\n",
|
||||||
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
|
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
|
||||||
|
@ -4159,6 +4179,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
{
|
{
|
||||||
err = wsaErrno();
|
err = wsaErrno();
|
||||||
|
if (cvalue) WS_AddCompletion( s, cvalue, err, 0 );
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4203,7 +4224,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
req->async.arg = wsa;
|
req->async.arg = wsa;
|
||||||
req->async.apc = ws2_async_apc;
|
req->async.apc = ws2_async_apc;
|
||||||
req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
|
req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
|
||||||
req->async.cvalue = 0;
|
req->async.cvalue = cvalue;
|
||||||
err = wine_server_call( req );
|
err = wine_server_call( req );
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
@ -4217,6 +4238,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
|
||||||
iosb->Information = n;
|
iosb->Information = n;
|
||||||
if (!wsa->completion_func)
|
if (!wsa->completion_func)
|
||||||
{
|
{
|
||||||
|
if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n );
|
||||||
SetEvent( lpOverlapped->hEvent );
|
SetEvent( lpOverlapped->hEvent );
|
||||||
HeapFree( GetProcessHeap(), 0, wsa );
|
HeapFree( GetProcessHeap(), 0, wsa );
|
||||||
}
|
}
|
||||||
|
|
|
@ -4189,6 +4189,21 @@ struct set_completion_info_reply
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct add_fd_completion_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
obj_handle_t handle;
|
||||||
|
unsigned long cvalue;
|
||||||
|
unsigned int status;
|
||||||
|
unsigned long information;
|
||||||
|
};
|
||||||
|
struct add_fd_completion_reply
|
||||||
|
{
|
||||||
|
struct reply_header __header;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enum request
|
enum request
|
||||||
{
|
{
|
||||||
REQ_new_process,
|
REQ_new_process,
|
||||||
|
@ -4418,6 +4433,7 @@ enum request
|
||||||
REQ_remove_completion,
|
REQ_remove_completion,
|
||||||
REQ_query_completion,
|
REQ_query_completion,
|
||||||
REQ_set_completion_info,
|
REQ_set_completion_info,
|
||||||
|
REQ_add_fd_completion,
|
||||||
REQ_NB_REQUESTS
|
REQ_NB_REQUESTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4652,6 +4668,7 @@ union generic_request
|
||||||
struct remove_completion_request remove_completion_request;
|
struct remove_completion_request remove_completion_request;
|
||||||
struct query_completion_request query_completion_request;
|
struct query_completion_request query_completion_request;
|
||||||
struct set_completion_info_request set_completion_info_request;
|
struct set_completion_info_request set_completion_info_request;
|
||||||
|
struct add_fd_completion_request add_fd_completion_request;
|
||||||
};
|
};
|
||||||
union generic_reply
|
union generic_reply
|
||||||
{
|
{
|
||||||
|
@ -4884,8 +4901,9 @@ union generic_reply
|
||||||
struct remove_completion_reply remove_completion_reply;
|
struct remove_completion_reply remove_completion_reply;
|
||||||
struct query_completion_reply query_completion_reply;
|
struct query_completion_reply query_completion_reply;
|
||||||
struct set_completion_info_reply set_completion_info_reply;
|
struct set_completion_info_reply set_completion_info_reply;
|
||||||
|
struct add_fd_completion_reply add_fd_completion_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 329
|
#define SERVER_PROTOCOL_VERSION 330
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
11
server/fd.c
11
server/fd.c
|
@ -2056,3 +2056,14 @@ DECL_HANDLER(set_completion_info)
|
||||||
release_object( fd );
|
release_object( fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* push new completion msg into a completion queue attached to the fd */
|
||||||
|
DECL_HANDLER(add_fd_completion)
|
||||||
|
{
|
||||||
|
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||||
|
if (fd)
|
||||||
|
{
|
||||||
|
fd_add_completion( fd, req->cvalue, req->status, req->information );
|
||||||
|
release_object( fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3006,3 +3006,12 @@ enum message_type
|
||||||
obj_handle_t chandle; /* port handle */
|
obj_handle_t chandle; /* port handle */
|
||||||
unsigned long ckey; /* completion key */
|
unsigned long ckey; /* completion key */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* check for associated completion and push msg */
|
||||||
|
@REQ(add_fd_completion)
|
||||||
|
obj_handle_t handle; /* async' object */
|
||||||
|
unsigned long cvalue; /* completion value */
|
||||||
|
unsigned int status; /* completion status */
|
||||||
|
unsigned long information; /* IO_STATUS_BLOCK Information */
|
||||||
|
@END
|
||||||
|
|
|
@ -337,6 +337,7 @@ DECL_HANDLER(add_completion);
|
||||||
DECL_HANDLER(remove_completion);
|
DECL_HANDLER(remove_completion);
|
||||||
DECL_HANDLER(query_completion);
|
DECL_HANDLER(query_completion);
|
||||||
DECL_HANDLER(set_completion_info);
|
DECL_HANDLER(set_completion_info);
|
||||||
|
DECL_HANDLER(add_fd_completion);
|
||||||
|
|
||||||
#ifdef WANT_REQUEST_HANDLERS
|
#ifdef WANT_REQUEST_HANDLERS
|
||||||
|
|
||||||
|
@ -570,6 +571,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_remove_completion,
|
(req_handler)req_remove_completion,
|
||||||
(req_handler)req_query_completion,
|
(req_handler)req_query_completion,
|
||||||
(req_handler)req_set_completion_info,
|
(req_handler)req_set_completion_info,
|
||||||
|
(req_handler)req_add_fd_completion,
|
||||||
};
|
};
|
||||||
#endif /* WANT_REQUEST_HANDLERS */
|
#endif /* WANT_REQUEST_HANDLERS */
|
||||||
|
|
||||||
|
|
|
@ -3698,6 +3698,14 @@ static void dump_set_completion_info_request( const struct set_completion_info_r
|
||||||
fprintf( stderr, " ckey=%lx", req->ckey );
|
fprintf( stderr, " ckey=%lx", req->ckey );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_add_fd_completion_request( const struct add_fd_completion_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%p,", req->handle );
|
||||||
|
fprintf( stderr, " cvalue=%lx,", req->cvalue );
|
||||||
|
fprintf( stderr, " status=%08x,", req->status );
|
||||||
|
fprintf( stderr, " information=%lx", req->information );
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
@ -3926,6 +3934,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_remove_completion_request,
|
(dump_func)dump_remove_completion_request,
|
||||||
(dump_func)dump_query_completion_request,
|
(dump_func)dump_query_completion_request,
|
||||||
(dump_func)dump_set_completion_info_request,
|
(dump_func)dump_set_completion_info_request,
|
||||||
|
(dump_func)dump_add_fd_completion_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
|
@ -4156,6 +4165,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_remove_completion_reply,
|
(dump_func)dump_remove_completion_reply,
|
||||||
(dump_func)dump_query_completion_reply,
|
(dump_func)dump_query_completion_reply,
|
||||||
(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] = {
|
||||||
|
@ -4386,6 +4396,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"remove_completion",
|
"remove_completion",
|
||||||
"query_completion",
|
"query_completion",
|
||||||
"set_completion_info",
|
"set_completion_info",
|
||||||
|
"add_fd_completion",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
|
|
Loading…
Reference in New Issue