server: Added mechanism for returning results of APC calls.

Defined APC_VIRTUAL_ALLOC and APC_VIRTUAL_FREE requests.
This commit is contained in:
Alexandre Julliard 2007-01-15 22:24:40 +01:00
parent 46d7fa4852
commit fb40dc4099
7 changed files with 196 additions and 5 deletions

View File

@ -662,14 +662,18 @@ static BOOL call_apcs( BOOL alertable )
BOOL user_apc = FALSE;
NTSTATUS ret;
apc_call_t call;
apc_result_t result;
HANDLE handle = 0;
memset( &result, 0, sizeof(result) );
for (;;)
{
SERVER_START_REQ( get_apc )
{
req->alertable = alertable;
req->prev = handle;
req->result = result;
if (!(ret = wine_server_call( req )))
{
handle = reply->handle;
@ -680,6 +684,8 @@ static BOOL call_apcs( BOOL alertable )
if (ret) return user_apc; /* no more APCs */
memset( &result, 0, sizeof(result) );
switch (call.type)
{
case APC_USER:

View File

@ -209,7 +209,15 @@ struct token_groups
};
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
enum apc_type
{
APC_NONE,
APC_USER,
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE
};
typedef union
{
@ -235,8 +243,43 @@ typedef union
void *sb;
unsigned int status;
} async_io;
struct
{
enum apc_type type;
void *addr;
unsigned long size;
unsigned int zero_bits;
unsigned int op_type;
unsigned int prot;
} virtual_alloc;
struct
{
enum apc_type type;
void *addr;
unsigned long size;
unsigned int op_type;
} virtual_free;
} apc_call_t;
typedef union
{
enum apc_type type;
struct
{
enum apc_type type;
unsigned int status;
void *addr;
unsigned long size;
} virtual_alloc;
struct
{
enum apc_type type;
unsigned int status;
void *addr;
unsigned long size;
} virtual_free;
} apc_result_t;
@ -554,6 +597,7 @@ struct get_apc_request
struct request_header __header;
int alertable;
obj_handle_t prev;
apc_result_t result;
};
struct get_apc_reply
{
@ -564,6 +608,19 @@ struct get_apc_reply
struct get_apc_result_request
{
struct request_header __header;
obj_handle_t handle;
};
struct get_apc_result_reply
{
struct reply_header __header;
apc_result_t result;
};
struct close_handle_request
{
struct request_header __header;
@ -3803,6 +3860,7 @@ enum request
REQ_unload_dll,
REQ_queue_apc,
REQ_get_apc,
REQ_get_apc_result,
REQ_close_handle,
REQ_set_handle_info,
REQ_dup_handle,
@ -4023,6 +4081,7 @@ union generic_request
struct unload_dll_request unload_dll_request;
struct queue_apc_request queue_apc_request;
struct get_apc_request get_apc_request;
struct get_apc_result_request get_apc_result_request;
struct close_handle_request close_handle_request;
struct set_handle_info_request set_handle_info_request;
struct dup_handle_request dup_handle_request;
@ -4241,6 +4300,7 @@ union generic_reply
struct unload_dll_reply unload_dll_reply;
struct queue_apc_reply queue_apc_reply;
struct get_apc_reply get_apc_reply;
struct get_apc_result_reply get_apc_result_reply;
struct close_handle_reply close_handle_reply;
struct set_handle_info_reply set_handle_info_reply;
struct dup_handle_reply dup_handle_reply;
@ -4437,6 +4497,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
#define SERVER_PROTOCOL_VERSION 264
#define SERVER_PROTOCOL_VERSION 265
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -225,7 +225,15 @@ struct token_groups
/* VARARGS(sids,SID); */
};
enum apc_type { APC_NONE, APC_USER, APC_TIMER, APC_ASYNC_IO };
enum apc_type
{
APC_NONE,
APC_USER,
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE
};
typedef union
{
@ -251,8 +259,43 @@ typedef union
void *sb; /* status block */
unsigned int status; /* I/O status */
} async_io;
struct
{
enum apc_type type; /* APC_VIRTUAL_ALLOC */
void *addr; /* requested address */
unsigned long size; /* allocation size */
unsigned int zero_bits; /* allocation alignment */
unsigned int op_type; /* type of operation */
unsigned int prot; /* memory protection flags */
} virtual_alloc;
struct
{
enum apc_type type; /* APC_VIRTUAL_FREE */
void *addr; /* requested address */
unsigned long size; /* allocation size */
unsigned int op_type; /* type of operation */
} virtual_free;
} apc_call_t;
typedef union
{
enum apc_type type;
struct
{
enum apc_type type; /* APC_VIRTUAL_ALLOC */
unsigned int status; /* status returned by call */
void *addr; /* resulting address */
unsigned long size; /* resulting size */
} virtual_alloc;
struct
{
enum apc_type type; /* APC_VIRTUAL_FREE */
unsigned int status; /* status returned by call */
void *addr; /* resulting address */
unsigned long size; /* resulting size */
} virtual_free;
} apc_result_t;
/****************************************************************/
/* Request declarations */
@ -472,12 +515,21 @@ typedef union
@REQ(get_apc)
int alertable; /* is thread alertable? */
obj_handle_t prev; /* handle to previous APC */
apc_result_t result; /* result of previous APC */
@REPLY
obj_handle_t handle; /* handle to APC */
apc_call_t call; /* call arguments */
@END
/* Get the result of an APC call */
@REQ(get_apc_result)
obj_handle_t handle; /* handle to the APC */
@REPLY
apc_result_t result; /* result of the APC */
@END
/* Close a handle for the current process */
@REQ(close_handle)
obj_handle_t handle; /* handle to close */

View File

@ -129,6 +129,7 @@ DECL_HANDLER(load_dll);
DECL_HANDLER(unload_dll);
DECL_HANDLER(queue_apc);
DECL_HANDLER(get_apc);
DECL_HANDLER(get_apc_result);
DECL_HANDLER(close_handle);
DECL_HANDLER(set_handle_info);
DECL_HANDLER(dup_handle);
@ -348,6 +349,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_unload_dll,
(req_handler)req_queue_apc,
(req_handler)req_get_apc,
(req_handler)req_get_apc_result,
(req_handler)req_close_handle,
(req_handler)req_set_handle_info,
(req_handler)req_dup_handle,

View File

@ -72,7 +72,8 @@ struct thread_apc
struct list entry; /* queue linked list */
struct object *owner; /* object that queued this apc */
int executed; /* has it been executed by the client? */
apc_call_t call;
apc_call_t call; /* call arguments */
apc_result_t result; /* call results once executed */
};
static void dump_thread_apc( struct object *obj, int verbose );
@ -1105,6 +1106,7 @@ DECL_HANDLER(get_apc)
{
if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->prev,
0, &thread_apc_ops ))) return;
apc->result = req->result;
apc->executed = 1;
wake_up( &apc->obj, 0 );
close_handle( current->process, req->prev );
@ -1135,6 +1137,23 @@ DECL_HANDLER(get_apc)
release_object( apc );
}
/* Get the result of an APC call */
DECL_HANDLER(get_apc_result)
{
struct thread_apc *apc;
if (!(apc = (struct thread_apc *)get_handle_obj( current->process, req->handle,
0, &thread_apc_ops ))) return;
if (!apc->executed) set_error( STATUS_PENDING );
else
{
reply->result = apc->result;
/* close the handle directly to avoid an extra round-trip */
close_handle( current->process, req->handle );
}
release_object( apc );
}
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{

View File

@ -119,6 +119,17 @@ static void dump_apc_call( const apc_call_t *call )
fprintf( stderr, "APC_ASYNC_IO,user=%p,sb=%p,status=%s",
call->async_io.user, call->async_io.sb, get_status_name(call->async_io.status) );
break;
case APC_VIRTUAL_ALLOC:
fprintf( stderr, "APC_VIRTUAL_ALLOC,addr=%p,size=%lu,zero_bits=%u,op_type=%x,prot=%x",
call->virtual_alloc.addr, call->virtual_alloc.size,
call->virtual_alloc.zero_bits, call->virtual_alloc.op_type,
call->virtual_alloc.prot );
break;
case APC_VIRTUAL_FREE:
fprintf( stderr, "APC_VIRTUAL_FREE,addr=%p,size=%lu,op_type=%x",
call->virtual_free.addr, call->virtual_free.size,
call->virtual_free.op_type );
break;
default:
fprintf( stderr, "type=%u", call->type );
break;
@ -126,6 +137,30 @@ static void dump_apc_call( const apc_call_t *call )
fputc( '}', stderr );
}
static void dump_apc_result( const apc_result_t *result )
{
fputc( '{', stderr );
switch(result->type)
{
case APC_NONE:
break;
case APC_VIRTUAL_ALLOC:
fprintf( stderr, "APC_VIRTUAL_ALLOC,status=%s,addr=%p,size=%lu",
get_status_name( result->virtual_alloc.status ),
result->virtual_alloc.addr, result->virtual_alloc.size );
break;
case APC_VIRTUAL_FREE:
fprintf( stderr, "APC_VIRTUAL_FREE,status=%s,addr=%p,size=%lu",
get_status_name( result->virtual_free.status ),
result->virtual_free.addr, result->virtual_free.size );
break;
default:
fprintf( stderr, "type=%u", result->type );
break;
}
fputc( '}', stderr );
}
static void dump_context( const CONTEXT *context )
{
#ifdef __i386__
@ -882,7 +917,9 @@ static void dump_queue_apc_request( const struct queue_apc_request *req )
static void dump_get_apc_request( const struct get_apc_request *req )
{
fprintf( stderr, " alertable=%d,", req->alertable );
fprintf( stderr, " prev=%p", req->prev );
fprintf( stderr, " prev=%p,", req->prev );
fprintf( stderr, " result=" );
dump_apc_result( &req->result );
}
static void dump_get_apc_reply( const struct get_apc_reply *req )
@ -892,6 +929,17 @@ static void dump_get_apc_reply( const struct get_apc_reply *req )
dump_apc_call( &req->call );
}
static void dump_get_apc_result_request( const struct get_apc_result_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_get_apc_result_reply( const struct get_apc_result_reply *req )
{
fprintf( stderr, " result=" );
dump_apc_result( &req->result );
}
static void dump_close_handle_request( const struct close_handle_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
@ -3310,6 +3358,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_unload_dll_request,
(dump_func)dump_queue_apc_request,
(dump_func)dump_get_apc_request,
(dump_func)dump_get_apc_result_request,
(dump_func)dump_close_handle_request,
(dump_func)dump_set_handle_info_request,
(dump_func)dump_dup_handle_request,
@ -3526,6 +3575,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)0,
(dump_func)dump_get_apc_reply,
(dump_func)dump_get_apc_result_reply,
(dump_func)0,
(dump_func)dump_set_handle_info_reply,
(dump_func)dump_dup_handle_reply,
@ -3742,6 +3792,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"unload_dll",
"queue_apc",
"get_apc",
"get_apc_result",
"close_handle",
"set_handle_info",
"dup_handle",

View File

@ -43,6 +43,7 @@ my %formats =
"rectangle_t" => "&dump_rectangle",
"char_info_t" => "&dump_char_info",
"apc_call_t" => "&dump_apc_call",
"apc_result_t" => "&dump_apc_result",
);
my @requests = ();