From a891713f48fbcdae05f27f7e73b1cec78cf42644 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 17 May 2021 21:30:01 -0500 Subject: [PATCH] ws2_32: Use IOCTL_AFD_WINE_CONNECT in connect(). Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- 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); -- 2.11.4.GIT