[CSRSRV]
[reactos.git] / subsystems / win32 / csrsrv / procsup.c
index 180892d..fe96ddb 100644 (file)
@@ -1,12 +1,12 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS CSR SubSystem
- * FILE:            subsystems/win32/csrss/csrsrv/procsup.c
+ * PROJECT:         ReactOS Client/Server Runtime SubSystem
+ * FILE:            subsystems/win32/csrsrv/procsup.c
  * PURPOSE:         CSR Server DLL Process Management
  * PROGRAMMERS:     ReactOS Portable Systems Group
  *                  Alex Ionescu (alex@relsoft.net)
  */
+
 /* INCLUDES *******************************************************************/
 
 #include <srv.h>
@@ -26,15 +26,15 @@ SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
     FALSE
 };
 ULONG CsrProcessSequenceCount = 5;
-extern ULONG CsrTotalPerProcessDataLength; // remove 'extern' if not needed.
+extern ULONG CsrTotalPerProcessDataLength;
 
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
 /*++
- * @name CsrpSetToNormalPriority
+ * @name CsrSetToNormalPriority
  *
- * The CsrpSetToNormalPriority routine sets the current NT Process'
+ * The CsrSetToNormalPriority routine sets the current NT Process'
  * priority to the normal priority for CSR Processes.
  *
  * @param None.
@@ -47,7 +47,7 @@ extern ULONG CsrTotalPerProcessDataLength; // remove 'extern' if not needed.
  *--*/
 VOID
 NTAPI
-CsrSetToNormalPriority(VOID) // CsrpSetToNormalPriority
+CsrSetToNormalPriority(VOID)
 {
     KPRIORITY BasePriority = (8 + 1) + 4;
 
@@ -59,9 +59,9 @@ CsrSetToNormalPriority(VOID) // CsrpSetToNormalPriority
 }
 
 /*++
- * @name CsrpSetToShutdownPriority
+ * @name CsrSetToShutdownPriority
  *
- * The CsrpSetToShutdownPriority routine sets the current NT Process'
+ * The CsrSetToShutdownPriority routine sets the current NT Process'
  * priority to the boosted priority for CSR Processes doing shutdown.
  * Additonally, it acquires the Shutdown Privilege required for shutdown.
  *
@@ -75,7 +75,7 @@ CsrSetToNormalPriority(VOID) // CsrpSetToNormalPriority
  *--*/
 VOID
 NTAPI
-CsrSetToShutdownPriority(VOID) // CsrpSetToShutdownPriority
+CsrSetToShutdownPriority(VOID)
 {
     KPRIORITY SetBasePriority = (8 + 1) + 6;
     BOOLEAN Old;
@@ -268,8 +268,8 @@ CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
     {
         /* Call the generic cleanup code */
         DPRINT1("Should kill process: %p\n", CsrProcess);
-        CsrProcessRefcountZero(CsrProcess);
         CsrAcquireProcessLock();
+        CsrProcessRefcountZero(CsrProcess);
     }
 }
 
@@ -305,7 +305,7 @@ CsrAllocateProcess(VOID)
     if (CsrProcessSequenceCount < 5) CsrProcessSequenceCount = 5;
 
     /* Increase the reference count */
-    CsrProcess->ReferenceCount++;
+    CsrLockedReferenceProcess(CsrProcess);
 
     /* Initialize the Thread List */
     InitializeListHead(&CsrProcess->ThreadList);
@@ -341,7 +341,7 @@ CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
  * @implemented NT4
  *
  * The CsrInitializeProcessStructure routine sets up support for CSR Processes
- * and CSR Threads.
+ * and CSR Threads by initializing our own CSR Root Process.
  *
  * @param None.
  *
@@ -437,7 +437,7 @@ CsrRemoveProcess(IN PCSR_PROCESS CsrProcess)
         ServerDll = CsrLoadedServerDll[i];
 
         /* Check if it's valid and if it has a Disconnect Callback */
-        if ((ServerDll) && (ServerDll->DisconnectCallback))
+        if (ServerDll && ServerDll->DisconnectCallback)
         {
             /* Call it */
             ServerDll->DisconnectCallback(CsrProcess);
@@ -451,11 +451,8 @@ CsrRemoveProcess(IN PCSR_PROCESS CsrProcess)
  * The CsrInsertProcess routine inserts a CSR Process into the Process List
  * and notifies Server DLLs of the creation of a new CSR Process.
  *
- * @param Parent
- *        Optional pointer to the CSR Process creating this CSR Process.
- *
- * @param CurrentProcess
- *        Optional pointer to the current CSR Process.
+ * @param ParentProcess
+ *        Optional pointer to the Parent Process creating this CSR Process.
  *
  * @param CsrProcess
  *        Pointer to the CSR Process which is to be inserted.
@@ -467,17 +464,13 @@ CsrRemoveProcess(IN PCSR_PROCESS CsrProcess)
  *--*/
 VOID
 NTAPI
-CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
-                 IN PCSR_PROCESS CurrentProcess OPTIONAL,
+CsrInsertProcess(IN PCSR_PROCESS ParentProcess OPTIONAL,
                  IN PCSR_PROCESS CsrProcess)
 {
     PCSR_SERVER_DLL ServerDll;
     ULONG i;
     ASSERT(ProcessStructureListLocked());
 
-    /* Set the parent */
-    CsrProcess->Parent = Parent;
-
     /* Insert it into the Root List */
     InsertTailList(&CsrRootProcess->ListLink, &CsrProcess->ListLink);
 
@@ -488,9 +481,9 @@ CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
         ServerDll = CsrLoadedServerDll[i];
 
         /* Make sure it's valid and that it has callback */
-        if ((ServerDll) && (ServerDll->NewProcessCallback))
+        if (ServerDll && ServerDll->NewProcessCallback)
         {
-            ServerDll->NewProcessCallback(CurrentProcess, CsrProcess);
+            ServerDll->NewProcessCallback(ParentProcess, CsrProcess);
         }
     }
 }
@@ -499,210 +492,266 @@ CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 /*++
- * @name CsrGetProcessLuid
+ * @name CsrCreateProcess
  * @implemented NT4
  *
  * Do nothing for 500ms.
  *
- * @param hProcess
- *        Optional handle to the process whose LUID should be returned.
+ * @param ArgumentCount
+ *        Description of the parameter. Wrapped to more lines on ~70th
+ *        column.
  *
- * @param Luid
- *        Pointer to a LUID Pointer which will receive the CSR Process' LUID
+ * @param Arguments
+ *        Description of the parameter. Wrapped to more lines on ~70th
+ *        column.
  *
  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
  *         otherwise.
  *
- * @remarks If hProcess is not supplied, then the current thread's token will
- *          be used. If that too is missing, then the current process' token
- *          will be used.
+ * @remarks None.
  *
  *--*/
 NTSTATUS
 NTAPI
-CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
-                  PLUID Luid)
+CsrCreateProcess(IN HANDLE hProcess,
+                 IN HANDLE hThread,
+                 IN PCLIENT_ID ClientId,
+                 IN PCSR_NT_SESSION NtSession,
+                 IN ULONG Flags,
+                 IN PCLIENT_ID DebugCid)
 {
-    HANDLE hToken = NULL;
+    PCSR_THREAD CurrentThread = CsrGetClientThread();
+    CLIENT_ID CurrentCid;
+    PCSR_PROCESS CurrentProcess;
+    PCSR_SERVER_DLL ServerDll;
+    PVOID ProcessData;
+    ULONG i;
+    PCSR_PROCESS CsrProcess;
     NTSTATUS Status;
-    ULONG Length;
-    PTOKEN_STATISTICS TokenStats;
+    PCSR_THREAD CsrThread;
+    KERNEL_USER_TIMES KernelTimes;
 
-    /* Check if we have a handle to a CSR Process */
-    if (!hProcess)
+    /* Get the current CID and lock Processes */
+    CurrentCid = CurrentThread->ClientId;
+    CsrAcquireProcessLock();
+
+    /* Get the current CSR Thread */
+    CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
+    if (!CurrentThread)
     {
-        /* We don't, so try opening the Thread's Token */
-        Status = NtOpenThreadToken(NtCurrentThread(),
-                                   TOKEN_QUERY,
-                                   FALSE,
-                                   &hToken);
+        /* We've failed to locate the thread */
+        CsrReleaseProcessLock();
+        return STATUS_THREAD_IS_TERMINATING;
+    }
 
-        /* Check for success */
-        if (!NT_SUCCESS(Status))
+    /* Allocate a new Process Object */
+    CsrProcess = CsrAllocateProcess();
+    if (!CsrProcess)
+    {
+        /* Couldn't allocate Process */
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Inherit the Process Data */
+    CurrentProcess = CurrentThread->Process;
+    ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Get the current Server */
+        ServerDll = CsrLoadedServerDll[i];
+
+        /* Check if the DLL is Loaded and has Per Process Data */
+        if (ServerDll && ServerDll->SizeOfProcessData)
         {
-            /* If we got some other failure, then return and quit */
-            if (Status != STATUS_NO_TOKEN) return Status;
+            /* Set the pointer */
+            CsrProcess->ServerData[i] = ProcessData;
 
-            /* We don't have a Thread Token, use a Process Token */
-            hProcess = NtCurrentProcess();
-            hToken = NULL;
+            /* Copy the Data */
+            RtlMoveMemory(ProcessData,
+                          CurrentProcess->ServerData[i],
+                          ServerDll->SizeOfProcessData);
+
+            /* Update next data pointer */
+            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
+                                  ServerDll->SizeOfProcessData);
+        }
+        else
+        {
+            /* No data for this Server */
+            CsrProcess->ServerData[i] = NULL;
         }
     }
 
-    /* Check if we have a token by now */
-    if (!hToken)
+    /* Set the Exception port for us */
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessExceptionPort,
+                                     &CsrApiPort,
+                                     sizeof(HANDLE));
+    if (!NT_SUCCESS(Status))
     {
-        /* No token yet, so open the Process Token */
-        Status = NtOpenProcessToken(hProcess,
-                                    TOKEN_QUERY,
-                                    &hToken);
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
+    if (!(Flags & CsrProcessCreateNewGroup))
+    {
+        /* Create new data */
+        CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess);
+        CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber;
+    }
+    else
+    {
+        /* Copy it from the current process */
+        CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId;
+        CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence;
+    }
+
+    /* Check if this is a console process */
+    if (Flags & CsrProcessIsConsoleApp) CsrProcess->Flags |= CsrProcessIsConsoleApp;
+
+    /* Mask out non-debug flags */
+    Flags &= ~(CsrProcessIsConsoleApp | CsrProcessCreateNewGroup | CsrProcessPriorityFlags);
+
+    /* Check if every process will be debugged */
+    if (!(Flags) && (CurrentProcess->DebugFlags & CsrDebugProcessChildren))
+    {
+        /* Pass it on to the current process */
+        CsrProcess->DebugFlags = CsrDebugProcessChildren;
+        CsrProcess->DebugCid = CurrentProcess->DebugCid;
+    }
+
+    /* Check if Debugging was used on this process */
+    if ((Flags & (CsrDebugOnlyThisProcess | CsrDebugProcessChildren)) && (DebugCid))
+    {
+        /* Save the debug flag used */
+        CsrProcess->DebugFlags = Flags;
+
+        /* Save the CID */
+        CsrProcess->DebugCid = *DebugCid;
+    }
+
+    /* Check if Debugging is enabled */
+    if (CsrProcess->DebugFlags)
+    {
+        /* Set the Debug Port for us */
+        Status = NtSetInformationProcess(hProcess,
+                                         ProcessDebugPort,
+                                         &CsrApiPort,
+                                         sizeof(HANDLE));
+        ASSERT(NT_SUCCESS(Status));
         if (!NT_SUCCESS(Status))
         {
-            /* Still no token, return the error */
-            return Status;
+            /* Failed */
+            CsrDeallocateProcess(CsrProcess);
+            CsrReleaseProcessLock();
+            return STATUS_NO_MEMORY;
         }
     }
 
-    /* Now get the size we'll need for the Token Information */
-    Status = NtQueryInformationToken(hToken,
-                                     TokenStatistics,
-                                     NULL,
-                                     0,
-                                     &Length);
+    /* Get the Thread Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      (PVOID)&KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
 
-    /* Allocate memory for the Token Info */
-    if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
+    /* Allocate a CSR Thread Structure */
+    CsrThread = CsrAllocateThread(CsrProcess);
+    if (!CsrThread)
     {
-        /* Fail and close the token */
-        NtClose(hToken);
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
         return STATUS_NO_MEMORY;
     }
 
-    /* Now query the information */
-    Status = NtQueryInformationToken(hToken,
-                                     TokenStatistics,
-                                     TokenStats,
-                                     Length,
-                                     &Length);
+    /* Save the data we have */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = *ClientId;
+    CsrThread->ThreadHandle = hThread;
+    ProtectHandle(hThread);
+    CsrThread->Flags = 0;
 
-    /* Close the handle */
-    NtClose(hToken);
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
 
-    /* Check for success */
-    if (NT_SUCCESS(Status))
-    {
-        /* Return the LUID */
-        *Luid = TokenStats->AuthenticationId;
-    }
+    /* Reference the session */
+    CsrReferenceNtSession(NtSession);
+    CsrProcess->NtSession = NtSession;
 
-    /* Free the query information */
-    RtlFreeHeap(CsrHeap, 0, TokenStats);
+    /* Setup Process Data */
+    CsrProcess->ClientId = *ClientId;
+    CsrProcess->ProcessHandle = hProcess;
+    CsrProcess->ShutdownLevel = 0x280;
 
-    /* Return the Status */
+    /* Set the Priority to Background */
+    CsrSetBackgroundPriority(CsrProcess);
+
+    /* Insert the Process */
+    CsrInsertProcess(CurrentProcess, CsrProcess);
+
+    /* Release lock and return */
+    CsrReleaseProcessLock();
     return Status;
 }
 
 /*++
- * @name CsrImpersonateClient
+ * @name CsrDebugProcess
  * @implemented NT4
  *
- * The CsrImpersonateClient will impersonate the given CSR Thread.
+ * The CsrDebugProcess routine is deprecated in NT 5.1 and higher. It is
+ * exported only for compatibility with older CSR Server DLLs.
  *
- * @param CsrThread
- *        Pointer to the CSR Thread to impersonate.
+ * @param CsrProcess
+ *        Deprecated.
  *
- * @return TRUE if impersionation suceeded, false otherwise.
+ * @return Deprecated
  *
- * @remarks Impersonation can be recursive.
+ * @remarks Deprecated.
  *
  *--*/
-BOOLEAN
+NTSTATUS
 NTAPI
-CsrImpersonateClient(IN PCSR_THREAD CsrThread)
+CsrDebugProcess(IN PCSR_PROCESS CsrProcess)
 {
-    NTSTATUS Status;
-    PCSR_THREAD CurrentThread = CsrGetClientThread();
-
-    /* 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 */
-/*
-        DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status);
-        if (Status != STATUS_BAD_IMPERSONATION_LEVEL) DbgBreakPoint();
-*/
-        return FALSE;
-    }
-
-    /* Increase the impersonation count for the current thread */
-    if (CurrentThread) ++CurrentThread->ImpersonationCount;
-
-    /* Return Success */
-    return TRUE;
-}
+    /* CSR does not handle debugging anymore */
+    DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
+    return STATUS_UNSUCCESSFUL;
+}
 
 /*++
- * @name CsrRevertToSelf
+ * @name CsrDebugProcessStop
  * @implemented NT4
  *
- * The CsrRevertToSelf routine will attempt to remove an active impersonation.
+ * The CsrDebugProcessStop routine is deprecated in NT 5.1 and higher. It is
+ * exported only for compatibility with older CSR Server DLLs.
  *
- * @param None.
+ * @param CsrProcess
+ *        Deprecated.
  *
- * @return TRUE if the reversion was succesful, false otherwise.
+ * @return Deprecated
  *
- * @remarks Impersonation can be recursive; as such, the impersonation token
- *          will only be deleted once the CSR Thread's impersonaton count
- *          has reached zero.
+ * @remarks Deprecated.
  *
  *--*/
-BOOLEAN
+NTSTATUS
 NTAPI
-CsrRevertToSelf(VOID)
+CsrDebugProcessStop(IN PCSR_PROCESS CsrProcess)
 {
-    NTSTATUS Status;
-    PCSR_THREAD CurrentThread = CsrGetClientThread();
-    HANDLE ImpersonationToken = NULL;
-
-    /* Check if we have a Current Thread */
-    if (CurrentThread)
-    {
-        /* Make sure impersonation is on */
-        if (!CurrentThread->ImpersonationCount)
-        {
-            // DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n");
-            // DbgBreakPoint();
-            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);
+    /* CSR does not handle debugging anymore */
+    DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
+    return STATUS_UNSUCCESSFUL;
 }
 
 /*++
@@ -798,10 +847,13 @@ CsrDestroyProcess(IN PCLIENT_ID Cid,
         /* Get the current thread entry */
         CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
 
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
         /* Make sure the thread isn't already dead */
         if (CsrThread->Flags & CsrThreadTerminated)
         {
-            NextEntry = NextEntry->Flink;
+            /* Go the the next thread */
             continue;
         }
 
@@ -828,7 +880,6 @@ CsrDestroyProcess(IN PCLIENT_ID Cid,
 
         /* Dereference the thread */
         CsrLockedDereferenceThread(CsrThread);
-        NextEntry = CsrProcess->ThreadList.Flink;
     }
 
     /* Release the Process Lock and return success */
@@ -837,271 +888,160 @@ CsrDestroyProcess(IN PCLIENT_ID Cid,
 }
 
 /*++
- * @name CsrCreateProcess
+ * @name CsrGetProcessLuid
  * @implemented NT4
  *
  * Do nothing for 500ms.
  *
- * @param ArgumentCount
- *        Description of the parameter. Wrapped to more lines on ~70th
- *        column.
+ * @param hProcess
+ *        Optional handle to the process whose LUID should be returned.
  *
- * @param Arguments
- *        Description of the parameter. Wrapped to more lines on ~70th
- *        column.
+ * @param Luid
+ *        Pointer to a LUID Pointer which will receive the CSR Process' LUID
  *
  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
  *         otherwise.
  *
- * @remarks None.
+ * @remarks If hProcess is not supplied, then the current thread's token will
+ *          be used. If that too is missing, then the current process' token
+ *          will be used.
  *
  *--*/
 NTSTATUS
 NTAPI
-CsrCreateProcess(IN HANDLE hProcess,
-                 IN HANDLE hThread,
-                 IN PCLIENT_ID ClientId,
-                 IN PCSR_NT_SESSION NtSession,
-                 IN ULONG Flags,
-                 IN PCLIENT_ID DebugCid)
+CsrGetProcessLuid(IN HANDLE hProcess OPTIONAL,
+                  OUT PLUID Luid)
 {
-    PCSR_THREAD CurrentThread = CsrGetClientThread();
-    CLIENT_ID CurrentCid;
-    PCSR_PROCESS CurrentProcess;
-    PVOID ProcessData;
-    ULONG i;
-    PCSR_PROCESS CsrProcess;
+    HANDLE hToken = NULL;
     NTSTATUS Status;
-    PCSR_THREAD CsrThread;
-    KERNEL_USER_TIMES KernelTimes;
-
-    /* Get the current CID and lock Processes */
-    CurrentCid = CurrentThread->ClientId;
-    CsrAcquireProcessLock();
-
-    /* Get the current CSR Thread */
-    CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
-    if (!CurrentThread)
-    {
-        /* We've failed to locate the thread */
-        CsrReleaseProcessLock();
-        return STATUS_THREAD_IS_TERMINATING;
-    }
+    ULONG Length;
+    PTOKEN_STATISTICS TokenStats;
 
-    /* Allocate a new Process Object */
-    CsrProcess = CsrAllocateProcess();
-    if (!CsrProcess)
+    /* Check if we have a handle to a CSR Process */
+    if (!hProcess)
     {
-        /* Couldn't allocate Process */
-        CsrReleaseProcessLock();
-        return STATUS_NO_MEMORY;
-    }
+        /* We don't, so try opening the Thread's Token */
+        Status = NtOpenThreadToken(NtCurrentThread(),
+                                   TOKEN_QUERY,
+                                   FALSE,
+                                   &hToken);
 
-    /* Inherit the Process Data */
-    CurrentProcess = CurrentThread->Process;
-    ProcessData = &CurrentProcess->ServerData[CSR_SERVER_DLL_MAX];
-    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
-    {
-        /* Check if the DLL is Loaded and has Per Process Data */
-        if ((CsrLoadedServerDll[i]) && (CsrLoadedServerDll[i]->SizeOfProcessData))
+        /* Check for success */
+        if (!NT_SUCCESS(Status))
         {
-            /* Set the pointer */
-            CsrProcess->ServerData[i] = ProcessData;
-
-            /* Copy the Data */
-            RtlMoveMemory(ProcessData,
-                          CurrentProcess->ServerData[i],
-                          CsrLoadedServerDll[i]->SizeOfProcessData);
+            /* If we got some other failure, then return and quit */
+            if (Status != STATUS_NO_TOKEN) return Status;
 
-            /* Update next data pointer */
-            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
-                                  CsrLoadedServerDll[i]->SizeOfProcessData);
-        }
-        else
-        {
-            /* No data for this Server */
-            CsrProcess->ServerData[i] = NULL;
+            /* We don't have a Thread Token, use a Process Token */
+            hProcess = NtCurrentProcess();
+            hToken = NULL;
         }
     }
 
-    /* Set the Exception port for us */
-    Status = NtSetInformationProcess(hProcess,
-                                     ProcessExceptionPort,
-                                     &CsrApiPort,
-                                     sizeof(HANDLE));
-    if (!NT_SUCCESS(Status))
-    {
-        /* Failed */
-        CsrDeallocateProcess(CsrProcess);
-        CsrReleaseProcessLock();
-        return STATUS_NO_MEMORY;
-    }
-
-    /* Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
-    if (!(Flags & CsrProcessCreateNewGroup))
-    {
-        /* Create new data */
-        CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess);
-        CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber;
-    }
-    else
-    {
-        /* Copy it from the current process */
-        CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId;
-        CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence;
-    }
-
-    /* Check if this is a console process */
-    if (Flags & CsrProcessIsConsoleApp) CsrProcess->Flags |= CsrProcessIsConsoleApp;
-
-    /* Mask out non-debug flags */
-    Flags &= ~(CsrProcessIsConsoleApp | CsrProcessCreateNewGroup | CsrProcessPriorityFlags);
-
-    /* Check if every process will be debugged */
-    if (!(Flags) && (CurrentProcess->DebugFlags & CsrDebugProcessChildren))
-    {
-        /* Pass it on to the current process */
-        CsrProcess->DebugFlags = CsrDebugProcessChildren;
-        CsrProcess->DebugCid = CurrentProcess->DebugCid;
-    }
-
-    /* Check if Debugging was used on this process */
-    if ((Flags & (CsrDebugOnlyThisProcess | CsrDebugProcessChildren)) && (DebugCid))
-    {
-        /* Save the debug flag used */
-        CsrProcess->DebugFlags = Flags;
-
-        /* Save the CID */
-        CsrProcess->DebugCid = *DebugCid;
-    }
-
-    /* Check if Debugging is enabled */
-    if (CsrProcess->DebugFlags)
+    /* Check if we have a token by now */
+    if (!hToken)
     {
-        /* Set the Debug Port for us */
-        Status = NtSetInformationProcess(hProcess,
-                                         ProcessDebugPort,
-                                         &CsrApiPort,
-                                         sizeof(HANDLE));
-        ASSERT(NT_SUCCESS(Status));
+        /* No token yet, so open the Process Token */
+        Status = NtOpenProcessToken(hProcess,
+                                    TOKEN_QUERY,
+                                    &hToken);
         if (!NT_SUCCESS(Status))
         {
-            /* Failed */
-            CsrDeallocateProcess(CsrProcess);
-            CsrReleaseProcessLock();
-            return STATUS_NO_MEMORY;
+            /* Still no token, return the error */
+            return Status;
         }
     }
 
-    /* Get the Thread Create Time */
-    Status = NtQueryInformationThread(hThread,
-                                      ThreadTimes,
-                                      (PVOID)&KernelTimes,
-                                      sizeof(KernelTimes),
-                                      NULL);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Failed */
-        CsrDeallocateProcess(CsrProcess);
-        CsrReleaseProcessLock();
-        return STATUS_NO_MEMORY;
-    }
+    /* Now get the size we'll need for the Token Information */
+    Status = NtQueryInformationToken(hToken,
+                                     TokenStatistics,
+                                     NULL,
+                                     0,
+                                     &Length);
 
-    /* Allocate a CSR Thread Structure */
-    CsrThread = CsrAllocateThread(CsrProcess);
-    if (!CsrThread)
+    /* Allocate memory for the Token Info */
+    if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
     {
-        /* Failed */
-        CsrDeallocateProcess(CsrProcess);
-        CsrReleaseProcessLock();
+        /* Fail and close the token */
+        NtClose(hToken);
         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 */
-    CsrInsertThread(CsrProcess, CsrThread);
-
-    /* Reference the session */
-    CsrReferenceNtSession(NtSession);
-    CsrProcess->NtSession = NtSession;
+    /* Now query the information */
+    Status = NtQueryInformationToken(hToken,
+                                     TokenStatistics,
+                                     TokenStats,
+                                     Length,
+                                     &Length);
 
-    /* Setup Process Data */
-    CsrProcess->ClientId = *ClientId;
-    CsrProcess->ProcessHandle = hProcess;
-    CsrProcess->ShutdownLevel = 0x280;
+    /* Close the handle */
+    NtClose(hToken);
 
-    /* Set the Priority to Background */
-    CsrSetBackgroundPriority(CsrProcess);
+    /* Check for success */
+    if (NT_SUCCESS(Status))
+    {
+        /* Return the LUID */
+        *Luid = TokenStats->AuthenticationId;
+    }
 
-    /* Insert the Process */
-    CsrInsertProcess(NULL, CurrentProcess, CsrProcess);
+    /* Free the query information */
+    RtlFreeHeap(CsrHeap, 0, TokenStats);
 
-    /* Release lock and return */
-    CsrReleaseProcessLock();
+    /* Return the Status */
     return Status;
 }
 
 /*++
- * @name CsrUnlockProcess
- * @implemented NT4
- *
- * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
- *
- * @param CsrProcess
- *        Pointer to a previously locked CSR Process.
- *
- * @return STATUS_SUCCESS.
- *
- * @remarks This routine must be called with the Process Lock held.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
-{
-    /* Dereference the process */
-    CsrLockedDereferenceProcess(CsrProcess);
-
-    /* Release the lock and return */
-    CsrReleaseProcessLock();
-    return STATUS_SUCCESS;
-}
-
-/*++
- * @name CsrSetBackgroundPriority
+ * @name CsrImpersonateClient
  * @implemented NT4
  *
- * The CsrSetBackgroundPriority routine sets the priority for the given CSR
- * Process as a Background priority.
+ * The CsrImpersonateClient will impersonate the given CSR Thread.
  *
- * @param CsrProcess
- *        Pointer to the CSR Process whose priority will be modified.
+ * @param CsrThread
+ *        Pointer to the CSR Thread to impersonate.
  *
- * @return None.
+ * @return TRUE if impersonation succeeded, false otherwise.
  *
- * @remarks None.
+ * @remarks Impersonation can be recursive.
  *
  *--*/
-VOID
+BOOLEAN
 NTAPI
-CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess)
+CsrImpersonateClient(IN PCSR_THREAD CsrThread)
 {
-    PROCESS_PRIORITY_CLASS PriorityClass;
+    NTSTATUS Status;
+    PCSR_THREAD CurrentThread = CsrGetClientThread();
 
-    /* Set the Foreground bit off */
-    PriorityClass.Foreground = FALSE;
+    /* Use the current thread if none given */
+    if (!CsrThread) CsrThread = CurrentThread;
 
-    /* Set the new Priority */
-    NtSetInformationProcess(CsrProcess->ProcessHandle,
-                            ProcessPriorityClass,
-                            &PriorityClass,
-                            sizeof(PriorityClass));
+    /* 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 */
+/*
+        DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status);
+        if (Status != STATUS_BAD_IMPERSONATION_LEVEL) DbgBreakPoint();
+*/
+        return FALSE;
+    }
+
+    /* Increase the impersonation count for the current thread */
+    if (CurrentThread) ++CurrentThread->ImpersonationCount;
+
+    /* Return Success */
+    return TRUE;
 }
 
 /*++
@@ -1132,7 +1072,7 @@ CsrLockProcessByClientId(IN HANDLE Pid,
 {
     PLIST_ENTRY NextEntry;
     PCSR_PROCESS CurrentProcess = NULL;
-    NTSTATUS Status;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
 
     /* Acquire the lock */
     CsrAcquireProcessLock();
@@ -1155,7 +1095,7 @@ CsrLockProcessByClientId(IN HANDLE Pid,
             break;
         }
 
-        /* Next entry */
+        /* Move to the next entry */
         NextEntry = NextEntry->Flink;
     } while (NextEntry != &CsrRootProcess->ListLink);
 
@@ -1171,11 +1111,123 @@ CsrLockProcessByClientId(IN HANDLE Pid,
         CsrLockedReferenceProcess(CurrentProcess);
         *CsrProcess = CurrentProcess;
     }
-    
+
     /* Return the result */
     return Status;
 }
 
+/*++
+ * @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;
+    PCSR_THREAD CurrentThread = CsrGetClientThread();
+    HANDLE ImpersonationToken = NULL;
+
+    /* Check if we have a Current Thread */
+    if (CurrentThread)
+    {
+        /* Make sure impersonation is on */
+        if (!CurrentThread->ImpersonationCount)
+        {
+            // DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n");
+            // DbgBreakPoint();
+            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);
+}
+
+/*++
+ * @name CsrSetBackgroundPriority
+ * @implemented NT4
+ *
+ * The CsrSetBackgroundPriority routine sets the priority for the given CSR
+ * Process as a Background priority.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process whose priority will be modified.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess)
+{
+    PROCESS_PRIORITY_CLASS PriorityClass;
+
+    /* Set the Foreground bit off */
+    PriorityClass.Foreground = FALSE;
+
+    /* Set the new Priority */
+    NtSetInformationProcess(CsrProcess->ProcessHandle,
+                            ProcessPriorityClass,
+                            &PriorityClass,
+                            sizeof(PriorityClass));
+}
+
+/*++
+ * @name CsrSetForegroundPriority
+ * @implemented NT4
+ *
+ * The CsrSetForegroundPriority routine sets the priority for the given CSR
+ * Process as a Foreground priority.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process whose priority will be modified.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess)
+{
+    PROCESS_PRIORITY_CLASS PriorityClass;
+
+    /* Set the Foreground bit on */
+    PriorityClass.Foreground = TRUE;
+
+    /* Set the new Priority */
+    NtSetInformationProcess(CsrProcess->ProcessHandle,
+                            ProcessPriorityClass,
+                            &PriorityClass,
+                            sizeof(PriorityClass));
+}
+
 /*++
  * @name CsrShutdownProcesses
  * @implemented NT4
@@ -1222,16 +1274,16 @@ CsrShutdownProcesses(IN PLUID CallerLuid,
         /* Get the Process */
         CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
 
-        /* Remove the skip flag, set shutdown flags to 0*/
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Remove the skip flag, set shutdown flags to 0 */
         CsrProcess->Flags &= ~CsrProcessSkipShutdown;
         CsrProcess->ShutdownFlags = 0;
-
-        /* Move to the next */
-        NextEntry = NextEntry->Flink;
     }
 
     /* Set shudown Priority */
-    CsrpSetToShutdownPriority();
+    CsrSetToShutdownPriority();
 
     /* Start looping */
     while (TRUE)
@@ -1241,7 +1293,7 @@ CsrShutdownProcesses(IN PLUID CallerLuid,
         if (!CsrProcess) break;
 
         /* Increase reference to process */
-        CsrProcess->ReferenceCount++;
+        CsrLockedReferenceProcess(CsrProcess);
 
         FirstTry = TRUE;
         while (TRUE)
@@ -1251,7 +1303,9 @@ CsrShutdownProcesses(IN PLUID CallerLuid,
             {
                 /* Get the current server */
                 ServerDll = CsrLoadedServerDll[i];
-                if ((ServerDll) && (ServerDll->ShutdownProcessCallback))
+
+                /* Check if it's valid and if it has a Shutdown Process Callback */
+                if (ServerDll && ServerDll->ShutdownProcessCallback)
                 {
                     /* Release the lock, make the callback, and acquire it back */
                     CsrReleaseProcessLock();
@@ -1305,11 +1359,13 @@ CsrShutdownProcesses(IN PLUID CallerLuid,
 
 Quickie:
     /* Return to normal priority */
-    CsrpSetToNormalPriority();
+    CsrSetToNormalPriority();
+
     return Status;
 }
 
-/* FIXME: Temporary hack. This is really "CsrShutdownProcess", mostly. Used by win32csr */
+/* FIXME: Temporary hack. This is really "CsrShutdownProcess", mostly. Used by winsrv */
+#if 0
 NTSTATUS
 WINAPI
 CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc,
@@ -1333,12 +1389,12 @@ CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc,
         /* Get the Process */
         CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
 
-        /* Remove the skip flag, set shutdown flags to 0*/
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Remove the skip flag, set shutdown flags to 0 */
         CsrProcess->Flags &= ~CsrProcessSkipShutdown;
         CsrProcess->ShutdownFlags = 0;
-
-        /* Move to the next */
-        NextEntry = NextEntry->Flink;
     }
     
     /* Set shudown Priority */
@@ -1400,84 +1456,32 @@ Quickie:
     CsrSetToNormalPriority();
     return Status;
 }
+#endif
 
 /*++
- * @name CsrDebugProcess
- * @implemented NT4
- *
- * The CsrDebugProcess routine is deprecated in NT 5.1 and higher. It is
- * exported only for compatibility with older CSR Server DLLs.
- *
- * @param CsrProcess
- *        Deprecated.
- *
- * @return Deprecated
- *
- * @remarks Deprecated.
- *
- *--*/
-NTSTATUS
-NTAPI
-CsrDebugProcess(IN PCSR_PROCESS CsrProcess)
-{
-    /* CSR does not handle debugging anymore */
-    DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
-    return STATUS_UNSUCCESSFUL;
-}
-
-/*++
- * @name CsrDebugProcessStop
+ * @name CsrUnlockProcess
  * @implemented NT4
  *
- * The CsrDebugProcessStop routine is deprecated in NT 5.1 and higher. It is
- * exported only for compatibility with older CSR Server DLLs.
+ * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
  *
  * @param CsrProcess
- *        Deprecated.
+ *        Pointer to a previously locked CSR Process.
  *
- * @return Deprecated
+ * @return STATUS_SUCCESS.
  *
- * @remarks Deprecated.
+ * @remarks This routine must be called with the Process Lock held.
  *
  *--*/
 NTSTATUS
 NTAPI
-CsrDebugProcessStop(IN PCSR_PROCESS CsrProcess)
-{
-    /* CSR does not handle debugging anymore */
-    DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
-    return STATUS_UNSUCCESSFUL;
-}
-
-/*++
- * @name CsrSetForegroundPriority
- * @implemented NT4
- *
- * The CsrSetForegroundPriority routine sets the priority for the given CSR
- * Process as a Foreground priority.
- *
- * @param CsrProcess
- *        Pointer to the CSR Process whose priority will be modified.
- *
- * @return None.
- *
- * @remarks None.
- *
- *--*/
-VOID
-NTAPI
-CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess)
+CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
 {
-    PROCESS_PRIORITY_CLASS PriorityClass;
-
-    /* Set the Foreground bit on */
-    PriorityClass.Foreground = TRUE;
+    /* Dereference the process */
+    CsrLockedDereferenceProcess(CsrProcess);
 
-    /* Set the new Priority */
-    NtSetInformationProcess(CsrProcess->ProcessHandle,
-                            ProcessPriorityClass,
-                            &PriorityClass,
-                            sizeof(PriorityClass));
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
 /* EOF */