- 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; }