mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 21:04:26 +00:00
- 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:
parent
2d51263ec6
commit
4c12530bbc
|
@ -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++;
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
/* Call the Kernel function */
|
||||||
Prev = KeSuspendThread(&Thread->Tcb);
|
Prev = KeSuspendThread(&Thread->Tcb);
|
||||||
|
|
||||||
/* Return it */
|
/* Return the Previous Count */
|
||||||
if(PreviousSuspendCount) {
|
if (PreviousSuspendCount) *PreviousSuspendCount = Prev;
|
||||||
|
}
|
||||||
_SEH_TRY {
|
_SEH_HANDLE
|
||||||
|
{
|
||||||
*PreviousSuspendCount = Prev;
|
|
||||||
|
|
||||||
} _SEH_HANDLE {
|
|
||||||
|
|
||||||
Status = _SEH_GetExceptionCode();
|
Status = _SEH_GetExceptionCode();
|
||||||
|
|
||||||
|
/* Don't fail if we merely couldn't write the handle back */
|
||||||
|
if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS;
|
||||||
} _SEH_END;
|
} _SEH_END;
|
||||||
}
|
|
||||||
|
|
||||||
/* Dereference and Return */
|
/* Return */
|
||||||
ObDereferenceObject((PVOID)Thread);
|
ObDereferenceObject(Thread);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue