Module: wine Branch: master Commit: 27cb7c72747507d495e3547d920b3330e24e1da9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=27cb7c72747507d495e3547d92...
Author: Andrey Turkin andrey.turkin@gmail.com Date: Sat Nov 10 01:11:58 2007 +0300
ws2_32: Make certain winsock functions generate i/o completion messages.
---
dlls/ws2_32/socket.c | 26 ++++++++++++++++++++++++-- include/wine/server_protocol.h | 20 +++++++++++++++++++- server/fd.c | 11 +++++++++++ server/protocol.def | 9 +++++++++ server/request.h | 2 ++ server/trace.c | 11 +++++++++++ 6 files changed, 76 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 5d51311..eab1550 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2562,6 +2562,22 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds, 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) @@ -2613,6 +2629,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, unsigned int i, options; int n, fd, err; 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", s, lpBuffers, dwBufferCount, dwFlags, @@ -2649,6 +2666,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, if (n == -1 && errno != EAGAIN) { err = wsaErrno(); + if (cvalue) WS_AddCompletion( s, cvalue, err, 0 ); goto error; }
@@ -2689,7 +2707,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, req->async.arg = wsa; req->async.apc = ws2_async_apc; req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; - req->async.cvalue = 0; + req->async.cvalue = cvalue; err = wine_server_call( req ); } SERVER_END_REQ; @@ -2704,6 +2722,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, *lpNumberOfBytesSent = n; if (!wsa->completion_func) { + if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n ); SetEvent( lpOverlapped->hEvent ); HeapFree( GetProcessHeap(), 0, wsa ); } @@ -4127,6 +4146,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, int n, fd, err; DWORD timeout_start = GetTickCount(); 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", s, lpBuffers, dwBufferCount, *lpFlags, lpFrom, @@ -4159,6 +4179,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, if (errno != EAGAIN) { err = wsaErrno(); + if (cvalue) WS_AddCompletion( s, cvalue, err, 0 ); goto error; } } @@ -4203,7 +4224,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, req->async.arg = wsa; req->async.apc = ws2_async_apc; req->async.event = lpCompletionRoutine ? 0 : lpOverlapped->hEvent; - req->async.cvalue = 0; + req->async.cvalue = cvalue; err = wine_server_call( req ); } SERVER_END_REQ; @@ -4217,6 +4238,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, iosb->Information = n; if (!wsa->completion_func) { + if (cvalue) WS_AddCompletion( s, cvalue, STATUS_SUCCESS, n ); SetEvent( lpOverlapped->hEvent ); HeapFree( GetProcessHeap(), 0, wsa ); } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 410b802..8598aef 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -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 { REQ_new_process, @@ -4418,6 +4433,7 @@ enum request REQ_remove_completion, REQ_query_completion, REQ_set_completion_info, + REQ_add_fd_completion, REQ_NB_REQUESTS };
@@ -4652,6 +4668,7 @@ union generic_request struct remove_completion_request remove_completion_request; struct query_completion_request query_completion_request; struct set_completion_info_request set_completion_info_request; + struct add_fd_completion_request add_fd_completion_request; }; union generic_reply { @@ -4884,8 +4901,9 @@ union generic_reply struct remove_completion_reply remove_completion_reply; struct query_completion_reply query_completion_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 */ diff --git a/server/fd.c b/server/fd.c index cb3aea8..4bfb3e1 100644 --- a/server/fd.c +++ b/server/fd.c @@ -2056,3 +2056,14 @@ DECL_HANDLER(set_completion_info) 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 ); + } +} diff --git a/server/protocol.def b/server/protocol.def index 93e4887..cf3ffa1 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3006,3 +3006,12 @@ enum message_type obj_handle_t chandle; /* port handle */ unsigned long ckey; /* completion key */ @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 diff --git a/server/request.h b/server/request.h index 90ec2e1..cd53e16 100644 --- a/server/request.h +++ b/server/request.h @@ -337,6 +337,7 @@ DECL_HANDLER(add_completion); DECL_HANDLER(remove_completion); DECL_HANDLER(query_completion); DECL_HANDLER(set_completion_info); +DECL_HANDLER(add_fd_completion);
#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_query_completion, (req_handler)req_set_completion_info, + (req_handler)req_add_fd_completion, }; #endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/trace.c b/server/trace.c index 7275e65..c580139 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3698,6 +3698,14 @@ static void dump_set_completion_info_request( const struct set_completion_info_r 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] = { (dump_func)dump_new_process_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_query_completion_request, (dump_func)dump_set_completion_info_request, + (dump_func)dump_add_fd_completion_request, };
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_query_completion_reply, (dump_func)0, + (dump_func)0, };
static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4386,6 +4396,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "remove_completion", "query_completion", "set_completion_info", + "add_fd_completion", };
static const struct