Updated support for Solaris/Sparc architecture.

diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c
index 8fd61fd..d64b5c0 100644
--- a/dlls/ntdll/signal_sparc.c
+++ b/dlls/ntdll/signal_sparc.c
@@ -12,6 +12,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #include <sys/ucontext.h>
 
@@ -348,4 +349,20 @@
     return FALSE;
 }
 
+/**********************************************************************
+ *              DbgBreakPoint   (NTDLL)
+ */
+void WINAPI DbgBreakPoint(void)
+{
+    /* FIXME */
+}
+
+/**********************************************************************
+ *              DbgUserBreakPoint   (NTDLL)
+ */
+void WINAPI DbgUserBreakPoint(void)
+{
+    /* FIXME */
+}
+
 #endif  /* __sparc__ */
diff --git a/memory/selector.c b/memory/selector.c
index 0f0b99f..c12b620 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -663,7 +663,7 @@
     if (!(req->flags & LDT_FLAGS_READONLY)) ldtent->HighWord.Bits.Type |= 0x2;
     return TRUE;
 #else
-    SetLastError( ERROR_NOT_IMPLEMENTED );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
     return FALSE;
 #endif
 }
diff --git a/scheduler/critsection.c b/scheduler/critsection.c
index 4437d0e..a68be29 100644
--- a/scheduler/critsection.c
+++ b/scheduler/critsection.c
@@ -222,6 +222,80 @@
                   "decl %eax\n\t"
                   "ret $4");
 
-#else /* __i386__ */
+#elif defined(__sparc__) && defined(__sun__)
+
+/*
+ * As the earlier Sparc processors lack necessary atomic instructions,
+ * I'm simply falling back to the library-provided _lwp_mutex routines
+ * to ensure mutual exclusion in a way appropriate for the current 
+ * architecture.  
+ *
+ * FIXME:  If we have the compare-and-swap instruction (Sparc v9 and above)
+ *         we could use this to speed up the Interlocked operations ...
+ */
+
+#include <synch.h>
+static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX;
+
+PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
+{
+    _lwp_mutex_lock( &interlocked_mutex );
+
+    if ( *dest == compare )
+        *dest = xchg;
+    else
+        compare = *dest;
+    
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return compare;
+}
+
+LONG WINAPI InterlockedExchange( PLONG dest, LONG val )
+{
+    LONG retv;
+    _lwp_mutex_lock( &interlocked_mutex );
+
+    retv = *dest;
+    *dest = val;
+
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return retv;
+}
+
+LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr )
+{
+    LONG retv;
+    _lwp_mutex_lock( &interlocked_mutex );
+
+    retv = *dest;
+    *dest += incr;
+
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return retv;
+}
+
+LONG WINAPI InterlockedIncrement( PLONG dest )
+{
+    LONG retv;
+    _lwp_mutex_lock( &interlocked_mutex );
+
+    retv = ++*dest;
+
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return retv;
+}
+
+LONG WINAPI InterlockedDecrement( PLONG dest )
+{
+    LONG retv;
+    _lwp_mutex_lock( &interlocked_mutex );
+
+    retv = --*dest;
+
+    _lwp_mutex_unlock( &interlocked_mutex );
+    return retv;
+}
+
+#else
 #error You must implement the Interlocked* functions for your CPU
-#endif /* __i386__ */
+#endif
diff --git a/server/Makefile.in b/server/Makefile.in
index 2416736..05c18d8 100644
--- a/server/Makefile.in
+++ b/server/Makefile.in
@@ -10,6 +10,7 @@
 	change.c \
 	console.c \
 	context_i386.c \
+	context_sparc.c \
 	debugger.c \
 	device.c \
 	event.c \
diff --git a/server/context_sparc.c b/server/context_sparc.c
new file mode 100644
index 0000000..2335120
--- /dev/null
+++ b/server/context_sparc.c
@@ -0,0 +1,201 @@
+/*
+ * Sparc register context support
+ *
+ * Copyright (C) 2000 Ulrich Weigand
+ */
+
+#include "config.h"
+
+#ifdef __sparc__
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_REG_H
+#include <sys/reg.h>
+#endif
+#include <unistd.h>
+#include <sys/ptrace.h>
+#include <sys/user.h>
+
+#include "winbase.h"
+
+#include "thread.h"
+#include "request.h"
+
+
+#if defined(__sun) || defined(__sun__)
+
+/* retrieve a thread context */
+static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+{
+    int pid = thread->unix_pid;
+    if (flags & CONTEXT_FULL)
+    {
+        struct regs regs;
+        if (ptrace( PTRACE_GETREGS, pid, 0, (int) &regs ) == -1) goto error;
+        if (flags & CONTEXT_INTEGER)
+        {
+            context->g0 = 0;
+            context->g1 = regs.r_g1;
+            context->g2 = regs.r_g2;
+            context->g3 = regs.r_g3;
+            context->g4 = regs.r_g4;
+            context->g5 = regs.r_g5;
+            context->g6 = regs.r_g6;
+            context->g7 = regs.r_g7;
+
+            context->o0 = regs.r_o0;
+            context->o1 = regs.r_o1;
+            context->o2 = regs.r_o2;
+            context->o3 = regs.r_o3;
+            context->o4 = regs.r_o4;
+            context->o5 = regs.r_o5;
+            context->o6 = regs.r_o6;
+            context->o7 = regs.r_o7;
+
+            /* FIXME: local and in registers */
+        }
+        if (flags & CONTEXT_CONTROL)
+        {
+            context->psr = regs.r_psr;
+            context->pc  = regs.r_pc;
+            context->npc = regs.r_npc;
+            context->y   = regs.r_y;
+            context->wim = 0;  /* FIXME */
+            context->tbr = 0;  /* FIXME */
+        }
+    }
+    if (flags & CONTEXT_FLOATING_POINT)
+    {
+        /* FIXME */
+    }
+    return;
+ error:
+    file_set_error();
+}
+
+
+/* set a thread context */
+static void set_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
+{
+    /* FIXME */
+}
+
+#else  /* __sun__ */
+#error You must implement get/set_thread_context for your platform
+#endif  /* __sun__ */
+
+
+/* copy a context structure according to the flags */
+static void copy_context( CONTEXT *to, CONTEXT *from, int flags )
+{
+    if (flags & CONTEXT_CONTROL)
+    {
+        to->psr    = from->psr;
+        to->pc     = from->pc;
+        to->npc    = from->npc;
+        to->y      = from->y;
+        to->wim    = from->wim;
+        to->tbr    = from->tbr;
+    }
+    if (flags & CONTEXT_INTEGER)
+    {
+        to->g0 = from->g0;
+        to->g1 = from->g1;
+        to->g2 = from->g2;
+        to->g3 = from->g3;
+        to->g4 = from->g4;
+        to->g5 = from->g5;
+        to->g6 = from->g6;
+        to->g7 = from->g7;
+        to->o0 = from->o0;
+        to->o1 = from->o1;
+        to->o2 = from->o2;
+        to->o3 = from->o3;
+        to->o4 = from->o4;
+        to->o5 = from->o5;
+        to->o6 = from->o6;
+        to->o7 = from->o7;
+        to->l0 = from->l0;
+        to->l1 = from->l1;
+        to->l2 = from->l2;
+        to->l3 = from->l3;
+        to->l4 = from->l4;
+        to->l5 = from->l5;
+        to->l6 = from->l6;
+        to->l7 = from->l7;
+        to->i0 = from->i0;
+        to->i1 = from->i1;
+        to->i2 = from->i2;
+        to->i3 = from->i3;
+        to->i4 = from->i4;
+        to->i5 = from->i5;
+        to->i6 = from->i6;
+        to->i7 = from->i7;
+    }
+    if (flags & CONTEXT_FLOATING_POINT)
+    {
+        /* FIXME */
+    }
+}
+
+/* retrieve the current instruction pointer of a thread */
+void *get_thread_ip( struct thread *thread )
+{
+    CONTEXT context;
+    context.pc = 0;
+    if (suspend_for_ptrace( thread ))
+    {
+        get_thread_context( thread, CONTEXT_CONTROL, &context );
+        resume_thread( thread );
+    }
+    return (void *)context.pc;
+}
+
+/* retrieve the current context of a thread */
+DECL_HANDLER(get_thread_context)
+{
+    struct thread *thread;
+    int flags = req->flags & ~CONTEXT_SPARC;  /* get rid of CPU id */
+
+    if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT )))
+    {
+        if (thread->context)  /* thread is inside an exception event */
+        {
+            copy_context( &req->context, thread->context, flags );
+            flags = 0;
+        }
+        if (flags && suspend_for_ptrace( thread ))
+        {
+            get_thread_context( thread, flags, &req->context );
+            resume_thread( thread );
+        }
+        release_object( thread );
+    }
+}
+
+
+/* set the current context of a thread */
+DECL_HANDLER(set_thread_context)
+{
+    struct thread *thread;
+    int flags = req->flags & ~CONTEXT_SPARC;  /* get rid of CPU id */
+
+    if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
+    {
+        if (thread->context)  /* thread is inside an exception event */
+        {
+            copy_context( thread->context, &req->context, flags );
+            flags = 0;
+        }
+        if (flags && suspend_for_ptrace( thread ))
+        {
+            set_thread_context( thread, flags, &req->context );
+            resume_thread( thread );
+        }
+        release_object( thread );
+    }
+}
+
+#endif  /* __sparc__ */