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

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


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

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

ws2_32: Use IOCTL_AFD_WINE_CONNECT in connect().

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

---

 dlls/ws2_32/socket.c     | 106 ++++++++++++++++++-----------------------------
 dlls/ws2_32/tests/sock.c |  21 +---------
 2 files changed, 43 insertions(+), 84 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index 3a39493bc3b..889f0327baf 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -1145,13 +1145,6 @@ static void _get_sock_errors(SOCKET s, int *events)
     SERVER_END_REQ;
 }
 
-static int get_sock_error(SOCKET s, unsigned int bit)
-{
-    int events[FD_MAX_EVENTS];
-    _get_sock_errors(s, events);
-    return events[bit];
-}
-
 static int _get_fd_type(int fd)
 {
     int sock_type = -1;
@@ -2976,82 +2969,65 @@ int WINAPI WS_closesocket(SOCKET s)
     return res;
 }
 
-static int do_connect(int fd, const struct WS_sockaddr* name, int namelen)
+
+/***********************************************************************
+ *      connect   (ws2_32.4)
+ */
+int WINAPI WS_connect( SOCKET s, const struct WS_sockaddr *addr, int len )
 {
     union generic_unix_sockaddr uaddr;
-    unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
+    unsigned int uaddrlen = ws_sockaddr_ws2u( addr, len, &uaddr );
+    struct afd_connect_params *params;
+    IO_STATUS_BLOCK io;
+    HANDLE sync_event;
+    NTSTATUS status;
+
+    TRACE( "socket %#lx, addr %s, len %d\n", s, debugstr_sockaddr(addr), len );
 
     if (!uaddrlen)
-        return WSAEFAULT;
+    {
+        SetLastError( WSAEFAULT );
+        return -1;
+    }
 
-    if (name->sa_family == WS_AF_INET)
+    if (addr->sa_family == WS_AF_INET)
     {
-        struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
-        if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
+        struct sockaddr_in *in4 = (struct sockaddr_in *)&uaddr;
+        if (!memcmp(&in4->sin_addr, magic_loopback_addr, sizeof(magic_loopback_addr)))
         {
-            /* Trying to connect to magic replace-loopback address,
-                * assuming we really want to connect to localhost */
-            TRACE("Trying to connect to magic IP address, using "
-                    "INADDR_LOOPBACK instead.\n");
+            TRACE("Replacing magic address 127.12.34.56 with INADDR_LOOPBACK.\n");
             in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
         }
     }
 
-    if (connect(fd, &uaddr.addr, uaddrlen) == 0)
-        return 0;
-
-    return wsaErrno();
-}
-
-/***********************************************************************
- *		connect		(WS2_32.4)
- */
-int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
-{
-    int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
+    if (!(sync_event = get_sync_event())) return -1;
 
-    TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
-
-    if (fd != -1)
+    if (!(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + uaddrlen )))
     {
-        BOOL is_blocking;
-        int ret = do_connect(fd, name, namelen);
-        if (ret == 0)
-            goto connect_success;
-
-        if (ret == WSAEWOULDBLOCK)
-        {
-            /* tell wineserver that a connection is in progress */
-            _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
-                          FD_CONNECT,
-                          FD_WINE_CONNECTED|FD_WINE_LISTENING);
-            ret = sock_is_blocking( s, &is_blocking );
-            if (!ret)
-            {
-                if (is_blocking)
-                {
-                    do_block(fd, POLLIN | POLLOUT, -1);
-                    _sync_sock_state(s); /* let wineserver notice connection */
-                    /* retrieve any error codes from it */
-                    if (!(ret = get_sock_error(s, FD_CONNECT_BIT))) goto connect_success;
-                }
-                else ret = WSAEWOULDBLOCK;
-            }
-        }
-        release_sock_fd( s, fd );
-        SetLastError(ret);
+        SetLastError( ERROR_NOT_ENOUGH_MEMORY );
+        return -1;
     }
-    return SOCKET_ERROR;
+    params->addr_len = uaddrlen;
+    params->synchronous = TRUE;
+    memcpy(params + 1, &uaddr, uaddrlen);
 
-connect_success:
-    release_sock_fd( s, fd );
-    _enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
-                  FD_WINE_CONNECTED|FD_READ|FD_WRITE,
-                  FD_CONNECT|FD_WINE_LISTENING);
-    TRACE("\tconnected %04lx\n", s);
+    status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_WINE_CONNECT,
+                                    params, sizeof(*params) + uaddrlen, NULL, 0);
+    HeapFree( GetProcessHeap(), 0, params );
+    if (status == STATUS_PENDING)
+    {
+        if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) return -1;
+        status = io.u.Status;
+    }
+    if (status)
+    {
+        SetLastError( NtStatusToWSAError( status ) );
+        return -1;
+    }
     return 0;
 }
 
+
 /***********************************************************************
  *              WSAConnect             (WS2_32.30)
  */
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index 33cdd5d6d15..5028a4e749e 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -4159,7 +4159,7 @@ static void test_connect_events(struct event_test_ctx *ctx)
     if (ctx->is_message)
         check_events(ctx, FD_WRITE, 0, 200);
     else
-        check_events_todo(ctx, FD_CONNECT, FD_WRITE, 200);
+        check_events(ctx, FD_CONNECT, FD_WRITE, 200);
 
     closesocket(client);
     closesocket(server);
@@ -6117,25 +6117,8 @@ todo_wine
 
     /* try to connect a socket that's being accepted into */
     iret = connect(acceptor,  (struct sockaddr*)&bindAddress, sizeof(bindAddress));
-    todo_wine ok(iret == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL,
+    ok(iret == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL,
        "connecting to acceptex acceptor succeeded? return %d + errno %d\n", iret, WSAGetLastError());
-    if (!iret || (iret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)) {
-        /* We need to cancel this call, otherwise things fail */
-        closesocket(acceptor);
-        acceptor = socket(AF_INET, SOCK_STREAM, 0);
-        ok(acceptor != INVALID_SOCKET, "failed to create socket, error %u\n", GetLastError());
-
-        bret = CancelIo((HANDLE) listener);
-        ok(bret, "Failed to cancel failed test. Bailing...\n");
-        if (!bret) return;
-
-        overlapped.Internal = 0xdeadbeef;
-        bret = pAcceptEx(listener, acceptor, buffer, 0,
-            sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
-            &bytesReturned, &overlapped);
-        ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx returned %d + errno %d\n", bret, WSAGetLastError());
-        ok(overlapped.Internal == STATUS_PENDING, "got %08x\n", (ULONG)overlapped.Internal);
-    }
 
     bret = pConnectEx(acceptor, (struct sockaddr *)&bindAddress, sizeof(bindAddress),
             NULL, 0, &bytesReturned, &overlapped2);




More information about the wine-cvs mailing list