server: Add support for retrieving results of queued ioctls once they are done.
diff --git a/server/device.c b/server/device.c
index b811ff1..c52cd22 100644
--- a/server/device.c
+++ b/server/device.c
@@ -269,6 +269,18 @@
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 @@
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 );
+}
diff --git a/server/protocol.def b/server/protocol.def
index 55055a4..fb2d8cd 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1979,6 +1979,15 @@
@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;
diff --git a/server/request.h b/server/request.h
index 4f175a6..90a0c6c 100644
--- a/server/request.h
+++ b/server/request.h
@@ -245,6 +245,7 @@
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 @@
(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,
diff --git a/server/trace.c b/server/trace.c
index 7b8b7e4..8ae8d73 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2424,6 +2424,18 @@
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 @@
(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 @@
(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 @@
"register_async",
"cancel_async",
"ioctl",
+ "get_ioctl_result",
"create_named_pipe",
"get_named_pipe_info",
"create_window",