[REACTOS]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 15 Apr 2013 19:46:07 +0000 (19:46 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 15 Apr 2013 19:46:07 +0000 (19:46 +0000)
Here is all the deprecated code: the old CSR as well as the new one which wasn't included; the ReactOS-specific win32csr and the csr module of win32k.

svn path=/trunk/; revision=58771

80 files changed:
reactos/deprecated/csr.c [new file with mode: 0644]
reactos/deprecated/csr.h [new file with mode: 0644]
reactos/deprecated/csr/CMakeLists.txt [new file with mode: 0644]
reactos/deprecated/csr/csr.rc [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/CMakeLists.txt [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/api.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/csrsrv.rc [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/csrsrv2.spec [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/init.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/process.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/server.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/session.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/srv.h [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/status.h [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/thread.c [new file with mode: 0644]
reactos/deprecated/csr/csrsrv/wait.c [new file with mode: 0644]
reactos/deprecated/csr/main.c [new file with mode: 0644]
reactos/deprecated/csrsrv/CMakeLists.txt [new file with mode: 0644]
reactos/deprecated/csrsrv/api/process.c [new file with mode: 0644]
reactos/deprecated/csrsrv/api/user.c [new file with mode: 0644]
reactos/deprecated/csrsrv/api/wapi.c [new file with mode: 0644]
reactos/deprecated/csrsrv/csrsrv.rc [new file with mode: 0644]
reactos/deprecated/csrsrv/csrsrv.spec [new file with mode: 0644]
reactos/deprecated/csrsrv/include/api.h [new file with mode: 0644]
reactos/deprecated/csrsrv/include/csrplugin.h [new file with mode: 0644]
reactos/deprecated/csrsrv/init.c [new file with mode: 0644]
reactos/deprecated/csrsrv/procsup.c [new file with mode: 0644]
reactos/deprecated/csrsrv/server.c [new file with mode: 0644]
reactos/deprecated/csrsrv/session.c [new file with mode: 0644]
reactos/deprecated/csrsrv/srv.h [new file with mode: 0644]
reactos/deprecated/csrsrv/thredsup.c [new file with mode: 0644]
reactos/deprecated/csrsrv/wait.c [new file with mode: 0644]
reactos/deprecated/win32csr/CMakeLists.txt [new file with mode: 0644]
reactos/deprecated/win32csr/alias.c [new file with mode: 0644]
reactos/deprecated/win32csr/coninput.c [new file with mode: 0644]
reactos/deprecated/win32csr/conio.h [new file with mode: 0644]
reactos/deprecated/win32csr/conoutput.c [new file with mode: 0644]
reactos/deprecated/win32csr/console.c [new file with mode: 0644]
reactos/deprecated/win32csr/desktopbg.c [new file with mode: 0644]
reactos/deprecated/win32csr/desktopbg.h [new file with mode: 0644]
reactos/deprecated/win32csr/dllmain.c [new file with mode: 0644]
reactos/deprecated/win32csr/exitros.c [new file with mode: 0644]
reactos/deprecated/win32csr/file.c [new file with mode: 0644]
reactos/deprecated/win32csr/file.h [new file with mode: 0644]
reactos/deprecated/win32csr/guiconsole.c [new file with mode: 0644]
reactos/deprecated/win32csr/guiconsole.h [new file with mode: 0644]
reactos/deprecated/win32csr/handle.c [new file with mode: 0644]
reactos/deprecated/win32csr/harderror.c [new file with mode: 0644]
reactos/deprecated/win32csr/lang/bg-BG.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/cs-CZ.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/de-DE.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/el-GR.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/en-US.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/es-ES.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/fr-FR.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/he-IL.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/id-ID.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/it-IT.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/ja-JP.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/no-NO.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/pl-PL.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/pt-BR.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/ro-RO.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/ru-RU.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/sk-SK.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/sv-SE.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/tr-TR.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/uk-UA.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/zh-CN.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lang/zh-TW.rc [new file with mode: 0644]
reactos/deprecated/win32csr/lineinput.c [new file with mode: 0644]
reactos/deprecated/win32csr/res/terminal.ico [new file with mode: 0644]
reactos/deprecated/win32csr/resource.h [new file with mode: 0644]
reactos/deprecated/win32csr/rsrc.rc [new file with mode: 0644]
reactos/deprecated/win32csr/tuiconsole.c [new file with mode: 0644]
reactos/deprecated/win32csr/tuiconsole.h [new file with mode: 0644]
reactos/deprecated/win32csr/w32csr.h [new file with mode: 0644]
reactos/deprecated/win32csr/win32csr.h [new file with mode: 0644]
reactos/deprecated/win32csr/win32csr.rc [new file with mode: 0644]
reactos/deprecated/win32csr/win32csr.spec [new file with mode: 0644]

diff --git a/reactos/deprecated/csr.c b/reactos/deprecated/csr.c
new file mode 100644 (file)
index 0000000..2b622e8
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          Interface to csrss
+ * FILE:             subsys/win32k/ntuser/csr.c
+ * PROGRAMER:        Ge van Geldorp (ge@gse.nl)
+ */
+
+#include <win32k.h>
+
+static HANDLE WindowsApiPort = NULL;
+PEPROCESS CsrProcess = NULL;
+
+NTSTATUS FASTCALL
+CsrInit(void)
+{
+   NTSTATUS Status;
+   UNICODE_STRING PortName;
+   ULONG ConnectInfoLength;
+   SECURITY_QUALITY_OF_SERVICE Qos;   
+
+   RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort");
+   ConnectInfoLength = 0;
+   Qos.Length = sizeof(Qos);
+   Qos.ImpersonationLevel = SecurityDelegation;
+   Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
+   Qos.EffectiveOnly = FALSE;
+
+   Status = ZwConnectPort(&WindowsApiPort,
+                          &PortName,
+                          &Qos,
+                          NULL,
+                          NULL,
+                          NULL,
+                          NULL,
+                          &ConnectInfoLength);
+   if (! NT_SUCCESS(Status))
+   {
+      return Status;
+   }
+
+   CsrProcess = PsGetCurrentProcess();
+
+   return STATUS_SUCCESS;
+}
+
+
+NTSTATUS FASTCALL
+co_CsrNotify(PCSR_API_MESSAGE Request)
+{
+   NTSTATUS Status;
+   PEPROCESS OldProcess;
+
+   if (NULL == CsrProcess)
+   {
+      return STATUS_INVALID_PORT_HANDLE;
+   }
+
+   Request->Header.u2.ZeroInit = 0;
+   Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
+   Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+
+   /* Switch to the process in which the WindowsApiPort handle is valid */
+   OldProcess = PsGetCurrentProcess();
+   if (CsrProcess != OldProcess)
+   {
+      KeAttachProcess(&CsrProcess->Pcb);
+   }
+
+   UserLeaveCo();
+
+   Status = ZwRequestWaitReplyPort(WindowsApiPort,
+                                   &Request->Header,
+                                   &Request->Header);
+
+   UserEnterCo();
+
+   if (CsrProcess != OldProcess)
+   {
+      KeDetachProcess();
+   }
+
+   if (NT_SUCCESS(Status))
+   {
+      Status = Request->Status;
+   }
+
+   return Status;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr.h b/reactos/deprecated/csr.h
new file mode 100644 (file)
index 0000000..5256c03
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          Interface to csrss
+ * FILE:             subsys/win32k/include/csr.h
+ * PROGRAMER:        Ge van Geldorp (ge@gse.nl)
+ */
+
+#pragma once
+
+extern PEPROCESS CsrProcess;
+
+NTSTATUS FASTCALL CsrInit(void);
+NTSTATUS FASTCALL co_CsrNotify(PCSR_API_MESSAGE Request);
+NTSTATUS FASTCALL CsrCloseHandle(HANDLE Handle);
+NTSTATUS WINAPI CsrInsertObject(HANDLE ObjectHandle,
+                                 ACCESS_MASK DesiredAccess,
+                                 PHANDLE Handle);
+
+/* EOF */
diff --git a/reactos/deprecated/csr/CMakeLists.txt b/reactos/deprecated/csr/CMakeLists.txt
new file mode 100644 (file)
index 0000000..29ccac1
--- /dev/null
@@ -0,0 +1,16 @@
+
+include_directories(
+    include
+    ${REACTOS_SOURCE_DIR}/include/reactos/subsys
+    ${REACTOS_SOURCE_DIR}/include/reactos/drivers)
+
+add_executable(csrss2 main.c csr.rc)
+
+set_module_type(csrss2 nativecui)
+target_link_libraries(csrss2 nt)
+add_importlibs(csrss2 ntdll csrsrv2)
+add_dependencies(csrss2 psdk bugcodes)
+add_cd_file(TARGET csrss2 DESTINATION reactos/system32 FOR all)
+
+add_subdirectory(csrsrv)
+
diff --git a/reactos/deprecated/csr/csr.rc b/reactos/deprecated/csr/csr.rc
new file mode 100644 (file)
index 0000000..c5d32a1
--- /dev/null
@@ -0,0 +1,4 @@
+#define REACTOS_STR_FILE_DESCRIPTION   "Client/Server Runtime Process\0"
+#define REACTOS_STR_INTERNAL_NAME      "csrss\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "csrss.exe\0"
+#include <reactos/version.rc>
diff --git a/reactos/deprecated/csr/csrsrv/CMakeLists.txt b/reactos/deprecated/csr/csrsrv/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8c48af5
--- /dev/null
@@ -0,0 +1,30 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/subsystems/win32/csrss/include)
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
+
+spec2def(csrsrv2.dll csrsrv2.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+     api.c
+     init.c
+     process.c
+     server.c
+     session.c
+     thread.c
+     wait.c
+     csrsrv.rc
+     ${CMAKE_CURRENT_BINARY_DIR}/csrsrv2.def)
+
+add_library(csrsrv2 SHARED ${SOURCE})
+
+target_link_libraries(csrsrv2 ${PSEH_LIB} smlib)
+
+set_module_type(csrsrv2 nativedll)
+
+add_importlibs(csrsrv2 ntdll)
+
+add_pch(csrsrv2 srv.h)
+
+add_dependencies(csrsrv2 psdk bugcodes)
+add_cd_file(TARGET csrsrv2 DESTINATION reactos/system32 FOR all)
+
diff --git a/reactos/deprecated/csr/csrsrv/api.c b/reactos/deprecated/csr/csrsrv/api.c
new file mode 100644 (file)
index 0000000..e725709
--- /dev/null
@@ -0,0 +1,1650 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/api.c
+ * PURPOSE:         CSR Server DLL API LPC Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;
+ULONG CsrMaxApiRequestThreads;
+UNICODE_STRING CsrSbApiPortName;
+UNICODE_STRING CsrApiPortName;
+HANDLE CsrSbApiPort;
+HANDLE CsrApiPort;
+PCSR_THREAD CsrSbApiRequestThreadPtr;
+volatile LONG CsrpStaticThreadCount;
+volatile LONG CsrpDynamicThreadTotal;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrpCheckRequestThreads
+ *
+ * The CsrpCheckRequestThreads routine checks if there are no more threads
+ * to handle CSR API Requests, and creates a new thread if possible, to
+ * avoid starvation.
+ *
+ * @param None.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         if a new thread couldn't be created.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrpCheckRequestThreads(VOID)
+{
+    HANDLE hThread;
+    CLIENT_ID ClientId;
+    NTSTATUS Status;
+
+    /* Decrease the count, and see if we're out */
+    if (!(_InterlockedDecrement(&CsrpStaticThreadCount)))
+    {
+        /* Check if we've still got space for a Dynamic Thread */
+        if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
+        {
+            /* Create a new dynamic thread */
+            Status = RtlCreateUserThread(NtCurrentProcess(),
+                                         NULL,
+                                         TRUE,
+                                         0,
+                                         0,
+                                         0,
+                                         (PVOID)CsrApiRequestThread,
+                                         NULL,
+                                         &hThread,
+                                         &ClientId);
+            /* Check success */
+            if (NT_SUCCESS(Status))
+            {
+                /* Increase the thread counts */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+                _InterlockedIncrement(&CsrpDynamicThreadTotal);
+
+                /* Add a new server thread */
+                if (CsrAddStaticServerThread(hThread,
+                                             &ClientId,
+                                             CsrThreadIsServerThread))
+                {
+                    /* Activate it */
+                    NtResumeThread(hThread,NULL);
+                }
+                else
+                {
+                    /* Failed to create a new static thread */
+                    _InterlockedDecrement(&CsrpStaticThreadCount);
+                    _InterlockedDecrement(&CsrpDynamicThreadTotal);
+
+                    /* Terminate it */
+                    NtTerminateThread(hThread,0);
+                    NtClose(hThread);
+
+                    /* Return */
+                    return STATUS_UNSUCCESSFUL;
+                }
+            }
+        }
+    }
+
+    /* Success */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSbApiPortInitialize
+ *
+ * The CsrSbApiPortInitialize routine initializes the LPC Port used for
+ * communications with the Session Manager (SM) and initializes the static
+ * thread that will handle connection requests and APIs.
+ *
+ * @param None
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSbApiPortInitialize(VOID)
+{
+    ULONG Size;
+    PSECURITY_DESCRIPTOR PortSd;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE hRequestThread;
+    CLIENT_ID ClientId;
+
+    /* Calculate how much space we'll need for the Port Name */
+    Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR);
+
+    /* Create the buffer for it */
+    CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
+    if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY;
+
+    /* Setup the rest of the empty string */
+    CsrSbApiPortName.Length = 0;
+    CsrSbApiPortName.MaximumLength = (USHORT)Size;
+
+    /* Now append the full port name */
+    RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName);
+    RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP);
+    RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME);
+    if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName);
+
+    /* Create Security Descriptor for this Port */
+    Status = CsrCreateLocalSystemSD(&PortSd);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Initialize the Attributes */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &CsrSbApiPortName,
+                               0,
+                               NULL,
+                               PortSd);
+
+    /* Create the Port Object */
+    Status = NtCreatePort(&CsrSbApiPort,
+                          &ObjectAttributes,
+                          sizeof(SB_CONNECTION_INFO),
+                          sizeof(SB_API_MSG),
+                          32 * sizeof(SB_API_MSG));
+    if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd);
+
+    if (NT_SUCCESS(Status))
+    {
+        /* Create the Thread to handle the API Requests */
+        Status = RtlCreateUserThread(NtCurrentProcess(),
+                                     NULL,
+                                     TRUE,
+                                     0,
+                                     0,
+                                     0,
+                                     (PVOID)CsrSbApiRequestThread,
+                                     NULL,
+                                     &hRequestThread,
+                                     &ClientId);
+        if (NT_SUCCESS(Status))
+        {
+            /* Add it as a Static Server Thread */
+            CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread,
+                                                                &ClientId,
+                                                                0);
+
+            /* Activate it */
+            Status = NtResumeThread(hRequestThread, NULL);
+        }
+    }
+
+    return Status;
+}
+
+/*++
+ * @name CsrApiPortInitialize
+ *
+ * The CsrApiPortInitialize routine initializes the LPC Port used for
+ * communications with the Client/Server Runtime (CSR) and initializes the
+ * static thread that will handle connection requests and APIs.
+ *
+ * @param None
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrApiPortInitialize(VOID)
+{
+    ULONG Size;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE hRequestEvent, hThread;
+    CLIENT_ID ClientId;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD ServerThread;
+
+    /* Calculate how much space we'll need for the Port Name */
+    Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
+
+    /* Create the buffer for it */
+    CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
+    if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY;
+
+    /* Setup the rest of the empty string */
+    CsrApiPortName.Length = 0;
+    CsrApiPortName.MaximumLength = (USHORT)Size;
+    RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);
+    RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);
+    RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);
+    if (CsrDebug & 1)
+    {
+        DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
+        DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld  sizeof( API_MSG ) == %ld\n",
+                sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE));
+    }
+
+    /* FIXME: Create a Security Descriptor */
+
+    /* Initialize the Attributes */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &CsrApiPortName,
+                               0,
+                               NULL,
+                               NULL /* FIXME*/);
+
+    /* Create the Port Object */
+    Status = NtCreatePort(&CsrApiPort,
+                          &ObjectAttributes,
+                          sizeof(CSR_CONNECTION_INFO),
+                          sizeof(CSR_API_MESSAGE),
+                          16 * PAGE_SIZE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Create the event the Port Thread will use */
+        Status = NtCreateEvent(&hRequestEvent,
+                               EVENT_ALL_ACCESS,
+                               NULL,
+                               SynchronizationEvent,
+                               FALSE);
+        if (NT_SUCCESS(Status))
+        {
+            /* Create the Request Thread */
+            Status = RtlCreateUserThread(NtCurrentProcess(),
+                                         NULL,
+                                         TRUE,
+                                         0,
+                                         0,
+                                         0,
+                                         (PVOID)CsrApiRequestThread,
+                                         (PVOID)hRequestEvent,
+                                         &hThread,
+                                         &ClientId);
+            if (NT_SUCCESS(Status))
+            {
+                /* Add this as a static thread to CSRSRV */
+                CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread);
+
+                /* Get the Thread List Pointers */
+                ListHead = &CsrRootProcess->ThreadList;
+                NextEntry = ListHead->Flink;
+
+                /* Start looping the list */
+                while (NextEntry != ListHead)
+                {
+                    /* Get the Thread */
+                    ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+                    /* Start it up */
+                    Status = NtResumeThread(ServerThread->ThreadHandle, NULL);
+
+                    /* Is this a Server Thread? */
+                    if (ServerThread->Flags & CsrThreadIsServerThread)
+                    {
+                        /* If so, then wait for it to initialize */
+                        Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
+                        ASSERT(NT_SUCCESS(Status));
+                    }
+
+                    /* Next thread */
+                    NextEntry = NextEntry->Flink;
+                }
+
+                /* We don't need this anymore */
+                NtClose(hRequestEvent);
+            }
+        }
+    }
+
+    /* Return */
+    return Status;
+}
+
+/*++
+ * @name CsrApiRequestThread
+ *
+ * The CsrApiRequestThread routine handles incoming messages or connection
+ * requests on the CSR API LPC Port.
+ *
+ * @param Parameter
+ *        System-default user-defined parameter. Unused.
+ *
+ * @return The thread exit code, if the thread is terminated.
+ *
+ * @remarks Before listening on the port, the routine will first attempt
+ *          to connect to the user subsystem.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrApiRequestThread(IN PVOID Parameter)
+{
+    PTEB Teb = NtCurrentTeb();
+    LARGE_INTEGER TimeOut;
+    PCSR_THREAD CurrentThread, CsrThread;
+    NTSTATUS Status;
+    PCSR_API_MESSAGE ReplyMsg;
+    CSR_API_MESSAGE ReceiveMsg;
+    PCSR_PROCESS CsrProcess;
+    PHARDERROR_MSG HardErrorMsg;
+    PVOID PortContext;
+    PCSR_SERVER_DLL ServerDll;
+    PCLIENT_DIED_MSG ClientDiedMsg;
+    PDBGKM_MSG DebugMessage;
+    ULONG ServerId, ApiId, Reply, MessageType, i;
+    HANDLE ReplyPort;
+
+    /* Setup LPC loop port and message */
+    ReplyMsg = NULL;
+    ReplyPort = CsrApiPort;
+
+    /* Connect to user32 */
+    while (!CsrConnectToUser())
+    {
+        /* Set up the timeout for the connect (30 seconds) */
+        TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
+
+        /* Keep trying until we get a response */
+        Teb->Win32ClientInfo[0] = 0;
+        NtDelayExecution(FALSE, &TimeOut);
+    }
+
+    /* Get our thread */
+    CurrentThread = Teb->CsrClientThread;
+
+    /* If we got an event... */
+    if (Parameter)
+    {
+        /* Set it, to let stuff waiting on us load */
+        Status = NtSetEvent((HANDLE)Parameter, NULL);
+        ASSERT(NT_SUCCESS(Status));
+
+        /* Increase the Thread Counts */
+        _InterlockedIncrement(&CsrpStaticThreadCount);
+        _InterlockedIncrement(&CsrpDynamicThreadTotal);
+    }
+
+    /* Now start the loop */
+    while (TRUE)
+    {
+        /* Make sure the real CID is set */
+        Teb->RealClientId = Teb->ClientId;
+
+        /* Debug check */
+        if (Teb->CountOfOwnedCriticalSections)
+        {
+            DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
+                    Teb->CountOfOwnedCriticalSections);
+            DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
+                    &ReceiveMsg, ReplyMsg);
+            DbgBreakPoint();
+        }
+
+        /* Wait for a message to come through */
+        Status = NtReplyWaitReceivePort(ReplyPort,
+                                        &PortContext,
+                                        &ReplyMsg->Header,
+                                        &ReceiveMsg.Header);
+
+        /* Check if we didn't get success */
+        if (Status != STATUS_SUCCESS)
+        {
+            /* Was it a failure or another success code? */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Check for specific status cases */
+                if ((Status != STATUS_INVALID_CID) &&
+                    (Status != STATUS_UNSUCCESSFUL) &&
+                    ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
+                {
+                    /* Notify the debugger */
+                    DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
+                    DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
+                }
+
+                /* We failed big time, so start out fresh */
+                ReplyMsg = NULL;
+                ReplyPort = CsrApiPort;
+                continue;
+            }
+            else
+            {
+                /* A bizare "success" code, just try again */
+                DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
+                continue;
+            }
+        }
+
+        /* Use whatever Client ID we got */
+        Teb->RealClientId = ReceiveMsg.Header.ClientId;
+
+        /* Get the Message Type */
+        MessageType = ReceiveMsg.Header.u2.s2.Type;
+
+        /* Handle connection requests */
+        if (MessageType == LPC_CONNECTION_REQUEST)
+        {
+            /* Handle the Connection Request */
+            CsrApiHandleConnectionRequest(&ReceiveMsg);
+            ReplyPort = CsrApiPort;
+            ReplyMsg = NULL;
+            continue;
+        }
+
+        /* It's some other kind of request. Get the lock for the lookup */
+        CsrAcquireProcessLock();
+
+        /* Now do the lookup to get the CSR_THREAD */
+        CsrThread = CsrLocateThreadByClientId(&CsrProcess,
+                                              &ReceiveMsg.Header.ClientId);
+
+        /* Did we find a thread? */
+        if (!CsrThread)
+        {
+            /* This wasn't a CSR Thread, release lock */
+            CsrReleaseProcessLock();
+
+            /* If this was an exception, handle it */
+            if (MessageType == LPC_EXCEPTION)
+            {
+                ReplyMsg = &ReceiveMsg;
+                ReplyPort = CsrApiPort;
+                ReplyMsg->Status = DBG_CONTINUE;
+            }
+            else if (MessageType == LPC_PORT_CLOSED ||
+                     MessageType == LPC_CLIENT_DIED)
+            {
+                /* The Client or Port are gone, loop again */
+                ReplyMsg = NULL;
+                ReplyPort = CsrApiPort;
+            }
+            else if (MessageType == LPC_ERROR_EVENT)
+            {
+                /* If it's a hard error, handle this too */
+                HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
+
+                /* Default it to unhandled */
+                HardErrorMsg->Response = ResponseNotHandled;
+
+                /* Check if there are free api threads */
+                CsrpCheckRequestThreads();
+                if (CsrpStaticThreadCount)
+                {
+                    /* Loop every Server DLL */
+                    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+                    {
+                        /* Get the Server DLL */
+                        ServerDll = CsrLoadedServerDll[i];
+
+                        /* Check if it's valid and if it has a Hard Error Callback */
+                        if ((ServerDll) && (ServerDll->HardErrorCallback))
+                        {
+                            /* Call it */
+                            ServerDll->HardErrorCallback(NULL, HardErrorMsg);
+
+                            /* If it's handled, get out of here */
+                            if (HardErrorMsg->Response != ResponseNotHandled) break;
+                        }
+                    }
+                }
+
+                /* Increase the thread count */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+
+                /* If the response was 0xFFFFFFFF, we'll ignore it */
+                if (HardErrorMsg->Response == 0xFFFFFFFF)
+                {
+                    ReplyMsg = NULL;
+                    ReplyPort = CsrApiPort;
+                }
+                else
+                {
+                    ReplyMsg = &ReceiveMsg;
+                }
+            }
+            else if (MessageType == LPC_REQUEST)
+            {
+                /* This is an API Message coming from a non-CSR Thread */
+                ReplyMsg = &ReceiveMsg;
+                ReplyPort = CsrApiPort;
+                ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
+            }
+            else if (MessageType == LPC_DATAGRAM)
+            {
+                /* This is an API call, get the Server ID */
+                ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode);
+
+                /* Make sure that the ID is within limits, and the Server DLL loaded */
+                ServerDll = NULL;
+                if ((ServerId >= CSR_SERVER_DLL_MAX) ||
+                    (!(ServerDll = CsrLoadedServerDll[ServerId])))
+                {
+                    /* We are beyond the Maximum Server ID */
+                    DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
+                            ServerId, ServerDll);
+                    DbgBreakPoint();
+                    ReplyPort = CsrApiPort;
+                    ReplyMsg = NULL;
+                    continue;
+                }
+
+                   /* Get the API ID */
+                ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode);
+
+                /* Normalize it with our Base ID */
+                ApiId -= ServerDll->ApiBase;
+
+                /* Make sure that the ID is within limits, and the entry exists */
+                if (ApiId >= ServerDll->HighestApiSupported)
+                {
+                    /* We are beyond the Maximum API ID, or it doesn't exist */
+                    DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
+                            CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode),
+                            &ServerDll->Name);
+                    ReplyPort = CsrApiPort;
+                    ReplyMsg = NULL;
+                    continue;
+                }
+
+                if (CsrDebug & 2)
+                {
+                    DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
+                            Teb->ClientId.UniqueThread,
+                            ReceiveMsg.Header.ClientId.UniqueProcess,
+                            ReceiveMsg.Header.ClientId.UniqueThread,
+                            ServerDll->NameTable[ApiId],
+                            NULL);
+                }
+
+                /* Assume success */
+                ReceiveMsg.Status = STATUS_SUCCESS;
+
+                /* Validation complete, start SEH */
+                _SEH2_TRY
+                {
+                    /* Make sure we have enough threads */
+                    CsrpCheckRequestThreads();
+
+                    /* Call the API and get the result */
+                    ReplyMsg = NULL;
+                    ReplyPort = CsrApiPort;
+                    ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
+
+                    /* Increase the static thread count */
+                    _InterlockedIncrement(&CsrpStaticThreadCount);
+                }
+                _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+                {
+                    ReplyMsg = NULL;
+                    ReplyPort = CsrApiPort;
+                }
+                _SEH2_END;
+            }
+            else
+            {
+                /* Some other ignored message type */
+                ReplyMsg = NULL;
+                ReplyPort = CsrApiPort;
+            }
+
+            /* Keep going */
+            continue;
+        }
+
+        /* We have a valid thread, was this an LPC Request? */
+        if (MessageType != LPC_REQUEST)
+        {
+            /* It's not an API, check if the client died */
+            if (MessageType == LPC_CLIENT_DIED)
+            {
+                /* Get the information and check if it matches our thread */
+                ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;
+                if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
+                {
+                    /* Reference the thread */
+                    CsrLockedReferenceThread(CsrThread);
+
+                    /* Destroy the thread in the API Message */
+                    CsrDestroyThread(&ReceiveMsg.Header.ClientId);
+
+                    /* Check if the thread was actually ourselves */
+                    if (CsrProcess->ThreadCount == 1)
+                    {
+                        /* Kill the process manually here */
+                        CsrDestroyProcess(&CsrThread->ClientId, 0);
+                    }
+
+                    /* Remove our extra reference */
+                    CsrLockedDereferenceThread(CsrThread);
+                }
+
+                /* Release the lock and keep looping */
+                CsrReleaseProcessLock();
+                ReplyMsg = NULL;
+                ReplyPort = CsrApiPort;
+                continue;
+            }
+
+            /* Reference the thread and release the lock */
+            CsrLockedReferenceThread(CsrThread);
+            CsrReleaseProcessLock();
+
+            /* Check if this was an exception */
+            if (MessageType == LPC_EXCEPTION)
+            {
+                /* Kill the process */
+                NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
+
+                /* Destroy it from CSR */
+                CsrDestroyProcess(&ReceiveMsg.Header.ClientId, STATUS_ABANDONED);
+
+                /* Return a Debug Message */
+                DebugMessage = (PDBGKM_MSG)&ReceiveMsg;
+                DebugMessage->ReturnedStatus = DBG_CONTINUE;
+                ReplyMsg = &ReceiveMsg;
+                ReplyPort = CsrApiPort;
+
+                /* Remove our extra reference */
+                CsrDereferenceThread(CsrThread);
+            }
+            else if (MessageType == LPC_ERROR_EVENT)
+            {
+                /* If it's a hard error, handle this too */
+                HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;
+
+                /* Default it to unhandled */
+                HardErrorMsg->Response = ResponseNotHandled;
+
+                /* Check if there are free api threads */
+                CsrpCheckRequestThreads();
+                if (CsrpStaticThreadCount)
+                {
+                    /* Loop every Server DLL */
+                    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+                    {
+                        /* Get the Server DLL */
+                        ServerDll = CsrLoadedServerDll[i];
+
+                        /* Check if it's valid and if it has a Hard Error Callback */
+                        if ((ServerDll) && (ServerDll->HardErrorCallback))
+                        {
+                            /* Call it */
+                            ServerDll->HardErrorCallback(CsrThread, HardErrorMsg);
+
+                            /* If it's handled, get out of here */
+                            if (HardErrorMsg->Response != ResponseNotHandled) break;
+                        }
+                    }
+                }
+
+                /* Increase the thread count */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+
+                /* If the response was 0xFFFFFFFF, we'll ignore it */
+                if (HardErrorMsg->Response == 0xFFFFFFFF)
+                {
+                    ReplyMsg = NULL;
+                    ReplyPort = CsrApiPort;
+                }
+                else
+                {
+                    CsrDereferenceThread(CsrThread);
+                    ReplyMsg = &ReceiveMsg;
+                    ReplyPort = CsrApiPort;
+                }
+            }
+            else
+            {
+                /* Something else */
+                CsrDereferenceThread(CsrThread);
+                ReplyMsg = NULL;
+            }
+
+            /* Keep looping */
+            continue;
+        }
+
+        /* We got an API Request */
+        CsrLockedReferenceThread(CsrThread);
+        CsrReleaseProcessLock();
+
+        /* This is an API call, get the Server ID */
+        ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode);
+
+        /* Make sure that the ID is within limits, and the Server DLL loaded */
+        ServerDll = NULL;
+        if ((ServerId >= CSR_SERVER_DLL_MAX) ||
+            (!(ServerDll = CsrLoadedServerDll[ServerId])))
+        {
+            /* We are beyond the Maximum Server ID */
+            DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
+                    ServerId, ServerDll);
+            DbgBreakPoint();
+
+            ReplyPort = CsrApiPort;
+            ReplyMsg = &ReceiveMsg;
+            ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
+            CsrDereferenceThread(CsrThread);
+            continue;
+        }
+
+        /* Get the API ID */
+        ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode);
+
+        /* Normalize it with our Base ID */
+        ApiId -= ServerDll->ApiBase;
+
+        /* Make sure that the ID is within limits, and the entry exists */
+        if (ApiId >= ServerDll->HighestApiSupported)
+        {
+            /* We are beyond the Maximum API ID, or it doesn't exist */
+            DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
+                    CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode),
+                    &ServerDll->Name);
+
+            ReplyPort = CsrApiPort;
+            ReplyMsg = &ReceiveMsg;
+            ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
+            CsrDereferenceThread(CsrThread);
+            continue;
+        }
+
+        if (CsrDebug & 2)
+        {
+            DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
+                    Teb->ClientId.UniqueThread,
+                    ReceiveMsg.Header.ClientId.UniqueProcess,
+                    ReceiveMsg.Header.ClientId.UniqueThread,
+                    ServerDll->NameTable[ApiId],
+                    CsrThread);
+        }
+
+        /* Assume success */
+        ReplyMsg = &ReceiveMsg;
+        ReceiveMsg.Status = STATUS_SUCCESS;
+
+        /* Now we reply to a particular client */
+        ReplyPort = CsrThread->Process->ClientPort;
+
+        /* Check if there's a capture buffer */
+        if (ReceiveMsg.CsrCaptureData)
+        {
+            /* Capture the arguments */
+            if (!CsrCaptureArguments(CsrThread, &ReceiveMsg))
+            {
+                /* Ignore this message if we failed to get the arguments */
+                CsrDereferenceThread(CsrThread);
+                continue;
+            }
+        }
+
+        /* Validation complete, start SEH */
+        _SEH2_TRY
+        {
+            /* Make sure we have enough threads */
+            CsrpCheckRequestThreads();
+
+            Teb->CsrClientThread = CsrThread;
+
+            /* Call the API and get the result */
+            Reply = 0;
+            ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
+
+            /* Increase the static thread count */
+            _InterlockedIncrement(&CsrpStaticThreadCount);
+
+            Teb->CsrClientThread = CurrentThread;
+
+            if (Reply == 3)
+            {
+                ReplyMsg = NULL;
+                if (ReceiveMsg.CsrCaptureData)
+                {
+                    CsrReleaseCapturedArguments(&ReceiveMsg);
+                }
+                CsrDereferenceThread(CsrThread);
+                ReplyPort = CsrApiPort;
+            }
+            else if (Reply == 2)
+            {
+                NtReplyPort(ReplyPort, &ReplyMsg->Header);
+                ReplyPort = CsrApiPort;
+                ReplyMsg = NULL;
+                CsrDereferenceThread(CsrThread);
+            }
+            else if (Reply == 1)
+            {
+                ReplyPort = CsrApiPort;
+                ReplyMsg = NULL;
+            }
+            else
+            {
+                if (ReceiveMsg.CsrCaptureData)
+                {
+                    CsrReleaseCapturedArguments(&ReceiveMsg);
+                }
+                CsrDereferenceThread(CsrThread);
+            }
+        }
+        _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+        {
+            ReplyMsg = NULL;
+            ReplyPort = CsrApiPort;
+        }
+        _SEH2_END;
+    }
+
+    /* We're out of the loop for some reason, terminate! */
+    NtTerminateThread(NtCurrentThread(), Status);
+    return Status;
+}
+
+/*++
+ * @name CsrApiHandleConnectionRequest
+ *
+ * The CsrApiHandleConnectionRequest routine handles and accepts a new
+ * connection request to the CSR API LPC Port.
+ *
+ * @param ApiMessage
+ *        Pointer to the incoming CSR API Message which contains the
+ *        connection request.
+ *
+ * @return STATUS_SUCCESS in case of success, or status code which caused
+ *         the routine to error.
+ *
+ * @remarks This routine is responsible for attaching the Shared Section to
+ *          new clients connecting to CSR.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
+{
+    PCSR_THREAD CsrThread = NULL;
+    PCSR_PROCESS CsrProcess = NULL;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PCSR_CONNECTION_INFO ConnectInfo = &ApiMessage->ConnectionInfo;
+    BOOLEAN AllowConnection = FALSE;
+    REMOTE_PORT_VIEW RemotePortView;
+    HANDLE hPort;
+
+    /* Acquire the Process Lock */
+    CsrAcquireProcessLock();
+
+    /* Lookup the CSR Thread */
+    CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);
+
+    /* Check if we have a thread */
+    if (CsrThread)
+    {
+        /* Get the Process */
+        CsrProcess = CsrThread->Process;
+
+        /* Make sure we have a Process as well */
+        if (CsrProcess)
+        {
+            /* Reference the Process */
+            CsrLockedReferenceProcess(CsrThread->Process);
+
+            /* Release the lock */
+            CsrReleaseProcessLock();
+
+            /* Duplicate the Object Directory */
+            Status = NtDuplicateObject(NtCurrentProcess(),
+                                       CsrObjectDirectory,
+                                       CsrProcess->ProcessHandle,
+                                       &ConnectInfo->ObjectDirectory,
+                                       0,
+                                       0,
+                                       DUPLICATE_SAME_ACCESS |
+                                       DUPLICATE_SAME_ATTRIBUTES);
+
+            /* Acquire the lock */
+            CsrAcquireProcessLock();
+
+            /* Check for success */
+            if (NT_SUCCESS(Status))
+            {
+                /* Attach the Shared Section */
+                Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);
+
+                /* Check how this went */
+                if (NT_SUCCESS(Status)) AllowConnection = TRUE;
+            }
+
+            /* Dereference the project */
+            CsrLockedDereferenceProcess(CsrProcess);
+        }
+    }
+
+    /* Release the lock */
+    CsrReleaseProcessLock();
+
+    /* Setup the Port View Structure */
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
+    RemotePortView.ViewSize = 0;
+    RemotePortView.ViewBase = NULL;
+
+    /* Save the Process ID */
+    ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
+
+    /* Accept the Connection */
+    Status = NtAcceptConnectPort(&hPort,
+                                 AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
+                                 &ApiMessage->Header,
+                                 AllowConnection,
+                                 NULL,
+                                 &RemotePortView);
+    if (!NT_SUCCESS(Status))
+    {
+         DPRINT1("CSRSS: NtAcceptConnectPort - failed.  Status == %X\n", Status);
+    }
+    else if (AllowConnection)
+    {
+        if (CsrDebug & 2)
+        {
+            DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
+                    ApiMessage->Header.ClientId.UniqueProcess,
+                    ApiMessage->Header.ClientId.UniqueThread,
+                    RemotePortView.ViewBase,
+                    RemotePortView.ViewSize);
+        }
+
+        /* Set some Port Data in the Process */
+        CsrProcess->ClientPort = hPort;
+        CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
+        CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
+                                                   (ULONG_PTR)RemotePortView.ViewSize);
+
+        /* Complete the connection */
+        Status = NtCompleteConnectPort(hPort);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("CSRSS: NtCompleteConnectPort - failed.  Status == %X\n", Status);
+        }
+    }
+    else
+    {
+        DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
+                ApiMessage->Header.ClientId.UniqueProcess,
+                ApiMessage->Header.ClientId.UniqueThread);
+    }
+
+    /* Return status to caller */
+    return Status;
+}
+
+/*++
+ * @name CsrSbApiRequestThread
+ *
+ * The CsrSbApiRequestThread routine handles incoming messages or connection
+ * requests on the SM API LPC Port.
+ *
+ * @param Parameter
+ *        System-default user-defined parameter. Unused.
+ *
+ * @return The thread exit code, if the thread is terminated.
+ *
+ * @remarks Before listening on the port, the routine will first attempt
+ *          to connect to the user subsystem.
+ *
+ *--*/
+VOID
+NTAPI
+CsrSbApiRequestThread(IN PVOID Parameter)
+{
+    NTSTATUS Status;
+    SB_API_MSG ReceiveMsg;
+    PSB_API_MSG ReplyMsg = NULL;
+    PVOID PortContext;
+    ULONG MessageType;
+
+    /* Start the loop */
+    while (TRUE)
+    {
+        /* Wait for a message to come in */
+        Status = NtReplyWaitReceivePort(CsrSbApiPort,
+                                        &PortContext,
+                                        &ReplyMsg->h,
+                                        &ReceiveMsg.h);
+
+        /* Check if we didn't get success */
+        if (Status != STATUS_SUCCESS)
+        {
+            /* If we only got a warning, keep going */
+            if (NT_SUCCESS(Status)) continue;
+
+            /* We failed big time, so start out fresh */
+            ReplyMsg = NULL;
+            DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
+            continue;
+        }
+
+        /* Save the message type */
+        MessageType = ReceiveMsg.h.u2.s2.Type;
+
+        /* Check if this is a connection request */
+        if (MessageType == LPC_CONNECTION_REQUEST)
+        {
+            /* Handle connection request */
+            CsrSbApiHandleConnectionRequest(&ReceiveMsg);
+
+            /* Start over */
+            ReplyMsg = NULL;
+            continue;
+        }
+
+        /* Check if the port died */
+        if (MessageType == LPC_PORT_CLOSED)
+        {
+            /* Close the handle if we have one */
+            if (PortContext) NtClose((HANDLE)PortContext);
+
+            /* Client died, start over */
+            ReplyMsg = NULL;
+            continue;
+        }
+        else if (MessageType == LPC_CLIENT_DIED)
+        {
+            /* Client died, start over */
+            ReplyMsg = NULL;
+            continue;
+        }
+
+        /*
+         * It's an API Message, check if it's within limits. If it's not, the
+         * NT Behaviour is to set this to the Maximum API.
+         */
+        if (ReceiveMsg.ApiNumber > SbpMaxApiNumber)
+        {
+            ReceiveMsg.ApiNumber = SbpMaxApiNumber;
+            DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber);
+         }
+
+        /* Reuse the message */
+        ReplyMsg = &ReceiveMsg;
+
+        /* Make sure that the message is supported */
+        if (ReceiveMsg.ApiNumber < SbpMaxApiNumber)
+        {
+            /* Call the API */
+            if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg))
+            {
+                /* It failed, so return nothing */
+                ReplyMsg = NULL;
+            }
+        }
+        else
+        {
+            /* We don't support this API Number */
+            ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED;
+        }
+    }
+}
+
+/*++
+ * @name CsrSbApiHandleConnectionRequest
+ *
+ * The CsrSbApiHandleConnectionRequest routine handles and accepts a new
+ * connection request to the SM API LPC Port.
+ *
+ * @param ApiMessage
+ *        Pointer to the incoming CSR API Message which contains the
+ *        connection request.
+ *
+ * @return STATUS_SUCCESS in case of success, or status code which caused
+ *         the routine to error.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message)
+{
+    NTSTATUS Status;
+    REMOTE_PORT_VIEW RemotePortView;
+    HANDLE hPort;
+
+    /* Set the Port View Structure Length */
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
+
+    /* Accept the connection */
+    Status = NtAcceptConnectPort(&hPort,
+                                 NULL,
+                                 (PPORT_MESSAGE)Message,
+                                 TRUE,
+                                 NULL,
+                                 &RemotePortView);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status);
+        return Status;
+    }
+
+    /* Complete the Connection */
+    Status = NtCompleteConnectPort(hPort);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status);
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*++
+ * @name CsrCallServerFromServer
+ * @implemented NT4
+ *
+ * The CsrCallServerFromServer routine calls a CSR API from within a server.
+ * It avoids using LPC messages since the request isn't coming from a client.
+ *
+ * @param ReceiveMsg
+ *        Pointer to the CSR API Message to send to the server.
+ *
+ * @param ReplyMsg
+ *        Pointer to the CSR API Message to receive from the server.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
+ *         if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there
+ *         was a problem executing the API.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg,
+                        PCSR_API_MESSAGE ReplyMsg)
+{
+    ULONG ServerId;
+    PCSR_SERVER_DLL ServerDll;
+    ULONG ApiId;
+    ULONG Reply;
+    NTSTATUS Status;
+
+    /* Get the Server ID */
+    ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode);
+
+    /* Make sure that the ID is within limits, and the Server DLL loaded */
+    if ((ServerId >= CSR_SERVER_DLL_MAX) ||
+        (!(ServerDll = CsrLoadedServerDll[ServerId])))
+    {
+        /* We are beyond the Maximum Server ID */
+        DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll);
+        ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+    else
+    {
+        /* Get the API ID */
+        ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode);
+
+        /* Normalize it with our Base ID */
+        ApiId -= ServerDll->ApiBase;
+
+        /* Make sure that the ID is within limits, and the entry exists */
+        if ((ApiId >= ServerDll->HighestApiSupported) ||
+            ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
+        {
+            /* We are beyond the Maximum API ID, or it doesn't exist */
+            DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
+                    "invalid API to call from the server.\n",
+                    ServerDll->ValidTable[ApiId],
+                    ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
+                    ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name);
+            DbgBreakPoint();
+            ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+            return STATUS_ILLEGAL_FUNCTION;
+        }
+    }
+
+    if (CsrDebug & 2)
+    {
+        DPRINT1("CSRSS: %s Api Request received from server process\n",
+                ServerDll->NameTable[ApiId]);
+    }
+        
+    /* Validation complete, start SEH */
+    _SEH2_TRY
+    {
+        /* Call the API and get the result */
+        Status = ServerDll->DispatchTable[ApiId](ReceiveMsg, &Reply);
+
+        /* Return the result, no matter what it is */
+        ReplyMsg->Status = Status;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* If we got an exception, return access violation */
+        ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
+    }
+    _SEH2_END;
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrConnectToUser
+ * @implemented NT4
+ *
+ * The CsrConnectToUser connects to the User subsystem.
+ *
+ * @param None
+ *
+ * @return A pointer to the CSR Thread
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrConnectToUser(VOID)
+{
+    NTSTATUS Status;
+    ANSI_STRING DllName;
+    UNICODE_STRING TempName;
+    HANDLE hUser32;
+    STRING StartupName;
+    PTEB Teb = NtCurrentTeb();
+    PCSR_THREAD CsrThread;
+    BOOLEAN Connected;
+
+    /* Check if we didn't already find it */
+    if (!CsrClientThreadSetup)
+    {
+        /* Get the DLL Handle for user32.dll */
+        RtlInitAnsiString(&DllName, "user32");
+        RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
+        Status = LdrGetDllHandle(NULL,
+                                 NULL,
+                                 &TempName,
+                                 &hUser32);
+        RtlFreeUnicodeString(&TempName);
+
+        /* If we got teh handle, get the Client Thread Startup Entrypoint */
+        if (NT_SUCCESS(Status))
+        {
+            RtlInitAnsiString(&StartupName,"ClientThreadSetup");
+            Status = LdrGetProcedureAddress(hUser32,
+                                            &StartupName,
+                                            0,
+                                            (PVOID)&CsrClientThreadSetup);
+        }
+    }
+
+    /* Connect to user32 */
+    _SEH2_TRY
+    {
+        Connected = CsrClientThreadSetup();
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Connected = FALSE;
+    } _SEH2_END;
+    
+    if (!Connected)
+    {
+        DPRINT1("CSRSS: CsrConnectToUser failed\n");
+        return NULL;
+    }
+
+    /* Save pointer to this thread in TEB */
+    CsrAcquireProcessLock();
+    CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
+    CsrReleaseProcessLock();
+    if (CsrThread) Teb->CsrClientThread = CsrThread;
+
+    /* Return it */
+    return CsrThread;
+}
+
+/*++
+ * @name CsrQueryApiPort
+ * @implemented NT4
+ *
+ * The CsrQueryApiPort routine returns a handle to the CSR API LPC port.
+ *
+ * @param None.
+ *
+ * @return A handle to the port.
+ *
+ * @remarks None.
+ *
+ *--*/
+HANDLE
+NTAPI
+CsrQueryApiPort(VOID)
+{
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+    return CsrApiPort;
+}
+
+/*++
+ * @name CsrCaptureArguments
+ * @implemented NT5.1
+ *
+ * The CsrCaptureArguments routine validates a CSR Capture Buffer and
+ * re-captures it into a server CSR Capture Buffer.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread performing the validation.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message containing the Capture Buffer
+ *        that needs to be validated.
+ *
+ * @return TRUE if validation succeeded, FALSE otherwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrCaptureArguments(IN PCSR_THREAD CsrThread,
+                    IN PCSR_API_MESSAGE ApiMessage)
+{
+    PCSR_CAPTURE_BUFFER LocalCaptureBuffer = NULL, RemoteCaptureBuffer = NULL;
+    ULONG LocalLength = 0, PointerCount = 0;
+    SIZE_T BufferDistance = 0;
+    ULONG_PTR **PointerOffsets = NULL, *CurrentPointer = NULL;
+
+    /* Use SEH to make sure this is valid */
+    _SEH2_TRY
+    {
+        /* Get the buffer we got from whoever called NTDLL */
+        LocalCaptureBuffer = ApiMessage->CsrCaptureData;
+        LocalLength = LocalCaptureBuffer->Size;
+
+        /* Now check if the buffer is inside our mapped section */
+        if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||
+            (((ULONG_PTR)LocalCaptureBuffer + LocalLength) >= CsrThread->Process->ClientViewBounds))
+        {
+            /* Return failure */
+            DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView\n");
+            ApiMessage->Status = STATUS_INVALID_PARAMETER;
+            _SEH2_YIELD(return FALSE);
+        }
+
+        /* Check if the Length is valid */
+        if (((LocalCaptureBuffer->PointerCount * 4 + sizeof(CSR_CAPTURE_BUFFER)) >
+            LocalLength) ||(LocalLength > MAXWORD))
+        {
+            /* Return failure */
+            DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer);
+            DbgBreakPoint();
+            ApiMessage->Status = STATUS_INVALID_PARAMETER;
+            _SEH2_YIELD(return FALSE);
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Return failure */
+        ApiMessage->Status = STATUS_INVALID_PARAMETER;
+        _SEH2_YIELD(return FALSE);
+    } _SEH2_END;
+
+    /* We validated the incoming buffer, now allocate the remote one */
+    RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, LocalLength);
+    if (!RemoteCaptureBuffer)
+    {
+        /* We're out of memory */
+        ApiMessage->Status = STATUS_NO_MEMORY;
+        return FALSE;
+    }
+
+    /* Copy the client's buffer */
+    RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, LocalLength);
+
+    /* Copy the length */
+    RemoteCaptureBuffer->Size = LocalLength;
+
+    /* Calculate the difference between our buffer and the client's */
+    BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
+
+    /* Save the pointer count and offset pointer */
+    PointerCount = RemoteCaptureBuffer->PointerCount;
+    PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
+
+    /* Start the loop */
+    while (PointerCount)
+    {
+        /* Get the current pointer */
+        if ((CurrentPointer = *PointerOffsets++))
+        {
+            /* Add it to the CSR Message structure */
+            CurrentPointer += (ULONG_PTR)ApiMessage;
+
+            /* Validate the bounds of the current pointer */
+            if ((*CurrentPointer >= CsrThread->Process->ClientViewBase) &&
+                (*CurrentPointer < CsrThread->Process->ClientViewBounds))
+            {
+                /* Modify the pointer to take into account its new position */
+                *CurrentPointer += BufferDistance;
+            }
+            else
+            {
+                /* Invalid pointer, fail */
+                DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n");
+                DbgBreakPoint();
+                ApiMessage->Status = STATUS_INVALID_PARAMETER;
+            }
+        }
+
+        /* Move to the next Pointer */
+        PointerCount--;
+    }
+
+    /* Check if we got success */
+    if (ApiMessage->Status != STATUS_SUCCESS)
+    {
+        /* Failure. Free the buffer and return*/
+        RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
+        return FALSE;
+    }
+    else
+    {
+        /* Success, save the previous buffer */
+        RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer;
+        ApiMessage->CsrCaptureData = RemoteCaptureBuffer;
+    }
+
+    /* Success */
+    return TRUE;
+}
+
+/*++
+ * @name CsrReleaseCapturedArguments
+ * @implemented NT5.1
+ *
+ * The CsrReleaseCapturedArguments routine releases a Capture Buffer
+ * that was previously captured with CsrCaptureArguments.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message containing the Capture Buffer
+ *        that needs to be released.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
+{
+    PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
+    SIZE_T BufferDistance;
+    ULONG PointerCount;
+    ULONG_PTR **PointerOffsets, *CurrentPointer;
+
+    /* Get the capture buffers */
+    RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
+    LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
+
+    /* Free the previous one */
+    RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
+
+    /* Find out the difference between the two buffers */
+    BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;
+
+    /* Save the pointer count and offset pointer */
+    PointerCount = RemoteCaptureBuffer->PointerCount;
+    PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
+
+    /* Start the loop */
+    while (PointerCount)
+    {
+        /* Get the current pointer */
+        CurrentPointer = *PointerOffsets++;
+        if (CurrentPointer)
+        {
+            /* Add it to the CSR Message structure */
+            CurrentPointer += (ULONG_PTR)ApiMessage;
+
+            /* Modify the pointer to take into account its new position */
+            *CurrentPointer += BufferDistance;
+        }
+
+        /* Move to the next Pointer */
+        PointerCount--;
+    }
+
+    /* Copy the data back */
+    RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
+
+    /* Free our allocated buffer */
+    RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
+}
+
+/*++
+ * @name CsrValidateMessageBuffer
+ * @implemented NT5.1
+ *
+ * The CsrValidateMessageBuffer routine validates a captured message buffer
+ * present in the CSR Api Message
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message containing the CSR Capture Buffer.
+ *
+ * @param Buffer
+ *        Pointer to the message buffer to validate.
+ *
+ * @param ArgumentSize
+ *        Size of the message to check.
+ *
+ * @param ArgumentCount
+ *        Number of messages to check.
+ *
+ * @return TRUE if validation suceeded, FALSE otherwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
+                         IN PVOID *Buffer,
+                         IN ULONG ArgumentSize,
+                         IN ULONG ArgumentCount)
+{
+    PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
+    SIZE_T BufferDistance;
+    ULONG PointerCount, i;
+    ULONG_PTR **PointerOffsets, *CurrentPointer;
+
+    /* Make sure there are some arguments */
+    if (!ArgumentCount) return FALSE;
+
+    /* Check if didn't get a buffer and there aren't any arguments to check */
+    if (!(*Buffer) && (!(ArgumentCount * ArgumentSize))) return TRUE;
+
+    /* Check if we have no capture buffer */
+    if (!CaptureBuffer)
+    {
+        /* In this case, check only the Process ID */
+        if (NtCurrentTeb()->ClientId.UniqueProcess ==
+            ApiMessage->Header.ClientId.UniqueProcess)
+        {
+            /* There is a match, validation succeeded */
+            return TRUE;
+        }
+    }
+    else
+    {
+        /* Make sure that there is still space left in the buffer */
+        if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) <
+            (ArgumentCount * ArgumentSize))
+        {
+            /* Find out the difference between the two buffers */
+            BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
+
+             /* Save the pointer count */
+            PointerCount = CaptureBuffer->PointerCount;
+            PointerOffsets = (ULONG_PTR**)(CaptureBuffer + 1);
+
+            /* Start the loop */
+            for (i = 0; i < PointerCount; i++)
+            {
+                /* Get the current pointer */
+                CurrentPointer = *PointerOffsets++;
+
+                /* Check if its' equal to the difference */
+                if (*CurrentPointer == BufferDistance) return TRUE;
+            }
+        }
+    }
+
+    /* Failure */
+    DbgPrint("CSRSRV: Bad message buffer %p\n", ApiMessage);
+    DbgBreakPoint();
+    return FALSE;
+}
+
+/*++
+ * @name CsrValidateMessageString
+ * @implemented NT5.1
+ *
+ * The CsrValidateMessageString validates a captured Wide-Character String
+ * present in a CSR API Message.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message containing the CSR Capture Buffer.
+ *
+ * @param MessageString
+ *        Pointer to the buffer containing the string to validate.
+ *
+ * @return TRUE if validation suceeded, FALSE otherwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,
+                         IN LPWSTR *MessageString)
+{
+    DPRINT1("CSRSRV: %s called\n", __FUNCTION__);
+    return FALSE;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/csrsrv.rc b/reactos/deprecated/csr/csrsrv/csrsrv.rc
new file mode 100644 (file)
index 0000000..658072d
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "ReactOS CSR Core Server\0"
+#define REACTOS_STR_INTERNAL_NAME      "csrsrv\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "csrsrv.dll\0"
+#include <reactos/version.rc>
diff --git a/reactos/deprecated/csr/csrsrv/csrsrv2.spec b/reactos/deprecated/csr/csrsrv/csrsrv2.spec
new file mode 100644 (file)
index 0000000..e379420
--- /dev/null
@@ -0,0 +1,35 @@
+@ stdcall CsrAddStaticServerThread(ptr ptr long)
+@ stdcall CsrCallServerFromServer(ptr ptr)
+@ stdcall CsrConnectToUser()
+@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr)
+@ stdcall CsrCreateRemoteThread(ptr ptr)
+@ stdcall CsrCreateThread(ptr ptr ptr long)
+@ stdcall CsrCreateWait(ptr ptr ptr ptr ptr ptr)
+@ stdcall CsrDebugProcess(ptr)
+@ stdcall CsrDebugProcessStop(ptr)
+@ stdcall CsrDereferenceProcess(ptr)
+@ stdcall CsrDereferenceThread(ptr)
+@ stdcall CsrDereferenceWait(ptr)
+@ stdcall CsrDestroyProcess(ptr long)
+@ stdcall CsrDestroyThread(ptr)
+@ stdcall CsrExecServerThread(ptr long)
+@ stdcall CsrGetProcessLuid(ptr ptr)
+@ stdcall CsrImpersonateClient(ptr)
+@ stdcall CsrLockProcessByClientId(ptr ptr)
+@ stdcall CsrLockThreadByClientId(ptr ptr)
+@ stdcall CsrMoveSatisfiedWait(ptr ptr)
+@ stdcall CsrNotifyWait(ptr long ptr ptr)
+@ stdcall CsrPopulateDosDevices()
+@ stdcall CsrQueryApiPort()
+@ stdcall CsrReferenceThread(ptr)
+@ stdcall CsrRevertToSelf()
+@ stdcall CsrServerInitialization(long ptr)
+@ stdcall CsrSetBackgroundPriority(ptr)
+@ stdcall CsrSetCallingSpooler(long)
+@ stdcall CsrSetForegroundPriority(ptr)
+@ stdcall CsrShutdownProcesses(ptr long)
+@ stdcall CsrUnhandledExceptionFilter(ptr)
+@ stdcall CsrUnlockProcess(ptr)
+@ stdcall CsrUnlockThread(ptr)
+@ stdcall CsrValidateMessageBuffer(ptr ptr long long)
+@ stdcall CsrValidateMessageString(ptr ptr)
diff --git a/reactos/deprecated/csr/csrsrv/init.c b/reactos/deprecated/csr/csrsrv/init.c
new file mode 100644 (file)
index 0000000..eee4f3d
--- /dev/null
@@ -0,0 +1,988 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/init.c
+ * PURPOSE:         CSR Server DLL Initialization
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+HANDLE CsrObjectDirectory;
+ULONG SessionId;
+BOOLEAN CsrProfileControl;
+UNICODE_STRING CsrDirectoryName;
+HANDLE CsrHeap;
+HANDLE BNOLinksDirectory;
+HANDLE SessionObjectDirectory;
+HANDLE DosDevicesDirectory;
+HANDLE CsrInitializationEvent;
+SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
+ULONG CsrDebug;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrParseServerCommandLine
+ *
+ * The CsrParseServerCommandLine routine parses the CSRSS command-line in the
+ * registry and performs operations for each entry found.
+ *
+ * @param ArgumentCount
+ *        Number of arguments on the command line.
+ *
+ * @param Arguments
+ *        Array of arguments.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+FASTCALL
+CsrParseServerCommandLine(IN ULONG ArgumentCount,
+                          IN PCHAR Arguments[])
+{
+    NTSTATUS Status;
+    PCHAR ParameterName = NULL, ParameterValue = NULL, EntryPoint, ServerString;
+    ULONG i, DllIndex;
+    ANSI_STRING AnsiString;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+
+    /* Set the Defaults */
+    CsrTotalPerProcessDataLength = 0;
+    CsrObjectDirectory = 0;
+    CsrMaxApiRequestThreads = 16;
+
+    /* Save our Session ID, and create a Directory for it */
+    SessionId = NtCurrentPeb()->SessionId;
+    Status = CsrCreateSessionObjectDirectory(SessionId);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: CsrCreateSessionObjectDirectory failed (%lx)\n",
+                Status);
+
+        /* It's not fatal if the session ID isn't zero */
+        if (SessionId) return Status;
+        ASSERT(NT_SUCCESS(Status));
+    }
+
+    /* Loop through every argument */
+    for (i = 1; i < ArgumentCount; i++)
+    {
+        /* Split Name and Value */
+        ParameterName = Arguments[i];
+        ParameterValue = NULL;
+        ParameterValue = strchr(ParameterName, '=');
+        if (ParameterValue) *ParameterValue++ = ANSI_NULL;
+        DPRINT1("Name=%s, Value=%s\n", ParameterName, ParameterValue);
+
+        /* Check for Object Directory */
+        if (!_stricmp(ParameterName, "ObjectDirectory"))
+        {
+            /* Check if a session ID is specified */
+            if (SessionId)
+            {
+                DPRINT1("Sessions not yet implemented\n");
+                ASSERT(SessionId);
+            }
+
+            /* Initialize the directory name */
+            RtlInitAnsiString(&AnsiString, ParameterValue);
+            Status = RtlAnsiStringToUnicodeString(&CsrDirectoryName,
+                                                  &AnsiString,
+                                                  TRUE);
+            ASSERT(NT_SUCCESS(Status) || SessionId != 0);
+            if (!NT_SUCCESS(Status)) return Status;
+
+            /* Create it */
+            InitializeObjectAttributes(&ObjectAttributes,
+                                       &CsrDirectoryName,
+                                       OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                                       NULL,
+                                       NULL);
+            Status = NtCreateDirectoryObject(&CsrObjectDirectory,
+                                             DIRECTORY_ALL_ACCESS,
+                                             &ObjectAttributes);
+            if (!NT_SUCCESS(Status)) return Status;
+
+            /* Secure it */
+            Status = CsrSetDirectorySecurity(CsrObjectDirectory);
+            if (!NT_SUCCESS(Status)) return Status;
+        }
+        else if (!_stricmp(ParameterName, "SubSystemType"))
+        {
+            /* Ignored */
+        }
+        else if (!_stricmp(ParameterName, "MaxRequestThreads"))
+        {
+            Status = RtlCharToInteger(ParameterValue,
+                                      0,
+                                      &CsrMaxApiRequestThreads);
+        }
+        else if (!_stricmp(ParameterName, "RequestThreads"))
+        {
+            /* Ignored */
+            Status = STATUS_SUCCESS;
+        }
+        else if (!_stricmp(ParameterName, "ProfileControl"))
+        {
+            /* Ignored */
+        }
+        else if (!_stricmp(ParameterName, "SharedSection"))
+        {
+            /* Craete the Section */
+            Status = CsrSrvCreateSharedSection(ParameterValue);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
+                        ParameterName, ParameterValue, Status);
+                return Status;
+            }
+
+            /* Load us */
+            Status = CsrLoadServerDll("CSRSS", NULL, CSR_SRV_SERVER);
+        }
+        else if (!_stricmp(ParameterName, "ServerDLL"))
+        {
+            /* Loop the command line */
+            EntryPoint = NULL;
+            Status = STATUS_INVALID_PARAMETER;
+            ServerString = ParameterValue;
+            while (*ServerString)
+            {
+                /* Check for the Entry Point */
+                if ((*ServerString == ':') && (!EntryPoint))
+                {
+                    /* Found it. Add a nullchar and save it */
+                    *ServerString++ = ANSI_NULL;
+                    EntryPoint = ServerString;
+                }
+
+                /* Check for the Dll Index */
+                if (*ServerString++ == ',') break;
+            }
+
+            /* Did we find something to load? */
+            if (!*ServerString)
+            {
+                DPRINT1("CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
+                        ParameterValue, Status);
+                return Status;
+            }
+
+            /* Convert it to a ULONG */
+            Status = RtlCharToInteger(ServerString, 10, &DllIndex);
+
+            /* Add a null char if it was valid */
+            if (NT_SUCCESS(Status)) ServerString[-1] = ANSI_NULL;
+
+            /* Load it */
+            if (CsrDebug & 1) DPRINT1("CSRSS: Loading ServerDll=%s:%s\n", ParameterValue, EntryPoint);
+            Status = CsrLoadServerDll(ParameterValue, EntryPoint, DllIndex);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT1("CSRSS: *** Failed loading ServerDll=%s (Status == 0x%x)\n",
+                        ParameterValue, Status);
+                return Status;
+            }
+        }
+        else if (!_stricmp(ParameterName, "Windows"))
+        {
+            /* Ignored */
+        }
+        else
+        {
+            /* Invalid parameter on the command line */
+            Status = STATUS_INVALID_PARAMETER;
+        }
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/*++
+ * @name CsrCreateLocalSystemSD
+ *
+ * The CsrCreateLocalSystemSD routine creates a Security Descriptor for
+ * the local account with PORT_ALL_ACCESS.
+ *
+ * @param LocalSystemSd
+ *        Pointer to a pointer to the security descriptor to create.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd)
+{
+    SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
+    PSID SystemSid;
+    ULONG Length;
+    PSECURITY_DESCRIPTOR SystemSd;
+    PACL Dacl;
+    NTSTATUS Status;
+
+    /* Initialize the System SID */
+    RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
+                                SECURITY_LOCAL_SYSTEM_RID,
+                                0, 0, 0, 0, 0, 0, 0,
+                                &SystemSid);
+
+    /* Get the length of the SID */
+    Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
+
+    /* Allocate a buffer for the Security Descriptor, with SID and DACL */
+    SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
+
+    /* Set the pointer to the DACL */
+    Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+    /* Now create the SD itself */
+    Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SystemSd);
+        return Status;
+    }
+
+    /* Create the DACL for it*/
+    RtlCreateAcl(Dacl, Length, ACL_REVISION2);
+
+    /* Create the ACE */
+    Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SystemSd);
+        return Status;
+    }
+
+    /* Clear the DACL in the SD */
+    Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SystemSd);
+        return Status;
+    }
+
+    /* Free the SID and return*/
+    RtlFreeSid(SystemSid);
+    *LocalSystemSd = SystemSd;
+    return Status;
+}
+
+/*++
+ * @name GetDosDevicesProtection
+ *
+ * The GetDosDevicesProtection creates a security descriptor for the DOS Devices
+ * Object Directory.
+ *
+ * @param DosDevicesSd
+ *        Pointer to the Security Descriptor to return.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks Depending on the DOS Devices Protection Mode (set in the registry),
+ *          regular users may or may not have full access to the directory.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+GetDosDevicesProtection(OUT PSECURITY_DESCRIPTOR DosDevicesSd)
+{
+    SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
+    SID_IDENTIFIER_AUTHORITY CreatorAuthority = {SECURITY_CREATOR_SID_AUTHORITY};
+    SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY};
+    PSID WorldSid, CreatorSid, AdminSid, SystemSid;
+    UCHAR KeyValueBuffer[0x40];
+    PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
+    UNICODE_STRING KeyName;
+    ULONG ProtectionMode = 0;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    PACL Dacl;
+    PACCESS_ALLOWED_ACE Ace;
+    HANDLE hKey;
+    NTSTATUS Status;
+    ULONG ResultLength, SidLength, AclLength;
+
+    /* Create the SD */
+    Status = RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Initialize the System SID */
+    Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 1,
+                                         SECURITY_LOCAL_SYSTEM_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &SystemSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Initialize the World SID */
+    Status = RtlAllocateAndInitializeSid(&WorldAuthority, 1,
+                                         SECURITY_WORLD_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &WorldSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Initialize the Admin SID */
+    Status = RtlAllocateAndInitializeSid(&NtSidAuthority, 2,
+                                         SECURITY_BUILTIN_DOMAIN_RID,
+                                         DOMAIN_ALIAS_RID_ADMINS,
+                                         0, 0, 0, 0, 0, 0,
+                                         &AdminSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Initialize the Creator SID */
+    Status = RtlAllocateAndInitializeSid(&CreatorAuthority, 1,
+                                         SECURITY_CREATOR_OWNER_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &CreatorSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Open the Session Manager Key */
+    RtlInitUnicodeString(&KeyName, SM_REG_KEY);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
+    if (NT_SUCCESS(Status))
+    {
+        /* Read the key value */
+        RtlInitUnicodeString(&KeyName, L"ProtectionMode");
+        Status = NtQueryValueKey(hKey,
+                                 &KeyName,
+                                 KeyValuePartialInformation,
+                                 KeyValueBuffer,
+                                 sizeof(KeyValueBuffer),
+                                 &ResultLength);
+
+        /* Make sure it's what we expect it to be */
+        KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
+        if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
+            (*(PULONG)KeyValuePartialInfo->Data))
+        {
+            /* Save the Protection Mode */
+            ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
+        }
+
+        /* Close the handle */
+        NtClose(hKey);
+    }
+
+    /* Check the Protection Mode */
+    if (ProtectionMode & 3)
+    {
+        /* Calculate SID Lengths */
+        SidLength = RtlLengthSid(CreatorSid) + RtlLengthSid(SystemSid) +
+                    RtlLengthSid(AdminSid);
+        AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
+
+        /* Allocate memory for the DACL */
+        Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
+        ASSERT(Dacl != NULL);
+
+        /* Build the ACL and add 3 ACEs */
+        Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, AdminSid);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, CreatorSid);
+        ASSERT(NT_SUCCESS(Status));
+
+        /* Edit the ACEs to make them inheritable */
+        Status = RtlGetAce(Dacl, 0, (PVOID*)&Ace);
+        ASSERT(NT_SUCCESS(Status));
+        Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+        Status = RtlGetAce(Dacl, 1, (PVOID*)&Ace);
+        ASSERT(NT_SUCCESS(Status));
+        Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
+        Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
+        ASSERT(NT_SUCCESS(Status));
+        Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
+
+        /* Set this DACL with the SD */
+        Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
+        ASSERT(NT_SUCCESS(Status));
+        goto Quickie;
+    }
+    else
+    {
+        /* Calculate SID Lengths */
+        SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid);
+        AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) + SidLength;
+
+        /* Allocate memory for the DACL */
+        Dacl = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, AclLength);
+        ASSERT(Dacl != NULL);
+
+        /* Build the ACL and add 3 ACEs */
+        Status = RtlCreateAcl(Dacl, AclLength, ACL_REVISION2);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE, WorldSid);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, SystemSid);
+        ASSERT(NT_SUCCESS(Status));
+        Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, GENERIC_ALL, WorldSid);
+        ASSERT(NT_SUCCESS(Status));
+
+        /* Edit the last ACE to make it inheritable */
+        Status = RtlGetAce(Dacl, 2, (PVOID*)&Ace);
+        ASSERT(NT_SUCCESS(Status));
+        Ace->Header.AceFlags |= OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
+
+        /* Set this DACL with the SD */
+        Status = RtlSetDaclSecurityDescriptor(DosDevicesSd, TRUE, Dacl, FALSE);
+        ASSERT(NT_SUCCESS(Status));
+        goto Quickie;
+    }
+
+/* FIXME: failure cases! Fail: */
+    /* Free the memory */
+    RtlFreeHeap(CsrHeap, 0, Dacl);
+
+/* FIXME: semi-failure cases! Quickie: */
+Quickie:
+    /* Free the SIDs */
+    RtlFreeSid(SystemSid);
+    RtlFreeSid(WorldSid);
+    RtlFreeSid(AdminSid);
+    RtlFreeSid(CreatorSid);
+
+    /* Return */
+    return Status;
+}
+
+/*++
+ * @name FreeDosDevicesProtection
+ *
+ * The FreeDosDevicesProtection frees the security descriptor that was created
+ * by GetDosDevicesProtection
+ *
+ * @param DosDevicesSd
+ *        Pointer to the security descriptor to free.
+
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+FreeDosDevicesProtection(IN PSECURITY_DESCRIPTOR DosDevicesSd)
+{
+    PACL Dacl;
+    BOOLEAN Present, Default;
+    NTSTATUS Status;
+
+    /* Get the DACL corresponding to this SD */
+    Status = RtlGetDaclSecurityDescriptor(DosDevicesSd, &Present, &Dacl, &Default);
+    ASSERT(NT_SUCCESS(Status));
+    ASSERT(Present);
+    ASSERT(Dacl != NULL);
+
+    /* Free it */
+    if ((NT_SUCCESS(Status)) && (Dacl)) RtlFreeHeap(CsrHeap, 0, Dacl);
+}
+
+/*++
+ * @name CsrCreateSessionObjectDirectory
+ *
+ * The CsrCreateSessionObjectDirectory routine creates the BaseNamedObjects,
+ * Session and Dos Devices directories for the specified session.
+ *
+ * @param Session
+ *        Session ID for which to create the directories.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateSessionObjectDirectory(IN ULONG Session)
+{
+    WCHAR SessionBuffer[512], BnoBuffer[512];
+    UNICODE_STRING SessionString, BnoString;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE BnoHandle;
+    SECURITY_DESCRIPTOR DosDevicesSd;
+    NTSTATUS Status;
+
+    /* Generate the Session BNOLINKS Directory name */
+    swprintf(SessionBuffer, L"%ws\\BNOLINKS", SESSION_ROOT);
+    RtlInitUnicodeString(&SessionString, SessionBuffer);
+
+    /* Create it */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtCreateDirectoryObject(&BNOLinksDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
+                "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
+        return Status;
+    }
+
+    /* Now add the Session ID */
+    swprintf(SessionBuffer, L"%ld", Session);
+    RtlInitUnicodeString(&SessionString, SessionBuffer);
+
+    /* Check if this is the first Session */
+    if (Session)
+    {
+        /* Not the first, so the name will be slighly more complex */
+        swprintf(BnoBuffer, L"%ws\\%ld\\BaseNamedObjects", SESSION_ROOT, Session);
+        RtlInitUnicodeString(&BnoString, BnoBuffer);
+    }
+    else
+    {
+        /* Use the direct name */
+        RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
+    }
+
+    /* Create the symlink */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               BNOLinksDirectory,
+                               NULL);
+    Status = NtCreateSymbolicLinkObject(&BnoHandle,
+                                        SYMBOLIC_LINK_ALL_ACCESS,
+                                        &ObjectAttributes,
+                                        &BnoString);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: NtCreateSymbolicLinkObject failed in "
+                "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
+        return Status;
+    }
+
+    /* Create the \DosDevices Security Descriptor */
+    Status = GetDosDevicesProtection(&DosDevicesSd);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Now create a directory for this session */
+    swprintf(SessionBuffer, L"%ws\\%ld", SESSION_ROOT, Session);
+    RtlInitUnicodeString(&SessionString, SessionBuffer);
+
+    /* Create the directory */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               0,
+                               &DosDevicesSd);
+    Status = NtCreateDirectoryObject(&SessionObjectDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
+                "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
+        FreeDosDevicesProtection(&DosDevicesSd);
+        return Status;
+    }
+
+    /* Next, create a directory for this session's DOS Devices */
+    RtlInitUnicodeString(&SessionString, L"DosDevices");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_CASE_INSENSITIVE,
+                               SessionObjectDirectory,
+                               &DosDevicesSd);
+    Status = NtCreateDirectoryObject(&DosDevicesDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSS: NtCreateDirectoryObject failed in "
+                "CsrCreateSessionObjectDirectory - status = %lx\n", Status);
+    }
+
+    /* Release the Security Descriptor */
+    FreeDosDevicesProtection(&DosDevicesSd);
+
+    /* Return */
+    return Status;
+}
+
+/*++
+ * @name CsrSetProcessSecurity
+ *
+ * The CsrSetProcessSecurity routine protects access to the CSRSS process
+ * from unauthorized tampering.
+ *
+ * @param None.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSetProcessSecurity(VOID)
+{
+    NTSTATUS Status;
+    HANDLE hToken, hProcess = NtCurrentProcess();
+    ULONG ReturnLength, Length;
+    PTOKEN_USER TokenInfo = NULL;
+    PSECURITY_DESCRIPTOR ProcSd = NULL;
+    PACL Dacl;
+    PSID UserSid;
+
+    /* Open our token */
+    Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Get the Token User Length */
+    NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length);
+
+    /* Allocate space for it */
+    TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
+    if (!TokenInfo)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* Now query the data */
+    Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length);
+    NtClose(hToken);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Now check the SID Length */
+    UserSid = TokenInfo->User.Sid;
+    ReturnLength = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
+
+    /* Allocate a buffer for the Security Descriptor, with SID and DACL */
+    ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length);
+    if (!ProcSd)
+    {
+        Status = STATUS_NO_MEMORY;
+        goto Quickie;
+    }
+
+    /* Set the pointer to the DACL */
+    Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+    /* Now create the SD itself */
+    Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Create the DACL for it*/
+    RtlCreateAcl(Dacl, Length, ACL_REVISION2);
+
+    /* Create the ACE */
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    PROCESS_VM_READ | PROCESS_VM_WRITE |
+                                    PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE |
+                                    PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME |
+                                    PROCESS_QUERY_INFORMATION | READ_CONTROL,
+                                    UserSid);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Clear the DACL in the SD */
+    Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    /* Write the SD into the Process */
+    Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd);
+
+    /* Free the memory and return */
+Quickie:
+    if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd);
+    RtlFreeHeap(CsrHeap, 0, TokenInfo);
+    return Status;
+}
+
+/*++
+ * @name CsrSetDirectorySecurity
+ *
+ * The CsrSetDirectorySecurity routine sets the security descriptor for the
+ * specified Object Directory.
+ *
+ * @param ObjectDirectory
+ *        Handle fo the Object Directory to protect.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSetDirectorySecurity(IN HANDLE ObjectDirectory)
+{
+    /* FIXME: Implement */
+    return STATUS_SUCCESS;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*++
+ * @name CsrServerInitialization
+ * @implemented NT4
+ *
+ * The CsrServerInitialization routine is the native (not Server) entrypoint
+ * of this Server DLL. It serves as the entrypoint for csrss.
+ *
+ * @param ArgumentCount
+ *        Number of arguments on the command line.
+ *
+ * @param Arguments
+ *        Array of arguments from the command line.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrServerInitialization(IN ULONG ArgumentCount,
+                        IN PCHAR Arguments[])
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG i = 0;
+    PVOID ProcessData;
+    PCSR_SERVER_DLL ServerDll;
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Create the Init Event */
+    Status = NtCreateEvent(&CsrInitializationEvent,
+                           EVENT_ALL_ACCESS,
+                           NULL,
+                           SynchronizationEvent,
+                           FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Cache System Basic Information so we don't always request it */
+    Status = NtQuerySystemInformation(SystemBasicInformation,
+                                      &CsrNtSysInfo,
+                                      sizeof(SYSTEM_BASIC_INFORMATION),
+                                      NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Save our Heap */
+    CsrHeap = RtlGetProcessHeap();
+
+    /* Set our Security Descriptor to protect the process */
+    Status = CsrSetProcessSecurity();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Set up Session Support */
+    Status = CsrInitializeNtSessionList();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Set up Process Support */
+    Status = CsrInitializeProcessStructure();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrInitializeProcessStructure failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Parse the command line */
+    Status = CsrParseServerCommandLine(ArgumentCount, Arguments);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrParseServerCommandLine failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* All Server DLLs are now loaded, allocate a heap for the Root Process */
+    ProcessData = RtlAllocateHeap(CsrHeap,
+                                  HEAP_ZERO_MEMORY,
+                                  CsrTotalPerProcessDataLength);
+    if (!ProcessData)
+    {
+        DPRINT1("CSRSRV:%s: RtlAllocateHeap failed (Status=%08lx)\n",
+                __FUNCTION__, STATUS_NO_MEMORY);
+        return STATUS_NO_MEMORY;
+    }
+
+    /*
+     * Our Root Process was never officially initalized, so write the data
+     * for each Server DLL manually.
+     */
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Get the current Server */
+        ServerDll = CsrLoadedServerDll[i];
+
+        /* Is it loaded, and does it have per process data? */
+        if ((ServerDll) && (ServerDll->SizeOfProcessData))
+        {
+            /* It does, give it part of our allocated heap */
+            CsrRootProcess->ServerData[i] = ProcessData;
+
+            /* Move to the next heap position */
+            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
+                                  ServerDll->SizeOfProcessData);
+        }
+        else
+        {
+            /* Nothing for this Server DLL */
+            CsrRootProcess->ServerData[i] = NULL;
+        }
+    }
+
+    /* Now initialize the Root Process manually as well */
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Get the current Server */
+        ServerDll = CsrLoadedServerDll[i];
+
+        /* Is it loaded, and does it a callback for new processes? */
+        if ((ServerDll) && (ServerDll->NewProcessCallback))
+        {
+            /* Call the callback */
+            ServerDll->NewProcessCallback(NULL, CsrRootProcess);
+        }
+    }
+
+    /* Now initialize our API Port */
+    Status = CsrApiPortInitialize();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrApiPortInitialize failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Initialize the API Port for SM communication */
+    Status = CsrSbApiPortInitialize();
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* We're all set! Connect to SM! */
+    Status = SmConnectToSm(&CsrSbApiPortName,
+                           CsrSbApiPort,
+                           IMAGE_SUBSYSTEM_WINDOWS_GUI,
+                           &CsrSmApiPort);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Finito! Signal the event */
+    Status = NtSetEvent(CsrInitializationEvent, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Close the event handle now */
+    NtClose(CsrInitializationEvent);
+
+    /* Have us handle Hard Errors */
+    Status = NtSetDefaultHardErrorPort(CsrApiPort);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/*++
+ * @name CsrPopulateDosDevices
+ * @unimplemented NT5.1
+ *
+ * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
+ * to populate the Dos Devices Object Directory for the session.
+ *
+ * @param None.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrPopulateDosDevices(VOID)
+{
+    DPRINT1("Deprecated API\n");
+    return;
+}
+
+BOOL
+NTAPI
+DllMain(IN HANDLE hDll,
+        IN DWORD dwReason,
+        IN LPVOID lpReserved)
+{
+    /* We don't do much */
+    UNREFERENCED_PARAMETER(hDll);
+    UNREFERENCED_PARAMETER(dwReason);
+    UNREFERENCED_PARAMETER(lpReserved);
+    return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/process.c b/reactos/deprecated/csr/csrsrv/process.c
new file mode 100644 (file)
index 0000000..9bf455d
--- /dev/null
@@ -0,0 +1,1342 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/process.c
+ * PURPOSE:         CSR Server DLL Process Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+PCSR_PROCESS CsrRootProcess = NULL;
+RTL_CRITICAL_SECTION CsrProcessLock;
+ULONG CsrProcessSequenceCount = 5;
+ULONG CsrTotalPerProcessDataLength;
+
+/* 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 CsrAllocateProcess
+ * @implemented NT4
+ *
+ * The CsrAllocateProcess routine allocates a new CSR Process object.
+ *
+ * @return Pointer to the newly allocated CSR Process.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_PROCESS
+NTAPI
+CsrAllocateProcess(VOID)
+{
+    PCSR_PROCESS CsrProcess;
+    ULONG TotalSize;
+
+    /* Calculate the amount of memory this should take */
+    TotalSize = sizeof(CSR_PROCESS) +
+                (CSR_SERVER_DLL_MAX * sizeof(PVOID)) +
+                CsrTotalPerProcessDataLength;
+
+    /* Allocate a Process */
+    CsrProcess = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, TotalSize);
+    if (!CsrProcess) return NULL;
+
+    /* Handle the Sequence Number and protect against overflow */
+    CsrProcess->SequenceNumber = CsrProcessSequenceCount++;
+    if (CsrProcessSequenceCount < 5) CsrProcessSequenceCount = 5;
+
+    /* Increase the reference count */
+    CsrProcess->ReferenceCount++;
+
+    /* Initialize the Thread List */
+    InitializeListHead(&CsrProcess->ThreadList);
+
+    /* Return the Process */
+    return CsrProcess;
+}
+
+/*++
+ * @name CsrServerInitialization
+ * @implemented NT4
+ *
+ * The CsrInitializeProcessStructure routine sets up support for CSR Processes
+ * and CSR Threads.
+ *
+ * @param None.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrInitializeProcessStructure(VOID)
+{
+    NTSTATUS Status;
+    ULONG i;
+
+    /* Initialize the Lock */
+    Status = RtlInitializeCriticalSection(&CsrProcessLock);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Set up the Root Process */
+    CsrRootProcess = CsrAllocateProcess();
+    if (!CsrRootProcess) return STATUS_NO_MEMORY;
+
+    /* Set up the minimal information for it */
+    InitializeListHead(&CsrRootProcess->ListLink);
+    CsrRootProcess->ProcessHandle = (HANDLE)-1;
+    CsrRootProcess->ClientId = NtCurrentTeb()->ClientId;
+
+    /* Initialize the Thread Hash List */
+    for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]);
+
+    /* Initialize the Wait Lock */
+    return RtlInitializeCriticalSection(&CsrWaitListsLock);
+}
+
+/*++
+ * @name CsrDeallocateProcess
+ *
+ * The CsrDeallocateProcess frees the memory associated with a CSR Process.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process to be freed.
+ *
+ * @return None.
+ *
+ * @remarks Do not call this routine. It is reserved for the internal
+ *          thread management routines when a CSR Process has been cleanly
+ *          dereferenced and killed.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess)
+{
+    /* Free the process object from the heap */
+    RtlFreeHeap(CsrHeap, 0, CsrProcess);
+}
+
+/*++
+ * @name CsrInsertProcess
+ *
+ * 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 CsrProcess
+ *        Pointer to the CSR Process which is to be inserted.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
+                 IN PCSR_PROCESS CurrentProcess 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);
+
+    /* Notify the Server DLLs */
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Get the current Server DLL */
+        ServerDll = CsrLoadedServerDll[i];
+
+        /* Make sure it's valid and that it has callback */
+        if ((ServerDll) && (ServerDll->NewProcessCallback))
+        {
+            ServerDll->NewProcessCallback(CurrentProcess, CsrProcess);
+        }
+    }
+}
+
+/*++
+ * @name CsrLockedDereferenceProcess
+ *
+ * The CsrLockedDereferenceProcess dereferences a CSR Process while the
+ * Process Lock is already being held.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process to be dereferenced.
+ *
+ * @return None.
+ *
+ * @remarks This routine will return with the Process Lock held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
+{
+    LONG LockCount;
+
+    /* Decrease reference count */
+    LockCount = --CsrProcess->ReferenceCount;
+    ASSERT(LockCount >= 0);
+    if (!LockCount)
+    {
+        /* Call the generic cleanup code */
+        CsrProcessRefcountZero(CsrProcess);
+        CsrAcquireProcessLock();
+    }
+}
+
+/*++
+ * @name CsrLockedReferenceProcess
+ *
+ * The CsrLockedReferenceProcess refences a CSR Process while the
+ * Process Lock is already being held.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process to be referenced.
+ *
+ * @return None.
+ *
+ * @remarks This routine will return with the Process Lock held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
+{
+    /* Increment the reference count */
+    ++CsrProcess->ReferenceCount;
+}
+
+/*++
+ * @name CsrRemoveProcess
+ *
+ * The CsrRemoveProcess function undoes a CsrInsertProcess operation and
+ * removes the CSR Process from the Process List and notifies Server DLLs
+ * of this removal.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process to remove.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrRemoveProcess(IN PCSR_PROCESS CsrProcess)
+{
+    PCSR_SERVER_DLL ServerDll;
+    ULONG i;
+    ASSERT(ProcessStructureListLocked());
+
+    /* Remove us from the Process List */
+    RemoveEntryList(&CsrProcess->ListLink);
+
+    /* Release the lock */
+    CsrReleaseProcessLock();
+
+    /* Loop every Server DLL */
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Get the Server DLL */
+        ServerDll = CsrLoadedServerDll[i];
+
+        /* Check if it's valid and if it has a Disconnect Callback */
+        if ((ServerDll) && (ServerDll->DisconnectCallback))
+        {
+            /* Call it */
+            ServerDll->DisconnectCallback(CsrProcess);
+        }
+    }
+}
+
+/*++
+ * @name CsrProcessRefcountZero
+ *
+ * The CsrProcessRefcountZero routine is executed when a CSR Process has lost
+ * all its active references. It removes and de-allocates the CSR Process.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process 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 Process has lost all
+ *          its references.
+ *
+ *          This routine is called with the Process Lock held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess)
+{
+    /* Remove the Process from the list */
+    CsrRemoveProcess(CsrProcess);
+
+    /* Check if there's a session */
+    if (CsrProcess->NtSession)
+    {
+        /* Dereference the Session */
+        CsrDereferenceNtSession(CsrProcess->NtSession, 0);
+    }
+
+    /* Close the Client Port if there is one */
+    if (CsrProcess->ClientPort) NtClose(CsrProcess->ClientPort);
+
+    /* Close the process handle */
+    NtClose(CsrProcess->ProcessHandle);
+
+    /* Free the Proces Object */
+    CsrDeallocateProcess(CsrProcess);
+}
+
+/*++
+ * @name CsrpSetToNormalPriority
+ *
+ * The CsrpSetToNormalPriority routine sets the current NT Process'
+ * priority to the normal priority for CSR Processes.
+ *
+ * @param None.
+ *
+ * @return None.
+ *
+ * @remarks The "Normal" Priority corresponds to the Normal Forground
+ *          Priority (9) plus a boost of 4.
+ *
+ *--*/
+VOID
+NTAPI
+CsrpSetToNormalPriority(VOID)
+{
+    KPRIORITY BasePriority = (8 + 1) + 4;
+
+    /* Set the Priority */
+    NtSetInformationProcess(NtCurrentProcess(),
+                            ProcessBasePriority,
+                            &BasePriority,
+                            sizeof(KPRIORITY));
+}
+
+/*++
+ * @name CsrpSetToShutdownPriority
+ *
+ * The CsrpSetToShutdownPriority 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.
+ *
+ * @param None.
+ *
+ * @return None.
+ *
+ * @remarks The "Shutdown" Priority corresponds to the Normal Forground
+ *          Priority (9) plus a boost of 6.
+ *
+ *--*/
+VOID
+NTAPI
+CsrpSetToShutdownPriority(VOID)
+{
+    KPRIORITY SetBasePriority = (8 + 1) + 6;
+    BOOLEAN Old;
+
+    /* Get the shutdown privilege */
+    if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
+                                      TRUE,
+                                      FALSE,
+                                      &Old)))
+    {
+        /* Set the Priority */
+        NtSetInformationProcess(NtCurrentProcess(),
+                                ProcessBasePriority,
+                                &SetBasePriority,
+                                sizeof(KPRIORITY));
+    }
+}
+
+/*++
+ * @name FindProcessForShutdown
+ *
+ * The FindProcessForShutdown routine returns a CSR Process which is ready
+ * to be shutdown, and sets the appropriate shutdown flags for it.
+ *
+ * @param CallerLuid
+ *        Pointer to the LUID of the CSR Process calling this routine.
+ *
+ * @return Pointer to a CSR Process which is ready to be shutdown.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_PROCESS
+NTAPI
+FindProcessForShutdown(IN PLUID CallerLuid)
+{
+    PLIST_ENTRY NextEntry;
+    LUID ProcessLuid;
+    NTSTATUS Status;
+    LUID SystemLuid = SYSTEM_LUID;
+    PCSR_PROCESS CsrProcess;
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS ReturnCsrProcess = NULL;
+    ULONG Level = 0;
+
+    /* Set the List Pointers */
+    NextEntry = CsrRootProcess->ListLink.Flink;
+    while (NextEntry != &CsrRootProcess->ListLink)
+    {
+        /* Get the process */
+        CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
+
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Skip this process if it's already been processed*/
+        if (CsrProcess->Flags & CsrProcessSkipShutdown) continue;
+
+        /* Get the LUID of this Process */
+        Status = CsrGetProcessLuid(CsrProcess->ProcessHandle, &ProcessLuid);
+
+        /* Check if we didn't get access to the LUID */
+        if (Status == STATUS_ACCESS_DENIED)
+        {
+            /* Check if we have any threads */
+            if (CsrProcess->ThreadCount)
+            {
+                /* Impersonate one of the threads and retry */
+                CsrThread = CONTAINING_RECORD(CsrProcess->ThreadList.Flink,
+                                              CSR_THREAD,
+                                              Link);
+                CsrImpersonateClient(CsrThread);
+                Status = CsrGetProcessLuid(NULL, &ProcessLuid);
+                CsrRevertToSelf();
+            }
+        }
+
+        if (!NT_SUCCESS(Status))
+        {
+            /* We didn't have access, so skip it */
+            CsrProcess->Flags |= CsrProcessSkipShutdown;
+            continue;
+        }
+
+        /* Check if this is the System LUID */
+        if (RtlEqualLuid(&ProcessLuid, &SystemLuid))
+        {
+            /* Mark this process */
+            CsrProcess->ShutdownFlags |= CsrShutdownSystem;
+        }
+        else if (!RtlEqualLuid(&ProcessLuid, CallerLuid))
+        {
+            /* Our LUID doesn't match with the caller's */
+            CsrProcess->ShutdownFlags |= CsrShutdownOther;
+        }
+
+        /* Check if we're past the previous level */
+        if ((CsrProcess->ShutdownLevel > Level) || !(ReturnCsrProcess))
+        {
+            /* Update the level */
+            Level = CsrProcess->ShutdownLevel;
+
+            /* Set the final process */
+            ReturnCsrProcess = CsrProcess;
+        }
+    }
+
+    /* Check if we found a process */
+    if (ReturnCsrProcess)
+    {
+        /* Skip this one next time */
+        ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
+    }
+
+    return ReturnCsrProcess;
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*++
+ * @name CsrCreateProcess
+ * @implemented NT4
+ *
+ * Do nothing for 500ms.
+ *
+ * @param ArgumentCount
+ *        Description of the parameter. Wrapped to more lines on ~70th
+ *        column.
+ *
+ * @param Arguments
+ *        Description of the parameter. Wrapped to more lines on ~70th
+ *        column.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+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)
+{
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+    CLIENT_ID CurrentCid;
+    PCSR_PROCESS CurrentProcess;
+    PVOID ProcessData;
+    ULONG i;
+    PCSR_PROCESS CsrProcess;
+    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;
+    }
+
+    /* 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 = &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)
+        {
+            /* Set the pointer */
+            CsrProcess->ServerData[i] = ProcessData;
+
+            /* Copy the Data */
+            RtlMoveMemory(ProcessData,
+                          CurrentProcess->ServerData[i],
+                          CsrLoadedServerDll[i]->SizeOfProcessData);
+
+            /* Update next data pointer */
+            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
+                                  CsrLoadedServerDll[i]->SizeOfProcessData);
+        }
+        else
+        {
+            /* No data for this Server */
+            CsrProcess->ServerData[i] = NULL;
+        }
+    }
+
+    /* Set the Exception port to us */
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessExceptionPort,
+                                     &CsrApiPort,
+                                     sizeof(HANDLE));
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* If 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 we debugging is enabled */
+    if (CsrProcess->DebugFlags)
+    {
+        /* Set the Debug Port to us */
+        Status = NtSetInformationProcess(hProcess,
+                                         ProcessDebugPort,
+                                         &CsrApiPort,
+                                         sizeof(HANDLE));
+        ASSERT(NT_SUCCESS(Status));
+        if (!NT_SUCCESS(Status))
+        {
+            /* Failed */
+            CsrDeallocateProcess(CsrProcess);
+            CsrReleaseProcessLock();
+            return STATUS_NO_MEMORY;
+        }
+    }
+
+    /* 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 a CSR Thread Structure */
+    CsrThread = CsrAllocateThread(CsrProcess);
+    if (!CsrThread)
+    {
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        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 */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Reference the session */
+    CsrReferenceNtSession(NtSession);
+    CsrProcess->NtSession = NtSession;
+
+    /* Setup Process Data */
+    CsrProcess->ClientId = *ClientId;
+    CsrProcess->ProcessHandle = hProcess;
+    CsrProcess->ShutdownLevel = 0x280;
+
+    /* Set the Priority to Background */
+    CsrSetBackgroundPriority(CsrProcess);
+
+    /* Insert the Process */
+    CsrInsertProcess(NULL, CurrentProcess, CsrProcess);
+
+    /* Release lock and return */
+    CsrReleaseProcessLock();
+    return Status;
+}
+
+/*++
+ * @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 CsrServerInitialization
+ * @implemented NT4
+ *
+ * The CsrDebugProcessStop 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
+CsrDebugProcessStop(IN PCSR_PROCESS CsrProcess)
+{
+    /* CSR does not handle debugging anymore */
+    DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
+    return STATUS_UNSUCCESSFUL;
+}
+
+/*++
+ * @name CsrDereferenceProcess
+ * @implemented NT4
+ *
+ * The CsrDereferenceProcess routine removes a reference from a CSR Process.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Process to dereference.
+ *
+ * @return None.
+ *
+ * @remarks If the reference count has reached zero (ie: the CSR Process has
+ *          no more active references), it will be deleted.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
+{
+    LONG LockCount;
+
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Decrease reference count */
+    LockCount = --CsrProcess->ReferenceCount;
+    ASSERT(LockCount >= 0);
+    if (!LockCount)
+    {
+        /* Call the generic cleanup code */
+        CsrProcessRefcountZero(CsrProcess);
+    }
+    else
+    {
+        /* Just release the lock */
+        CsrReleaseProcessLock();
+    }
+}
+
+/*++
+ * @name CsrDestroyProcess
+ * @implemented NT4
+ *
+ * The CsrDestroyProcess routine destroys the CSR Process corresponding to
+ * a given Client ID.
+ *
+ * @param Cid
+ *        Pointer to the Client ID Structure corresponding to the CSR
+ *        Process which is about to be destroyed.
+ *
+ * @param ExitStatus
+ *        Unused.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
+ *         if the CSR Process is already terminating.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrDestroyProcess(IN PCLIENT_ID Cid,
+                  IN NTSTATUS ExitStatus)
+{
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS CsrProcess;
+    CLIENT_ID ClientId = *Cid;
+    PLIST_ENTRY NextEntry;
+
+    /* 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) || (CsrProcess->Flags & CsrProcessTerminating))
+    {
+        /* Release the lock and return failure */
+        CsrReleaseProcessLock();
+        return STATUS_THREAD_IS_TERMINATING;
+    }
+
+    /* Set the terminated flag */
+    CsrProcess->Flags |= CsrProcessTerminating;
+
+    /* Get the List Pointers */
+    NextEntry = CsrProcess->ThreadList.Flink;
+    while (NextEntry != &CsrProcess->ThreadList)
+    {
+        /* Get the current thread entry */
+        CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+        /* Make sure the thread isn't already dead */
+        if (CsrThread->Flags & CsrThreadTerminated)
+        {
+            NextEntry = NextEntry->Flink;
+            continue;
+        }
+
+        /* 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);
+        NextEntry = CsrProcess->ThreadList.Flink;
+    }
+
+    /* Release the Process Lock and return success */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrGetProcessLuid
+ * @implemented NT4
+ *
+ * Do nothing for 500ms.
+ *
+ * @param hProcess
+ *        Optional handle to the process whose LUID should be returned.
+ *
+ * @param Luid
+ *        Pointer to a LUID Pointer which will receive the CSR Process' LUID
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @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
+CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
+                  PLUID Luid)
+{
+    HANDLE hToken = NULL;
+    NTSTATUS Status;
+    ULONG Length;
+    PTOKEN_STATISTICS TokenStats;
+
+    /* Check if we have a handle to a CSR Process */
+    if (!hProcess)
+    {
+        /* We don't, so try opening the Thread's Token */
+        Status = NtOpenThreadToken(NtCurrentThread(),
+                                   TOKEN_QUERY,
+                                   FALSE,
+                                   &hToken);
+
+        /* Check for success */
+        if (!NT_SUCCESS(Status))
+        {
+            /* If we got some other failure, then return and quit */
+            if (Status != STATUS_NO_TOKEN) return Status;
+
+            /* We don't have a Thread Token, use a Process Token */
+            hProcess = NtCurrentProcess();
+            hToken = NULL;
+        }
+    }
+
+    /* Check if we have a token by now */
+    if (!hToken)
+    {
+        /* No token yet, so open the Process Token */
+        Status = NtOpenProcessToken(hProcess,
+                                    TOKEN_QUERY,
+                                    &hToken);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Now get the size we'll need for the Token Information */
+    Status = NtQueryInformationToken(hToken,
+                                     TokenStatistics,
+                                     NULL,
+                                     0,
+                                     &Length);
+
+    /* Allocate memory for the Token Info */
+    TokenStats = RtlAllocateHeap(CsrHeap, 0, Length);
+    if (!TokenStats)
+    {
+        /* Fail and close the token */
+        NtClose(hToken);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Now query the information */
+    Status = NtQueryInformationToken(hToken,
+                                     TokenStatistics,
+                                     TokenStats,
+                                     Length,
+                                     &Length);
+
+    /* Close the handle */
+    NtClose(hToken);
+
+    /* Check for success to return the LUID */
+    if (NT_SUCCESS(Status)) *Luid = TokenStats->AuthenticationId;
+
+    /* Free the query information */
+    RtlFreeHeap(CsrHeap, 0, TokenStats);
+
+    /* Return the Status */
+    return Status;
+}
+
+/*++
+ * @name CsrLockProcessByClientId
+ * @implemented NT4
+ *
+ * The CsrLockProcessByClientId routine locks the CSR Process corresponding
+ * to the given Process ID and optionally returns it.
+ *
+ * @param Pid
+ *        Process ID corresponding to the CSR Process which will be locked.
+ *
+ * @param CsrProcess
+ *        Optional pointer to a CSR Process pointer which will hold the
+ *        CSR Process corresponding to the given Process ID.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks Locking a CSR Process is defined as acquiring an extra
+ *          reference to it and returning with the Process Lock held.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrLockProcessByClientId(IN HANDLE Pid,
+                         OUT PCSR_PROCESS *CsrProcess)
+{
+    PLIST_ENTRY NextEntry;
+    PCSR_PROCESS CurrentProcess = NULL;
+    NTSTATUS Status;
+
+    /* Acquire the lock */
+    CsrAcquireProcessLock();
+
+    /* Assume failure */
+    ASSERT(CsrProcess != NULL);
+    *CsrProcess = NULL;
+
+    /* Setup the List Pointers */
+    NextEntry = &CsrRootProcess->ListLink;
+    do
+    {
+        /* Get the Process */
+        CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
+
+        /* Check for PID Match */
+        if (CurrentProcess->ClientId.UniqueProcess == Pid)
+        {
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    } while (NextEntry != &CsrRootProcess->ListLink);
+
+    /* Check if we didn't find it in the list */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Nothing found, release the lock */
+        CsrReleaseProcessLock();
+    }
+    else
+    {
+        /* Lock the found process and return it */
+        CsrLockedReferenceProcess(CurrentProcess);
+        *CsrProcess = CurrentProcess;
+    }
+    
+    /* Return the result */
+    return Status;
+}
+
+/*++
+ * @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 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 CsrShutdownProcesses
+ * @implemented NT4
+ *
+ * The CsrShutdownProcesses routine shuts down every CSR Process possible
+ * and calls each Server DLL's shutdown notification.
+ *
+ * @param CallerLuid
+ *        Pointer to the LUID of the CSR Process that is ordering the
+ *        shutdown.
+ *
+ * @param Flags
+ *        Flags to send to the shutdown notification routine.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrShutdownProcesses(IN PLUID CallerLuid,
+                     IN ULONG Flags)
+{
+    PLIST_ENTRY NextEntry;
+    PCSR_PROCESS CsrProcess;
+    NTSTATUS Status;
+    BOOLEAN FirstTry;
+    ULONG i;
+    PCSR_SERVER_DLL ServerDll;
+    ULONG Result = 0; /* Intentionally invalid enumeratee to silence compiler warning */
+
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Add shutdown flag */
+    CsrRootProcess->ShutdownFlags |= CsrShutdownSystem;
+
+    /* Get the list pointers */
+    NextEntry = CsrRootProcess->ListLink.Flink;
+    while (NextEntry != &CsrRootProcess->ListLink)
+    {
+        /* Get the Process */
+        CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
+
+        /* 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();
+
+    /* Start looping */
+    while (TRUE)
+    {
+        /* Find the next process to shutdown */
+        CsrProcess = FindProcessForShutdown(CallerLuid);
+        if (!CsrProcess) break;
+
+        /* Increase reference to process */
+        CsrProcess->ReferenceCount++;
+
+        FirstTry = TRUE;
+        while (TRUE)
+        {
+            /* Loop all the servers */
+            for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+            {
+                /* Get the current server */
+                ServerDll = CsrLoadedServerDll[i];
+                if ((ServerDll) && (ServerDll->ShutdownProcessCallback))
+                {
+                    /* Release the lock, make the callback, and acquire it back */
+                    CsrReleaseProcessLock();
+                    Result = ServerDll->ShutdownProcessCallback(CsrProcess,
+                                                                Flags,
+                                                                FirstTry);
+                    CsrAcquireProcessLock();
+
+                    /* Check the result */
+                    if (Result == CsrShutdownCsrProcess)
+                    {
+                        /* The callback unlocked the process */
+                        break;
+                    }
+                    else if (Result == CsrShutdownCancelled)
+                    {
+                        /* Check if this was a forced shutdown */
+                        if (Flags & EWX_FORCE)
+                        {
+                            DPRINT1("Process %x cancelled forced shutdown (Dll = %d)\n",
+                                     CsrProcess->ClientId.UniqueProcess, i);
+                            DbgBreakPoint();
+                        }
+
+                        /* Shutdown was cancelled, unlock and exit */
+                        CsrReleaseProcessLock();
+                        Status = STATUS_CANCELLED;
+                        goto Quickie;
+                    }
+                }
+            }
+
+            /* No matches during the first try, so loop again */
+            if ((FirstTry) && (Result == CsrShutdownNonCsrProcess))
+            {
+                FirstTry = FALSE;
+                continue;
+            }
+
+            /* Second try, break out */
+            break;
+        }
+
+        /* We've reached the final loop here, so dereference */
+        if (i == CSR_SERVER_DLL_MAX) CsrLockedDereferenceProcess(CsrProcess);
+    }
+
+    /* Success path */
+    CsrReleaseProcessLock();
+    Status = STATUS_SUCCESS;
+
+Quickie:
+    /* Return to normal priority */
+    CsrpSetToNormalPriority();
+    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;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/server.c b/reactos/deprecated/csr/csrsrv/server.c
new file mode 100644 (file)
index 0000000..1210005
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/server.c
+ * PURPOSE:         CSR Server DLL Server Functions
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+PCSR_API_ROUTINE CsrServerApiDispatchTable[5] =
+{
+    CsrSrvClientConnect,
+    CsrSrvUnusedFunction,
+    CsrSrvUnusedFunction,
+    CsrSrvIdentifyAlertableThread,
+    CsrSrvSetPriorityClass
+};
+
+BOOLEAN CsrServerApiServerValidTable[5] =
+{
+    TRUE,
+    FALSE,
+    TRUE,
+    TRUE,
+    TRUE
+};
+
+PCHAR CsrServerApiNameTable[5] =
+{
+    "ClientConnect",
+    "ThreadConnect",
+    "ProfileControl",
+    "IdentifyAlertableThread",
+    "SetPriorityClass"
+};
+
+PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
+PVOID CsrSrvSharedSectionHeap;
+PVOID CsrSrvSharedSectionBase;
+PVOID *CsrSrvSharedStaticServerData;
+ULONG CsrSrvSharedSectionSize;
+HANDLE CsrSrvSharedSection;
+
+/* PRIVATE FUNCTIONS**********************************************************/
+
+/*++
+ * @name CsrLoadServerDll
+ * @implemented NT4
+ *
+ * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
+ *
+ * @param DllString
+ *        Pointer to the CSR Server DLL to load and call.
+ *
+ * @param EntryPoint
+ *        Pointer to the name of the server's initialization function. If
+ *        this parameter is NULL, the default ServerDllInitialize will be
+ *        assumed.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrLoadServerDll(IN PCHAR DllString,
+                 IN PCHAR EntryPoint OPTIONAL,
+                 IN ULONG ServerId)
+{
+    NTSTATUS Status;
+    ANSI_STRING DllName;
+    UNICODE_STRING TempString, ErrorString;
+    ULONG_PTR Parameters[2];
+    HANDLE hServerDll = NULL;
+    ULONG Size;
+    PCSR_SERVER_DLL ServerDll;
+    STRING EntryPointString;
+    PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure;
+    ULONG Response;
+
+    /* Check if it's beyond the maximum we support */
+    if (ServerId >= CSR_SERVER_DLL_MAX) return STATUS_TOO_MANY_NAMES;
+
+    /* Check if it's already been loaded */
+    if (CsrLoadedServerDll[ServerId]) return STATUS_INVALID_PARAMETER;
+
+    /* Convert the name to Unicode */
+    ASSERT(DllString != NULL);
+    RtlInitAnsiString(&DllName, DllString);
+    Status = RtlAnsiStringToUnicodeString(&TempString, &DllName, TRUE);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* If we are loading ourselves, don't actually load us */
+    if (ServerId != CSR_SRV_SERVER)
+    {
+        /* Load the DLL */
+        Status = LdrLoadDll(NULL, 0, &TempString, &hServerDll);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Setup error parameters */
+            Parameters[0] = (ULONG_PTR)&TempString;
+            Parameters[1] = (ULONG_PTR)&ErrorString;
+            RtlInitUnicodeString(&ErrorString, L"Default Load Path");
+
+            /* Send a hard error */
+            NtRaiseHardError(Status,
+                             2,
+                             3,
+                             Parameters,
+                             OptionOk,
+                             &Response);
+        }
+
+        /* Get rid of the string */
+        RtlFreeUnicodeString(&TempString);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Allocate a CSR DLL Object */
+    Size = sizeof(CSR_SERVER_DLL) + DllName.MaximumLength;
+    ServerDll = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Size);
+    if (!ServerDll)
+    {
+        if (hServerDll) LdrUnloadDll(hServerDll);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Set up the Object */
+    ServerDll->Length = Size;
+    ServerDll->SharedSection = CsrSrvSharedSectionHeap;
+    ServerDll->Event = CsrInitializationEvent;
+    ServerDll->Name.Length = DllName.Length;
+    ServerDll->Name.MaximumLength = DllName.MaximumLength;
+    ServerDll->Name.Buffer = (PCHAR)(ServerDll + 1);
+    if (DllName.Length)
+    {
+        strncpy(ServerDll->Name.Buffer, DllName.Buffer, DllName.Length);
+    }
+    ServerDll->ServerId = ServerId;
+    ServerDll->ServerHandle = hServerDll;
+
+    /* Now get the entrypoint */
+    if (hServerDll)
+    {
+        /* Initialize a string for the entrypoint, or use the default */
+        RtlInitAnsiString(&EntryPointString,
+                          !(EntryPoint) ? "ServerDllInitialization" :
+                                          EntryPoint);
+
+        /* Get a pointer to it */
+        Status = LdrGetProcedureAddress(hServerDll,
+                                        &EntryPointString,
+                                        0,
+                                        (PVOID)&ServerDllInitProcedure);
+    }
+    else
+    {
+        /* No handle, so we are loading ourselves */
+        ServerDllInitProcedure = CsrServerDllInitialization;
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Check if we got the pointer, and call it */
+    if (NT_SUCCESS(Status))
+    {
+        /* Get the result from the Server DLL */
+        Status = ServerDllInitProcedure(ServerDll);
+
+        /* Check for Success */
+        if (NT_SUCCESS(Status))
+        {
+            /*
+             * Add this Server's Per-Process Data Size to the total that each
+             * process will need.
+             */
+            CsrTotalPerProcessDataLength += ServerDll->SizeOfProcessData;
+
+            /* Save the pointer in our list */
+            CsrLoadedServerDll[ServerDll->ServerId] = ServerDll;
+
+            /* Does it use our generic heap? */
+            if (ServerDll->SharedSection != CsrSrvSharedSectionHeap)
+            {
+                /* No, save the pointer to its shared section in our list */
+                CsrSrvSharedStaticServerData[ServerDll->ServerId] = ServerDll->SharedSection;
+            }
+        }
+        else
+        {
+            /* Use shared failure code */
+            goto LoadFailed;
+        }
+    }
+    else
+    {
+LoadFailed:
+        /* Server Init failed, unload it */
+        if (hServerDll) LdrUnloadDll(hServerDll);
+
+        /* Delete the Object */
+        RtlFreeHeap(CsrHeap, 0, ServerDll);
+    }
+
+    /* Return to caller */
+    return Status;
+}
+
+/*++
+ * @name CsrServerDllInitialization
+ * @implemented NT4
+ *
+ * The CsrServerDllInitialization is the initialization routine for
+ * the this Server DLL.
+ *
+ * @param LoadedServerDll
+ *        Pointer to the CSR Server DLL structure representing this Server DLL.
+ *
+ * @return STATUS_SUCCESS.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll)
+{
+    /* Setup the DLL Object */
+    LoadedServerDll->ApiBase = 0;
+    LoadedServerDll->HighestApiSupported = 5;
+    LoadedServerDll->DispatchTable = CsrServerApiDispatchTable;
+    LoadedServerDll->ValidTable = CsrServerApiServerValidTable;
+    LoadedServerDll->NameTable = CsrServerApiNameTable;
+    LoadedServerDll->SizeOfProcessData = 0;
+    LoadedServerDll->ConnectCallback = NULL;
+    LoadedServerDll->DisconnectCallback = NULL;
+
+    /* All done */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSrvClientConnect
+ *
+ * The CsrSrvClientConnect CSR API handles a new connection to a server DLL.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message for this request.
+ *
+ * @param Reply
+ *        Optional reply to this request.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_INVALID_PARAMETER
+ *         or STATUS_TOO_MANY_NAMES in case of failure.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvClientConnect(IN OUT PCSR_API_MESSAGE ApiMessage,
+                    IN OUT PULONG Reply OPTIONAL)
+{
+    NTSTATUS Status;
+    PCSR_CLIENT_CONNECT ClientConnect;
+    PCSR_SERVER_DLL ServerDll;
+    PCSR_PROCESS CurrentProcess = ((PCSR_THREAD)NtCurrentTeb()->CsrClientThread)->Process;
+
+    /* Load the Message, set default reply */
+    ClientConnect = (PCSR_CLIENT_CONNECT)&ApiMessage->CsrClientConnect;
+    *Reply = 0;
+
+    /* Validate the ServerID */
+    if (ClientConnect->ServerId >= CSR_SERVER_DLL_MAX)
+    {
+        return STATUS_TOO_MANY_NAMES;
+    }
+    else if (!CsrLoadedServerDll[ClientConnect->ServerId])
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validate the Message Buffer */
+    if (!(CsrValidateMessageBuffer(ApiMessage,
+                                   ClientConnect->ConnectionInfo,
+                                   ClientConnect->ConnectionInfoSize,
+                                   1)))
+    {
+        /* Fail due to buffer overflow or other invalid buffer */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Load the Server DLL */
+    ServerDll = CsrLoadedServerDll[ClientConnect->ServerId];
+
+    /* Check if it has a Connect Callback */
+    if (ServerDll->ConnectCallback)
+    {
+        /* Call the callback */
+        Status = ServerDll->ConnectCallback(CurrentProcess,
+                                            ClientConnect->ConnectionInfo,
+                                            &ClientConnect->ConnectionInfoSize);
+    }
+    else
+    {
+        /* Assume success */
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Return status */
+    return Status;
+}
+
+/*++
+ * @name CsrSrvCreateSharedSection
+ *
+ * The CsrSrvCreateSharedSection creates the Shared Section that all CSR Server
+ * DLLs and Clients can use to share data.
+ *
+ * @param ParameterValue
+ *        Specially formatted string from our registry command-line which
+ *        specifies various arguments for the shared section.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvCreateSharedSection(IN PCHAR ParameterValue)
+{
+    PCHAR SizeValue = ParameterValue;
+    ULONG Size;
+    NTSTATUS Status;
+    LARGE_INTEGER SectionSize;
+    ULONG ViewSize = 0;
+    PPEB Peb = NtCurrentPeb();
+
+    /* If there's no parameter, fail */
+    if (!ParameterValue) return STATUS_INVALID_PARAMETER;
+
+    /* Find the first comma, and null terminate */
+    while (*SizeValue)
+    {
+        if (*SizeValue == ',')
+        {
+            *SizeValue++ = ANSI_NULL;
+            break;
+        }
+        else
+        {
+            SizeValue++;
+        }
+    }
+
+    /* Make sure it's valid */
+    if (!*SizeValue) return STATUS_INVALID_PARAMETER;
+
+    /* Convert it to an integer */
+    Status = RtlCharToInteger(SizeValue, 0, &Size);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Multiply by 1024 entries and round to page size */
+    CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize);
+
+    /* Create the Secion */
+    SectionSize.LowPart = CsrSrvSharedSectionSize;
+    SectionSize.HighPart = 0;
+    Status = NtCreateSection(&CsrSrvSharedSection,
+                             SECTION_ALL_ACCESS,
+                             NULL,
+                             &SectionSize,
+                             PAGE_EXECUTE_READWRITE,
+                             SEC_BASED | SEC_RESERVE,
+                             NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Map the section */
+    Status = NtMapViewOfSection(CsrSrvSharedSection,
+                                NtCurrentProcess(),
+                                &CsrSrvSharedSectionBase,
+                                0,
+                                0,
+                                NULL,
+                                &ViewSize,
+                                ViewUnmap,
+                                MEM_TOP_DOWN,
+                                PAGE_EXECUTE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        NtClose(CsrSrvSharedSection);
+        return Status;
+    }
+
+    /* FIXME: Write the value to registry */
+
+    /* The Heap is the same place as the Base */
+    CsrSrvSharedSectionHeap = CsrSrvSharedSectionBase;
+
+    /* Create the heap */
+    if (!(RtlCreateHeap(HEAP_ZERO_MEMORY | HEAP_CLASS_7,
+                        CsrSrvSharedSectionHeap,
+                        CsrSrvSharedSectionSize,
+                        PAGE_SIZE,
+                        0,
+                        0)))
+    {
+        /* Failure, unmap section and return */
+        NtUnmapViewOfSection(NtCurrentProcess(), CsrSrvSharedSectionBase);
+        NtClose(CsrSrvSharedSection);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Now allocate space from the heap for the Shared Data */
+    CsrSrvSharedStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
+                                                   0,
+                                                   CSR_SERVER_DLL_MAX *
+                                                   sizeof(PVOID));
+    if (!CsrSrvSharedStaticServerData) return STATUS_NO_MEMORY;
+
+    /* Write the values to the PEB */
+    Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
+    Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
+    Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData;
+
+    /* Return */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSrvAttachSharedSection
+ *
+ * The CsrSrvAttachSharedSection maps the CSR Shared Section into a new
+ * CSR Process' address space, and returns the pointers to the section
+ * through the Connection Info structure.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process that is attempting a connection.
+ *
+ * @param ConnectInfo
+ *        Pointer to the CSR Connection Info structure for the incoming
+ *        connection.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
+                          OUT PCSR_CONNECTION_INFO ConnectInfo)
+{
+    NTSTATUS Status;
+    ULONG ViewSize = 0;
+
+    /* Check if we have a process */
+    if (CsrProcess)
+    {
+        /* Map the sectio into this process */
+        Status = NtMapViewOfSection(CsrSrvSharedSection,
+                                    CsrProcess->ProcessHandle,
+                                    &CsrSrvSharedSectionBase,
+                                    0,
+                                    0,
+                                    NULL,
+                                    &ViewSize,
+                                    ViewUnmap,
+                                    SEC_NO_CHANGE,
+                                    PAGE_EXECUTE_READ);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Write the values in the Connection Info structure */
+    ConnectInfo->SharedSectionBase = CsrSrvSharedSectionBase;
+    ConnectInfo->SharedSectionHeap = CsrSrvSharedSectionHeap;
+    ConnectInfo->SharedSectionData = CsrSrvSharedStaticServerData;
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSrvIdentifyAlertableThread
+ * @implemented NT4
+ *
+ * The CsrSrvIdentifyAlertableThread CSR API marks a CSR Thread as alertable.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message for this request.
+ *
+ * @param Reply
+ *        Pointer to an optional reply to this request.
+ *
+ * @return STATUS_SUCCESS.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvIdentifyAlertableThread(IN OUT PCSR_API_MESSAGE ApiMessage,
+                              IN OUT PULONG Reply)
+{
+    PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
+
+    /* Set the alertable flag */
+    CsrThread->Flags |= CsrThreadAltertable;
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSrvSetPriorityClass
+ * @implemented NT4
+ *
+ * The CsrSrvSetPriorityClass CSR API is deprecated.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message for this request.
+ *
+ * @param Reply
+ *        Pointer to an optional reply to this request.
+ *
+ * @return STATUS_SUCCESS.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvSetPriorityClass(IN OUT PCSR_API_MESSAGE ApiMessage,
+                       IN OUT PULONG Reply)
+{
+    /* Deprecated */
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrSrvUnusedFunction
+ * @implemented NT4
+ *
+ * The CsrSrvUnusedFunction CSR API is a stub for deprecated APIs.
+ *
+ * The CsrSrvSetPriorityClass CSR API is deprecated.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message for this request.
+ *
+ * @param Reply
+ *        Pointer to an optional reply to this request.
+ *
+ * @return STATUS_INVALID_PARAMETER.
+ *
+ * @remarks CsrSrvSetPriorityClass does not use this stub because it must
+ *          return success.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrSrvUnusedFunction(IN OUT PCSR_API_MESSAGE ApiMessage,
+                     IN OUT PULONG Reply)
+{
+    /* Deprecated */
+    return STATUS_INVALID_PARAMETER;
+}
+
+/* PUBLIC FUNCTIONS***********************************************************/
+
+/*++
+ * @name CsrSetCallingSpooler
+ * @implemented NT4
+ *
+ * the CsrSetCallingSpooler routine is deprecated.
+ *
+ * @param Reserved
+ *        Deprecated
+ *
+ * @return None.
+ *
+ * @remarks This routine was used in archaic versions of NT for Printer Drivers.
+ *
+ *--*/
+VOID
+NTAPI
+CsrSetCallingSpooler(ULONG Reserved)
+{
+    /* Deprecated */
+    return;
+}
+
+/*++
+ * @name CsrUnhandledExceptionFilter
+ * @implemented NT5
+ *
+ * The CsrUnhandledExceptionFilter routine handles all exceptions
+ * within SEH-protected blocks.
+ *
+ * @param ExceptionPointers
+ *        System-defined Argument.
+ *
+ * @return EXCEPTION_EXECUTE_HANDLER.
+ *
+ * @remarks None.
+ *
+ *--*/
+LONG
+NTAPI
+CsrUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
+{
+    SYSTEM_KERNEL_DEBUGGER_INFORMATION DebuggerInfo;
+    EXCEPTION_DISPOSITION Result = EXCEPTION_EXECUTE_HANDLER;
+    BOOLEAN OldValue;
+    NTSTATUS Status;
+    UNICODE_STRING ErrorSource;
+    ULONG_PTR ErrorParameters[4];
+    ULONG Response;
+
+    /* Check if a debugger is installed */
+    Status = NtQuerySystemInformation(SystemKernelDebuggerInformation,
+                                      &DebuggerInfo,
+                                      sizeof(DebuggerInfo),
+                                      NULL);
+
+    /* Check if this is Session 0, and the Debugger is Enabled */
+    if ((NtCurrentPeb()->SessionId) && (NT_SUCCESS(Status)) &&
+        (DebuggerInfo.KernelDebuggerEnabled))
+    {
+        /* Call the Unhandled Exception Filter */
+        if ((Result = RtlUnhandledExceptionFilter(ExceptionInfo)) !=
+            EXCEPTION_CONTINUE_EXECUTION)
+        {
+            /* We're going to raise an error. Get Shutdown Privilege first */
+            Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
+                                        TRUE,
+                                        TRUE,
+                                        &OldValue);
+
+            /* Use the Process token if that failed */
+            if (Status == STATUS_NO_TOKEN)
+            {
+                Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
+                                            TRUE,
+                                            FALSE,
+                                            &OldValue);
+            }
+
+            /* Initialize our Name String */
+            RtlInitUnicodeString(&ErrorSource, L"Windows SubSystem");
+
+            /* Set the parameters */
+            ErrorParameters[0] = (ULONG_PTR)&ErrorSource;
+            ErrorParameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
+            ErrorParameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
+            ErrorParameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
+
+            /* Bugcheck */
+            Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
+                                      4,
+                                      1,
+                                      ErrorParameters,
+                                      OptionShutdownSystem,
+                                      &Response);
+        }
+
+        /* Just terminate us */
+        NtTerminateProcess(NtCurrentProcess(),
+                           ExceptionInfo->ExceptionRecord->ExceptionCode);
+    }
+
+    return Result;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/session.c b/reactos/deprecated/csr/csrsrv/session.c
new file mode 100644 (file)
index 0000000..2ec08a6
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/session.c
+ * PURPOSE:         CSR Server DLL Session Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+RTL_CRITICAL_SECTION CsrNtSessionLock;
+LIST_ENTRY CsrNtSessionList;
+HANDLE CsrSmApiPort;
+
+PSB_API_ROUTINE CsrServerSbApiDispatch[5] =
+{
+    CsrSbCreateSession,
+    CsrSbTerminateSession,
+    CsrSbForeignSessionComplete,
+    CsrSbCreateProcess,
+    NULL
+};
+
+PCHAR CsrServerSbApiName[5] =
+{
+    "SbCreateSession",
+    "SbTerminateSession",
+    "SbForeignSessionComplete",
+    "SbCreateProcess",
+    "Unknown Csr Sb Api Number"
+};
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrInitializeNtSessionList
+ *
+ * The CsrInitializeNtSessionList routine sets up support for CSR Sessions.
+ *
+ * @param None
+ *
+ * @return None
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrInitializeNtSessionList(VOID)
+{
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Initialize the Session List */
+    InitializeListHead(&CsrNtSessionList);
+
+    /* Initialize the Session Lock */
+    return RtlInitializeCriticalSection(&CsrNtSessionLock);
+}
+
+/*++
+ * @name CsrAllocateNtSession
+ *
+ * The CsrAllocateNtSession routine allocates a new CSR NT Session.
+ *
+ * @param SessionId
+ *        Session ID of the CSR NT Session to allocate.
+ *
+ * @return Pointer to the newly allocated CSR NT Session.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_NT_SESSION
+NTAPI
+CsrAllocateNtSession(IN ULONG SessionId)
+{
+    PCSR_NT_SESSION NtSession;
+
+    /* Allocate an NT Session Object */
+    NtSession = RtlAllocateHeap(CsrHeap, 0, sizeof(CSR_NT_SESSION));
+    if (NtSession)
+    {
+        /* Setup the Session Object */
+        NtSession->SessionId = SessionId;
+        NtSession->ReferenceCount = 1;
+
+        /* Insert it into the Session List */
+        CsrAcquireNtSessionLock();
+        InsertHeadList(&CsrNtSessionList, &NtSession->SessionLink);
+        CsrReleaseNtSessionLock();
+    }
+    else
+    {
+        ASSERT(NtSession != NULL);
+    }
+
+    /* Return the Session (or NULL) */
+    return NtSession;
+}
+
+/*++
+ * @name CsrReferenceNtSession
+ *
+ * The CsrReferenceNtSession increases the reference count of a CSR NT Session.
+ *
+ * @param Session
+ *        Pointer to the CSR NT Session to reference.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrReferenceNtSession(IN PCSR_NT_SESSION Session)
+{
+    /* Acquire the lock */
+    CsrAcquireNtSessionLock();
+
+    /* Sanity checks */
+    ASSERT(!IsListEmpty(&Session->SessionLink));
+    ASSERT(Session->SessionId != 0);
+    ASSERT(Session->ReferenceCount != 0);
+
+    /* Increase the reference count */
+    Session->ReferenceCount++;
+
+    /* Release the lock */
+    CsrReleaseNtSessionLock();
+}
+
+/*++
+ * @name CsrDereferenceNtSession
+ *
+ * The CsrDereferenceNtSession decreases the reference count of a
+ * CSR NT Session.
+ *
+ * @param Session
+ *        Pointer to the CSR NT Session to reference.
+ *
+ * @param ExitStatus
+ *        If this is the last reference to the session, this argument
+ *        specifies the exit status.
+ *
+ * @return None.
+ *
+ * @remarks CsrDereferenceNtSession will complete the session if
+ *          the last reference to it has been closed.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDereferenceNtSession(IN PCSR_NT_SESSION Session,
+                        IN NTSTATUS ExitStatus)
+{
+    /* Acquire the lock */
+    CsrAcquireNtSessionLock();
+
+    /* Sanity checks */
+    ASSERT(!IsListEmpty(&Session->SessionLink));
+    ASSERT(Session->SessionId != 0);
+    ASSERT(Session->ReferenceCount != 0);
+
+    /* Dereference the Session Object */
+    if (!(--Session->ReferenceCount))
+    {
+        /* Remove it from the list */
+        RemoveEntryList(&Session->SessionLink);
+
+        /* Release the lock */
+        CsrReleaseNtSessionLock();
+
+        /* Tell SM that we're done here */
+        SmSessionComplete(CsrSmApiPort, Session->SessionId, ExitStatus);
+
+        /* Free the Session Object */
+        RtlFreeHeap(CsrHeap, 0, Session);
+    }
+    else
+    {
+        /* Release the lock, the Session is still active */
+        CsrReleaseNtSessionLock();
+    }
+}
+
+
+/* SESSION MANAGER FUNCTIONS**************************************************/
+
+/*++
+ * @name CsrSbCreateSession
+ *
+ * The CsrSbCreateSession API is called by the Session Manager whenever a new
+ * session is created.
+ *
+ * @param ApiMessage
+ *        Pointer to the Session Manager API Message.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks The CsrSbCreateSession routine will initialize a new CSR NT
+ *          Session and allocate a new CSR Process for the subsystem process.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrSbCreateSession(IN PSB_API_MSG ApiMessage)
+{
+    PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession;
+    HANDLE hProcess, hThread;
+    PCSR_PROCESS CsrProcess;
+    NTSTATUS Status;
+    KERNEL_USER_TIMES KernelTimes;
+    PCSR_THREAD CsrThread;
+    PVOID ProcessData;
+    ULONG i;
+
+    /* Save the Process and Thread Handles */
+    hProcess = CreateSession->ProcessInfo.ProcessHandle;
+    hThread = CreateSession->ProcessInfo.ThreadHandle;
+
+    /* Lock the Processes */
+    CsrAcquireProcessLock();
+
+    /* Allocate a new process */
+    CsrProcess = CsrAllocateProcess();
+    if (!CsrProcess)
+    {
+        /* Fail */
+        ApiMessage->ReturnValue = STATUS_NO_MEMORY;
+        CsrReleaseProcessLock();
+        return TRUE;
+    }
+
+    /* Set the exception port */
+    Status = NtSetInformationProcess(hProcess,
+                                     ProcessExceptionPort,
+                                     &CsrApiPort,
+                                     sizeof(HANDLE));
+
+    /* Check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail the request */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+
+        /* Strange as it seems, NTSTATUSes are actually returned */
+        return (BOOLEAN)STATUS_NO_MEMORY;
+    }
+
+    /* Get the Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      &KernelTimes,
+                                      sizeof(KERNEL_USER_TIMES),
+                                      NULL);
+
+    /* Check for success */
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail the request */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+
+        /* Strange as it seems, NTSTATUSes are actually returned */
+        return (BOOLEAN)Status;
+    }
+
+    /* Allocate a new Thread */
+    CsrThread = CsrAllocateThread(CsrProcess);
+    if (!CsrThread)
+    {
+        /* Fail the request */
+        CsrDeallocateProcess(CsrProcess);
+        ApiMessage->ReturnValue = STATUS_NO_MEMORY;
+        CsrReleaseProcessLock();
+        return TRUE;
+    }
+
+    /* Setup the Thread Object */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
+    CsrThread->ThreadHandle = hThread;
+    ProtectHandle(hThread);
+    CsrThread->Flags = 0;
+
+    /* Insert it into the Process List */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Setup Process Data */
+    CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
+    CsrProcess->ProcessHandle = hProcess;
+    CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId);
+
+    /* Set the Process Priority */
+    CsrSetBackgroundPriority(CsrProcess);
+
+    /* Get the first data location */
+    ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX];
+
+    /* Loop every DLL */
+    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
+    {
+        /* Check if the DLL is loaded and has Process Data */
+        if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
+        {
+            /* Write the pointer to the data */
+            CsrProcess->ServerData[i] = ProcessData;
+
+            /* Move to the next data location */
+            ProcessData = (PVOID)((ULONG_PTR)ProcessData +
+                                  CsrLoadedServerDll[i]->SizeOfProcessData);
+        }
+        else
+        {
+            /* Nothing for this Process */
+            CsrProcess->ServerData[i] = NULL;
+        }
+    }
+
+    /* Insert the Process */
+    CsrInsertProcess(NULL, NULL, CsrProcess);
+
+    /* Activate the Thread */
+    ApiMessage->ReturnValue = NtResumeThread(hThread, NULL);
+
+    /* Release lock and return */
+    CsrReleaseProcessLock();
+    return TRUE;
+}
+
+/*++
+ * @name CsrSbForeignSessionComplete
+ *
+ * The CsrSbForeignSessionComplete API is called by the Session Manager
+ * whenever a foreign session is completed (ie: terminated).
+ *
+ * @param ApiMessage
+ *        Pointer to the Session Manager API Message.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks The CsrSbForeignSessionComplete API is not yet implemented.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage)
+{
+    /* Deprecated/Unimplemented in NT */
+    ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
+    return TRUE;
+}
+
+/*++
+ * @name CsrSbTerminateSession
+ *
+ * The CsrSbTerminateSession API is called by the Session Manager
+ * whenever a foreign session should be destroyed.
+ *
+ * @param ApiMessage
+ *        Pointer to the Session Manager API Message.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks The CsrSbTerminateSession API is not yet implemented.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrSbTerminateSession(IN PSB_API_MSG ApiMessage)
+{
+    ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
+    return TRUE;
+}
+
+/*++
+ * @name CsrSbCreateProcess
+ *
+ * The CsrSbCreateProcess API is called by the Session Manager
+ * whenever a foreign session is created and a new process should be started.
+ *
+ * @param ApiMessage
+ *        Pointer to the Session Manager API Message.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks The CsrSbCreateProcess API is not yet implemented.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrSbCreateProcess(IN PSB_API_MSG ApiMessage)
+{
+    ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED;
+    return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/srv.h b/reactos/deprecated/csr/csrsrv/srv.h
new file mode 100644 (file)
index 0000000..48a9f0f
--- /dev/null
@@ -0,0 +1,395 @@
+#ifndef _SRV_H
+#define _SRV_H
+
+/* PSDK/NDK Headers */
+#define NTOS_MODE_USER
+#include <stdio.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <winnt.h>
+#include <ndk/ntndk.h>
+
+/* CSR Header */
+#include <csr/server.h>
+#include <sm/smmsg.h>
+
+/* PSEH for SEH Support */
+#include <pseh/pseh2.h>
+
+/* DEFINES *******************************************************************/
+
+#define CSR_SERVER_DLL_MAX 4
+
+#define CsrAcquireProcessLock() \
+    RtlEnterCriticalSection(&CsrProcessLock);
+
+#define CsrReleaseProcessLock() \
+    RtlLeaveCriticalSection(&CsrProcessLock);
+
+#define CsrAcquireWaitLock() \
+    RtlEnterCriticalSection(&CsrWaitListsLock);
+
+#define CsrReleaseWaitLock() \
+    RtlLeaveCriticalSection(&CsrWaitListsLock);
+
+#define CsrAcquireNtSessionLock() \
+    RtlEnterCriticalSection(&CsrNtSessionLock)
+
+#define CsrReleaseNtSessionLock() \
+    RtlLeaveCriticalSection(&CsrNtSessionLock)
+
+#define CsrHashThread(t) \
+    (HandleToUlong(t)&(256 - 1))
+    
+#define ProcessStructureListLocked() \
+    (CsrProcessLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
+
+#define SM_REG_KEY \
+    L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager"
+
+#define SESSION_ROOT        L"\\Sessions"
+#define GLOBAL_ROOT         L"\\GLOBAL??"
+#define SYMLINK_NAME        L"SymbolicLink"
+#define SB_PORT_NAME        L"SbAbiPort"
+#define CSR_PORT_NAME       L"ApiPort"
+#define UNICODE_PATH_SEP    L"\\"
+
+#define ROUND_UP(n, align) ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
+#define ROUND_DOWN(n, align) (((ULONG)n) & ~((align) - 1l))
+
+/* DATA **********************************************************************/
+
+extern ULONG CsrTotalPerProcessDataLength;
+extern ULONG CsrMaxApiRequestThreads;
+extern PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
+extern PCSR_PROCESS CsrRootProcess;
+extern UNICODE_STRING CsrSbApiPortName;
+extern UNICODE_STRING CsrApiPortName;
+extern HANDLE CsrSbApiPort;
+extern HANDLE CsrSmApiPort;
+extern HANDLE CsrApiPort;
+extern HANDLE CsrHeap;
+extern RTL_CRITICAL_SECTION CsrProcessLock;
+extern RTL_CRITICAL_SECTION CsrWaitListsLock;
+extern LIST_ENTRY CsrThreadHashTable[256];
+extern HANDLE CsrInitializationEvent;
+extern SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
+extern UNICODE_STRING CsrDirectoryName;
+extern HANDLE CsrObjectDirectory;
+extern PSB_API_ROUTINE CsrServerSbApiDispatch[5];
+extern ULONG CsrDebug;
+
+/* FUNCTIONS *****************************************************************/
+
+/* FIXME: Public APIs should go in the CSR Server Include */
+BOOLEAN
+NTAPI
+CsrCaptureArguments(
+    IN PCSR_THREAD CsrThread,
+    IN PCSR_API_MESSAGE ApiMessage
+);
+
+NTSTATUS
+NTAPI
+CsrLoadServerDll(
+    IN PCHAR DllString,
+    IN PCHAR EntryPoint,
+    IN ULONG ServerId
+);
+
+NTSTATUS
+NTAPI
+CsrServerInitialization(
+    ULONG ArgumentCount,
+    PCHAR Arguments[]
+);
+
+BOOLEAN
+NTAPI
+UnProtectHandle(IN HANDLE ObjectHandle);
+
+VOID
+NTAPI
+CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrLockedReferenceThread(IN PCSR_THREAD CsrThread);
+
+NTSTATUS
+NTAPI
+CsrCreateSessionObjectDirectory(IN ULONG SessionId);
+
+NTSTATUS
+NTAPI
+CsrCreateObjectDirectory(IN PCHAR ObjectDirectory);
+
+NTSTATUS
+NTAPI
+CsrSrvCreateSharedSection(IN PCHAR ParameterValue);
+
+NTSTATUS
+NTAPI
+CsrInitializeNtSessionList(VOID);
+
+NTSTATUS
+NTAPI
+CsrInitializeProcessStructure(VOID);
+
+NTSTATUS
+NTAPI
+CsrApiPortInitialize(VOID);
+
+NTSTATUS
+NTAPI
+CsrSbApiPortInitialize(VOID);
+
+BOOLEAN
+NTAPI
+CsrSbCreateSession(IN PSB_API_MSG ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrSbTerminateSession(IN PSB_API_MSG ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrSbCreateProcess(IN PSB_API_MSG ApiMessage);
+
+PCSR_PROCESS
+NTAPI
+CsrAllocateProcess(VOID);
+
+PCSR_THREAD
+NTAPI
+CsrAllocateThread(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrInsertThread(
+    IN PCSR_PROCESS Process,
+    IN PCSR_THREAD Thread
+);
+
+VOID
+NTAPI
+CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess);
+
+NTSTATUS
+NTAPI
+CsrGetProcessLuid(
+    HANDLE hProcess,
+    PLUID Luid
+);
+
+BOOLEAN
+NTAPI
+CsrImpersonateClient(IN PCSR_THREAD CsrThread);
+
+BOOLEAN
+NTAPI
+CsrRevertToSelf(VOID);
+
+PCSR_THREAD
+NTAPI
+CsrLocateThreadByClientId(
+    OUT PCSR_PROCESS *Process,
+    IN PCLIENT_ID ClientId
+);
+
+VOID
+NTAPI
+CsrDereferenceNtSession(
+    IN PCSR_NT_SESSION Session,
+    NTSTATUS ExitStatus
+);
+
+VOID
+NTAPI
+CsrReferenceNtSession(PCSR_NT_SESSION Session);
+
+VOID
+NTAPI
+CsrLockedDereferenceThread(PCSR_THREAD CsrThread);
+
+VOID
+NTAPI
+CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess);
+
+NTSTATUS
+NTAPI
+CsrLockProcessByClientId(
+    IN HANDLE Pid,
+    OUT PCSR_PROCESS *CsrProcess OPTIONAL
+);
+
+NTSTATUS
+NTAPI
+CsrUnlockProcess(PCSR_PROCESS CsrProcess);
+
+NTSTATUS
+NTAPI
+CsrSrvClientConnect(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvUnusedFunction(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvIdentifyAlertableThread(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvSetPriorityClass(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrServerDllInitialization(IN PCSR_SERVER_DLL LoadedServerDll);
+
+VOID
+NTAPI
+CsrDereferenceThread(PCSR_THREAD CsrThread);
+
+VOID
+NTAPI
+CsrSbApiRequestThread(IN PVOID Parameter);
+
+NTSTATUS
+NTAPI
+CsrApiRequestThread(IN PVOID Parameter);
+
+BOOLEAN
+NTAPI
+ProtectHandle(IN HANDLE ObjectHandle);
+
+PCSR_THREAD
+NTAPI
+CsrAddStaticServerThread(
+    IN HANDLE hThread,
+    IN PCLIENT_ID ClientId,
+    IN ULONG ThreadFlags
+);
+
+PCSR_THREAD
+NTAPI
+CsrConnectToUser(VOID);
+
+PCSR_THREAD
+NTAPI
+CsrLocateThreadInProcess(
+    IN PCSR_PROCESS CsrProcess OPTIONAL,
+    IN PCLIENT_ID Cid
+);
+
+NTSTATUS
+NTAPI
+CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message);
+
+NTSTATUS
+NTAPI
+CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage);
+
+NTSTATUS
+NTAPI
+CsrSrvAttachSharedSection(
+    IN PCSR_PROCESS CsrProcess OPTIONAL,
+    OUT PCSR_CONNECTION_INFO ConnectInfo
+);
+
+VOID
+NTAPI
+CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrNotifyWaitBlock(
+    IN PCSR_WAIT_BLOCK WaitBlock,
+    IN PLIST_ENTRY WaitList,
+    IN PVOID WaitArgument1,
+    IN PVOID WaitArgument2,
+    IN ULONG WaitFlags,
+    IN BOOLEAN DereferenceThread
+);
+
+VOID
+NTAPI
+CsrDereferenceProcess(PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrInsertProcess(
+    IN PCSR_PROCESS Parent OPTIONAL,
+    IN PCSR_PROCESS CurrentProcess OPTIONAL,
+    IN PCSR_PROCESS CsrProcess
+);
+
+NTSTATUS
+NTAPI
+CsrPopulateDosDevicesDirectory(
+    IN HANDLE DosDevicesDirectory,
+    IN PPROCESS_DEVICEMAP_INFORMATION DeviceMap
+);
+
+BOOLEAN
+NTAPI
+CsrValidateMessageBuffer(
+    IN PCSR_API_MESSAGE ApiMessage,
+    IN PVOID *Buffer,
+    IN ULONG ArgumentSize,
+    IN ULONG ArgumentCount
+);
+
+NTSTATUS
+NTAPI
+CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd);
+
+NTSTATUS
+NTAPI
+CsrDestroyThread(IN PCLIENT_ID Cid);
+
+NTSTATUS
+NTAPI
+CsrDestroyProcess(
+    IN PCLIENT_ID Cid,
+    IN NTSTATUS ExitStatus
+);
+
+LONG
+NTAPI
+CsrUnhandledExceptionFilter(
+    IN PEXCEPTION_POINTERS ExceptionInfo
+);
+
+VOID
+NTAPI
+CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
+
+NTSTATUS
+NTAPI
+CsrSetDirectorySecurity(IN HANDLE ObjectDirectory);
+#endif
diff --git a/reactos/deprecated/csr/csrsrv/status.h b/reactos/deprecated/csr/csrsrv/status.h
new file mode 100644 (file)
index 0000000..e619443
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * CSRSRV Status 
+ */
+
+/* Organization
+ *
+ * api.c     - Handles the LPC Reply/Request Threads which wait on Sb and Csr APIs.
+ *             Also in charge of creating those threads and setting up the ports.
+ *             Finally, it provides external APIs for validating the API buffers
+ *             and doing server-to-server API calls.
+ *
+ * init.c    - Handles initialization of CSRSRV, including command-line parsing,
+ *             loading the Server DLLs, creating the Session Directories, setting
+ *             up the DosDevices Object Directory, and initializing each component.
+ *
+ * process.c - Handles all internal functions dealing with the CSR Process Object,
+ *             including de/allocation, de/referencing, un/locking, prority, and 
+ *             lookups. Also handles all external APIs which touch the CSR Process Object.
+ *
+ * server.c  - Handles all internal functions related to loading and managing Server
+ *             DLLs, as well as the routines handling the Shared Static Memory Section.
+ *             Holds the API Dispatch/Valid/Name Tables and the public CSR_SERVER API
+ *             interface. Also home of the SEH handler.
+ *
+ * session.c - Handles all internal functions dealing with the CSR Session Object,
+ *             including de/allocation, de/referencing, and un/locking. Holds the SB API
+ *             Dispatch/Name Tables and the public CsrSv API Interface for commmunication
+ *             with the Session Manager.
+ *
+ * thread.c  - Handles all internal functions dealing with the CSR Thread Object,
+ *             including de/allocation, de/referencing, un/locking, impersonation, and
+ *             lookups. Also handles all external APIs which touch the CSR Thread Object.
+ *
+ * wait.c   -  Handles all internal functions dealing with the CSR Wait Object,
+ *             including de/allocation, de/referencing and un/locking. Also implements
+ *             the external Wait API for creating, removing and/or notifying waits.
+ */
+
+/* Exported APIs, their location, and their status
+ * CsrAddStaticServerThread    753E679E 1  - server.c  - IMPLEMENTED
+ * CsrCallServerFromServer     753E4FD9 2  - api.c     - IMPLEMENTED
+ * CsrConnectToUser            753E4E48 3  - api.c     - IMPLEMENTED
+ * CsrCreateProcess            753E6FD3 4  - process.c - IMPLEMENTED
+ * CsrCreateRemoteThread       753E73BD 5  - thread.c  - IMPLEMENTED
+ * CsrCreateThread             753E72DA 6  - thread.c  - IMPLEMENTED
+ * CsrCreateWait               753E770E 7  - wait.c    - IMPLEMENTED
+ * CsrDebugProcess             753E7682 8  - process.c - IMPLEMENTED
+ * CsrDebugProcessStop         753E768A 9  - process.c - IMPLEMENTED
+ * CsrDereferenceProcess       753E6281 10 - process.c - IMPLEMENTED
+ * CsrDereferenceThread        753E6964 11 - thread.c  - IMPLEMENTED
+ * CsrDereferenceWait          753E7886 12 - wait.c    - IMPLEMENTED
+ * CsrDestroyProcess           753E7225 13 - process.c - IMPLEMENTED
+ * CsrDestroyThread            753E7478 14 - thread.c  - IMPLEMENTED
+ * CsrExecServerThread         753E6841 15 - thread.c  - IMPLEMENTED
+ * CsrGetProcessLuid           753E632F 16 - process.c - IMPLEMENTED
+ * CsrImpersonateClient        753E60F8 17 - thread.c  - IMPLEMENTED
+ * CsrLockProcessByClientId    753E668F 18 - process.c - IMPLEMENTED
+ * CsrLockThreadByClientId     753E6719 19 - thread.c  - IMPLEMENTED
+ * CsrMoveSatisfiedWait        753E7909 20 - wait.c    - IMPLEMENTED
+ * CsrNotifyWait               753E782F 21 - wait.c    - IMPLEMENTED
+ * CsrPopulateDosDevices       753E37A5 22 - init.c    - IMPLEMENTED
+ * CsrQueryApiPort             753E4E42 23 - api.c     - IMPLEMENTED
+ * CsrReferenceThread          753E61E5 24 - thread.c  - IMPLEMENTED
+ * CsrRevertToSelf             753E615A 25 - thread.c  - IMPLEMENTED
+ * CsrServerInitialization     753E3D75 26 - server.c  - IMPLEMENTED
+ * CsrSetBackgroundPriority    753E5E87 27 - process.c - IMPLEMENTED
+ * CsrSetCallingSpooler        753E6425 28 - server.c  - IMPLEMENTED
+ * CsrSetForegroundPriority    753E5E67 29 - process.c - IMPLEMENTED
+ * CsrShutdownProcesses        753E7547 30 - process.c - IMPLEMENTED
+ * CsrUnhandledExceptionFilter 753E3FE3 31 - server.c  - IMPLEMENTED
+ * CsrUnlockProcess            753E66FD 32 - process.c - IMPLEMENTED
+ * CsrUnlockThread             753E7503 33 - thread.c  - IMPLEMENTED
+ * CsrValidateMessageBuffer    753E528D 34 - api.c     - IMPLEMENTED
+ * CsrValidateMessageString    753E5323 35 - api.c     - UNIMPLEMENTED
+ */
+
+/* Public CSR API Interface Status (server.c)
+ * CsrSrvClientConnect                                 - IMPLEMENTED
+ * CsrSrvUnusedFunction                                - IMPLEMENTED
+ * CsrSrvIdentifyAlertableThread                       - IMPLEMENTED
+ * CsrSrvSetPriorityClass                              - IMPLEMENTED
+ */
+
+/* Public SB API Interface Status (session.c)
+ * CsrSbCreateSession                                  - IMPLEMENTED
+ * CsrSbForeignSessionComplete                         - IMPLEMENTED
+ * CsrSbTerminateSession                               - UNIMPLEMENTED
+ * CsrSbCreateProcess                                  - UNIMPLEMENTED
+ */
+
+/* What's missing:
+ *
+ * - SMSS needs to be partly re-written to match some things done here.
+ *   Among other things, SmConnectToSm, SmCompleteSession and the other
+ *   Sm* Exported APIs have to be properly implemented, as well as the
+ *   callback calling and SM LPC APIs. [DONE!]
+ *
+ * - NTDLL needs to get the Csr* routines properly implemented. [DONE!]
+ *
+ * - KERNEL32, USER32 need to register with their servers properly.
+ *   Additionally, user32 needs to have ClientThreadStartup implemented
+ *   properly and do the syscall NtUserInitialize (I think) which also
+ *   needs to be implemented in win32k.sys. All this should be less then
+ *   100 lines of code. [KERNEL32 50% DONE, USER32 NOT DONE]
+ *
+ * - The skeleton code for winsrv and basesrv which connects with CSR/CSRSRV
+ *   needs to be written. [NOT DONE]
+ *
+ * - The kernel's LPC implementation needs to be made compatible. [DONE!]
+ */
+
diff --git a/reactos/deprecated/csr/csrsrv/thread.c b/reactos/deprecated/csr/csrsrv/thread.c
new file mode 100644 (file)
index 0000000..c03f61d
--- /dev/null
@@ -0,0 +1,1056 @@
+/*
+ * 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
+#include <debug.h>
+
+/* 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 NextEntry;
+    PCSR_THREAD FoundThread;
+    ASSERT(ProcessStructureListLocked());
+
+    /* Hash the Thread */
+    i = CsrHashThread(ClientId->UniqueThread);
+
+    /* Set the list pointers */
+    NextEntry = CsrThreadHashTable[i].Flink;
+
+    /* Star the loop */
+    while (NextEntry != &CsrThreadHashTable[i])
+    {
+        /* Get the thread */
+        FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
+
+        /* Compare the CID */
+        if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
+        {
+            /* 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 NextEntry;
+    PCSR_THREAD FoundThread = NULL;
+
+    /* Use the Root Process if none was specified */
+    if (!CsrProcess) CsrProcess = CsrRootProcess;
+
+    /* Save the List pointers */
+    NextEntry = CsrProcess->ThreadList.Flink;
+
+    /* Start the Loop */
+    while (NextEntry != &CsrProcess->ThreadList)
+    {
+        /* 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;
+    ASSERT(ProcessStructureListLocked());
+
+    /* 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 */
+    ASSERT(CsrThread->WaitBlock == NULL);
+    RtlFreeHeap(CsrHeap, 0, CsrThread);
+}
+
+/*++
+ * @name CsrLockedReferenceThread
+ *
+ * The CsrLockedReferenceThread refences 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 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(IN PCSR_THREAD CsrThread)
+{
+    LONG LockCount;
+
+    /* Decrease reference count */
+    LockCount = --CsrThread->ReferenceCount;
+    ASSERT(LockCount >= 0);
+    if (!LockCount)
+    {
+        /* 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)
+{
+    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)
+    {
+        /* 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;
+    NTSTATUS Status;
+
+    /* Remove this thread */
+    CsrRemoveThread(CsrThread);
+
+    /* Release the Process Lock */
+    CsrReleaseProcessLock();
+
+    /* Close the NT Thread Handle */
+    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);
+}
+
+/* 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
+ *         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,
+                                      &KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* 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 */
+    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)) 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 */
+    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,
+                IN BOOLEAN HaveClient)
+{
+    NTSTATUS Status;
+    PCSR_THREAD CsrThread, CurrentThread;
+    PCSR_PROCESS CurrentProcess;
+    CLIENT_ID CurrentCid;
+    KERNEL_USER_TIMES KernelTimes;
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    if (HaveClient)
+    {
+        /* Get the current thread and CID */
+        CurrentThread = NtCurrentTeb()->CsrClientThread;
+        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);
+        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 */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* 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))
+    {
+        /* Call the generic cleanup code */
+        CsrThreadRefcountZero(CsrThread);
+    }
+    else
+    {
+        /* Just release the lock */
+        CsrReleaseProcessLock();
+    }
+}
+
+/*++
+ * @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)
+{
+    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 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 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;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+
+    /* Use the current thread if none given */
+    if (!CsrThread) CsrThread = CurrentThread;
+
+    /* Still no thread, something is wrong */
+    if (!CsrThread) return FALSE;
+
+    /* Make the call */
+    Status = NtImpersonateThread(NtCurrentThread(),
+                                 CsrThread->ThreadHandle,
+                                 &CsrSecurityQos);
+    if (!NT_SUCCESS(Status))
+    {
+        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 and return */
+    if (CurrentThread) ++CurrentThread->ImpersonationCount;
+    return TRUE;
+}
+
+/*++
+ * @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 = NtCurrentTeb()->CsrClientThread;
+    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 */
+    ASSERT(NT_SUCCESS(Status));
+    return NT_SUCCESS(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
+ *         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)
+{
+    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 Process */
+        CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
+
+        /* Check for PID Match */
+        if ((CurrentThread->ClientId.UniqueThread == Tid) &&
+            !(CurrentThread->Flags & CsrThreadTerminated))
+        {
+            /* Get out of here */
+            break;
+        }
+
+        /* 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;
+        CurrentThread->ReferenceCount++;
+        *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(PCSR_THREAD CsrThread)
+{
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Sanity checks */
+    ASSERT(CsrThread->Flags & CsrThreadTerminated); // CSR_THREAD_DESTROYED in ASSERT
+    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(PCSR_THREAD CsrThread)
+{
+    /* Dereference the Thread */
+    ASSERT(ProcessStructureListLocked());
+    CsrLockedDereferenceThread(CsrThread);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/csrsrv/wait.c b/reactos/deprecated/csr/csrsrv/wait.c
new file mode 100644 (file)
index 0000000..00d0bdf
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/wait.c
+ * PURPOSE:         CSR Server DLL Wait Implementation
+ * PROGRAMMERS:     Emanuele Aliberti
+ *                  Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "srv.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* DATA **********************************************************************/
+
+RTL_CRITICAL_SECTION CsrWaitListsLock;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrInitializeWait
+ *
+ * The CsrInitializeWait routine initializes a CSR Wait Object.
+ *
+ * @param WaitFunction
+ *        Pointer to the function that will handle this wait.
+ *
+ * @param CsrWaitThread
+ *        Pointer to the CSR Thread that will perform the wait.
+ *
+ * @param WaitApiMessage
+ *        Pointer to the CSR API Message associated to this wait.
+ *
+ * @param WaitContext
+ *        Pointer to a user-defined parameter associated to this wait.
+ *
+ * @param NewWaitBlock
+ *        Pointed to the initialized CSR Wait Block for this wait.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrInitializeWait(IN CSR_WAIT_FUNCTION WaitFunction,
+                  IN PCSR_THREAD CsrWaitThread,
+                  IN OUT PCSR_API_MESSAGE WaitApiMessage,
+                  IN PVOID WaitContext,
+                  OUT PCSR_WAIT_BLOCK *NewWaitBlock)
+{
+    ULONG Size;
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Calculate the size of the wait block */
+    Size = sizeof(CSR_WAIT_BLOCK) -
+           sizeof(WaitBlock->WaitApiMessage) +
+           WaitApiMessage->Header.u1.s1.TotalLength;
+
+    /* Allocate the Wait Block */
+    WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size);
+    if (!WaitBlock)
+    {
+        /* Fail */
+        WaitApiMessage->Status = STATUS_NO_MEMORY;
+        return FALSE;
+    }
+
+    /* Initialize it */
+    WaitBlock->Size = Size;
+    WaitBlock->WaitThread = CsrWaitThread;
+    WaitBlock->WaitContext = WaitContext;
+    WaitBlock->WaitFunction = WaitFunction;
+    WaitBlock->UserWaitList.Flink = NULL;
+    WaitBlock->UserWaitList.Blink = NULL;
+    WaitBlock->WaitList = WaitBlock->UserWaitList;
+
+    /* Copy the message */
+    RtlMoveMemory(&WaitBlock->WaitApiMessage,
+                  WaitApiMessage,
+                  WaitApiMessage->Header.u1.s1.TotalLength);
+
+    /* Return the block */
+    *NewWaitBlock = WaitBlock;
+    return TRUE;
+}
+
+/*++
+ * @name CsrNotifyWaitBlock
+ *
+ * The CsrNotifyWaitBlock routine calls the wait function for a registered
+ * CSR Wait Block, and replies to the attached CSR API Message, if any.
+ *
+ * @param WaitBlock
+ *        Pointer to the CSR Wait Block
+ *
+ * @param WaitList
+ *        Pointer to the wait list for this wait.
+ *
+ * @param WaitArgument[1-2]
+ *        User-defined values to pass to the wait function.
+ *
+ * @param WaitFlags
+ *        Wait flags for this wait.
+ *
+ * @param DereferenceThread
+ *        Specifies whether the CSR Thread should be dereferenced at the
+ *        end of this wait.
+ *
+ * @return TRUE in case of success, FALSE otherwise.
+ *
+ * @remarks After a wait block is notified, the wait function becomes invalid.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock,
+                   IN PLIST_ENTRY WaitList,
+                   IN PVOID WaitArgument1,
+                   IN PVOID WaitArgument2,
+                   IN ULONG WaitFlags,
+                   IN BOOLEAN DereferenceThread)
+{
+    /* Call the wait function */
+    if ((WaitBlock->WaitFunction)(WaitList,
+                                  WaitBlock->WaitThread,
+                                  &WaitBlock->WaitApiMessage,
+                                  WaitBlock->WaitContext,
+                                  WaitArgument1,
+                                  WaitArgument2,
+                                  WaitFlags))
+    {
+        /* The wait is done, clear the block */
+        WaitBlock->WaitThread->WaitBlock = NULL;
+
+        /* Check for captured arguments */
+        if (WaitBlock->WaitApiMessage.CsrCaptureData)
+        {
+            /* Release them */
+            CsrReleaseCapturedArguments(&WaitBlock->WaitApiMessage);
+        }
+
+        /* Reply to the port */
+        NtReplyPort(WaitBlock->WaitThread->Process->ClientPort,
+                    (PPORT_MESSAGE)&WaitBlock->WaitApiMessage);
+
+        /* Check if we should dereference the thread */
+        if (DereferenceThread)
+        {
+            /* Remove it from the Wait List */
+            if (WaitBlock->WaitList.Flink)
+            {
+                RemoveEntryList(&WaitBlock->WaitList);
+            }
+
+            /* Remove it from the User Wait List */
+            if (WaitBlock->UserWaitList.Flink)
+            {
+                RemoveEntryList(&WaitBlock->UserWaitList);
+            }
+
+            /* Dereference teh thread */
+            CsrDereferenceThread(WaitBlock->WaitThread);
+
+            /* Free the wait block */
+            RtlFreeHeap(CsrHeap, 0, WaitBlock);
+        }
+        else
+        {
+            /* The wait is complete, but the thread is being kept alive */
+            WaitBlock->WaitFunction = NULL;
+        }
+    
+        /* The wait suceeded */
+        return TRUE;
+    }
+    
+    /* The wait failed */
+    return FALSE;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*++
+ * @name CsrCreateWait
+ * @implemented NT4
+ *
+ * The CsrCreateWait routine creates a CSR Wait.
+ *
+ * @param WaitList
+ *        Pointer to a list entry of the waits to associate.
+ *
+ * @param WaitFunction
+ *        Pointer to the function that will handle this wait.
+ *
+ * @param CsrWaitThread
+ *        Pointer to the CSR Thread that will perform the wait.
+ *
+ * @param WaitApiMessage
+ *        Pointer to the CSR API Message associated to this wait.
+ *
+ * @param WaitContext
+ *        Pointer to a user-defined parameter associated to this wait.
+ *
+ * @param UserWaitList
+ *        Pointer to a list entry of the user-defined waits to associate.
+ *
+ * @return TRUE in case of success, FALSE otherwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrCreateWait(IN PLIST_ENTRY WaitList,
+              IN CSR_WAIT_FUNCTION WaitFunction,
+              IN PCSR_THREAD CsrWaitThread,
+              IN OUT PCSR_API_MESSAGE WaitApiMessage,
+              IN PVOID WaitContext,
+              IN PLIST_ENTRY UserWaitList OPTIONAL)
+{
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Initialize the wait */
+    if (!CsrInitializeWait(WaitFunction,
+                           CsrWaitThread,
+                           WaitApiMessage,
+                           WaitContext,
+                           &WaitBlock))
+    {
+        return FALSE;
+    }
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Make sure the thread wasn't destroyed */
+    if (CsrWaitThread->Flags & CsrThreadTerminated)
+    {
+        /* Fail the wait */
+        RtlFreeHeap(CsrHeap, 0, WaitBlock);
+        CsrReleaseWaitLock();
+        return FALSE;
+    }
+
+    /* Insert the wait in the queue */
+    InsertTailList(WaitList, &WaitBlock->WaitList);
+
+    /* Insert the User Wait too, if one was given */
+    if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList);
+
+    /* Return */
+    CsrReleaseWaitLock();
+    return TRUE;
+}
+
+/*++
+ * @name CsrDereferenceWait
+ * @implemented NT4
+ *
+ * The CsrDereferenceWait routine derefences a CSR Wait Block.
+ *
+ * @param WaitList
+ *        Pointer to the Wait List associated to the wait.
+
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDereferenceWait(IN PLIST_ENTRY WaitList)
+{
+    PLIST_ENTRY NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Acquire the Process and Wait Locks */
+    CsrAcquireProcessLock();
+    CsrAcquireWaitLock();
+
+    /* Set the list pointers */
+    NextEntry = WaitList->Flink;
+
+    /* Start the loop */
+    while (NextEntry != WaitList)
+    {
+        /* Get the wait block */
+        WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
+
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Check if there's no Wait Routine */
+        if (!WaitBlock->WaitFunction)
+        {
+            /* Remove it from the Wait List */
+            if (WaitBlock->WaitList.Flink)
+            {
+                RemoveEntryList(&WaitBlock->WaitList);
+            }
+
+            /* Remove it from the User Wait List */
+            if (WaitBlock->UserWaitList.Flink)
+            {
+                RemoveEntryList(&WaitBlock->UserWaitList);
+            }
+
+            /* Dereference the thread waiting on it */
+            CsrDereferenceThread(WaitBlock->WaitThread);
+
+            /* Free the block */
+            RtlFreeHeap(CsrHeap, 0, WaitBlock);
+        }
+    }
+
+    /* Release the locks */
+    CsrReleaseWaitLock();
+    CsrReleaseProcessLock();
+}
+
+/*++
+ * @name CsrMoveSatisfiedWait
+ * @implemented NT5
+ *
+ * The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list
+ * to another list entry.
+ *
+ * @param NewEntry
+ *        Pointer to a list entry where the satisfied waits will be added.
+ *
+ * @param WaitList
+ *        Pointer to a list entry to analyze for satisfied waits.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry,
+                     IN PLIST_ENTRY WaitList)
+{
+    PLIST_ENTRY NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Set the List pointers */
+    NextEntry = WaitList->Flink;
+
+    /* Start looping */
+    while (NextEntry != WaitList)
+    {
+        /* Get the Wait block */
+        WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
+
+        /* Go to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Check if there is a Wait Callback */
+        if (WaitBlock->WaitFunction)
+        {
+            /* Remove it from the Wait Block Queue */
+            RemoveEntryList(&WaitBlock->WaitList);
+
+            /* Insert the new entry */
+            InsertTailList(&WaitBlock->WaitList, NewEntry);
+        }
+    }
+
+    /* Release the wait lock */
+    CsrReleaseWaitLock();
+}
+
+/*++
+ * @name CsrNotifyWait
+ * @implemented NT4
+ *
+ * The CsrNotifyWait notifies a CSR Wait Block.
+ *
+ * @param WaitList
+ *        Pointer to the list entry for this wait.
+ *
+ * @param WaitType
+ *        Type of the wait to perform, either WaitAny or WaitAll.
+ *
+ * @param WaitArgument[1-2]
+ *        User-defined argument to pass on to the wait function.
+ *
+ * @return TRUE in case of success, FALSE othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrNotifyWait(IN PLIST_ENTRY WaitList,
+              IN ULONG WaitType,
+              IN PVOID WaitArgument1,
+              IN PVOID WaitArgument2)
+{
+    PLIST_ENTRY NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+    BOOLEAN NotifySuccess = FALSE;
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Set the List pointers */
+    NextEntry = WaitList->Flink;
+
+    /* Start looping */
+    while (NextEntry != WaitList)
+    {
+        /* Get the Wait block */
+        WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList);
+
+        /* Go to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Check if there is a Wait Callback */
+        if (WaitBlock->WaitFunction)
+        {
+            /* Notify the Waiter */
+            NotifySuccess |= CsrNotifyWaitBlock(WaitBlock,
+                                                WaitList,
+                                                WaitArgument1,
+                                                WaitArgument2,
+                                                0,
+                                                FALSE);
+            
+            /* We've already done a wait, so leave unless this is a Wait All */
+            if (WaitType != WaitAll) break;
+        }
+    }
+
+    /* Release the wait lock and return */
+    CsrReleaseWaitLock();
+    return NotifySuccess;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csr/main.c b/reactos/deprecated/csr/main.c
new file mode 100644 (file)
index 0000000..301ff50
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrss.c
+ * PURPOSE:         CSR Executable
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#define WIN32_NO_STATUS
+#include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+#include <csr/server.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+CsrpSetDefaultProcessHardErrorMode (VOID)
+{
+    ULONG DefaultHardErrorMode = 0;
+
+    /* Disable hard errors */
+    NtSetInformationProcess(NtCurrentProcess(),
+                            ProcessDefaultHardErrorMode,
+                            &DefaultHardErrorMode,
+                            sizeof(DefaultHardErrorMode));
+}
+
+/*
+ * Note: Standard entrypoint for Native C Programs.
+ * The OS backend (NtProcessStartup) which calls this routine is
+ * implemented in a CRT-like static library (much like mainCRTStartup).
+ * Do NOT manually add the NtProcessStartup entrypoint or anything else.
+ */
+int
+_cdecl
+_main(int argc,
+      char *argv[],
+      char *envp[],
+      int DebugFlag)
+{
+    KPRIORITY BasePriority = (8 + 1) + 4;
+    NTSTATUS Status;
+    ULONG Response;
+    UNREFERENCED_PARAMETER(envp);
+    UNREFERENCED_PARAMETER(DebugFlag);
+
+    /* Set the Priority */
+    NtSetInformationProcess(NtCurrentProcess(),
+                            ProcessBasePriority,
+                            &BasePriority,
+                            sizeof(KPRIORITY));
+
+    /* Give us IOPL so that we can access the VGA registers */
+    Status = NtSetInformationProcess(NtCurrentProcess(),
+                                     ProcessUserModeIOPL,
+                                     NULL,
+                                     0);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Raise a hard error */
+        DPRINT1("CSRSS: Could not raise IOPL: %x\n", Status);
+        Status = NtRaiseHardError(STATUS_IO_PRIVILEGE_FAILED,
+                                  0,
+                                  0,
+                                  NULL,
+                                  OptionOk,
+                                  &Response);
+    }
+
+    /* Initialize CSR through CSRSRV */
+    Status = CsrServerInitialization(argc, argv);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Kill us */
+        DPRINT1("CSRSS: CsrServerInitialization failed:% lx\n", Status);
+        NtTerminateProcess(NtCurrentProcess(), Status);
+    }
+
+    /* Disable errors */
+    CsrpSetDefaultProcessHardErrorMode();
+
+    /* If this is Session 0, make sure killing us bugchecks the system */
+    if (!NtCurrentPeb()->SessionId) RtlSetProcessIsCritical(TRUE, NULL, FALSE);
+
+    /* Kill this thread. CSRSRV keeps us going */
+    NtTerminateThread(NtCurrentThread(), Status);
+    return 0;
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csrsrv/CMakeLists.txt b/reactos/deprecated/csrsrv/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0fabebe
--- /dev/null
@@ -0,0 +1,31 @@
+
+include_directories(${REACTOS_SOURCE_DIR}/subsystems/win32/csrss/include)
+include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
+
+spec2def(csrsrv.dll csrsrv.spec ADD_IMPORTLIB)
+
+list(APPEND SOURCE
+    api/process.c
+    api/user.c
+    api/wapi.c
+    procsup.c
+    thredsup.c
+    init.c
+    wait.c
+    session.c
+    server.c
+    ${CMAKE_CURRENT_BINARY_DIR}/csrsrv.def)
+
+add_library(csrsrv SHARED ${SOURCE})
+
+target_link_libraries(csrsrv ${PSEH_LIB} smlib)
+
+set_module_type(csrsrv nativedll)
+
+add_importlibs(csrsrv ntdll smdll)
+
+add_pch(csrsrv srv.h)
+
+add_dependencies(csrsrv psdk bugcodes)
+add_cd_file(TARGET csrsrv DESTINATION reactos/system32 FOR all)
+
diff --git a/reactos/deprecated/csrsrv/api/process.c b/reactos/deprecated/csrsrv/api/process.c
new file mode 100644 (file)
index 0000000..2493481
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * subsystems/win32/csrss/csrsrv/api/process.c
+ *
+ * "\windows\ApiPort" port process management functions
+ *
+ * ReactOS Operating System
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <srv.h>
+
+#define NDEBUG
+#include <debug.h>
+    
+extern NTSTATUS CallProcessCreated(PCSR_PROCESS, PCSR_PROCESS);
+
+/* GLOBALS *******************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+/**********************************************************************
+ *     CSRSS API
+ *********************************************************************/
+
+CSR_API(CsrSrvCreateProcess)
+{
+     NTSTATUS Status;
+     HANDLE ProcessHandle, ThreadHandle;
+     PCSR_THREAD CsrThread;
+     PCSR_PROCESS NewProcessData;
+     ULONG Flags, VdmPower = 0, DebugFlags = 0;
+
+     /* Get the current client thread */
+     CsrThread = NtCurrentTeb()->CsrClientThread;
+     ASSERT(CsrThread != NULL);
+
+     /* Extract the flags out of the process handle */
+     Flags = (ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & 3;
+     Request->Data.CreateProcessRequest.ProcessHandle = (HANDLE)((ULONG_PTR)Request->Data.CreateProcessRequest.ProcessHandle & ~3);
+
+     /* Duplicate the process handle */
+     Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
+                                Request->Data.CreateProcessRequest.ProcessHandle,
+                                NtCurrentProcess(),
+                                &ProcessHandle,
+                                0,
+                                0,
+                                DUPLICATE_SAME_ACCESS);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to duplicate process handle\n");
+         return Status;
+     }
+
+     /* Duplicate the thread handle */
+     Status = NtDuplicateObject(CsrThread->Process->ProcessHandle,
+                                Request->Data.CreateProcessRequest.ThreadHandle,
+                                NtCurrentProcess(),
+                                &ThreadHandle,
+                                0,
+                                0,
+                                DUPLICATE_SAME_ACCESS);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to duplicate process handle\n");
+        NtClose(ProcessHandle);
+        return Status;
+    }
+
+    /* See if this is a VDM process */
+    if (VdmPower)
+    {
+        /* Request VDM powers */
+        Status = NtSetInformationProcess(ProcessHandle,
+                                         ProcessWx86Information,
+                                         &VdmPower,
+                                         sizeof(VdmPower));
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to get VDM powers\n");
+            NtClose(ProcessHandle);
+            NtClose(ThreadHandle);
+            return Status;
+        }
+    }
+    
+    /* Convert some flags. FIXME: More need conversion */
+    if (Request->Data.CreateProcessRequest.CreationFlags & CREATE_NEW_PROCESS_GROUP)
+    {
+        DebugFlags |= CsrProcessCreateNewGroup;
+    }
+
+    /* FIXME: SxS Stuff */
+
+    /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */
+    Status = CsrCreateProcess(ProcessHandle,
+                              ThreadHandle,
+                              &Request->Data.CreateProcessRequest.ClientId,
+                              CsrThread->Process->NtSession,
+                              DebugFlags,
+                              NULL);
+    if (Status == STATUS_THREAD_IS_TERMINATING)
+    {
+        DPRINT1("Thread already dead\n");
+        return Status;
+    }
+
+    /* Check for other failures */
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create process/thread structures: %lx\n", Status);
+        return Status;
+    }
+
+    /* FIXME: Should notify user32 */
+
+    /* FIXME: VDM vodoo */
+    
+    /* ReactOS Compatibility */
+    Status = CsrLockProcessByClientId(Request->Data.CreateProcessRequest.ClientId.UniqueProcess, &NewProcessData);
+    ASSERT(Status == STATUS_SUCCESS);
+    if (!(Request->Data.CreateProcessRequest.CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
+    {
+        NewProcessData->ParentConsole = ProcessData->Console;
+        NewProcessData->bInheritHandles = Request->Data.CreateProcessRequest.bInheritHandles;
+    }
+    RtlInitializeCriticalSection(&NewProcessData->HandleTableLock);
+    CallProcessCreated(ProcessData, NewProcessData);
+    CsrUnlockProcess(NewProcessData);
+
+    /* Return the result of this operation */
+    return Status;
+}
+
+CSR_API(CsrSrvCreateThread)
+{
+    PCSR_THREAD CurrentThread;
+    HANDLE ThreadHandle;
+    NTSTATUS Status;
+    PCSR_PROCESS CsrProcess;
+    
+    /* Get the current CSR thread */
+    CurrentThread = NtCurrentTeb()->CsrClientThread;
+    if (!CurrentThread)
+    {
+        DPRINT1("Server Thread TID: [%lx.%lx]\n",
+                Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
+                Request->Data.CreateThreadRequest.ClientId.UniqueThread);
+        return STATUS_SUCCESS; // server-to-server
+    }
+
+    /* Get the CSR Process for this request */
+    CsrProcess = CurrentThread->Process;
+    if (CsrProcess->ClientId.UniqueProcess !=
+        Request->Data.CreateThreadRequest.ClientId.UniqueProcess)
+    {
+        /* This is a remote thread request -- is it within the server itself? */
+        if (Request->Data.CreateThreadRequest.ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess)
+        {
+            /* Accept this without any further work */
+            return STATUS_SUCCESS;
+        }
+
+        /* Get the real CSR Process for the remote thread's process */
+        Status = CsrLockProcessByClientId(Request->Data.CreateThreadRequest.ClientId.UniqueProcess,
+                                          &CsrProcess);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    /* Duplicate the thread handle so we can own it */
+    Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle,
+                               Request->Data.CreateThreadRequest.ThreadHandle,
+                               NtCurrentProcess(),
+                               &ThreadHandle,
+                               0,
+                               0,
+                               DUPLICATE_SAME_ACCESS);
+    if (NT_SUCCESS(Status))
+    {
+        /* Call CSRSRV to tell it about the new thread */
+        Status = CsrCreateThread(CsrProcess,
+                                 ThreadHandle,
+                                 &Request->Data.CreateThreadRequest.ClientId);
+    }
+
+    /* Unlock the process and return */
+    if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess);
+    return Status;
+}
+
+CSR_API(CsrTerminateProcess)
+{
+    PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
+    ASSERT(CsrThread != NULL);
+
+    /* Set magic flag so we don't reply this message back */
+    Request->Type = 0xBABE;
+
+    /* Remove the CSR_THREADs and CSR_PROCESS */
+    return CsrDestroyProcess(&CsrThread->ClientId,
+                             (NTSTATUS)Request->Data.TerminateProcessRequest.uExitCode);
+}
+
+CSR_API(CsrConnectProcess)
+{
+
+   return(STATUS_SUCCESS);
+}
+
+CSR_API(CsrGetShutdownParameters)
+{
+
+  Request->Data.GetShutdownParametersRequest.Level = ProcessData->ShutdownLevel;
+  Request->Data.GetShutdownParametersRequest.Flags = ProcessData->ShutdownFlags;
+
+  return(STATUS_SUCCESS);
+}
+
+CSR_API(CsrSetShutdownParameters)
+{
+
+  ProcessData->ShutdownLevel = Request->Data.SetShutdownParametersRequest.Level;
+  ProcessData->ShutdownFlags = Request->Data.SetShutdownParametersRequest.Flags;
+
+  return(STATUS_SUCCESS);
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csrsrv/api/user.c b/reactos/deprecated/csrsrv/api/user.c
new file mode 100644 (file)
index 0000000..9ce9da0
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * subsystems/win32/csrss/csrsrv/api/user.c
+ *
+ * User functions
+ *
+ * ReactOS Operating System
+ *
+ * PROGRAMMER: Eric Kohl
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <srv.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+static BOOLEAN ServicesProcessIdValid = FALSE;
+static ULONG_PTR ServicesProcessId;
+
+
+/* FUNCTIONS *****************************************************************/
+
+CSR_API(CsrRegisterServicesProcess)
+{
+  if (ServicesProcessIdValid == TRUE)
+    {
+      /* Only accept a single call */
+      return STATUS_INVALID_PARAMETER;
+    }
+  else
+    {
+      ServicesProcessId = (ULONG_PTR)Request->Data.RegisterServicesProcessRequest.ProcessId;
+      ServicesProcessIdValid = TRUE;
+      return STATUS_SUCCESS;
+    }
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csrsrv/api/wapi.c b/reactos/deprecated/csrsrv/api/wapi.c
new file mode 100644 (file)
index 0000000..af4f764
--- /dev/null
@@ -0,0 +1,1400 @@
+/*
+ * subsystems/win32/csrss/csrsrv/api/wapi.c
+ *
+ * CSRSS port message processing
+ *
+ * ReactOS Operating System
+ *
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <srv.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+static unsigned ApiDefinitionsCount = 0;
+static PCSRSS_API_DEFINITION ApiDefinitions = NULL;
+UNICODE_STRING CsrApiPortName;
+volatile LONG CsrpStaticThreadCount;
+volatile LONG CsrpDynamicThreadTotal;
+extern ULONG CsrMaxApiRequestThreads;
+
+/* FUNCTIONS *****************************************************************/
+
+NTSTATUS FASTCALL
+CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions)
+{
+  unsigned NewCount;
+  PCSRSS_API_DEFINITION Scan;
+  PCSRSS_API_DEFINITION New;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+  NewCount = 0;
+  for (Scan = NewDefinitions; 0 != Scan->Handler; Scan++)
+    {
+      NewCount++;
+    }
+
+  New = RtlAllocateHeap(CsrHeap, 0,
+                        (ApiDefinitionsCount + NewCount)
+                        * sizeof(CSRSS_API_DEFINITION));
+  if (NULL == New)
+    {
+      DPRINT1("Unable to allocate memory\n");
+      return STATUS_NO_MEMORY;
+    }
+  if (0 != ApiDefinitionsCount)
+    {
+      RtlCopyMemory(New, ApiDefinitions,
+                    ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION));
+      RtlFreeHeap(CsrHeap, 0, ApiDefinitions);
+    }
+  RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions,
+                NewCount * sizeof(CSRSS_API_DEFINITION));
+  ApiDefinitions = New;
+  ApiDefinitionsCount += NewCount;
+
+  return STATUS_SUCCESS;
+}
+
+VOID
+FASTCALL
+CsrApiCallHandler(PCSR_PROCESS ProcessData,
+                  PCSR_API_MESSAGE Request)
+{
+  unsigned DefIndex;
+  ULONG Type;
+
+  DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
+  Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
+  DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >> 16);
+
+  /* FIXME: Extract DefIndex instead of looping */
+  for (DefIndex = 0; DefIndex < ApiDefinitionsCount; DefIndex++)
+    {
+      if (ApiDefinitions[DefIndex].Type == Type)
+        {
+          if (Request->Header.u1.s1.DataLength < ApiDefinitions[DefIndex].MinRequestSize)
+            {
+              DPRINT1("Request type %d min request size %d actual %d\n",
+                      Type, ApiDefinitions[DefIndex].MinRequestSize,
+                      Request->Header.u1.s1.DataLength);
+              Request->Status = STATUS_INVALID_PARAMETER;
+            }
+          else
+            {
+              Request->Status = (ApiDefinitions[DefIndex].Handler)(ProcessData, Request);
+            }
+          return;
+        }
+    }
+  DPRINT1("CSR: Unknown request type 0x%x\n", Request->Type);
+  Request->Status = STATUS_INVALID_SYSTEM_SERVICE;
+}
+
+VOID
+CallHardError(IN PCSR_THREAD ThreadData,
+              IN PHARDERROR_MSG HardErrorMessage);
+
+static
+VOID
+NTAPI
+CsrHandleHardError(IN PCSR_THREAD ThreadData,
+                   IN OUT PHARDERROR_MSG Message)
+{
+    DPRINT1("CSR: received hard error %lx\n", Message->Status);
+
+    /* Call the hard error handler in win32csr */
+    CallHardError(ThreadData, Message);
+}
+
+/*++
+ * @name CsrCallServerFromServer
+ * @implemented NT4
+ *
+ * The CsrCallServerFromServer routine calls a CSR API from within a server.
+ * It avoids using LPC messages since the request isn't coming from a client.
+ *
+ * @param ReceiveMsg
+ *        Pointer to the CSR API Message to send to the server.
+ *
+ * @param ReplyMsg
+ *        Pointer to the CSR API Message to receive from the server.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION
+ *         if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there
+ *         was a problem executing the API.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg,
+                        PCSR_API_MESSAGE ReplyMsg)
+{
+#if 0 // real code
+    ULONG ServerId;
+    PCSR_SERVER_DLL ServerDll;
+    ULONG ApiId;
+    ULONG Reply;
+    NTSTATUS Status;
+
+    /* Get the Server ID */
+    ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode);
+
+    /* Make sure that the ID is within limits, and the Server DLL loaded */
+    if ((ServerId >= CSR_SERVER_DLL_MAX) ||
+        (!(ServerDll = CsrLoadedServerDll[ServerId])))
+    {
+        /* We are beyond the Maximum Server ID */
+        DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll);
+        ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+        return STATUS_ILLEGAL_FUNCTION;
+    }
+    else
+    {
+        /* Get the API ID */
+        ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode);
+
+        /* Normalize it with our Base ID */
+        ApiId -= ServerDll->ApiBase;
+
+        /* Make sure that the ID is within limits, and the entry exists */
+        if ((ApiId >= ServerDll->HighestApiSupported) ||
+            ((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
+        {
+            /* We are beyond the Maximum API ID, or it doesn't exist */
+            DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
+                    "invalid API to call from the server.\n",
+                    ServerDll->ValidTable[ApiId],
+                    ((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
+                    ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name);
+            DbgBreakPoint();
+            ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+            return STATUS_ILLEGAL_FUNCTION;
+        }
+    }
+
+    if (CsrDebug & 2)
+    {
+        DPRINT1("CSRSS: %s Api Request received from server process\n",
+                ServerDll->NameTable[ApiId]);
+    }
+
+    /* Validation complete, start SEH */
+    _SEH2_TRY
+    {
+        /* Call the API and get the result */
+        Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);
+
+        /* Return the result, no matter what it is */
+        ReplyMsg->Status = Status;
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* If we got an exception, return access violation */
+        ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
+    }
+    _SEH2_END;
+
+    /* Return success */
+    return STATUS_SUCCESS;
+
+#else // Hacky reactos code
+
+    PCSR_PROCESS ProcessData;
+
+    /* Get the Process Data */
+    CsrLockProcessByClientId(&ReceiveMsg->Header.ClientId.UniqueProcess, &ProcessData);
+    if (!ProcessData)
+    {
+        DPRINT1("Message: Unable to find data for process 0x%x\n",
+                ReceiveMsg->Header.ClientId.UniqueProcess);
+        return STATUS_NOT_SUPPORTED;
+    }
+
+    /* Validation complete, start SEH */
+    _SEH2_TRY
+    {
+        /* Call the API and get the result */
+        CsrApiCallHandler(ProcessData, ReplyMsg);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* If we got an exception, return access violation */
+        ReplyMsg->Status = STATUS_ACCESS_VIOLATION;
+    }
+    _SEH2_END;
+
+    /* Release the process reference */
+    CsrUnlockProcess(ProcessData);
+
+    /* Return success */
+    return STATUS_SUCCESS;
+#endif
+}
+
+/*++
+ * @name CsrApiPortInitialize
+ *
+ * The CsrApiPortInitialize routine initializes the LPC Port used for
+ * communications with the Client/Server Runtime (CSR) and initializes the
+ * static thread that will handle connection requests and APIs.
+ *
+ * @param None
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         otherwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrApiPortInitialize(VOID)
+{
+    ULONG Size;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    HANDLE hRequestEvent, hThread;
+    CLIENT_ID ClientId;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD ServerThread;
+
+    /* Calculate how much space we'll need for the Port Name */
+    Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);
+
+    /* Create the buffer for it */
+    CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);
+    if (!CsrApiPortName.Buffer) return STATUS_NO_MEMORY;
+
+    /* Setup the rest of the empty string */
+    CsrApiPortName.Length = 0;
+    CsrApiPortName.MaximumLength = (USHORT)Size;
+    RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);
+    RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);
+    RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);
+    if (CsrDebug & 1)
+    {
+        DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
+        DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld  sizeof( API_MSG ) == %ld\n",
+                sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE));
+    }
+
+    /* FIXME: Create a Security Descriptor */
+
+    /* Initialize the Attributes */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &CsrApiPortName,
+                               0,
+                               NULL,
+                               NULL /* FIXME*/);
+
+    /* Create the Port Object */
+    Status = NtCreatePort(&CsrApiPort,
+                          &ObjectAttributes,
+                          LPC_MAX_DATA_LENGTH, // hack ; sizeof(CSR_CONNECTION_INFO),
+                          LPC_MAX_MESSAGE_LENGTH, // hack ; sizeof(CSR_API_MESSAGE),
+                          16 * PAGE_SIZE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Create the event the Port Thread will use */
+        Status = NtCreateEvent(&hRequestEvent,
+                               EVENT_ALL_ACCESS,
+                               NULL,
+                               SynchronizationEvent,
+                               FALSE);
+        if (NT_SUCCESS(Status))
+        {
+            /* Create the Request Thread */
+            Status = RtlCreateUserThread(NtCurrentProcess(),
+                                         NULL,
+                                         TRUE,
+                                         0,
+                                         0,
+                                         0,
+                                         (PVOID)ClientConnectionThread,//CsrApiRequestThread,
+                                         (PVOID)hRequestEvent,
+                                         &hThread,
+                                         &ClientId);
+            if (NT_SUCCESS(Status))
+            {
+                /* Add this as a static thread to CSRSRV */
+                CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread);
+
+                /* Get the Thread List Pointers */
+                ListHead = &CsrRootProcess->ThreadList;
+                NextEntry = ListHead->Flink;
+
+                /* Start looping the list */
+                while (NextEntry != ListHead)
+                {
+                    /* Get the Thread */
+                    ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+                    /* Start it up */
+                    Status = NtResumeThread(ServerThread->ThreadHandle, NULL);
+
+                    /* Is this a Server Thread? */
+                    if (ServerThread->Flags & CsrThreadIsServerThread)
+                    {
+                        /* If so, then wait for it to initialize */
+                        Status = NtWaitForSingleObject(hRequestEvent, FALSE, NULL);
+                        ASSERT(NT_SUCCESS(Status));
+                    }
+
+                    /* Next thread */
+                    NextEntry = NextEntry->Flink;
+                }
+
+                /* We don't need this anymore */
+                NtClose(hRequestEvent);
+            }
+        }
+    }
+
+    /* Return */
+    return Status;
+}
+
+PBASE_STATIC_SERVER_DATA BaseStaticServerData;
+
+NTSTATUS
+NTAPI
+CreateBaseAcls(OUT PACL* Dacl,
+               OUT PACL* RestrictedDacl)
+{
+    PSID SystemSid, WorldSid, RestrictedSid;
+    SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+    SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
+    NTSTATUS Status;
+    UCHAR KeyValueBuffer[0x40];
+    PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo;
+    UNICODE_STRING KeyName;
+    ULONG ProtectionMode = 0;
+    ULONG AclLength, ResultLength;
+    HANDLE hKey;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+
+    /* Open the Session Manager Key */
+    RtlInitUnicodeString(&KeyName, SM_REG_KEY);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
+    if (NT_SUCCESS(Status))
+    {
+        /* Read the key value */
+        RtlInitUnicodeString(&KeyName, L"ProtectionMode");
+        Status = NtQueryValueKey(hKey,
+                                 &KeyName,
+                                 KeyValuePartialInformation,
+                                 KeyValueBuffer,
+                                 sizeof(KeyValueBuffer),
+                                 &ResultLength);
+
+        /* Make sure it's what we expect it to be */
+        KeyValuePartialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueBuffer;
+        if ((NT_SUCCESS(Status)) && (KeyValuePartialInfo->Type == REG_DWORD) &&
+            (*(PULONG)KeyValuePartialInfo->Data))
+        {
+            /* Save the Protection Mode */
+            ProtectionMode = *(PULONG)KeyValuePartialInfo->Data;
+        }
+
+        /* Close the handle */
+        NtClose(hKey);
+    }
+
+    /* Allocate the System SID */
+    Status = RtlAllocateAndInitializeSid(&NtAuthority,
+                                         1, SECURITY_LOCAL_SYSTEM_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &SystemSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Allocate the World SID */
+    Status = RtlAllocateAndInitializeSid(&WorldAuthority,
+                                         1, SECURITY_WORLD_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &WorldSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Allocate the restricted SID */
+    Status = RtlAllocateAndInitializeSid(&NtAuthority,
+                                         1, SECURITY_RESTRICTED_CODE_RID,
+                                         0, 0, 0, 0, 0, 0, 0,
+                                         &RestrictedSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Allocate one ACL with 3 ACEs each for one SID */
+    AclLength = sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
+                RtlLengthSid(SystemSid) +
+                RtlLengthSid(RestrictedSid) +
+                RtlLengthSid(WorldSid);
+    *Dacl = RtlAllocateHeap(CsrHeap, 0, AclLength);
+    ASSERT(*Dacl != NULL);
+
+    /* Set the correct header fields */
+    Status = RtlCreateAcl(*Dacl, AclLength, ACL_REVISION2);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Give the appropriate rights to each SID */
+    /* FIXME: Should check SessionId/ProtectionMode */
+    Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
+    ASSERT(NT_SUCCESS(Status));
+    Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
+    ASSERT(NT_SUCCESS(Status));
+    Status = RtlAddAccessAllowedAce(*Dacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Now allocate the restricted DACL */
+    *RestrictedDacl = RtlAllocateHeap(CsrHeap, 0, AclLength);
+    ASSERT(*RestrictedDacl != NULL);
+
+    /* Initialize it */
+    Status = RtlCreateAcl(*RestrictedDacl, AclLength, ACL_REVISION2);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* And add the same ACEs as before */
+    /* FIXME: Not really fully correct */
+    Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_QUERY | DIRECTORY_TRAVERSE | DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_SUBDIRECTORY | READ_CONTROL, WorldSid);
+    ASSERT(NT_SUCCESS(Status));
+    Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_ALL_ACCESS, SystemSid);
+    ASSERT(NT_SUCCESS(Status));
+    Status = RtlAddAccessAllowedAce(*RestrictedDacl, ACL_REVISION2, DIRECTORY_TRAVERSE, RestrictedSid);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* The SIDs are captured, can free them now */
+    RtlFreeHeap(CsrHeap, 0, SystemSid);
+    RtlFreeHeap(CsrHeap, 0, WorldSid);
+    RtlFreeHeap(CsrHeap, 0, RestrictedSid);
+    return Status;
+}
+
+VOID
+WINAPI
+BasepFakeStaticServerData(VOID)
+{
+    NTSTATUS Status;
+    WCHAR Buffer[MAX_PATH];
+    PWCHAR HeapBuffer;
+    UNICODE_STRING SystemRootString;
+    UNICODE_STRING UnexpandedSystemRootString = RTL_CONSTANT_STRING(L"%SystemRoot%");
+    UNICODE_STRING BaseSrvCSDString;
+    UNICODE_STRING BaseSrvWindowsDirectory;
+    UNICODE_STRING BaseSrvWindowsSystemDirectory;
+    UNICODE_STRING BnoString;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    ULONG SessionId;
+    HANDLE BaseSrvNamedObjectDirectory;
+    HANDLE BaseSrvRestrictedObjectDirectory;
+    PACL BnoDacl, BnoRestrictedDacl;
+    PSECURITY_DESCRIPTOR BnoSd;
+    HANDLE SymHandle;
+    UNICODE_STRING DirectoryName, SymlinkName;
+    ULONG LuidEnabled;
+    RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[2] =
+    {
+        {
+            NULL,
+            RTL_QUERY_REGISTRY_DIRECT,
+            L"CSDVersion",
+            &BaseSrvCSDString
+        },
+        {0}
+    };
+
+    /* Get the session ID */
+    SessionId = NtCurrentPeb()->SessionId;
+
+    /* Get the Windows directory */
+    RtlInitEmptyUnicodeString(&SystemRootString, Buffer, sizeof(Buffer));
+    Status = RtlExpandEnvironmentStrings_U(NULL,
+                                           &UnexpandedSystemRootString,
+                                           &SystemRootString,
+                                           NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Create the base directory */
+    Buffer[SystemRootString.Length / sizeof(WCHAR)] = UNICODE_NULL;
+    Status = RtlCreateUnicodeString(&BaseSrvWindowsDirectory,
+                                    SystemRootString.Buffer);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Create the system directory */
+    wcscat(SystemRootString.Buffer, L"\\system32");
+    Status = RtlCreateUnicodeString(&BaseSrvWindowsSystemDirectory,
+                                    SystemRootString.Buffer);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* FIXME: Check Session ID */
+    wcscpy(Buffer, L"\\BaseNamedObjects");
+    RtlInitUnicodeString(&BnoString, Buffer);
+
+    /* Allocate the server data */
+    BaseStaticServerData = RtlAllocateHeap(CsrSrvSharedSectionHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           sizeof(BASE_STATIC_SERVER_DATA));
+    ASSERT(BaseStaticServerData != NULL);
+
+    /* Process timezone information */
+    BaseStaticServerData->TermsrvClientTimeZoneId = TIME_ZONE_ID_INVALID;
+    BaseStaticServerData->TermsrvClientTimeZoneChangeNum = 0;
+    Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
+                                      &BaseStaticServerData->TimeOfDay,
+                                      sizeof(BaseStaticServerData->TimeOfDay),
+                                      NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Make a shared heap copy of the Windows directory */
+    BaseStaticServerData->WindowsDirectory = BaseSrvWindowsDirectory;
+    HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
+                                 0,
+                                 BaseSrvWindowsDirectory.MaximumLength);
+    ASSERT(HeapBuffer);
+    RtlCopyMemory(HeapBuffer,
+                  BaseStaticServerData->WindowsDirectory.Buffer,
+                  BaseSrvWindowsDirectory.MaximumLength);
+    BaseStaticServerData->WindowsDirectory.Buffer = HeapBuffer;
+
+    /* Make a shared heap copy of the System directory */
+    BaseStaticServerData->WindowsSystemDirectory = BaseSrvWindowsSystemDirectory;
+    HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
+                                 0,
+                                 BaseSrvWindowsSystemDirectory.MaximumLength);
+    ASSERT(HeapBuffer);
+    RtlCopyMemory(HeapBuffer,
+                  BaseStaticServerData->WindowsSystemDirectory.Buffer,
+                  BaseSrvWindowsSystemDirectory.MaximumLength);
+    BaseStaticServerData->WindowsSystemDirectory.Buffer = HeapBuffer;
+
+    /* This string is not used */
+    RtlInitEmptyUnicodeString(&BaseStaticServerData->WindowsSys32x86Directory,
+                              NULL,
+                              0);
+
+    /* Make a shared heap copy of the BNO directory */
+    BaseStaticServerData->NamedObjectDirectory = BnoString;
+    BaseStaticServerData->NamedObjectDirectory.MaximumLength = BnoString.Length +
+                                                               sizeof(UNICODE_NULL);
+    HeapBuffer = RtlAllocateHeap(CsrSrvSharedSectionHeap,
+                                 0,
+                                 BaseStaticServerData->NamedObjectDirectory.MaximumLength);
+    ASSERT(HeapBuffer);
+    RtlCopyMemory(HeapBuffer,
+                  BaseStaticServerData->NamedObjectDirectory.Buffer,
+                  BaseStaticServerData->NamedObjectDirectory.MaximumLength);
+    BaseStaticServerData->NamedObjectDirectory.Buffer = HeapBuffer;
+
+    /*
+     * Confirmed that in Windows, CSDNumber and RCNumber are actually Length
+     * and MaximumLength of the CSD String, since the same UNICODE_STRING is
+     * being queried twice, the first time as a ULONG!
+     *
+     * Somehow, in Windows this doesn't cause a buffer overflow, but it might
+     * in ReactOS, so this code is disabled until someone figures out WTF.
+     */
+    BaseStaticServerData->CSDNumber = 0;
+    BaseStaticServerData->RCNumber = 0;
+
+    /* Initialize the CSD string and query its value from the registry */
+    RtlInitEmptyUnicodeString(&BaseSrvCSDString, Buffer, sizeof(Buffer));
+    Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
+                                    L"",
+                                    BaseServerRegistryConfigurationTable,
+                                    NULL,
+                                    NULL);
+    if (NT_SUCCESS(Status))
+    {
+        /* Copy into the shared buffer */
+        wcsncpy(BaseStaticServerData->CSDVersion,
+                BaseSrvCSDString.Buffer,
+                BaseSrvCSDString.Length / sizeof(WCHAR));
+    }
+    else
+    {
+        /* NULL-terminate to indicate nothing is there */
+        BaseStaticServerData->CSDVersion[0] = UNICODE_NULL;
+    }
+
+    /* Cache the system information */
+    Status = NtQuerySystemInformation(SystemBasicInformation,
+                                      &BaseStaticServerData->SysInfo,
+                                      sizeof(BaseStaticServerData->SysInfo),
+                                      NULL);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* FIXME: Should query the registry for these */
+    BaseStaticServerData->DefaultSeparateVDM = FALSE;
+    BaseStaticServerData->IsWowTaskReady = FALSE;
+
+    /* Allocate a security descriptor and create it */
+    BnoSd = RtlAllocateHeap(CsrHeap, 0, 1024);
+    ASSERT(BnoSd);
+    Status = RtlCreateSecurityDescriptor(BnoSd, SECURITY_DESCRIPTOR_REVISION);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Create the BNO and \Restricted DACLs */
+    Status = CreateBaseAcls(&BnoDacl, &BnoRestrictedDacl);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Set the BNO DACL as active for now */
+    Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoDacl, FALSE);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Create the BNO directory */
+    RtlInitUnicodeString(&BnoString, L"\\BaseNamedObjects");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &BnoString,
+                               OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               BnoSd);
+    Status = NtCreateDirectoryObject(&BaseSrvNamedObjectDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Check if we are session 0 */
+    if (!SessionId)
+    {
+        /* Mark this as a session 0 directory */
+        Status = NtSetInformationObject(BaseSrvNamedObjectDirectory,
+                                        ObjectSessionInformation,
+                                        NULL,
+                                        0);
+        ASSERT(NT_SUCCESS(Status));
+    }
+
+    /* Check if LUID device maps are enabled */
+    Status = NtQueryInformationProcess(NtCurrentProcess(),
+                                       ProcessLUIDDeviceMapsEnabled,
+                                       &LuidEnabled,
+                                       sizeof(LuidEnabled),
+                                       NULL);
+    ASSERT(NT_SUCCESS(Status));
+    BaseStaticServerData->LUIDDeviceMapsEnabled = LuidEnabled;
+    if (!BaseStaticServerData->LUIDDeviceMapsEnabled)
+    {
+        /* Make Global point back to BNO */
+        RtlInitUnicodeString(&DirectoryName, L"Global");
+        RtlInitUnicodeString(&SymlinkName, L"\\BaseNamedObjects");
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DirectoryName,
+                                   OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                                   BaseSrvNamedObjectDirectory,
+                                   BnoSd);
+        Status = NtCreateSymbolicLinkObject(&SymHandle,
+                                            SYMBOLIC_LINK_ALL_ACCESS,
+                                            &ObjectAttributes,
+                                            &SymlinkName);
+        if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
+
+        /* Make local point back to \Sessions\x\BNO */
+        RtlInitUnicodeString(&DirectoryName, L"Local");
+        ASSERT(SessionId == 0);
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DirectoryName,
+                                   OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                                   BaseSrvNamedObjectDirectory,
+                                   BnoSd);
+        Status = NtCreateSymbolicLinkObject(&SymHandle,
+                                            SYMBOLIC_LINK_ALL_ACCESS,
+                                            &ObjectAttributes,
+                                            &SymlinkName);
+        if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
+
+        /* Make Session point back to BNOLINKS */
+        RtlInitUnicodeString(&DirectoryName, L"Session");
+        RtlInitUnicodeString(&SymlinkName, L"\\Sessions\\BNOLINKS");
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DirectoryName,
+                                   OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                                   BaseSrvNamedObjectDirectory,
+                                   BnoSd);
+        Status = NtCreateSymbolicLinkObject(&SymHandle,
+                                            SYMBOLIC_LINK_ALL_ACCESS,
+                                            &ObjectAttributes,
+                                            &SymlinkName);
+        if ((NT_SUCCESS(Status)) && !(SessionId)) NtClose(SymHandle);
+
+        /* Create the BNO\Restricted directory and set the restricted DACL */
+        RtlInitUnicodeString(&DirectoryName, L"Restricted");
+        Status = RtlSetDaclSecurityDescriptor(BnoSd, TRUE, BnoRestrictedDacl, FALSE);
+        ASSERT(NT_SUCCESS(Status));
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &DirectoryName,
+                                   OBJ_OPENIF | OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
+                                   BaseSrvNamedObjectDirectory,
+                                   BnoSd);
+        Status = NtCreateDirectoryObject(&BaseSrvRestrictedObjectDirectory,
+                                         DIRECTORY_ALL_ACCESS,
+                                         &ObjectAttributes);
+        ASSERT(NT_SUCCESS(Status));
+    }
+
+    /* Finally, set the pointer */
+    CsrSrvSharedStaticServerData[CSR_CONSOLE] = BaseStaticServerData;
+}
+
+NTSTATUS WINAPI
+CsrpHandleConnectionRequest(PPORT_MESSAGE Request)
+{
+    NTSTATUS Status;
+    HANDLE ServerPort = NULL;//, ServerThread = NULL;
+    PCSR_PROCESS ProcessData = NULL;
+    REMOTE_PORT_VIEW RemotePortView;
+//    CLIENT_ID ClientId;
+    BOOLEAN AllowConnection = FALSE;
+    PCSR_CONNECTION_INFO ConnectInfo;
+    ServerPort = NULL;
+
+    DPRINT("CSR: %s: Handling: %p\n", __FUNCTION__, Request);
+
+    ConnectInfo = (PCSR_CONNECTION_INFO)(Request + 1);
+
+    /* Save the process ID */
+    RtlZeroMemory(ConnectInfo, sizeof(CSR_CONNECTION_INFO));
+
+    CsrLockProcessByClientId(Request->ClientId.UniqueProcess, &ProcessData);
+    if (!ProcessData)
+    {
+        DPRINT1("CSRSRV: Unknown process: %lx. Will be rejecting connection\n",
+                Request->ClientId.UniqueProcess);
+    }
+
+    if ((ProcessData) && (ProcessData != CsrRootProcess))
+    {
+        /* Attach the Shared Section */
+        Status = CsrSrvAttachSharedSection(ProcessData, ConnectInfo);
+        if (NT_SUCCESS(Status))
+        {
+            DPRINT("Connection ok\n");
+            AllowConnection = TRUE;
+        }
+        else
+        {
+            DPRINT1("Shared section map failed: %lx\n", Status);
+        }
+    }
+    else if (ProcessData == CsrRootProcess)
+    {
+        AllowConnection = TRUE;
+    }
+
+    /* Release the process */
+    if (ProcessData) CsrUnlockProcess(ProcessData);
+
+    /* Setup the Port View Structure */
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
+    RemotePortView.ViewSize = 0;
+    RemotePortView.ViewBase = NULL;
+
+    /* Save the Process ID */
+    ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
+
+    Status = NtAcceptConnectPort(&ServerPort,
+                                 AllowConnection ? UlongToPtr(ProcessData->SequenceNumber) : 0,
+                                 Request,
+                                 AllowConnection,
+                                 NULL,
+                                 &RemotePortView);
+    if (!NT_SUCCESS(Status))
+    {
+         DPRINT1("CSRSS: NtAcceptConnectPort - failed.  Status == %X\n", Status);
+    }
+    else if (AllowConnection)
+    {
+        if (CsrDebug & 2)
+        {
+            DPRINT1("CSRSS: ClientId: %lx.%lx has ClientView: Base=%p, Size=%lx\n",
+                    Request->ClientId.UniqueProcess,
+                    Request->ClientId.UniqueThread,
+                    RemotePortView.ViewBase,
+                    RemotePortView.ViewSize);
+        }
+
+        /* Set some Port Data in the Process */
+        ProcessData->ClientPort = ServerPort;
+        ProcessData->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;
+        ProcessData->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +
+                                                    (ULONG_PTR)RemotePortView.ViewSize);
+
+        /* Complete the connection */
+        Status = NtCompleteConnectPort(ServerPort);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("CSRSS: NtCompleteConnectPort - failed.  Status == %X\n", Status);
+        }
+    }
+    else
+    {
+        DPRINT1("CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
+                Request->ClientId.UniqueProcess,
+                Request->ClientId.UniqueThread);
+    }
+
+    return Status;
+}
+
+/*++
+ * @name CsrConnectToUser
+ * @implemented NT4
+ *
+ * The CsrConnectToUser connects to the User subsystem.
+ *
+ * @param None
+ *
+ * @return A pointer to the CSR Thread
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrConnectToUser(VOID)
+{
+    PTEB Teb = NtCurrentTeb();
+    PCSR_THREAD CsrThread;
+#if 0
+    NTSTATUS Status;
+    ANSI_STRING DllName;
+    UNICODE_STRING TempName;
+    HANDLE hUser32;
+    STRING StartupName;
+
+    /* Check if we didn't already find it */
+    if (!CsrClientThreadSetup)
+    {
+        /* Get the DLL Handle for user32.dll */
+        RtlInitAnsiString(&DllName, "user32");
+        RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);
+        Status = LdrGetDllHandle(NULL,
+                                 NULL,
+                                 &TempName,
+                                 &hUser32);
+        RtlFreeUnicodeString(&TempName);
+
+        /* If we got teh handle, get the Client Thread Startup Entrypoint */
+        if (NT_SUCCESS(Status))
+        {
+            RtlInitAnsiString(&StartupName,"ClientThreadSetup");
+            Status = LdrGetProcedureAddress(hUser32,
+                                            &StartupName,
+                                            0,
+                                            (PVOID)&CsrClientThreadSetup);
+        }
+    }
+
+    /* Connect to user32 */
+    CsrClientThreadSetup();
+#endif
+    /* Save pointer to this thread in TEB */
+    CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
+    if (CsrThread) Teb->CsrClientThread = CsrThread;
+
+    /* Return it */
+    return CsrThread;
+}
+
+/*++
+ * @name CsrpCheckRequestThreads
+ *
+ * The CsrpCheckRequestThreads routine checks if there are no more threads
+ * to handle CSR API Requests, and creates a new thread if possible, to
+ * avoid starvation.
+ *
+ * @param None.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         if a new thread couldn't be created.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrpCheckRequestThreads(VOID)
+{
+    HANDLE hThread;
+    CLIENT_ID ClientId;
+    NTSTATUS Status;
+
+    /* Decrease the count, and see if we're out */
+    if (!(_InterlockedDecrement(&CsrpStaticThreadCount)))
+    {
+        /* Check if we've still got space for a Dynamic Thread */
+        if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
+        {
+            /* Create a new dynamic thread */
+            Status = RtlCreateUserThread(NtCurrentProcess(),
+                                         NULL,
+                                         TRUE,
+                                         0,
+                                         0,
+                                         0,
+                                         (PVOID)ClientConnectionThread,//CsrApiRequestThread,
+                                         NULL,
+                                         &hThread,
+                                         &ClientId);
+            /* Check success */
+            if (NT_SUCCESS(Status))
+            {
+                /* Increase the thread counts */
+                _InterlockedIncrement(&CsrpStaticThreadCount);
+                _InterlockedIncrement(&CsrpDynamicThreadTotal);
+
+                /* Add a new server thread */
+                if (CsrAddStaticServerThread(hThread,
+                                             &ClientId,
+                                             CsrThreadIsServerThread))
+                {
+                    /* Activate it */
+                    NtResumeThread(hThread, NULL);
+                }
+                else
+                {
+                    /* Failed to create a new static thread */
+                    _InterlockedDecrement(&CsrpStaticThreadCount);
+                    _InterlockedDecrement(&CsrpDynamicThreadTotal);
+
+                    /* Terminate it */
+                    DPRINT1("Failing\n");
+                    NtTerminateThread(hThread, 0);
+                    NtClose(hThread);
+
+                    /* Return */
+                    return STATUS_UNSUCCESSFUL;
+                }
+            }
+        }
+    }
+
+    /* Success */
+    return STATUS_SUCCESS;
+}
+
+VOID
+WINAPI
+ClientConnectionThread(IN PVOID Parameter)
+{
+    PTEB Teb = NtCurrentTeb();
+    LARGE_INTEGER TimeOut;
+    NTSTATUS Status;
+    BYTE RawRequest[LPC_MAX_DATA_LENGTH];
+    PCSR_API_MESSAGE Request = (PCSR_API_MESSAGE)RawRequest;
+    PCSR_API_MESSAGE Reply;
+    PCSR_PROCESS CsrProcess;
+    PCSR_THREAD ServerThread, CsrThread;
+    ULONG MessageType;
+    HANDLE ReplyPort;
+    PDBGKM_MSG DebugMessage;
+    PHARDERROR_MSG HardErrorMsg;
+    PCLIENT_DIED_MSG ClientDiedMsg;
+    DPRINT("CSR: %s called\n", __FUNCTION__);
+
+    /* Setup LPC loop port and message */
+    Reply = NULL;
+    ReplyPort = CsrApiPort;
+
+    /* Connect to user32 */
+    while (!CsrConnectToUser())
+    {
+        /* Set up the timeout for the connect (30 seconds) */
+        TimeOut.QuadPart = -30 * 1000 * 1000 * 10;
+
+        /* Keep trying until we get a response */
+        Teb->Win32ClientInfo[0] = 0;
+        NtDelayExecution(FALSE, &TimeOut);
+    }
+
+    /* Get our thread */
+    ServerThread = Teb->CsrClientThread;
+
+    /* If we got an event... */
+    if (Parameter)
+    {
+        /* Set it, to let stuff waiting on us load */
+        Status = NtSetEvent((HANDLE)Parameter, NULL);
+        ASSERT(NT_SUCCESS(Status));
+
+        /* Increase the Thread Counts */
+        _InterlockedIncrement(&CsrpStaticThreadCount);
+        _InterlockedIncrement(&CsrpDynamicThreadTotal);
+    }
+
+    /* Now start the loop */
+    while (TRUE)
+    {
+        /* Make sure the real CID is set */
+        Teb->RealClientId = Teb->ClientId;
+
+        /* Debug check */
+        if (Teb->CountOfOwnedCriticalSections)
+        {
+            DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
+                    Teb->CountOfOwnedCriticalSections);
+            DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",
+                    Request, Reply);
+            DbgBreakPoint();
+        }
+
+        /* Send the reply and wait for a new request */
+        DPRINT("Replying to: %lx (%lx)\n", ReplyPort, CsrApiPort);
+        Status = NtReplyWaitReceivePort(ReplyPort,
+                                        0,
+                                        &Reply->Header,
+                                        &Request->Header);
+        /* Check if we didn't get success */
+        if (Status != STATUS_SUCCESS)
+        {
+            /* Was it a failure or another success code? */
+            if (!NT_SUCCESS(Status))
+            {
+                /* Check for specific status cases */
+                if ((Status != STATUS_INVALID_CID) &&
+                    (Status != STATUS_UNSUCCESSFUL) &&
+                    ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
+                {
+                    /* Notify the debugger */
+                    DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
+                    DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
+                }
+
+                /* We failed big time, so start out fresh */
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+                DPRINT1("failed: %lx\n", Status);
+                continue;
+            }
+            else
+            {
+                /* A bizare "success" code, just try again */
+                DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
+                continue;
+            }
+        }
+
+        /* Use whatever Client ID we got */
+        Teb->RealClientId = Request->Header.ClientId;
+
+        /* Get the Message Type */
+        MessageType = Request->Header.u2.s2.Type;
+
+        /* Handle connection requests */
+        if (MessageType == LPC_CONNECTION_REQUEST)
+        {
+            /* Handle the Connection Request */
+            DPRINT("Accepting new connection\n");
+            CsrpHandleConnectionRequest((PPORT_MESSAGE)Request);
+            Reply = NULL;
+            ReplyPort = CsrApiPort;
+            continue;
+        }
+
+        /* It's some other kind of request. Get the lock for the lookup */
+        CsrAcquireProcessLock();
+
+        /* Now do the lookup to get the CSR_THREAD */
+        CsrThread = CsrLocateThreadByClientId(&CsrProcess,
+                                              &Request->Header.ClientId);
+
+        /* Did we find a thread? */
+        if (!CsrThread)
+        {
+            /* This wasn't a CSR Thread, release lock */
+            CsrReleaseProcessLock();
+
+            /* If this was an exception, handle it */
+            if (MessageType == LPC_EXCEPTION)
+            {
+                DPRINT1("Exception from unknown thread, just continue\n");
+                Reply = Request;
+                ReplyPort = CsrApiPort;
+                Reply->Status = DBG_CONTINUE;
+            }
+            else if (MessageType == LPC_PORT_CLOSED ||
+                     MessageType == LPC_CLIENT_DIED)
+            {
+                /* The Client or Port are gone, loop again */
+                DPRINT("Death from unknown thread, just continue\n");
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+            }
+            else if (MessageType == LPC_ERROR_EVENT)
+            {
+                /* If it's a hard error, handle this too */
+                DPRINT1("Hard error from unknown thread, call handlers\n");
+HandleHardError:
+                HardErrorMsg = (PHARDERROR_MSG)Request;
+
+                /* Default it to unhandled */
+                HardErrorMsg->Response = ResponseNotHandled;
+
+                /* Check if there are free api threads */
+                CsrpCheckRequestThreads();
+                if (CsrpStaticThreadCount)
+                {
+                    CsrHandleHardError(CsrThread, (PHARDERROR_MSG)Request);
+                }
+
+                /* If the response was 0xFFFFFFFF, we'll ignore it */
+                if (HardErrorMsg->Response == 0xFFFFFFFF)
+                {
+                    Reply = NULL;
+                    ReplyPort = CsrApiPort;
+                }
+                else
+                {
+                    if (CsrThread) CsrDereferenceThread(CsrThread);
+                    Reply = Request;
+                    ReplyPort = CsrApiPort;
+                }
+            }
+            else if (MessageType == LPC_REQUEST)
+            {
+                /* This is an API Message coming from a non-CSR Thread */
+                DPRINT1("No thread found for request %lx and clientID %lx.%lx\n",
+                        Request->Type & 0xFFFF,
+                        Request->Header.ClientId.UniqueProcess,
+                        Request->Header.ClientId.UniqueThread);
+                Reply = Request;
+                ReplyPort = CsrApiPort;
+                Reply->Status = STATUS_ILLEGAL_FUNCTION;
+            }
+            else if (MessageType == LPC_DATAGRAM)
+            {
+                DPRINT1("Kernel datagram: not yet supported\n");
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+            }
+            else
+            {
+                /* Some other ignored message type */
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+            }
+
+            /* Keep going */
+            continue;
+        }
+
+        /* We have a valid thread, was this an LPC Request? */
+        if (MessageType != LPC_REQUEST)
+        {
+            /* It's not an API, check if the client died */
+            if (MessageType == LPC_CLIENT_DIED)
+            {
+                /* Get the information and check if it matches our thread */
+                ClientDiedMsg = (PCLIENT_DIED_MSG)Request;
+                if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
+                {
+                    /* Reference the thread */
+                    CsrLockedReferenceThread(CsrThread);
+
+                    /* Destroy the thread in the API Message */
+                    CsrDestroyThread(&Request->Header.ClientId);
+
+                    /* Check if the thread was actually ourselves */
+                    if (CsrProcess->ThreadCount == 1)
+                    {
+                        /* Kill the process manually here */
+                        DPRINT1("Last thread\n");
+                        CsrDestroyProcess(&CsrThread->ClientId, 0);
+                    }
+
+                    /* Remove our extra reference */
+                    CsrLockedDereferenceThread(CsrThread);
+                }
+
+                /* Release the lock and keep looping */
+                CsrReleaseProcessLock();
+                Reply = NULL;
+                ReplyPort = CsrApiPort;
+                continue;
+            }
+
+            /* Reference the thread and release the lock */
+            CsrLockedReferenceThread(CsrThread);
+            CsrReleaseProcessLock();
+
+            /* If this was an exception, handle it */
+            if (MessageType == LPC_EXCEPTION)
+            {
+                /* Kill the process */
+                DPRINT1("Exception in %lx.%lx. Killing...\n",
+                        Request->Header.ClientId.UniqueProcess,
+                        Request->Header.ClientId.UniqueThread);
+                NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);
+
+                /* Destroy it from CSR */
+                CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED);
+
+                /* Return a Debug Message */
+                DebugMessage = (PDBGKM_MSG)Request;
+                DebugMessage->ReturnedStatus = DBG_CONTINUE;
+                Reply = Request;
+                ReplyPort = CsrApiPort;
+
+                /* Remove our extra reference */
+                CsrDereferenceThread(CsrThread);
+            }
+            else if (MessageType == LPC_ERROR_EVENT)
+            {
+                DPRINT1("Hard error from known CSR thread... handling\n");
+                goto HandleHardError;
+            }
+            else
+            {
+                /* Something else */
+                DPRINT1("Unhandled message type: %lx\n", MessageType);
+                CsrDereferenceThread(CsrThread);
+                Reply = NULL;
+            }
+
+            /* Keep looping */
+            continue;
+        }
+
+        /* We got an API Request */
+        CsrLockedReferenceThread(CsrThread);
+        CsrReleaseProcessLock();
+
+        /* Assume success */
+        Reply = Request;
+        Request->Status = STATUS_SUCCESS;
+
+        /* Now we reply to a particular client */
+        ReplyPort = CsrThread->Process->ClientPort;
+
+        DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
+                Request->Type,
+                Request->Header.ClientId.UniqueThread);
+
+        /* Validation complete, start SEH */
+        _SEH2_TRY
+        {
+            /* Make sure we have enough threads */
+            CsrpCheckRequestThreads();
+
+            /* Set the client thread pointer */
+            NtCurrentTeb()->CsrClientThread = CsrThread;
+
+            /* Call the Handler */
+            CsrApiCallHandler(CsrThread->Process, Request);
+
+            /* Increase the static thread count */
+            _InterlockedIncrement(&CsrpStaticThreadCount);
+
+            /* Restore the server thread */
+            NtCurrentTeb()->CsrClientThread = ServerThread;
+
+            /* Check if this is a dead client now */
+            if (Request->Type == 0xBABE)
+            {
+                /* Reply to the death message */
+                NtReplyPort(ReplyPort, &Reply->Header);
+
+                /* Reply back to the API port now */
+                ReplyPort = CsrApiPort;
+                Reply = NULL;
+
+                /* Drop the reference */
+                CsrDereferenceThread(CsrThread);
+            }
+            else
+            {
+                /* Drop the reference */
+                CsrDereferenceThread(CsrThread);
+            }
+        }
+        _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+        {
+            Reply = NULL;
+            ReplyPort = CsrApiPort;
+        }
+        _SEH2_END;
+    }
+
+    /* Close the port and exit the thread */
+    // NtClose(ServerPort);
+
+    DPRINT1("CSR: %s done\n", __FUNCTION__);
+    /* We're out of the loop for some reason, terminate! */
+    NtTerminateThread(NtCurrentThread(), Status);
+    //return Status;
+}
+
+/*++
+ * @name CsrReleaseCapturedArguments
+ * @implemented NT5.1
+ *
+ * The CsrReleaseCapturedArguments routine releases a Capture Buffer
+ * that was previously captured with CsrCaptureArguments.
+ *
+ * @param ApiMessage
+ *        Pointer to the CSR API Message containing the Capture Buffer
+ *        that needs to be released.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
+{
+    PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
+    SIZE_T BufferDistance;
+    ULONG PointerCount;
+    ULONG_PTR **PointerOffsets, *CurrentPointer;
+
+    /* Get the capture buffers */
+    RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
+    LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
+
+    /* Free the previous one */
+    RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
+
+    /* Find out the difference between the two buffers */
+    BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;
+
+    /* Save the pointer count and offset pointer */
+    PointerCount = RemoteCaptureBuffer->PointerCount;
+    PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);
+
+    /* Start the loop */
+    while (PointerCount)
+    {
+        /* Get the current pointer */
+        CurrentPointer = *PointerOffsets++;
+        if (CurrentPointer)
+        {
+            /* Add it to the CSR Message structure */
+            CurrentPointer += (ULONG_PTR)ApiMessage;
+
+            /* Modify the pointer to take into account its new position */
+            *CurrentPointer += BufferDistance;
+        }
+
+        /* Move to the next Pointer */
+        PointerCount--;
+    }
+
+    /* Copy the data back */
+    RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
+
+    /* Free our allocated buffer */
+    RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
+}
+
+/* EOF */
diff --git a/reactos/deprecated/csrsrv/csrsrv.rc b/reactos/deprecated/csrsrv/csrsrv.rc
new file mode 100644 (file)
index 0000000..fbe30d3
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "Client/Server Runtime SubSystem Process\0"
+#define REACTOS_STR_INTERNAL_NAME      "csrsrv\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "csrsrv.dll\0"
+#include <reactos/version.rc>
diff --git a/reactos/deprecated/csrsrv/csrsrv.spec b/reactos/deprecated/csrsrv/csrsrv.spec
new file mode 100644 (file)
index 0000000..19f4428
--- /dev/null
@@ -0,0 +1,36 @@
+@ stdcall CsrAddStaticServerThread(ptr ptr long)
+@ stdcall CsrCallServerFromServer(ptr ptr)
+;@ stdcall CsrConnectToUser()
+;@ stdcall CsrCreateProcess(ptr ptr ptr ptr long ptr)
+@ stdcall CsrCreateRemoteThread(ptr ptr)
+@ stdcall CsrCreateThread(ptr ptr ptr)
+;@ stdcall CsrCreateWait(ptr ptr ptr ptr ptr ptr)
+;@ stdcall CsrDebugProcess(ptr)
+;@ stdcall CsrDebugProcessStop(ptr)
+;@ stdcall CsrDereferenceProcess(ptr)
+;@ stdcall CsrDereferenceThread(ptr)
+;@ stdcall CsrDereferenceWait(ptr)
+;@ stdcall CsrDestroyProcess(ptr long)
+;@ stdcall CsrDestroyThread(ptr)
+@ stdcall CsrEnumProcesses(ptr ptr) ; Temporary hack
+;@ stdcall CsrExecServerThread(ptr long)
+@ stdcall CsrGetProcessLuid(ptr ptr)
+@ stdcall CsrImpersonateClient(ptr)
+@ stdcall CsrLockProcessByClientId(ptr ptr)
+;@ stdcall CsrLockThreadByClientId(ptr ptr)
+;@ stdcall CsrMoveSatisfiedWait(ptr ptr)
+;@ stdcall CsrNotifyWait(ptr long ptr ptr)
+;@ stdcall CsrPopulateDosDevices()
+;@ stdcall CsrQueryApiPort()
+;@ stdcall CsrReferenceThread(ptr)
+@ stdcall CsrRevertToSelf()
+@ stdcall CsrServerInitialization(long ptr)
+;@ stdcall CsrSetBackgroundPriority(ptr)
+;@ stdcall CsrSetCallingSpooler(long)
+;@ stdcall CsrSetForegroundPriority(ptr)
+;@ stdcall CsrShutdownProcesses(ptr long)
+;@ stdcall CsrUnhandledExceptionFilter(ptr)
+@ stdcall CsrUnlockProcess(ptr)
+;@ stdcall CsrUnlockThread(ptr)
+;@ stdcall CsrValidateMessageBuffer(ptr ptr long long)
+;@ stdcall CsrValidateMessageString(ptr ptr)
diff --git a/reactos/deprecated/csrsrv/include/api.h b/reactos/deprecated/csrsrv/include/api.h
new file mode 100644 (file)
index 0000000..6a71ee0
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS system libraries
+ * FILE:            subsys/csrss/include/api.h
+ * PURPOSE:         CSRSS API interface
+ */
+
+#pragma once
+
+#define NTOS_MODE_USER
+#include <ndk/psfuncs.h>
+#include <ndk/rtlfuncs.h>
+
+#include <csrss/csrss.h>
+
+#define CSR_SRV_SERVER 0
+#define CSR_SERVER_DLL_MAX 4
+#define LOCK   RtlEnterCriticalSection(&ProcessDataLock)
+#define UNLOCK RtlLeaveCriticalSection(&ProcessDataLock)
+#define CsrAcquireProcessLock() LOCK
+#define CsrReleaseProcessLock() UNLOCK
+#define ProcessStructureListLocked() \
+    (ProcessDataLock.OwningThread == NtCurrentTeb()->ClientId.UniqueThread)
+
+#define CsrAcquireWaitLock() \
+    RtlEnterCriticalSection(&CsrWaitListsLock);
+
+#define CsrReleaseWaitLock() \
+    RtlLeaveCriticalSection(&CsrWaitListsLock);
+
+#define CsrAcquireNtSessionLock() \
+    RtlEnterCriticalSection(&CsrNtSessionLock);
+
+#define CsrReleaseNtSessionLock() \
+    RtlLeaveCriticalSection(&CsrNtSessionLock);
+
+typedef enum _CSR_THREAD_FLAGS
+{
+    CsrThreadAltertable     = 0x1,
+    CsrThreadInTermination  = 0x2,
+    CsrThreadTerminated     = 0x4,
+    CsrThreadIsServerThread = 0x10
+} CSR_THREAD_FLAGS, *PCSR_THREAD_FLAGS;
+
+typedef enum _SHUTDOWN_RESULT
+{
+    CsrShutdownCsrProcess = 1,
+    CsrShutdownNonCsrProcess,
+    CsrShutdownCancelled
+} SHUTDOWN_RESULT, *PSHUTDOWN_RESULT;
+
+typedef enum _CSR_SHUTDOWN_FLAGS
+{
+    CsrShutdownSystem = 4,
+    CsrShutdownOther  = 8
+} CSR_SHUTDOWN_FLAGS, *PCSR_SHUTDOWN_FLAGS;
+
+typedef enum _CSR_DEBUG_FLAGS
+{
+    CsrDebugOnlyThisProcess = 1,
+    CsrDebugProcessChildren = 2
+} CSR_PROCESS_DEBUG_FLAGS, *PCSR_PROCESS_DEBUG_FLAGS;
+
+typedef enum _CSR_PROCESS_FLAGS
+{
+    CsrProcessTerminating          = 0x1,
+    CsrProcessSkipShutdown         = 0x2,
+    CsrProcessNormalPriority       = 0x10,
+    CsrProcessIdlePriority         = 0x20,
+    CsrProcessHighPriority         = 0x40,
+    CsrProcessRealtimePriority     = 0x80,
+    CsrProcessCreateNewGroup       = 0x100,
+    CsrProcessTerminated           = 0x200,
+    CsrProcessLastThreadTerminated = 0x400,
+    CsrProcessIsConsoleApp         = 0x800
+} CSR_PROCESS_FLAGS, *PCSR_PROCESS_FLAGS;
+
+#define CsrProcessPriorityFlags (CsrProcessNormalPriority | \
+                                 CsrProcessIdlePriority   | \
+                                 CsrProcessHighPriority   | \
+                                 CsrProcessRealtimePriority)
+
+typedef struct _CSRSS_CON_PROCESS_DATA
+{
+    HANDLE ConsoleEvent;
+    struct tagCSRSS_CONSOLE *Console;
+    struct tagCSRSS_CONSOLE *ParentConsole;
+    BOOL bInheritHandles;
+    RTL_CRITICAL_SECTION HandleTableLock;
+    ULONG HandleTableSize;
+    struct _CSRSS_HANDLE *HandleTable;
+    PCONTROLDISPATCHER CtrlDispatcher;
+    LIST_ENTRY ConsoleLink;
+} CSRSS_CON_PROCESS_DATA, *PCSRSS_CON_PROCESS_DATA;
+
+typedef struct _CSR_NT_SESSION
+{
+    ULONG ReferenceCount;
+    LIST_ENTRY SessionLink;
+    ULONG SessionId;
+} CSR_NT_SESSION, *PCSR_NT_SESSION;
+
+typedef struct _CSR_PROCESS
+{
+    CLIENT_ID ClientId;
+    LIST_ENTRY ListLink;
+    LIST_ENTRY ThreadList;
+    struct _CSR_PROCESS *Parent;
+    PCSR_NT_SESSION NtSession;
+    ULONG ExpectedVersion;
+    HANDLE ClientPort;
+    ULONG_PTR ClientViewBase;
+    ULONG_PTR ClientViewBounds;
+    HANDLE ProcessHandle;
+    ULONG SequenceNumber;
+    ULONG Flags;
+    ULONG DebugFlags;
+    CLIENT_ID DebugCid;
+    ULONG ReferenceCount;
+    ULONG ProcessGroupId;
+    ULONG ProcessGroupSequence;
+    ULONG fVDM;
+    ULONG ThreadCount;
+    ULONG PriorityClass;
+    ULONG Reserved;
+    ULONG ShutdownLevel;
+    ULONG ShutdownFlags;
+//    PVOID ServerData[ANYSIZE_ARRAY];
+    CSRSS_CON_PROCESS_DATA;
+} CSR_PROCESS, *PCSR_PROCESS;
+
+typedef struct _CSR_THREAD
+{
+    LARGE_INTEGER CreateTime;
+    LIST_ENTRY Link;
+    LIST_ENTRY HashLinks;
+    CLIENT_ID ClientId;
+    PCSR_PROCESS Process;
+    struct _CSR_WAIT_BLOCK *WaitBlock;
+    HANDLE ThreadHandle;
+    ULONG Flags;
+    ULONG ReferenceCount;
+    ULONG ImpersonationCount;
+} CSR_THREAD, *PCSR_THREAD;
+
+typedef
+BOOLEAN
+(*CSR_WAIT_FUNCTION)(
+    IN PLIST_ENTRY WaitList,
+    IN PCSR_THREAD WaitThread,
+    IN PCSR_API_MESSAGE WaitApiMessage,
+    IN PVOID WaitContext,
+    IN PVOID WaitArgument1,
+    IN PVOID WaitArgument2,
+    IN ULONG WaitFlags
+);
+
+typedef struct _CSR_WAIT_BLOCK
+{
+    ULONG Size;
+    LIST_ENTRY WaitList;
+    LIST_ENTRY UserWaitList;
+    PVOID WaitContext;
+    PCSR_THREAD WaitThread;
+    CSR_WAIT_FUNCTION WaitFunction;
+    CSR_API_MESSAGE WaitApiMessage;
+} CSR_WAIT_BLOCK, *PCSR_WAIT_BLOCK;
+
+typedef
+NTSTATUS
+(NTAPI *PCSR_CONNECT_CALLBACK)(
+    IN PCSR_PROCESS CsrProcess,
+    IN OUT PVOID ConnectionInfo,
+    IN OUT PULONG ConnectionInfoLength
+);
+
+typedef
+VOID
+(NTAPI *PCSR_DISCONNECT_CALLBACK)(IN PCSR_PROCESS CsrProcess);
+
+typedef
+NTSTATUS
+(NTAPI *PCSR_NEWPROCESS_CALLBACK)(
+    IN PCSR_PROCESS Parent,
+    IN PCSR_PROCESS CsrProcess
+);
+
+typedef
+VOID
+(NTAPI *PCSR_HARDERROR_CALLBACK)(
+    IN PCSR_THREAD CsrThread,
+    IN PHARDERROR_MSG HardErrorMessage
+);
+
+typedef
+ULONG
+(NTAPI *PCSR_SHUTDOWNPROCESS_CALLBACK)(
+    IN PCSR_PROCESS CsrProcess,
+    IN ULONG Flags,
+    IN BOOLEAN FirstPhase
+);
+
+typedef
+NTSTATUS
+(NTAPI *PCSR_API_ROUTINE)(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+typedef struct _CSR_SERVER_DLL
+{
+    ULONG Length;
+    HANDLE Event;
+    ANSI_STRING Name;
+    HANDLE ServerHandle;
+    ULONG ServerId;
+    ULONG Unknown;
+    ULONG ApiBase;
+    ULONG HighestApiSupported;
+    PCSR_API_ROUTINE *DispatchTable;
+    PBOOLEAN ValidTable;
+    PCHAR *NameTable;
+    ULONG SizeOfProcessData;
+    PCSR_CONNECT_CALLBACK ConnectCallback;
+    PCSR_DISCONNECT_CALLBACK DisconnectCallback;
+    PCSR_HARDERROR_CALLBACK HardErrorCallback;
+    PVOID SharedSection;
+    PCSR_NEWPROCESS_CALLBACK NewProcessCallback;
+    PCSR_SHUTDOWNPROCESS_CALLBACK ShutdownProcessCallback;
+    ULONG Unknown2[3];
+} CSR_SERVER_DLL, *PCSR_SERVER_DLL;
+
+typedef
+NTSTATUS
+(NTAPI *PCSR_SERVER_DLL_INIT_CALLBACK)(IN PCSR_SERVER_DLL ServerDll);
+
+
+typedef NTSTATUS (WINAPI *CSRSS_API_PROC)(PCSR_PROCESS ProcessData,
+                                           PCSR_API_MESSAGE Request);
+
+typedef struct _CSRSS_API_DEFINITION
+{
+    ULONG Type;
+    ULONG MinRequestSize;
+    CSRSS_API_PROC Handler;
+} CSRSS_API_DEFINITION, *PCSRSS_API_DEFINITION;
+
+#define CSRSS_DEFINE_API(Func, Handler) \
+  { Func, sizeof(CSRSS_##Func), Handler }
+
+typedef struct _CSRSS_LISTEN_DATA
+{
+  HANDLE ApiPortHandle;
+  ULONG ApiDefinitionsCount;
+  PCSRSS_API_DEFINITION *ApiDefinitions;
+} CSRSS_LISTEN_DATA, *PCSRSS_LISTEN_DATA;
+
+#define CSR_API(n) NTSTATUS WINAPI n (  \
+    PCSR_PROCESS ProcessData,           \
+    PCSR_API_MESSAGE Request)
+
+/* init.c */
+extern HANDLE hBootstrapOk;
+NTSTATUS NTAPI CsrServerInitialization(ULONG ArgumentCount, PCHAR Arguments[]);
+
+/* api/process.c */
+CSR_API(CsrConnectProcess);
+CSR_API(CsrSrvCreateProcess);
+CSR_API(CsrTerminateProcess);
+CSR_API(CsrSrvCreateThread);
+CSR_API(CsrGetShutdownParameters);
+CSR_API(CsrSetShutdownParameters);
+
+VOID
+NTAPI
+CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess);
+
+PCSR_THREAD
+NTAPI
+CsrAllocateThread(IN PCSR_PROCESS CsrProcess);
+
+PCSR_PROCESS
+NTAPI
+CsrAllocateProcess(VOID);
+
+VOID
+NTAPI
+CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrRemoveProcess(IN PCSR_PROCESS CsrProcess);
+
+VOID
+NTAPI
+CsrDereferenceThread(IN PCSR_THREAD CsrThread);
+
+VOID
+NTAPI
+CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
+                 IN PCSR_PROCESS CurrentProcess OPTIONAL,
+                 IN PCSR_PROCESS CsrProcess);
+
+
+/* api/wapi.c */
+NTSTATUS FASTCALL CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions);
+VOID FASTCALL CsrApiCallHandler(PCSR_PROCESS ProcessData,
+                                PCSR_API_MESSAGE Request);
+VOID WINAPI CsrSbApiRequestThread (PVOID PortHandle);
+VOID NTAPI ClientConnectionThread(HANDLE ServerPort);
+
+VOID
+NTAPI
+CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage);
+
+extern HANDLE CsrApiPort;
+extern HANDLE CsrSmApiPort;
+extern HANDLE CsrSbApiPort;
+extern LIST_ENTRY CsrThreadHashTable[256];
+extern PCSR_PROCESS CsrRootProcess;
+extern RTL_CRITICAL_SECTION ProcessDataLock, CsrWaitListsLock;
+extern UNICODE_STRING CsrDirectoryName;
+extern ULONG CsrDebug;
+extern ULONG CsrTotalPerProcessDataLength;
+extern SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
+extern PVOID CsrSrvSharedSectionHeap;
+extern PVOID *CsrSrvSharedStaticServerData;
+extern HANDLE CsrInitializationEvent;
+extern PCSR_SERVER_DLL CsrLoadedServerDll[CSR_SERVER_DLL_MAX];
+extern ULONG CsrMaxApiRequestThreads;
+
+NTSTATUS
+NTAPI
+CsrApiPortInitialize(VOID);
+
+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);
+
+BOOLEAN
+NTAPI
+ProtectHandle(IN HANDLE ObjectHandle);
+
+VOID
+NTAPI
+CsrInsertThread(IN PCSR_PROCESS Process,
+IN PCSR_THREAD Thread);
+
+VOID
+NTAPI
+CsrLockedReferenceThread(IN PCSR_THREAD CsrThread);
+
+/* api/process.c */
+typedef NTSTATUS (WINAPI *CSRSS_ENUM_PROCESS_PROC)(PCSR_PROCESS ProcessData,
+                                                    PVOID Context);
+NTSTATUS WINAPI CsrInitializeProcessStructure(VOID);
+
+NTSTATUS WINAPI CsrEnumProcesses(CSRSS_ENUM_PROCESS_PROC EnumProc, PVOID Context);
+PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN  ULONG ThreadFlags);
+PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, IN PCLIENT_ID Cid);
+PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL, IN PCLIENT_ID ClientId);
+NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL);
+NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId);
+NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess);
+
+//hack
+VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread);
+
+NTSTATUS
+NTAPI
+CsrInitializeNtSessionList(VOID);
+
+NTSTATUS
+NTAPI
+CsrSrvAttachSharedSection(IN PCSR_PROCESS CsrProcess OPTIONAL,
+OUT PCSR_CONNECTION_INFO ConnectInfo);
+
+NTSTATUS
+NTAPI
+CsrSrvCreateSharedSection(IN PCHAR ParameterValue);
+
+NTSTATUS
+NTAPI
+CsrSrvClientConnect(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvUnusedFunction(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvIdentifyAlertableThread(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrSrvSetPriorityClass(
+    IN OUT PCSR_API_MESSAGE ApiMessage,
+    IN OUT PULONG Reply
+);
+
+NTSTATUS
+NTAPI
+CsrDestroyProcess(IN PCLIENT_ID Cid,
+IN NTSTATUS ExitStatus);
+
+NTSTATUS
+NTAPI
+CsrDestroyThread(IN PCLIENT_ID Cid);
+
+VOID
+NTAPI
+CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread);
+
+BOOLEAN
+NTAPI
+CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK&nbs