From 5da6c3508fc98abebcbd547179dfae754e9031b4 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 20 Jul 2006 18:29:54 +0000 Subject: [PATCH] - Refactor NtSuspend/ResumeThread into PsSuspend/ResumeThread. - Implement NtSuspend/ResumeProcess with PsSuspend/ResumeProcess. - Improve the previous code to use rundown protection and be thread-safe. svn path=/trunk/; revision=23198 --- reactos/ntoskrnl/ps/state.c | 190 ++++++++++++++++++++++++++++++------ 1 file changed, 160 insertions(+), 30 deletions(-) diff --git a/reactos/ntoskrnl/ps/state.c b/reactos/ntoskrnl/ps/state.c index 5aae747c307..9739fec7593 100644 --- a/reactos/ntoskrnl/ps/state.c +++ b/reactos/ntoskrnl/ps/state.c @@ -13,7 +13,153 @@ #define NDEBUG #include -/* FUNCTIONS *****************************************************************/ +/* PRIVATE FUNCTIONS *********************************************************/ + +NTSTATUS +NTAPI +PsResumeThread(IN PETHREAD Thread, + OUT PULONG PreviousCount OPTIONAL) +{ + ULONG OldCount; + PAGED_CODE(); + + /* Resume the thread */ + OldCount = KeResumeThread(&Thread->Tcb); + + /* Return the count if asked */ + if (PreviousCount) *PreviousCount = OldCount; + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +PsSuspendThread(IN PETHREAD Thread, + OUT PULONG PreviousCount OPTIONAL) +{ + NTSTATUS Status = STATUS_SUCCESS; + ULONG OldCount = 0; + PAGED_CODE(); + + /* Guard with SEH because KeSuspendThread can raise an exception */ + _SEH_TRY + { + /* Check if we're suspending ourselves */ + if (Thread == PsGetCurrentThread()) + { + /* Do the suspend */ + OldCount = KeSuspendThread(&Thread->Tcb); + } + else + { + /* Acquire rundown */ + if (ExAcquireRundownProtection(&Thread->RundownProtect)) + { + /* Make sure the thread isn't terminating */ + if (Thread->Terminated) + { + /* Fail */ + Status = STATUS_THREAD_IS_TERMINATING; + } + else + { + /* Otherwise, do the suspend */ + OldCount = KeSuspendThread(&Thread->Tcb); + + /* Check if it terminated during the suspend */ + if (Thread->Terminated) + { + /* Wake it back up and fail */ + KeForceResumeThread(&Thread->Tcb); + Status = STATUS_THREAD_IS_TERMINATING; + OldCount = 0; + } + } + + /* Release rundown protection */ + ExReleaseRundownProtection(&Thread->RundownProtect); + } + else + { + /* Thread is terminating */ + Status = STATUS_THREAD_IS_TERMINATING; + } + } + } + _SEH_HANDLE + { + 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; + + /* Write back the previous count */ + if (PreviousCount) *PreviousCount = OldCount; + return Status; +} + +NTSTATUS +NTAPI +PsResumeProcess(IN PEPROCESS Process) +{ + PETHREAD Thread; + PAGED_CODE(); + + /* Lock the Process */ + if (!ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Process is terminating */ + return STATUS_PROCESS_IS_TERMINATING; + } + + /* Get the first thread */ + Thread = PsGetNextProcessThread(Process, NULL); + while (Thread) + { + /* Resume it */ + KeResumeThread(&Thread->Tcb); + + /* Move to the next thread */ + Thread = PsGetNextProcessThread(Process, Thread); + } + + /* Unlock the process */ + ExReleaseRundownProtection(&Process->RundownProtect); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +PsSuspendProcess(IN PEPROCESS Process) +{ + PETHREAD Thread; + PAGED_CODE(); + + /* Lock the Process */ + if (!ExAcquireRundownProtection(&Process->RundownProtect)) + { + /* Process is terminating */ + return STATUS_PROCESS_IS_TERMINATING; + } + + /* Get the first thread */ + Thread = PsGetNextProcessThread(Process, NULL); + while (Thread) + { + /* Resume it */ + PsSuspendThread(Thread, NULL); + + /* Move to the next thread */ + Thread = PsGetNextProcessThread(Process, Thread); + } + + /* Unlock the process */ + ExReleaseRundownProtection(&Process->RundownProtect); + return STATUS_SUCCESS; +} + +/* PUBLIC FUNCTIONS **********************************************************/ /* * @implemented @@ -76,8 +222,6 @@ NtAlertResumeThread(IN HANDLE ThreadHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Fail on exception */ if (!NT_SUCCESS(Status)) return Status; } @@ -144,8 +288,6 @@ NtResumeThread(IN HANDLE ThreadHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Fail on exception */ if(!NT_SUCCESS(Status)) return Status; } @@ -158,8 +300,8 @@ NtResumeThread(IN HANDLE ThreadHandle, NULL); if (!NT_SUCCESS(Status)) return Status; - /* Call the Kernel Function */ - Prev = KeResumeThread(&Thread->Tcb); + /* Call the internal function */ + Status = PsResumeThread(Thread, &Prev); /* Check if the caller wanted the count back */ if (SuspendCount) @@ -209,8 +351,6 @@ NtSuspendThread(IN HANDLE ThreadHandle, Status = _SEH_GetExceptionCode(); } _SEH_END; - - /* Fail on exception */ if(!NT_SUCCESS(Status)) return Status; } @@ -223,33 +363,25 @@ NtSuspendThread(IN HANDLE ThreadHandle, NULL); if (!NT_SUCCESS(Status)) return Status; - /* Guard with SEH because KeSuspendThread can raise an exception */ + /* Call the internal function */ + Status = PsSuspendThread(Thread, &Prev); + ObDereferenceObject(Thread); + if (!NT_SUCCESS(Status)) return Status; + + /* Protect write with SEH */ _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 { + /* Get the exception code */ 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; /* Return */ - ObDereferenceObject(Thread); return Status; } @@ -271,9 +403,8 @@ NtSuspendProcess(IN HANDLE ProcessHandle) NULL); if (NT_SUCCESS(Status)) { - /* FIXME */ - Status = STATUS_NOT_IMPLEMENTED; - DPRINT1("NtSuspendProcess not yet implemented!\n"); + /* Call the internal function */ + Status = PsSuspendProcess(Process); ObDereferenceObject(Process); } @@ -299,9 +430,8 @@ NtResumeProcess(IN HANDLE ProcessHandle) NULL); if (NT_SUCCESS(Status)) { - /* FIXME */ - Status = STATUS_NOT_IMPLEMENTED; - DPRINT1("NtResumeProcess not yet implemented!\n"); + /* Call the internal function */ + Status = PsResumeProcess(Process); ObDereferenceObject(Process); }