From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ws2_32/tests/sock.c | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index f8d86950f3c..ce7bbd6d088 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -14463,6 +14463,53 @@ static void test_send_buffering(void) closesocket(client); }
+static void test_valid_handle(void) +{ + HANDLE duplicated, invalid; + SOCKET client, server; + char buffer[1]; + WSABUF wsabuf; + DWORD size; + int ret; + + /* Unlike WSAGetOverlappedResult(), duplicated handles are allowed. */ + + tcp_socketpair(&client, &server); + ret = DuplicateHandle(GetCurrentProcess(), (HANDLE)client, + GetCurrentProcess(), &duplicated, 0, FALSE, DUPLICATE_SAME_ACCESS); + ok(ret, "got error %lu\n", GetLastError()); + invalid = CreateEventA(NULL, TRUE, TRUE, NULL); + + ret = send((SOCKET)duplicated, buffer, 1, 0); + todo_wine ok(ret == 1, "got %d\n", ret); + + ret = sendto((SOCKET)duplicated, buffer, 1, 0, NULL, 0); + todo_wine ok(ret == 1, "got %d\n", ret); + + wsabuf.buf = buffer; + wsabuf.len = 1; + + ret = WSASend((SOCKET)duplicated, &wsabuf, 1, NULL, 0, NULL, NULL); + ok(ret == -1, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); + + ret = WSASend((SOCKET)duplicated, &wsabuf, 1, &size, 0, NULL, NULL); + todo_wine ok(!ret, "got %d\n", ret); + + ret = WSASend((SOCKET)invalid, &wsabuf, 1, NULL, 0, NULL, NULL); + ok(ret == -1, "got %d\n", ret); + ok(WSAGetLastError() == WSAENOTSOCK, "got error %u\n", WSAGetLastError()); + + ret = WSASend(INVALID_SOCKET, &wsabuf, 1, NULL, 0, NULL, NULL); + ok(ret == -1, "got %d\n", ret); + ok(WSAGetLastError() == WSAENOTSOCK, "got error %u\n", WSAGetLastError()); + + CloseHandle(invalid); + CloseHandle(duplicated); + closesocket(client); + closesocket(server); +} + START_TEST( sock ) { int i; @@ -14548,6 +14595,7 @@ START_TEST( sock ) test_tcp_sendto_recvfrom(); test_broadcast(); test_send_buffering(); + test_valid_handle();
/* There is apparently an obscure interaction between this test and * test_WSAGetOverlappedResult().
From: Elizabeth Figura zfigura@codeweavers.com
--- dlls/ntdll/unix/socket.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index a02194f843f..5156bbfee10 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -1755,12 +1755,16 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
case IOCTL_AFD_WINE_COMPLETE_ASYNC: { + enum server_fd_type type; + if (in_size != sizeof(NTSTATUS)) return STATUS_BUFFER_TOO_SMALL;
- if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, &options ))) + if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, &type, &options ))) return status; if (needs_close) close( fd ); + if (type != FD_TYPE_SOCKET) + return STATUS_INVALID_DEVICE_REQUEST;
status = *(NTSTATUS *)in_buffer; file_complete_async( handle, options, event, apc, apc_user, io, status, 0 );
From: Elizabeth Figura zfigura@codeweavers.com
Wine-Bug: http://bugs.winehq.org/show_bug.cgi?id=58122 --- dlls/ws2_32/socket.c | 21 ++++++++++++++++++++- dlls/ws2_32/tests/sock.c | 8 ++++---- 2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 3a412b00c1e..2f49157cb8b 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -462,6 +462,25 @@ static BOOL socket_list_remove( SOCKET socket ) return FALSE; }
+ +static BOOL is_valid_socket( SOCKET socket ) +{ + NTSTATUS status = STATUS_SUCCESS; + IO_STATUS_BLOCK io; + + if (socket_list_find( socket )) + return TRUE; + + /* Some functions allow socket handles output with DuplicateHandle(), which + * will not be in the socket list. We can't necessarily just delegate to + * ntdll to check the handle type, because sometimes we need to check the + * handle validity *before* checking e.g. pointer validity. + * Instead try to perform an ioctl to see if it's truly a socket. */ + return NtDeviceIoControlFile( (HANDLE)socket, NULL, NULL, NULL, &io, IOCTL_AFD_WINE_COMPLETE_ASYNC, + &status, sizeof(status), NULL, 0 ) == STATUS_SUCCESS; +} + + static INT WINAPI WSA_DefaultBlockingHook( FARPROC x );
int num_startup; @@ -1026,7 +1045,7 @@ static int WS2_sendto( SOCKET s, WSABUF *buffers, DWORD buffer_count, DWORD *ret "addr_len %d, overlapped %p, completion %p\n", s, buffers, buffer_count, flags, addr, addr_len, overlapped, completion );
- if (!socket_list_find( s )) + if (!is_valid_socket( s )) { SetLastError( WSAENOTSOCK ); return -1; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ce7bbd6d088..2ca5b9fc8b2 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -14481,20 +14481,20 @@ static void test_valid_handle(void) invalid = CreateEventA(NULL, TRUE, TRUE, NULL);
ret = send((SOCKET)duplicated, buffer, 1, 0); - todo_wine ok(ret == 1, "got %d\n", ret); + ok(ret == 1, "got %d\n", ret);
ret = sendto((SOCKET)duplicated, buffer, 1, 0, NULL, 0); - todo_wine ok(ret == 1, "got %d\n", ret); + ok(ret == 1, "got %d\n", ret);
wsabuf.buf = buffer; wsabuf.len = 1;
ret = WSASend((SOCKET)duplicated, &wsabuf, 1, NULL, 0, NULL, NULL); ok(ret == -1, "got %d\n", ret); - todo_wine ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError()); + ok(WSAGetLastError() == WSAEFAULT, "got error %u\n", WSAGetLastError());
ret = WSASend((SOCKET)duplicated, &wsabuf, 1, &size, 0, NULL, NULL); - todo_wine ok(!ret, "got %d\n", ret); + ok(!ret, "got %d\n", ret);
ret = WSASend((SOCKET)invalid, &wsabuf, 1, NULL, 0, NULL, NULL); ok(ret == -1, "got %d\n", ret);