Zebediah Figura : ws2_32: Use IOCTL_AFD_WINE_CONNECT in ConnectEx().

Alexandre Julliard julliard at winehq.org
Tue May 18 15:42:37 CDT 2021


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

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Mon May 17 21:30:00 2021 -0500

ws2_32: Use IOCTL_AFD_WINE_CONNECT in ConnectEx().

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ws2_32/socket.c | 138 ++++++++++++++++++---------------------------------
 1 file changed, 48 insertions(+), 90 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 0c1ba594825..3a39493bc3b 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -3064,116 +3064,74 @@ int WINAPI WSAConnect( SOCKET s, const struct WS_sockaddr* name, int namelen,
     return WS_connect( s, name, namelen );
 }
 
-/***********************************************************************
- *             ConnectEx
- */
-static BOOL WINAPI WS2_ConnectEx(SOCKET s, const struct WS_sockaddr* name, int namelen,
-                          PVOID sendBuf, DWORD sendBufLen, LPDWORD sent, LPOVERLAPPED ov)
-{
-    int fd, ret, status;
 
-    if (!ov)
-    {
-        SetLastError( ERROR_INVALID_PARAMETER );
-        return FALSE;
-    }
+static BOOL WINAPI WS2_ConnectEx( SOCKET s, const struct WS_sockaddr *name, int namelen,
+                                  void *send_buffer, DWORD send_len, DWORD *ret_len, OVERLAPPED *overlapped )
+{
+    union generic_unix_sockaddr uaddr;
+    unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
+    struct afd_connect_params *params;
+    void *cvalue = NULL;
+    NTSTATUS status;
+    int fd, ret;
 
-    fd = get_sock_fd( s, FILE_READ_DATA, NULL );
-    if (fd == -1) return FALSE;
+    TRACE( "socket %#lx, ptr %p %s, length %d, send_buffer %p, send_len %u, overlapped %p\n",
+           s, name, debugstr_sockaddr(name), namelen, send_buffer, send_len, overlapped );
 
-    TRACE("socket %04lx, ptr %p %s, length %d, sendptr %p, len %d, ov %p\n",
-          s, name, debugstr_sockaddr(name), namelen, sendBuf, sendBufLen, ov);
+    if ((fd = get_sock_fd( s, FILE_READ_DATA, NULL )) == -1)
+        return FALSE;
 
-    ret = is_fd_bound(fd, NULL, NULL);
-    if (ret <= 0)
+    if ((ret = is_fd_bound( fd, NULL, NULL )) <= 0)
     {
-        SetLastError(ret == -1 ? wsaErrno() : WSAEINVAL);
+        SetLastError( ret ? wsaErrno() : WSAEINVAL );
         release_sock_fd( s, fd );
         return FALSE;
     }
+    release_sock_fd( s, fd );
 
-    ret = do_connect(fd, name, namelen);
-    if (ret == 0)
+    if (!overlapped)
     {
-        WSABUF wsabuf;
-
-        _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
-                            FD_WINE_CONNECTED|FD_READ|FD_WRITE,
-                            FD_CONNECT|FD_WINE_LISTENING);
-
-        wsabuf.len = sendBufLen;
-        wsabuf.buf = (char*) sendBuf;
-
-        /* WSASend takes care of completion if need be */
-        if (WSASend(s, &wsabuf, sendBuf ? 1 : 0, sent, 0, ov, NULL) != SOCKET_ERROR)
-            goto connection_success;
+        SetLastError( WSA_INVALID_PARAMETER );
+        return FALSE;
     }
-    else if (ret == WSAEWOULDBLOCK)
-    {
-        struct ws2_async *wsa;
-        DWORD size;
-
-        ULONG_PTR cvalue = (((ULONG_PTR)ov->hEvent & 1) == 0) ? (ULONG_PTR)ov : 0;
 
-        _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
-                      FD_CONNECT,
-                      FD_WINE_CONNECTED|FD_WINE_LISTENING);
+    if (!((ULONG_PTR)overlapped->hEvent & 1)) cvalue = overlapped;
+    overlapped->Internal = STATUS_PENDING;
+    overlapped->InternalHigh = 0;
 
-        size = offsetof( struct ws2_async, iovec[1] ) + sendBufLen;
+    if (!uaddrlen)
+    {
+        SetLastError( WSAEFAULT );
+        return SOCKET_ERROR;
+    }
 
-        /* Indirectly call WSASend */
-        if (!(wsa = (struct ws2_async *)alloc_async_io( size, WS2_async_send )))
-        {
-            SetLastError(WSAEFAULT);
-        }
-        else
+    if (name->sa_family == WS_AF_INET)
+    {
+        struct sockaddr_in *in4 = (struct sockaddr_in *)&uaddr;
+        if (!memcmp( &in4->sin_addr, magic_loopback_addr, sizeof(magic_loopback_addr) ))
         {
-            IO_STATUS_BLOCK *iosb = (IO_STATUS_BLOCK *)ov;
-            iosb->u.Status = STATUS_PENDING;
-            iosb->Information = 0;
-
-            wsa->hSocket     = SOCKET2HANDLE(s);
-            wsa->addr        = NULL;
-            wsa->addrlen.val = 0;
-            wsa->flags       = 0;
-            wsa->lpFlags     = &wsa->flags;
-            wsa->control     = NULL;
-            wsa->n_iovecs    = sendBuf ? 1 : 0;
-            wsa->first_iovec = 0;
-            wsa->completion_func = NULL;
-            wsa->iovec[0].iov_base = &wsa->iovec[1];
-            wsa->iovec[0].iov_len  = sendBufLen;
-
-            if (sendBufLen)
-                memcpy( wsa->iovec[0].iov_base, sendBuf, sendBufLen );
-
-            status = register_async( ASYNC_TYPE_WRITE, wsa->hSocket, &wsa->io, ov->hEvent,
-                                      NULL, (void *)cvalue, iosb );
-            if (status != STATUS_PENDING) HeapFree(GetProcessHeap(), 0, wsa);
-
-            /* If the connect already failed */
-            if (status == STATUS_PIPE_DISCONNECTED)
-            {
-                ov->Internal = sock_error_to_ntstatus( get_sock_error( s, FD_CONNECT_BIT  ));
-                ov->InternalHigh = 0;
-                if (cvalue) WS_AddCompletion( s, cvalue, ov->Internal, ov->InternalHigh, TRUE );
-                if (ov->hEvent) NtSetEvent( ov->hEvent, NULL );
-                status = STATUS_PENDING;
-            }
-            SetLastError( NtStatusToWSAError(status) );
+            TRACE("Replacing magic address 127.12.34.56 with INADDR_LOOPBACK.\n");
+            in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
         }
     }
-    else
+
+    if (!(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + uaddrlen + send_len )))
     {
-        SetLastError(ret);
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return SOCKET_ERROR;
     }
+    params->addr_len = uaddrlen;
+    params->synchronous = FALSE;
+    memcpy( params + 1, &uaddr, uaddrlen );
+    memcpy( (char *)(params + 1) + uaddrlen, send_buffer, send_len );
 
-    release_sock_fd( s, fd );
-    return FALSE;
-
-connection_success:
-    release_sock_fd( s, fd );
-    return TRUE;
+    status = NtDeviceIoControlFile( SOCKET2HANDLE(s), overlapped->hEvent, NULL, cvalue,
+                                    (IO_STATUS_BLOCK *)overlapped, IOCTL_AFD_WINE_CONNECT,
+                                    params, sizeof(*params) + uaddrlen + send_len, NULL, 0 );
+    HeapFree( GetProcessHeap(), 0, params );
+    if (ret_len) *ret_len = overlapped->InternalHigh;
+    SetLastError( NtStatusToWSAError( status ) );
+    return !status;
 }
 
 /***********************************************************************




More information about the wine-cvs mailing list