Commit 9783e2e1 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntdll: Use the recv_socket request for NtReadFile() on a socket.

recv_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 recv requests so that they go through recv_socket.
parent cc879c25
......@@ -5177,6 +5177,12 @@ NTSTATUS WINAPI NtReadFile( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, vo
goto done;
}
}
else if (type == FD_TYPE_SOCKET)
{
status = sock_read( handle, unix_handle, event, apc, apc_user, io, buffer, length );
if (needs_close) close( unix_handle );
return status;
}
if (type == FD_TYPE_SERIAL && async_read && length)
{
......
......@@ -676,17 +676,67 @@ static BOOL async_recv_proc( void *user, ULONG_PTR *info, NTSTATUS *status )
}
static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io,
int fd, const void *buffers_ptr, unsigned int count, WSABUF *control,
struct WS_sockaddr *addr, int *addr_len, DWORD *ret_flags, int unix_flags, int force_async )
int fd, struct async_recv_ioctl *async, int force_async )
{
struct async_recv_ioctl *async;
BOOL nonblocking, alerted;
ULONG_PTR information;
HANDLE wait_handle;
DWORD async_size;
NTSTATUS status;
unsigned int i;
ULONG options;
BOOL nonblocking, alerted;
for (i = 0; i < async->count; ++i)
{
if (!virtual_check_buffer_for_write( async->iov[i].iov_base, async->iov[i].iov_len ))
{
release_fileio( &async->io );
return STATUS_ACCESS_VIOLATION;
}
}
SERVER_START_REQ( recv_socket )
{
req->force_async = force_async;
req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
req->oob = !!(async->unix_flags & MSG_OOB);
status = wine_server_call( req );
wait_handle = wine_server_ptr_handle( reply->wait );
options = reply->options;
nonblocking = reply->nonblocking;
}
SERVER_END_REQ;
alerted = status == STATUS_ALERTED;
if (alerted)
{
status = try_recv( fd, async, &information );
if (status == STATUS_DEVICE_NOT_READY && (force_async || !nonblocking))
status = STATUS_PENDING;
}
if (status != STATUS_PENDING)
{
if (!NT_ERROR(status) || (wait_handle && !alerted))
{
io->Status = status;
io->Information = information;
}
release_fileio( &async->io );
}
if (alerted) set_async_direct_result( &wait_handle, status, information, FALSE );
if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT );
return status;
}
static NTSTATUS sock_ioctl_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io,
int fd, const void *buffers_ptr, unsigned int count, WSABUF *control,
struct WS_sockaddr *addr, int *addr_len, DWORD *ret_flags, int unix_flags, int force_async )
{
struct async_recv_ioctl *async;
DWORD async_size;
unsigned int i;
if (unix_flags & MSG_OOB)
{
......@@ -728,48 +778,29 @@ static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, voi
async->addr_len = addr_len;
async->ret_flags = ret_flags;
for (i = 0; i < count; ++i)
{
if (!virtual_check_buffer_for_write( async->iov[i].iov_base, async->iov[i].iov_len ))
{
release_fileio( &async->io );
return STATUS_ACCESS_VIOLATION;
}
}
return sock_recv( handle, event, apc, apc_user, io, fd, async, force_async );
}
SERVER_START_REQ( recv_socket )
{
req->force_async = force_async;
req->async = server_async( handle, &async->io, event, apc, apc_user, iosb_client_ptr(io) );
req->oob = !!(unix_flags & MSG_OOB);
status = wine_server_call( req );
wait_handle = wine_server_ptr_handle( reply->wait );
options = reply->options;
nonblocking = reply->nonblocking;
}
SERVER_END_REQ;
alerted = status == STATUS_ALERTED;
if (alerted)
{
status = try_recv( fd, async, &information );
if (status == STATUS_DEVICE_NOT_READY && (force_async || !nonblocking))
status = STATUS_PENDING;
}
NTSTATUS sock_read( HANDLE handle, int fd, HANDLE event, PIO_APC_ROUTINE apc,
void *apc_user, IO_STATUS_BLOCK *io, void *buffer, ULONG length )
{
static const DWORD async_size = offsetof( struct async_recv_ioctl, iov[1] );
struct async_recv_ioctl *async;
if (status != STATUS_PENDING)
{
if (!NT_ERROR(status) || (wait_handle && !alerted))
{
io->Status = status;
io->Information = information;
}
release_fileio( &async->io );
}
if (!(async = (struct async_recv_ioctl *)alloc_fileio( async_size, async_recv_proc, handle )))
return STATUS_NO_MEMORY;
if (alerted) set_async_direct_result( &wait_handle, status, information, FALSE );
if (wait_handle) status = wait_async( wait_handle, options & FILE_SYNCHRONOUS_IO_ALERT );
return status;
async->count = 1;
async->iov[0].iov_base = buffer;
async->iov[0].iov_len = length;
async->unix_flags = 0;
async->control = NULL;
async->addr = NULL;
async->addr_len = NULL;
async->ret_flags = NULL;
return sock_recv( handle, event, apc, apc_user, io, fd, async, 1 );
}
......@@ -1334,8 +1365,8 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
unix_flags |= MSG_PEEK;
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_ioctl_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) );
if (needs_close) close( fd );
return status;
}
......@@ -1361,10 +1392,10 @@ NTSTATUS sock_ioctl( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc
unix_flags |= MSG_PEEK;
if (*ws_flags & WS_MSG_WAITALL)
FIXME( "MSG_WAITALL is not supported\n" );
status = sock_recv( handle, event, apc, apc_user, io, fd, u64_to_user_ptr(params->buffers_ptr),
params->count, u64_to_user_ptr(params->control_ptr),
u64_to_user_ptr(params->addr_ptr), u64_to_user_ptr(params->addr_len_ptr),
ws_flags, unix_flags, params->force_async );
status = sock_ioctl_recv( handle, event, apc, apc_user, io, fd, u64_to_user_ptr(params->buffers_ptr),
params->count, u64_to_user_ptr(params->control_ptr),
u64_to_user_ptr(params->addr_ptr), u64_to_user_ptr(params->addr_len_ptr),
ws_flags, unix_flags, params->force_async );
if (needs_close) close( fd );
return status;
}
......
......@@ -256,6 +256,8 @@ extern NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROU
extern NTSTATUS serial_FlushBuffersFile( int fd ) DECLSPEC_HIDDEN;
extern NTSTATUS sock_ioctl( HANDLE handle, 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;
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 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;
......
......@@ -2645,7 +2645,7 @@ static void test_read_write(void)
ret = WSAEnumNetworkEvents(client, event, &events);
ok(!ret, "got error %lu\n", GetLastError());
todo_wine ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
ok(events.lNetworkEvents == FD_READ, "got events %#lx\n", events.lNetworkEvents);
memset(buffer, 0xcc, sizeof(buffer));
ret = NtReadFile((HANDLE)client, NULL, NULL, NULL, &io, buffer, sizeof(buffer), NULL, NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment