Alexandre Julliard : ws2_32: Queue a proper user APC also on immediate success in WSARecvFrom/WSASendTo .

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jun 5 05:48:11 CDT 2007


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun  4 17:44:24 2007 +0200

ws2_32: Queue a proper user APC also on immediate success in WSARecvFrom/WSASendTo.

---

 dlls/ws2_32/socket.c |  133 +++++++++++++++++++++++++++++++-------------------
 1 files changed, 82 insertions(+), 51 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 4c87d23..2b7efdc 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -2634,37 +2634,37 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
         n = WS2_send( fd, iovec, dwBufferCount, to, tolen, dwFlags );
         if (n != -1 || errno != EINTR) break;
     }
-    if (n == -1)
+    if (n == -1 && errno != EAGAIN)
     {
-        if (errno != EAGAIN)
+        err = wsaErrno();
+        goto error;
+    }
+
+    if ((lpOverlapped || lpCompletionRoutine) &&
+        !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
+    {
+        IO_STATUS_BLOCK *iosb;
+        struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
+
+        if ( !wsa )
         {
-            err = wsaErrno();
+            err = WSAEFAULT;
             goto error;
         }
+        release_sock_fd( s, fd );
 
-        if ((lpOverlapped || lpCompletionRoutine) &&
-            !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
-        {
-            IO_STATUS_BLOCK *iosb;
-            struct ws2_async *wsa = HeapAlloc( GetProcessHeap(), 0, sizeof(*wsa) );
-
-            if ( !wsa )
-            {
-                err = WSAEFAULT;
-                goto error;
-            }
-            release_sock_fd( s, fd );
-
-            wsa->hSocket         = SOCKET2HANDLE(s);
-            wsa->addr            = (struct WS_sockaddr *)to;
-            wsa->addrlen.val     = tolen;
-            wsa->flags           = 0;
-            wsa->user_overlapped = lpOverlapped;
-            wsa->completion_func = lpCompletionRoutine;
-            wsa->n_iovecs        = dwBufferCount;
-            memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
+        wsa->hSocket         = SOCKET2HANDLE(s);
+        wsa->addr            = (struct WS_sockaddr *)to;
+        wsa->addrlen.val     = tolen;
+        wsa->flags           = 0;
+        wsa->user_overlapped = lpOverlapped;
+        wsa->completion_func = lpCompletionRoutine;
+        wsa->n_iovecs        = dwBufferCount;
+        memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
 
-            iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
+        iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
+        if (n == -1)
+        {
             iosb->u.Status = STATUS_PENDING;
             iosb->Information = 0;
 
@@ -2689,6 +2689,18 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
             WSASetLastError( NtStatusToWSAError( err ));
             return SOCKET_ERROR;
         }
+
+        iosb->u.Status = STATUS_SUCCESS;
+        iosb->Information = n;
+        *lpNumberOfBytesSent = n;
+        if (!wsa->completion_func)
+        {
+            SetEvent( lpOverlapped->hEvent );
+            HeapFree( GetProcessHeap(), 0, wsa );
+        }
+        else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
+                               (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
+        return 0;
     }
 
     if ( _is_blocking(s) )
@@ -4140,14 +4152,17 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     for (;;)
     {
         n = WS2_recv( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
-        if (n != -1) break;
-
-        if (errno == EINTR) continue;
-        if (errno != EAGAIN)
+        if (n == -1)
         {
-            err = wsaErrno();
-            goto error;
+            if (errno == EINTR) continue;
+            if (errno != EAGAIN)
+            {
+                err = wsaErrno();
+                goto error;
+            }
         }
+        else
+            *lpNumberOfBytesRecvd = n;
 
         if ((lpOverlapped || lpCompletionRoutine) &&
              !(options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
@@ -4172,31 +4187,49 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
             memcpy( wsa->iovec, iovec, dwBufferCount * sizeof(*iovec) );
 
             iosb = lpOverlapped ? (IO_STATUS_BLOCK *)lpOverlapped : &wsa->local_iosb;
-            iosb->u.Status = STATUS_PENDING;
-            iosb->Information = 0;
 
-            SERVER_START_REQ( register_async )
+            if (n == -1)
             {
-                req->handle = wsa->hSocket;
-                req->type   = ASYNC_TYPE_READ;
-                req->async.callback = WS2_async_recv;
-                req->async.iosb     = iosb;
-                req->async.arg      = wsa;
-                req->async.apc      = ws2_async_apc;
-                req->async.event    = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
-                err = wine_server_call( req );
+                iosb->u.Status = STATUS_PENDING;
+                iosb->Information = 0;
+
+                SERVER_START_REQ( register_async )
+                {
+                    req->handle = wsa->hSocket;
+                    req->type   = ASYNC_TYPE_READ;
+                    req->async.callback = WS2_async_recv;
+                    req->async.iosb     = iosb;
+                    req->async.arg      = wsa;
+                    req->async.apc      = ws2_async_apc;
+                    req->async.event    = lpCompletionRoutine ? 0 : lpOverlapped->hEvent;
+                    err = wine_server_call( req );
+                }
+                SERVER_END_REQ;
+
+                if (err == STATUS_PENDING)
+                    NtCurrentTeb()->num_async_io++;
+                else
+                    HeapFree( GetProcessHeap(), 0, wsa );
+
+                WSASetLastError( NtStatusToWSAError( err ));
+                return SOCKET_ERROR;
             }
-            SERVER_END_REQ;
 
-            if (err == STATUS_PENDING)
-                NtCurrentTeb()->num_async_io++;
-            else
+            iosb->u.Status = STATUS_SUCCESS;
+            iosb->Information = n;
+            if (!wsa->completion_func)
+            {
+                SetEvent( lpOverlapped->hEvent );
                 HeapFree( GetProcessHeap(), 0, wsa );
-
-            WSASetLastError( NtStatusToWSAError( err ));
-            return SOCKET_ERROR;
+            }
+            else NtQueueApcThread( GetCurrentThread(), (PNTAPCFUNC)ws2_async_apc,
+                                   (ULONG_PTR)wsa, (ULONG_PTR)iosb, 0 );
+            _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
+            return 0;
         }
 
+        if (n != -1) break;
+
         if ( _is_blocking(s) )
         {
             struct pollfd pfd;
@@ -4228,8 +4261,6 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
     }
 
     TRACE(" -> %i bytes\n", n);
-    *lpNumberOfBytesRecvd = n;
-
     release_sock_fd( s, fd );
     _enable_event(SOCKET2HANDLE(s), FD_READ, 0, 0);
 




More information about the wine-cvs mailing list