- Some NDK fixes when compiling with PSDK.
[reactos.git] / reactos / subsys / csr / csrsrv / thread.c
index c06c539..ca7c632 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/thread.c - CSR server - thread management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/thread.c
+ * PURPOSE:         CSR Server DLL Thread Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
+
+/* INCLUDES ******************************************************************/
+
 #include "srv.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
+/* DATA **********************************************************************/
+
+LIST_ENTRY CsrThreadHashTable[256];
+SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
+{
+    sizeof(SECURITY_QUALITY_OF_SERVICE),
+    SecurityImpersonation,
+    SECURITY_STATIC_TRACKING,
+    FALSE
+};
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @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 */
+    CsrThread->ReferenceCount++;
+    CsrProcess->ReferenceCount++;
+
+    /* Set the Parent Process */
+    CsrThread->Process = CsrProcess;
+
+    /* Return Thread */
+    return CsrThread;
+}
+
+/*++
+ * @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;
+
+    /* 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);
+
+        /* Compare the CID */
+        if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
+        {
+            /* Match found, return the process */
+            *Process = FoundThread->Process;
+
+            /* Return thread too */
+            return FoundThread;
+        }
+
+        /* Next */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* 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 != NextEntry)
+    {
+        /* Get Thread Entry */
+        FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+        /* Check for TID Match */
+        if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
+
+        /* 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.
+ *
+ *--*/
+VOID
+NTAPI
+CsrInsertThread(IN PCSR_PROCESS Process,
+                IN PCSR_THREAD Thread)
+{
+    ULONG i;
+
+    /* 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);
+}
+
+/*++
+ * @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 */
+    RtlFreeHeap(CsrHeap, 0, CsrThread);
+}
+
+/*++
+ * @name CsrLockedDereferenceThread
+ *
+ * The CsrLockedDereferenceThread derefences 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(PCSR_THREAD CsrThread)
+{
+    /* Decrease reference count */
+    if (!(--CsrThread->ReferenceCount))
+    {
+        /* Call the generic cleanup code */
+        CsrThreadRefcountZero(CsrThread);
+        CsrAcquireProcessLock();
+    }
+}
+
+/*++
+ * @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)
+{
+    /* 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)
+    {
+        /* Check if it's not already been marked for deletion */
+        if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
+        {
+            /* 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;
+
+    /* Remove this thread */
+    CsrRemoveThread(CsrThread);
+
+    /* Release the Process Lock */
+    CsrReleaseProcessLock();
+
+    /* Close the NT Thread Handle */
+    NtClose(CsrThread->ThreadHandle);
+    
+    /* De-allocate the CSR Thread Object */
+    CsrDeallocateThread(CsrThread);
+
+    /* Remove a reference from the process */
+    CsrDereferenceProcess(CsrProcess);
+}
+
+/* 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 */
+    if ((CsrThread = CsrAllocateThread(CsrRootProcess)))
+    {
+        /* Setup the Object */
+        CsrThread->ThreadHandle = hThread;
+        CsrThread->ClientId = *ClientId;
+        CsrThread->Flags = ThreadFlags;
+
+        /* Insert it into the Thread List */
+        InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
+
+        /* Increment the thread count */
+        CsrRootProcess->ThreadCount++;
+    }
+
+    /* 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
+ *         othwerwise.
+ *
+ * @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;
+
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Get the Thread Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      (PVOID)&KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+
+    /* Lock the Owner Process */
+    Status = CsrLockProcessByClientId(&ClientId->UniqueProcess,
+                                      &CsrProcess);
+
+    /* Make sure the thread didn't terminate */
+    if (KernelTimes.ExitTime.QuadPart)
+    {
+        /* Unlock the process and return */
+        CsrUnlockProcess(CsrProcess);
+        return STATUS_THREAD_IS_TERMINATING;
+    }
+
+    /* Allocate a CSR Thread Structure */
+    if (!(CsrThread = CsrAllocateThread(CsrProcess)))
+    {
+        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)) ThreadHandle = hThread;
+
+    /* Save the data we have */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = *ClientId;
+    CsrThread->ThreadHandle = ThreadHandle;
+    CsrThread->Flags = 0;
 
-NTSTATUS STDCALL CsrCreateRemoteThread ()
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* 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
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateThread(IN PCSR_PROCESS CsrProcess,
+                IN HANDLE hThread,
+                IN PCLIENT_ID ClientId)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS CurrentProcess;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+    CLIENT_ID CurrentCid;
+    KERNEL_USER_TIMES KernelTimes;
+
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Get the current thread and CID */
+    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;
+    }
+
+    /* Get the Thread Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      (PVOID)&KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+
+    /* Allocate a CSR Thread Structure */
+    if (!(CsrThread = CsrAllocateThread(CsrProcess)))
+    {
+        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;
+    CsrThread->Flags = 0;
+
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS STDCALL CsrCreateThread (PCSR_PROCESS pCsrProcess, PCSR_THREAD *ppCsrThread)
+/*++
+ * @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(PCSR_THREAD CsrThread)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       PCSR_THREAD pCsrThread = NULL;
-       PCSR_SESSION pCsrSession = NULL;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
 
-       if (NULL == pCsrProcess || NULL == ppCsrThread)
-       {
-               return STATUS_INVALID_PARAMETER;
-       }
-       pCsrSession = pCsrProcess->NtSession;
-       pCsrThread = RtlAllocateHeap (pCsrSession->Heap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof (CSR_THREAD));
-       if (NULL == pCsrThread)
-       {
-               DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
-               return STATUS_NO_MEMORY;
-       }
-       pCsrThread->Process = pCsrProcess;      
-       return Status;
+    /* Decrease reference count */
+    if (!(--CsrThread->ReferenceCount))
+    {
+        /* Call the generic cleanup code */
+        CsrThreadRefcountZero(CsrThread);
+    }
+    else
+    {
+        /* Just release the lock */
+        CsrReleaseProcessLock();
+    }
 }
 
-NTSTATUS STDCALL CsrDereferenceThread (PCSR_THREAD pCsrThread)
+/*++
+ * @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
+ *         othwerwise.
+ *
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    PCSR_THREAD CsrThread;
+    HANDLE hThread;
+    CLIENT_ID ClientId;
+    NTSTATUS Status;
+
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Allocate a CSR Thread in the Root Process */
+    if (!(CsrThread = CsrAllocateThread(CsrRootProcess)))
+    {
+        /* 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;
+    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;
 }
 
-NTSTATUS STDCALL CsrDestroyThread (PCSR_THREAD pCsrThread)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    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;
 }
 
-NTSTATUS STDCALL CsrLockThreadByClientId ()
+/*++
+ * @name CsrImpersonateClient
+ * @implemented NT4
+ *
+ * The CsrImpersonateClient will impersonate the given CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to impersonate.    
+ *
+ * @return TRUE if impersionation suceeded, false otherwise.
+ *
+ * @remarks Impersonation can be recursive.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrImpersonateClient(IN PCSR_THREAD CsrThread)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+
+    /* Use the current thread if none given */
+    if (!CsrThread) CsrThread = CurrentThread;
+
+    /* Still no thread, something is wrong */
+    if (!CsrThread)
+    {
+        /* Failure */
+        return FALSE;
+    }
+
+    /* Make the call */
+    Status = NtImpersonateThread(NtCurrentThread(),
+                                 CsrThread->ThreadHandle,
+                                 &CsrSecurityQos);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failure */
+        return FALSE;
+    }
+
+    /* Increase the impersonation count for the current thread */
+    if (CurrentThread) ++CurrentThread->ImpersonationCount;
+
+    /* Return Success */
+    return TRUE;
 }
 
-NTSTATUS STDCALL CsrReferenceThread (PCSR_THREAD pCsrThread)
+/*++
+ * @name CsrRevertToSelf
+ * @implemented NT4
+ *
+ * The CsrRevertToSelf routine will attempt to remove an active impersonation.
+ *
+ * @param None.  
+ *
+ * @return TRUE if the reversion was succesful, false otherwise.
+ *
+ * @remarks Impersonation can be recursive; as such, the impersonation token
+ *          will only be deleted once the CSR Thread's impersonaton count
+ *          has reached zero.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrRevertToSelf(VOID)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+    HANDLE ImpersonationToken = NULL;
+
+    /* Check if we have a Current Thread */
+    if (CurrentThread)
+    {
+        /* Make sure impersonation is on */
+        if (!CurrentThread->ImpersonationCount)
+        {
+            return FALSE;
+        }
+        else if (--CurrentThread->ImpersonationCount > 0)
+        {
+            /* Success; impersonation count decreased but still not zero */
+            return TRUE;
+        }
+    }
+
+    /* Impersonation has been totally removed, revert to ourselves */
+    Status = NtSetInformationThread(NtCurrentThread(),
+                                    ThreadImpersonationToken,
+                                    &ImpersonationToken,
+                                    sizeof(HANDLE));
+
+    /* Return TRUE or FALSE */
+    return NT_SUCCESS(Status);
 }
 
-NTSTATUS STDCALL CsrUnlockThread (PCSR_THREAD pCsrThread)
+/*++
+ * @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
+ *         othwerwise.
+ *
+ * @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 OPTIONAL)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD CurrentThread = NULL;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    ULONG i;
+
+    /* Acquire the lock */
+    CsrAcquireProcessLock();
+
+    /* Convert to Hash */
+    i = CsrHashThread(Tid);
+
+    /* Setup the List Pointers */
+    ListHead = &CsrThreadHashTable[i];
+    NextEntry = ListHead;
+
+    /* Start Loop */
+    while (NextEntry != ListHead)
+    {
+        /* Get the Process */
+        CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
+
+        /* Check for PID Match */
+        if ((CurrentThread->ClientId.UniqueThread == Tid) &&
+            !(CurrentThread->Flags & CsrThreadTerminated))
+        {
+            /* Get out of here with success */
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Did the loop find something? */
+    if (NT_SUCCESS(Status))
+    {
+        /* Reference the found thread */
+        CurrentThread->ReferenceCount++;
+    }
+    else
+    {
+        /* Nothing found, release the lock */
+        CsrReleaseProcessLock();
+    }
+
+    /* Return the status and thread */
+    if (CsrThread) *CsrThread = CurrentThread;
+    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(PCSR_THREAD CsrThread)
+{
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* 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(PCSR_THREAD CsrThread)
+{
+    /* Dereference the Thread */
+    CsrLockedDereferenceThread(CsrThread);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
 /* EOF */