server: Added mechanism for returning results of APC calls.
Defined APC_VIRTUAL_ALLOC and APC_VIRTUAL_FREE requests.
diff --git a/server/protocol.def b/server/protocol.def
index 3f7fbd5..7b5d0fd 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -225,7 +225,15 @@
/* 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 @@
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 @@
@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 */
diff --git a/server/request.h b/server/request.h
index 8cfeccd..5a7dcfc 100644
--- a/server/request.h
+++ b/server/request.h
@@ -129,6 +129,7 @@
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 @@
(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,
diff --git a/server/thread.c b/server/thread.c
index 13563c3..133953b 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -72,7 +72,8 @@
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 @@
{
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 @@
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)
{
diff --git a/server/trace.c b/server/trace.c
index 5defbda..2724e7d 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -119,6 +119,17 @@
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 @@
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_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 @@
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 @@
(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 @@
(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 @@
"unload_dll",
"queue_apc",
"get_apc",
+ "get_apc_result",
"close_handle",
"set_handle_info",
"dup_handle",