From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Signed-off-by: Alistair Leslie-Hughes leslie_alistair@hotmail.com --- dlls/ntdll/unix/socket.c | 33 +++++++++++++++++++++++++ dlls/ws2_32/socket.c | 17 +++++++++++++ dlls/ws2_32/tests/sock.c | 52 ++++++++++++++++++++++++++++++++++++++++ include/wine/afd.h | 1 + 4 files changed, 103 insertions(+)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index f8ed9f6f854..faad0763632 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1726,6 +1726,39 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return STATUS_SUCCESS; }
+ case IOCTL_AFD_WINE_SEND_BACKLOG_QUERY: + { + union unix_sockaddr addr; + socklen_t addr_len; + + if (out_size < sizeof(DWORD)) + { + status = STATUS_BUFFER_TOO_SMALL; + break; + } + + if(get_sock_type( handle ) != SOCK_STREAM) + { + status = STATUS_NOT_SUPPORTED; + break; + } + + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL ))) + return status; + + addr_len = sizeof(addr); + if (getpeername( fd, &addr.addr, &addr_len ) != 0) + { + if (needs_close) close( fd ); + return sock_errno_to_status( errno ); + } + + *(DWORD*)out_buffer = 0x10000; /* 64k */ + + if (needs_close) close( fd ); + return STATUS_SUCCESS; + } + case IOCTL_AFD_WINE_SIOCATMARK: { int value, ret; diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 9d51fef1adb..e74736eb601 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2327,6 +2327,23 @@ INT WINAPI WSAIoctl(SOCKET s, DWORD code, LPVOID in_buff, DWORD in_size, LPVOID return ret ? -1 : 0; }
+ case SIO_IDEAL_SEND_BACKLOG_QUERY: + { + DWORD ret; + + if (!out_buff) + { + SetLastError(WSAEFAULT); + return SOCKET_ERROR; + } + + ret = server_ioctl_sock( s, IOCTL_AFD_WINE_SEND_BACKLOG_QUERY, in_buff, in_size, + out_buff, out_size, ret_size, overlapped, completion ); + SetLastError( ret ); + if (!ret) *ret_size = sizeof(u_long); + return ret ? -1 : 0; + } + case SIOCATMARK: { DWORD ret; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 3e6faaffa4c..0cd8efa202a 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -5273,6 +5273,55 @@ static void test_get_extension_func(void) closesocket(s); }
+static void test_backlog_query(void) +{ + const struct sockaddr_in addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)}; + GUID acceptex_guid = WSAID_ACCEPTEX; + LPFN_ACCEPTEX pAcceptEx; + struct sockaddr_in destaddr; + DWORD size; + SOCKET s, listener; + int len, ret; + ULONG backlog = 0; + + listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ok(listener != -1, "failed to create socket, error %u\n", WSAGetLastError()); + + ret = WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &acceptex_guid, sizeof(acceptex_guid), + &pAcceptEx, sizeof(pAcceptEx), &size, NULL, NULL); + ok(!ret, "failed to get AcceptEx, error %u\n", WSAGetLastError()); + + ret = bind(listener, (const struct sockaddr *)&addr, sizeof(addr)); + ok(!ret, "failed to bind, error %u\n", WSAGetLastError()); + len = sizeof(destaddr); + ret = getsockname(listener, (struct sockaddr *)&destaddr, &len); + ok(!ret, "failed to get address, error %u\n", WSAGetLastError()); + ret = listen(listener, 2); + ok(!ret, "failed to listen, error %u\n", WSAGetLastError()); + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + ret = WSAIoctl(s, SIO_IDEAL_SEND_BACKLOG_QUERY, NULL, 0, &backlog, sizeof(backlog), &size, NULL, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAENOTCONN, + "WSAIoctl() failed: %d/%d\n", ret, WSAGetLastError()); + + ret = connect(s, (struct sockaddr *)&destaddr, sizeof(destaddr)); + ok(!ret, "failed to connect, error %u\n", WSAGetLastError()); + ret = WSAIoctl(s, SIO_IDEAL_SEND_BACKLOG_QUERY, NULL, 0, &backlog, sizeof(backlog), &size, NULL, NULL); + ok(!ret, "WSAIoctl() failed: %d\n", WSAGetLastError()); + ok(backlog == 0x10000, "got %08lx\n", backlog); + + closesocket(listener); + closesocket(s); + + s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + backlog = 0; + ret = WSAIoctl(s, SIO_IDEAL_SEND_BACKLOG_QUERY, NULL, 0, &backlog, sizeof(backlog), &size, NULL, NULL); + ok(ret == SOCKET_ERROR && WSAGetLastError() == WSAEOPNOTSUPP, + "WSAIoctl() failed: %d/%d\n", ret, WSAGetLastError()); + closesocket(s); +} + static void test_base_handle(void) { OVERLAPPED overlapped = {0}, *overlapped_ptr; @@ -6857,6 +6906,8 @@ static void test_WSASendTo(void) ok(!ret, "got error %u\n", WSAGetLastError()); ok(ret_addr.sin_family == AF_INET, "got family %u\n", ret_addr.sin_family); ok(ret_addr.sin_port, "expected nonzero port\n"); + + closesocket(s); }
struct recv_thread_apc_param @@ -13242,6 +13293,7 @@ START_TEST( sock ) test_fionbio(); test_fionread_siocatmark(); test_get_extension_func(); + test_backlog_query(); test_get_interface_list(); test_keepalive_vals(); test_sioRoutingInterfaceQuery(); diff --git a/include/wine/afd.h b/include/wine/afd.h index 993730cacdb..04dad6ace21 100644 --- a/include/wine/afd.h +++ b/include/wine/afd.h @@ -283,6 +283,7 @@ C_ASSERT( sizeof(struct afd_get_events_params) == 56 ); #define IOCTL_AFD_WINE_SET_IP_RECVTTL WINE_AFD_IOC(294) #define IOCTL_AFD_WINE_GET_IP_RECVTOS WINE_AFD_IOC(295) #define IOCTL_AFD_WINE_SET_IP_RECVTOS WINE_AFD_IOC(296) +#define IOCTL_AFD_WINE_SEND_BACKLOG_QUERY WINE_AFD_IOC(297)
struct afd_iovec {
On 9/10/22 19:28, Alistair Leslie-Hughes wrote:
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index f8ed9f6f854..faad0763632 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1726,6 +1726,39 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return STATUS_SUCCESS; }
case IOCTL_AFD_WINE_SEND_BACKLOG_QUERY:
{
union unix_sockaddr addr;
socklen_t addr_len;
if (out_size < sizeof(DWORD))
{
status = STATUS_BUFFER_TOO_SMALL;
break;
}
if(get_sock_type( handle ) != SOCK_STREAM)
{
status = STATUS_NOT_SUPPORTED;
break;
}
if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
return status;
addr_len = sizeof(addr);
if (getpeername( fd, &addr.addr, &addr_len ) != 0)
{
if (needs_close) close( fd );
return sock_errno_to_status( errno );
}
*(DWORD*)out_buffer = 0x10000; /* 64k */
if (needs_close) close( fd );
return STATUS_SUCCESS;
}
I believe all of this can be implemented on the PE side, which would be less code to deal with.
Also, should we add a FIXME or WARN for this?
On 9/10/22 19:28, Alistair Leslie-Hughes wrote:
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index f8ed9f6f854..faad0763632 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1726,6 +1726,39 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return STATUS_SUCCESS; }
case IOCTL_AFD_WINE_SEND_BACKLOG_QUERY:
{
union unix_sockaddr addr;
socklen_t addr_len;
if (out_size < sizeof(DWORD))
{
status = STATUS_BUFFER_TOO_SMALL;
break;
}
if(get_sock_type( handle ) != SOCK_STREAM)
{
status = STATUS_NOT_SUPPORTED;
break;
}
if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
return status;
addr_len = sizeof(addr);
if (getpeername( fd, &addr.addr, &addr_len ) != 0)
{
if (needs_close) close( fd );
return sock_errno_to_status( errno );
}
*(DWORD*)out_buffer = 0x10000; /* 64k */
if (needs_close) close( fd );
return STATUS_SUCCESS;
}
I believe all of this can be implemented on the PE side, which would be less code to deal with.
Also, should we add a FIXME or WARN for this?
On 9/10/22 19:28, Alistair Leslie-Hughes wrote:
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index f8ed9f6f854..faad0763632 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1726,6 +1726,39 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc return STATUS_SUCCESS; }
case IOCTL_AFD_WINE_SEND_BACKLOG_QUERY:
{
union unix_sockaddr addr;
socklen_t addr_len;
if (out_size < sizeof(DWORD))
{
status = STATUS_BUFFER_TOO_SMALL;
break;
}
if(get_sock_type( handle ) != SOCK_STREAM)
{
status = STATUS_NOT_SUPPORTED;
break;
}
if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
return status;
addr_len = sizeof(addr);
if (getpeername( fd, &addr.addr, &addr_len ) != 0)
{
if (needs_close) close( fd );
return sock_errno_to_status( errno );
}
*(DWORD*)out_buffer = 0x10000; /* 64k */
if (needs_close) close( fd );
return STATUS_SUCCESS;
}
case IOCTL_AFD_WINE_SIOCATMARK: { int value, ret;
I believe all of this can be implemented on the PE side, which would be less code to deal with.
Also, should we add a FIXME or WARN for this?