Commit 85a615f1 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntdll: Introduce IOCTL_AFD_WINE_SENDMSG.

parent ac3ec2d9
...@@ -92,6 +92,7 @@ struct afd_poll_params ...@@ -92,6 +92,7 @@ struct afd_poll_params
#define IOCTL_AFD_WINE_CONNECT CTL_CODE(FILE_DEVICE_NETWORK, 203, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_CONNECT CTL_CODE(FILE_DEVICE_NETWORK, 203, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_SHUTDOWN CTL_CODE(FILE_DEVICE_NETWORK, 204, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_SHUTDOWN CTL_CODE(FILE_DEVICE_NETWORK, 204, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_RECVMSG CTL_CODE(FILE_DEVICE_NETWORK, 205, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_RECVMSG CTL_CODE(FILE_DEVICE_NETWORK, 205, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_SENDMSG CTL_CODE(FILE_DEVICE_NETWORK, 206, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_AFD_WINE_ADDRESS_LIST_CHANGE CTL_CODE(FILE_DEVICE_NETWORK, 323, METHOD_BUFFERED, FILE_ANY_ACCESS)
...@@ -126,4 +127,14 @@ struct afd_recvmsg_params ...@@ -126,4 +127,14 @@ struct afd_recvmsg_params
WSABUF *buffers; WSABUF *buffers;
}; };
struct afd_sendmsg_params
{
const struct WS(sockaddr) *addr;
unsigned int addr_len;
unsigned int ws_flags;
int force_async;
unsigned int count;
const WSABUF *buffers;
};
#endif #endif
...@@ -1852,6 +1852,23 @@ struct poll_socket_reply ...@@ -1852,6 +1852,23 @@ struct poll_socket_reply
struct send_socket_request
{
struct request_header __header;
char __pad_12[4];
async_data_t async;
unsigned int status;
unsigned int total;
};
struct send_socket_reply
{
struct reply_header __header;
obj_handle_t wait;
unsigned int options;
};
struct get_next_console_request_request struct get_next_console_request_request
{ {
struct request_header __header; struct request_header __header;
...@@ -5503,6 +5520,7 @@ enum request ...@@ -5503,6 +5520,7 @@ enum request
REQ_set_socket_deferred, REQ_set_socket_deferred,
REQ_recv_socket, REQ_recv_socket,
REQ_poll_socket, REQ_poll_socket,
REQ_send_socket,
REQ_get_next_console_request, REQ_get_next_console_request,
REQ_read_directory_changes, REQ_read_directory_changes,
REQ_read_change, REQ_read_change,
...@@ -5786,6 +5804,7 @@ union generic_request ...@@ -5786,6 +5804,7 @@ union generic_request
struct set_socket_deferred_request set_socket_deferred_request; struct set_socket_deferred_request set_socket_deferred_request;
struct recv_socket_request recv_socket_request; struct recv_socket_request recv_socket_request;
struct poll_socket_request poll_socket_request; struct poll_socket_request poll_socket_request;
struct send_socket_request send_socket_request;
struct get_next_console_request_request get_next_console_request_request; struct get_next_console_request_request get_next_console_request_request;
struct read_directory_changes_request read_directory_changes_request; struct read_directory_changes_request read_directory_changes_request;
struct read_change_request read_change_request; struct read_change_request read_change_request;
...@@ -6067,6 +6086,7 @@ union generic_reply ...@@ -6067,6 +6086,7 @@ union generic_reply
struct set_socket_deferred_reply set_socket_deferred_reply; struct set_socket_deferred_reply set_socket_deferred_reply;
struct recv_socket_reply recv_socket_reply; struct recv_socket_reply recv_socket_reply;
struct poll_socket_reply poll_socket_reply; struct poll_socket_reply poll_socket_reply;
struct send_socket_reply send_socket_reply;
struct get_next_console_request_reply get_next_console_request_reply; struct get_next_console_request_reply get_next_console_request_reply;
struct read_directory_changes_reply read_directory_changes_reply; struct read_directory_changes_reply read_directory_changes_reply;
struct read_change_reply read_change_reply; struct read_change_reply read_change_reply;
...@@ -6287,7 +6307,7 @@ union generic_reply ...@@ -6287,7 +6307,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 707 #define SERVER_PROTOCOL_VERSION 708
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -1502,6 +1502,17 @@ struct poll_socket_output ...@@ -1502,6 +1502,17 @@ struct poll_socket_output
@END @END
/* Perform a send on a socket */
@REQ(send_socket)
async_data_t async; /* async I/O parameters */
unsigned int status; /* status of initial call */
unsigned int total; /* number of bytes already sent */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking send */
unsigned int options; /* device open options */
@END
/* Retrieve the next pending console ioctl request */ /* Retrieve the next pending console ioctl request */
@REQ(get_next_console_request) @REQ(get_next_console_request)
obj_handle_t handle; /* console server handle */ obj_handle_t handle; /* console server handle */
......
...@@ -179,6 +179,7 @@ DECL_HANDLER(enable_socket_event); ...@@ -179,6 +179,7 @@ DECL_HANDLER(enable_socket_event);
DECL_HANDLER(set_socket_deferred); DECL_HANDLER(set_socket_deferred);
DECL_HANDLER(recv_socket); DECL_HANDLER(recv_socket);
DECL_HANDLER(poll_socket); DECL_HANDLER(poll_socket);
DECL_HANDLER(send_socket);
DECL_HANDLER(get_next_console_request); DECL_HANDLER(get_next_console_request);
DECL_HANDLER(read_directory_changes); DECL_HANDLER(read_directory_changes);
DECL_HANDLER(read_change); DECL_HANDLER(read_change);
...@@ -461,6 +462,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -461,6 +462,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_set_socket_deferred, (req_handler)req_set_socket_deferred,
(req_handler)req_recv_socket, (req_handler)req_recv_socket,
(req_handler)req_poll_socket, (req_handler)req_poll_socket,
(req_handler)req_send_socket,
(req_handler)req_get_next_console_request, (req_handler)req_get_next_console_request,
(req_handler)req_read_directory_changes, (req_handler)req_read_directory_changes,
(req_handler)req_read_change, (req_handler)req_read_change,
...@@ -1082,6 +1084,13 @@ C_ASSERT( sizeof(struct poll_socket_request) == 64 ); ...@@ -1082,6 +1084,13 @@ C_ASSERT( sizeof(struct poll_socket_request) == 64 );
C_ASSERT( FIELD_OFFSET(struct poll_socket_reply, wait) == 8 ); C_ASSERT( FIELD_OFFSET(struct poll_socket_reply, wait) == 8 );
C_ASSERT( FIELD_OFFSET(struct poll_socket_reply, options) == 12 ); C_ASSERT( FIELD_OFFSET(struct poll_socket_reply, options) == 12 );
C_ASSERT( sizeof(struct poll_socket_reply) == 16 ); C_ASSERT( sizeof(struct poll_socket_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct send_socket_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct send_socket_request, status) == 56 );
C_ASSERT( FIELD_OFFSET(struct send_socket_request, total) == 60 );
C_ASSERT( sizeof(struct send_socket_request) == 64 );
C_ASSERT( FIELD_OFFSET(struct send_socket_reply, wait) == 8 );
C_ASSERT( FIELD_OFFSET(struct send_socket_reply, options) == 12 );
C_ASSERT( sizeof(struct send_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, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, signal) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, signal) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, read) == 20 ); C_ASSERT( FIELD_OFFSET(struct get_next_console_request_request, read) == 20 );
......
...@@ -768,14 +768,11 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) ...@@ -768,14 +768,11 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error )
event &= ~(POLLIN | POLLPRI); event &= ~(POLLIN | POLLPRI);
} }
if (is_fd_overlapped( sock->fd )) if (event & POLLOUT && async_waiting( &sock->write_q ))
{ {
if (event & POLLOUT && async_waiting( &sock->write_q )) if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock );
{ async_wake_up( &sock->write_q, STATUS_ALERTED );
if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock ); event &= ~POLLOUT;
async_wake_up( &sock->write_q, STATUS_ALERTED );
event &= ~POLLOUT;
}
} }
if (event & (POLLERR | POLLHUP)) if (event & (POLLERR | POLLHUP))
...@@ -2508,3 +2505,84 @@ DECL_HANDLER(poll_socket) ...@@ -2508,3 +2505,84 @@ DECL_HANDLER(poll_socket)
release_object( sock ); release_object( sock );
} }
DECL_HANDLER(send_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;
if (status != STATUS_SUCCESS)
{
/* send() calls only clear and reselect events if unsuccessful. */
sock->pending_events &= ~FD_WRITE;
sock->reported_events &= ~FD_WRITE;
}
/* If we had a short write and the socket is nonblocking (and the client is
* not trying to force the operation to be asynchronous), return success.
* Windows actually refuses to send any data in this case, and returns
* EWOULDBLOCK, but we have no way of doing that. */
if (status == STATUS_DEVICE_NOT_READY && req->total && (sock->state & FD_WINE_NONBLOCKING))
status = STATUS_SUCCESS;
/* send() returned EWOULDBLOCK or a short write, i.e. cannot send all data yet */
if (status == STATUS_DEVICE_NOT_READY && !(sock->state & FD_WINE_NONBLOCKING))
{
#ifdef SO_SNDTIMEO
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 WSASend*() 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_SNDTIMEO, (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_WRITE)) status = STATUS_PIPE_DISCONNECTED;
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->write_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 );
}
...@@ -2150,6 +2150,19 @@ static void dump_poll_socket_reply( const struct poll_socket_reply *req ) ...@@ -2150,6 +2150,19 @@ static void dump_poll_socket_reply( const struct poll_socket_reply *req )
dump_varargs_poll_socket_output( ", sockets=", cur_size ); dump_varargs_poll_socket_output( ", sockets=", cur_size );
} }
static void dump_send_socket_request( const struct send_socket_request *req )
{
dump_async_data( " async=", &req->async );
fprintf( stderr, ", status=%08x", req->status );
fprintf( stderr, ", total=%08x", req->total );
}
static void dump_send_socket_reply( const struct send_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 ) static void dump_get_next_console_request_request( const struct get_next_console_request_request *req )
{ {
fprintf( stderr, " handle=%04x", req->handle ); fprintf( stderr, " handle=%04x", req->handle );
...@@ -4599,6 +4612,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -4599,6 +4612,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_set_socket_deferred_request, (dump_func)dump_set_socket_deferred_request,
(dump_func)dump_recv_socket_request, (dump_func)dump_recv_socket_request,
(dump_func)dump_poll_socket_request, (dump_func)dump_poll_socket_request,
(dump_func)dump_send_socket_request,
(dump_func)dump_get_next_console_request_request, (dump_func)dump_get_next_console_request_request,
(dump_func)dump_read_directory_changes_request, (dump_func)dump_read_directory_changes_request,
(dump_func)dump_read_change_request, (dump_func)dump_read_change_request,
...@@ -4878,6 +4892,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -4878,6 +4892,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL, NULL,
(dump_func)dump_recv_socket_reply, (dump_func)dump_recv_socket_reply,
(dump_func)dump_poll_socket_reply, (dump_func)dump_poll_socket_reply,
(dump_func)dump_send_socket_reply,
(dump_func)dump_get_next_console_request_reply, (dump_func)dump_get_next_console_request_reply,
NULL, NULL,
(dump_func)dump_read_change_reply, (dump_func)dump_read_change_reply,
...@@ -5157,6 +5172,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -5157,6 +5172,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"set_socket_deferred", "set_socket_deferred",
"recv_socket", "recv_socket",
"poll_socket", "poll_socket",
"send_socket",
"get_next_console_request", "get_next_console_request",
"read_directory_changes", "read_directory_changes",
"read_change", "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