server: Introduced iosb struct for server-side IO_STATUS_BLOCK representation and use it in irp_call.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
478feea23c
commit
d2b3c6c3f9
|
@ -389,6 +389,68 @@ void async_wake_up( struct async_queue *queue, unsigned int status )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iosb_dump( struct object *obj, int verbose );
|
||||||
|
static void iosb_destroy( struct object *obj );
|
||||||
|
|
||||||
|
static const struct object_ops iosb_ops =
|
||||||
|
{
|
||||||
|
sizeof(struct iosb), /* size */
|
||||||
|
iosb_dump, /* dump */
|
||||||
|
no_get_type, /* get_type */
|
||||||
|
no_add_queue, /* add_queue */
|
||||||
|
NULL, /* remove_queue */
|
||||||
|
NULL, /* signaled */
|
||||||
|
NULL, /* satisfied */
|
||||||
|
no_signal, /* signal */
|
||||||
|
no_get_fd, /* get_fd */
|
||||||
|
no_map_access, /* map_access */
|
||||||
|
default_get_sd, /* get_sd */
|
||||||
|
default_set_sd, /* set_sd */
|
||||||
|
no_lookup_name, /* lookup_name */
|
||||||
|
no_link_name, /* link_name */
|
||||||
|
NULL, /* unlink_name */
|
||||||
|
no_open_file, /* open_file */
|
||||||
|
no_close_handle, /* close_handle */
|
||||||
|
iosb_destroy /* destroy */
|
||||||
|
};
|
||||||
|
|
||||||
|
static void iosb_dump( struct object *obj, int verbose )
|
||||||
|
{
|
||||||
|
assert( obj->ops == &iosb_ops );
|
||||||
|
fprintf( stderr, "I/O status block\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void iosb_destroy( struct object *obj )
|
||||||
|
{
|
||||||
|
struct iosb *iosb = (struct iosb *)obj;
|
||||||
|
|
||||||
|
free( iosb->in_data );
|
||||||
|
free( iosb->out_data );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate iosb struct */
|
||||||
|
struct iosb *create_iosb( const void *in_data, data_size_t in_size, data_size_t out_size )
|
||||||
|
{
|
||||||
|
struct iosb *iosb;
|
||||||
|
|
||||||
|
if (!(iosb = alloc_object( &iosb_ops ))) return NULL;
|
||||||
|
|
||||||
|
iosb->status = STATUS_PENDING;
|
||||||
|
iosb->result = 0;
|
||||||
|
iosb->in_size = in_size;
|
||||||
|
iosb->in_data = NULL;
|
||||||
|
iosb->out_size = out_size;
|
||||||
|
iosb->out_data = NULL;
|
||||||
|
|
||||||
|
if (in_size && !(iosb->in_data = memdup( in_data, in_size )))
|
||||||
|
{
|
||||||
|
release_object( iosb );
|
||||||
|
iosb = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return iosb;
|
||||||
|
}
|
||||||
|
|
||||||
/* cancels all async I/O */
|
/* cancels all async I/O */
|
||||||
DECL_HANDLER(cancel_async)
|
DECL_HANDLER(cancel_async)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,13 +50,8 @@ struct irp_call
|
||||||
struct thread *thread; /* thread that queued the irp */
|
struct thread *thread; /* thread that queued the irp */
|
||||||
client_ptr_t user_arg; /* user arg used to identify the request */
|
client_ptr_t user_arg; /* user arg used to identify the request */
|
||||||
struct async *async; /* pending async op */
|
struct async *async; /* pending async op */
|
||||||
unsigned int status; /* resulting status (or STATUS_PENDING) */
|
|
||||||
irp_params_t params; /* irp parameters */
|
irp_params_t params; /* irp parameters */
|
||||||
data_size_t result; /* size of result (input or output depending on the type) */
|
struct iosb *iosb; /* I/O status block */
|
||||||
data_size_t in_size; /* size of input data */
|
|
||||||
void *in_data; /* input data */
|
|
||||||
data_size_t out_size; /* size of output data */
|
|
||||||
void *out_data; /* output data */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void irp_call_dump( struct object *obj, int verbose );
|
static void irp_call_dump( struct object *obj, int verbose );
|
||||||
|
@ -241,13 +236,12 @@ static void irp_call_destroy( struct object *obj )
|
||||||
{
|
{
|
||||||
struct irp_call *irp = (struct irp_call *)obj;
|
struct irp_call *irp = (struct irp_call *)obj;
|
||||||
|
|
||||||
free( irp->in_data );
|
|
||||||
free( irp->out_data );
|
|
||||||
if (irp->async)
|
if (irp->async)
|
||||||
{
|
{
|
||||||
async_terminate( irp->async, STATUS_CANCELLED );
|
async_terminate( irp->async, STATUS_CANCELLED );
|
||||||
release_object( irp->async );
|
release_object( irp->async );
|
||||||
}
|
}
|
||||||
|
if (irp->iosb) release_object( irp->iosb );
|
||||||
if (irp->file) release_object( irp->file );
|
if (irp->file) release_object( irp->file );
|
||||||
if (irp->thread) release_object( irp->thread );
|
if (irp->thread) release_object( irp->thread );
|
||||||
}
|
}
|
||||||
|
@ -269,14 +263,8 @@ static struct irp_call *create_irp( struct device_file *file, const irp_params_t
|
||||||
irp->thread = NULL;
|
irp->thread = NULL;
|
||||||
irp->async = NULL;
|
irp->async = NULL;
|
||||||
irp->params = *params;
|
irp->params = *params;
|
||||||
irp->status = STATUS_PENDING;
|
|
||||||
irp->result = 0;
|
|
||||||
irp->in_size = in_size;
|
|
||||||
irp->in_data = NULL;
|
|
||||||
irp->out_size = out_size;
|
|
||||||
irp->out_data = NULL;
|
|
||||||
|
|
||||||
if (irp->in_size && !(irp->in_data = memdup( in_data, in_size )))
|
if (!(irp->iosb = create_iosb( in_data, in_size, out_size )))
|
||||||
{
|
{
|
||||||
release_object( irp );
|
release_object( irp );
|
||||||
irp = NULL;
|
irp = NULL;
|
||||||
|
@ -289,15 +277,16 @@ static void set_irp_result( struct irp_call *irp, unsigned int status,
|
||||||
const void *out_data, data_size_t out_size, data_size_t result )
|
const void *out_data, data_size_t out_size, data_size_t result )
|
||||||
{
|
{
|
||||||
struct device_file *file = irp->file;
|
struct device_file *file = irp->file;
|
||||||
|
struct iosb *iosb = irp->iosb;
|
||||||
|
|
||||||
if (!file) return; /* already finished */
|
if (!file) return; /* already finished */
|
||||||
|
|
||||||
/* FIXME: handle the STATUS_PENDING case */
|
/* FIXME: handle the STATUS_PENDING case */
|
||||||
irp->status = status;
|
iosb->status = status;
|
||||||
irp->result = result;
|
iosb->result = result;
|
||||||
irp->out_size = min( irp->out_size, out_size );
|
iosb->out_size = min( iosb->out_size, out_size );
|
||||||
if (irp->out_size && !(irp->out_data = memdup( out_data, irp->out_size )))
|
if (iosb->out_size && !(iosb->out_data = memdup( out_data, iosb->out_size )))
|
||||||
irp->out_size = 0;
|
iosb->out_size = 0;
|
||||||
irp->file = NULL;
|
irp->file = NULL;
|
||||||
if (irp->async)
|
if (irp->async)
|
||||||
{
|
{
|
||||||
|
@ -761,6 +750,7 @@ DECL_HANDLER(get_next_device_request)
|
||||||
struct irp_call *irp;
|
struct irp_call *irp;
|
||||||
struct device_manager *manager;
|
struct device_manager *manager;
|
||||||
struct list *ptr;
|
struct list *ptr;
|
||||||
|
struct iosb *iosb;
|
||||||
|
|
||||||
reply->params.major = IRP_MJ_MAXIMUM_FUNCTION + 1;
|
reply->params.major = IRP_MJ_MAXIMUM_FUNCTION + 1;
|
||||||
|
|
||||||
|
@ -788,14 +778,15 @@ DECL_HANDLER(get_next_device_request)
|
||||||
reply->client_tid = get_thread_id( irp->thread );
|
reply->client_tid = get_thread_id( irp->thread );
|
||||||
}
|
}
|
||||||
reply->params = irp->params;
|
reply->params = irp->params;
|
||||||
reply->in_size = irp->in_size;
|
iosb = irp->iosb;
|
||||||
reply->out_size = irp->out_size;
|
reply->in_size = iosb->in_size;
|
||||||
if (irp->in_size > get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW );
|
reply->out_size = iosb->out_size;
|
||||||
|
if (iosb->in_size > get_reply_max_size()) set_error( STATUS_BUFFER_OVERFLOW );
|
||||||
else if ((reply->next = alloc_handle( current->process, irp, 0, 0 )))
|
else if ((reply->next = alloc_handle( current->process, irp, 0, 0 )))
|
||||||
{
|
{
|
||||||
set_reply_data_ptr( irp->in_data, irp->in_size );
|
set_reply_data_ptr( iosb->in_data, iosb->in_size );
|
||||||
irp->in_data = NULL;
|
iosb->in_data = NULL;
|
||||||
irp->in_size = 0;
|
iosb->in_size = 0;
|
||||||
list_remove( &irp->mgr_entry );
|
list_remove( &irp->mgr_entry );
|
||||||
list_init( &irp->mgr_entry );
|
list_init( &irp->mgr_entry );
|
||||||
}
|
}
|
||||||
|
@ -833,17 +824,18 @@ DECL_HANDLER(get_irp_result)
|
||||||
|
|
||||||
if ((irp = find_irp_call( file, current, req->user_arg )))
|
if ((irp = find_irp_call( file, current, req->user_arg )))
|
||||||
{
|
{
|
||||||
if (irp->out_data)
|
struct iosb *iosb = irp->iosb;
|
||||||
|
if (iosb->out_data)
|
||||||
{
|
{
|
||||||
data_size_t size = min( irp->out_size, get_reply_max_size() );
|
data_size_t size = min( iosb->out_size, get_reply_max_size() );
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
set_reply_data_ptr( irp->out_data, size );
|
set_reply_data_ptr( iosb->out_data, size );
|
||||||
irp->out_data = NULL;
|
iosb->out_data = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reply->size = irp->result;
|
reply->size = iosb->result;
|
||||||
set_error( irp->status );
|
set_error( iosb->status );
|
||||||
list_remove( &irp->dev_entry );
|
list_remove( &irp->dev_entry );
|
||||||
release_object( irp ); /* no longer on the device queue */
|
release_object( irp ); /* no longer on the device queue */
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,18 @@ struct fd_ops
|
||||||
void (*reselect_async)( struct fd *, struct async_queue *queue );
|
void (*reselect_async)( struct fd *, struct async_queue *queue );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* server-side representation of I/O status block */
|
||||||
|
struct iosb
|
||||||
|
{
|
||||||
|
struct object obj; /* object header */
|
||||||
|
unsigned int status; /* resulting status (or STATUS_PENDING) */
|
||||||
|
data_size_t result; /* size of result (input or output depending on the type) */
|
||||||
|
data_size_t in_size; /* size of input data */
|
||||||
|
void *in_data; /* input data */
|
||||||
|
data_size_t out_size; /* size of output data */
|
||||||
|
void *out_data; /* output data */
|
||||||
|
};
|
||||||
|
|
||||||
/* file descriptor functions */
|
/* file descriptor functions */
|
||||||
|
|
||||||
extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user,
|
extern struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *user,
|
||||||
|
@ -175,6 +187,7 @@ extern void async_terminate( struct async *async, unsigned int status );
|
||||||
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 );
|
||||||
|
extern struct iosb *create_iosb( const void *in_data, data_size_t in_size, data_size_t out_size );
|
||||||
extern void cancel_process_asyncs( struct process *process );
|
extern void cancel_process_asyncs( struct process *process );
|
||||||
|
|
||||||
/* access rights that require Unix read permission */
|
/* access rights that require Unix read permission */
|
||||||
|
|
Loading…
Reference in New Issue