- 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;
}
Show replies by date