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