From 45d60558d0ccc4e60c13dbf88201162c7397c63f Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 12 Sep 2013 09:02:48 +0000 Subject: [PATCH] [NTOSKRNL]: Implement ThreadIsTermination info class in NtQueryInformationThread. [CSRSRV]: CsrInsertThread should call this API to make sure the thread isn't dead already. Update the callers to handle this possible failure. This behavior was obeserved in Windows' CSRSRV.DLL. It now works in ReactOS as well. svn path=/trunk/; revision=60059 --- reactos/ntoskrnl/ps/query.c | 26 +++++++++++++++++ reactos/subsystems/win32/csrsrv/api.h | 6 +++- reactos/subsystems/win32/csrsrv/procsup.c | 10 ++++++- reactos/subsystems/win32/csrsrv/session.c | 10 ++++++- reactos/subsystems/win32/csrsrv/thredsup.c | 33 ++++++++++++++++++++-- 5 files changed, 79 insertions(+), 6 deletions(-) diff --git a/reactos/ntoskrnl/ps/query.c b/reactos/ntoskrnl/ps/query.c index b5ac9dabb86..87d2fda3e90 100644 --- a/reactos/ntoskrnl/ps/query.c +++ b/reactos/ntoskrnl/ps/query.c @@ -2412,6 +2412,7 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, (PTHREAD_BASIC_INFORMATION)ThreadInformation; PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation; KIRQL OldIrql; + ULONG ThreadTerminated; PAGED_CODE(); /* Check if we were called from user mode */ @@ -2661,6 +2662,31 @@ NtQueryInformationThread(IN HANDLE ThreadHandle, _SEH2_END; break; + case ThreadIsTerminated: + + /* Set the return length*/ + Length = sizeof(ThreadTerminated); + + if (ThreadInformationLength != Length) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + + ThreadTerminated = PsIsThreadTerminating(Thread); + + _SEH2_TRY + { + *(PULONG)ThreadInformation = ThreadTerminated ? 1 : 0; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + break; + /* Anything else */ default: diff --git a/reactos/subsystems/win32/csrsrv/api.h b/reactos/subsystems/win32/csrsrv/api.h index e03cc89089f..6bf294475ff 100644 --- a/reactos/subsystems/win32/csrsrv/api.h +++ b/reactos/subsystems/win32/csrsrv/api.h @@ -137,11 +137,15 @@ BOOLEAN NTAPI UnProtectHandle(IN HANDLE ObjectHandle); -VOID +NTSTATUS NTAPI CsrInsertThread(IN PCSR_PROCESS Process, IN PCSR_THREAD Thread); +VOID +NTAPI +CsrDeallocateThread(IN PCSR_THREAD CsrThread); + VOID NTAPI CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess); diff --git a/reactos/subsystems/win32/csrsrv/procsup.c b/reactos/subsystems/win32/csrsrv/procsup.c index 2dc5c116598..def775e8025 100644 --- a/reactos/subsystems/win32/csrsrv/procsup.c +++ b/reactos/subsystems/win32/csrsrv/procsup.c @@ -690,7 +690,15 @@ CsrCreateProcess(IN HANDLE hProcess, CsrThread->Flags = 0; /* Insert the Thread into the Process */ - CsrInsertThread(CsrProcess, CsrThread); + Status = CsrInsertThread(CsrProcess, CsrThread); + if (!NT_SUCCESS(Status)) + { + /* Bail out */ + CsrDeallocateProcess(CsrProcess); + CsrDeallocateThread(CsrThread); + CsrReleaseProcessLock(); + return Status; + } /* Reference the session */ CsrReferenceNtSession(NtSession); diff --git a/reactos/subsystems/win32/csrsrv/session.c b/reactos/subsystems/win32/csrsrv/session.c index 79702903a62..f2d1ccde9ec 100644 --- a/reactos/subsystems/win32/csrsrv/session.c +++ b/reactos/subsystems/win32/csrsrv/session.c @@ -289,7 +289,15 @@ CsrSbCreateSession(IN PSB_API_MSG ApiMessage) CsrThread->Flags = 0; /* Insert it into the Process List */ - CsrInsertThread(CsrProcess, CsrThread); + Status = CsrInsertThread(CsrProcess, CsrThread); + if (!NT_SUCCESS(Status)) + { + /* Bail out */ + CsrDeallocateProcess(CsrProcess); + CsrDeallocateThread(CsrThread); + CsrReleaseProcessLock(); + return Status; + } /* Setup Process Data */ CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId; diff --git a/reactos/subsystems/win32/csrsrv/thredsup.c b/reactos/subsystems/win32/csrsrv/thredsup.c index 26b5bb12b86..b4063c6b7aa 100644 --- a/reactos/subsystems/win32/csrsrv/thredsup.c +++ b/reactos/subsystems/win32/csrsrv/thredsup.c @@ -292,14 +292,25 @@ CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, * @remarks None. * *--*/ -VOID +NTSTATUS NTAPI CsrInsertThread(IN PCSR_PROCESS Process, IN PCSR_THREAD Thread) { ULONG i; + NTSTATUS Status; + ULONG ThreadInfo; // ASSERT(ProcessStructureListLocked()); + /* Make sure the thread isn't already dead by the time we got this */ + Status = NtQueryInformationThread(Thread->ThreadHandle, + ThreadIsTerminated, + &ThreadInfo, + sizeof(ThreadInfo), + NULL); + if (!NT_SUCCESS(Status)) return Status; + if (ThreadInfo == TRUE) return STATUS_THREAD_IS_TERMINATING; + /* Insert it into the Regular List */ InsertTailList(&Process->ThreadList, &Thread->Link); @@ -311,6 +322,7 @@ CsrInsertThread(IN PCSR_PROCESS Process, /* Insert it there too */ InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks); + return STATUS_SUCCESS; } /*++ @@ -623,7 +635,15 @@ CsrCreateRemoteThread(IN HANDLE hThread, CsrThread->Flags = 0; /* Insert the Thread into the Process */ - CsrInsertThread(CsrProcess, CsrThread); + Status = CsrInsertThread(CsrProcess, CsrThread); + if (!NT_SUCCESS(Status)) + { + /* Bail out */ + if (CsrThread->ThreadHandle != hThread) NtClose(CsrThread->ThreadHandle); + CsrUnlockProcess(CsrProcess); + CsrDeallocateThread(CsrThread); + return Status; + } /* Release the lock and return */ CsrUnlockProcess(CsrProcess); @@ -720,7 +740,14 @@ CsrCreateThread(IN PCSR_PROCESS CsrProcess, CsrThread->Flags = 0; /* Insert the Thread into the Process */ - CsrInsertThread(CsrProcess, CsrThread); + Status = CsrInsertThread(CsrProcess, CsrThread); + if (!NT_SUCCESS(Status)) + { + /* Bail out */ + CsrUnlockProcess(CsrProcess); + CsrDeallocateThread(CsrThread); + return Status; + } /* Release the lock and return */ CsrReleaseProcessLock();