Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 73 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index d9cb629caa4..6cfdced79dc 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -10219,25 +10219,51 @@ static void test_bind(void) /* Test calling methods on a socket which is currently connecting. */ static void test_connecting_socket(void) { + const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_ANY)}; const struct sockaddr_in invalid_addr = { .sin_family = AF_INET, .sin_addr.s_addr = inet_addr("192.0.2.0"), .sin_port = 255 }; + OVERLAPPED overlapped = {0}, overlapped2 = {0}; + GUID connectex_guid = WSAID_CONNECTEX; + LPFN_CONNECTEX pConnectEx; struct sockaddr_in addr; char buffer[4]; SOCKET client; int ret, len; + DWORD size;
client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); set_blocking(client, FALSE);
+ ret = bind(client, (const struct sockaddr *)&bind_addr, sizeof(bind_addr)); + ok(!ret, "expected success\n"); + ok(!WSAGetLastError(), "got %u\n", WSAGetLastError()); + ret = connect(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr)); ok(ret == -1, "got %d\n", ret); ok(WSAGetLastError() == WSAEWOULDBLOCK, "got %u\n", WSAGetLastError());
+ /* Mortal Kombat 11 connects to the same address twice and expects the + * second to return WSAEALREADY. */ + ret = connect(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr)); + ok(ret == -1, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAEALREADY, "got %u\n", WSAGetLastError()); + + ret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &connectex_guid, sizeof(connectex_guid), + &pConnectEx, sizeof(pConnectEx), &size, NULL, NULL); + ok(!ret, "failed to get ConnectEx, error %u\n", WSAGetLastError()); + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + ret = pConnectEx(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr), NULL, 0, &size, &overlapped); + ok(!ret, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); + ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + len = sizeof(addr); ret = getsockname(client, (struct sockaddr *)&addr, &len); ok(!ret, "got error %u\n", WSAGetLastError()); @@ -10263,6 +10289,53 @@ static void test_connecting_socket(void) todo_wine ok(WSAGetLastError() == WSAENOTCONN, "got %u\n", WSAGetLastError());
closesocket(client); + + /* Test with ConnectEx(). */ + + client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(client != -1, "failed to create socket, error %u\n", WSAGetLastError()); + set_blocking(client, FALSE); + + ret = bind(client, (const struct sockaddr *)&bind_addr, sizeof(bind_addr)); + ok(!ret, "expected success\n"); + ok(!WSAGetLastError(), "got %u\n", WSAGetLastError()); + + ret = pConnectEx(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr), NULL, 0, &size, &overlapped2); + ok(!ret, "got %d\n", ret); + ok(WSAGetLastError() == ERROR_IO_PENDING, "got error %u\n", WSAGetLastError()); + + ret = connect(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr)); + ok(ret == -1, "got %d\n", ret); + ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); + + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + ret = pConnectEx(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr), NULL, 0, &size, &overlapped); + ok(!ret, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); + ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); + todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh); + + len = sizeof(addr); + ret = getsockname(client, (struct sockaddr *)&addr, &len); + ok(!ret, "got error %u\n", WSAGetLastError()); + ok(addr.sin_family == AF_INET, "got family %u\n", addr.sin_family); + ok(addr.sin_port, "expected nonzero port\n"); + + len = sizeof(addr); + ret = getpeername(client, (struct sockaddr *)&addr, &len); + ok(ret == -1, "got %d\n", ret); + ok(WSAGetLastError() == WSAENOTCONN, "got %u\n", WSAGetLastError()); + + ret = recv(client, buffer, sizeof(buffer), 0); + ok(ret == -1, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAENOTCONN, "got %u\n", WSAGetLastError()); + + ret = send(client, "data", 5, 0); + ok(ret == -1, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAENOTCONN, "got %u\n", WSAGetLastError()); + + closesocket(client); }
static DWORD map_status( NTSTATUS status )
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 6cfdced79dc..95bf7a12830 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -10312,7 +10312,7 @@ static void test_connecting_socket(void) overlapped.InternalHigh = 0xdeadbeef; ret = pConnectEx(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr), NULL, 0, &size, &overlapped); ok(!ret, "got %d\n", ret); - todo_wine ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh);
diff --git a/server/sock.c b/server/sock.c index f2450fcc541..cae0c2ff32b 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1780,7 +1780,7 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
if (sock->connect_req) { - set_error( params->synchronous ? STATUS_INVALID_PARAMETER : STATUS_CONNECTION_ACTIVE ); + set_error( STATUS_INVALID_PARAMETER ); return 0; }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92238
Your paranoid android.
=== debiant2 (32 bit Arabic:Morocco report) ===
ws2_32: sock.c:4665: Test failed: got events 0x10 sock.c:4666: Test failed: expected timeout sock.c:4666: Test failed: got events 0x2
Fixes connection in Mortal Kombat 11; reported by Thomas Crider.
Fixes: a891713f48fbcdae05f27f7e73b1cec78cf42644 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 3 ++- dlls/ws2_32/tests/sock.c | 4 ++-- server/sock.c | 8 ++++++++ 3 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index a4d0e932eae..5f0d712f5b7 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2222,7 +2222,8 @@ int WINAPI WS_connect( SOCKET s, const struct WS_sockaddr *addr, int len ) } if (status) { - SetLastError( NtStatusToWSAError( status ) ); + /* NtStatusToWSAError() has no mapping for WSAEALREADY */ + SetLastError( status == STATUS_ADDRESS_ALREADY_ASSOCIATED ? WSAEALREADY : NtStatusToWSAError( status ) ); return -1; } return 0; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 95bf7a12830..d581b1df6c1 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -10251,7 +10251,7 @@ static void test_connecting_socket(void) * second to return WSAEALREADY. */ ret = connect(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr)); ok(ret == -1, "got %d\n", ret); - todo_wine ok(WSAGetLastError() == WSAEALREADY, "got %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEALREADY, "got %u\n", WSAGetLastError());
ret = WSAIoctl(client, SIO_GET_EXTENSION_FUNCTION_POINTER, &connectex_guid, sizeof(connectex_guid), &pConnectEx, sizeof(pConnectEx), &size, NULL, NULL); @@ -10260,7 +10260,7 @@ static void test_connecting_socket(void) overlapped.InternalHigh = 0xdeadbeef; ret = pConnectEx(client, (struct sockaddr *)&invalid_addr, sizeof(invalid_addr), NULL, 0, &size, &overlapped); ok(!ret, "got %d\n", ret); - todo_wine ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEINVAL, "got %u\n", WSAGetLastError()); ok((NTSTATUS)overlapped.Internal == STATUS_PENDING, "got status %#x\n", (NTSTATUS)overlapped.Internal); todo_wine ok(overlapped.InternalHigh == 0xdeadbeef, "got size %Iu\n", overlapped.InternalHigh);
diff --git a/server/sock.c b/server/sock.c index cae0c2ff32b..b4649abbf08 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1784,6 +1784,14 @@ static int sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) return 0; }
+ if (sock->state & FD_CONNECT) + { + /* 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; + } + ret = connect( unix_fd, addr, params->addr_len ); if (ret < 0 && errno != EINPROGRESS) {
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 98 ++++++-------------------------------------- 1 file changed, 13 insertions(+), 85 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 5f0d712f5b7..843ec5ba3ab 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -473,8 +473,6 @@ static int ws_protocol_info(SOCKET s, int unicode, WSAPROTOCOL_INFOW *buffer, in int WSAIOCTL_GetInterfaceCount(void); int WSAIOCTL_GetInterfaceName(int intNumber, char *intName);
-static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, ULONG Information, BOOL force ); - #define MAP_OPTION(opt) { WS_##opt, opt }
static const int ws_sock_map[][2] = @@ -646,45 +644,6 @@ static UINT wsaErrno(void) return sock_get_error( loc_errno ); }
-static NTSTATUS sock_error_to_ntstatus( DWORD err ) -{ - switch (err) - { - case 0: return STATUS_SUCCESS; - case WSAEBADF: return STATUS_INVALID_HANDLE; - case WSAEACCES: return STATUS_ACCESS_DENIED; - case WSAEFAULT: return STATUS_ACCESS_VIOLATION; - case WSAEINVAL: return STATUS_INVALID_PARAMETER; - case WSAEMFILE: return STATUS_TOO_MANY_OPENED_FILES; - case WSAEINPROGRESS: - case WSAEWOULDBLOCK: return STATUS_DEVICE_NOT_READY; - case WSAEALREADY: return STATUS_NETWORK_BUSY; - case WSAENOTSOCK: return STATUS_OBJECT_TYPE_MISMATCH; - case WSAEDESTADDRREQ: return STATUS_INVALID_PARAMETER; - case WSAEMSGSIZE: return STATUS_BUFFER_OVERFLOW; - case WSAEPROTONOSUPPORT: - case WSAESOCKTNOSUPPORT: - case WSAEPFNOSUPPORT: - case WSAEAFNOSUPPORT: - case WSAEPROTOTYPE: return STATUS_NOT_SUPPORTED; - case WSAENOPROTOOPT: return STATUS_INVALID_PARAMETER; - case WSAEOPNOTSUPP: return STATUS_NOT_SUPPORTED; - case WSAEADDRINUSE: return STATUS_SHARING_VIOLATION; - case WSAEADDRNOTAVAIL: return STATUS_INVALID_PARAMETER; - case WSAECONNREFUSED: return STATUS_CONNECTION_REFUSED; - case WSAESHUTDOWN: return STATUS_PIPE_DISCONNECTED; - case WSAENOTCONN: return STATUS_INVALID_CONNECTION; - case WSAETIMEDOUT: return STATUS_IO_TIMEOUT; - case WSAENETUNREACH: return STATUS_NETWORK_UNREACHABLE; - case WSAENETDOWN: return STATUS_NETWORK_BUSY; - case WSAECONNRESET: return STATUS_CONNECTION_RESET; - case WSAECONNABORTED: return STATUS_CONNECTION_ABORTED; - default: - FIXME("unmapped error %u\n", err); - return STATUS_UNSUCCESSFUL; - } -} - static DWORD NtStatusToWSAError( NTSTATUS status ) { static const struct @@ -3224,8 +3183,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID DWORD out_size, LPDWORD ret_size, LPWSAOVERLAPPED overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion ) { - DWORD status = 0, total = 0; - TRACE("%04lx, %s, %p, %d, %p, %d, %p, %p, %p\n", s, debugstr_wsaioctl(code), in_buff, in_size, out_buff, out_size, ret_size, overlapped, completion);
@@ -3290,7 +3247,7 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID
case WS_SIO_ADDRESS_LIST_QUERY: { - DWORD size; + DWORD size, total;
TRACE("-> SIO_ADDRESS_LIST_QUERY request\n");
@@ -3483,10 +3440,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return ret ? -1 : 0; }
- case WS_SIO_UDP_CONNRESET: - FIXME("WS_SIO_UDP_CONNRESET stub\n"); - break; - case WS_SIO_ADDRESS_LIST_CHANGE: { int force_async = !!overlapped; @@ -3498,6 +3451,18 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return ret ? -1 : 0; }
+ case WS_SIO_UDP_CONNRESET: + { + NTSTATUS status = STATUS_SUCCESS; + DWORD ret; + + FIXME( "WS_SIO_UDP_CONNRESET stub\n" ); + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_COMPLETE_ASYNC, &status, sizeof(status), + NULL, 0, ret_size, overlapped, completion ); + SetLastError( ret ); + return ret ? -1 : 0; + } + default: FIXME( "unimplemented ioctl %s\n", debugstr_wsaioctl( code ) ); /* fall through */ @@ -3520,27 +3485,6 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return -1; } } - - if (completion) - { - FIXME( "completion routine %p not supported\n", completion ); - } - else if (overlapped) - { - ULONG_PTR cvalue = (overlapped && ((ULONG_PTR)overlapped->hEvent & 1) == 0) ? (ULONG_PTR)overlapped : 0; - overlapped->Internal = sock_error_to_ntstatus( status ); - overlapped->InternalHigh = total; - if (cvalue) WS_AddCompletion( HANDLE2SOCKET(s), cvalue, overlapped->Internal, total, FALSE ); - if (overlapped->hEvent) NtSetEvent( overlapped->hEvent, NULL ); - } - - if (!status) - { - *ret_size = total; - return 0; - } - SetLastError( status ); - return SOCKET_ERROR; }
@@ -3922,22 +3866,6 @@ int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout) return ret; }
-/* helper to send completion messages for client-only i/o operation case */ -static void WS_AddCompletion( SOCKET sock, ULONG_PTR CompletionValue, NTSTATUS CompletionStatus, - ULONG Information, BOOL async ) -{ - SERVER_START_REQ( add_fd_completion ) - { - req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) ); - req->cvalue = CompletionValue; - req->status = CompletionStatus; - req->information = Information; - req->async = async; - wine_server_call( req ); - } - SERVER_END_REQ; -} -
/*********************************************************************** * send (WS2_32.19)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=92240
Your paranoid android.
=== debiant2 (32 bit report) ===
ws2_32: sock.c:4665: Test failed: got events 0x10 sock.c:4666: Test failed: expected timeout sock.c:4666: Test failed: got events 0x2
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50520 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ws2_32/socket.c | 22 ++++++++++ dlls/ws2_32/tests/sock.c | 92 ++++++++++++++++++++++++++++++++++++++++ include/mswsock.h | 10 +++-- 3 files changed, 120 insertions(+), 4 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 843ec5ba3ab..f4e3a6c9e43 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -3463,6 +3463,28 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return ret ? -1 : 0; }
+ case WS_SIO_BASE_HANDLE: + { + NTSTATUS status; + DWORD ret; + + if (overlapped) + { + status = STATUS_NOT_SUPPORTED; + } + else + { + status = STATUS_SUCCESS; + *(SOCKET *)out_buff = s; + } + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_COMPLETE_ASYNC, &status, sizeof(status), + NULL, 0, ret_size, overlapped, completion ); + if (overlapped) ret = ERROR_IO_PENDING; + if (!ret) *ret_size = sizeof(SOCKET); + SetLastError( ret ); + return ret ? -1 : 0; + } + default: FIXME( "unimplemented ioctl %s\n", debugstr_wsaioctl( code ) ); /* fall through */ diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index d581b1df6c1..76d0a3f3b19 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -4275,6 +4275,97 @@ static void test_get_extension_func(void) closesocket(s); }
+static void test_base_handle(void) +{ + OVERLAPPED overlapped = {0}, *overlapped_ptr; + unsigned int i; + SOCKET s, base; + ULONG_PTR key; + HANDLE port; + DWORD size; + int ret; + + static const struct + { + int family, type, protocol; + } + tests[] = + { + {AF_INET, SOCK_STREAM, IPPROTO_TCP}, + {AF_INET, SOCK_DGRAM, IPPROTO_UDP}, + {AF_INET6, SOCK_STREAM, IPPROTO_TCP}, + {AF_INET6, SOCK_DGRAM, IPPROTO_UDP}, + }; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + s = socket(tests[i].family, tests[i].type, tests[i].protocol); + if (s == INVALID_SOCKET) continue; + port = CreateIoCompletionPort((HANDLE)s, NULL, 123, 0); + + WSASetLastError(0xdeadbeef); + ret = WSAIoctl(s, SIO_BASE_HANDLE, NULL, 0, &base, sizeof(base), NULL, &overlapped, NULL); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); + + WSASetLastError(0xdeadbeef); + size = 0xdeadbeef; + base = 0xdeadbeef; + ret = WSAIoctl(s, SIO_BASE_HANDLE, NULL, 0, &base, sizeof(base), &size, NULL, NULL); + ok(!ret, "expected success\n"); + ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError()); + ok(size == sizeof(base), "got size %u\n", size); + ok(base == s, "expected %#Ix, got %#Ix\n", s, base); + + WSASetLastError(0xdeadbeef); + size = 0xdeadbeef; + base = 0xdeadbeef; + overlapped.Internal = 0xdeadbeef; + overlapped.InternalHigh = 0xdeadbeef; + ret = WSAIoctl(s, SIO_BASE_HANDLE, NULL, 0, &base, sizeof(base), &size, &overlapped, NULL); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == ERROR_IO_PENDING, "got error %u\n", WSAGetLastError()); + ok(size == 0xdeadbeef, "got size %u\n", size); + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_NOT_SUPPORTED, "got error %u\n", GetLastError()); + ok(!size, "got size %u\n", size); + ok(key == 123, "got key %Iu\n", key); + ok(overlapped_ptr == &overlapped, "got overlapped %p\n", overlapped_ptr); + ok((NTSTATUS)overlapped.Internal == STATUS_NOT_SUPPORTED, "got status %#x\n", (NTSTATUS)overlapped.Internal); + ok(!overlapped.InternalHigh, "got size %Iu\n", overlapped.InternalHigh); + ok(base == 0xdeadbeef, "expected %#Ix, got %#Ix\n", s, base); + + CloseHandle(port); + closesocket(s); + + s = socket(tests[i].family, tests[i].type, tests[i].protocol); + + ret = WSAIoctl(s, SIO_BASE_HANDLE, NULL, 0, &base, sizeof(base), NULL, &overlapped, socket_apc); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); + + apc_count = 0; + size = 0xdeadbeef; + base = 0xdeadbeef; + ret = WSAIoctl(s, SIO_BASE_HANDLE, NULL, 0, &base, sizeof(base), &size, &overlapped, socket_apc); + ok(ret == -1, "expected failure\n"); + ok(WSAGetLastError() == ERROR_IO_PENDING, "got error %u\n", WSAGetLastError()); + ok(size == 0xdeadbeef, "got size %u\n", size); + + ret = SleepEx(0, TRUE); + ok(ret == WAIT_IO_COMPLETION, "got %d\n", ret); + ok(apc_count == 1, "APC was called %u times\n", apc_count); + ok(apc_error == WSAEOPNOTSUPP, "got APC error %u\n", apc_error); + ok(!apc_size, "got APC size %u\n", apc_size); + ok(apc_overlapped == &overlapped, "got APC overlapped %p\n", apc_overlapped); + ok(base == 0xdeadbeef, "expected %#Ix, got %#Ix\n", s, base); + + closesocket(s); + } +} + static BOOL drain_pause = FALSE; static DWORD WINAPI drain_socket_thread(LPVOID arg) { @@ -10837,6 +10928,7 @@ START_TEST( sock ) test_keepalive_vals(); test_sioRoutingInterfaceQuery(); test_sioAddressListChange(); + test_base_handle(); test_unsupported_ioctls();
test_WSASendMsg(); diff --git a/include/mswsock.h b/include/mswsock.h index e402f33ecf7..fa97d5bf04d 100644 --- a/include/mswsock.h +++ b/include/mswsock.h @@ -83,11 +83,13 @@ extern "C" { #endif
#ifndef USE_WS_PREFIX -#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) -#define SIO_SET_COMPATIBILITY_MODE _WSAIOW(IOC_VENDOR,300) +#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12) +#define SIO_SET_COMPATIBILITY_MODE _WSAIOW(IOC_VENDOR, 300) +#define SIO_BASE_HANDLE _WSAIOR(IOC_WS2, 34) #else -#define WS_SIO_UDP_CONNRESET _WSAIOW(WS_IOC_VENDOR,12) -#define WS_SIO_SET_COMPATIBILITY_MODE _WSAIOW(WS_IOC_VENDOR,300) +#define WS_SIO_UDP_CONNRESET _WSAIOW(WS_IOC_VENDOR, 12) +#define WS_SIO_SET_COMPATIBILITY_MODE _WSAIOW(WS_IOC_VENDOR, 300) +#define WS_SIO_BASE_HANDLE _WSAIOR(WS_IOC_WS2, 34) #endif
#define DE_REUSE_SOCKET TF_REUSE_SOCKET