- 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
#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 @@ 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++;

View file

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