From 4c12530bbc232b6e814e0ed641a73eceb71b6dba Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 9 Aug 2005 05:54:57 +0000 Subject: [PATCH] - 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. svn path=/trunk/; revision=17230 --- reactos/ntoskrnl/ke/kthread.c | 14 +++++--- reactos/ntoskrnl/ps/suspend.c | 63 ++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index e082f32afc7..64a9d70560b 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -14,10 +14,8 @@ #define NDEBUG #include -#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 @@ KeSuspendThread(PKTHREAD Thread) /* 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++; diff --git a/reactos/ntoskrnl/ps/suspend.c b/reactos/ntoskrnl/ps/suspend.c index 3b50812ef3b..98e3a90abda 100644 --- a/reactos/ntoskrnl/ps/suspend.c +++ b/reactos/ntoskrnl/ps/suspend.c @@ -115,25 +115,22 @@ NtSuspendThread(IN HANDLE ThreadHandle, { 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 @@ NtSuspendThread(IN HANDLE ThreadHandle, 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); + + /* Return the Previous Count */ + if (PreviousSuspendCount) *PreviousSuspendCount = Prev; } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); - /* Call the Kernel Function */ - Prev = KeSuspendThread(&Thread->Tcb); + /* Don't fail if we merely couldn't write the handle back */ + if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS; + } _SEH_END; - /* Return it */ - if(PreviousSuspendCount) { - - _SEH_TRY { - - *PreviousSuspendCount = Prev; - - } _SEH_HANDLE { - - Status = _SEH_GetExceptionCode(); - - } _SEH_END; - } - - /* Dereference and Return */ - ObDereferenceObject((PVOID)Thread); + /* Return */ + ObDereferenceObject(Thread); return Status; }