- Fix NtSuspendThread: correct PreviousMode check, return error if thread is terminating, handle KeSuspendThread's possible exception, only attempt to return previous suspend count if asked to.
- Make KeSuspendThread return an exception if the thread has been suspended beyond the limit.

This fixes another wine test.
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
Modified: trunk/reactos/ntoskrnl/ps/suspend.c

Modified: trunk/reactos/ntoskrnl/ke/kthread.c
--- trunk/reactos/ntoskrnl/ke/kthread.c	2005-08-09 04:59:19 UTC (rev 17229)
+++ trunk/reactos/ntoskrnl/ke/kthread.c	2005-08-09 05:54:57 UTC (rev 17230)
@@ -14,10 +14,8 @@
 #define NDEBUG
 #include <internal/debug.h>
 
-#ifndef MUTANT_INCREMENT
-#define MUTANT_INCREMENT                1
-#endif
-
+/* FIXME: NDK */
+#define MAXIMUM_SUSPEND_COUNT 0x7F
 #define THREAD_ALERT_INCREMENT 2
 
 extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
@@ -599,6 +597,14 @@
     /* Save the Old Count */
     PreviousCount = Thread->SuspendCount;
 
+    /* Handle the maximum */
+    if (PreviousCount == MAXIMUM_SUSPEND_COUNT)
+    {
+        /* Raise an exception */
+        KeReleaseDispatcherDatabaseLock(OldIrql);
+        ExRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
+    }
+
     /* Increment it */
     Thread->SuspendCount++;
 

Modified: trunk/reactos/ntoskrnl/ps/suspend.c
--- trunk/reactos/ntoskrnl/ps/suspend.c	2005-08-09 04:59:19 UTC (rev 17229)
+++ trunk/reactos/ntoskrnl/ps/suspend.c	2005-08-09 05:54:57 UTC (rev 17230)
@@ -115,25 +115,22 @@
 {
     PETHREAD Thread;
     ULONG Prev;
-    KPROCESSOR_MODE PreviousMode;
+    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status = STATUS_SUCCESS;
-
     PAGED_CODE();
 
-    PreviousMode = ExGetPreviousMode();
-
     /* Check buffer validity */
-    if(PreviousSuspendCount && PreviousMode == UserMode) {
-
-        _SEH_TRY {
-
+    if(PreviousSuspendCount && PreviousMode != KernelMode)
+    {
+        _SEH_TRY
+        {
             ProbeForWrite(PreviousSuspendCount,
                           sizeof(ULONG),
                           sizeof(ULONG));
-         } _SEH_HANDLE {
-
+         }
+        _SEH_HANDLE
+        {
             Status = _SEH_GetExceptionCode();
-
         } _SEH_END;
 
         if(!NT_SUCCESS(Status)) return Status;
@@ -146,30 +143,34 @@
                                        PreviousMode,
                                        (PVOID*)&Thread,
                                        NULL);
-    if (!NT_SUCCESS(Status)) {
+    if (!NT_SUCCESS(Status)) return Status;
 
-        return Status;
-    }
+    /* Guard with SEH because KeSuspendThread can raise an exception */
+    _SEH_TRY
+    {
+        /* Make sure the thread isn't terminating */
+        if ((Thread != PsGetCurrentThread()) && (Thread->Terminated))
+        {
+            ObDereferenceObject(Thread);
+            return STATUS_THREAD_IS_TERMINATING;
+        }
 
-    /* Call the Kernel Function */
-    Prev = KeSuspendThread(&Thread->Tcb);
+        /* Call the Kernel function */
+        Prev = KeSuspendThread(&Thread->Tcb);
 
-    /* Return it */
-    if(PreviousSuspendCount) {
+        /* Return the Previous Count */
+        if (PreviousSuspendCount) *PreviousSuspendCount = Prev;
+    }
+    _SEH_HANDLE
+    {
+        Status = _SEH_GetExceptionCode();
 
-        _SEH_TRY {
+        /* Don't fail if we merely couldn't write the handle back */
+        if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS;
+    } _SEH_END;
 
-            *PreviousSuspendCount = Prev;
-
-        } _SEH_HANDLE {
-
-            Status = _SEH_GetExceptionCode();
-
-        } _SEH_END;
-    }
-
-    /* Dereference and Return */
-    ObDereferenceObject((PVOID)Thread);
+    /* Return */
+    ObDereferenceObject(Thread);
     return Status;
 }