server: Add infrastructure for ioctl server request.
diff --git a/server/change.c b/server/change.c
index c7d5823..e996d49 100644
--- a/server/change.c
+++ b/server/change.c
@@ -187,6 +187,7 @@
default_poll_event, /* poll_event */
no_flush, /* flush */
dir_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
@@ -520,6 +521,7 @@
inotify_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL, /* cancel_async */
diff --git a/server/fd.c b/server/fd.c
index 88fa6a4..37ddefb 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1686,6 +1686,13 @@
else if (!fd->inode) set_fd_events( fd, fd->fd_ops->get_poll_events( fd ) );
}
+/* default ioctl() routine */
+void default_fd_ioctl( struct fd *fd, unsigned int code, const async_data_t *async,
+ const void *data, data_size_t size )
+{
+ set_error( STATUS_NOT_SUPPORTED );
+}
+
struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
{
struct async_queue *queue;
@@ -1918,6 +1925,19 @@
}
}
+/* perform an ioctl on a file */
+DECL_HANDLER(ioctl)
+{
+ unsigned int access = (req->code >> 14) & (FILE_READ_DATA|FILE_WRITE_DATA);
+ struct fd *fd = get_handle_fd_obj( current->process, req->handle, access );
+
+ if (fd)
+ {
+ fd->fd_ops->ioctl( fd, req->code, &req->async, get_req_data(), get_req_data_size() );
+ release_object( fd );
+ }
+}
+
/* create / reschedule an async I/O */
DECL_HANDLER(register_async)
{
diff --git a/server/file.c b/server/file.c
index 8e10847..a45c340 100644
--- a/server/file.c
+++ b/server/file.c
@@ -94,6 +94,7 @@
default_poll_event, /* poll_event */
file_flush, /* flush */
file_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
diff --git a/server/file.h b/server/file.h
index 5e2e5f0..2c54e4d 100644
--- a/server/file.h
+++ b/server/file.h
@@ -39,6 +39,9 @@
void (*flush)(struct fd *, struct event **);
/* get file information */
enum server_fd_type (*get_fd_type)(struct fd *fd);
+ /* perform an ioctl on the file */
+ void (*ioctl)(struct fd *fd, unsigned int code, const async_data_t *async,
+ const void *data, data_size_t size);
/* queue an async operation */
void (*queue_async)(struct fd *, const async_data_t *data, int type, int count);
/* selected events for async i/o need an update */
@@ -74,6 +77,8 @@
extern struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
+extern void default_fd_ioctl( struct fd *fd, unsigned int code, const async_data_t *async,
+ const void *data, data_size_t size );
extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );
extern void default_fd_cancel_async( struct fd *fd );
diff --git a/server/mailslot.c b/server/mailslot.c
index 8872742..94f7f34 100644
--- a/server/mailslot.c
+++ b/server/mailslot.c
@@ -96,6 +96,7 @@
default_poll_event, /* poll_event */
no_flush, /* flush */
mailslot_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
mailslot_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
@@ -142,6 +143,7 @@
default_poll_event, /* poll_event */
no_flush, /* flush */
mail_writer_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
@@ -187,6 +189,7 @@
default_poll_event, /* poll_event */
no_flush, /* flush */
mailslot_device_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
diff --git a/server/named_pipe.c b/server/named_pipe.c
index d5b88a2..62c30c4 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -162,6 +162,7 @@
default_poll_event, /* poll_event */
pipe_server_flush, /* flush */
pipe_server_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async, /* cancel_async */
@@ -197,6 +198,7 @@
default_poll_event, /* poll_event */
pipe_client_flush, /* flush */
pipe_client_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
@@ -234,6 +236,7 @@
default_poll_event, /* poll_event */
no_flush, /* flush */
named_pipe_device_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
diff --git a/server/process.c b/server/process.c
index 2e9fd59..fffae51 100644
--- a/server/process.c
+++ b/server/process.c
@@ -86,6 +86,7 @@
process_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL /* cancel async */
diff --git a/server/protocol.def b/server/protocol.def
index 3396d4a..3ca7241 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1972,6 +1972,17 @@
@END
+/* Perform an ioctl on a file */
+@REQ(ioctl)
+ obj_handle_t handle; /* handle to the device */
+ unsigned int code; /* ioctl code */
+ async_data_t async; /* async I/O parameters */
+ VARARG(in_data,bytes); /* ioctl input data */
+@REPLY
+ VARARG(out_data,bytes); /* ioctl output data */
+@END
+
+
/* Create a named pipe */
@REQ(create_named_pipe)
unsigned int access;
diff --git a/server/queue.c b/server/queue.c
index fa80d62..85e0856 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -168,6 +168,7 @@
msg_queue_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL /* cancel async */
diff --git a/server/request.c b/server/request.c
index 404dda0..4c4036a 100644
--- a/server/request.c
+++ b/server/request.c
@@ -108,6 +108,7 @@
master_socket_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL /* cancel_async */
diff --git a/server/request.h b/server/request.h
index 5b28a7f..3424fb3 100644
--- a/server/request.h
+++ b/server/request.h
@@ -245,6 +245,7 @@
DECL_HANDLER(set_serial_info);
DECL_HANDLER(register_async);
DECL_HANDLER(cancel_async);
+DECL_HANDLER(ioctl);
DECL_HANDLER(create_named_pipe);
DECL_HANDLER(connect_named_pipe);
DECL_HANDLER(wait_named_pipe);
@@ -468,6 +469,7 @@
(req_handler)req_set_serial_info,
(req_handler)req_register_async,
(req_handler)req_cancel_async,
+ (req_handler)req_ioctl,
(req_handler)req_create_named_pipe,
(req_handler)req_connect_named_pipe,
(req_handler)req_wait_named_pipe,
diff --git a/server/serial.c b/server/serial.c
index 4d1853c..d677d17 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -107,6 +107,7 @@
default_poll_event, /* poll_event */
serial_flush, /* flush */
serial_get_fd_type, /* get_file_info */
+ default_fd_ioctl, /* ioctl */
serial_queue_async, /* queue_async */
default_fd_reselect_async, /* reselect_async */
default_fd_cancel_async /* cancel_async */
diff --git a/server/signal.c b/server/signal.c
index 11a0179..fb16c2f 100644
--- a/server/signal.c
+++ b/server/signal.c
@@ -84,6 +84,7 @@
handler_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL /* cancel_async */
diff --git a/server/sock.c b/server/sock.c
index 817c6bd..29b685e 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -126,6 +126,7 @@
sock_poll_event, /* poll_event */
no_flush, /* flush */
sock_get_fd_type, /* get_file_info */
+ default_fd_ioctl, /* ioctl */
sock_queue_async, /* queue_async */
sock_reselect_async, /* reselect_async */
sock_cancel_async /* cancel_async */
diff --git a/server/thread.c b/server/thread.c
index 2bf031e..8e63e8b 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -131,6 +131,7 @@
thread_poll_event, /* poll_event */
NULL, /* flush */
NULL, /* get_fd_type */
+ NULL, /* ioctl */
NULL, /* queue_async */
NULL, /* reselect_async */
NULL /* cancel_async */
diff --git a/server/trace.c b/server/trace.c
index 2b42a90..84c409e 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2401,6 +2401,23 @@
fprintf( stderr, " handle=%p", req->handle );
}
+static void dump_ioctl_request( const struct ioctl_request *req )
+{
+ fprintf( stderr, " handle=%p,", req->handle );
+ fprintf( stderr, " code=%08x,", req->code );
+ fprintf( stderr, " async=" );
+ dump_async_data( &req->async );
+ fprintf( stderr, "," );
+ fprintf( stderr, " in_data=" );
+ dump_varargs_bytes( cur_size );
+}
+
+static void dump_ioctl_reply( const struct ioctl_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 );
@@ -3590,6 +3607,7 @@
(dump_func)dump_set_serial_info_request,
(dump_func)dump_register_async_request,
(dump_func)dump_cancel_async_request,
+ (dump_func)dump_ioctl_request,
(dump_func)dump_create_named_pipe_request,
(dump_func)dump_connect_named_pipe_request,
(dump_func)dump_wait_named_pipe_request,
@@ -3810,6 +3828,7 @@
(dump_func)0,
(dump_func)0,
(dump_func)0,
+ (dump_func)dump_ioctl_reply,
(dump_func)dump_create_named_pipe_reply,
(dump_func)0,
(dump_func)0,
@@ -4030,6 +4049,7 @@
"set_serial_info",
"register_async",
"cancel_async",
+ "ioctl",
"create_named_pipe",
"connect_named_pipe",
"wait_named_pipe",
@@ -4166,6 +4186,7 @@
{ "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY },
{ "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED },
{ "NOT_REGISTRY_FILE", STATUS_NOT_REGISTRY_FILE },
+ { "NOT_SUPPORTED", STATUS_NOT_SUPPORTED },
{ "NO_DATA_DETECTED", STATUS_NO_DATA_DETECTED },
{ "NO_IMPERSONATION_TOKEN", STATUS_NO_IMPERSONATION_TOKEN },
{ "NO_MEMORY", STATUS_NO_MEMORY },