From: Zebediah Figura zfigura@codeweavers.com
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;