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

This commit is contained in:
Alexandre Julliard 2013-08-22 10:34:11 +02:00
parent e69670f76b
commit c2ab7a625e
5 changed files with 103 additions and 22 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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)
{

View File

@ -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 )