Alexandre Julliard : server: Add a structure to pass the parameters of a select request.

Alexandre Julliard julliard at winehq.org
Tue Aug 27 14:47:55 CDT 2013


Module: wine
Branch: master
Commit: c2ab7a625e5728977668688a66c4e0b7eaa14c3e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c2ab7a625e5728977668688a66c4e0b7eaa14c3e

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Aug 22 10:34:11 2013 +0200

server: Add a structure to pass the parameters of a select request.

---

 dlls/ntdll/sync.c              |    7 +++--
 include/wine/server_protocol.h |   20 +++++++++++++++-
 server/protocol.def            |   18 ++++++++++++++-
 server/thread.c                |   34 ++++++++++++++++++++++-------
 server/trace.c                 |   46 +++++++++++++++++++++++++++++++++-------
 5 files changed, 103 insertions(+), 22 deletions(-)

diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 2e6ffdf..89f6ee6 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -1109,18 +1109,19 @@ NTSTATUS NTDLL_queue_process_apc( HANDLE process, const apc_call_t *call, apc_re
 NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
                                           const LARGE_INTEGER *timeout, HANDLE signal_object )
 {
+    select_op_t select_op;
     NTSTATUS ret;
     UINT i;
     int cookie;
     BOOL user_apc = FALSE;
-    obj_handle_t obj_handles[MAXIMUM_WAIT_OBJECTS];
     obj_handle_t apc_handle = 0;
     apc_call_t call;
     apc_result_t result;
     timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
 
     memset( &result, 0, sizeof(result) );
-    for (i = 0; i < count; i++) obj_handles[i] = wine_server_obj_handle( handles[i] );
+    select_op.wait.op = SELECT_WAIT;
+    for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
 
     for (;;)
     {
@@ -1132,7 +1133,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN
             req->prev_apc = apc_handle;
             req->timeout  = abs_timeout;
             wine_server_add_data( req, &result, sizeof(result) );
-            wine_server_add_data( req, obj_handles, count * sizeof(*obj_handles) );
+            wine_server_add_data( req, &select_op, offsetof( select_op_t, wait.handles[count] ));
             ret = wine_server_call( req );
             abs_timeout = reply->timeout;
             apc_handle  = reply->apc_handle;
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 98835b2..590bd81 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -404,6 +404,22 @@ struct token_groups
 
 };
 
+enum select_op
+{
+    SELECT_NONE,
+    SELECT_WAIT
+};
+
+typedef union
+{
+    enum select_op op;
+    struct
+    {
+        enum select_op  op;
+        obj_handle_t    handles[MAXIMUM_WAIT_OBJECTS];
+    } wait;
+} select_op_t;
+
 enum apc_type
 {
     APC_NONE,
@@ -1056,7 +1072,7 @@ struct select_request
     obj_handle_t prev_apc;
     timeout_t    timeout;
     /* VARARG(result,apc_result); */
-    /* VARARG(handles,handles); */
+    /* VARARG(data,select_op); */
 };
 struct select_reply
 {
@@ -5771,6 +5787,6 @@ union generic_reply
     struct set_suspend_context_reply set_suspend_context_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 443
+#define SERVER_PROTOCOL_VERSION 444
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 6748e5d..4601942 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -420,6 +420,22 @@ struct token_groups
     /* VARARG(sids,SID); */
 };
 
+enum select_op
+{
+    SELECT_NONE,
+    SELECT_WAIT
+};
+
+typedef union
+{
+    enum select_op op;
+    struct
+    {
+        enum select_op  op;      /* SELECT_WAIT */
+        obj_handle_t    handles[MAXIMUM_WAIT_OBJECTS];
+    } wait;
+} select_op_t;
+
 enum apc_type
 {
     APC_NONE,
@@ -924,7 +940,7 @@ struct rawinput_device
     obj_handle_t prev_apc;     /* handle to previous APC */
     timeout_t    timeout;      /* timeout */
     VARARG(result,apc_result); /* result of previous APC */
-    VARARG(handles,handles);   /* handles to select on */
+    VARARG(data,select_op);    /* operation-specific data */
 @REPLY
     timeout_t    timeout;      /* timeout converted to absolute */
     apc_call_t   call;         /* APC call arguments */
diff --git a/server/thread.c b/server/thread.c
index 5f9738d..c6eeaf9 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -710,23 +710,39 @@ static int signal_object( obj_handle_t handle )
 }
 
 /* select on a list of handles */
-static timeout_t select_on( unsigned int count, client_ptr_t cookie, const obj_handle_t *handles,
+static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, client_ptr_t cookie,
                             int flags, timeout_t timeout, obj_handle_t signal_obj )
 {
     int ret;
-    unsigned int i;
+    unsigned int i, count;
     struct object *objects[MAXIMUM_WAIT_OBJECTS];
 
     if (timeout <= 0) timeout = current_time - timeout;
 
-    if (count > MAXIMUM_WAIT_OBJECTS)
+    switch (select_op->op)
     {
+    case SELECT_NONE:
+        count = 0;
+        break;
+
+    case SELECT_WAIT:
+        count = (op_size - offsetof( select_op_t, wait.handles )) / sizeof(select_op->wait.handles[0]);
+        if (op_size < offsetof( select_op_t, wait.handles ) || count > MAXIMUM_WAIT_OBJECTS)
+        {
+            set_error( STATUS_INVALID_PARAMETER );
+            return 0;
+        }
+        break;
+
+    default:
         set_error( STATUS_INVALID_PARAMETER );
         return 0;
     }
+
     for (i = 0; i < count; i++)
     {
-        if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL )))
+        if (!(objects[i] = get_handle_obj( current->process, select_op->wait.handles[i],
+                                           SYNCHRONIZE, NULL )))
             break;
     }
 
@@ -1310,17 +1326,19 @@ DECL_HANDLER(resume_thread)
 /* select on a handle list */
 DECL_HANDLER(select)
 {
+    select_op_t select_op;
+    data_size_t op_size;
     struct thread_apc *apc;
-    unsigned int count;
     const apc_result_t *result = get_req_data();
-    const obj_handle_t *handles = (const obj_handle_t *)(result + 1);
 
     if (get_req_data_size() < sizeof(*result))
     {
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
-    count = (get_req_data_size() - sizeof(*result)) / sizeof(obj_handle_t);
+    op_size = min( get_req_data_size() - sizeof(*result), sizeof(select_op) );
+    memset( &select_op, 0, sizeof(select_op) );
+    memcpy( &select_op, result + 1, op_size );
 
     /* first store results of previous apc */
     if (req->prev_apc)
@@ -1348,7 +1366,7 @@ DECL_HANDLER(select)
         release_object( apc );
     }
 
-    reply->timeout = select_on( count, req->cookie, handles, req->flags, req->timeout, req->signal );
+    reply->timeout = select_on( &select_op, op_size, req->cookie, req->flags, req->timeout, req->signal );
 
     if (get_error() == STATUS_USER_APC)
     {
diff --git a/server/trace.c b/server/trace.c
index 7740545..c9af74f 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -66,6 +66,19 @@ static void dump_uints( const int *ptr, int len )
     fputc( '}', stderr );
 }
 
+static void dump_handles( const char *prefix, const obj_handle_t *data, data_size_t size )
+{
+    data_size_t len = size / sizeof(*data);
+
+    fprintf( stderr,"%s{", prefix );
+    while (len > 0)
+    {
+        fprintf( stderr, "%04x", *data++ );
+        if (--len) fputc( ',', stderr );
+    }
+    fputc( '}', stderr );
+}
+
 static void dump_timeout( const char *prefix, const timeout_t *time )
 {
     fprintf( stderr, "%s%s", prefix, get_timeout_str(*time) );
@@ -367,16 +380,33 @@ static void dump_varargs_apc_result( const char *prefix, data_size_t size )
     remove_data( size );
 }
 
-static void dump_varargs_handles( const char *prefix, data_size_t size )
+static void dump_varargs_select_op( const char *prefix, data_size_t size )
 {
-    const obj_handle_t *data = cur_data;
-    data_size_t len = size / sizeof(*data);
+    select_op_t data;
 
-    fprintf( stderr,"%s{", prefix );
-    while (len > 0)
+    if (!size)
     {
-        fprintf( stderr, "%04x", *data++ );
-        if (--len) fputc( ',', stderr );
+        fprintf( stderr, "%s{}", prefix );
+        return;
+    }
+    memset( &data, 0, sizeof(data) );
+    memcpy( &data, cur_data, min( size, sizeof(data) ));
+
+    fprintf( stderr, "%s{", prefix );
+    switch (data.op)
+    {
+    case SELECT_NONE:
+        fprintf( stderr, "NONE" );
+        break;
+    case SELECT_WAIT:
+        fprintf( stderr, "WAIT" );
+        if (size > offsetof( select_op_t, wait.handles ))
+            dump_handles( ",handles=", data.wait.handles,
+                          min( size, sizeof(data.wait) ) - offsetof( select_op_t, wait.handles ));
+        break;
+    default:
+        fprintf( stderr, "op=%u", data.op );
+        break;
     }
     fputc( '}', stderr );
     remove_data( size );
@@ -1361,7 +1391,7 @@ static void dump_select_request( const struct select_request *req )
     fprintf( stderr, ", prev_apc=%04x", req->prev_apc );
     dump_timeout( ", timeout=", &req->timeout );
     dump_varargs_apc_result( ", result=", cur_size );
-    dump_varargs_handles( ", handles=", cur_size );
+    dump_varargs_select_op( ", data=", cur_size );
 }
 
 static void dump_select_reply( const struct select_reply *req )




More information about the wine-cvs mailing list