- 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
This commit is contained in:
Alex Ionescu 2005-08-09 05:54:57 +00:00
parent 2d51263ec6
commit 4c12530bbc
2 changed files with 42 additions and 35 deletions

View file

@ -14,10 +14,8 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
#ifndef MUTANT_INCREMENT /* FIXME: NDK */
#define MUTANT_INCREMENT 1 #define MAXIMUM_SUSPEND_COUNT 0x7F
#endif
#define THREAD_ALERT_INCREMENT 2 #define THREAD_ALERT_INCREMENT 2
extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue]; extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];
@ -599,6 +597,14 @@ KeSuspendThread(PKTHREAD Thread)
/* Save the Old Count */ /* Save the Old Count */
PreviousCount = Thread->SuspendCount; PreviousCount = Thread->SuspendCount;
/* Handle the maximum */
if (PreviousCount == MAXIMUM_SUSPEND_COUNT)
{
/* Raise an exception */
KeReleaseDispatcherDatabaseLock(OldIrql);
ExRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);
}
/* Increment it */ /* Increment it */
Thread->SuspendCount++; Thread->SuspendCount++;

View file

@ -115,25 +115,22 @@ NtSuspendThread(IN HANDLE ThreadHandle,
{ {
PETHREAD Thread; PETHREAD Thread;
ULONG Prev; ULONG Prev;
KPROCESSOR_MODE PreviousMode; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE(); PAGED_CODE();
PreviousMode = ExGetPreviousMode();
/* Check buffer validity */ /* Check buffer validity */
if(PreviousSuspendCount && PreviousMode == UserMode) { if(PreviousSuspendCount && PreviousMode != KernelMode)
{
_SEH_TRY { _SEH_TRY
{
ProbeForWrite(PreviousSuspendCount, ProbeForWrite(PreviousSuspendCount,
sizeof(ULONG), sizeof(ULONG),
sizeof(ULONG)); sizeof(ULONG));
} _SEH_HANDLE { }
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} _SEH_END; } _SEH_END;
if(!NT_SUCCESS(Status)) return Status; if(!NT_SUCCESS(Status)) return Status;
@ -146,30 +143,34 @@ NtSuspendThread(IN HANDLE ThreadHandle,
PreviousMode, PreviousMode,
(PVOID*)&Thread, (PVOID*)&Thread,
NULL); 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 */ /* Don't fail if we merely couldn't write the handle back */
Prev = KeSuspendThread(&Thread->Tcb); if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS;
} _SEH_END;
/* Return it */ /* Return */
if(PreviousSuspendCount) { ObDereferenceObject(Thread);
_SEH_TRY {
*PreviousSuspendCount = Prev;
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
} _SEH_END;
}
/* Dereference and Return */
ObDereferenceObject((PVOID)Thread);
return Status; return Status;
} }