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);