Andrey Turkin : ws2_32: Make certain winsock functions generate i/ o completion messages.

Alexandre Julliard julliard at winehq.org
Thu Nov 15 07:45:06 CST 2007


Module: wine
Branch: master
Commit: 27cb7c72747507d495e3547d920b3330e24e1da9
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=27cb7c72747507d495e3547d920b3330e24e1da9

Author: Andrey Turkin <andrey.turkin at 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 */
+ at 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 */
+ at 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




More information about the wine-cvs mailing list