{
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;
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);
-
- /* Return it */
- if(PreviousSuspendCount) {
-
- _SEH_TRY {
-
- *PreviousSuspendCount = Prev;
-
- } _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;
- } _SEH_END;
- }
-
- /* Dereference and Return */
- ObDereferenceObject((PVOID)Thread);
+ /* Return */
+ ObDereferenceObject(Thread);
return Status;
}