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",