From: Bruno Jesus <00cpxxx@gmail.com> Subject: ws2_32: Add WSAPoll() implementation Message-Id: Date: Mon, 16 Nov 2015 21:30:14 +0800 Signed-off-by: Bruno Jesus <00cpxxx@gmail.com> Still some todos to fix but fixes https://bugs.winehq.org/show_bug.cgi?id=38600 Thanks to Sebastian for keeping it in the staging for long time. diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 9e8510d..67c2ae4 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -771,6 +771,17 @@ static const int ws_eai_map[][2] = { 0, 0 } }; +static const int ws_poll_map[][2] = +{ + MAP_OPTION( POLLERR ), + MAP_OPTION( POLLHUP ), + MAP_OPTION( POLLNVAL ), + MAP_OPTION( POLLWRNORM ), + MAP_OPTION( POLLWRBAND ), + MAP_OPTION( POLLRDNORM ), + { WS_POLLRDBAND, POLLPRI } +}; + static const char magic_loopback_addr[] = {127, 12, 34, 56}; #ifndef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS @@ -1413,6 +1424,40 @@ convert_socktype_u2w(int unixsocktype) { return -1; } +static int convert_poll_w2u(int events) +{ + int i, ret; + for (i = ret = 0; events && i < sizeof(ws_poll_map) / sizeof(ws_poll_map[0]); i++) + { + if (ws_poll_map[i][0] & events) + { + ret |= ws_poll_map[i][1]; + events &= ~ws_poll_map[i][0]; + } + } + + if (events) + FIXME("Unsupported WSAPoll() flags 0x%x\n", events); + return ret; +} + +static int convert_poll_u2w(int events) +{ + int i, ret; + for (i = ret = 0; events && i < sizeof(ws_poll_map) / sizeof(ws_poll_map[0]); i++) + { + if (ws_poll_map[i][1] & events) + { + ret |= ws_poll_map[i][0]; + events &= ~ws_poll_map[i][1]; + } + } + + if (events) + FIXME("Unsupported poll() flags 0x%x\n", events); + return ret; +} + static int set_ipx_packettype(int sock, int ptype) { #ifdef HAS_IPX @@ -5225,6 +5270,55 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds, return ret; } +/*********************************************************************** + * WSAPoll + */ +int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout) +{ + int i, ret; + struct pollfd *ufds; + + if (!count) + { + SetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + if (!wfds) + { + SetLastError(WSAEFAULT); + return SOCKET_ERROR; + } + + if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0])))) + { + SetLastError(WSAENOBUFS); + return SOCKET_ERROR; + } + + for (i = 0; i < count; i++) + { + ufds[i].fd = get_sock_fd(wfds[i].fd, 0, NULL); + ufds[i].events = convert_poll_w2u(wfds[i].events); + ufds[i].revents = 0; + } + + ret = do_poll(ufds, count, timeout); + + for (i = 0; i < count; i++) + { + if (ufds[i].fd != -1) + { + release_sock_fd(wfds[i].fd, ufds[i].fd); + wfds[i].revents = convert_poll_u2w(ufds[i].revents); + } + else + wfds[i].revents = WS_POLLNVAL; + } + + HeapFree(GetProcessHeap(), 0, ufds); + 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 ) diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 8676b07..8fb3c43 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -6481,6 +6481,7 @@ static void test_WSAPoll(void) POLL_SET(fdWrite, POLLIN); ret = pWSAPoll(fds, ix, poll_timeout); ok(ret == 1, "expected 1, got %d\n", ret); +todo_wine ok(POLL_ISSET(fdWrite, POLLHUP), "fdWrite socket events incorrect\n"); ret = recv(fdWrite, tmp_buf, sizeof(tmp_buf), 0); ok(ret == 0, "expected 0, got %d\n", ret); @@ -6499,6 +6500,7 @@ static void test_WSAPoll(void) POLL_SET(fdWrite, POLLIN | POLLOUT); poll_timeout = 2000; ret = pWSAPoll(fds, ix, poll_timeout); +todo_wine ok(ret == 0, "expected 0, got %d\n", ret); len = sizeof(id); id = 0xdeadbeef; @@ -6520,6 +6522,7 @@ static void test_WSAPoll(void) POLL_SET(fdWrite, POLLIN | POLLOUT); ret = pWSAPoll(fds, ix, poll_timeout); ok(ret == 1, "expected 1, got %d\n", ret); +todo_wine ok(POLL_ISSET(fdWrite, POLLWRNORM | POLLHUP) || broken(POLL_ISSET(fdWrite, POLLWRNORM)) /* <= 2008 */, "fdWrite socket events incorrect\n"); closesocket(fdWrite); @@ -6543,6 +6546,7 @@ static void test_WSAPoll(void) POLL_SET(fdWrite, POLLIN); ret = pWSAPoll(fds, ix, poll_timeout); ok(ret == 1, "expected 1, got %d\n", ret); +todo_wine ok(POLL_ISSET(fdWrite, POLLNVAL), "fdWrite socket events incorrect\n"); WaitForSingleObject (thread_handle, 1000); closesocket(fdRead); diff --git a/dlls/ws2_32/ws2_32.spec b/dlls/ws2_32/ws2_32.spec index 6de888f..7625f38 100644 --- a/dlls/ws2_32/ws2_32.spec +++ b/dlls/ws2_32/ws2_32.spec @@ -91,6 +91,7 @@ @ stdcall WSANSPIoctl(ptr long ptr long ptr long ptr ptr) @ stdcall WSANtohl(long long ptr) @ stdcall WSANtohs(long long ptr) +@ stdcall WSAPoll(ptr long long) @ stdcall WSAProviderConfigChange(ptr ptr ptr) @ stdcall WSARecv(long ptr long ptr ptr ptr ptr) @ stdcall WSARecvDisconnect(long ptr) diff --git a/include/winsock2.h b/include/winsock2.h index 461b90c..24f0ea3 100644 --- a/include/winsock2.h +++ b/include/winsock2.h @@ -113,8 +113,8 @@ extern "C" { #define SD_BOTH 0x02 /* Constants for WSAPoll() */ -#ifndef __WINE_WINE_PORT_H #ifndef USE_WS_PREFIX +#ifndef __WINE_WINE_PORT_H #define POLLERR 0x0001 #define POLLHUP 0x0002 #define POLLNVAL 0x0004 @@ -125,6 +125,7 @@ extern "C" { #define POLLPRI 0x0400 #define POLLIN (POLLRDNORM|POLLRDBAND) #define POLLOUT (POLLWRNORM) +#endif #else #define WS_POLLERR 0x0001 #define WS_POLLHUP 0x0002 @@ -137,7 +138,6 @@ extern "C" { #define WS_POLLIN (WS_POLLRDNORM|WS_POLLRDBAND) #define WS_POLLOUT (WS_POLLWRNORM) #endif -#endif /* Constants for WSAIoctl() */ #ifdef USE_WS_PREFIX