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
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 */
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 )
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 iosb *iosb;
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
return 0;
}
if (!queue_host_ioctl( screen_buffer->input->server, IOCTL_CONDRV_WRITE_FILE,
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;
return queue_host_ioctl( screen_buffer->input->server, IOCTL_CONDRV_WRITE_FILE,
screen_buffer->id, async, &screen_buffer->ioctl_q );
}
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)
if (ioctl)
{
struct async *async = ioctl->async;
unsigned int status = req->status;
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)
{
iosb->status = status;
iosb->out_size = min( iosb->out_size, get_req_data_size() );
if (iosb->out_size)
{
if ((iosb->out_data = memdup( get_req_data(), iosb->out_size )))
{
iosb->result = iosb->out_size;
}
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;
data_size_t 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;
void *out_data;
if (!out_size || (out_data = memdup( get_req_data(), out_size )))
async_request_complete( async, status, result, out_size, out_data );
else
async_terminate( async, STATUS_NO_MEMORY );
}
release_object( async );
}
console_host_ioctl_terminate( ioctl, status );
free( ioctl );
if (iosb) release_object( iosb );
if (req->read)
......
......@@ -385,16 +385,12 @@ static void set_irp_result( struct irp_call *irp, unsigned int status,
irp->file = NULL;
if (irp->async)
{
struct iosb *iosb = irp->iosb;
void *out_data;
iosb->status = status;
iosb->result = result;
iosb->out_size = min( iosb->out_size, out_size );
if (iosb->out_size && !(iosb->out_data = memdup( out_data, iosb->out_size )))
iosb->out_size = 0;
if (result) status = STATUS_ALERTED;
async_terminate( irp->async, status );
out_size = min( irp->iosb->out_size, out_size );
if (out_size && !(out_data = memdup( out_data, out_size )))
out_size = 0;
async_request_complete( irp->async, status, result, out_size, out_data );
release_object( irp->async );
irp->async = NULL;
}
......
......@@ -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 int async_waiting( struct async_queue *queue );
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 struct completion *fd_get_completion( struct fd *fd, apc_param_t *p_key );
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 )
message->async = NULL;
if (!async) return;
message->iosb->status = STATUS_SUCCESS;
message->iosb->result = result;
async_terminate( async, message->iosb->result ? STATUS_ALERTED : STATUS_SUCCESS );
async_request_complete( async, STATUS_SUCCESS, result, 0, NULL );
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