Commit b8f4061d authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntdll: Implement IOCTL_AFD_RECV.

parent 5d3fde08
......@@ -57,6 +57,7 @@ C_SRCS = \
unix/signal_arm64.c \
unix/signal_i386.c \
unix/signal_x86_64.c \
unix/socket.c \
unix/sync.c \
unix/system.c \
unix/tape.c \
......
......@@ -4645,7 +4645,7 @@ struct async_irp
static struct async_fileio *fileio_freelist;
static void release_fileio( struct async_fileio *io )
void release_fileio( struct async_fileio *io )
{
for (;;)
{
......@@ -4655,7 +4655,7 @@ static void release_fileio( struct async_fileio *io )
}
}
static struct async_fileio *alloc_fileio( DWORD size, async_callback_t callback, HANDLE handle )
struct async_fileio *alloc_fileio( DWORD size, async_callback_t callback, HANDLE handle )
{
/* first free remaining previous fileinfos */
struct async_fileio *io = InterlockedExchangePointer( (void **)&fileio_freelist, NULL );
......@@ -5729,6 +5729,9 @@ NTSTATUS WINAPI NtDeviceIoControlFile( HANDLE handle, HANDLE event, PIO_APC_ROUT
switch (device)
{
case FILE_DEVICE_BEEP:
status = sock_ioctl( handle, event, apc, apc_context, io, code, in_buffer, in_size, out_buffer, out_size );
break;
case FILE_DEVICE_DISK:
case FILE_DEVICE_CD_ROM:
case FILE_DEVICE_DVD:
......
......@@ -257,10 +257,14 @@ extern NTSTATUS serial_DeviceIoControl( HANDLE device, HANDLE event, PIO_APC_ROU
IO_STATUS_BLOCK *io, ULONG code, void *in_buffer,
ULONG in_size, void *out_buffer, ULONG out_size ) DECLSPEC_HIDDEN;
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 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;
extern struct async_fileio *alloc_fileio( DWORD size, async_callback_t callback, HANDLE handle ) DECLSPEC_HIDDEN;
extern void release_fileio( struct async_fileio *io ) DECLSPEC_HIDDEN;
extern NTSTATUS errno_to_status( int err ) DECLSPEC_HIDDEN;
extern BOOL get_redirect( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *redir ) DECLSPEC_HIDDEN;
extern NTSTATUS nt_to_unix_file_name( const OBJECT_ATTRIBUTES *attr, char **name_ret, UINT disposition ) DECLSPEC_HIDDEN;
......
......@@ -21,10 +21,12 @@
#ifndef __WINE_WINE_AFD_H
#define __WINE_WINE_AFD_H
#include <winternl.h>
#include <winioctl.h>
#include "wine/server_protocol.h"
#define IOCTL_AFD_LISTEN CTL_CODE(FILE_DEVICE_BEEP, 0x802, METHOD_NEITHER, FILE_ANY_ACCESS)
#define IOCTL_AFD_RECV CTL_CODE(FILE_DEVICE_BEEP, 0x805, METHOD_NEITHER, FILE_ANY_ACCESS)
struct afd_listen_params
{
......@@ -33,6 +35,21 @@ struct afd_listen_params
int unknown2;
};
#define AFD_RECV_FORCE_ASYNC 0x2
#define AFD_MSG_NOT_OOB 0x0020
#define AFD_MSG_OOB 0x0040
#define AFD_MSG_PEEK 0x0080
#define AFD_MSG_WAITALL 0x4000
struct afd_recv_params
{
const WSABUF *buffers;
unsigned int count;
int recv_flags;
int msg_flags;
};
#define IOCTL_AFD_WINE_CREATE CTL_CODE(FILE_DEVICE_NETWORK, 200, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ACCEPT CTL_CODE(FILE_DEVICE_NETWORK, 201, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ACCEPT_INTO CTL_CODE(FILE_DEVICE_NETWORK, 202, METHOD_BUFFERED, FILE_ANY_ACCESS)
......
......@@ -1818,6 +1818,23 @@ struct set_socket_deferred_reply
struct recv_socket_request
{
struct request_header __header;
char __pad_12[4];
async_data_t async;
unsigned int status;
unsigned int total;
};
struct recv_socket_reply
{
struct reply_header __header;
obj_handle_t wait;
unsigned int options;
};
struct get_next_console_request_request
{
struct request_header __header;
......@@ -5467,6 +5484,7 @@ enum request
REQ_get_socket_info,
REQ_enable_socket_event,
REQ_set_socket_deferred,
REQ_recv_socket,
REQ_get_next_console_request,
REQ_read_directory_changes,
REQ_read_change,
......@@ -5748,6 +5766,7 @@ union generic_request
struct get_socket_info_request get_socket_info_request;
struct enable_socket_event_request enable_socket_event_request;
struct set_socket_deferred_request set_socket_deferred_request;
struct recv_socket_request recv_socket_request;
struct get_next_console_request_request get_next_console_request_request;
struct read_directory_changes_request read_directory_changes_request;
struct read_change_request read_change_request;
......@@ -6027,6 +6046,7 @@ union generic_reply
struct get_socket_info_reply get_socket_info_reply;
struct enable_socket_event_reply enable_socket_event_reply;
struct set_socket_deferred_reply set_socket_deferred_reply;
struct recv_socket_reply recv_socket_reply;
struct get_next_console_request_reply get_next_console_request_reply;
struct read_directory_changes_reply read_directory_changes_reply;
struct read_change_reply read_change_reply;
......@@ -6247,7 +6267,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 702
#define SERVER_PROTOCOL_VERSION 703
/* ### protocol_version end ### */
......
......@@ -2076,6 +2076,12 @@ unsigned int get_fd_options( struct fd *fd )
return fd->options;
}
/* retrieve the completion flags for the fd */
unsigned int get_fd_comp_flags( struct fd *fd )
{
return fd->comp_flags;
}
/* check if fd is in overlapped mode */
int is_fd_overlapped( struct fd *fd )
{
......
......@@ -89,6 +89,7 @@ extern struct fd *get_fd_object_for_mapping( struct fd *fd, unsigned int access,
extern void *get_fd_user( struct fd *fd );
extern void set_fd_user( struct fd *fd, const struct fd_ops *ops, struct object *user );
extern unsigned int get_fd_options( struct fd *fd );
extern unsigned int get_fd_comp_flags( struct fd *fd );
extern int is_fd_overlapped( struct fd *fd );
extern int get_unix_fd( struct fd *fd );
extern int is_same_file_fd( struct fd *fd1, struct fd *fd2 );
......
......@@ -1479,6 +1479,17 @@ enum server_fd_type
@END
/* Perform a recv on a socket */
@REQ(recv_socket)
async_data_t async; /* async I/O parameters */
unsigned int status; /* status of initial call */
unsigned int total; /* number of bytes already read */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking recv */
unsigned int options; /* device open options */
@END
/* Retrieve the next pending console ioctl request */
@REQ(get_next_console_request)
obj_handle_t handle; /* console server handle */
......
......@@ -177,6 +177,7 @@ DECL_HANDLER(get_socket_event);
DECL_HANDLER(get_socket_info);
DECL_HANDLER(enable_socket_event);
DECL_HANDLER(set_socket_deferred);
DECL_HANDLER(recv_socket);
DECL_HANDLER(get_next_console_request);
DECL_HANDLER(read_directory_changes);
DECL_HANDLER(read_change);
......@@ -457,6 +458,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_get_socket_info,
(req_handler)req_enable_socket_event,
(req_handler)req_set_socket_deferred,
(req_handler)req_recv_socket,
(req_handler)req_get_next_console_request,
(req_handler)req_read_directory_changes,
(req_handler)req_read_change,
......@@ -1064,6 +1066,13 @@ C_ASSERT( sizeof(struct enable_socket_event_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct set_socket_deferred_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_socket_deferred_request, deferred) == 16 );
C_ASSERT( sizeof(struct set_socket_deferred_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_request, status) == 56 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_request, total) == 60 );
C_ASSERT( sizeof(struct recv_socket_request) == 64 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, wait) == 8 );
C_ASSERT( FIELD_OFFSET(struct recv_socket_reply, options) == 12 );
C_ASSERT( sizeof(struct recv_socket_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, signal) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, read) == 20 );
......
......@@ -653,14 +653,15 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
async_terminate( sock->connect_req->async, get_error() );
}
if (event & (POLLIN | POLLPRI) && async_waiting( &sock->read_q ))
{
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
async_wake_up( &sock->read_q, STATUS_ALERTED );
event &= ~(POLLIN | POLLPRI);
}
if (is_fd_overlapped( sock->fd ))
{
if (event & (POLLIN|POLLPRI) && async_waiting( &sock->read_q ))
{
if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock );
async_wake_up( &sock->read_q, STATUS_ALERTED );
event &= ~(POLLIN|POLLPRI);
}
if (event & POLLOUT && async_waiting( &sock->write_q ))
{
if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock );
......@@ -2129,3 +2130,73 @@ DECL_HANDLER(get_socket_info)
release_object( &sock->obj );
}
DECL_HANDLER(recv_socket)
{
struct sock *sock = (struct sock *)get_handle_obj( current->process, req->async.handle, 0, &sock_ops );
unsigned int status = req->status;
timeout_t timeout = 0;
struct async *async;
struct fd *fd;
if (!sock) return;
fd = sock->fd;
/* recv() returned EWOULDBLOCK, i.e. no data available yet */
if (status == STATUS_DEVICE_NOT_READY && !(sock->state & FD_WINE_NONBLOCKING))
{
#ifdef SO_RCVTIMEO
struct timeval tv;
socklen_t len = sizeof(tv);
/* Set a timeout on the async if necessary.
*
* We want to do this *only* if the client gave us STATUS_DEVICE_NOT_READY.
* If the client gave us STATUS_PENDING, it expects the async to always
* block (it was triggered by WSARecv*() with a valid OVERLAPPED
* structure) and for the timeout not to be respected. */
if (is_fd_overlapped( fd ) && !getsockopt( get_unix_fd( fd ), SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &len ))
timeout = tv.tv_sec * -10000000 + tv.tv_usec * -10;
#endif
status = STATUS_PENDING;
}
/* are we shut down? */
if (status == STATUS_PENDING && !(sock->state & FD_READ)) status = STATUS_PIPE_DISCONNECTED;
sock->pending_events &= ~FD_READ;
sock->reported_events &= ~FD_READ;
if ((async = create_request_async( fd, get_fd_comp_flags( fd ), &req->async )))
{
int success = 0;
if (status == STATUS_SUCCESS)
{
struct iosb *iosb = async_get_iosb( async );
iosb->result = req->total;
release_object( iosb );
success = 1;
}
else if (status == STATUS_PENDING)
{
success = 1;
}
set_error( status );
if (timeout)
async_set_timeout( async, timeout, STATUS_IO_TIMEOUT );
if (status == STATUS_PENDING)
queue_async( &sock->read_q, async );
/* always reselect; we changed reported_events above */
sock_reselect( sock );
reply->wait = async_handoff( async, success, NULL, 0 );
reply->options = get_fd_options( fd );
release_object( async );
}
release_object( sock );
}
......@@ -2094,6 +2094,19 @@ static void dump_set_socket_deferred_request( const struct set_socket_deferred_r
fprintf( stderr, ", deferred=%04x", req->deferred );
}
static void dump_recv_socket_request( const struct recv_socket_request *req )
{
dump_async_data( " async=", &req->async );
fprintf( stderr, ", status=%08x", req->status );
fprintf( stderr, ", total=%08x", req->total );
}
static void dump_recv_socket_reply( const struct recv_socket_reply *req )
{
fprintf( stderr, " wait=%04x", req->wait );
fprintf( stderr, ", options=%08x", req->options );
}
static void dump_get_next_console_request_request( const struct get_next_console_request_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
......@@ -4540,6 +4553,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_socket_info_request,
(dump_func)dump_enable_socket_event_request,
(dump_func)dump_set_socket_deferred_request,
(dump_func)dump_recv_socket_request,
(dump_func)dump_get_next_console_request_request,
(dump_func)dump_read_directory_changes_request,
(dump_func)dump_read_change_request,
......@@ -4817,6 +4831,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_socket_info_reply,
NULL,
NULL,
(dump_func)dump_recv_socket_reply,
(dump_func)dump_get_next_console_request_reply,
NULL,
(dump_func)dump_read_change_reply,
......@@ -5094,6 +5109,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_socket_info",
"enable_socket_event",
"set_socket_deferred",
"recv_socket",
"get_next_console_request",
"read_directory_changes",
"read_change",
......
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