server: Add support for retrieving results of queued ioctls once they are done.
This commit is contained in:
parent
78b75108cd
commit
aafcfe7663
|
@ -918,10 +918,35 @@ done:
|
|||
}
|
||||
|
||||
|
||||
struct async_ioctl
|
||||
{
|
||||
HANDLE handle; /* handle to the device */
|
||||
void *buffer; /* buffer for output */
|
||||
ULONG size; /* size of buffer */
|
||||
};
|
||||
|
||||
/* callback for ioctl async I/O completion */
|
||||
static NTSTATUS ioctl_completion( void *arg, IO_STATUS_BLOCK *io, NTSTATUS status )
|
||||
{
|
||||
io->u.Status = status;
|
||||
struct async_ioctl *async = arg;
|
||||
|
||||
if (status == STATUS_ALERTED)
|
||||
{
|
||||
SERVER_START_REQ( get_ioctl_result )
|
||||
{
|
||||
req->handle = async->handle;
|
||||
req->user_arg = async;
|
||||
wine_server_set_reply( req, async->buffer, async->size );
|
||||
if (!(status = wine_server_call( req )))
|
||||
io->Information = wine_server_reply_size( reply );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
if (status != STATUS_PENDING)
|
||||
{
|
||||
RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||
io->u.Status = status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -932,17 +957,24 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
|||
PVOID in_buffer, ULONG in_size,
|
||||
PVOID out_buffer, ULONG out_size )
|
||||
{
|
||||
struct async_ioctl *async;
|
||||
NTSTATUS status;
|
||||
HANDLE wait_handle;
|
||||
ULONG options;
|
||||
|
||||
if (!(async = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*async) )))
|
||||
return STATUS_NO_MEMORY;
|
||||
async->handle = handle;
|
||||
async->buffer = out_buffer;
|
||||
async->size = out_size;
|
||||
|
||||
SERVER_START_REQ( ioctl )
|
||||
{
|
||||
req->handle = handle;
|
||||
req->code = code;
|
||||
req->async.callback = ioctl_completion;
|
||||
req->async.iosb = io;
|
||||
req->async.arg = NULL;
|
||||
req->async.arg = async;
|
||||
req->async.apc = apc;
|
||||
req->async.apc_arg = apc_context;
|
||||
req->async.event = event;
|
||||
|
@ -959,6 +991,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event,
|
|||
FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n",
|
||||
code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3);
|
||||
|
||||
if (status != STATUS_PENDING) RtlFreeHeap( GetProcessHeap(), 0, async );
|
||||
|
||||
if (wait_handle)
|
||||
{
|
||||
NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL );
|
||||
|
|
|
@ -2684,6 +2684,20 @@ struct ioctl_reply
|
|||
|
||||
|
||||
|
||||
struct get_ioctl_result_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
void* user_arg;
|
||||
};
|
||||
struct get_ioctl_result_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
/* VARARG(out_data,bytes); */
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct create_named_pipe_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -4172,6 +4186,7 @@ enum request
|
|||
REQ_register_async,
|
||||
REQ_cancel_async,
|
||||
REQ_ioctl,
|
||||
REQ_get_ioctl_result,
|
||||
REQ_create_named_pipe,
|
||||
REQ_get_named_pipe_info,
|
||||
REQ_create_window,
|
||||
|
@ -4397,6 +4412,7 @@ union generic_request
|
|||
struct register_async_request register_async_request;
|
||||
struct cancel_async_request cancel_async_request;
|
||||
struct ioctl_request ioctl_request;
|
||||
struct get_ioctl_result_request get_ioctl_result_request;
|
||||
struct create_named_pipe_request create_named_pipe_request;
|
||||
struct get_named_pipe_info_request get_named_pipe_info_request;
|
||||
struct create_window_request create_window_request;
|
||||
|
@ -4620,6 +4636,7 @@ union generic_reply
|
|||
struct register_async_reply register_async_reply;
|
||||
struct cancel_async_reply cancel_async_reply;
|
||||
struct ioctl_reply ioctl_reply;
|
||||
struct get_ioctl_result_reply get_ioctl_result_reply;
|
||||
struct create_named_pipe_reply create_named_pipe_reply;
|
||||
struct get_named_pipe_info_reply get_named_pipe_info_reply;
|
||||
struct create_window_reply create_window_reply;
|
||||
|
@ -4705,6 +4722,6 @@ union generic_reply
|
|||
struct get_next_device_request_reply get_next_device_request_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 302
|
||||
#define SERVER_PROTOCOL_VERSION 303
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -269,6 +269,18 @@ static enum server_fd_type device_get_fd_type( struct fd *fd )
|
|||
return FD_TYPE_DEVICE;
|
||||
}
|
||||
|
||||
static struct ioctl_call *find_ioctl_call( struct device *device, struct thread *thread,
|
||||
void *user_arg )
|
||||
{
|
||||
struct ioctl_call *ioctl;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( ioctl, &device->requests, struct ioctl_call, dev_entry )
|
||||
if (ioctl->thread == thread && ioctl->user_arg == user_arg) return ioctl;
|
||||
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
|
||||
const void *data, data_size_t size )
|
||||
{
|
||||
|
@ -488,3 +500,31 @@ DECL_HANDLER(get_next_device_request)
|
|||
|
||||
release_object( manager );
|
||||
}
|
||||
|
||||
|
||||
/* retrieve results of an async ioctl */
|
||||
DECL_HANDLER(get_ioctl_result)
|
||||
{
|
||||
struct device *device;
|
||||
struct ioctl_call *ioctl;
|
||||
|
||||
if (!(device = (struct device *)get_handle_obj( current->process, req->handle, 0, &device_ops )))
|
||||
return;
|
||||
|
||||
if ((ioctl = find_ioctl_call( device, current, req->user_arg )))
|
||||
{
|
||||
if (ioctl->out_data)
|
||||
{
|
||||
data_size_t size = min( ioctl->out_size, get_reply_max_size() );
|
||||
if (size)
|
||||
{
|
||||
set_reply_data_ptr( ioctl->out_data, size );
|
||||
ioctl->out_data = NULL;
|
||||
}
|
||||
}
|
||||
set_error( ioctl->status );
|
||||
list_remove( &ioctl->dev_entry );
|
||||
release_object( ioctl ); /* no longer on the device queue */
|
||||
}
|
||||
release_object( device );
|
||||
}
|
||||
|
|
|
@ -1979,6 +1979,15 @@ enum message_type
|
|||
@END
|
||||
|
||||
|
||||
/* Retrieve results of an async ioctl */
|
||||
@REQ(get_ioctl_result)
|
||||
obj_handle_t handle; /* handle to the device */
|
||||
void* user_arg; /* user arg used to identify the request */
|
||||
@REPLY
|
||||
VARARG(out_data,bytes); /* ioctl output data */
|
||||
@END
|
||||
|
||||
|
||||
/* Create a named pipe */
|
||||
@REQ(create_named_pipe)
|
||||
unsigned int access;
|
||||
|
|
|
@ -245,6 +245,7 @@ DECL_HANDLER(set_serial_info);
|
|||
DECL_HANDLER(register_async);
|
||||
DECL_HANDLER(cancel_async);
|
||||
DECL_HANDLER(ioctl);
|
||||
DECL_HANDLER(get_ioctl_result);
|
||||
DECL_HANDLER(create_named_pipe);
|
||||
DECL_HANDLER(get_named_pipe_info);
|
||||
DECL_HANDLER(create_window);
|
||||
|
@ -469,6 +470,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_register_async,
|
||||
(req_handler)req_cancel_async,
|
||||
(req_handler)req_ioctl,
|
||||
(req_handler)req_get_ioctl_result,
|
||||
(req_handler)req_create_named_pipe,
|
||||
(req_handler)req_get_named_pipe_info,
|
||||
(req_handler)req_create_window,
|
||||
|
|
|
@ -2424,6 +2424,18 @@ static void dump_ioctl_reply( const struct ioctl_reply *req )
|
|||
dump_varargs_bytes( cur_size );
|
||||
}
|
||||
|
||||
static void dump_get_ioctl_result_request( const struct get_ioctl_result_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%p,", req->handle );
|
||||
fprintf( stderr, " user_arg=%p", req->user_arg );
|
||||
}
|
||||
|
||||
static void dump_get_ioctl_result_reply( const struct get_ioctl_result_reply *req )
|
||||
{
|
||||
fprintf( stderr, " out_data=" );
|
||||
dump_varargs_bytes( cur_size );
|
||||
}
|
||||
|
||||
static void dump_create_named_pipe_request( const struct create_named_pipe_request *req )
|
||||
{
|
||||
fprintf( stderr, " access=%08x,", req->access );
|
||||
|
@ -3650,6 +3662,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_register_async_request,
|
||||
(dump_func)dump_cancel_async_request,
|
||||
(dump_func)dump_ioctl_request,
|
||||
(dump_func)dump_get_ioctl_result_request,
|
||||
(dump_func)dump_create_named_pipe_request,
|
||||
(dump_func)dump_get_named_pipe_info_request,
|
||||
(dump_func)dump_create_window_request,
|
||||
|
@ -3871,6 +3884,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)0,
|
||||
(dump_func)0,
|
||||
(dump_func)dump_ioctl_reply,
|
||||
(dump_func)dump_get_ioctl_result_reply,
|
||||
(dump_func)dump_create_named_pipe_reply,
|
||||
(dump_func)dump_get_named_pipe_info_reply,
|
||||
(dump_func)dump_create_window_reply,
|
||||
|
@ -4092,6 +4106,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"register_async",
|
||||
"cancel_async",
|
||||
"ioctl",
|
||||
"get_ioctl_result",
|
||||
"create_named_pipe",
|
||||
"get_named_pipe_info",
|
||||
"create_window",
|
||||
|
|
Loading…
Reference in New Issue