[PATCH v2 0/1] MR9111: ws2_32: Implement SIO_BSP_HANDLE_SELECT.
My understanding is that, in the absence of layered service providers, `SIO_BSP_HANDLE_SELECT` should behave like `SIO_BASE_HANDLE` (this is relied upon by https://github.com/python-trio/trio). Should I add tests to verify this? If so, should they basically just be the same as the existing `SIO_BASE_HANDLE` tests? -- v2: ws2_32: Implement SIO_BSP_HANDLE_SELECT. https://gitlab.winehq.org/wine/wine/-/merge_requests/9111
From: Josh Steffen <josh(a)joshsteffen.com> Wine does not support layered service providers, so just fall through to SIO_BASE_HANDLE. --- dlls/ws2_32/socket.c | 1 + dlls/ws2_32/tests/sock.c | 92 ++++++++++++++++++++++++++++++++++++++++ include/mswsock.h | 2 + 3 files changed, 95 insertions(+) diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index d4223e93bd1..a267f65ab91 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2701,6 +2701,7 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return ret ? -1 : 0; } + case SIO_BSP_HANDLE_SELECT: case SIO_BASE_HANDLE: { NTSTATUS status; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 77bc3beeabf..a8a48438a83 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6253,6 +6253,97 @@ static void test_base_handle(void) } } +static void test_bsp_handle_select(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_BSP_HANDLE_SELECT, 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_BSP_HANDLE_SELECT, 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 %lu\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_BSP_HANDLE_SELECT, 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 %lu\n", size); + + ret = GetQueuedCompletionStatus(port, &size, &key, &overlapped_ptr, 0); + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_NOT_SUPPORTED, "got error %lu\n", GetLastError()); + ok(!size, "got size %lu\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 %#lx\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_BSP_HANDLE_SELECT, 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_BSP_HANDLE_SELECT, 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 %lu\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 %lu\n", apc_error); + ok(!apc_size, "got APC size %lu\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 void test_circular_queueing(void) { SOCKET s; @@ -14646,6 +14737,7 @@ START_TEST( sock ) test_sioRoutingInterfaceQuery(); test_sioAddressListChange(); test_base_handle(); + test_bsp_handle_select(); test_circular_queueing(); test_unsupported_ioctls(); diff --git a/include/mswsock.h b/include/mswsock.h index fa97d5bf04d..754b8ec3dd0 100644 --- a/include/mswsock.h +++ b/include/mswsock.h @@ -85,10 +85,12 @@ extern "C" { #ifndef USE_WS_PREFIX #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12) #define SIO_SET_COMPATIBILITY_MODE _WSAIOW(IOC_VENDOR, 300) +#define SIO_BSP_HANDLE_SELECT _WSAIOR(IOC_WS2, 28) #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_BSP_HANDLE_SELECT _WSAIOR(WS_IOC_WS2, 28) #define WS_SIO_BASE_HANDLE _WSAIOR(WS_IOC_WS2, 34) #endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9111
On Mon Oct 6 20:31:41 2025 +0000, Elizabeth Figura wrote:
Should I add tests to verify this? If so, should they basically just be the same as the existing `SIO_BASE_HANDLE` tests? Yes, please. Done (I think... I'm a bit out of my depth here with overlapped IO and completions so I hope my find-and-replacing is okay)
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9111#note_117737
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9111
On Mon Oct 6 20:31:40 2025 +0000, Josh Steffen wrote:
Done (I think... I'm a bit out of my depth here with overlapped IO and completions so I hope my find-and-replacing is okay) It is, thank you. Actually we could probably go as far as putting another loop in the same test with different ioctl codes.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9111#note_117741
On Mon Oct 6 21:12:30 2025 +0000, Elizabeth Figura wrote:
It is, thank you. Actually we could probably go as far as putting another loop in the same test with different ioctl codes. Oh good thinking, I can do that now if you'd like. Will the name `test_base_handle` need to be updated?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9111#note_117845
Will the name `test_base_handle` need to be updated?
It's fine enough as-is I think. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9111#note_117856
participants (3)
-
Elizabeth Figura (@zfigura) -
Josh Steffen -
Josh Steffen (@joshsteffen)