server: Moved some common bits of get/set_thread_context to thread.c.
diff --git a/server/context_alpha.c b/server/context_alpha.c
index 05506f8..f4d8693 100644
--- a/server/context_alpha.c
+++ b/server/context_alpha.c
@@ -239,8 +239,9 @@
 }
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
+void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
 {
+    flags &= ~CONTEXT_ALPHA;  /* get rid of CPU id */
     if (flags & CONTEXT_CONTROL)
     {
         to->IntRa = from->IntRa;
@@ -327,17 +328,23 @@
     return (void *)context->Fir;
 }
 
+/* return the context flag that contains the CPU id */
+unsigned int get_context_cpu_flag(void)
+{
+    return CONTEXT_ALPHA;
+}
+
+/* return only the context flags that correspond to system regs */
+/* (system regs are the ones we can't access on the client side) */
+unsigned int get_context_system_regs( unsigned int flags )
+{
+    return flags & ~CONTEXT_ALPHA;
+}
+
 /* retrieve the thread context */
 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
-    context->ContextFlags |= CONTEXT_ALPHA;
-    flags &= ~CONTEXT_ALPHA;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( context, thread->context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         get_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
@@ -347,13 +354,7 @@
 /* set the thread context */
 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    flags &= ~CONTEXT_ALPHA;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( thread->context, context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         set_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
diff --git a/server/context_i386.c b/server/context_i386.c
index 35c30ae..82faf8b 100644
--- a/server/context_i386.c
+++ b/server/context_i386.c
@@ -89,81 +89,111 @@
     return 0;
 }
 
-/* retrieve the thread x86 debug registers */
-static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
+/* retrieve the thread x86 registers */
+void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
     int pid = get_ptrace_pid(thread);
 
+    /* all other regs are handled on the client side */
+    assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
+
+    if (!suspend_for_ptrace( thread )) return;
+
     if (get_debug_reg( pid, 0, &context->Dr0 ) == -1) goto error;
     if (get_debug_reg( pid, 1, &context->Dr1 ) == -1) goto error;
     if (get_debug_reg( pid, 2, &context->Dr2 ) == -1) goto error;
     if (get_debug_reg( pid, 3, &context->Dr3 ) == -1) goto error;
     if (get_debug_reg( pid, 6, &context->Dr6 ) == -1) goto error;
     if (get_debug_reg( pid, 7, &context->Dr7 ) == -1) goto error;
-    return 1;
+    context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+    resume_after_ptrace( thread );
+    return;
  error:
     file_set_error();
-    return 0;
+    resume_after_ptrace( thread );
 }
 
-/* set the thread x86 debug registers */
-static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
+/* set the thread x86 registers */
+void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    int pid = get_ptrace_pid(thread);
+    int pid = get_ptrace_pid( thread );
+
+    /* all other regs are handled on the client side */
+    assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
+
+    if (!suspend_for_ptrace( thread )) return;
 
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(0), context->Dr0 ) == -1) goto error;
+    if (thread->context) thread->context->Dr0 = context->Dr0;
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(1), context->Dr1 ) == -1) goto error;
+    if (thread->context) thread->context->Dr1 = context->Dr1;
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(2), context->Dr2 ) == -1) goto error;
+    if (thread->context) thread->context->Dr2 = context->Dr2;
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(3), context->Dr3 ) == -1) goto error;
+    if (thread->context) thread->context->Dr3 = context->Dr3;
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(6), context->Dr6 ) == -1) goto error;
+    if (thread->context) thread->context->Dr6 = context->Dr6;
     if (ptrace( PTRACE_POKEUSER, pid, DR_OFFSET(7), context->Dr7 ) == -1) goto error;
-    return 1;
+    if (thread->context) thread->context->Dr7 = context->Dr7;
+    resume_after_ptrace( thread );
+    return;
  error:
     file_set_error();
-    return 0;
+    resume_after_ptrace( thread );
 }
 
 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__)
 #include <machine/reg.h>
 
-/* retrieve the thread x86 debug registers */
-static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
+/* retrieve the thread x86 registers */
+void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
 #ifdef PTRACE_GETDBREGS
     int pid = get_ptrace_pid(thread);
-
     struct dbreg dbregs;
-    if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1)
-        goto error;
+
+    /* all other regs are handled on the client side */
+    assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
+
+    if (!suspend_for_ptrace( thread )) return;
+
+    if (ptrace( PTRACE_GETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
+    else
+    {
 #ifdef DBREG_DRX
-    /* needed for FreeBSD, the structure fields have changed under 5.x */
-    context->Dr0 = DBREG_DRX((&dbregs), 0);
-    context->Dr1 = DBREG_DRX((&dbregs), 1);
-    context->Dr2 = DBREG_DRX((&dbregs), 2);
-    context->Dr3 = DBREG_DRX((&dbregs), 3);
-    context->Dr6 = DBREG_DRX((&dbregs), 6);
-    context->Dr7 = DBREG_DRX((&dbregs), 7);
+        /* needed for FreeBSD, the structure fields have changed under 5.x */
+        context->Dr0 = DBREG_DRX((&dbregs), 0);
+        context->Dr1 = DBREG_DRX((&dbregs), 1);
+        context->Dr2 = DBREG_DRX((&dbregs), 2);
+        context->Dr3 = DBREG_DRX((&dbregs), 3);
+        context->Dr6 = DBREG_DRX((&dbregs), 6);
+        context->Dr7 = DBREG_DRX((&dbregs), 7);
 #else
-    context->Dr0 = dbregs.dr0;
-    context->Dr1 = dbregs.dr1;
-    context->Dr2 = dbregs.dr2;
-    context->Dr3 = dbregs.dr3;
-    context->Dr6 = dbregs.dr6;
-    context->Dr7 = dbregs.dr7;
+        context->Dr0 = dbregs.dr0;
+        context->Dr1 = dbregs.dr1;
+        context->Dr2 = dbregs.dr2;
+        context->Dr3 = dbregs.dr3;
+        context->Dr6 = dbregs.dr6;
+        context->Dr7 = dbregs.dr7;
 #endif
-    return 1;
- error:
-    file_set_error();
+        context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
+    }
+    resume_after_ptrace( thread );
 #endif
-    return 0;
 }
 
-/* set the thread x86 debug registers */
-static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
+/* set the thread x86 registers */
+void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
 #ifdef PTRACE_SETDBREGS
     int pid = get_ptrace_pid(thread);
     struct dbreg dbregs;
+
+    /* all other regs are handled on the client side */
+    assert( (flags | CONTEXT_i386) == CONTEXT_DEBUG_REGISTERS );
+
+    if (!suspend_for_ptrace( thread )) return;
+
 #ifdef DBREG_DRX
     /* needed for FreeBSD, the structure fields have changed under 5.x */
     DBREG_DRX((&dbregs), 0) = context->Dr0;
@@ -184,32 +214,39 @@
     dbregs.dr6 = context->Dr6;
     dbregs.dr7 = context->Dr7;
 #endif
-    if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) != -1) return 1;
-    file_set_error();
+    if (ptrace( PTRACE_SETDBREGS, pid, (caddr_t) &dbregs, 0 ) == -1) file_set_error();
+    else if (thread->context)  /* update the cached values */
+    {
+        thread->context->Dr0 = context->Dr0;
+        thread->context->Dr1 = context->Dr1;
+        thread->context->Dr2 = context->Dr2;
+        thread->context->Dr3 = context->Dr3;
+        thread->context->Dr6 = context->Dr6;
+        thread->context->Dr7 = context->Dr7;
+    }
+    resume_after_ptrace( thread );
 #endif
-    return 0;
 }
 
 #else  /* linux || __FreeBSD__ */
 
-/* retrieve the thread x86 debug registers */
-static int get_thread_debug_regs( struct thread *thread, CONTEXT *context )
+/* retrieve the thread x86 registers */
+void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
-    return 0;
 }
 
 /* set the thread x86 debug registers */
-static int set_thread_debug_regs( struct thread *thread, const CONTEXT *context )
+void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    return 0;
 }
 
 #endif  /* linux || __FreeBSD__ */
 
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
+void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
 {
+    flags &= ~CONTEXT_i386;  /* get rid of CPU id */
     if (flags & CONTEXT_CONTROL)
     {
         to->Ebp    = from->Ebp;
@@ -257,34 +294,17 @@
     return (void *)context->Eip;
 }
 
-/* retrieve the thread context */
-void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
+/* return the context flag that contains the CPU id */
+unsigned int get_context_cpu_flag(void)
 {
-    context->ContextFlags |= CONTEXT_i386;
-    flags &= ~CONTEXT_i386;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-        copy_context( context, thread->context, flags & ~CONTEXT_DEBUG_REGISTERS );
-
-    if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread ))
-    {
-        if (get_thread_debug_regs( thread, context )) context->ContextFlags |= CONTEXT_DEBUG_REGISTERS;
-        resume_after_ptrace( thread );
-    }
+    return CONTEXT_i386;
 }
 
-/* set the thread context */
-void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
+/* return only the context flags that correspond to system regs */
+/* (system regs are the ones we can't access on the client side) */
+unsigned int get_context_system_regs( unsigned int flags )
 {
-    flags &= ~CONTEXT_i386;  /* get rid of CPU id */
-
-    if ((flags & CONTEXT_DEBUG_REGISTERS) && suspend_for_ptrace( thread ))
-    {
-        if (!set_thread_debug_regs( thread, context )) flags &= ~CONTEXT_DEBUG_REGISTERS;
-        resume_after_ptrace( thread );
-    }
-
-    if (thread->context) copy_context( thread->context, context, flags );
+    return flags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386);
 }
 
 #endif  /* __i386__ */
diff --git a/server/context_powerpc.c b/server/context_powerpc.c
index 1ee63a7..b984a58 100644
--- a/server/context_powerpc.c
+++ b/server/context_powerpc.c
@@ -201,7 +201,7 @@
 #define FREG(x) to->Fpr##x = from->Fpr##x;
 #define CREG(x) to->x = from->x;
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
+void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
 {
     if (flags & CONTEXT_CONTROL)
     {
@@ -266,14 +266,23 @@
     return (void *)context->Iar;
 }
 
+/* return the context flag that contains the CPU id */
+unsigned int get_context_cpu_flag(void)
+{
+    return 0;
+}
+
+/* return only the context flags that correspond to system regs */
+/* (system regs are the ones we can't access on the client side) */
+unsigned int get_context_system_regs( unsigned int flags )
+{
+    return flags;
+}
+
 /* retrieve the thread context */
 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( context, thread->context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         get_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
@@ -283,11 +292,7 @@
 /* set the thread context */
 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( thread->context, context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         set_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
diff --git a/server/context_sparc.c b/server/context_sparc.c
index ccc8419..ce6b9cc 100644
--- a/server/context_sparc.c
+++ b/server/context_sparc.c
@@ -106,8 +106,9 @@
 
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
+void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
 {
+    flags &= ~CONTEXT_SPARC;  /* get rid of CPU id */
     if (flags & CONTEXT_CONTROL)
     {
         to->psr    = from->psr;
@@ -165,17 +166,23 @@
     return (void *)context->pc;
 }
 
+/* return the context flag that contains the CPU id */
+unsigned int get_context_cpu_flag(void)
+{
+    return CONTEXT_SPARC;
+}
+
+/* return only the context flags that correspond to system regs */
+/* (system regs are the ones we can't access on the client side) */
+unsigned int get_context_system_regs( unsigned int flags )
+{
+    return flags & ~CONTEXT_SPARC;
+}
+
 /* retrieve the thread context */
 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
-    context->ContextFlags |= CONTEXT_SPARC;
-    flags &= ~CONTEXT_SPARC;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( context, thread->context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         get_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
@@ -185,13 +192,7 @@
 /* set the thread context */
 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    flags &= ~CONTEXT_SPARC;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( thread->context, context, flags );
-    }
-    else if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         set_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
diff --git a/server/context_x86_64.c b/server/context_x86_64.c
index f2200ae..2f742b2 100644
--- a/server/context_x86_64.c
+++ b/server/context_x86_64.c
@@ -203,8 +203,9 @@
 
 
 /* copy a context structure according to the flags */
-static void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
+void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags )
 {
+    flags &= ~CONTEXT_AMD64;  /* get rid of CPU id */
     if (flags & CONTEXT_CONTROL)
     {
         to->Rbp    = from->Rbp;
@@ -254,19 +255,23 @@
     return (void *)context->Rip;
 }
 
+/* return the context flag that contains the CPU id */
+unsigned int get_context_cpu_flag(void)
+{
+    return CONTEXT_AMD64;
+}
+
+/* return only the context flags that correspond to system regs */
+/* (system regs are the ones we can't access on the client side) */
+unsigned int get_context_system_regs( unsigned int flags )
+{
+    return flags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_AMD64);
+}
+
 /* retrieve the thread context */
 void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags )
 {
-    context->ContextFlags |= CONTEXT_AMD64;
-    flags &= ~CONTEXT_AMD64;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( context, thread->context, flags );
-        flags &= CONTEXT_DEBUG_REGISTERS;
-    }
-
-    if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         get_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
@@ -276,15 +281,7 @@
 /* set the thread context */
 void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags )
 {
-    flags &= ~CONTEXT_AMD64;  /* get rid of CPU id */
-
-    if (thread->context)  /* thread is inside an exception event or suspended */
-    {
-        copy_context( thread->context, context, flags );
-        flags &= CONTEXT_DEBUG_REGISTERS;
-    }
-
-    if (flags && suspend_for_ptrace( thread ))
+    if (suspend_for_ptrace( thread ))
     {
         set_thread_context_ptrace( thread, flags, context );
         resume_after_ptrace( thread );
diff --git a/server/thread.c b/server/thread.c
index e2c8807..7e4ba3b 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1043,7 +1043,7 @@
 DECL_HANDLER(get_thread_context)
 {
     struct thread *thread;
-    void *data;
+    CONTEXT *context;
 
     if (get_reply_max_size() < sizeof(CONTEXT))
     {
@@ -1072,10 +1072,14 @@
         if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
         else set_error( STATUS_PENDING );
     }
-    else if ((data = set_reply_data_size( sizeof(CONTEXT) )))
+    else if ((context = set_reply_data_size( sizeof(CONTEXT) )))
     {
-        memset( data, 0, sizeof(CONTEXT) );
-        get_thread_context( thread, data, req->flags );
+        unsigned int flags = get_context_system_regs( req->flags );
+
+        memset( context, 0, sizeof(CONTEXT) );
+        context->ContextFlags = get_context_cpu_flag();
+        if (thread->context) copy_context( context, thread->context, req->flags & ~flags );
+        if (flags) get_thread_context( thread, context, flags );
     }
     reply->self = (thread == current);
     release_object( thread );
@@ -1115,7 +1119,12 @@
     }
     else
     {
-        set_thread_context( thread, get_req_data(), req->flags );
+        const CONTEXT *context = get_req_data();
+        unsigned int flags = get_context_system_regs( req->flags );
+
+        if (flags) set_thread_context( thread, context, flags );
+        if (thread->context && !get_error())
+            copy_context( thread->context, context, req->flags & ~flags );
     }
     reply->self = (thread == current);
     release_object( thread );
diff --git a/server/thread.h b/server/thread.h
index ace5be3..0a40565 100644
--- a/server/thread.h
+++ b/server/thread.h
@@ -119,13 +119,18 @@
 extern struct thread_snapshot *thread_snap( int *count );
 extern struct token *thread_get_impersonation_token( struct thread *thread );
 
+/* CPU context functions */
+extern void copy_context( CONTEXT *to, const CONTEXT *from, unsigned int flags );
+extern void *get_context_ip( const CONTEXT *context );
+extern unsigned int get_context_cpu_flag(void);
+extern unsigned int get_context_system_regs( unsigned int flags );
+
 /* ptrace functions */
 
 extern void sigchld_callback(void);
 extern int get_ptrace_pid( struct thread *thread );
 extern int suspend_for_ptrace( struct thread *thread );
 extern void resume_after_ptrace( struct thread *thread );
-extern void *get_context_ip( const CONTEXT *context );
 extern void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int flags );
 extern void set_thread_context( struct thread *thread, const CONTEXT *context, unsigned int flags );
 extern int send_thread_signal( struct thread *thread, int sig );