Zebediah Figura : ntdll: Use the send_socket request for NtWriteFile() on a socket.

Alexandre Julliard julliard at winehq.org
Thu Jul 14 16:59:25 CDT 2022


Module: wine
Branch: master
Commit: cb8937801d42417c2b98cba15366ccc154c1cc40
URL:    https://gitlab.winehq.org/wine/wine/-/commit/cb8937801d42417c2b98cba15366ccc154c1cc40

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Sun May 29 16:51:00 2022 -0500

ntdll: Use the send_socket request for NtWriteFile() on a socket.

send_socket does some extra bookkeeping that's currently missing from the
register_async path. Instead of adding it to sock_queue_async(), let's just
centralize all send requests so that they go through send_socket.

---

 dlls/ntdll/unix/file.c         |  10 +++-
 dlls/ntdll/unix/socket.c       | 111 ++++++++++++++++++++++++++---------------
 dlls/ntdll/unix/unix_private.h |   2 +
 3 files changed, 81 insertions(+), 42 deletions(-)

diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index f57532f55bf..738367dbb57 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -4768,7 +4768,7 @@ static BOOL async_write_proc( void *user, ULONG_PTR *info, NTSTATUS *status )
                                           &needs_close, &type, NULL )))
             break;
 
-        if (!fileio->count && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
+        if (!fileio->count && type == FD_TYPE_MAILSLOT)
             result = send( fd, fileio->buffer, 0, 0 );
         else
             result = write( fd, &fileio->buffer[fileio->already], fileio->count - fileio->already );
@@ -5498,11 +5498,17 @@ NTSTATUS WINAPI NtWriteFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, v
             goto done;
         }
     }
+    else if (type == FD_TYPE_SOCKET)
+    {
+        status = sock_write( handle, unix_handle, event, apc, apc_user, io, buffer, length );
+        if (needs_close) close( unix_handle );
+        return status;
+    }
 
     for (;;)
     {
         /* zero-length writes on sockets may not work with plain write(2) */
-        if (!length && (type == FD_TYPE_MAILSLOT || type == FD_TYPE_SOCKET))
+        if (!length && type == FD_TYPE_MAILSLOT)
             result = send( unix_handle, buffer, 0, 0 );
         else
             result = write( unix_handle, (const char *)buffer + total, length - total );
diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c
index 6abee680ee5..ef3c8494c3d 100644
--- a/dlls/ntdll/unix/socket.c
+++ b/dlls/ntdll/unix/socket.c
@@ -895,49 +895,13 @@ static BOOL async_send_proc( void *user, ULONG_PTR *info, NTSTATUS *status )
 }
 
 static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
-                           IO_STATUS_BLOCK *io, int fd, const void *buffers_ptr, unsigned int count,
-                           const struct WS_sockaddr *addr, unsigned int addr_len, int unix_flags, int force_async )
+                           IO_STATUS_BLOCK *io, int fd, struct async_send_ioctl *async, int force_async )
 {
-    struct async_send_ioctl *async;
+    BOOL nonblocking, alerted;
     ULONG_PTR information;
     HANDLE wait_handle;
-    DWORD async_size;
     NTSTATUS status;
-    unsigned int i;
     ULONG options;
-    BOOL nonblocking, alerted;
-
-    async_size = offsetof( struct async_send_ioctl, iov[count] );
-
-    if (!(async = (struct async_send_ioctl *)alloc_fileio( async_size, async_send_proc, handle )))
-        return STATUS_NO_MEMORY;
-
-    async->count = count;
-    if (in_wow64_call())
-    {
-        const struct afd_wsabuf_32 *buffers = buffers_ptr;
-
-        for (i = 0; i < count; ++i)
-        {
-            async->iov[i].iov_base = ULongToPtr( buffers[i].buf );
-            async->iov[i].iov_len = buffers[i].len;
-        }
-    }
-    else
-    {
-        const WSABUF *buffers = buffers_ptr;
-
-        for (i = 0; i < count; ++i)
-        {
-            async->iov[i].iov_base = buffers[i].buf;
-            async->iov[i].iov_len = buffers[i].len;
-        }
-    }
-    async->unix_flags = unix_flags;
-    async->addr = addr;
-    async->addr_len = addr_len;
-    async->iov_cursor = 0;
-    async->sent_len = 0;
 
     SERVER_START_REQ( send_socket )
     {
@@ -982,6 +946,72 @@ static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
     return status;
 }
 
+static NTSTATUS sock_ioctl_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
+                                 IO_STATUS_BLOCK *io, int fd, const void *buffers_ptr, unsigned int count,
+                                 const struct WS_sockaddr *addr, unsigned int addr_len, int unix_flags, int force_async )
+{
+    struct async_send_ioctl *async;
+    DWORD async_size;
+    unsigned int i;
+
+    async_size = offsetof( struct async_send_ioctl, iov[count] );
+
+    if (!(async = (struct async_send_ioctl *)alloc_fileio( async_size, async_send_proc, handle )))
+        return STATUS_NO_MEMORY;
+
+    async->count = count;
+    if (in_wow64_call())
+    {
+        const struct afd_wsabuf_32 *buffers = buffers_ptr;
+
+        for (i = 0; i < count; ++i)
+        {
+            async->iov[i].iov_base = ULongToPtr( buffers[i].buf );
+            async->iov[i].iov_len = buffers[i].len;
+        }
+    }
+    else
+    {
+        const WSABUF *buffers = buffers_ptr;
+
+        for (i = 0; i < count; ++i)
+        {
+            async->iov[i].iov_base = buffers[i].buf;
+            async->iov[i].iov_len = buffers[i].len;
+        }
+    }
+    async->unix_flags = unix_flags;
+    async->addr = addr;
+    async->addr_len = addr_len;
+    async->iov_cursor = 0;
+    async->sent_len = 0;
+
+    return sock_send( handle, event, apc, apc_user, io, fd, async, force_async );
+}
+
+
+NTSTATUS sock_write( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc,
+                     void *apc_user, IO_STATUS_BLOCK *io, const void *buffer, ULONG length )
+{
+    static const DWORD async_size = offsetof( struct async_send_ioctl, iov[1] );
+    struct async_send_ioctl *async;
+
+    if (!(async = (struct async_send_ioctl *)alloc_fileio( async_size, async_recv_proc, handle )))
+        return STATUS_NO_MEMORY;
+
+    async->count = 1;
+    async->iov[0].iov_base = (void *)buffer;
+    async->iov[0].iov_len = length;
+    async->unix_flags = 0;
+    async->addr = NULL;
+    async->addr_len = 0;
+    async->iov_cursor = 0;
+    async->sent_len = 0;
+
+    return sock_send( handle, event, apc, apc_user, io, fd, async, 1 );
+}
+
+
 static ssize_t do_send( int fd, const void *buffer, size_t len, int flags )
 {
     ssize_t ret;
@@ -1420,8 +1450,9 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
                 WARN( "ignoring MSG_PARTIAL\n" );
             if (params->ws_flags & ~(WS_MSG_OOB | WS_MSG_PARTIAL))
                 FIXME( "unknown flags %#x\n", params->ws_flags );
-            status = sock_send( handle, event, apc, apc_user, io, fd, u64_to_user_ptr( params->buffers_ptr ), params->count,
-                                u64_to_user_ptr( params->addr_ptr ), params->addr_len, unix_flags, params->force_async );
+            status = sock_ioctl_send( handle, event, apc, apc_user, io, fd, u64_to_user_ptr( params->buffers_ptr ),
+                                      params->count, u64_to_user_ptr( params->addr_ptr ), params->addr_len,
+                                      unix_flags, params->force_async );
             if (needs_close) close( fd );
             return status;
         }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index 8d305bdada6..47f0f9c56a9 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -258,6 +258,8 @@ extern NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, vo
                             ULONG code, void *in_buffer, ULONG in_size, void *out_buffer, ULONG out_size ) DECLSPEC_HIDDEN;
 extern NTSTATUS sock_read( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
                            IO_STATUS_BLOCK *io, void *buffer, ULONG length ) DECLSPEC_HIDDEN;
+extern NTSTATUS sock_write( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
+                            IO_STATUS_BLOCK *io, const void *buffer, ULONG length ) DECLSPEC_HIDDEN;
 extern NTSTATUS tape_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user,
                                       IO_STATUS_BLOCK *io, ULONG code, void *in_buffer,
                                       ULONG in_size, void *out_buffer, ULONG out_size ) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list