Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 9e7cd3a1d39..75e83927007 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3344,7 +3344,7 @@ static void test_select(void) id = 0xdeadbeef; ret = getsockopt(fdWrite, SOL_SOCKET, SO_ERROR, (char *)&id, &len); ok(!ret, "getsockopt failed with %d\n", WSAGetLastError()); - todo_wine ok(!id, "got error %u\n", id); + ok(!id, "got error %u\n", id);
closesocket(fdWrite);
diff --git a/server/sock.c b/server/sock.c index 58e9cf4302a..5fdbf0bd9ba 100644 --- a/server/sock.c +++ b/server/sock.c @@ -983,7 +983,10 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
case SOCK_CONNECTING: if (event & POLLOUT) + { post_socket_event( sock, AFD_POLL_BIT_CONNECT, 0 ); + sock->errors[AFD_POLL_BIT_CONNECT_ERR] = 0; + } if (event & (POLLERR | POLLHUP)) post_socket_event( sock, AFD_POLL_BIT_CONNECT_ERR, error ); break;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 95 +++++++++++++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 10 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 75e83927007..3e0ac405447 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6576,7 +6576,7 @@ static void test_WSAPoll(void) closesocket(server); }
-static void test_ConnectEx(void) +static void test_connect(void) { SOCKET listener = INVALID_SOCKET; SOCKET acceptor = INVALID_SOCKET; @@ -6610,6 +6610,9 @@ static void test_ConnectEx(void) iret = getsockname(listener, (struct sockaddr*)&address, &addrlen); ok(!iret, "failed to get address, error %u\n", WSAGetLastError());
+ iret = listen(listener, 1); + ok(!iret, "failed to listen, error %u\n", WSAGetLastError()); + iret = set_blocking(listener, TRUE); ok(!iret, "failed to set nonblocking, error %u\n", WSAGetLastError());
@@ -6620,6 +6623,20 @@ static void test_ConnectEx(void)
ok(bytesReturned == sizeof(pConnectEx), "expected sizeof(pConnectEx), got %u\n", bytesReturned);
+ WSASetLastError(0xdeadbeef); + iret = connect(listener, (struct sockaddr *)&address, sizeof(address)); + ok(iret == -1, "got %d\n", iret); + todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + iret = pConnectEx(listener, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); + ok(!iret, "got %d\n", iret); + todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); + ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + bret = pConnectEx(INVALID_SOCKET, (struct sockaddr*)&address, addrlen, NULL, 0, &bytesReturned, &overlapped); ok(bret == FALSE && WSAGetLastError() == WSAENOTSOCK, "ConnectEx on invalid socket " "returned %d + errno %d\n", bret, WSAGetLastError()); @@ -6641,9 +6658,6 @@ static void test_ConnectEx(void)
overlapped.hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
- iret = listen(listener, 1); - ok(!iret, "failed to listen, error %u\n", WSAGetLastError()); - bret = pConnectEx(connector, (struct sockaddr*)&address, addrlen, NULL, 0, &bytesReturned, &overlapped); ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "ConnectEx failed: " "returned %d + errno %d\n", bret, WSAGetLastError()); @@ -6690,7 +6704,73 @@ static void test_ConnectEx(void) ok(buffer[0] == '1' && buffer[1] == '2' && buffer[2] == '3', "Failed to get the right data, expected '123', got '%s'\n", buffer);
+ WSASetLastError(0xdeadbeef); + iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); + todo_wine ok(iret == -1, "got %d\n", iret); + todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + iret = connect(acceptor, (struct sockaddr *)&address, sizeof(address)); + ok(iret == -1, "got %d\n", iret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + bret = pConnectEx(connector, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); + ok(!bret, "got %d\n", bret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + + WSASetLastError(0xdeadbeef); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + bret = pConnectEx(acceptor, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); + ok(!bret, "got %d\n", bret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + closesocket(connector); + closesocket(acceptor); + closesocket(listener); + + tcp_socketpair(&connector, &acceptor); + + WSASetLastError(0xdeadbeef); + iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); + todo_wine ok(iret == -1, "got %d\n", iret); + todo_wine ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + iret = connect(acceptor, (struct sockaddr *)&address, sizeof(address)); + ok(iret == -1, "got %d\n", iret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + bret = pConnectEx(connector, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); + ok(!bret, "got %d\n", bret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + + WSASetLastError(0xdeadbeef); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + bret = pConnectEx(acceptor, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); + ok(!bret, "got %d\n", bret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + + closesocket(connector); + closesocket(acceptor); + + /* Connect with error */ + connector = socket(AF_INET, SOCK_STREAM, 0); ok(connector != INVALID_SOCKET, "failed to create socket, error %u\n", WSAGetLastError()); /* ConnectEx needs a bound socket */ @@ -6700,11 +6780,6 @@ static void test_ConnectEx(void) iret = bind(connector, (struct sockaddr*)&conaddress, sizeof(conaddress)); ok(!iret, "failed to bind, error %u\n", WSAGetLastError());
- closesocket(acceptor); - closesocket(listener); - - /* Connect with error */ - address.sin_port = htons(1);
bret = pConnectEx(connector, (struct sockaddr*)&address, addrlen, NULL, 0, &bytesReturned, &overlapped); @@ -11264,7 +11339,7 @@ START_TEST( sock ) test_ipv6only(); test_TransmitFile(); test_AcceptEx(); - test_ConnectEx(); + test_connect(); test_shutdown(); test_DisconnectEx();
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51381 Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 10 +++++----- server/sock.c | 23 ++++++++++++++++++----- 2 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 3e0ac405447..97b772e12d9 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6626,14 +6626,14 @@ static void test_connect(void) WSASetLastError(0xdeadbeef); iret = connect(listener, (struct sockaddr *)&address, sizeof(address)); ok(iret == -1, "got %d\n", iret); - todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError());
WSASetLastError(0xdeadbeef); overlapped.Internal = 0xdeadbeef; overlapped.InternalHigh = 0xdeadbeef; iret = pConnectEx(listener, (struct sockaddr *)&address, sizeof(address), NULL, 0, &bytesReturned, &overlapped); ok(!iret, "got %d\n", iret); - todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError()); ok(overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh);
@@ -6706,7 +6706,7 @@ static void test_connect(void)
WSASetLastError(0xdeadbeef); iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); - todo_wine ok(iret == -1, "got %d\n", iret); + ok(iret == -1, "got %d\n", iret); todo_wine ok(WSAGetLastError() == WSAEINVAL, "got error %u\n", WSAGetLastError());
WSASetLastError(0xdeadbeef); @@ -6740,8 +6740,8 @@ static void test_connect(void)
WSASetLastError(0xdeadbeef); iret = connect(connector, (struct sockaddr *)&address, sizeof(address)); - todo_wine ok(iret == -1, "got %d\n", iret); - todo_wine ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError()); + ok(iret == -1, "got %d\n", iret); + ok(WSAGetLastError() == WSAEISCONN, "got error %u\n", WSAGetLastError());
WSASetLastError(0xdeadbeef); iret = connect(acceptor, (struct sockaddr *)&address, sizeof(address)); diff --git a/server/sock.c b/server/sock.c index 5fdbf0bd9ba..3f0526016f9 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2164,12 +2164,25 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
- if (sock->state == SOCK_CONNECTING) + switch (sock->state) { - /* FIXME: STATUS_ADDRESS_ALREADY_ASSOCIATED probably isn't right, - * but there's no status code that maps to WSAEALREADY... */ - set_error( params->synchronous ? STATUS_ADDRESS_ALREADY_ASSOCIATED : STATUS_INVALID_PARAMETER ); - return 0; + case SOCK_LISTENING: + set_error( STATUS_INVALID_PARAMETER ); + return 0; + + case SOCK_CONNECTING: + /* FIXME: STATUS_ADDRESS_ALREADY_ASSOCIATED probably isn't right, + * but there's no status code that maps to WSAEALREADY... */ + set_error( params->synchronous ? STATUS_ADDRESS_ALREADY_ASSOCIATED : STATUS_INVALID_PARAMETER ); + return 0; + + case SOCK_CONNECTED: + set_error( STATUS_CONNECTION_ACTIVE ); + return 0; + + case SOCK_UNCONNECTED: + case SOCK_CONNECTIONLESS: + break; }
unix_len = sockaddr_to_unix( addr, params->addr_len, &unix_addr );
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 4 +++- include/wine/afd.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 3f2dfe7c1f2..04917d19e92 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1736,6 +1736,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc } #endif
+ case IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP: + return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_MEMBERSHIP, in_buffer, in_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 10e79d3f8ff..48b9fe8c594 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3637,6 +3637,9 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, case WS_IP_DONTFRAGMENT: return server_setsockopt( s, IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT, optval, optlen );
+ case WS_IP_DROP_MEMBERSHIP: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP, optval, optlen ); + case WS_IP_DROP_SOURCE_MEMBERSHIP: case WS_IP_UNBLOCK_SOURCE: { @@ -3651,7 +3654,6 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, convert_sockopt(&level, &optname); break; } - case WS_IP_DROP_MEMBERSHIP: #ifdef IP_HDRINCL case WS_IP_HDRINCL: #endif diff --git a/include/wine/afd.h b/include/wine/afd.h index 5b4114f4d77..c660e982d0e 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -186,6 +186,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_SET_IP_BLOCK_SOURCE WINE_AFD_IOC(241) #define IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT WINE_AFD_IOC(242) #define IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT WINE_AFD_IOC(243) +#define IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP WINE_AFD_IOC(244)
struct afd_create_params {
From: Zebediah Figura z.figura12@gmail.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/socket.c | 3 +++ dlls/ws2_32/socket.c | 2 ++ include/wine/afd.h | 1 + 3 files changed, 6 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 04917d19e92..46ed673b81e 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1739,6 +1739,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc case IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP: return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_MEMBERSHIP, in_buffer, in_size );
+ case IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP: + return do_setsockopt( handle, io, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, in_buffer, in_size ); + default: { if ((code >> 16) == FILE_DEVICE_NETWORK) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 48b9fe8c594..09f04fff60f 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3641,6 +3641,8 @@ int WINAPI WS_setsockopt(SOCKET s, int level, int optname, return server_setsockopt( s, IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP, optval, optlen );
case WS_IP_DROP_SOURCE_MEMBERSHIP: + return server_setsockopt( s, IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP, optval, optlen ); + case WS_IP_UNBLOCK_SOURCE: { WS_IP_MREQ_SOURCE* val = (void*)optval; diff --git a/include/wine/afd.h b/include/wine/afd.h index c660e982d0e..93c1744c031 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -187,6 +187,7 @@ struct afd_get_events_params #define IOCTL_AFD_WINE_GET_IP_DONTFRAGMENT WINE_AFD_IOC(242) #define IOCTL_AFD_WINE_SET_IP_DONTFRAGMENT WINE_AFD_IOC(243) #define IOCTL_AFD_WINE_SET_IP_DROP_MEMBERSHIP WINE_AFD_IOC(244) +#define IOCTL_AFD_WINE_SET_IP_DROP_SOURCE_MEMBERSHIP WINE_AFD_IOC(245)
struct afd_create_params {