[PATCH 05/11] ntdll: Handle WoW64 translation in IOCTL_AFD_RECV.

Zebediah Figura zfigura at codeweavers.com
Thu Dec 9 21:43:55 CST 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ntdll/unix/socket.c | 50 ++++++++++++++++++++++++++++------------
 include/wine/afd.h       |  8 +++++++
 2 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 221e1bf303b..9cc9352403d 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -1278,7 +1278,7 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
 
         case IOCTL_AFD_RECV:
         {
-            const struct afd_recv_params *params = in_buffer;
+            struct afd_recv_params params;
             int unix_flags = 0;
 
             if ((status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL )))
@@ -1286,33 +1286,53 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
 
             if (out_size) FIXME( "unexpected output size %u\n", out_size );
 
-            if (in_size < sizeof(struct afd_recv_params))
+            if (in_wow64_call())
             {
-                status = STATUS_INVALID_PARAMETER;
-                break;
+                const struct afd_recv_params_32 *params32 = in_buffer;
+
+                if (in_size < sizeof(struct afd_recv_params_32))
+                {
+                    status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                params.recv_flags = params32->recv_flags;
+                params.msg_flags = params32->msg_flags;
+                params.buffers = ULongToPtr( params32->buffers );
+                params.count = params32->count;
+            }
+            else
+            {
+                if (in_size < sizeof(struct afd_recv_params))
+                {
+                    status = STATUS_INVALID_PARAMETER;
+                    break;
+                }
+
+                memcpy( &params, in_buffer, sizeof(params) );
             }
 
-            if ((params->msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == 0 ||
-                (params->msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == (AFD_MSG_NOT_OOB | AFD_MSG_OOB))
+            if ((params.msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == 0 ||
+                (params.msg_flags & (AFD_MSG_NOT_OOB | AFD_MSG_OOB)) == (AFD_MSG_NOT_OOB | AFD_MSG_OOB))
             {
                 status = STATUS_INVALID_PARAMETER;
                 break;
             }
 
-            if (params->msg_flags & ~(AFD_MSG_NOT_OOB | AFD_MSG_OOB | AFD_MSG_PEEK | AFD_MSG_WAITALL))
-                FIXME( "unknown msg_flags %#x\n", params->msg_flags );
-            if (params->recv_flags & ~AFD_RECV_FORCE_ASYNC)
-                FIXME( "unknown recv_flags %#x\n", params->recv_flags );
+            if (params.msg_flags & ~(AFD_MSG_NOT_OOB | AFD_MSG_OOB | AFD_MSG_PEEK | AFD_MSG_WAITALL))
+                FIXME( "unknown msg_flags %#x\n", params.msg_flags );
+            if (params.recv_flags & ~AFD_RECV_FORCE_ASYNC)
+                FIXME( "unknown recv_flags %#x\n", params.recv_flags );
 
-            if (params->msg_flags & AFD_MSG_OOB)
+            if (params.msg_flags & AFD_MSG_OOB)
                 unix_flags |= MSG_OOB;
-            if (params->msg_flags & AFD_MSG_PEEK)
+            if (params.msg_flags & AFD_MSG_PEEK)
                 unix_flags |= MSG_PEEK;
-            if (params->msg_flags & AFD_MSG_WAITALL)
+            if (params.msg_flags & AFD_MSG_WAITALL)
                 FIXME( "MSG_WAITALL is not supported\n" );
 
-            status = sock_recv( handle, event, apc, apc_user, io, fd, params->buffers, params->count, NULL,
-                                NULL, NULL, NULL, unix_flags, !!(params->recv_flags & AFD_RECV_FORCE_ASYNC) );
+            status = sock_recv( handle, event, apc, apc_user, io, fd, params.buffers, params.count, NULL,
+                                NULL, NULL, NULL, unix_flags, !!(params.recv_flags & AFD_RECV_FORCE_ASYNC) );
             break;
         }
 
diff --git a/include/wine/afd.h b/include/wine/afd.h
index 60dd2806d9d..9d1af44f117 100644
--- a/include/wine/afd.h
+++ b/include/wine/afd.h
@@ -107,6 +107,14 @@ struct afd_recv_params
     int msg_flags;
 };
 
+struct afd_recv_params_32
+{
+    ULONG buffers;
+    unsigned int count;
+    int recv_flags;
+    int msg_flags;
+};
+
 #include <pshpack4.h>
 struct afd_poll_params
 {
-- 
2.34.1




More information about the wine-devel mailing list