+++ /dev/null
-/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS Client/Server Runtime SubSystem
- * FILE: subsystems/win32/csrsrv/thredsup.c
- * PURPOSE: CSR Server DLL Thread Management
- * PROGRAMMERS: ReactOS Portable Systems Group
- * Alex Ionescu (alex@relsoft.net)
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <srv.h>
-
-#define NDEBUG
-#include <debug.h>
-
-#define CsrHashThread(t) (HandleToUlong(t) % NUMBER_THREAD_HASH_BUCKETS)
-
-/* GLOBALS ********************************************************************/
-
-LIST_ENTRY CsrThreadHashTable[NUMBER_THREAD_HASH_BUCKETS];
-
-
-/* PRIVATE FUNCTIONS **********************************************************/
-
-/*++
- * @name ProtectHandle
- * @implemented NT5.2
- *
- * The ProtectHandle routine protects an object handle against closure.
- *
- * @return TRUE or FALSE.
- *
- * @remarks None.
- *
- *--*/
-BOOLEAN
-NTAPI
-ProtectHandle(IN HANDLE ObjectHandle)
-{
- NTSTATUS Status;
- OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
-
- /* Query current state */
- Status = NtQueryObject(ObjectHandle,
- ObjectHandleFlagInformation,
- &HandleInfo,
- sizeof(HandleInfo),
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* Enable protect from close */
- HandleInfo.ProtectFromClose = TRUE;
- Status = NtSetInformationObject(ObjectHandle,
- ObjectHandleFlagInformation,
- &HandleInfo,
- sizeof(HandleInfo));
- if (NT_SUCCESS(Status)) return TRUE;
- }
-
- /* We failed to or set the state */
- return FALSE;
-}
-
-/*++
- * @name UnProtectHandle
- * @implemented NT5.2
- *
- * The UnProtectHandle routine unprotects an object handle against closure.
- *
- * @return TRUE or FALSE.
- *
- * @remarks None.
- *
- *--*/
-BOOLEAN
-NTAPI
-UnProtectHandle(IN HANDLE ObjectHandle)
-{
- NTSTATUS Status;
- OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
-
- /* Query current state */
- Status = NtQueryObject(ObjectHandle,
- ObjectHandleFlagInformation,
- &HandleInfo,
- sizeof(HandleInfo),
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* Disable protect from close */
- HandleInfo.ProtectFromClose = FALSE;
- Status = NtSetInformationObject(ObjectHandle,
- ObjectHandleFlagInformation,
- &HandleInfo,
- sizeof(HandleInfo));
- if (NT_SUCCESS(Status)) return TRUE;
- }
-
- /* We failed to or set the state */
- return FALSE;
-}
-
-/*++
- * @name CsrAllocateThread
- *
- * The CsrAllocateThread routine allocates a new CSR Thread object.
- *
- * @param CsrProcess
- * Pointer to the CSR Process which will contain this CSR Thread.
- *
- * @return Pointer to the newly allocated CSR Thread.
- *
- * @remarks None.
- *
- *--*/
-PCSR_THREAD
-NTAPI
-CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
-{
- PCSR_THREAD CsrThread;
-
- /* Allocate the structure */
- CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
- if (!CsrThread) return NULL;
-
- /* Reference the Thread and Process */
- CsrLockedReferenceThread(CsrThread);
- CsrLockedReferenceProcess(CsrProcess);
-
- /* Set the Parent Process */
- CsrThread->Process = CsrProcess;
-
- /* Return Thread */
- return CsrThread;
-}
-
-/*++
- * @name CsrLockedReferenceThread
- *
- * The CsrLockedReferenceThread references a CSR Thread while the
- * Process Lock is already being held.
- *
- * @param CsrThread
- * Pointer to the CSR Thread to be referenced.
- *
- * @return None.
- *
- * @remarks This routine will return with the Process Lock held.
- *
- *--*/
-VOID
-NTAPI
-CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
-{
- /* Increment the reference count */
- ++CsrThread->ReferenceCount;
-}
-
-/*++
- * @name CsrLocateThreadByClientId
- *
- * The CsrLocateThreadByClientId routine locates the CSR Thread and,
- * optionally, its parent CSR Process, corresponding to a Client ID.
- *
- * @param Process
- * Optional pointer to a CSR Process pointer which will contain
- * the CSR Thread's parent.
- *
- * @param ClientId
- * Pointer to a Client ID structure containing the Unique Thread ID
- * to look up.
- *
- * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
- * none was found.
- *
- * @remarks None.
- *
- *--*/
-PCSR_THREAD
-NTAPI
-CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL,
- IN PCLIENT_ID ClientId)
-{
- ULONG i;
- PLIST_ENTRY ListHead, NextEntry;
- PCSR_THREAD FoundThread;
- // ASSERT(ProcessStructureListLocked());
-
- if (Process) *Process = NULL;
-
- /* Hash the Thread */
- i = CsrHashThread(ClientId->UniqueThread);
-
- /* Set the list pointers */
- ListHead = &CsrThreadHashTable[i];
- NextEntry = ListHead->Flink;
-
- /* Star the loop */
- while (NextEntry != ListHead)
- {
- /* Get the thread */
- FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
-
- /* Move to the next entry */
- NextEntry = NextEntry->Flink;
-
- /* Compare the CID */
- // if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
- if ( FoundThread->ClientId.UniqueProcess == ClientId->UniqueProcess &&
- FoundThread->ClientId.UniqueThread == ClientId->UniqueThread )
- {
- /* Match found, return the process */
- if (Process) *Process = FoundThread->Process;
-
- /* Return thread too */
- return FoundThread;
- }
- }
-
- /* Nothing found */
- return NULL;
-}
-
-/*++
- * @name CsrLocateThreadInProcess
- *
- * The CsrLocateThreadInProcess routine locates the CSR Thread
- * corresponding to a Client ID inside a specific CSR Process.
- *
- * @param Process
- * Optional pointer to the CSR Process which contains the CSR Thread
- * that will be looked up.
- *
- * @param ClientId
- * Pointer to a Client ID structure containing the Unique Thread ID
- * to look up.
- *
- * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
- * none was found.
- *
- * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
- * CsrRootProcess.
- *
- *--*/
-PCSR_THREAD
-NTAPI
-CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL,
- IN PCLIENT_ID Cid)
-{
- PLIST_ENTRY ListHead, NextEntry;
- PCSR_THREAD FoundThread = NULL;
-
- /* Use the Root Process if none was specified */
- if (!CsrProcess) CsrProcess = CsrRootProcess;
-
- /* Save the List pointers */
- ListHead = &CsrProcess->ThreadList;
- NextEntry = ListHead->Flink;
-
- /* Start the Loop */
- while (NextEntry != ListHead)
- {
- /* Get Thread Entry */
- FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
-
- /* Check for TID Match */
- if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
-
- /* Move to the next entry */
- NextEntry = NextEntry->Flink;
- }
-
- /* Return what we found */
- return FoundThread;
-}
-
-/*++
- * @name CsrInsertThread
- *
- * The CsrInsertThread routine inserts a CSR Thread into its parent's
- * Thread List and into the Thread Hash Table.
- *
- * @param Process
- * Pointer to the CSR Process containing this CSR Thread.
- *
- * @param Thread
- * Pointer to the CSR Thread to be inserted.
- *
- * @return None.
- *
- * @remarks None.
- *
- *--*/
-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) return STATUS_THREAD_IS_TERMINATING;
-
- /* Insert it into the Regular List */
- InsertTailList(&Process->ThreadList, &Thread->Link);
-
- /* Increase Thread Count */
- Process->ThreadCount++;
-
- /* Hash the Thread */
- i = CsrHashThread(Thread->ClientId.UniqueThread);
-
- /* Insert it there too */
- InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
- return STATUS_SUCCESS;
-}
-
-/*++
- * @name CsrDeallocateThread
- *
- * The CsrDeallocateThread frees the memory associated with a CSR Thread.
- *
- * @param CsrThread
- * Pointer to the CSR Thread to be freed.
- *
- * @return None.
- *
- * @remarks Do not call this routine. It is reserved for the internal
- * thread management routines when a CSR Thread has been cleanly
- * dereferenced and killed.
- *
- *--*/
-VOID
-NTAPI
-CsrDeallocateThread(IN PCSR_THREAD CsrThread)
-{
- /* Free the process object from the heap */
- // ASSERT(CsrThread->WaitBlock == NULL);
- RtlFreeHeap(CsrHeap, 0, CsrThread);
-}
-
-/*++
- * @name CsrRemoveThread
- *
- * The CsrRemoveThread function undoes a CsrInsertThread operation and
- * removes the CSR Thread from the the Hash Table and Thread List.
- *
- * @param CsrThread
- * Pointer to the CSR Thread to remove.
- *
- * @return None.
- *
- * @remarks If this CSR Thread is the last one inside a CSR Process, the
- * parent will be dereferenced and the CsrProcessLastThreadTerminated
- * flag will be set.
- *
- * After executing this routine, the CSR Thread will have the
- * CsrThreadInTermination flag set.
- *
- *--*/
-VOID
-NTAPI
-CsrRemoveThread(IN PCSR_THREAD CsrThread)
-{
- ASSERT(ProcessStructureListLocked());
-
- /* Remove it from the List */
- RemoveEntryList(&CsrThread->Link);
-
- /* Decreate the thread count of the process */
- CsrThread->Process->ThreadCount--;
-
- /* Remove it from the Hash List as well */
- if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
-
- /* Check if this is the last Thread */
- if (CsrThread->Process->ThreadCount == 0)
- {
- /* Check if it's not already been marked for deletion */
- if ((CsrThread->Process->Flags & CsrProcessLastThreadTerminated) == 0)
- {
- /* Let everyone know this process is about to lose the thread */
- CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
-
- /* Reference the Process */
- CsrLockedDereferenceProcess(CsrThread->Process);
- }
- }
-
- /* Mark the thread for deletion */
- CsrThread->Flags |= CsrThreadInTermination;
-}
-
-/*++
- * @name CsrThreadRefcountZero
- *
- * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
- * all its active references. It removes and de-allocates the CSR Thread.
- *
- * @param CsrThread
- * Pointer to the CSR Thread that is to be deleted.
- *
- * @return None.
- *
- * @remarks Do not call this routine. It is reserved for the internal
- * thread management routines when a CSR Thread has lost all
- * its references.
- *
- * This routine is called with the Process Lock held.
- *
- *--*/
-VOID
-NTAPI
-CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
-{
- PCSR_PROCESS CsrProcess = CsrThread->Process;
- NTSTATUS Status;
- ASSERT(ProcessStructureListLocked());
-
- /* Remove this thread */
- CsrRemoveThread(CsrThread);
-
- /* Release the Process Lock */
- CsrReleaseProcessLock();
-
- /* Close the NT Thread Handle */
- if (CsrThread->ThreadHandle)
- {
- UnProtectHandle(CsrThread->ThreadHandle);
- Status = NtClose(CsrThread->ThreadHandle);
- ASSERT(NT_SUCCESS(Status));
- }
-
- /* De-allocate the CSR Thread Object */
- CsrDeallocateThread(CsrThread);
-
- /* Remove a reference from the process */
- CsrDereferenceProcess(CsrProcess);
-}
-
-/*++
- * @name CsrLockedDereferenceThread
- *
- * The CsrLockedDereferenceThread dereferences a CSR Thread while the
- * Process Lock is already being held.
- *
- * @param CsrThread
- * Pointer to the CSR Thread to be dereferenced.
- *
- * @return None.
- *
- * @remarks This routine will return with the Process Lock held.
- *
- *--*/
-VOID
-NTAPI
-CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
-{
- LONG LockCount;
-
- /* Decrease reference count */
- LockCount = --CsrThread->ReferenceCount;
- ASSERT(LockCount >= 0);
- if (LockCount == 0)
- {
- /* Call the generic cleanup code */
- CsrAcquireProcessLock();
- CsrThreadRefcountZero(CsrThread);
- }
-}
-
-
-/* PUBLIC FUNCTIONS ***********************************************************/
-
-/*++
- * @name CsrAddStaticServerThread
- * @implemented NT4
- *
- * The CsrAddStaticServerThread routine adds a new CSR Thread to the
- * CSR Server Process (CsrRootProcess).
- *
- * @param hThread
- * Handle to an existing NT Thread to which to associate this
- * CSR Thread.
- *
- * @param ClientId
- * Pointer to the Client ID structure of the NT Thread to associate
- * with this CSR Thread.
- *
- * @param ThreadFlags
- * Initial CSR Thread Flags to associate to this CSR Thread. Usually
- * CsrThreadIsServerThread.
- *
- * @return Pointer to the newly allocated CSR Thread.
- *
- * @remarks None.
- *
- *--*/
-PCSR_THREAD
-NTAPI
-CsrAddStaticServerThread(IN HANDLE hThread,
- IN PCLIENT_ID ClientId,
- IN ULONG ThreadFlags)
-{
- PCSR_THREAD CsrThread;
-
- /* Get the Lock */
- CsrAcquireProcessLock();
-
- /* Allocate the Server Thread */
- CsrThread = CsrAllocateThread(CsrRootProcess);
- if (CsrThread)
- {
- /* Setup the Object */
- CsrThread->ThreadHandle = hThread;
- ProtectHandle(hThread);
- CsrThread->ClientId = *ClientId;
- CsrThread->Flags = ThreadFlags;
-
- /* Insert it into the Thread List */
- InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
-
- /* Increment the thread count */
- CsrRootProcess->ThreadCount++;
- }
- else
- {
- DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread);
- }
-
- /* Release the Process Lock and return */
- CsrReleaseProcessLock();
- return CsrThread;
-}
-
-/*++
- * @name CsrCreateRemoteThread
- * @implemented NT4
- *
- * The CsrCreateRemoteThread routine creates a CSR Thread object for
- * an NT Thread which is not part of the current NT Process.
- *
- * @param hThread
- * Handle to an existing NT Thread to which to associate this
- * CSR Thread.
- *
- * @param ClientId
- * Pointer to the Client ID structure of the NT Thread to associate
- * with this CSR Thread.
- *
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
- *
- * @remarks None.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrCreateRemoteThread(IN HANDLE hThread,
- IN PCLIENT_ID ClientId)
-{
- NTSTATUS Status;
- HANDLE ThreadHandle;
- PCSR_THREAD CsrThread;
- PCSR_PROCESS CsrProcess;
- KERNEL_USER_TIMES KernelTimes;
-
- /* Get the Thread Create Time */
- Status = NtQueryInformationThread(hThread,
- ThreadTimes,
- &KernelTimes,
- sizeof(KernelTimes),
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to query thread times: %lx\n", Status);
- return Status;
- }
-
- /* Lock the Owner Process */
- Status = CsrLockProcessByClientId(ClientId->UniqueProcess, &CsrProcess);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("No known process for %lx\n", ClientId->UniqueProcess);
- return Status;
- }
-
- /* Make sure the thread didn't terminate */
- if (KernelTimes.ExitTime.QuadPart)
- {
- /* Unlock the process and return */
- CsrUnlockProcess(CsrProcess);
- DPRINT1("Dead thread: %I64x\n", KernelTimes.ExitTime.QuadPart);
- return STATUS_THREAD_IS_TERMINATING;
- }
-
- /* Allocate a CSR Thread Structure */
- CsrThread = CsrAllocateThread(CsrProcess);
- if (!CsrThread)
- {
- DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
- CsrUnlockProcess(CsrProcess);
- return STATUS_NO_MEMORY;
- }
-
- /* Duplicate the Thread Handle */
- Status = NtDuplicateObject(NtCurrentProcess(),
- hThread,
- NtCurrentProcess(),
- &ThreadHandle,
- 0,
- 0,
- DUPLICATE_SAME_ACCESS);
- /* Allow failure */
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Thread duplication failed: %lx\n", Status);
- ThreadHandle = hThread;
- }
-
- /* Save the data we have */
- CsrThread->CreateTime = KernelTimes.CreateTime;
- CsrThread->ClientId = *ClientId;
- CsrThread->ThreadHandle = ThreadHandle;
- ProtectHandle(ThreadHandle);
- CsrThread->Flags = 0;
-
- /* Insert the Thread into the Process */
- 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);
- return STATUS_SUCCESS;
-}
-
-/*++
- * @name CsrCreateThread
- * @implemented NT4
- *
- * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
- *
- * @param CsrProcess
- * Pointer to the CSR Process which will contain the CSR Thread.
- *
- * @param hThread
- * Handle to an existing NT Thread to which to associate this
- * CSR Thread.
- *
- * @param ClientId
- * Pointer to the Client ID structure of the NT Thread to associate
- * with this CSR Thread.
- *
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
- *
- * @remarks None.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrCreateThread(IN PCSR_PROCESS CsrProcess,
- IN HANDLE hThread,
- IN PCLIENT_ID ClientId,
- IN BOOLEAN HaveClient)
-{
- NTSTATUS Status;
- PCSR_THREAD CsrThread, CurrentThread;
- PCSR_PROCESS CurrentProcess;
- CLIENT_ID CurrentCid;
- KERNEL_USER_TIMES KernelTimes;
-
- if (HaveClient)
- {
- /* Get the current thread and CID */
- CurrentThread = CsrGetClientThread();
- CurrentCid = CurrentThread->ClientId;
-
- /* Acquire the Process Lock */
- CsrAcquireProcessLock();
-
- /* Get the current Process and make sure the Thread is valid with this CID */
- CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
-
- /* Something is wrong if we get an empty thread back */
- if (!CurrentThread)
- {
- DPRINT1("CSRSRV: %s: invalid thread!\n", __FUNCTION__);
- CsrReleaseProcessLock();
- return STATUS_THREAD_IS_TERMINATING;
- }
- }
- else
- {
- /* Acquire the Process Lock */
- CsrAcquireProcessLock();
- }
-
- /* Get the Thread Create Time */
- Status = NtQueryInformationThread(hThread,
- ThreadTimes,
- (PVOID)&KernelTimes,
- sizeof(KernelTimes),
- NULL);
- if (!NT_SUCCESS(Status))
- {
- CsrReleaseProcessLock();
- return Status;
- }
-
- /* Allocate a CSR Thread Structure */
- CsrThread = CsrAllocateThread(CsrProcess);
- if (!CsrThread)
- {
- DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
- CsrReleaseProcessLock();
- return STATUS_NO_MEMORY;
- }
-
- /* Save the data we have */
- CsrThread->CreateTime = KernelTimes.CreateTime;
- CsrThread->ClientId = *ClientId;
- CsrThread->ThreadHandle = hThread;
- ProtectHandle(hThread);
- CsrThread->Flags = 0;
-
- /* Insert the Thread into the Process */
- Status = CsrInsertThread(CsrProcess, CsrThread);
- if (!NT_SUCCESS(Status))
- {
- /* Bail out */
- CsrUnlockProcess(CsrProcess);
- CsrDeallocateThread(CsrThread);
- return Status;
- }
-
- /* Release the lock and return */
- CsrReleaseProcessLock();
-
- return STATUS_SUCCESS;
-}
-
-/*++
- * @name CsrDereferenceThread
- * @implemented NT4
- *
- * The CsrDereferenceThread routine removes a reference from a CSR Thread.
- *
- * @param CsrThread
- * Pointer to the CSR Thread to dereference.
- *
- * @return None.
- *
- * @remarks If the reference count has reached zero (ie: the CSR Thread has
- * no more active references), it will be deleted.
- *
- *--*/
-VOID
-NTAPI
-CsrDereferenceThread(IN PCSR_THREAD CsrThread)
-{
- /* Acquire process lock */
- CsrAcquireProcessLock();
-
- /* Decrease reference count */
- ASSERT(CsrThread->ReferenceCount > 0);
- if ((--CsrThread->ReferenceCount) == 0)
- {
- /* Call the generic cleanup code */
- CsrThreadRefcountZero(CsrThread);
- }
- else
- {
- /* Just release the lock */
- CsrReleaseProcessLock();
- }
-}
-
-/*++
- * @name CsrDestroyThread
- * @implemented NT4
- *
- * The CsrDestroyThread routine destroys the CSR Thread corresponding to
- * a given Thread ID.
- *
- * @param Cid
- * Pointer to the Client ID Structure corresponding to the CSR
- * Thread which is about to be destroyed.
- *
- * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
- * if the CSR Thread is already terminating.
- *
- * @remarks None.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrDestroyThread(IN PCLIENT_ID Cid)
-{
- CLIENT_ID ClientId = *Cid;
- PCSR_THREAD CsrThread;
- PCSR_PROCESS CsrProcess;
-
- /* Acquire lock */
- CsrAcquireProcessLock();
-
- /* Find the thread */
- CsrThread = CsrLocateThreadByClientId(&CsrProcess,
- &ClientId);
-
- /* Make sure we got one back, and that it's not already gone */
- if (!CsrThread || (CsrThread->Flags & CsrThreadTerminated))
- {
- /* Release the lock and return failure */
- CsrReleaseProcessLock();
- return STATUS_THREAD_IS_TERMINATING;
- }
-
- /* Set the terminated flag */
- CsrThread->Flags |= CsrThreadTerminated;
-
- /* Acquire the Wait Lock */
- CsrAcquireWaitLock();
-
- /* Do we have an active wait block? */
- if (CsrThread->WaitBlock)
- {
- /* Notify waiters of termination */
- CsrNotifyWaitBlock(CsrThread->WaitBlock,
- NULL,
- NULL,
- NULL,
- CsrProcessTerminating,
- TRUE);
- }
-
- /* Release the Wait Lock */
- CsrReleaseWaitLock();
-
- /* Dereference the thread */
- CsrLockedDereferenceThread(CsrThread);
-
- /* Release the Process Lock and return success */
- CsrReleaseProcessLock();
- return STATUS_SUCCESS;
-}
-
-/*++
- * @name CsrExecServerThread
- * @implemented NT4
- *
- * The CsrExecServerThread routine creates an NT Thread and then
- * initializes a CSR Thread for it.
- *
- * @param ThreadHandler
- * Pointer to the thread's startup routine.
- *
- * @param Flags
- * Initial CSR Thread Flags to set to the CSR Thread.
- *
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
- *
- * @remarks This routine is similar to CsrAddStaticServerThread, but it
- * also creates an NT Thread instead of expecting one to already
- * exist.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrExecServerThread(IN PVOID ThreadHandler,
- IN ULONG Flags)
-{
- PCSR_THREAD CsrThread;
- HANDLE hThread;
- CLIENT_ID ClientId;
- NTSTATUS Status;
-
- /* Acquire process lock */
- CsrAcquireProcessLock();
-
- /* Allocate a CSR Thread in the Root Process */
- ASSERT(CsrRootProcess != NULL);
- CsrThread = CsrAllocateThread(CsrRootProcess);
- if (!CsrThread)
- {
- /* Fail */
- CsrReleaseProcessLock();
- return STATUS_NO_MEMORY;
- }
-
- /* Create the Thread */
- Status = RtlCreateUserThread(NtCurrentProcess(),
- NULL,
- FALSE,
- 0,
- 0,
- 0,
- ThreadHandler,
- NULL,
- &hThread,
- &ClientId);
- if (!NT_SUCCESS(Status))
- {
- /* Fail */
- CsrDeallocateThread(CsrThread);
- CsrReleaseProcessLock();
- return Status;
- }
-
- /* Setup the Thread Object */
- CsrThread->ThreadHandle = hThread;
- ProtectHandle(hThread);
- CsrThread->ClientId = ClientId;
- CsrThread->Flags = Flags;
-
- /* Insert it into the Thread List */
- InsertHeadList(&CsrRootProcess->ThreadList, &CsrThread->Link);
-
- /* Increase the thread count */
- CsrRootProcess->ThreadCount++;
-
- /* Return */
- CsrReleaseProcessLock();
- return Status;
-}
-
-/*++
- * @name CsrLockThreadByClientId
- * @implemented NT4
- *
- * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
- * to the given Thread ID and optionally returns it.
- *
- * @param Tid
- * Thread ID corresponding to the CSR Thread which will be locked.
- *
- * @param CsrThread
- * Optional pointer to a CSR Thread pointer which will hold the
- * CSR Thread corresponding to the given Thread ID.
- *
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
- *
- * @remarks Locking a CSR Thread is defined as acquiring an extra
- * reference to it and returning with the Process Lock held.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrLockThreadByClientId(IN HANDLE Tid,
- OUT PCSR_THREAD *CsrThread)
-{
- PLIST_ENTRY NextEntry;
- PCSR_THREAD CurrentThread = NULL;
- NTSTATUS Status = STATUS_UNSUCCESSFUL;
- ULONG i;
-
- /* Acquire the lock */
- CsrAcquireProcessLock();
-
- /* Assume failure */
- ASSERT(CsrThread != NULL);
- *CsrThread = NULL;
-
- /* Convert to Hash */
- i = CsrHashThread(Tid);
-
- /* Setup the List Pointers */
- NextEntry = CsrThreadHashTable[i].Flink;
-
- /* Start Loop */
- while (NextEntry != &CsrThreadHashTable[i])
- {
- /* Get the Thread */
- CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
-
- /* Check for TID Match */
- if ((CurrentThread->ClientId.UniqueThread == Tid) &&
- (CurrentThread->Flags & CsrThreadTerminated) == 0)
- {
- /* Get out of here */
- break;
- }
-
- /* Move to the next entry */
- NextEntry = NextEntry->Flink;
- }
-
- /* Nothing found if we got back to the list */
- if (NextEntry == &CsrThreadHashTable[i]) CurrentThread = NULL;
-
- /* Did the loop find something? */
- if (CurrentThread)
- {
- /* Reference the found thread */
- Status = STATUS_SUCCESS;
- CsrLockedReferenceThread(CurrentThread);
- *CsrThread = CurrentThread;
- }
- else
- {
- /* Nothing found, release the lock */
- Status = STATUS_UNSUCCESSFUL;
- CsrReleaseProcessLock();
- }
-
- /* Return the status */
- return Status;
-}
-
-/*++
- * @name CsrReferenceThread
- * @implemented NT4
- *
- * The CsrReferenceThread routine increases the active reference count of
- * a CSR Thread.
- *
- * @param CsrThread
- * Pointer to the CSR Thread whose reference count will be increased.
- *
- * @return None.
- *
- * @remarks Do not use this routine if the Process Lock is already held.
- *
- *--*/
-VOID
-NTAPI
-CsrReferenceThread(IN PCSR_THREAD CsrThread)
-{
- /* Acquire process lock */
- CsrAcquireProcessLock();
-
- /* Sanity checks */
- ASSERT((CsrThread->Flags & CsrThreadTerminated) == 0);
- ASSERT(CsrThread->ReferenceCount != 0);
-
- /* Increment reference count */
- CsrThread->ReferenceCount++;
-
- /* Release the lock */
- CsrReleaseProcessLock();
-}
-
-/*++
- * @name CsrUnlockThread
- * @implemented NT4
- *
- * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
- *
- * @param CsrThread
- * Pointer to a previously locked CSR Thread.
- *
- * @return STATUS_SUCCESS.
- *
- * @remarks This routine must be called with the Process Lock held.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrUnlockThread(IN PCSR_THREAD CsrThread)
-{
- /* Dereference the Thread */
- ASSERT(ProcessStructureListLocked());
- CsrLockedDereferenceThread(CsrThread);
-
- /* Release the lock and return */
- CsrReleaseProcessLock();
- return STATUS_SUCCESS;
-}
-
-/* EOF */