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

server: Introduce a helper to fill an iosb and terminate the async.

For convenience, and to centralize the STATUS_ALERTED logic into one place. Signed-off-by: 's avatarZebediah Figura <zfigura@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent fd4e7703
...@@ -332,6 +332,35 @@ obj_handle_t async_handoff( struct async *async, int success, data_size_t *resul ...@@ -332,6 +332,35 @@ obj_handle_t async_handoff( struct async *async, int success, data_size_t *resul
return async->wait_handle; return async->wait_handle;
} }
/* complete a request-based async with a pre-allocated buffer */
void async_request_complete( struct async *async, unsigned int status, data_size_t result,
data_size_t out_size, void *out_data )
{
struct iosb *iosb = async_get_iosb( async );
/* the async may have already been canceled */
if (iosb->status != STATUS_PENDING)
{
release_object( iosb );
free( out_data );
return;
}
iosb->status = status;
iosb->result = result;
iosb->out_data = out_data;
iosb->out_size = out_size;
release_object( iosb );
/* if the result is nonzero or there is output data, the client needs to
* make an extra request to retrieve them; use STATUS_ALERTED to signal
* this case */
if (result || out_data)
status = STATUS_ALERTED;
async_terminate( async, status );
}
/* set the timeout of an async operation */ /* set the timeout of an async operation */
void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ) void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status )
{ {
......
...@@ -976,7 +976,6 @@ static int console_flush( struct fd *fd, struct async *async ) ...@@ -976,7 +976,6 @@ static int console_flush( struct fd *fd, struct async *async )
static int screen_buffer_write( struct fd *fd, struct async *async, file_pos_t pos ) static int screen_buffer_write( struct fd *fd, struct async *async, file_pos_t pos )
{ {
struct screen_buffer *screen_buffer = get_fd_user( fd ); struct screen_buffer *screen_buffer = get_fd_user( fd );
struct iosb *iosb;
if (!screen_buffer->input || !screen_buffer->input->server) if (!screen_buffer->input || !screen_buffer->input->server)
{ {
...@@ -984,16 +983,8 @@ static int screen_buffer_write( struct fd *fd, struct async *async, file_pos_t p ...@@ -984,16 +983,8 @@ static int screen_buffer_write( struct fd *fd, struct async *async, file_pos_t p
return 0; return 0;
} }
if (!queue_host_ioctl( screen_buffer->input->server, IOCTL_CONDRV_WRITE_FILE, return queue_host_ioctl( screen_buffer->input->server, IOCTL_CONDRV_WRITE_FILE,
screen_buffer->id, async, &screen_buffer->ioctl_q )) screen_buffer->id, async, &screen_buffer->ioctl_q );
return 0;
/* we can't use default async handling, because write result is not
* compatible with ioctl result */
iosb = async_get_iosb( async );
iosb->result = iosb->in_size;
release_object( iosb );
return 1;
} }
static int screen_buffer_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) static int screen_buffer_ioctl( struct fd *fd, ioctl_code_t code, struct async *async )
...@@ -1498,36 +1489,28 @@ DECL_HANDLER(get_next_console_request) ...@@ -1498,36 +1489,28 @@ DECL_HANDLER(get_next_console_request)
if (ioctl) if (ioctl)
{ {
struct async *async = ioctl->async;
unsigned int status = req->status; unsigned int status = req->status;
if (status == STATUS_PENDING) status = STATUS_INVALID_PARAMETER; if (status == STATUS_PENDING) status = STATUS_INVALID_PARAMETER;
if (ioctl->async) if (async)
{ {
iosb = async_get_iosb( ioctl->async ); iosb = async_get_iosb( async );
if (iosb->status == STATUS_PENDING) if (iosb->status == STATUS_PENDING)
{ {
iosb->status = status; data_size_t out_size = min( iosb->out_size, get_req_data_size() );
iosb->out_size = min( iosb->out_size, get_req_data_size() ); data_size_t result = ioctl->code == IOCTL_CONDRV_WRITE_FILE ? iosb->in_size : out_size;
if (iosb->out_size) void *out_data;
{
if ((iosb->out_data = memdup( get_req_data(), iosb->out_size ))) if (!out_size || (out_data = memdup( get_req_data(), out_size )))
{ async_request_complete( async, status, result, out_size, out_data );
iosb->result = iosb->out_size; else
} async_terminate( async, STATUS_NO_MEMORY );
else if (!status)
{
iosb->status = STATUS_NO_MEMORY;
iosb->out_size = 0;
}
}
if (iosb->result) status = STATUS_ALERTED;
}
else
{
release_object( ioctl->async );
ioctl->async = NULL;
} }
release_object( async );
} }
console_host_ioctl_terminate( ioctl, status ); free( ioctl );
if (iosb) release_object( iosb ); if (iosb) release_object( iosb );
if (req->read) if (req->read)
......
...@@ -385,16 +385,12 @@ static void set_irp_result( struct irp_call *irp, unsigned int status, ...@@ -385,16 +385,12 @@ static void set_irp_result( struct irp_call *irp, unsigned int status,
irp->file = NULL; irp->file = NULL;
if (irp->async) if (irp->async)
{ {
struct iosb *iosb = irp->iosb; void *out_data;
iosb->status = status; out_size = min( irp->iosb->out_size, out_size );
iosb->result = result; if (out_size && !(out_data = memdup( out_data, out_size )))
iosb->out_size = min( iosb->out_size, out_size ); out_size = 0;
if (iosb->out_size && !(iosb->out_data = memdup( out_data, iosb->out_size ))) async_request_complete( irp->async, status, result, out_size, out_data );
iosb->out_size = 0;
if (result) status = STATUS_ALERTED;
async_terminate( irp->async, status );
release_object( irp->async ); release_object( irp->async );
irp->async = NULL; irp->async = NULL;
} }
......
...@@ -227,6 +227,8 @@ extern void async_set_completion_callback( struct async *async, async_completion ...@@ -227,6 +227,8 @@ extern void async_set_completion_callback( struct async *async, async_completion
extern void set_async_pending( struct async *async, int signal ); extern void set_async_pending( struct async *async, int signal );
extern int async_waiting( struct async_queue *queue ); extern int async_waiting( struct async_queue *queue );
extern void async_terminate( struct async *async, unsigned int status ); extern void async_terminate( struct async *async, unsigned int status );
extern void async_request_complete( struct async *async, unsigned int status, data_size_t result,
data_size_t out_size, void *out_data );
extern void async_wake_up( struct async_queue *queue, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status );
extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key ); extern struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
extern void fd_copy_completion( struct fd *src, struct fd *dst ); extern void fd_copy_completion( struct fd *src, struct fd *dst );
......
...@@ -390,9 +390,7 @@ static void wake_message( struct pipe_message *message, data_size_t result ) ...@@ -390,9 +390,7 @@ static void wake_message( struct pipe_message *message, data_size_t result )
message->async = NULL; message->async = NULL;
if (!async) return; if (!async) return;
message->iosb->status = STATUS_SUCCESS; async_request_complete( async, STATUS_SUCCESS, result, 0, NULL );
message->iosb->result = result;
async_terminate( async, message->iosb->result ? STATUS_ALERTED : STATUS_SUCCESS );
release_object( async ); release_object( async );
} }
......
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