Patch: async-winsock.diff (8 in series)

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Fri Apr 12 10:22:32 CDT 2002


Patch: async-winsock.diff

Basic implementation of asynchronous WSARecvFrom()/WSASendTo()/WSAGetOverlappedResult(),
client side.

Patch against:  CVS 2002-04-12, with my sock-fd-type and sock-accept-deferred patches applied.
        Also requires the server side patch (async-sock-server).

Modified files:
        dlls/winsock:   socket.c, ws2_32.spec
        include:        winsock2.h

diff -ruNX ignore TMP/wine/dlls/winsock/socket.c MW/wine/dlls/winsock/socket.c
--- TMP/wine/dlls/winsock/socket.c	Fri Apr 12 14:55:42 2002
+++ MW/wine/dlls/winsock/socket.c	Fri Apr 12 15:13:28 2002
@@ -105,6 +105,7 @@
 #include "wine/winbase16.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winerror.h"
 #include "winsock2.h"
 #include "ws2tcpip.h"
 #include "wsipx.h"
@@ -126,6 +127,170 @@
                         inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
                         ntohs(((struct sockaddr_in *)a)->sin_port))

+/****************************************************************
+ * Async IO declarations and operations
+ ****************************************************************/
+#include "async.h"
+
+static DWORD ws2_async_get_status (const struct async_private *ovp);
+static DWORD ws2_async_get_count  (const struct async_private *ovp);
+static void  ws2_async_set_status (struct async_private *ovp, const DWORD status);
+static void CALLBACK ws2_async_call_completion (ULONG_PTR data);
+static void ws2_async_cleanup ( struct async_private *ovp );
+
+static struct async_ops ws2_async_ops =
+{
+    ws2_async_get_status,
+    ws2_async_set_status,
+    ws2_async_get_count,
+    ws2_async_call_completion,
+    ws2_async_cleanup
+};
+
+static struct async_ops ws2_nocomp_async_ops =
+{
+    ws2_async_get_status,
+    ws2_async_set_status,
+    ws2_async_get_count,
+    NULL,                     /* call_completion */
+    ws2_async_cleanup
+};
+
+typedef struct ws2_async
+{
+    async_private                       async;
+    LPWSAOVERLAPPED                     overlapped;
+    LPWSAOVERLAPPED                     user_overlapped;
+    LPWSAOVERLAPPED_COMPLETION_ROUTINE  completion_func;
+    struct iovec                        *iovec;
+    int                                 n_iovecs;
+    struct WS_sockaddr            *addr;
+    union {
+        int val;     /* for send operations */
+        int *ptr;    /* for recv operations */
+    }                                   addrlen;
+    DWORD                               flags;
+} ws2_async;
+
+static DWORD ws2_async_get_status (const struct async_private *ovp)
+{
+    return ((ws2_async*) ovp)->overlapped->Internal;
+}
+
+static VOID ws2_async_set_status (struct async_private *ovp, const DWORD status)
+{
+    ((ws2_async*) ovp)->overlapped->Internal = status;
+}
+
+static DWORD ws2_async_get_count (const struct async_private *ovp)
+{
+    return ((ws2_async*) ovp)->overlapped->InternalHigh;
+}
+
+static void ws2_async_cleanup ( struct async_private *ap )
+{
+    struct ws2_async *as = (struct ws2_async*) ap;
+
+    TRACE ( "as: %p uovl %p ovl %p\n", as, as->user_overlapped, as->overlapped );
+    if ( !as->user_overlapped )
+    {
+        if ( as->overlapped->hEvent != INVALID_HANDLE_VALUE )
+            WSACloseEvent ( as->overlapped->hEvent  );
+        HeapFree ( GetProcessHeap(), 0, as->overlapped );
+    }
+
+    if ( as->iovec )
+        HeapFree ( GetProcessHeap(), 0, as->iovec );
+
+    HeapFree ( GetProcessHeap(), 0, as );
+}
+
+static void CALLBACK ws2_async_call_completion (ULONG_PTR data)
+{
+    ws2_async* as = (ws2_async*) data;
+
+    TRACE ("data: %p\n", as);
+
+    as->completion_func ( RtlNtStatusToDosError (as->overlapped->Internal),
+                          as->overlapped->InternalHigh,
+                          as->user_overlapped,
+                          as->flags );
+    ws2_async_cleanup ( &as->async );
+}
+
+static void WS2_async_recv (async_private *as);
+static void WS2_async_send (async_private *as);
+
+/***********************************************************************
+ *              WS2_make_async          (WS2_32.69)
+ */
+inline static struct ws2_async*
+WS2_make_async (SOCKET s, int fd, int type, struct iovec *iovec, DWORD dwBufferCount,
+                LPDWORD lpFlags, struct WS_sockaddr *addr,
+                LPINT addrlen, LPWSAOVERLAPPED lpOverlapped,
+                LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+{
+    struct ws2_async *wsa = HeapAlloc ( GetProcessHeap(), 0, sizeof ( ws2_async ) );
+
+    TRACE ( "wsa %p\n", wsa );
+
+    if (!wsa)
+        return NULL;
+
+    wsa->async.ops = ( lpCompletionRoutine ? &ws2_async_ops : &ws2_nocomp_async_ops );
+    wsa->async.handle = (HANDLE) s;
+    wsa->async.fd = fd;
+    wsa->async.type = type;
+    switch (type)
+    {
+    case ASYNC_TYPE_READ:
+        wsa->flags = *lpFlags;
+        wsa->async.func = WS2_async_recv;
+        wsa->addrlen.ptr = addrlen;
+        break;
+    case ASYNC_TYPE_WRITE:
+        wsa->flags = 0;
+        wsa->async.func = WS2_async_send;
+        wsa->addrlen.val = *addrlen;
+        break;
+    default:
+        ERR ("Invalid async type: %d\n", type);
+    }
+    wsa->user_overlapped = lpOverlapped;
+    wsa->completion_func = lpCompletionRoutine;
+    wsa->iovec = iovec;
+    wsa->n_iovecs = dwBufferCount;
+    wsa->addr = addr;
+
+    if ( lpOverlapped )
+    {
+        wsa->overlapped = lpOverlapped;
+        wsa->async.event = ( lpCompletionRoutine ? INVALID_HANDLE_VALUE : lpOverlapped->hEvent );
+    }
+    else
+    {
+        wsa->overlapped = HeapAlloc ( GetProcessHeap(), 0,
+                                      sizeof (WSAOVERLAPPED) );
+        if ( !wsa->overlapped )
+            goto error;
+        wsa->async.event = wsa->overlapped->hEvent = INVALID_HANDLE_VALUE;
+    }
+
+    wsa->overlapped->InternalHigh = 0;
+    TRACE ( "wsa %p, ops %p, h %d, ev %d, fd %d, func %p, ov %p, uov %p, cfunc %p\n",
+            wsa, wsa->async.ops, wsa->async.handle, wsa->async.event, wsa->async.fd, wsa->async.func,
+            wsa->overlapped, wsa->user_overlapped, wsa->completion_func );
+
+    return wsa;
+
+error:
+    TRACE ("Error\n");
+    HeapFree ( GetProcessHeap(), 0, wsa );
+    return NULL;
+}
+
+/****************************************************************/
+
 /* ----------------------------------- internal data */

 /* ws_... struct conversion flags */
@@ -1988,6 +2153,88 @@
 }

 /***********************************************************************
+ *              WS2_send                (INTERNAL)
+ */
+static int WS2_send ( int fd, struct iovec* iov, int count,
+                      const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
+{
+    struct msghdr hdr;
+    int n = -1;
+    TRACE ( "fd %d, iovec %p, count %d addr %p, len %d, flags %lx\n",
+            fd, iov, count, to, tolen, dwFlags);
+
+    hdr.msg_name = NULL;
+
+    if ( to )
+    {
+#if DEBUG_SOCKADDR
+        dump_sockaddr (to);
+#endif
+        hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
+        if ( !hdr.msg_name )
+        {
+            WSASetLastError ( WSAEFAULT );
+            goto out;
+        }
+    }
+    else
+        hdr.msg_namelen = 0;
+
+    hdr.msg_iov = iov;
+    hdr.msg_iovlen = count;
+    hdr.msg_control = NULL;
+    hdr.msg_controllen = 0;
+    hdr.msg_flags = 0;
+
+    n = sendmsg (fd, &hdr, dwFlags);
+
+out:
+    ws_sockaddr_free ( hdr.msg_name, to );
+    return n;
+}
+
+/***********************************************************************
+ *              WS2_async_send          (INTERNAL)
+ */
+static void WS2_async_send ( async_private *as )
+{
+    ws2_async* wsa = (ws2_async*) as;
+    int result, err;
+
+    TRACE ( "async %p\n", wsa );
+
+    if ( wsa->overlapped->Internal != STATUS_PENDING )
+    {
+        TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+        return;
+    }
+
+    result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
+                        wsa->addr, wsa->addrlen.val, wsa->flags );
+
+    if (result >= 0)
+    {
+        wsa->overlapped->Internal = STATUS_SUCCESS;
+        wsa->overlapped->InternalHigh = result;
+        TRACE ( "sent %d bytes\n", result );
+        _enable_event ( (SOCKET) wsa->async.handle, FD_WRITE, 0, 0 );
+        return;
+    }
+
+    err = errno;
+    if ( err == EAGAIN || err == EINTR )
+    {
+        wsa->overlapped->Internal = STATUS_PENDING;
+        TRACE ( "still pending\n" );
+    }
+    else
+    {
+        wsa->overlapped->Internal = STATUS_UNSUCCESSFUL;
+        TRACE ( "Error: %d\n", errno );
+    }
+}
+
+/***********************************************************************
  *		WSASendTo		(WS2_32.74)
  */
 INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
@@ -1996,9 +2243,9 @@
                       LPWSAOVERLAPPED lpOverlapped,
                       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
 {
-    int i, n, fd, err = WSAENOTSOCK, flags;
+    int i, n, fd, err = WSAENOTSOCK, flags, ret;
     struct iovec* iovec;
-    struct msghdr msghdr;
+    struct ws2_async *wsa;
     enum fd_type type;

     TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
@@ -2006,6 +2253,7 @@
            to, tolen, lpOverlapped, lpCompletionRoutine);

     fd = _get_sock_fd_type( s, &type, &flags );
+    TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );

     if ( fd == -1 )
         goto error;
@@ -2014,7 +2262,7 @@

     if ( !iovec )
     {
-        err = WSAENOBUFS;
+        err = WSAEFAULT;
         goto err_close;
     }

@@ -2024,30 +2272,46 @@
         iovec[i].iov_len  = lpBuffers[i].len;
     }

-    msghdr.msg_name = NULL;
-
-    if (to)
+    if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
     {
-#if DEBUG_SOCKADDR
-        dump_sockaddr (to);
-#endif
-        msghdr.msg_name = (void*) ws_sockaddr_ws2u (to, tolen, &msghdr.msg_namelen);
-        if ( !msghdr.msg_name )
+        wsa = WS2_make_async ( s, fd, ASYNC_TYPE_WRITE, iovec, dwBufferCount,
+                               &dwFlags, (struct WS_sockaddr*) to, &tolen,
+                               lpOverlapped, lpCompletionRoutine );
+        if ( !wsa )
         {
             err = WSAEFAULT;
             goto err_free;
         }
-    }
-    else
-        msghdr.msg_namelen = 0;
+
+        if ( ( ret = register_new_async ( &wsa->async )) )
+        {
+            err = RtlNtStatusToDosError ( ret );

-    msghdr.msg_iov = iovec;
-    msghdr.msg_iovlen = dwBufferCount;
-    msghdr.msg_control = NULL;
-    msghdr.msg_controllen = 0;
-    msghdr.msg_flags = 0;
+            if ( !lpOverlapped )
+                HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+            HeapFree ( GetProcessHeap(), 0, wsa );
+            goto err_free;
+        }

-    /* FIXME: Treat overlapped IO here */
+        _enable_event ( s, FD_WRITE, 0, 0 );
+
+        /* Try immediate completion */
+        if ( lpOverlapped )
+        {
+            if  ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+                                           lpNumberOfBytesSent, FALSE, &dwFlags) )
+                return 0;
+
+            if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+            {
+                WARN ("err=%d\n", err);
+                goto err_free;
+            }
+        }
+
+        WSASetLastError (WSA_IO_PENDING);
+        return SOCKET_ERROR;
+    }

     if (_is_blocking(s))
     {
@@ -2055,9 +2319,8 @@
         do_block(fd, 2);
     }

-    /* FIXME: can we support MSG_PARTIAL ? How does it relate to sendmsg()'s msg_flags ? */
-
-    if ((n = sendmsg (fd, &msghdr, dwFlags)) == -1)
+    n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
+    if ( n == -1 )
     {
         err = wsaErrno();
         if ( err == WSAEWOULDBLOCK )
@@ -2065,24 +2328,22 @@
         goto err_free;
     }

+    TRACE(" -> %i bytes\n", n);
     *lpNumberOfBytesSent = n;

-    ws_sockaddr_free ( msghdr.msg_name, to );
-    WS_FREE ( iovec );
+    HeapFree ( GetProcessHeap(), 0, iovec );
     close ( fd );
-
     return 0;

 err_free:
-    ws_sockaddr_free ( msghdr.msg_name, to );
-    WS_FREE ( iovec );
+    HeapFree ( GetProcessHeap(), 0, iovec );

 err_close:
     close ( fd );

 error:
     WARN (" -> ERROR %d\n", err);
-    SetLastError (err);
+    WSASetLastError (err);
     return SOCKET_ERROR;
 }

@@ -2686,6 +2947,53 @@
     return SOCKET_ERROR;
 }

+/**********************************************************************
+ *      WSAGetOverlappedResult (WS2_32.40)
+ */
+BOOL WINAPI WSAGetOverlappedResult ( SOCKET s, LPWSAOVERLAPPED lpOverlapped,
+                                     LPDWORD lpcbTransfer, BOOL fWait,
+                                     LPDWORD lpdwFlags )
+{
+    DWORD r;
+
+    TRACE ( "socket %d ovl %p trans %p, wait %d flags %p\n",
+            s, lpOverlapped, lpcbTransfer, fWait, lpdwFlags );
+
+    if ( !(lpOverlapped && lpOverlapped->hEvent) )
+    {
+        ERR ( "Invalid pointer\n" );
+        WSASetLastError (WSA_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    do {
+        r = WaitForSingleObjectEx (lpOverlapped->hEvent, fWait ? INFINITE : 0, TRUE);
+    } while (r == STATUS_USER_APC);
+
+    if ( lpcbTransfer )
+        *lpcbTransfer = lpOverlapped->InternalHigh;
+
+    if ( lpdwFlags )
+        *lpdwFlags = lpOverlapped->Offset;
+
+    TRACE ("r=%lx, int=%lx inth%ld\n", r, lpOverlapped->Internal, lpOverlapped->InternalHigh);
+
+    if ( r == WAIT_OBJECT_0 )
+        return TRUE;
+
+    if ( lpOverlapped->Internal  == STATUS_PENDING )
+        WSASetLastError ( WSA_IO_INCOMPLETE );
+    else
+    {
+        DWORD err = RtlNtStatusToDosError ( lpOverlapped->Internal );
+        WSASetLastError ( err );
+        TRACE ( "Error: %lx\n", err );
+    }
+
+    return FALSE;
+}
+
+
 /***********************************************************************
  *      WSAAsyncSelect			(WS2_32.101)
  */
@@ -3278,6 +3586,105 @@
 }

 /***********************************************************************
+ *              WS2_recv                (INTERNAL)
+ */
+static int WS2_recv ( int fd, struct iovec* iov, int count,
+                      struct WS_sockaddr *lpFrom, LPINT lpFromlen,
+                      LPDWORD lpFlags )
+{
+    struct msghdr hdr;
+    int n;
+    TRACE ( "fd %d, iovec %p, count %d addr %p, len %p, flags %lx\n",
+            fd, iov, count, lpFrom, lpFromlen, *lpFlags);
+
+    hdr.msg_name = NULL;
+
+    if ( lpFrom )
+    {
+#if DEBUG_SOCKADDR
+        dump_sockaddr (lpFrom);
+#endif
+
+        hdr.msg_namelen = *lpFromlen;
+        hdr.msg_name = ws_sockaddr_alloc ( lpFrom, lpFromlen, &hdr.msg_namelen );
+        if ( !hdr.msg_name )
+        {
+            WSASetLastError ( WSAEFAULT );
+            n = -1;
+            goto out;
+        }
+    }
+    else
+        hdr.msg_namelen = 0;
+
+    hdr.msg_iov = iov;
+    hdr.msg_iovlen = count;
+    hdr.msg_control = NULL;
+    hdr.msg_controllen = 0;
+    hdr.msg_flags = 0;
+
+    if ( (n = recvmsg (fd, &hdr, *lpFlags)) == -1 )
+        goto out;
+
+    if ( lpFrom &&
+         ws_sockaddr_u2ws ( hdr.msg_name, hdr.msg_namelen,
+                            lpFrom, lpFromlen ) != 0 )
+    {
+        /* The from buffer was too small, but we read the data
+         * anyway. Is that really bad?
+         */
+        WSASetLastError ( WSAEFAULT );
+        WARN ( "Address buffer too small\n" );
+    }
+
+out:
+
+    ws_sockaddr_free ( hdr.msg_name, lpFrom );
+    return n;
+}
+
+/***********************************************************************
+ *              WS2_async_recv          (INTERNAL)
+ */
+static void WS2_async_recv ( async_private *as )
+{
+    ws2_async* wsa = (ws2_async*) as;
+    int result, err;
+
+    TRACE ( "async %p\n", wsa );
+
+    if ( wsa->overlapped->Internal != STATUS_PENDING )
+    {
+        TRACE ( "status: %ld\n", wsa->overlapped->Internal );
+        return;
+    }
+
+    result = WS2_recv ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
+                        wsa->addr, wsa->addrlen.ptr, &wsa->flags );
+
+    if (result >= 0)
+    {
+        wsa->overlapped->Internal = STATUS_SUCCESS;
+        wsa->overlapped->InternalHigh = result;
+        TRACE ( "received %d bytes\n", result );
+        _enable_event ( (SOCKET) wsa->async.handle, FD_READ, 0, 0 );
+        return;
+    }
+
+    err = errno;
+    if ( err == EAGAIN || err == EINTR )
+    {
+        wsa->overlapped->Internal = STATUS_PENDING;
+        TRACE ( "still pending\n" );
+    }
+    else
+    {
+        wsa->overlapped->Internal = STATUS_UNSUCCESSFUL;
+        TRACE ( "Error: %d\n", errno );
+    }
+}
+
+/***********************************************************************
  *              WSARecvFrom             (WS2_32.69)
  */
 INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
@@ -3286,11 +3693,9 @@
                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )

 {
-    /* Uses recvmsg() in order to provide scatter-gather I/O */
-
+    int i, n, fd, err = WSAENOTSOCK, flags, ret;
     struct iovec* iovec;
-    struct msghdr msghdr;
-    int fd, i, length, err = WSAENOTSOCK, flags;
+    struct ws2_async *wsa;
     enum fd_type type;

     TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
@@ -3299,6 +3704,7 @@
           lpOverlapped, lpCompletionRoutine);

     fd = _get_sock_fd_type( s, &type, &flags );
+    TRACE ( "fd=%d, type=%d, flags=%x\n", fd, type, flags );

     if (fd == -1)
     {
@@ -3306,11 +3712,10 @@
         goto error;
     }

-    /* FIXME: should this be HeapAlloc() or WS_ALLOC ? */
-    iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
+    iovec = HeapAlloc ( GetProcessHeap(), 0, dwBufferCount * sizeof (struct iovec) );
     if ( !iovec )
     {
-        err = WSAENOBUFS;
+        err = WSAEFAULT;
         goto err_close;
     }

@@ -3320,67 +3725,69 @@
         iovec[i].iov_len  = lpBuffers[i].len;
     }

-    msghdr.msg_name = NULL;
-
-    if ( lpFrom )
+    if ( (lpOverlapped || lpCompletionRoutine) && flags & FD_FLAG_OVERLAPPED )
     {
-#if DEBUG_SOCKADDR
-        dump_sockaddr (lpFrom);
-#endif
+        wsa = WS2_make_async ( s, fd, ASYNC_TYPE_READ, iovec, dwBufferCount,
+                               lpFlags, lpFrom, lpFromlen,
+                               lpOverlapped, lpCompletionRoutine );

-        msghdr.msg_namelen = *lpFromlen;
-        msghdr.msg_name = ws_sockaddr_alloc (lpFrom, lpFromlen, &msghdr.msg_namelen);
-    }
-    else
-        msghdr.msg_namelen = 0;
+        if ( !wsa )
+        {
+            err = WSAEFAULT;
+            goto err_free;
+        }
+
+        if ( ( ret = register_new_async ( &wsa->async )) )
+        {
+            err = RtlNtStatusToDosError ( ret );

-    msghdr.msg_iov = iovec;
-    msghdr.msg_iovlen = dwBufferCount;
-    msghdr.msg_control = NULL;
-    msghdr.msg_controllen = 0;
-    msghdr.msg_flags = 0;
+            if ( !lpOverlapped )
+                HeapFree ( GetProcessHeap(), 0, wsa->overlapped );
+            HeapFree ( GetProcessHeap(), 0, wsa );
+            goto err_free;
+        }

-    /* FIXME: Treat overlapped IO here */
+        _enable_event ( s, FD_READ, 0, 0 );

-    if (_is_blocking(s))
+        /* Try immediate completion */
+        if ( lpOverlapped )
+        {
+            if  ( WSAGetOverlappedResult ( (HANDLE) s, lpOverlapped,
+                                           lpNumberOfBytesRecvd, FALSE, lpFlags) )
+                return 0;
+
+            if ( (err = WSAGetLastError ()) != WSA_IO_INCOMPLETE )
+                goto err_free;
+        }
+
+        WSASetLastError ( WSA_IO_PENDING );
+        return SOCKET_ERROR;
+    }
+
+    if ( _is_blocking(s) )
     {
         /* block here */
         /* FIXME: OOB and exceptfds? */
         do_block(fd, 1);
     }
-
-    /* FIXME: can we support MSG_PARTIAL ?
-       How does it relate to recvmsg()'s msg_flags ? */
-
-    if ((length = recvmsg (fd, &msghdr, *lpFlags)) == -1)
+
+    n = WS2_recv ( fd, iovec, dwBufferCount, lpFrom, lpFromlen, lpFlags );
+    if ( n == -1 )
     {
         err = wsaErrno();
         goto err_free;
     }

-    TRACE(" -> %i bytes\n", length);
+    TRACE(" -> %i bytes\n", n);
+    *lpNumberOfBytesRecvd = n;

-    if ( lpFrom && ws_sockaddr_u2ws (msghdr.msg_name, msghdr.msg_namelen, lpFrom, lpFromlen) != 0 )
-    {
-        /* The from buffer was too small, but we read the data
-         * anyway. Is that really bad?
-         */
-        SetLastError ( WSAEFAULT );
-        WARN ( " -> Address buffer too small\n" );
-    }
-
-    *lpNumberOfBytesRecvd = length;
-
-    WS_FREE (iovec);
-    ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+    HeapFree (GetProcessHeap(), 0, iovec);
     close(fd);
     _enable_event(s, FD_READ, 0, 0);
-
     return 0;

 err_free:
-    WS_FREE (iovec);
-    ws_sockaddr_free ( msghdr.msg_name, lpFrom );
+    HeapFree (GetProcessHeap(), 0, iovec);

 err_close:
     close (fd);
diff -ruNX ignore TMP/wine/dlls/winsock/ws2_32.spec MW/wine/dlls/winsock/ws2_32.spec
--- TMP/wine/dlls/winsock/ws2_32.spec	Fri Apr 12 14:55:42 2002
+++ MW/wine/dlls/winsock/ws2_32.spec	Fri Apr 12 15:05:29 2002
@@ -52,7 +52,7 @@
 37  stdcall  WSAEnumProtocolsA(ptr ptr ptr) WSAEnumProtocolsA
 38  stdcall  WSAEnumProtocolsW(ptr ptr ptr) WSAEnumProtocolsW
 39  stdcall  WSAEventSelect(long long long) WSAEventSelect
-40  stub     WSAGetOverlappedResult
+40  stdcall  WSAGetOverlappedResult(long ptr ptr long ptr) WSAGetOverlappedResult
 41  stub     WSAGetQOSByName
 42  stub     WSAGetServiceClassInfoA
 43  stub     WSAGetServiceClassInfoW
diff -ruNX ignore TMP/wine/include/winsock2.h MW/wine/include/winsock2.h
--- TMP/wine/include/winsock2.h	Tue Apr  2 16:51:40 2002
+++ MW/wine/include/winsock2.h	Fri Apr 12 15:05:29 2002
@@ -221,8 +221,7 @@

 #define WSAEVENT      HANDLE
 #define LPWSAEVENT    LPHANDLE
-#define WSAOVERLAPPED OVERLAPPED
-typedef struct _OVERLAPPED* LPWSAOVERLAPPED;
+typedef OVERLAPPED    WSAOVERLAPPED, *LPWSAOVERLAPPED;

 #define WSA_IO_PENDING             (ERROR_IO_PENDING)
 #define WSA_IO_INCOMPLETE          (ERROR_IO_INCOMPLETE)








More information about the wine-devel mailing list