[PATCH 2/6] ws2_32: Use IOCTL_AFD_POLL in WSAPoll().

Zebediah Figura z.figura12 at gmail.com
Sun Jun 20 11:05:53 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/ws2_32/socket.c     | 170 +++++++++++++++++++++------------------
 dlls/ws2_32/tests/sock.c |  14 ++--
 2 files changed, 97 insertions(+), 87 deletions(-)

diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c
index bfc4bb6c09d..f5958e86e9f 100644
--- a/dlls/ws2_32/socket.c
+++ b/dlls/ws2_32/socket.c
@@ -510,17 +510,6 @@ static const int ws_socktype_map[][2] =
     {FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO},
 };
 
-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 }
-};
-
 UINT sock_get_error( int err )
 {
 	switch(err)
@@ -988,40 +977,6 @@ convert_socktype_u2w(int unixsocktype) {
     return -1;
 }
 
-static int convert_poll_w2u(int events)
-{
-    int i, ret;
-    for (i = ret = 0; events && i < ARRAY_SIZE(ws_poll_map); 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 < ARRAY_SIZE(ws_poll_map); 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
@@ -3531,65 +3486,120 @@ static unsigned int afd_poll_flag_to_win32( unsigned int flags )
 
 
 /***********************************************************************
- *     WSAPoll
+ *      WSAPoll   (ws2_32.@)
  */
-int WINAPI WSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
+int WINAPI WSAPoll( WSAPOLLFD *fds, ULONG count, int timeout )
 {
-    int i, ret;
-    struct pollfd *ufds;
+    struct afd_poll_params *params;
+    ULONG params_size, i, j;
+    SOCKET poll_socket = 0;
+    IO_STATUS_BLOCK io;
+    HANDLE sync_event;
+    int ret_count = 0;
+    NTSTATUS status;
 
     if (!count)
     {
         SetLastError(WSAEINVAL);
         return SOCKET_ERROR;
     }
-    if (!wfds)
+    if (!fds)
     {
         SetLastError(WSAEFAULT);
         return SOCKET_ERROR;
     }
 
-    if (!(ufds = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ufds[0]))))
+    if (!(sync_event = get_sync_event())) return -1;
+
+    params_size = offsetof( struct afd_poll_params, sockets[count] );
+    if (!(params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, params_size )))
     {
         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;
-    }
+    params->timeout = (timeout >= 0 ? timeout * -10000 : TIMEOUT_INFINITE);
 
-    ret = do_poll(ufds, count, timeout);
-
-    for (i = 0; i < count; i++)
+    for (i = 0; i < count; ++i)
     {
-        if (ufds[i].fd != -1)
+        unsigned int flags = AFD_POLL_HUP | AFD_POLL_RESET | AFD_POLL_CONNECT_ERR;
+
+        if ((INT_PTR)fds[i].fd < 0 || !socket_list_find( fds[i].fd ))
         {
-            release_sock_fd(wfds[i].fd, ufds[i].fd);
-            if (ufds[i].revents & POLLHUP)
-            {
-                /* Check if the socket still exists */
-                int fd = get_sock_fd(wfds[i].fd, 0, NULL);
-                if (fd != -1)
-                {
-                    wfds[i].revents = WS_POLLHUP;
-                    release_sock_fd(wfds[i].fd, fd);
-                }
-                else
-                    wfds[i].revents = WS_POLLNVAL;
-            }
-            else
-                wfds[i].revents = convert_poll_u2w(ufds[i].revents);
+            fds[i].revents = WS_POLLNVAL;
+            continue;
         }
-        else
-            wfds[i].revents = WS_POLLNVAL;
+
+        poll_socket = fds[i].fd;
+        params->sockets[params->count].socket = fds[i].fd;
+
+        if (fds[i].events & WS_POLLRDNORM)
+            flags |= AFD_POLL_ACCEPT | AFD_POLL_READ;
+        if (fds[i].events & WS_POLLRDBAND)
+            flags |= AFD_POLL_OOB;
+        if (fds[i].events & WS_POLLWRNORM)
+            flags |= AFD_POLL_WRITE;
+        params->sockets[params->count].flags = flags;
+        ++params->count;
+
+        fds[i].revents = 0;
     }
 
-    HeapFree(GetProcessHeap(), 0, ufds);
-    return ret;
+    if (!poll_socket)
+    {
+        SetLastError( WSAENOTSOCK );
+        HeapFree( GetProcessHeap(), 0, params );
+        return -1;
+    }
+
+    status = NtDeviceIoControlFile( (HANDLE)poll_socket, sync_event, NULL, NULL, &io, IOCTL_AFD_POLL,
+                                    params, params_size, params, params_size );
+    if (status == STATUS_PENDING)
+    {
+        if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED)
+        {
+            HeapFree( GetProcessHeap(), 0, params );
+            return -1;
+        }
+        status = io.u.Status;
+    }
+    if (!status)
+    {
+        for (i = 0; i < count; ++i)
+        {
+            for (j = 0; j < params->count; ++j)
+            {
+                if (fds[i].fd == params->sockets[j].socket)
+                {
+                    unsigned int revents = 0;
+
+                    if (params->sockets[j].flags & (AFD_POLL_ACCEPT | AFD_POLL_READ))
+                        revents |= WS_POLLRDNORM;
+                    if (params->sockets[j].flags & AFD_POLL_OOB)
+                        revents |= WS_POLLRDBAND;
+                    if (params->sockets[j].flags & AFD_POLL_WRITE)
+                        revents |= WS_POLLWRNORM;
+                    if (params->sockets[j].flags & AFD_POLL_HUP)
+                        revents |= WS_POLLHUP;
+                    if (params->sockets[j].flags & (AFD_POLL_RESET | AFD_POLL_CONNECT_ERR))
+                        revents |= WS_POLLERR;
+                    if (params->sockets[j].flags & AFD_POLL_CLOSE)
+                        revents |= WS_POLLNVAL;
+
+                    fds[i].revents = revents & (fds[i].events | WS_POLLHUP | WS_POLLERR | WS_POLLNVAL);
+
+                    if (fds[i].revents)
+                        ++ret_count;
+                }
+            }
+        }
+    }
+    if (status == STATUS_TIMEOUT) status = STATUS_SUCCESS;
+
+    HeapFree( GetProcessHeap(), 0, params );
+
+    SetLastError( NtStatusToWSAError( status ) );
+    return status ? -1 : ret_count;
 }
 
 
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index b171e6c03e1..7b92d0b4e84 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -6064,7 +6064,7 @@ static void test_WSAPoll(void)
     WSASetLastError(0xdeadbeef);
     ret = pWSAPoll(fds, 2, 0);
     ok(!ret, "got %d\n", ret);
-    todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+    ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
     ok(fds[0].revents == POLLNVAL, "got events %#x\n", fds[0].revents);
     ok(!fds[1].revents, "got events %#x\n", fds[1].revents);
 
@@ -6077,7 +6077,7 @@ static void test_WSAPoll(void)
     WSASetLastError(0xdeadbeef);
     ret = pWSAPoll(fds, 2, 0);
     ok(!ret, "got %d\n", ret);
-    todo_wine ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
+    ok(!WSAGetLastError(), "got error %u\n", WSAGetLastError());
     ok(!fds[0].revents, "got events %#x\n", fds[0].revents);
     ok(fds[1].revents == POLLNVAL, "got events %#x\n", fds[1].revents);
 
@@ -6102,7 +6102,7 @@ static void test_WSAPoll(void)
     fds[1].revents = 0xdead;
     WSASetLastError(0xdeadbeef);
     ret = pWSAPoll(fds, 2, 0);
-    todo_wine ok(ret == -1, "got %d\n", ret);
+    ok(ret == -1, "got %d\n", ret);
     ok(WSAGetLastError() == WSAENOTSOCK, "got error %u\n", WSAGetLastError());
     ok(fds[0].revents == POLLNVAL, "got events %#x\n", fds[0].revents);
     ok(fds[1].revents == POLLNVAL, "got events %#x\n", fds[1].revents);
@@ -6222,8 +6222,8 @@ static void test_WSAPoll(void)
     ok(ret == 1, "got %d\n", ret);
 
     check_poll(client, POLLWRNORM);
-    check_poll_mask_todo(server, POLLRDNORM | POLLRDBAND, POLLRDNORM);
-    check_poll_todo(server, POLLWRNORM | POLLRDNORM);
+    check_poll_mask(server, POLLRDNORM | POLLRDBAND, POLLRDNORM);
+    check_poll(server, POLLWRNORM | POLLRDNORM);
 
     buffer[0] = 0xcc;
     ret = recv(server, buffer, 1, 0);
@@ -6261,8 +6261,8 @@ static void test_WSAPoll(void)
 
     closesocket(client);
 
-    check_poll_mask_todo(server, 0, POLLHUP);
-    check_poll_todo(server, POLLWRNORM | POLLHUP);
+    check_poll_mask(server, 0, POLLHUP);
+    check_poll(server, POLLWRNORM | POLLHUP);
 
     closesocket(server);
 
-- 
2.30.2




More information about the wine-devel mailing list