[PATCH v7 1/2] ntdll/socket: Implement exclusive flag for IOCTL_AFD_POLL.

Guillaume Charifi guillaume.charifi at sfr.fr
Mon Sep 6 12:47:38 CDT 2021


Signed-off-by: Guillaume Charifi <guillaume.charifi at sfr.fr>
---
 dlls/ntdll/unix/socket.c |  6 ++---
 include/wine/afd.h       |  2 +-
 server/protocol.def      |  1 +
 server/sock.c            | 52 ++++++++++++++++++++++++++++++++++++++--
 4 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 8469def786a..b1b90b363ee 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -747,12 +747,11 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
             || in_size < offsetof( struct afd_poll_params, sockets[params->count] ))
         return STATUS_INVALID_PARAMETER;
 
-    TRACE( "timeout %s, count %u, unknown %#x, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
-            wine_dbgstr_longlong(params->timeout), params->count, params->unknown,
+    TRACE( "timeout %s, count %u, exclusive %u, padding (%#x, %#x, %#x), sockets[0] {%04lx, %#x}\n",
+            wine_dbgstr_longlong(params->timeout), params->count, params->exclusive,
             params->padding[0], params->padding[1], params->padding[2],
             params->sockets[0].socket, params->sockets[0].flags );
 
-    if (params->unknown) FIXME( "unknown boolean is %#x\n", params->unknown );
     if (params->padding[0]) FIXME( "padding[0] is %#x\n", params->padding[0] );
     if (params->padding[1]) FIXME( "padding[1] is %#x\n", params->padding[1] );
     if (params->padding[2]) FIXME( "padding[2] is %#x\n", params->padding[2] );
@@ -793,6 +792,7 @@ static NTSTATUS sock_poll( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
     SERVER_START_REQ( poll_socket )
     {
         req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
+        req->exclusive = !!params->exclusive;
         req->timeout = params->timeout;
         wine_server_add_data( req, input, params->count * sizeof(*input) );
         wine_server_set_reply( req, async->sockets, params->count * sizeof(async->sockets[0]) );
diff --git a/include/wine/afd.h b/include/wine/afd.h
index e67ecae25a9..f4682f464e8 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -104,7 +104,7 @@ struct afd_poll_params
 {
     LONGLONG timeout;
     unsigned int count;
-    BOOLEAN unknown;
+    BOOLEAN exclusive;
     BOOLEAN padding[3];
     struct
     {
diff --git a/server/protocol.def b/server/protocol.def
index 133d6ad0552..c6da8576f39 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1450,6 +1450,7 @@ struct poll_socket_output
 
 /* Perform an async poll on a socket */
 @REQ(poll_socket)
+    int          exclusive;
     async_data_t async;         /* async I/O parameters */
     timeout_t    timeout;       /* timeout */
     VARARG(sockets,poll_socket_input); /* list of sockets to poll */
diff --git a/server/sock.c b/server/sock.c
index 3c5f2612b51..8fc21e39da1 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -128,12 +128,14 @@ struct poll_req
     struct async *async;
     struct iosb *iosb;
     struct timeout_user *timeout;
+    int exclusive;
     unsigned int count;
     struct poll_socket_output *output;
     struct
     {
         struct sock *sock;
         int flags;
+        int main;
     } sockets[1];
 };
 
@@ -2839,7 +2841,50 @@ static int poll_single_socket( struct sock *sock, int mask )
     return get_poll_flags( sock, pollfd.revents ) & mask;
 }
 
-static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t timeout,
+static void poll_handle_exclusive(struct poll_req *req)
+{
+    struct poll_req *areq;
+    unsigned int i, j;
+
+    for (i = 0; i < req->count; ++i)
+    {
+        int has_main = FALSE;
+
+        LIST_FOR_EACH_ENTRY(areq, &poll_list, struct poll_req, entry)
+        {
+            for (j = 0; j < areq->count; ++j)
+            {
+                if (areq->sockets[j].sock != req->sockets[i].sock)
+                    continue;
+
+                if (!areq->sockets[j].main)
+                    continue;
+
+                has_main = TRUE;
+
+                if (areq->exclusive && req->exclusive)
+                {
+                    /* Previous exclusive main poll replaced by new exclusive poll */
+                    areq->sockets[j].main = FALSE;
+
+                    areq->iosb->status = STATUS_SUCCESS;
+                    areq->iosb->out_data = areq->output;
+                    areq->iosb->out_size = areq->count * sizeof(*areq->output);
+                    async_terminate(areq->async, STATUS_ALERTED);
+
+                    has_main = FALSE;
+                }
+
+                goto next;
+            }
+        }
+
+    next:
+        req->sockets[i].main = !has_main;
+    }
+}
+
+static void poll_socket( struct sock *poll_sock, struct async *async, int exclusive, timeout_t timeout,
                          unsigned int count, const struct poll_socket_input *input )
 {
     struct poll_socket_output *output;
@@ -2880,11 +2925,14 @@ static void poll_socket( struct sock *poll_sock, struct async *async, timeout_t
         req->sockets[i].flags = input[i].flags;
     }
 
+    req->exclusive = exclusive;
     req->count = count;
     req->async = (struct async *)grab_object( async );
     req->iosb = async_get_iosb( async );
     req->output = output;
 
+    poll_handle_exclusive(req);
+
     list_add_tail( &poll_list, &req->entry );
     async_set_completion_callback( async, free_poll_req, req );
     queue_async( &poll_sock->poll_q, async );
@@ -3285,7 +3333,7 @@ DECL_HANDLER(poll_socket)
 
     if ((async = create_request_async( sock->fd, get_fd_comp_flags( sock->fd ), &req->async )))
     {
-        poll_socket( sock, async, req->timeout, count, input );
+        poll_socket( sock, async, req->exclusive, req->timeout, count, input );
         reply->wait = async_handoff( async, NULL, 0 );
         reply->options = get_fd_options( sock->fd );
         release_object( async );
-- 
2.33.0




More information about the wine-devel mailing list