- Some NDK fixes when compiling with PSDK.
authorAlex Ionescu <aionescu@gmail.com>
Tue, 27 Sep 2005 04:53:33 +0000 (04:53 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 27 Sep 2005 04:53:33 +0000 (04:53 +0000)
- Commit the new CSR (csrsrv and csrss). Compiles and passes PREfast with msvc 2005. Does not link yet. Is not complete yet (3 missing functions). Does not build with mingw yet. Code is probably still buggy. Work in other areas is needed as well. I'm comitting this under recommendation from Emanuele. See status.h for more info.
- Thanks to Emanuele and Filip which have helped with this patch.

svn path=/trunk/; revision=18118

20 files changed:
reactos/include/ndk/extypes.h
reactos/include/ndk/ldrfuncs.h
reactos/include/ndk/rtltypes.h
reactos/include/subsys/csr/protocol.h [deleted file]
reactos/include/subsys/csr/server.h
reactos/subsys/csr/args.c [deleted file]
reactos/subsys/csr/csr.h [deleted file]
reactos/subsys/csr/csrsrv/api.c [new file with mode: 0644]
reactos/subsys/csr/csrsrv/csrsrv.def
reactos/subsys/csr/csrsrv/debug.c [deleted file]
reactos/subsys/csr/csrsrv/dllmain.c [deleted file]
reactos/subsys/csr/csrsrv/init.c
reactos/subsys/csr/csrsrv/process.c
reactos/subsys/csr/csrsrv/server.c
reactos/subsys/csr/csrsrv/session.c
reactos/subsys/csr/csrsrv/srv.h
reactos/subsys/csr/csrsrv/status.h [new file with mode: 0644]
reactos/subsys/csr/csrsrv/thread.c
reactos/subsys/csr/csrsrv/wait.c
reactos/subsys/csr/main.c

index 4d1a052..26b853c 100644 (file)
@@ -13,7 +13,7 @@
 /* DEPENDENCIES **************************************************************/
 #include <cfg.h>
 /* FIXME: this needs be implemented in the w32api ddk */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(NTOS_MODE_USER)
 #include <ntimage.h>
 #endif
 #include "cmtypes.h"
index cb96ed7..6776c00 100644 (file)
@@ -12,7 +12,7 @@
 /* DEPENDENCIES **************************************************************/
 #include "ldrtypes.h"
 /* FIXME: this needs be implemented in the w32api ddk */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(NTOS_MODE_USER)
 #include <ntimage.h>
 #endif
 
index 4620416..f48581f 100644 (file)
@@ -393,6 +393,14 @@ typedef LPOSVERSIONINFOW PRTL_OSVERSIONINFOW;
 typedef OSVERSIONINFOEXW RTL_OSVERSIONINFOEXW;
 typedef LPOSVERSIONINFOEXW PRTL_OSVERSIONINFOEXW;
 
+typedef EXCEPTION_DISPOSITION
+(*PEXCEPTION_HANDLER)(
+    struct _EXCEPTION_RECORD*,
+    PVOID,
+    struct _CONTEXT*,
+    PVOID
+);
+
 typedef struct _RTL_HEAP_PARAMETERS
 {
     ULONG Length;
diff --git a/reactos/include/subsys/csr/protocol.h b/reactos/include/subsys/csr/protocol.h
deleted file mode 100644 (file)
index 32d2101..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef __INCLUDE_CSR_PROTOCOL_H
-#define __INCLUDE_CSR_PROTOCOL_H
-
-typedef ULONG CSR_API_NUMBER;
-
-#define MAKE_CSR_OPCODE(s,m) ((s) << 16) + (m)
-
-//
-// Shared CSR Message Header for all CSR Servers
-// Gary Nebbett - Alex Ionescu
-//
-typedef struct _CSR_PORT_MESSAGE_HEADER
-{
-    //
-    // LPC Header
-    //
-    PORT_MESSAGE PortHeader;
-
-    //
-    // Buffer allocated with CsrAllocateCaptureBuffer.
-    // Sent as 2nd parameter to CsrClientCallServer.
-    //
-    PVOID CsrCaptureData;
-
-    //
-    // CSR API Message ID and Return Value
-    //
-    CSR_API_NUMBER Opcode;
-    ULONG Status; 
-    ULONG Reserved;
-
-    //
-    // Server-defined union of supported structures
-    // 
-} CSR_PORT_MESSAGE_HEADER, * PCSR_PORT_MESSAGE_HEADER;
-
-#endif /* ndef __INCLUDE_CSR_PROTOCOL_H */
index 4b23006..542c93f 100644 (file)
-#if !defined(__INCLUDE_CSR_SERVER_H)
-#define __INCLUDE_CSR_SERVER_H
+#ifndef _CSRSERVER_H
+#define _CSRSERVER_H
 
 #define CSR_SRV_SERVER 0
 
-typedef struct _CSR_SESSION
+typedef enum _CSR_PROCESS_FLAGS
 {
-       ULONG   SessionId;
-       HANDLE  Heap;
-       PVOID   ServerData;
+    CsrProcessTerminating = 0x1,
+    CsrProcessSkipShutdown = 0x2,
+    CsrProcessCreateNewGroup = 0x100,
+    CsrProcessTerminated = 0x200,
+    CsrProcessLastThreadTerminated = 0x400,
+    CsrProcessIsConsoleApp = 0x800
+} CSR_PROCESS_FLAGS, *PCSR_PROCESS_FLAGS;
 
-} CSR_SESSION, * PCSR_SESSION;
+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 struct _CSR_NT_SESSION
+{
+    ULONG ReferenceCount;
+    LIST_ENTRY SessionList;
+       ULONG SessionId;
+} CSR_NT_SESSION, *PCSR_NT_SESSION;
 
 typedef struct _CSR_PROCESS
 {
-       CLIENT_ID     ClientId;
-       LIST_ENTRY    ListLink;
-       LIST_ENTRY    ThreadList;
-       PCSR_SESSION  NtSession;
-       ULONG         ExpectedVersion;
-       HANDLE        ClientPort;
-       ULONG_PTR     ClientViewBase;
-       ULONG_PTR     ClientViewBounds;
-       HANDLE        ProcessHandle;
-       ULONG         SequenceNumber;
-       ULONG         Flags;
-       ULONG         DebugFlags;
-       ULONG         ReferenceCount;
-       ULONG         ProcessGroupId;
-       ULONG         ProcessGroupSequence;
-       ULONG         fVDM;
-       ULONG         ThreadCount;
-       ULONG         PriorityClass;
-       ULONG         Reserved;
-       ULONG         ShutdownLevel;
-       ULONG         ShutdownFlags;
-       PVOID         ServerData; 
-       
-} CSR_PROCESS, * PCSR_PROCESS;
-
-struct _CSR_WAIT;
+    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[];
+} 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  *WaitBlock;
-       HANDLE            ThreadHandle;
-       ULONG             Flags;
-       ULONG             ReferenceCount;
-       ULONG             ImpersonationCount; 
-       
-} CSR_THREAD, * PCSR_THREAD;
-
-typedef struct _CSR_WAIT
-{
-       PCSR_THREAD CsrThread;
-
-} CSR_WAIT, * PCSR_WAIT;
-
-
-typedef VOID (CALLBACK * CSR_SERVER_THREAD)(PVOID);
-
-/* symbols exported by native DLL csrsrv.dll */
-
-NTSTATUS STDCALL CsrAddStaticServerThread(CSR_SERVER_THREAD);
-NTSTATUS STDCALL CsrCallServerFromServer();
-NTSTATUS STDCALL CsrCreateProcess(PCSR_SESSION,PCSR_PROCESS*);
-NTSTATUS STDCALL CsrCreateRemoteThread();
-NTSTATUS STDCALL CsrCreateSession(PCSR_SESSION*);
-NTSTATUS STDCALL CsrCreateThread(PCSR_PROCESS,PCSR_THREAD*);
-NTSTATUS STDCALL CsrCreateWait(PCSR_THREAD,PCSR_WAIT*);
-NTSTATUS STDCALL CsrDebugProcess(PCSR_PROCESS);
-NTSTATUS STDCALL CsrDebugProcessStop(PCSR_PROCESS);
-NTSTATUS STDCALL CsrDereferenceProcess(PCSR_PROCESS);
-NTSTATUS STDCALL CsrDereferenceThread(PCSR_THREAD);
-NTSTATUS STDCALL CsrDereferenceWait(PCSR_WAIT);
-NTSTATUS STDCALL CsrDestroyProcess(PCSR_PROCESS);
-NTSTATUS STDCALL CsrDestroySession (PCSR_SESSION);
-NTSTATUS STDCALL CsrDestroyThread(PCSR_THREAD);
-NTSTATUS STDCALL CsrExecServerThread();
-NTSTATUS STDCALL CsrGetProcessLuid(PCSR_PROCESS,PLUID);
-NTSTATUS STDCALL CsrImpersonateClient();
-NTSTATUS STDCALL CsrLockProcessByClientId();
-NTSTATUS STDCALL CsrLockThreadByClientId();
-NTSTATUS STDCALL CsrMoveSatisfiedWait(PCSR_WAIT);
-NTSTATUS STDCALL CsrNotifyWait(PCSR_WAIT);
-HANDLE   STDCALL CsrQueryApiPort(VOID);
-NTSTATUS STDCALL CsrReferenceThread(PCSR_THREAD);
-NTSTATUS STDCALL CsrRevertToSelf();
-NTSTATUS STDCALL CsrServerInitialization(ULONG,LPWSTR*);
-NTSTATUS STDCALL CsrSetBackgroundPriority();
-NTSTATUS STDCALL CsrSetCallingSpooler();
-NTSTATUS STDCALL CsrSetForegroundPriority();
-NTSTATUS STDCALL CsrShutdownProcesses(PCSR_SESSION);
-NTSTATUS STDCALL CsrUnhandledExceptionFilter();
-NTSTATUS STDCALL CsrUnlockProcess(PCSR_PROCESS);
-NTSTATUS STDCALL CsrUnlockThread(PCSR_THREAD);
-NTSTATUS STDCALL CsrValidateMessageBuffer();
-NTSTATUS STDCALL CsrValidateMessageString();
-
-#endif /* ndef __INCLUDE_CSR_SERVER_H */
+    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
+NTSTATUS
+(*PCSR_CONNECT_CALLBACK)(
+    IN PCSR_PROCESS CsrProcess,
+    IN OUT PVOID ConnectionInfo,
+    IN OUT PULONG ConnectionInfoLength
+);
+
+typedef
+VOID
+(*PCSR_DISCONNECT_CALLBACK)(IN PCSR_PROCESS CsrProcess);
+
+typedef
+NTSTATUS
+(*PCSR_NEWPROCESS_CALLBACK)(
+    IN PCSR_PROCESS Parent,
+    IN PCSR_PROCESS CsrProcess
+);
+
+typedef
+VOID
+(*PCSR_HARDERROR_CALLBACK)(
+    IN PCSR_THREAD CsrThread,
+    IN PHARDERROR_MSG HardErrorMessage
+);
+
+typedef
+ULONG
+(*PCSR_SHUTDOWNPROCESS_CALLBACK)(
+    IN PCSR_PROCESS CsrProcess,
+    IN ULONG Flags,
+    IN BOOLEAN FirstPhase
+);
+
+/* FIXME: Put into public NDK Header */
+typedef ULONG CSR_API_NUMBER;
+
+#define CSR_MAKE_OPCODE(s,m) ((s) << 16) | (m)
+#define CSR_API_ID_FROM_OPCODE(n) ((ULONG)((USHORT)(n)))
+#define CSR_SERVER_ID_FROM_OPCODE(n) (ULONG)((n) >> 16)
+
+typedef struct _CSR_CONNECTION_INFO
+{
+    ULONG Unknown[2];
+    HANDLE ObjectDirectory;
+    PVOID SharedSectionBase;
+    PVOID SharedSectionHeap;
+    PVOID SharedSectionData;
+    ULONG DebugFlags;
+    ULONG Unknown2[3];
+    HANDLE ProcessId;
+} CSR_CONNECTION_INFO, *PCSR_CONNECTION_INFO;
+
+typedef struct _CSR_CLIENT_CONNECT
+{
+    ULONG ServerId;
+    PVOID ConnectionInfo;
+    ULONG ConnectionInfoSize;
+} CSR_CLIENT_CONNECT, *PCSR_CLIENT_CONNECT;
+
+typedef struct _CSR_API_MESSAGE
+{
+    PORT_MESSAGE Header;
+    union
+    {
+        CSR_CONNECTION_INFO ConnectionInfo;
+        struct
+        {
+            PVOID CsrCaptureData;
+            CSR_API_NUMBER Opcode;
+            ULONG Status; 
+            ULONG Reserved;
+            union
+            {
+                CSR_CLIENT_CONNECT CsrClientConnect;
+            };
+        };
+    };
+} CSR_API_MESSAGE, *PCSR_API_MESSAGE;
+
+typedef struct _CSR_CAPTURE_BUFFER
+{
+    ULONG Size;
+    struct _CSR_CAPTURE_BUFFER *PreviousCaptureBuffer;
+    ULONG PointerCount;
+    ULONG_PTR BufferEnd;
+} CSR_CAPTURE_BUFFER, *PCSR_CAPTURE_BUFFER;
+
+/* Private data resumes here */
+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
+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;
+
+/* FIXME: Put into new SM headers */
+typedef struct _SB_CREATE_SESSION
+{
+    ULONG SessionId;
+    RTL_USER_PROCESS_INFORMATION ProcessInfo;
+} SB_CREATE_SESSION, *PSB_CREATE_SESSION;
+
+typedef struct _SB_TERMINATE_SESSION
+{
+    ULONG SessionId;
+} SB_TERMINATE_SESSION, *PSB_TERMINATE_SESSION;
+
+typedef struct _SB_FOREIGN_SESSION_COMPLETE
+{
+    ULONG SessionId;
+} SB_FOREIGN_SESSION_COMPLETE, *PSB_FOREIGN_SESSION_COMPLETE;
+
+typedef struct _SB_CREATE_PROCESS
+{
+    ULONG SessionId;
+} SB_CREATE_PROCESS, *PSB_CREATE_PROCESS;
+
+typedef struct _SB_CONNECTION_INFO
+{
+    ULONG SubsystemId;
+} SB_CONNECTION_INFO, *PSB_CONNECTION_INFO;
+
+typedef struct _SB_API_MESSAGE
+{
+    PORT_MESSAGE Header;
+    union
+    {
+        SB_CONNECTION_INFO ConnectionInfo;
+        struct
+        {
+            ULONG Opcode;
+            NTSTATUS Status;
+            union
+            {
+                SB_CREATE_SESSION SbCreateSession;
+                SB_TERMINATE_SESSION SbTerminateSession;
+                SB_FOREIGN_SESSION_COMPLETE SbForeignSessionComplete;
+                SB_CREATE_PROCESS SbCreateProcess;
+            };
+        };
+    };
+} SB_API_MESSAGE, *PSB_API_MESSAGE;
+
+typedef
+BOOLEAN
+(NTAPI *PSB_API_ROUTINE)(IN PSB_API_MESSAGE ApiMessage);
+
+NTSTATUS
+NTAPI
+SmSessionComplete(
+    IN HANDLE hApiPort,
+    IN ULONG SessionId,
+    IN NTSTATUS Status
+);
+
+NTSTATUS
+NTAPI
+SmConnectToSm(
+    IN PUNICODE_STRING SbApiPortName OPTIONAL,
+    IN HANDLE hSbApiPort OPTIONAL,
+    IN ULONG SubsystemType OPTIONAL,
+    OUT PHANDLE hSmApiPort
+);
+#endif
diff --git a/reactos/subsys/csr/args.c b/reactos/subsys/csr/args.c
deleted file mode 100644 (file)
index 15b2f6d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* $Id$
- *
- * args.c - Client/Server Runtime - command line parsing
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
- */
-#include "csr.h"
-
-#define NDEBUG
-#include <debug.h>
-
-/**********************************************************************
- * NAME                                                        PRIVATE
- *     CsrParseCommandLine/2
- */
-NTSTATUS FASTCALL CsrParseCommandLine (PPEB  Peb,
-                                     PCOMMAND_LINE_ARGUMENT  Argument)
-{
-   HANDLE                        ProcessHeap = Peb->ProcessHeap;
-   PRTL_USER_PROCESS_PARAMETERS  RtlProcessParameters = RtlNormalizeProcessParams (Peb->ProcessParameters);
-   INT                           i = 0;
-   INT                           afterlastspace = 0;
-
-
-   DPRINT("CSR: %s called\n", __FUNCTION__);
-
-   RtlZeroMemory (Argument, sizeof (COMMAND_LINE_ARGUMENT));
-
-   Argument->Vector = (PWSTR *) RtlAllocateHeap (ProcessHeap,
-                                                0,
-                                                (CSRP_MAX_ARGUMENT_COUNT * sizeof Argument->Vector[0]));
-   if(NULL == Argument->Vector)
-   {
-          DPRINT("CSR: %s: no memory for Argument->Vector\n", __FUNCTION__);
-          return STATUS_NO_MEMORY;
-   }
-
-   Argument->Buffer.Length =
-   Argument->Buffer.MaximumLength =
-       RtlProcessParameters->CommandLine.Length
-       + sizeof Argument->Buffer.Buffer [0]; /* zero terminated */
-   Argument->Buffer.Buffer =
-       (PWSTR) RtlAllocateHeap (ProcessHeap,
-                                0,
-                                 Argument->Buffer.MaximumLength);
-   if(NULL == Argument->Buffer.Buffer)
-   {
-          DPRINT("CSR: %s: no memory for Argument->Buffer.Buffer\n", __FUNCTION__);
-          return STATUS_NO_MEMORY;
-   }
-
-   RtlCopyMemory (Argument->Buffer.Buffer,
-                 RtlProcessParameters->CommandLine.Buffer,
-                 RtlProcessParameters->CommandLine.Length);
-
-   while (Argument->Buffer.Buffer [i])
-     {
-       if (Argument->Buffer.Buffer[i] == L' ')
-         {
-            Argument->Count ++;
-            Argument->Buffer.Buffer [i] = L'\0';
-            Argument->Vector [Argument->Count - 1] = & (Argument->Buffer.Buffer [afterlastspace]);
-            i++;
-            while (Argument->Buffer.Buffer [i] == L' ')
-            {
-               i++;
-            }
-            afterlastspace = i;
-         }
-       else
-         {
-            i++;
-         }
-     }
-
-   if (Argument->Buffer.Buffer [afterlastspace] != L'\0')
-     {
-       Argument->Count ++;
-       Argument->Buffer.Buffer [i] = L'\0';
-       Argument->Vector [Argument->Count - 1] = & (Argument->Buffer.Buffer [afterlastspace]);
-     }
-#if !defined(NDEBUG)
-   for (i=0; i<Argument->Count; i++)
-   {
-          DPRINT("CSR: Argument[%d] = '%S'\n", i, Argument->Vector [i]);
-   }
-#endif
-  return STATUS_SUCCESS;
-}
-/**********************************************************************
- * NAME                                                        PRIVATE
- *     CsrFreeCommandLine/2
- */
-
-VOID FASTCALL CsrFreeCommandLine (PPEB  Peb,
-                                 PCOMMAND_LINE_ARGUMENT  Argument)
-{
-       DPRINT("CSR: %s called\n", __FUNCTION__);
-
-       RtlFreeHeap (Peb->ProcessHeap,
-                    0,
-                    Argument->Vector);
-       RtlFreeHeap (Peb->ProcessHeap,
-                    0,
-                    Argument->Buffer.Buffer);
-}
-/* EOF */
diff --git a/reactos/subsys/csr/csr.h b/reactos/subsys/csr/csr.h
deleted file mode 100644 (file)
index 5b6a33a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#if !defined(_INCLUDE_CSR_H)
-#define _INCLUDE_CSR_H
-
-/* PSDK/NDK Headers */
-#include <stdio.h>
-#include <windows.h>
-
-#define NTOS_MODE_USER
-#include <ndk/ntndk.h>
-
-#include <csr/server.h>
-
-
-#define CSRSS_ARGUMENT_SIZE 16
-
-/* args.c */
-#define CSRP_MAX_ARGUMENT_COUNT 512
-
-typedef struct _COMMAND_LINE_ARGUMENT
-{
-       ULONG           Count;
-       UNICODE_STRING  Buffer;
-       PWSTR           * Vector;
-
-} COMMAND_LINE_ARGUMENT, *PCOMMAND_LINE_ARGUMENT;
-
-NTSTATUS FASTCALL CsrParseCommandLine (PPEB,PCOMMAND_LINE_ARGUMENT);
-VOID FASTCALL CsrFreeCommandLine (PPEB,PCOMMAND_LINE_ARGUMENT);
-
-/* csrsrv.dll  */
-NTSTATUS STDCALL CsrServerInitialization (ULONG,LPWSTR*);
-
-#endif /* !def _INCLUDE_CSR_H */
-       
diff --git a/reactos/subsys/csr/csrsrv/api.c b/reactos/subsys/csr/csrsrv/api.c
new file mode 100644 (file)
index 0000000..221e033
--- /dev/null
@@ -0,0 +1,1412 @@
+/*\r
+ * COPYRIGHT:       See COPYING in the top level directory\r
+ * PROJECT:         ReactOS CSR Sub System\r
+ * FILE:            subsys/csr/csrsrv/api.c\r
+ * PURPOSE:         CSR Server DLL API LPC Implementation\r
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)\r
+ */\r
+\r
+/* INCLUDES ******************************************************************/\r
+\r
+#include "srv.h"\r
+\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+/* DATA **********************************************************************/\r
+BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;\r
+ULONG CsrMaxApiRequestThreads;\r
+UNICODE_STRING CsrSbApiPortName;\r
+UNICODE_STRING CsrApiPortName;\r
+HANDLE CsrSbApiPort;\r
+HANDLE CsrApiPort;\r
+PCSR_THREAD CsrSbApiRequestThreadPtr;\r
+ULONG CsrpStaticThreadCount;\r
+ULONG CsrpDynamicThreadTotal;\r
+\r
+/* PRIVATE FUNCTIONS *********************************************************/\r
+\r
+/*++\r
+ * @name CsrCheckRequestThreads\r
+ *\r
+ * The CsrCheckRequestThreads routine checks if there are no more threads\r
+ * to handle CSR API Requests, and creates a new thread if possible, to\r
+ * avoid starvation.\r
+ *\r
+ * @param None.\r
+ *\r
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL\r
+ *         if a new thread couldn't be created.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrCheckRequestThreads(VOID)\r
+{\r
+    HANDLE hThread;\r
+    CLIENT_ID ClientId;\r
+    NTSTATUS Status;\r
+\r
+    /* Decrease the count, and see if we're out */\r
+    if (!(InterlockedDecrement(&CsrpStaticThreadCount)))\r
+    {\r
+        /* Check if we've still got space for a Dynamic Thread */\r
+        if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)\r
+        {\r
+            /* Create a new dynamic thread */\r
+            Status = RtlCreateUserThread(NtCurrentProcess(),\r
+                                         NULL,\r
+                                         TRUE,\r
+                                         0,\r
+                                         0,\r
+                                         0,\r
+                                         CsrApiRequestThread,\r
+                                         NULL,\r
+                                         &hThread,\r
+                                         &ClientId);\r
+            /* Check success */\r
+            if(NT_SUCCESS(Status))\r
+            {\r
+                /* Increase the thread counts */\r
+                CsrpStaticThreadCount++;\r
+                CsrpDynamicThreadTotal++;\r
+\r
+                /* Add a new server thread */\r
+                if (CsrAddStaticServerThread(hThread,\r
+                                             &ClientId,\r
+                                             CsrThreadIsServerThread))\r
+                {\r
+                    /* Activate it */\r
+                    NtResumeThread(hThread,NULL);\r
+                }\r
+                else\r
+                {\r
+                    /* Failed to create a new static thread */\r
+                    CsrpStaticThreadCount--;\r
+                    CsrpDynamicThreadTotal--;\r
+\r
+                    /* Terminate it */\r
+                    NtTerminateThread(hThread,0);\r
+                    NtClose(hThread);\r
+\r
+                    /* Return */\r
+                    return STATUS_UNSUCCESSFUL;\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /* Success */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+ * @name CsrSbApiPortInitialize\r
+ *\r
+ * The CsrSbApiPortInitialize routine initializes the LPC Port used for\r
+ * communications with the Session Manager (SM) and initializes the static\r
+ * thread that will handle connection requests and APIs.\r
+ *\r
+ * @param None \r
+ *\r
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL\r
+ *         othwerwise.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrSbApiPortInitialize(VOID)\r
+{\r
+    ULONG Size;\r
+    PSECURITY_DESCRIPTOR PortSd;\r
+    OBJECT_ATTRIBUTES ObjectAttributes;\r
+    NTSTATUS Status;\r
+    HANDLE hRequestThread;\r
+    CLIENT_ID ClientId;\r
+\r
+    /* Calculate how much space we'll need for the Port Name */\r
+    Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR);\r
+\r
+    /* Allocate space for it, and create it */\r
+    CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);\r
+    CsrSbApiPortName.Length = 0;\r
+    CsrSbApiPortName.MaximumLength = (USHORT)Size;\r
+    RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName);\r
+    RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP);\r
+    RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME);\r
+\r
+    /* Create Security Descriptor for this Port */\r
+    CsrCreateLocalSystemSD(&PortSd);\r
+\r
+    /* Initialize the Attributes */\r
+    InitializeObjectAttributes(&ObjectAttributes,\r
+                               &CsrSbApiPortName,\r
+                               0,\r
+                               PortSd,\r
+                               NULL);\r
+\r
+    /* Create the Port Object */\r
+    Status = NtCreatePort(&CsrSbApiPort,\r
+                          &ObjectAttributes,\r
+                          sizeof(SB_CONNECTION_INFO),\r
+                          sizeof(SB_API_MESSAGE),\r
+                          32 * sizeof(SB_API_MESSAGE));\r
+    if(!NT_SUCCESS(Status))\r
+    {\r
+\r
+    }\r
+\r
+    /* Create the Thread to handle the API Requests */\r
+    Status = RtlCreateUserThread(NtCurrentProcess(),\r
+                                 NULL,\r
+                                 TRUE,\r
+                                 0,\r
+                                 0,\r
+                                 0,\r
+                                 (PVOID)CsrSbApiRequestThread,\r
+                                 NULL,\r
+                                 &hRequestThread,\r
+                                 &ClientId);\r
+    if(!NT_SUCCESS(Status))\r
+    {\r
+\r
+    }\r
+\r
+    /* Add it as a Static Server Thread */\r
+    CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread,\r
+                                                        &ClientId,\r
+                                                        0);\r
+\r
+    /* Activate it */\r
+    return NtResumeThread(hRequestThread, NULL);\r
+}\r
+\r
+/*++\r
+ * @name CsrApiPortInitialize\r
+ *\r
+ * The CsrApiPortInitialize routine initializes the LPC Port used for\r
+ * communications with the Client/Server Runtime (CSR) and initializes the\r
+ * static thread that will handle connection requests and APIs.\r
+ *\r
+ * @param None \r
+ *\r
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL\r
+ *         othwerwise.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrApiPortInitialize(VOID)\r
+{\r
+    ULONG Size;\r
+    OBJECT_ATTRIBUTES ObjectAttributes;\r
+    NTSTATUS Status;\r
+    HANDLE hRequestEvent, hThread;\r
+    CLIENT_ID ClientId;\r
+    PLIST_ENTRY ListHead, NextEntry;\r
+    PCSR_THREAD ServerThread;\r
+\r
+    /* Calculate how much space we'll need for the Port Name */\r
+    Size = CsrDirectoryName.Length + sizeof(CSR_PORT_NAME) + sizeof(WCHAR);\r
+\r
+    /* Allocate space for it, and create it */\r
+    CsrApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size);\r
+    CsrApiPortName.Length = 0;\r
+    CsrApiPortName.MaximumLength = (USHORT)Size;\r
+    RtlAppendUnicodeStringToString(&CsrApiPortName, &CsrDirectoryName);\r
+    RtlAppendUnicodeToString(&CsrApiPortName, UNICODE_PATH_SEP);\r
+    RtlAppendUnicodeToString(&CsrApiPortName, CSR_PORT_NAME);\r
+\r
+    /* FIXME: Create a Security Descriptor */\r
+\r
+    /* Initialize the Attributes */\r
+    InitializeObjectAttributes(&ObjectAttributes,\r
+                               &CsrApiPortName,\r
+                               0,\r
+                               NULL,\r
+                               NULL /* FIXME*/);\r
+\r
+    /* Create the Port Object */\r
+    Status = NtCreatePort(&CsrApiPort,\r
+                          &ObjectAttributes,\r
+                          sizeof(CSR_CONNECTION_INFO),\r
+                          sizeof(CSR_API_MESSAGE),\r
+                          16 * PAGE_SIZE);\r
+    if(!NT_SUCCESS(Status))\r
+    {\r
+\r
+    }\r
+\r
+    /* Create the event the Port Thread will use */\r
+    Status = NtCreateEvent(&hRequestEvent,\r
+                           EVENT_ALL_ACCESS,\r
+                           NULL,\r
+                           SynchronizationEvent,\r
+                           FALSE);\r
+    if(!NT_SUCCESS(Status))\r
+    {\r
+\r
+    }\r
+\r
+    /* Create the Request Thread */\r
+    Status = RtlCreateUserThread(NtCurrentProcess(),\r
+                                 NULL,\r
+                                 TRUE,\r
+                                 0,\r
+                                 0,\r
+                                 0,\r
+                                 (PVOID)CsrApiRequestThread,\r
+                                 (PVOID)hRequestEvent,\r
+                                 &hThread,\r
+                                 &ClientId);\r
+    if(!NT_SUCCESS(Status))\r
+    {\r
+\r
+    }\r
+\r
+    /* Add this as a static thread to CSRSRV */\r
+    CsrAddStaticServerThread(hThread, &ClientId, CsrThreadIsServerThread);\r
+\r
+    /* Get the Thread List Pointers */\r
+    ListHead = &CsrRootProcess->ThreadList;\r
+    NextEntry = ListHead->Flink;\r
+\r
+    /* Start looping the list */\r
+    while (NextEntry != ListHead)\r
+    {\r
+        /* Get the Thread */\r
+        ServerThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);\r
+\r
+        /* Start it up */\r
+        Status = NtResumeThread(ServerThread->ThreadHandle, NULL);\r
+\r
+        /* Is this a Server Thread? */\r
+        if (ServerThread->Flags & CsrThreadIsServerThread)\r
+        {\r
+            /* If so, then wait for it to initialize */\r
+            NtWaitForSingleObject(hRequestEvent, FALSE, NULL);\r
+        }\r
+\r
+        /* Next thread */\r
+        NextEntry = NextEntry->Flink;\r
+    }\r
+\r
+    /* We don't need this anymore */\r
+    NtClose(hRequestEvent);\r
+\r
+    /* Return */\r
+    return Status;\r
+}\r
+\r
+/*++\r
+ * @name CsrApiRequestThread\r
+ *\r
+ * The CsrApiRequestThread routine handles incoming messages or connection\r
+ * requests on the CSR API LPC Port.\r
+ *\r
+ * @param Parameter\r
+ *        System-default user-defined parameter. Unused.  \r
+ *\r
+ * @return The thread exit code, if the thread is terminated.\r
+ *\r
+ * @remarks Before listening on the port, the routine will first attempt\r
+ *          to connect to the user subsystem.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrApiRequestThread(IN PVOID Parameter)\r
+{\r
+    PTEB Teb = NtCurrentTeb();\r
+    LARGE_INTEGER TimeOut;\r
+    PCSR_THREAD CurrentThread;\r
+    NTSTATUS Status;\r
+    PCSR_API_MESSAGE ReplyMsg = NULL;\r
+    CSR_API_MESSAGE ReceiveMsg;\r
+    PCSR_THREAD CsrThread;\r
+    PCSR_PROCESS CsrProcess;\r
+    PHARDERROR_MSG HardErrorMsg;\r
+    PVOID PortContext;\r
+    ULONG MessageType;\r
+    ULONG i;\r
+    PCSR_SERVER_DLL ServerDll;\r
+    PCLIENT_DIED_MSG ClientDiedMsg;\r
+    PDBGKM_MSG DebugMessage;\r
+    ULONG ServerId, ApiId;\r
+    ULONG Reply;\r
+\r
+    /* Probably because of the way GDI is loaded, this has to be done here */\r
+    Teb->GdiClientPID = HandleToUlong(Teb->Cid.UniqueProcess);\r
+    Teb->GdiClientTID = HandleToUlong(Teb->Cid.UniqueThread);\r
+\r
+    /* Set up the timeout for the connect (30 seconds) */\r
+    TimeOut.QuadPart = -30 * 1000 * 1000 * 10;\r
+\r
+    /* Connect to user32 */\r
+    while (!CsrConnectToUser())\r
+    {\r
+        /* Keep trying until we get a response */\r
+        Teb->Win32ClientInfo[0] = 0;\r
+        NtDelayExecution(FALSE, &TimeOut);\r
+    }\r
+\r
+    /* Get our thread */\r
+    CurrentThread = Teb->CsrClientThread;\r
+\r
+    /* If we got an event... */\r
+    if (Parameter)\r
+    {\r
+        /* Set it, to let stuff waiting on us load */\r
+        NtSetEvent((HANDLE)Parameter, NULL);\r
+\r
+        /* Increase the Thread Counts */\r
+        InterlockedIncrement(&CsrpStaticThreadCount);\r
+        InterlockedIncrement(&CsrpDynamicThreadTotal);\r
+    }\r
+\r
+    /* Now start the loop */\r
+    while (TRUE)\r
+    {\r
+        /* Make sure the real CID is set */\r
+        Teb->RealClientId = Teb->Cid;\r
+\r
+        /* Wait for a message to come through */\r
+        Status = NtReplyWaitReceivePort(CsrApiPort,\r
+                                        &PortContext,\r
+                                        (PPORT_MESSAGE)ReplyMsg,\r
+                                        (PPORT_MESSAGE)&ReceiveMsg);\r
+\r
+        /* Check if we didn't get success */\r
+        if(Status != STATUS_SUCCESS)\r
+        {\r
+            /* If we only got a warning, keep going */\r
+            if (NT_SUCCESS(Status)) continue;\r
+\r
+            /* We failed big time, so start out fresh */\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+\r
+        /* Use whatever Client ID we got */\r
+        Teb->RealClientId = ReceiveMsg.Header.ClientId;\r
+\r
+        /* Get the Message Type */\r
+        MessageType = ReceiveMsg.Header.u2.s2.Type;\r
+\r
+        /* Handle connection requests */\r
+        if (MessageType == LPC_CONNECTION_REQUEST)\r
+        {\r
+            /* Handle the Connection Request */\r
+            CsrApiHandleConnectionRequest(&ReceiveMsg);\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+\r
+        /* It's some other kind of request. Get the lock for the lookup*/\r
+        CsrAcquireProcessLock();\r
+\r
+        /* Now do the lookup to get the CSR_THREAD */\r
+        CsrThread = CsrLocateThreadByClientId(&CsrProcess,\r
+                                              &ReceiveMsg.Header.ClientId);\r
+\r
+        /* Did we find a thread? */\r
+        if(!CsrThread)\r
+        {\r
+            /* This wasn't a CSR Thread, release lock */\r
+            CsrReleaseProcessLock();\r
+\r
+            /* If this was an exception, handle it */\r
+            if (MessageType == LPC_EXCEPTION)\r
+            {\r
+                ReplyMsg = &ReceiveMsg;\r
+                ReplyMsg->Status = DBG_CONTINUE;\r
+            }\r
+            else if (MessageType == LPC_PORT_CLOSED ||\r
+                     MessageType == LPC_CLIENT_DIED)\r
+            {\r
+                /* The Client or Port are gone, loop again */\r
+                ReplyMsg = NULL;\r
+            }\r
+            else if (MessageType == LPC_ERROR_EVENT)\r
+            {\r
+                /* If it's a hard error, handle this too */\r
+                HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;\r
+\r
+                /* Default it to unhandled */\r
+                HardErrorMsg->Response = ResponseNotHandled;\r
+\r
+                /* Check if there are free api threads */\r
+                CsrCheckRequestThreads();\r
+                if (CsrpStaticThreadCount)\r
+                {\r
+                    /* Loop every Server DLL */\r
+                    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)\r
+                    {\r
+                        /* Get the Server DLL */\r
+                        ServerDll = CsrLoadedServerDll[i];\r
+\r
+                        /* Check if it's valid and if it has a Hard Error Callback */\r
+                        if (ServerDll && ServerDll->HardErrorCallback)\r
+                        {\r
+                            /* Call it */\r
+                            (*ServerDll->HardErrorCallback)(CsrThread, HardErrorMsg);\r
+\r
+                            /* If it's handled, get out of here */\r
+                            if (HardErrorMsg->Response != ResponseNotHandled) break;\r
+                        }\r
+                    }\r
+                }\r
+                    \r
+                /* Increase the thread count */\r
+                InterlockedIncrement(&CsrpStaticThreadCount);\r
+\r
+                /* If the response was 0xFFFFFFFF, we'll ignore it */\r
+                if (HardErrorMsg->Response == 0xFFFFFFFF)\r
+                {\r
+                    ReplyMsg = NULL;\r
+                }\r
+                else\r
+                {\r
+                    ReplyMsg = &ReceiveMsg;\r
+                }\r
+            }\r
+            else if (MessageType == LPC_REQUEST)\r
+            {\r
+                /* This is an API Message coming from a non-CSR Thread */\r
+                ReplyMsg = &ReceiveMsg;\r
+                ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;\r
+            }\r
+            else if (MessageType == LPC_DATAGRAM)\r
+            {\r
+                /* This is an API call, get the Server ID */\r
+                ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg.Opcode);\r
+\r
+                /* Make sure that the ID is within limits, and the Server DLL loaded */\r
+                if ((ServerId >= CSR_SERVER_DLL_MAX) ||\r
+                    (!(ServerDll = CsrLoadedServerDll[ServerId])))\r
+                {\r
+                    /* We are beyond the Maximum Server ID */\r
+                    ReplyMsg = NULL;\r
+                }\r
+                else\r
+                {\r
+                    /* Get the API ID */\r
+                    ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg.Opcode);\r
+\r
+                    /* Normalize it with our Base ID */\r
+                    ApiId -= ServerDll->ApiBase;\r
+\r
+                    /* Make sure that the ID is within limits, and the entry exists */\r
+                    if ((ApiId >= ServerDll->HighestApiSupported))\r
+                    {\r
+                        /* We are beyond the Maximum API ID, or it doesn't exist */\r
+                        ReplyMsg = NULL;\r
+                    }\r
+\r
+                    /* Assume success */\r
+                    ReceiveMsg.Status = STATUS_SUCCESS;\r
+\r
+                    /* Validation complete, start SEH */\r
+                    _SEH_TRY\r
+                    {\r
+                        /* Make sure we have enough threads */\r
+                        CsrCheckRequestThreads();\r
+\r
+                        /* Call the API and get the result */\r
+                        ReplyMsg = NULL;\r
+                        (ServerDll->DispatchTable[ApiId])(&ReceiveMsg, &Reply);\r
+\r
+                        /* Increase the static thread count */\r
+                        InterlockedIncrement(&CsrpStaticThreadCount);\r
+                    }\r
+                    _SEH_EXCEPT(CsrUnhandledExceptionFilter)\r
+                    {\r
+                        ReplyMsg = NULL;\r
+                    }\r
+                    _SEH_END;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                /* Some other ignored message type */\r
+                ReplyMsg = NULL;\r
+            }\r
+\r
+            /* Keep going */\r
+            continue;\r
+        }\r
+\r
+        /* We have a valid thread, was this an LPC Request? */\r
+        if (MessageType != LPC_REQUEST)\r
+        {\r
+            /* It's not an API, check if the client died */\r
+            if (MessageType == LPC_CLIENT_DIED)\r
+            {\r
+                /* Get the information and check if it matches our thread */\r
+                ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;\r
+                if (ClientDiedMsg->CreateTime.QuadPart = CsrThread->CreateTime.QuadPart)\r
+                {\r
+                    /* Reference the thread */\r
+                    CsrThread->ReferenceCount++;\r
+\r
+                    /* Destroy the thread in the API Message */\r
+                    CsrDestroyThread(&ReceiveMsg.Header.ClientId);\r
+\r
+                    /* Check if the thread was actually ourselves */\r
+                    if (CsrProcess->ThreadCount == 1)\r
+                    {\r
+                        /* Kill the process manually here */\r
+                        CsrDestroyProcess(&CsrThread->ClientId, 0);\r
+                    }\r
+\r
+                    /* Remove our extra reference */\r
+                    CsrLockedDereferenceThread(CsrThread);\r
+                }\r
+\r
+                /* Release the lock and keep looping */\r
+                CsrReleaseProcessLock();\r
+                ReplyMsg = NULL;\r
+                continue;\r
+            }\r
+\r
+            /* Reference the thread and release the lock */\r
+            CsrThread->ReferenceCount++;\r
+            CsrReleaseProcessLock();\r
+\r
+            /* Check if this was an exception */\r
+            if (MessageType == LPC_EXCEPTION)\r
+            {\r
+                /* Kill the process */\r
+                NtTerminateProcess(CsrProcess->ProcessHandle, STATUS_ABANDONED);\r
+\r
+                /* Destroy it from CSR */\r
+                CsrDestroyProcess(&ReceiveMsg.Header.ClientId, STATUS_ABANDONED);\r
+\r
+                /* Return a Debug Message */\r
+                DebugMessage = (PDBGKM_MSG)&ReceiveMsg;\r
+                DebugMessage->Status = DBG_CONTINUE;\r
+                ReplyMsg = &ReceiveMsg;\r
+\r
+                /* Remove our extra reference */\r
+                CsrDereferenceThread(CsrThread);\r
+            }\r
+            else if (MessageType == LPC_ERROR_EVENT)\r
+            {\r
+                /* If it's a hard error, handle this too */\r
+                HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg;\r
+\r
+                /* Default it to unhandled */\r
+                HardErrorMsg->Response = ResponseNotHandled;\r
+\r
+                /* Check if there are free api threads */\r
+                CsrCheckRequestThreads();\r
+                if (CsrpStaticThreadCount)\r
+                {\r
+                    /* Loop every Server DLL */\r
+                    for (i = 0; i < CSR_SERVER_DLL_MAX; i++)\r
+                    {\r
+                        /* Get the Server DLL */\r
+                        ServerDll = CsrLoadedServerDll[i];\r
+\r
+                        /* Check if it's valid and if it has a Hard Error Callback */\r
+                        if (ServerDll && ServerDll->HardErrorCallback)\r
+                        {\r
+                            /* Call it */\r
+                            (*ServerDll->HardErrorCallback)(CsrThread, HardErrorMsg);\r
+\r
+                            /* If it's handled, get out of here */\r
+                            if (HardErrorMsg->Response != ResponseNotHandled) break;\r
+                        }\r
+                    }\r
+                }\r
+                    \r
+                /* Increase the thread count */\r
+                InterlockedIncrement(&CsrpStaticThreadCount);\r
+\r
+                /* If the response was 0xFFFFFFFF, we'll ignore it */\r
+                if (HardErrorMsg->Response == 0xFFFFFFFF)\r
+                {\r
+                    ReplyMsg = NULL;\r
+                }\r
+                else\r
+                {\r
+                    CsrDereferenceThread(CsrThread);\r
+                    ReplyMsg = &ReceiveMsg;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                /* Something else */\r
+                CsrDereferenceThread(CsrThread);\r
+                ReplyMsg = NULL;\r
+            }\r
+\r
+            /* Keep looping */\r
+            continue;\r
+        }\r
+\r
+        /* We got an API Request */\r
+        CsrDereferenceThread(CsrThread);\r
+        CsrReleaseProcessLock();\r
+\r
+        /* FIXME: Handle the API */\r
+\r
+    }\r
+\r
+    /* We're out of the loop for some reason, terminate! */\r
+    NtTerminateThread(NtCurrentThread(), Status);\r
+    return Status;\r
+}\r
+\r
+/*++\r
+ * @name CsrApiHandleConnectionRequest\r
+ *\r
+ * The CsrApiHandleConnectionRequest routine handles and accepts a new\r
+ * connection request to the CSR API LPC Port.\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the incoming CSR API Message which contains the\r
+ *        connection request.\r
+ *\r
+ * @return STATUS_SUCCESS in case of success, or status code which caused\r
+ *         the routine to error.\r
+ *\r
+ * @remarks This routine is responsible for attaching the Shared Section to\r
+ *          new clients connecting to CSR.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)\r
+{\r
+    PCSR_THREAD CsrThread;\r
+    PCSR_PROCESS CsrProcess;\r
+    NTSTATUS Status;\r
+    PCSR_CONNECTION_INFO ConnectInfo = &ApiMessage->ConnectionInfo;\r
+    BOOLEAN AllowConnection = FALSE;\r
+    REMOTE_PORT_VIEW RemotePortView;\r
+    HANDLE hPort;\r
+\r
+    /* Acquire the Process Lock */\r
+    CsrAcquireProcessLock();\r
+\r
+    /* Lookup the CSR Thread */\r
+    CsrThread = CsrLocateThreadByClientId(NULL, &ApiMessage->Header.ClientId);\r
+\r
+    /* Check if we have a thread */\r
+    if (CsrThread)\r
+    {\r
+        /* Get the Process */\r
+        CsrProcess = CsrThread->Process;\r
+\r
+        /* Make sure we have a Process as well */\r
+        if (CsrProcess)\r
+        {\r
+            /* Reference the Process */\r
+            CsrProcess->ReferenceCount++;\r
+\r
+            /* Release the lock */\r
+            CsrReleaseProcessLock();\r
+\r
+            /* Duplicate the Object Directory */\r
+            Status = NtDuplicateObject(NtCurrentProcess(),\r
+                                       CsrObjectDirectory,\r
+                                       CsrProcess->ProcessHandle,\r
+                                       &ConnectInfo->ObjectDirectory,\r
+                                       0,\r
+                                       0,\r
+                                       DUPLICATE_SAME_ACCESS |\r
+                                       DUPLICATE_SAME_ATTRIBUTES);\r
+\r
+            /* Acquire the lock */\r
+            CsrAcquireProcessLock();\r
+\r
+            /* Check for success */\r
+            if (NT_SUCCESS(Status))\r
+            {\r
+                /* Attach the Shared Section */\r
+                Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);\r
+\r
+                /* Check how this went */\r
+                if (NT_SUCCESS(Status)) AllowConnection = TRUE;\r
+            }\r
+\r
+            /* Dereference the project */\r
+            CsrProcess->ReferenceCount--;\r
+        }\r
+    }\r
+\r
+    /* Release the lock */\r
+    CsrReleaseProcessLock();\r
+\r
+    /* Setup the Port View Structure */\r
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);\r
+    RemotePortView.ViewSize = 0;\r
+    RemotePortView.ViewBase = NULL;\r
+\r
+    /* Save the Process ID */\r
+    ConnectInfo->ProcessId = NtCurrentTeb()->Cid.UniqueProcess;\r
+\r
+    /* Accept the Connection */\r
+    Status = NtAcceptConnectPort(&hPort,\r
+                                 AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,\r
+                                 &ApiMessage->Header,\r
+                                 AllowConnection,\r
+                                 NULL,\r
+                                 &RemotePortView);\r
+\r
+    /* Check if the connection was established, or if we allowed it */\r
+    if (NT_SUCCESS(Status) && AllowConnection)\r
+    {\r
+        /* Set some Port Data in the Process */\r
+        CsrProcess->ClientPort = hPort;\r
+        CsrProcess->ClientViewBase = (ULONG_PTR)RemotePortView.ViewBase;\r
+        CsrProcess->ClientViewBounds = (ULONG_PTR)((ULONG_PTR)RemotePortView.ViewBase +\r
+                                                   (ULONG_PTR)RemotePortView.ViewSize);\r
+\r
+        /* Complete the connection */\r
+        Status = NtCompleteConnectPort(hPort);\r
+    }\r
+\r
+    /* The accept or complete could've failed, let debug builds know */\r
+    if (!NT_SUCCESS(Status))\r
+    {\r
+        DPRINT1("CSRSS: Failure to accept connection. Status: %lx\n", Status);\r
+    }\r
+\r
+    /* Return status to caller */\r
+    return Status;\r
+}\r
+\r
+/*++\r
+ * @name CsrSbApiRequestThread\r
+ *\r
+ * The CsrSbApiRequestThread routine handles incoming messages or connection\r
+ * requests on the SM API LPC Port.\r
+ *\r
+ * @param Parameter\r
+ *        System-default user-defined parameter. Unused.  \r
+ *\r
+ * @return The thread exit code, if the thread is terminated.\r
+ *\r
+ * @remarks Before listening on the port, the routine will first attempt\r
+ *          to connect to the user subsystem.\r
+ *\r
+ *--*/\r
+VOID\r
+NTAPI\r
+CsrSbApiRequestThread(IN PVOID Parameter)\r
+{\r
+    NTSTATUS Status;\r
+    SB_API_MESSAGE ReceiveMsg;\r
+    PSB_API_MESSAGE ReplyMsg = NULL;\r
+    PVOID PortContext;\r
+    ULONG MessageType;\r
+\r
+    /* Start the loop */\r
+    while (TRUE)\r
+    {\r
+        /* Wait for a message to come in */\r
+        Status = NtReplyWaitReceivePort(CsrSbApiPort,\r
+                                        &PortContext,\r
+                                        (PPORT_MESSAGE)ReplyMsg,\r
+                                        (PPORT_MESSAGE)&ReceiveMsg);\r
+\r
+        /* Check if we didn't get success */\r
+        if(Status != STATUS_SUCCESS)\r
+        {\r
+            /* If we only got a warning, keep going */\r
+            if (NT_SUCCESS(Status)) continue;\r
+\r
+            /* We failed big time, so start out fresh */\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+\r
+        /* Save the message type */\r
+        MessageType = ReceiveMsg.Header.u2.s2.Type;\r
+\r
+        /* Check if this is a connection request */\r
+        if (MessageType == LPC_CONNECTION_REQUEST)\r
+        {\r
+            /* Handle connection request */\r
+            CsrSbApiHandleConnectionRequest(&ReceiveMsg);\r
+\r
+            /* Start over */\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+\r
+        /* Check if the port died */\r
+        if (MessageType == LPC_PORT_CLOSED)\r
+        {\r
+            /* Close the handle if we have one */\r
+            if (PortContext) NtClose((HANDLE)PortContext);\r
+            \r
+            /* Client died, start over */\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+        else if (MessageType == LPC_CLIENT_DIED)\r
+        {\r
+            /* Client died, start over */\r
+            ReplyMsg = NULL;\r
+            continue;\r
+        }\r
+\r
+        /*\r
+         * It's an API Message, check if it's within limits. If it's not, the\r
+         * NT Behaviour is to set this to the Maximum API.\r
+         */\r
+        if (ReceiveMsg.Opcode > 4) ReceiveMsg.Opcode = 4;\r
+\r
+        /* Reuse the message */\r
+        ReplyMsg = &ReceiveMsg;\r
+\r
+        /* Make sure that the message is supported */\r
+        if (ReceiveMsg.Opcode < 4)\r
+        {\r
+            /* Call the API */\r
+            if (!(CsrServerSbApiDispatch[ReceiveMsg.Opcode])(&ReceiveMsg))\r
+            {\r
+                /* It failed, so return nothing */\r
+                ReplyMsg = NULL;\r
+            }\r
+        }\r
+        else\r
+        {\r
+            /* We don't support this API Number */\r
+            ReplyMsg->Status = STATUS_NOT_IMPLEMENTED;\r
+        }\r
+    }\r
+}\r
+\r
+/*++\r
+ * @name CsrSbApiHandleConnectionRequest\r
+ *\r
+ * The CsrSbApiHandleConnectionRequest routine handles and accepts a new\r
+ * connection request to the SM API LPC Port.\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the incoming CSR API Message which contains the\r
+ *        connection request.\r
+ *\r
+ * @return STATUS_SUCCESS in case of success, or status code which caused\r
+ *         the routine to error.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrSbApiHandleConnectionRequest(IN PSB_API_MESSAGE Message)\r
+{\r
+    NTSTATUS Status;\r
+    REMOTE_PORT_VIEW RemotePortView;\r
+    HANDLE hPort;\r
+\r
+    /* Set the Port View Structure Length */\r
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);\r
+\r
+    /* Accept the connection */\r
+    Status = NtAcceptConnectPort(&hPort,\r
+                                 NULL,\r
+                                 (PPORT_MESSAGE)Message,\r
+                                 TRUE,\r
+                                 NULL,\r
+                                 &RemotePortView);\r
+\r
+    if (!NT_SUCCESS(Status))\r
+    {\r
+        DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status);\r
+        return Status;\r
+    }\r
+\r
+    /* Complete the Connection */\r
+    if (!NT_SUCCESS(Status = NtCompleteConnectPort(hPort)))\r
+    {\r
+        DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status);\r
+    }\r
+\r
+    /* Return status */\r
+    return Status;\r
+}\r
+\r
+/* PUBLIC FUNCTIONS **********************************************************/\r
+\r
+/*++\r
+ * @name CsrCallServerFromServer\r
+ * @implemented NT4\r
+ *\r
+ * The CsrCallServerFromServer routine calls a CSR API from within a server.\r
+ * It avoids using LPC messages since the request isn't coming from a client.\r
+ *\r
+ * @param ReceiveMsg\r
+ *        Pointer to the CSR API Message to send to the server.\r
+ *\r
+ * @param ReplyMsg\r
+ *        Pointer to the CSR API Message to receive from the server.\r
+ *\r
+ * @return STATUS_SUCCESS in case of success, STATUS_ILLEGAL_FUNCTION\r
+ *         if the opcode is invalid, or STATUS_ACCESS_VIOLATION if there\r
+ *         was a problem executing the API.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+NTSTATUS\r
+NTAPI\r
+CsrCallServerFromServer(PCSR_API_MESSAGE ReceiveMsg,\r
+                        PCSR_API_MESSAGE ReplyMsg)\r
+{\r
+    ULONG ServerId;\r
+    PCSR_SERVER_DLL ServerDll;\r
+    ULONG ApiId;\r
+    ULONG Reply;\r
+    NTSTATUS Status;\r
+\r
+    /* Get the Server ID */\r
+    ServerId = CSR_SERVER_ID_FROM_OPCODE(ReceiveMsg->Opcode);\r
+\r
+    /* Make sure that the ID is within limits, and the Server DLL loaded */\r
+    if ((ServerId >= CSR_SERVER_DLL_MAX) ||\r
+        (!(ServerDll = CsrLoadedServerDll[ServerId])))\r
+    {\r
+        /* We are beyond the Maximum Server ID */\r
+        ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;\r
+        return STATUS_ILLEGAL_FUNCTION;\r
+    }\r
+    else\r
+    {\r
+        /* Get the API ID */\r
+        ApiId = CSR_API_ID_FROM_OPCODE(ReceiveMsg->Opcode);\r
+\r
+        /* Normalize it with our Base ID */\r
+        ApiId -= ServerDll->ApiBase;\r
+\r
+        /* Make sure that the ID is within limits, and the entry exists */\r
+        if ((ApiId >= ServerDll->HighestApiSupported) ||\r
+            (ServerDll->ValidTable && !ServerDll->ValidTable[ApiId]))\r
+        {\r
+            /* We are beyond the Maximum API ID, or it doesn't exist */\r
+            ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;\r
+            return STATUS_ILLEGAL_FUNCTION;\r
+        }\r
+    }\r
+\r
+    /* Validation complete, start SEH */\r
+    _SEH_TRY\r
+    {\r
+        /* Call the API and get the result */\r
+        Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);\r
+\r
+        /* Return the result, no matter what it is */\r
+        ReplyMsg->Status = Status;\r
+    }\r
+    _SEH_HANDLE\r
+    {\r
+        /* If we got an exception, return access violation */\r
+        ReplyMsg->Status = STATUS_ACCESS_VIOLATION;\r
+    }\r
+    _SEH_END;\r
+\r
+    /* Return success */\r
+    return STATUS_SUCCESS;\r
+}\r
+\r
+/*++\r
+ * @name CsrConnectToUser\r
+ * @implemented NT4\r
+ *\r
+ * The CsrConnectToUser connects to the User subsystem.\r
+ *\r
+ * @param None   \r
+ *\r
+ * @return A pointer to the CSR Thread\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+PCSR_THREAD\r
+NTAPI\r
+CsrConnectToUser(VOID)\r
+{\r
+    NTSTATUS Status;\r
+    ANSI_STRING DllName;\r
+    UNICODE_STRING TempName;\r
+    HANDLE hUser32;\r
+    STRING StartupName;\r
+    PTEB Teb = NtCurrentTeb();\r
+    PCSR_THREAD CsrThread;\r
+\r
+    /* Check if we didn't already find it */\r
+    if (!CsrClientThreadSetup)\r
+    {\r
+        /* Get the DLL Handle for user32.dll */\r
+        RtlInitAnsiString(&DllName, "user32");\r
+        RtlAnsiStringToUnicodeString(&TempName, &DllName, TRUE);\r
+        Status = LdrGetDllHandle(NULL,\r
+                                 NULL,\r
+                                 &TempName,\r
+                                 &hUser32);\r
+        RtlFreeUnicodeString(&TempName);\r
+\r
+        /* If we got teh handle, get the Client Thread Startup Entrypoint */\r
+        if (NT_SUCCESS(Status))\r
+        {\r
+            RtlInitAnsiString(&StartupName,"ClientThreadSetup");\r
+            Status = LdrGetProcedureAddress(hUser32,\r
+                                            &StartupName,\r
+                                            0,\r
+                                            (PVOID)&CsrClientThreadSetup);\r
+        }\r
+    }\r
+\r
+    /* Connect to user32 */\r
+    CsrClientThreadSetup();\r
+\r
+    /* Save pointer to this thread in TEB */\r
+    CsrThread = CsrLocateThreadInProcess(NULL, &Teb->Cid);\r
+    if (CsrThread) Teb->CsrClientThread = CsrThread;\r
+\r
+    /* Return it */\r
+    return CsrThread;\r
+}\r
+\r
+/*++\r
+ * @name CsrQueryApiPort\r
+ * @implemented NT4\r
+ *\r
+ * The CsrQueryApiPort routine returns a handle to the CSR API LPC port.\r
+ *\r
+ * @param None.\r
+ *\r
+ * @return A handle to the port.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+HANDLE\r
+NTAPI\r
+CsrQueryApiPort(VOID)\r
+{\r
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);\r
+    return CsrApiPort;\r
+}\r
+\r
+/*++\r
+ * @name CsrCaptureArguments\r
+ * @implemented NT5.1\r
+ *\r
+ * The CsrCaptureArguments routine validates a CSR Capture Buffer and\r
+ * re-captures it into a server CSR Capture Buffer.\r
+ *\r
+ * @param CsrThread\r
+ *        Pointer to the CSR Thread performing the validation.\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the CSR API Message containing the Capture Buffer\r
+ *        that needs to be validated.\r
+ *\r
+ * @return TRUE if validation succeeded, FALSE otherwise.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+BOOLEAN\r
+NTAPI\r
+CsrCaptureArguments(IN PCSR_THREAD CsrThread,\r
+                    IN PCSR_API_MESSAGE ApiMessage)\r
+{\r
+    PCSR_CAPTURE_BUFFER LocalCaptureBuffer;\r
+    ULONG LocalLength;\r
+    PCSR_CAPTURE_BUFFER RemoteCaptureBuffer;\r
+    SIZE_T BufferDistance;\r
+    ULONG PointerCount;\r
+    ULONG_PTR **PointerOffsets;\r
+    ULONG_PTR *CurrentPointer;\r
+\r
+    /* Use SEH to make sure this is valid */\r
+    _SEH_TRY\r
+    {\r
+        /* Get the buffer we got from whoever called NTDLL */\r
+        LocalCaptureBuffer = ApiMessage->CsrCaptureData;\r
+        LocalLength = LocalCaptureBuffer->Size;\r
+\r
+        /* Now check if the buffer is inside our mapped section */\r
+        if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||\r
+            (((ULONG_PTR)LocalCaptureBuffer + LocalLength) >= CsrThread->Process->ClientViewBounds))\r
+        {\r
+            /* Return failure */\r
+            ApiMessage->Status = STATUS_INVALID_PARAMETER;\r
+            return FALSE;\r
+        }\r
+\r
+        /* Check if the Length is valid */\r
+        if (((LocalCaptureBuffer->PointerCount * 4 + sizeof(CSR_CAPTURE_BUFFER)) >\r
+            LocalLength) ||(LocalLength > MAXWORD))\r
+        {\r
+            /* Return failure */\r
+            ApiMessage->Status = STATUS_INVALID_PARAMETER;\r
+            return FALSE;\r
+        }\r
+    }\r
+    _SEH_HANDLE\r
+    {\r
+        /* Return failure */\r
+        ApiMessage->Status = STATUS_INVALID_PARAMETER;\r
+        return FALSE;\r
+    } _SEH_END;\r
+\r
+    /* We validated the incoming buffer, now allocate the remote one */\r
+    RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, LocalLength);\r
+    if (!RemoteCaptureBuffer)\r
+    {\r
+        /* We're out of memory */\r
+        ApiMessage->Status = STATUS_NO_MEMORY;\r
+        return FALSE;\r
+    }\r
+\r
+    /* Copy the client's buffer */\r
+    RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, LocalLength);\r
+\r
+    /* Copy the length */\r
+    RemoteCaptureBuffer->Size = LocalLength;\r
+\r
+    /* Calculate the difference between our buffer and the client's */\r
+    BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;\r
+\r
+    /* Save the pointer count and offset pointer */\r
+    PointerCount = RemoteCaptureBuffer->PointerCount;\r
+    PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);\r
+\r
+    /* Start the loop */\r
+    while (PointerCount)\r
+    {\r
+        /* Get the current pointer */\r
+        if ((CurrentPointer = *PointerOffsets++))\r
+        {\r
+            /* Add it to the CSR Message structure */\r
+            CurrentPointer += (ULONG_PTR)ApiMessage;\r
+\r
+            /* Validate the bounds of the current pointer */\r
+            if ((*CurrentPointer >= CsrThread->Process->ClientViewBase) &&\r
+                (*CurrentPointer < CsrThread->Process->ClientViewBounds))\r
+            {\r
+                /* Modify the pointer to take into account its new position */\r
+                *CurrentPointer += BufferDistance;\r
+            }\r
+            else\r
+            {\r
+                /* Invalid pointer, fail */\r
+                ApiMessage->Status = (ULONG)STATUS_INVALID_PARAMETER;\r
+            }\r
+        }\r
+\r
+        /* Move to the next Pointer */\r
+        PointerCount--;\r
+    }\r
+\r
+    /* Check if we got success */\r
+    if (ApiMessage->Status != STATUS_SUCCESS)\r
+    {\r
+        /* Failure. Free the buffer and return*/\r
+        RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);\r
+        return FALSE;\r
+    }\r
+    else\r
+    {\r
+        /* Success, save the previous buffer */\r
+        RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer;\r
+        ApiMessage->CsrCaptureData = RemoteCaptureBuffer;\r
+    }\r
+     \r
+    /* Success */\r
+    return TRUE;\r
+}\r
+\r
+/*++\r
+ * @name CsrReleaseCapturedArguments\r
+ * @implemented NT5.1\r
+ *\r
+ * The CsrReleaseCapturedArguments routine releases a Capture Buffer\r
+ * that was previously captured with CsrCaptureArguments.\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the CSR API Message containing the Capture Buffer\r
+ *        that needs to be released.\r
+ *\r
+ * @return None.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+VOID\r
+NTAPI\r
+CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)\r
+{\r
+    PCSR_CAPTURE_BUFFER RemoteCaptureBuffer;\r
+    PCSR_CAPTURE_BUFFER LocalCaptureBuffer;\r
+    SIZE_T BufferDistance;\r
+    ULONG PointerCount;\r
+    ULONG_PTR **PointerOffsets;\r
+    ULONG_PTR *CurrentPointer;\r
+\r
+    /* Get the capture buffers */\r
+    RemoteCaptureBuffer = ApiMessage->CsrCaptureData;\r
+    LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;\r
+\r
+    /* Free the previous one */\r
+    RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;\r
+\r
+    /* Find out the difference between the two buffers */\r
+    BufferDistance = (ULONG_PTR)LocalCaptureBuffer - (ULONG_PTR)RemoteCaptureBuffer;\r
+  \r
+    /* Save the pointer count and offset pointer */\r
+    PointerCount = RemoteCaptureBuffer->PointerCount;\r
+    PointerOffsets = (ULONG_PTR**)(RemoteCaptureBuffer + 1);\r
+\r
+    /* Start the loop */\r
+    while (PointerCount)\r
+    {\r
+        /* Get the current pointer */\r
+        if ((CurrentPointer = *PointerOffsets++))\r
+        {\r
+            /* Add it to the CSR Message structure */\r
+            CurrentPointer += (ULONG_PTR)ApiMessage;\r
+\r
+            /* Modify the pointer to take into account its new position */\r
+            *CurrentPointer += BufferDistance;\r
+        }\r
+                \r
+        /* Move to the next Pointer */\r
+        PointerCount--;\r
+    }\r
+\r
+    /* Copy the data back */\r
+    RtlMoveMemory(LocalCaptureBuffer,\r
+                  RemoteCaptureBuffer,\r
+                  RemoteCaptureBuffer->Size);\r
+\r
+    /* Free our allocated buffer */\r
+    RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);\r
+}\r
+\r
+/*++\r
+ * @name CsrValidateMessageBuffer\r
+ * @implemented NT5.1\r
+ *\r
+ * The CsrValidateMessageBuffer routine validates a captured message buffer\r
+ * present in the CSR Api Message\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the CSR API Message containing the CSR Capture Buffer.\r
+ *\r
+ * @param Buffer\r
+ *        Pointer to the message buffer to validate.\r
+ *\r
+ * @param ArgumentSize\r
+ *        Size of the message to check.\r
+ *\r
+ * @param ArgumentCount\r
+ *        Number of messages to check.\r
+ *\r
+ * @return TRUE if validation suceeded, FALSE otherwise.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+BOOLEAN\r
+NTAPI\r
+CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,\r
+                         IN PVOID *Buffer,\r
+                         IN ULONG ArgumentSize,\r
+                         IN ULONG ArgumentCount)\r
+{\r
+    PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;\r
+    SIZE_T BufferDistance;\r
+    ULONG PointerCount;\r
+    ULONG_PTR **PointerOffsets;\r
+    ULONG_PTR *CurrentPointer;\r
+    ULONG i;\r
+\r
+    /* Make sure there are some arguments */\r
+    if (!ArgumentCount) return FALSE;\r
+\r
+    /* Check if didn't get a buffer and there aren't any arguments to check */\r
+    if (!(*Buffer) && (!(ArgumentCount * ArgumentSize))) return TRUE;\r
+\r
+    /* Check if we have no capture buffer */\r
+    if (!CaptureBuffer)\r
+    {\r
+        /* In this case, check only the Process ID */\r
+        if (NtCurrentTeb()->Cid.UniqueProcess ==\r
+            ApiMessage->Header.ClientId.UniqueProcess)\r
+        {\r
+            /* There is a match, validation succeeded */\r
+            return TRUE;\r
+        }\r
+    }\r
+    else\r
+    {\r
+        /* Make sure that there is still space left in the buffer */\r
+        if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) <\r
+            (ArgumentCount * ArgumentSize))\r
+        {\r
+            /* Find out the difference between the two buffers */\r
+            BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;\r
+\r
+             /* Save the pointer count */\r
+            PointerCount = CaptureBuffer->PointerCount;\r
+            PointerOffsets = (ULONG_PTR**)(CaptureBuffer + 1);\r
+\r
+            /* Start the loop */\r
+            for (i = 0; i < PointerCount; i++)\r
+            {\r
+                /* Get the current pointer */\r
+                CurrentPointer = *PointerOffsets++;\r
+\r
+                /* Check if its' equal to the difference */\r
+                if (*CurrentPointer == BufferDistance) return TRUE;\r
+            }\r
+        }\r
+    }\r
+\r
+    /* Failure */\r
+    return FALSE;\r
+}\r
+\r
+/*++\r
+ * @name CsrValidateMessageString\r
+ * @implemented NT5.1\r
+ *\r
+ * The CsrValidateMessageString validates a captured Wide-Character String\r
+ * present in a CSR API Message.\r
+ *\r
+ * @param ApiMessage\r
+ *        Pointer to the CSR API Message containing the CSR Capture Buffer.\r
+ *\r
+ * @param MessageString\r
+ *        Pointer to the buffer containing the string to validate.\r
+ *\r
+ * @return TRUE if validation suceeded, FALSE otherwise.\r
+ *\r
+ * @remarks None.\r
+ *\r
+ *--*/\r
+BOOLEAN\r
+NTAPI\r
+CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,\r
+                         IN LPWSTR *MessageString)\r
+{\r
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);\r
+    return FALSE;\r
+}\r
+\r
+/* EOF */\r
index 1a1f066..0efc417 100644 (file)
@@ -1,37 +1,38 @@
-; $Id$
-LIBRARY csrsrv.dll
+LIBRARY CSRSRV
+
 EXPORTS
-CsrAddStaticServerThread@4
-CsrCallServerFromServer@0
-CsrCreateProcess@8
-CsrCreateRemoteThread@0
-CsrCreateThread@8
-CsrCreateWait@8
-CsrDebugProcess@4
-CsrDebugProcessStop@4
-CsrDereferenceProcess@4
-CsrDereferenceThread@4
-CsrDereferenceWait@4
-CsrDestroyProcess@4
-CsrDestroyThread@4
-CsrExecServerThread@0
-CsrGetProcessLuid@8
-CsrImpersonateClient@0
-CsrLockProcessByClientId@0
-CsrLockThreadByClientId@0
-CsrMoveSatisfiedWait@4
-CsrNotifyWait@4
-CsrQueryApiPort@0
-CsrReferenceThread@4
-CsrRevertToSelf@0
-CsrServerInitialization@8
-CsrSetBackgroundPriority@0
-CsrSetCallingSpooler@0
-CsrSetForegroundPriority@0
-CsrShutdownProcesses@4
-CsrUnhandledExceptionFilter@0
-CsrUnlockProcess@4
-CsrUnlockThread@4
-CsrValidateMessageBuffer@0
-CsrValidateMessageString@0
-; EOF
+CsrAddStaticServerThread
+CsrCallServerFromServer
+CsrConnectToUser
+CsrCreateProcess
+CsrCreateRemoteThread
+CsrCreateThread
+CsrCreateWait
+CsrDebugProcess
+CsrDebugProcessStop
+CsrDereferenceProcess
+CsrDereferenceThread
+CsrDereferenceWait
+CsrDestroyProcess
+CsrDestroyThread
+CsrExecServerThread
+CsrGetProcessLuid
+CsrImpersonateClient
+CsrLockProcessByClientId
+CsrLockThreadByClientId
+CsrMoveSatisfiedWait
+CsrNotifyWait
+CsrPopulateDosDevices
+CsrQueryApiPort
+CsrReferenceThread
+CsrRevertToSelf
+CsrServerInitialization
+CsrSetBackgroundPriority
+CsrSetCallingSpooler
+CsrSetForegroundPriority
+CsrShutdownProcesses
+CsrUnhandledExceptionFilter
+CsrUnlockProcess
+CsrUnlockThread
+CsrValidateMessageBuffer
+CsrValidateMessageString
diff --git a/reactos/subsys/csr/csrsrv/debug.c b/reactos/subsys/csr/csrsrv/debug.c
deleted file mode 100644 (file)
index c5c9abd..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id$
- *
- * subsys/csr/csrsrv/debug.c - CSR server - debugging management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
- */
-#include "srv.h"
-
-//#define NDEBUG
-#include <debug.h>
-
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
-
-NTSTATUS STDCALL CsrDebugProcess (PCSR_PROCESS pCsrProcess)
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, pCsrProcess);
-       
-       return Status;
-}
-
-NTSTATUS STDCALL CsrDebugProcessStop (PCSR_PROCESS pCsrProcess)
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, pCsrProcess);
-       
-       return Status;
-}
-
-/* EOF */
diff --git a/reactos/subsys/csr/csrsrv/dllmain.c b/reactos/subsys/csr/csrsrv/dllmain.c
deleted file mode 100644 (file)
index 483aacf..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS system libraries
- * FILE:            subsys/csr/csrsrv/dllmain.c
- * PURPOSE:         DLL entry point
- */
-
-/* INCLUDES ******************************************************************/
-
-#include "srv.h"
-
-#define NDEBUG
-#include <debug.h>
-
-HANDLE CsrSrvDllHandle = 0;
-
-/* FUNCTIONS *****************************************************************/
-
-BOOL STDCALL
-DllMain(HANDLE hDll,
-       DWORD dwReason,
-       LPVOID lpReserved)
-{
-  if (DLL_PROCESS_ATTACH == dwReason)
-    {
-      CsrSrvDllHandle = hDll;
-    }
-
-  return TRUE;
-}
-
-/* EOF */
index 2b28762..6dabdda 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/init.c - CSR server - initialization
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/init.c
+ * PURPOSE:         CSR Server DLL Initialization
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
 
+/* INCLUDES ******************************************************************/
+
 #include "srv.h"
 
-//#define NDEBUG
+#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;
 
-typedef enum {
-       CSRAT_UNKNOWN=0,
-       CSRAT_OBJECT_DIRECTORY,
-       CSRAT_SUBSYSTEM_TYPE,
-       CSRAT_REQUEST_THREADS, /* ReactOS extension */
-       CSRAT_REQUEST_THREADS_MAX,
-       CSRAT_PROFILE_CONTROL,
-       CSRAT_SHARED_SECTION,
-       CSRAT_SERVER_DLL,
-       CSRAT_WINDOWS,
-       CSRAT_SESSIONS, /* ReactOS extension */
-       CSRAT_MAX
-} CSR_ARGUMENT_TYPE, *PCSR_ARGUMENT_TYPE;
-
-typedef struct _CSR_ARGUMENT_ITEM
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrPopulateDosDevicesDirectory
+ *
+ * The CsrPopulateDosDevicesDirectory routine uses the DOS Device Map from the
+ * Kernel to populate the Dos Devices Object Directory for the session.
+ *
+ * @param TODO.
+ *
+ * @return TODO.
+ *
+ * @remarks TODO.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrPopulateDosDevicesDirectory(IN HANDLE hDosDevicesDirectory,
+                               IN PPROCESS_DEVICEMAP_INFORMATION DeviceMap)
 {
-       CSR_ARGUMENT_TYPE Type;
-       UNICODE_STRING Data;
-       union {
-               UNICODE_STRING     ObjectDirectory;
-               CSR_SUBSYSTEM_TYPE SubSystemType;
-               USHORT             RequestThreads;
-               USHORT             MaxRequestThreads;
-               BOOL               ProfileControl;
-               BOOL               Windows;
-               BOOL               Sessions;
-               CSR_SERVER_DLL     ServerDll;
-               struct {
-                                  USHORT PortSectionSize;                   // 1024k; 128k..?
-                                  USHORT InteractiveDesktopHeapSize;    // 3072k; 128k..
-                                  USHORT NonInteractiveDesktopHeapSize; // (InteractiveDesktopHeapSize); 128k..
-                                  USHORT Reserved; /* unused */
-                                } SharedSection;
-       } Item;
-       
-} CSR_ARGUMENT_ITEM, * PCSR_ARGUMENT_ITEM;
-
-/**********************************************************************
- * CsrpStringToBool/3                                          PRIVATE
- */
-static BOOL STDCALL CsrpStringToBool (LPWSTR TestString, LPWSTR TrueString, LPWSTR FalseString)
+    WCHAR SymLinkBuffer[0x1000];
+    UNICODE_STRING GlobalString;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE hDirectory = 0;
+    NTSTATUS Status;
+    ULONG ReturnLength = 0;
+    ULONG BufferLength = 0x4000;
+    ULONG Context;
+    POBJECT_DIRECTORY_INFORMATION QueryBuffer;
+    HANDLE hSymLink;
+    UNICODE_STRING LinkTarget;
+
+    /* Initialize the Global String */
+    RtlInitUnicodeString(&GlobalString, GLOBAL_ROOT);
+
+    /* Initialize the Object Attributes */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &GlobalString,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    /* Open the directory */
+    Status = NtOpenDirectoryObject(&hDirectory,
+                                   DIRECTORY_QUERY,
+                                   &ObjectAttributes);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /*  Allocate memory */
+    QueryBuffer = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, 0x4000);
+    if (!QueryBuffer) return STATUS_NO_MEMORY;
+
+    /* Start query loop */
+    while (TRUE)
+    {
+        /* Query the Directory */
+        Status = NtQueryDirectoryObject(hDirectory,
+                                        QueryBuffer,
+                                        BufferLength,
+                                        FALSE,
+                                        FALSE,
+                                        &Context,
+                                        &ReturnLength);
+
+        /* Check for the status */
+        if (NT_SUCCESS(Status))
+        {
+            /* Make sure it has a name */
+            if (!QueryBuffer->ObjectName.Buffer[0]) continue;
+
+            /* Check if it's actually a symbolic link */
+            if (wcscmp(QueryBuffer->ObjectTypeName.Buffer, SYMLINK_NAME))
+            {
+                /* It is, open it */
+                InitializeObjectAttributes(&ObjectAttributes,
+                                           &QueryBuffer->ObjectName,
+                                           OBJ_CASE_INSENSITIVE,
+                                           NULL,
+                                           hDirectory);
+                Status = NtOpenSymbolicLinkObject(&hSymLink,
+                                                  SYMBOLIC_LINK_QUERY,
+                                                  &ObjectAttributes);
+                if (NT_SUCCESS(Status))
+                {
+                    /* Setup the Target String */
+                    LinkTarget.Length = 0;
+                    LinkTarget.MaximumLength = sizeof(SymLinkBuffer);
+                    LinkTarget.Buffer = SymLinkBuffer;
+                    
+                    /* Query the target */
+                    Status = NtQuerySymbolicLinkObject(hSymLink,
+                                                       &LinkTarget,
+                                                       &ReturnLength);
+
+                    /* Close the handle */
+                    NtClose(hSymLink);
+
+                }
+            }
+        }
+    }
+}
+
+/*++
+ * @name CsrLoadServerDllFromCommandLine
+ *
+ * The CsrLoadServerDllFromCommandLine routine loads a Server DLL from the
+ * CSRSS command-line in the registry.
+ *
+ * @param KeyValue
+ *        Pointer to the specially formatted string for this Server DLL.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrLoadServerDllFromCommandLine(PCHAR KeyValue)
 {
-       if((0 == wcscmp(TestString, TrueString)))
-       {
-               return TRUE;
-       }
-       if((0 == wcscmp(TestString, FalseString)))
-       {
-               return FALSE;
-       }
-       DPRINT1("CSRSRV:%s: replacing invalid value '%S' with '%S'!\n",
-                       __FUNCTION__, TestString, FalseString);
-       return FALSE;
+    PCHAR EntryPoint = NULL;
+    ULONG DllIndex = 0;
+    PCHAR ServerString = KeyValue;
+    NTSTATUS Status;
+
+    /* Loop the command line */
+    while (*ServerString)
+    {
+        /* Check for the Entry Point */
+        if ((*ServerString == ':') && (!EntryPoint))
+        {
+            /* Found it. Add a nullchar and save it */
+            *ServerString++ = '\0';
+            EntryPoint = ServerString;
+        }
+
+        /* Check for the Dll Index */
+        if (*ServerString++ == ',')
+        {
+            /* Convert it to a ULONG */
+            Status = RtlCharToInteger(ServerString, 10, &DllIndex);
+
+            /* Add a null char if it was valid */
+            if (NT_SUCCESS(Status)) ServerString[-1] = '\0';
+
+            /* We're done here */
+            break;
+        }
+    }
+
+    /* We've got the name, entrypoint and index, load it */
+    return CsrLoadServerDll(KeyValue, EntryPoint, DllIndex);
 }
-/**********************************************************************
- * CsrpSplitServerDll/2                                                PRIVATE
+
+/*++
+ * @name CsrpParseCommandLine
  *
- * RETURN VALUE
- *     0: syntax error
- *     2: ServerDll=="basesrv,1"
- *     3: ServerDll=="winsrv:UserServerDllInitialization,3"
- */
-static INT STDCALL CsrpSplitServerDll (LPWSTR ServerDll, PCSR_ARGUMENT_ITEM pItem)
+ * The CsrpParseCommandLine 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
+CsrpParseCommandLine(IN ULONG ArgumentCount,
+                     IN PCHAR Arguments[])
 {
-       LPWSTR DllName = NULL;
-       LPWSTR DllEntryPoint = NULL;
-       LPWSTR DllId = NULL;
-       static LPWSTR DefaultDllEntryPoint = L"ServerDllInitialization";
-       LPWSTR tmp = NULL;
-       INT rc = 0;
-       PCSR_SERVER_DLL pCsrServerDll = & pItem->Item.ServerDll;
-
-       if (L'\0' == *ServerDll)
-       {
-               return 0;
-       }
-       /*
-        *      DllName (required)
-        */
-       DllName = ServerDll;
-       if (NULL == DllName)
-       {
-               return 0;
-       }
-       /*
-        *      DllEntryPoint (optional)
-        */
-       DllEntryPoint = wcschr (ServerDll, L':');
-       if (NULL == DllEntryPoint)
-       {
-               DllEntryPoint = DefaultDllEntryPoint;
-               tmp = ServerDll;
-               rc = 2;
-       } else {
-               tmp = ++DllEntryPoint;
-               rc = 3;
-       }
-       /*
-        *      DllId (required)
-        */     
-       DllId = wcschr (tmp, L',');
-       if (NULL == DllId)
-       {
-               return 0;
-       }
-       *DllId++ = L'\0';
-       // OK
-       pCsrServerDll->ServerIndex = wcstoul (DllId, NULL, 10);
-       pCsrServerDll->Unused = 0;
-       RtlInitUnicodeString (& pCsrServerDll->DllName, DllName);
-       RtlInitUnicodeString (& pCsrServerDll->DllEntryPoint, DllEntryPoint);
-       return rc;
+    NTSTATUS Status;
+    PCHAR ParameterName = NULL;
+    PCHAR ParameterValue = NULL;
+    ULONG i;
+
+    /* 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 SID is 0 */
+        if (SessionId != 0) return Status;
+    }
+
+    /* Loop through every argument */
+    for (i = 1; i < ArgumentCount; i++)
+    {
+        /* Split Name and Value */
+        ParameterName = Arguments[i];
+        ParameterValue = strchr(ParameterName, L'=');
+        *ParameterValue++ = '\0';
+        DPRINT("Name=%S, Value=%S\n", ParameterName, ParameterValue);
+
+        /* Check for Object Directory */
+        if (!_stricmp(ParameterName, "ObjectDirectory"))
+        {
+            CsrCreateObjectDirectory(ParameterValue);
+        }
+        else if(!_stricmp(ParameterName, "SubSystemType"))
+        {
+            /* Ignored */
+            Status = STATUS_SUCCESS;
+        }
+        else if (!_stricmp(ParameterName, "MaxRequestThreads"))
+        {
+            Status = RtlCharToInteger(ParameterValue,
+                                      0,
+                                      &CsrMaxApiRequestThreads);
+        }
+        else if (!_stricmp(ParameterName, "RequestThreads"))
+        {
+            /* Ignored */
+            Status = STATUS_SUCCESS;
+        }
+        else if (!_stricmp(ParameterName, "ProfileControl"))
+        {
+            CsrProfileControl = (!_stricmp(ParameterValue, "On")) ? TRUE : FALSE;
+        }
+        else if (!_stricmp(ParameterName, "SharedSection"))
+        {
+            /* Craete the Section */
+            Status = CsrSrvCreateSharedSection(ParameterValue);
+
+            /* Load us */
+            Status = CsrLoadServerDll("CSRSS", NULL, CSR_SRV_SERVER);
+        }
+        else if (!_stricmp(ParameterName, "ServerDLL"))
+        {
+            /* Parse the Command-Line and load this DLL */
+            Status = CsrLoadServerDllFromCommandLine(ParameterValue);
+        }
+        else if (!_stricmp(ParameterName, "Windows"))
+        {
+            /* Ignored */
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            /* Invalid parameter on the command line */
+            Status = STATUS_INVALID_PARAMETER;
+        }
+    }
+
+    /* Return status */
+    return Status;
 }
-/**********************************************************************
- * CsrpSplitSharedSection/2                                    PRIVATE
- *
- * RETURN VALUE
- *     0: syntax error
- *     1: PortSectionSize (required)
- *     2: PortSection,InteractiveDesktopHeap
- *     3: PortSection,InteractiveDesktopHeap,NonInteractiveDesktopHeap
- */
-static INT STDCALL CsrpSplitSharedSection (LPWSTR SharedSection, PCSR_ARGUMENT_ITEM pItem)
+
+/*++
+ * @name CsrCreateObjectDirectory
+ *
+ * The CsrCreateObjectDirectory creates the Object Directory on the CSRSS
+ * command-line from the registry.
+ *
+ * @param ObjectDirectory
+ *        Pointer to the name of the Object Directory to create.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateObjectDirectory(IN PCHAR ObjectDirectory)
 {
-       LPWSTR PortSectionSize = NULL;
-       LPWSTR InteractiveDesktopHeapSize = NULL;
-       LPWSTR NonInteractiveDesktopHeapSize = NULL;
-       INT rc = 1;
-
-       DPRINT("CSRSRV:%s(%S) called\n", __FUNCTION__, SharedSection);
-
-       if(L'\0' == *SharedSection)
-       {
-               DPRINT("CSRSRV:%s(%S): *SharedSection == L'\\0'\n", __FUNCTION__, SharedSection);
-               return 0;
-       }
-
-       // PortSectionSize (required)
-       PortSectionSize = SharedSection;
-       // InteractiveDesktopHeapSize (optional)
-       InteractiveDesktopHeapSize = wcschr (PortSectionSize, L',');
-       if (NULL == InteractiveDesktopHeapSize)
-       {
-               // Default value is 128k
-               InteractiveDesktopHeapSize = L"128";
-       } else {
-               rc = 2;
-       }
-       // NonInteractiveDesktopHeapSize (optional)
-       NonInteractiveDesktopHeapSize = wcschr (InteractiveDesktopHeapSize, L',');
-       if (NULL == NonInteractiveDesktopHeapSize)
-       {
-               // Default value equals interactive one
-               NonInteractiveDesktopHeapSize = InteractiveDesktopHeapSize;
-       } else {
-               rc = 3;
-       }
-       // OK - normalization
-       pItem->Item.SharedSection.PortSectionSize = wcstoul (PortSectionSize, NULL, 10);
-       if (pItem->Item.SharedSection.PortSectionSize < 64)
-       {
-               pItem->Item.SharedSection.PortSectionSize = 64;
-       }
-       pItem->Item.SharedSection.InteractiveDesktopHeapSize = wcstoul (InteractiveDesktopHeapSize, NULL, 10);
-       if (pItem->Item.SharedSection.InteractiveDesktopHeapSize < 128)
-       {
-               pItem->Item.SharedSection.InteractiveDesktopHeapSize = 128;
-       }
-       pItem->Item.SharedSection.NonInteractiveDesktopHeapSize = wcstoul (NonInteractiveDesktopHeapSize, NULL, 10);
-       if (pItem->Item.SharedSection.NonInteractiveDesktopHeapSize < 128)
-       {
-               pItem->Item.SharedSection.NonInteractiveDesktopHeapSize = 128;
-       }
-       // done
-       return rc;
+    NTSTATUS Status = STATUS_SUCCESS;
+    ANSI_STRING TempString;
+    OBJECT_ATTRIBUTES DirectoryAttributes;
+
+    DPRINT("CSRSRV:%s(%s) called\n", __FUNCTION__, ObjectDirectory);
+
+    /* Convert the parameter to our Global Unicode name */
+    RtlInitAnsiString(&TempString, ObjectDirectory);
+    Status = RtlAnsiStringToUnicodeString(&CsrDirectoryName, &TempString, TRUE);
+
+    /* Initialize the attributes for the Directory */
+    InitializeObjectAttributes(&DirectoryAttributes,
+                               &CsrDirectoryName,
+                               OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&CsrObjectDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &DirectoryAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
+                __FUNCTION__, Status);
+    }
+
+    /* Set the Security */
+    Status = CsrSetDirectorySecurity(CsrObjectDirectory);
+
+    /* Return */
+    return Status;
 }
-/**********************************************************************
- * CsrpParseArgumentItem/1                                     PRIVATE
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *     Argument: argument to decode;
- *
- * RETURN VALUE
- *     STATUS_SUCCESS; otherwise, STATUS_UNSUCCESSFUL and
- *     pItem->Type = CSRAT_UNKNOWN.
- *
- * NOTE
- *     The command line could be as complex as the following one,
- *     which is the original command line for the Win32 subsystem
- *     in NT 5.1:
- *     
- *     %SystemRoot%\system32\csrss.exe
- *             ObjectDirectory=\Windows
- *             SharedSection=1024,3072,512
- *             Windows=On
- *             SubSystemType=Windows
- *             ServerDll=basesrv,1
- *             ServerDll=winsrv:UserServerDllInitialization,3
- *             ServerDll=winsrv:ConServerDllInitialization,2
- *             ProfileControl=Off
- *             MaxRequestThreads=16
- */
-static NTSTATUS FASTCALL CsrpParseArgumentItem (IN OUT PCSR_ARGUMENT_ITEM pItem)
+
+/*++
+ * @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 SidLength;
+    PSECURITY_DESCRIPTOR SecurityDescriptor;
+    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 */
+    SidLength = RtlLengthSid(SystemSid);
+
+    /* Allocate a buffer for the Security Descriptor, with SID and DACL */
+    SecurityDescriptor = RtlAllocateHeap(CsrHeap,
+                                         0,
+                                         SECURITY_DESCRIPTOR_MIN_LENGTH +
+                                         sizeof(ACL) + SidLength +
+                                         sizeof(ACCESS_ALLOWED_ACE));
+
+    /* Set the pointer to the DACL */
+    Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+    /* Now create the SD itself */
+    Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+                                         SECURITY_DESCRIPTOR_REVISION);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        return Status;
+    }
+
+    /* Create the DACL for it*/
+    RtlCreateAcl(Dacl,
+                 sizeof(ACL) + SidLength + sizeof(ACCESS_ALLOWED_ACE),
+                 ACL_REVISION2);
+
+    /* Create the ACE */
+    Status = RtlAddAccessAllowedAce(Dacl,
+                                    ACL_REVISION,
+                                    PORT_ALL_ACCESS,
+                                    SystemSid);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        return Status;
+    }
+
+    /* Clear the DACL in the SD */
+    Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
+                                          TRUE,
+                                          Dacl,
+                                          FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        return Status;
+    }
+
+    /* Free the SID and return*/
+    RtlFreeSid(SystemSid);
+    *LocalSystemSd = SecurityDescriptor;
+    return Status;
+}
+
+/*++
+ * @name CsrGetDosDevicesSd
+ *
+ * The CsrGetDosDevicesSd 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
+CsrGetDosDevicesSd(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;
+
+    /* Create the SD */
+    RtlCreateSecurityDescriptor(DosDevicesSd, SECURITY_DESCRIPTOR_REVISION);
+
+    /* Initialize the System SID */
+    RtlAllocateAndInitializeSid(&NtSidAuthority,
+                                1,
+                                SECURITY_LOCAL_SYSTEM_RID,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                &SystemSid);
+
+    /* Initialize the World SID */
+    RtlAllocateAndInitializeSid(&WorldAuthority,
+                                1,
+                                SECURITY_WORLD_RID,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                &WorldSid);
+
+    /* Initialize the Admin SID */
+    RtlAllocateAndInitializeSid(&NtSidAuthority,
+                                2,
+                                SECURITY_BUILTIN_DOMAIN_RID,
+                                DOMAIN_ALIAS_RID_ADMINS,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                &AdminSid);
+
+    /* Initialize the Creator SID */
+    RtlAllocateAndInitializeSid(&CreatorAuthority,
+                                1,
+                                SECURITY_CREATOR_OWNER_RID,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                0,
+                                &CreatorSid);
+
+    /* Open the Session Manager Key */
+    RtlInitUnicodeString(&KeyName, SM_REG_KEY);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    if (NT_SUCCESS(Status = NtOpenKey(&hKey,
+                                      KEY_READ,
+                                      &ObjectAttributes)))
+    {
+        /* Read the ProtectionMode. See http://support.microsoft.com/kb/q218473/ */
+        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 ((KeyValuePartialInfo->Type == REG_DWORD) && 
+            (*(PULONG)KeyValuePartialInfo->Data != 0))
+        {
+            /* 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);
+
+        /* Allocate memory for the DACL */
+        Dacl = RtlAllocateHeap(CsrHeap,
+                               HEAP_ZERO_MEMORY,
+                               sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
+                               SidLength);
+
+        /* Create it */
+        Status = RtlCreateAcl(Dacl,
+                              sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
+                              SidLength,
+                              ACL_REVISION2);
+
+        /* Give full access to the System */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_ALL,
+                                        SystemSid);
+
+        /* Get the ACE back */
+        Status = RtlGetAce(Dacl, 0, (PACE*)&Ace);
+
+        /* Add some flags to it for the Admin SID */
+        Ace->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
+
+        /* Add the ACE to the Admin SID */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_ALL,
+                                        AdminSid);
+
+        /* Get the ACE back */
+        Status = RtlGetAce(Dacl, 1, (PACE*)&Ace);
+
+        /* Add some flags to it for the Creator SID */
+        Ace->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
+
+        /* Add the ACE to the Admin SID */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_ALL,
+                                        CreatorSid);
+
+        /* Get the ACE back */
+        Status = RtlGetAce(Dacl, 2, (PACE*)&Ace);
+
+        /* Add some flags to it for the SD */
+        Ace->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+                                INHERIT_ONLY_ACE);
+
+        /* Set this DACL with the SD */
+        Status = RtlSetDaclSecurityDescriptor(DosDevicesSd,
+                                              TRUE,
+                                              Dacl,
+                                              FALSE);
+    }
+    else
+    {
+        /* Calculate SID Lengths */
+        SidLength = RtlLengthSid(WorldSid) + RtlLengthSid(SystemSid);
+
+        /* Allocate memory for the DACL */
+        Dacl = RtlAllocateHeap(CsrHeap,
+                               HEAP_ZERO_MEMORY,
+                               sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
+                               SidLength);
+
+        /* Create it */
+        Status = RtlCreateAcl(Dacl,
+                              sizeof(ACL) + 3 * sizeof(ACCESS_ALLOWED_ACE) +
+                              SidLength,
+                              ACL_REVISION2);
+
+        /* Give RWE access to the World */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_READ | GENERIC_WRITE |
+                                        GENERIC_EXECUTE,
+                                        WorldSid);
+
+        /* Give full access to the System */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_ALL,
+                                        SystemSid);
+
+        /* Give full access to the World */
+        Status = RtlAddAccessAllowedAce(Dacl,
+                                        ACL_REVISION,
+                                        GENERIC_ALL,
+                                        WorldSid);
+
+        /* Get the ACE back */
+        Status = RtlGetAce(Dacl, 2, (PACE*)&Ace);
+
+        /* Add some flags to it for the SD */
+        Ace->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
+                                INHERIT_ONLY_ACE);
+
+        /* Set this DACL with the SD */
+        Status = RtlSetDaclSecurityDescriptor(DosDevicesSd,
+                                              TRUE,
+                                              Dacl,
+                                              FALSE);
+    }
+
+/* FIXME: failure cases! Fail: */
+    /* Free the memory */
+    RtlFreeHeap(CsrHeap, 0, Dacl);
+
+/* FIXME: semi-failure cases! Quickie: */
+    /* Free the SIDs */
+    RtlFreeSid(SystemSid);
+    RtlFreeSid(WorldSid);
+    RtlFreeSid(AdminSid);
+    RtlFreeSid(CreatorSid);
+
+    /* Return */
+    return Status;
+}
+
+/*++
+ * @name CsrFreeDosDevicesSd
+ *
+ * The CsrFreeDosDevicesSd frees the security descriptor that was created
+ * by CsrGetDosDevicesSd
+ *
+ * @param DosDevicesSd
+ *        Pointer to the security descriptor to free.
+
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrFreeDosDevicesSd(IN PSECURITY_DESCRIPTOR DosDevicesSd)
+{
+    PACL Dacl;
+    BOOLEAN Present, Default;
+    NTSTATUS Status;
+
+    /* Get the DACL corresponding to this SD */
+    Status = RtlGetDaclSecurityDescriptor(DosDevicesSd,
+                                          &Present,
+                                          &Dacl,
+                                          &Default);
+
+    /* 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];
+    WCHAR BnoBuffer[512];
+    UNICODE_STRING SessionString;
+    UNICODE_STRING BnoString;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE BnoHandle;
+    SECURITY_DESCRIPTOR DosDevicesSd;
+    NTSTATUS Status;
+
+    /* Generate the Session BNOLINKS Directory */
+    swprintf(SessionBuffer, L"%ws\\BNOLINKS", SESSION_ROOT);
+    RtlInitUnicodeString(&SessionString, SessionBuffer);
+
+    /* Initialize the attributes for the Directory */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&BNOLinksDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
+                __FUNCTION__, 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);
+    }
+    else
+    {
+        /* Use the direct name */
+        RtlCopyMemory(BnoBuffer, L"\\BaseNamedObjects", 36);
+    }
+
+    /* Create the Unicode String for the BNO SymLink */
+    RtlInitUnicodeString(&BnoString, BnoBuffer);
+
+    /* Initialize the attributes for the SymLink */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               BNOLinksDirectory,
+                               NULL);
+
+    /* Create it */
+    Status = NtCreateSymbolicLinkObject(&BnoHandle,
+                                        SYMBOLIC_LINK_ALL_ACCESS,
+                                        &ObjectAttributes,
+                                        &BnoString);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: fatal: NtCreateSymbolicLinkObject failed (Status=0x%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Create the \DosDevices Security Descriptor */
+    CsrGetDosDevicesSd(&DosDevicesSd);
+
+    /* Now create a directory for this session */
+    swprintf(SessionBuffer, L"%ws\\%ld", SESSION_ROOT, Session);
+    RtlInitUnicodeString(&SessionString, SessionBuffer);
+
+    /* Initialize the attributes for the Directory */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               0,
+                               &DosDevicesSd);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&SessionObjectDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
+                __FUNCTION__, Status);
+        /* Release the Security Descriptor */
+        CsrFreeDosDevicesSd(&DosDevicesSd);
+        return Status;
+    }
+
+    /* Next, create a directory for this session's DOS Devices */
+    /* Now create a directory for this session */
+    RtlInitUnicodeString(&SessionString, L"DosDevices");
+
+    /* Initialize the attributes for the Directory */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &SessionString,
+                               OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+                               0,
+                               &DosDevicesSd);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&DosDevicesDirectory,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
+                __FUNCTION__, Status);
+    }
+
+    /* Release the Security Descriptor */
+    CsrFreeDosDevicesSd(&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;
+    ULONG ReturnLength;
+    PTOKEN_USER TokenUserInformation;
+    PSECURITY_DESCRIPTOR SecurityDescriptor;
+    PACL Dacl;
+
+    /* Open our token */
+    Status = NtOpenProcessToken(NtCurrentProcess(),
+                                TOKEN_QUERY,
+                                &hToken);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Get the Token User Length */
+    NtQueryInformationToken(hToken,
+                            TokenUser,
+                            NULL,
+                            0,
+                            &ReturnLength);
+
+    /* Allocate space for it */
+    TokenUserInformation = RtlAllocateHeap(CsrHeap,
+                                           HEAP_ZERO_MEMORY,
+                                           ReturnLength);
+
+    /* Now query the data */
+    Status = NtQueryInformationToken(hToken,
+                                     TokenUser,
+                                     TokenUserInformation,
+                                     ReturnLength,
+                                     &ReturnLength);
+
+    /* Close the handle */
+    NtClose(hToken);
+
+    /* Make sure that we got the data */
+    if (!NT_SUCCESS(Status))
+    {
+        /* FAil */
+        RtlFreeHeap(CsrHeap, 0, TokenUserInformation);
+        return Status;
+    }
+
+    /* Now check the SID Length */
+    ReturnLength = RtlLengthSid(TokenUserInformation->User.Sid);
+
+    /* Allocate a buffer for the Security Descriptor, with SID and DACL */
+    SecurityDescriptor = RtlAllocateHeap(CsrHeap,
+                                         HEAP_ZERO_MEMORY,
+                                         SECURITY_DESCRIPTOR_MIN_LENGTH +
+                                         sizeof(ACL) + ReturnLength +
+                                         sizeof(ACCESS_ALLOWED_ACE));
+    
+    /* Set the pointer to the DACL */
+    Dacl = (PACL)((ULONG_PTR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+    /* Now create the SD itself */
+    Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+                                         SECURITY_DESCRIPTOR_REVISION);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        RtlFreeHeap(CsrHeap, 0, TokenUserInformation);
+        return Status;
+    }
+
+    /* Create the DACL for it*/
+    RtlCreateAcl(Dacl,
+                 sizeof(ACL) + ReturnLength + sizeof(ACCESS_ALLOWED_ACE),
+                 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,
+                                    TokenUserInformation->User.Sid);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        RtlFreeHeap(CsrHeap, 0, TokenUserInformation);
+        return Status;
+    }
+
+    /* Clear the DACL in the SD */
+    Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
+                                          TRUE,
+                                          Dacl,
+                                          FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+        RtlFreeHeap(CsrHeap, 0, TokenUserInformation);
+        return Status;
+    }
+
+    /* Write the SD into the Process */
+    Status = NtSetSecurityObject(NtCurrentProcess(),
+                                 DACL_SECURITY_INFORMATION,
+                                 SecurityDescriptor);
+
+    /* Free the memory and return */
+    RtlFreeHeap(CsrHeap, 0, SecurityDescriptor);
+    RtlFreeHeap(CsrHeap, 0, TokenUserInformation);
+    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(ULONG ArgumentCount,
+                        PCHAR Arguments[])
 {
-       NTSTATUS Status = STATUS_SUCCESS;
-       LPWSTR   ParameterName = NULL;
-       LPWSTR   ParameterValue = NULL;
-
-       pItem->Type = CSRAT_UNKNOWN;
-
-       if(0 == pItem->Data.Length)
-       {
-               DPRINT1("CSRSRV:%s: (0 == Data.Length)!\n", __FUNCTION__);
-               return STATUS_INVALID_PARAMETER;
-       }
-       //--- Seek '=' to split name and value
-       ParameterName = pItem->Data.Buffer;
-       ParameterValue = wcschr (ParameterName, L'=');
-       if (NULL == ParameterValue)
-       {
-               DPRINT1("CSRSRV:%s: (NULL == ParameterValue)!\n", __FUNCTION__);
-               return STATUS_INVALID_PARAMETER;
-       }
-       *ParameterValue++ = L'\0';
-       DPRINT("Name=%S, Value=%S\n", ParameterName, ParameterValue);
-       //---
-       if(0 == wcscmp(ParameterName, L"ObjectDirectory"))
-       {
-               RtlInitUnicodeString (& pItem->Item.ObjectDirectory, ParameterValue);
-               pItem->Type = CSRAT_OBJECT_DIRECTORY;
-       }
-       else if(0 == wcscmp(ParameterName, L"SubSystemType"))
-       {
-               pItem->Type = CSRAT_SUBSYSTEM_TYPE;
-               pItem->Item.Windows = CsrpStringToBool (ParameterValue, L"Windows", L"Text");
-       }
-       else if(0 == wcscmp(ParameterName, L"MaxRequestThreads"))
-       {
-               pItem->Item.MaxRequestThreads = (USHORT) wcstoul (ParameterValue, NULL, 10);
-               pItem->Type = CSRAT_REQUEST_THREADS_MAX;
-       }
-       else if(0 == wcscmp(ParameterName, L"RequestThreads"))
-       {
-               // ROS Extension
-               pItem->Item.RequestThreads = (USHORT) wcstoul (ParameterValue, NULL, 10);
-               pItem->Type = CSRAT_REQUEST_THREADS;
-       }
-       else if(0 == wcscmp(ParameterName, L"ProfileControl"))
-       {
-               pItem->Item.ProfileControl = CsrpStringToBool (ParameterValue, L"On", L"Off");
-               pItem->Type = CSRAT_PROFILE_CONTROL;
-       }
-       else if(0 == wcscmp(ParameterName, L"SharedSection"))
-       {
-               if (0 != CsrpSplitSharedSection(ParameterValue, pItem))
-               {
-                       pItem->Type = CSRAT_SHARED_SECTION;
-               } else {
-                       pItem->Type = CSRAT_UNKNOWN;
-                       return STATUS_INVALID_PARAMETER;
-               }
-       }
-       else if(0 == wcscmp(ParameterName, L"ServerDll"))
-       {
-               if (0 != CsrpSplitServerDll(ParameterValue, pItem))
-               {
-                       pItem->Type = CSRAT_SERVER_DLL;
-               } else {
-                       pItem->Type = CSRAT_UNKNOWN;
-                       return STATUS_INVALID_PARAMETER;
-               }
-       }
-       else if(0 == wcscmp(ParameterName, L"Windows"))
-       {
-               pItem->Item.Windows = CsrpStringToBool (ParameterValue, L"On", L"Off");
-               pItem->Type = CSRAT_WINDOWS;
-       }
-       else if(0 == wcscmp(ParameterName, L"Sessions"))
-       {
-               // ROS Extension
-               pItem->Item.Sessions = CsrpStringToBool (ParameterValue, L"On", L"Off");
-               pItem->Type = CSRAT_SESSIONS;
-       }
-       else
-       {
-               DPRINT1("CSRSRV:%s: unknown parameter '%S'!\n", __FUNCTION__, ParameterName);
-               pItem->Type = CSRAT_UNKNOWN;
-               Status = STATUS_INVALID_PARAMETER;
+    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);
+
+    /* Cache System Basic Information so we don't always request it */
+    Status = NtQuerySystemInformation(SystemBasicInformation,
+                                      &CsrNtSysInfo,
+                                      sizeof(SYSTEM_BASIC_INFORMATION),
+                                      NULL);
+
+    /* Save our Heap */
+    CsrHeap = RtlGetProcessHeap();
+
+    /* Set our Security Descriptor to protect the process */
+    CsrSetProcessSecurity();
+
+    /* Set up Session Support */
+    Status = CsrInitializeNtSessions();
+    if(!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrInitializeSessions failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Set up Process Support */
+    Status = CsrInitializeProcesses();
+    if(!NT_SUCCESS(Status))
+    {
+        DPRINT1("CSRSRV:%s: CsrInitializeProcesses failed (Status=%08lx)\n",
+                __FUNCTION__, Status);
+        return Status;
+    }
+
+    /* Parse the command line */
+    CsrpParseCommandLine(ArgumentCount, Arguments);
+
+    /* All Server DLLs are now loaded, allocate a heap for the Root Process */
+    ProcessData = RtlAllocateHeap(CsrHeap,
+                                  HEAP_ZERO_MEMORY,
+                                  CsrTotalPerProcessDataLength);
+
+    /*
+     * 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);
         }
-       return Status;
+        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 */
+    NtSetEvent(CsrInitializationEvent, NULL);
+    NtClose(CsrInitializationEvent);
+
+    /* Have us handle Hard Errors */
+    NtSetDefaultHardErrorPort(CsrApiPort);
+    
+    /* Return status */
+    return Status;
 }
-/**********************************************************************
- * CsrServerInitialization/2
+
+/*++
+ * @name CsrPopulateDosDevices
+ * @implemented NT5.1
  *
- * DESCRIPTION
- *     Every environment subsystem implicitly starts where this 
- *     routines stops. This routine is called by CSR on startup
- *     and then it calls the entry points in the following server
- *     DLLs, as per command line.
+ * The CsrPopulateDosDevices routine uses the DOS Device Map from the Kernel
+ * to populate the Dos Devices Object Directory for the session.
  *
- * ARGUMENTS
- *     ArgumentCount:
- *     Argument:
+ * @param None.
  *
- * RETURN VALUE
- *     STATUS_SUCCESS if it succeeds. Otherwise a status code.
+ * @return None.
  *
- * NOTE
- *     This is the only function explicitly called by csr.exe.
- */
-NTSTATUS STDCALL CsrServerInitialization (ULONG ArgumentCount,
-                                         LPWSTR *Argument)
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrPopulateDosDevices(VOID)
 {
-       NTSTATUS           Status = STATUS_SUCCESS;
-       ULONG              ArgumentIndex = 0;
-       CSR_ARGUMENT_ITEM  ArgumentItem = {CSRAT_UNKNOWN,};
-
-       // get registry bootstrap options
-       for (ArgumentIndex = 0; ArgumentIndex < ArgumentCount; ArgumentIndex++)
-       {
-               RtlInitUnicodeString (& ArgumentItem.Data, Argument[ArgumentIndex]);
-               Status = CsrpParseArgumentItem (& ArgumentItem);
-               if (NT_SUCCESS(Status))
-               {
-                       switch (ArgumentItem.Type)
-                       {
-                       case CSRAT_UNKNOWN:
-                               // ignore unknown parameters
-                               DPRINT1("CSRSRV: ignoring param '%s'\n", Argument[ArgumentIndex]);
-                               break;
-                       case CSRAT_OBJECT_DIRECTORY:
-                               RtlDuplicateUnicodeString (1, & ArgumentItem.Item.ObjectDirectory, & CsrSrvOption.NameSpace.Root);
-                               DPRINT("ObjectDirectory: '%S'\n", CsrSrvOption.NameSpace.Root.Buffer);
-                               break;
-                       case CSRAT_SUBSYSTEM_TYPE:
-                               CsrSrvOption.SubSystemType = ArgumentItem.Item.SubSystemType;
-                               DPRINT("SubSystemType: %u\n", CsrSrvOption.SubSystemType);
-                               break;
-                       case CSRAT_REQUEST_THREADS:
-                               CsrSrvOption.Threads.RequestCount = ArgumentItem.Item.RequestThreads;
-                               DPRINT("RequestThreads: %u\n", CsrSrvOption.Threads.RequestCount);
-                               break;
-                       case CSRAT_REQUEST_THREADS_MAX:
-                               CsrSrvOption.Threads.MaxRequestCount = ArgumentItem.Item.MaxRequestThreads;
-                               DPRINT("MaxRequestThreads: %u\n", CsrSrvOption.Threads.MaxRequestCount);
-                               break;
-                       case CSRAT_PROFILE_CONTROL:
-                               CsrSrvOption.Flag.ProfileControl = ArgumentItem.Item.ProfileControl;
-                               DPRINT("ProfileControl: %u \n", CsrSrvOption.Flag.ProfileControl);
-                               break;
-                       case CSRAT_SHARED_SECTION:
-                               CsrSrvOption.PortSharedSectionSize              = ArgumentItem.Item.SharedSection.PortSectionSize;
-                               CsrSrvOption.Heap.InteractiveDesktopHeapSize    = ArgumentItem.Item.SharedSection.InteractiveDesktopHeapSize;
-                               CsrSrvOption.Heap.NonInteractiveDesktopHeapSize = ArgumentItem.Item.SharedSection.NonInteractiveDesktopHeapSize;
-                               DPRINT("SharedSection: %u-%u-%u\n",
-                                               CsrSrvOption.PortSharedSectionSize,
-                                               CsrSrvOption.Heap.InteractiveDesktopHeapSize,
-                                               CsrSrvOption.Heap.NonInteractiveDesktopHeapSize);
-                               break;
-                       case CSRAT_SERVER_DLL:
-                               Status = CsrSrvRegisterServerDll (& ArgumentItem.Item.ServerDll);
-                               if(!NT_SUCCESS(Status))
-                               {
-                                       DPRINT1("CSRSRV: CsrSrvRegisterServerDll(%S) failed!\n",
-                                               Argument[ArgumentIndex]);
-                               } else {
-                                       DPRINT("ServerDll: DLL='%S' Entrypoint='%S' ID=%u\n",
-                                               ArgumentItem.Item.ServerDll.DllName.Buffer,
-                                               ArgumentItem.Item.ServerDll.DllEntryPoint.Buffer,
-                                               ArgumentItem.Item.ServerDll.ServerIndex);
-                               }
-                               break;
-                       case CSRAT_WINDOWS:
-                               CsrSrvOption.Flag.Windows = ArgumentItem.Item.Windows;
-                               DPRINT("Windows: %d\n", CsrSrvOption.Flag.Windows);
-                               break;
-                       case CSRAT_SESSIONS:
-                               CsrSrvOption.Flag.Sessions = ArgumentItem.Item.Sessions;
-                               DPRINT("Sessions: %d\n", CsrSrvOption.Flag.Sessions);
-                               break;
-                       default:
-                               DPRINT("CSRSRV: unknown ArgumentItem->Type=%ld!\n", ArgumentItem.Type);
-                       }
-               } else {
-                       DPRINT1("CSRSRV:%s: CsrpParseArgumentItem(%S) failed with Status = %08lx\n",
-                                       __FUNCTION__, Argument[ArgumentIndex], Status);
-               }
-       }
-       // TODO: verify required 
-       Status = CsrSrvBootstrap ();
-       return Status;
+    NTSTATUS Status;
+    PROCESS_DEVICEMAP_INFORMATION OldDeviceMap;
+    PROCESS_DEVICEMAP_INFORMATION NewDeviceMap;
+
+    /* Query the Device Map */
+    Status = NtQueryInformationProcess(NtCurrentProcess(),
+                                       ProcessDeviceMap,
+                                       &OldDeviceMap.Query,
+                                       sizeof(PROCESS_DEVICEMAP_INFORMATION),
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return;
+
+    /* Set the new one */
+    NewDeviceMap.Set.DirectoryHandle = DosDevicesDirectory;
+    Status = NtSetInformationProcess(NtCurrentProcess(),
+                                     ProcessDeviceMap,
+                                     &NewDeviceMap,
+                                     sizeof(ULONG));
+    if (!NT_SUCCESS(Status)) return;
+
+    /* Populate the Directory */
+    CsrPopulateDosDevicesDirectory(DosDevicesDirectory, &OldDeviceMap);
 }
+
+BOOL
+NTAPI
+DllMain(HANDLE hDll,
+        DWORD dwReason,
+        LPVOID lpReserved)
+{
+    /* We don't do much */
+    return TRUE;
+}
+
 /* EOF */
index 2ff3413..c6e4069 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/process.c - CSR server - process management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/process.c
+ * PURPOSE:         CSR Server DLL Process Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
+
+/* INCLUDES ******************************************************************/
+
 #include "srv.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
-/* LOCALS */
+/* DATA **********************************************************************/
+
+PCSR_PROCESS CsrRootProcess = NULL;
+RTL_CRITICAL_SECTION CsrProcessLock;
+ULONG CsrProcessSequenceCount = 5;
+ULONG CsrTotalPerProcessDataLength;
 
-struct {
-       RTL_CRITICAL_SECTION Lock;
-} Process;
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @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;
 
-NTSTATUS STDCALL CsrSrvInitializeProcess (VOID)
+    /* Handle the Sequence Number */
+    CsrProcess->SequenceNumber = CsrProcessSequenceCount++;
+
+    /* Increase the reference count */
+    CsrProcess->ReferenceCount++;
+
+    /* Initialize the Thread List */
+    InitializeListHead(&CsrProcess->ThreadList);
+
+    /* Return the Process */
+    return CsrProcess;
+}
+
+/*++
+ * @name CsrServerInitialization
+ * @implemented NT4
+ *
+ * The CsrInitializeProcesses 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
+CsrInitializeProcesses(VOID)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
+    NTSTATUS Status;
+    ULONG i;
+
+    /* Initialize the Lock */
+    Status = RtlInitializeCriticalSection(&CsrProcessLock);
+
+    /* Set up the Root Process */
+    CsrRootProcess = CsrAllocateProcess();
+    if (!CsrRootProcess) return STATUS_NO_MEMORY;
 
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       Status = RtlInitializeCriticalSection (& Process.Lock);
-       if(NT_SUCCESS(Status))
-       {
-               // more process management initialization
-       }
-       return Status;
+    /* Set up the minimal information for it */
+    InitializeListHead(&CsrRootProcess->ListLink);
+    CsrRootProcess->ProcessHandle = (HANDLE)-1;
+    CsrRootProcess->ClientId = NtCurrentTeb()->Cid;
+
+    /* Initialize the Thread Hash List */
+    for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]);
+
+    /* Initialize the Wait Lock */
+    Status = RtlInitializeCriticalSection(&CsrWaitListsLock);
+    return Status;
 }
 
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
+/*++
+ * @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);
+}
 
-NTSTATUS STDCALL CsrCreateProcess (PCSR_SESSION pCsrSession, PCSR_PROCESS * ppCsrProcess)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_SUCCESS;
-       PCSR_PROCESS pCsrProcess = NULL;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+    PCSR_SERVER_DLL ServerDll;
+    ULONG i;
+
+    /* Set the parent */
+    CsrProcess->Parent = Parent;
 
-       pCsrProcess = RtlAllocateHeap (pCsrSession->Heap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof (CSR_PROCESS));
-       if (NULL == pCsrProcess)
-       {
-               Status = STATUS_NO_MEMORY;
-       } else {
-               pCsrProcess->NtSession = pCsrSession;
-               if (NULL != ppCsrProcess)
-               {
-                       *ppCsrProcess = pCsrProcess;
-               }
-       }
-       return Status;
+    /* 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);
+        }
+    }
 }
 
-NTSTATUS STDCALL CsrDereferenceProcess (PCSR_PROCESS pCsrProcess)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* Decrease reference count */
+    if (!(--CsrProcess->ReferenceCount))
+    {
+        /* Call the generic cleanup code */
+        CsrAcquireProcessLock();
+        CsrProcessRefcountZero(CsrProcess);
+    }
 }
 
-NTSTATUS STDCALL CsrDestroyProcess (PCSR_PROCESS pCsrProcess)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    PCSR_SERVER_DLL ServerDll;
+    ULONG i;
+
+    /* 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);
+        }
+    }
 }
 
-NTSTATUS STDCALL CsrGetProcessLuid (PCSR_PROCESS pCsrProcess, PLUID pLuid)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* 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);
 }
 
-NTSTATUS STDCALL CsrLockProcessByClientId ()
+/*++
+ * @name CsrSetToNormalPriority
+ *
+ * The CsrSetToNormalPriority 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
+CsrSetToNormalPriority(VOID)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    KPRIORITY BasePriority = (8 + 1) + 4;
+
+    /* Set the Priority */
+    NtSetInformationProcess(NtCurrentProcess(),
+                            ProcessBasePriority,
+                            &BasePriority,
+                            sizeof(KPRIORITY));
 }
 
-NTSTATUS STDCALL CsrShutdownProcesses (PCSR_SESSION pCsrSession OPTIONAL)
+/*++
+ * @name CsrSetToShutdownPriority
+ *
+ * The CsrSetToShutdownPriority routine sets the current NT Process'
+ * priority to the boosted priority for CSR Processes doing shutdown.
+ * Additonally, it acquires the Shutdown Privilege required for shutdown.
+ *
+ * @param None.
+ *
+ * @return None.
+ *
+ * @remarks The "Shutdown" Priority corresponds to the Normal Forground
+ *          Priority (9) plus a boost of 6.
+ *
+ *--*/
+VOID
+NTAPI
+CsrSetToShutdownPriority(VOID)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+    KPRIORITY SetBasePriority = (8 + 1) + 6;
+    BOOLEAN Old;
 
-       if (NULL == pCsrSession)
-       {
-               // TODO: shutdown every session
-       } else {
-               // TODO: shutdown every process in pCsrSession
-       }
-       return Status;
+    /* Get the shutdown privilege */
+    if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
+                                      TRUE,
+                                      FALSE,
+                                      &Old)))
+    {
+        /* Set the Priority */
+        NtSetInformationProcess(NtCurrentProcess(),
+                                ProcessBasePriority,
+                                &SetBasePriority,
+                                sizeof(KPRIORITY));
+    }
 }
 
-NTSTATUS STDCALL CsrUnlockProcess (PCSR_PROCESS pCsrProcess)
+/*++
+ * @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(PLUID CallerLuid)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    PLIST_ENTRY ListHead, NextEntry;
+    LUID ProcessLuid;
+    NTSTATUS Status;
+    LUID SystemLuid = SYSTEM_LUID;
+    PCSR_PROCESS CsrProcess;
+    PCSR_THREAD CsrThread;
+    BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE;
+    PCSR_PROCESS ReturnCsrProcess = NULL;
+    ULONG Level = 0;
+
+    /* Set the List Pointers */
+    ListHead = &CsrRootProcess->ListLink;
+    NextEntry = ListHead->Flink;
+
+    /* Start looping */
+    while (NextEntry != ListHead)
+    {
+        /* 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 ((IsSystemLuid = RtlEqualLuid(&ProcessLuid, &SystemLuid)))
+        {
+            /* Mark this process */
+            CsrProcess->ShutdownFlags |= CsrShutdownSystem;
+        }
+        else if (!(IsOurLuid = 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)
+        {
+            /* 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 */
+    if (!(CsrProcess = CsrAllocateProcess()))
+    {
+        /* Couldn't allocate Process */
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Setup Process Data */
+    CsrProcess->ClientId = *ClientId;
+    CsrProcess->ProcessHandle = hProcess;
+    CsrProcess->ShutdownLevel = 0x280;
+
+    /* Inherit the Process Data */
+    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);
+
+    /* 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))
+    {
+        /* Save the debug flag used */
+        CsrProcess->DebugFlags = Flags;
+
+        /* Save the CID */
+        if (DebugCid) 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));
+        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);
+
+    /* Allocate a CSR Thread Structure */
+    CsrThread = CsrAllocateThread(CsrProcess);
+    if (CsrThread == NULL)
+    {
+        /* Failed */
+        CsrDeallocateProcess(CsrProcess);
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Save the data we have */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = *ClientId;
+    CsrThread->ThreadHandle = hThread;
+    CsrThread->Flags = 0;
+
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Reference the session */
+    CsrReferenceNtSession(NtSession);
+    CsrProcess->NtSession = NtSession;
+
+    /* 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(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(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(PCSR_PROCESS CsrProcess)
+{
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Decrease reference count */
+    if (!(--CsrProcess->ReferenceCount))
+    {
+        /* 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 ListHead, 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 */
+    ListHead = &CsrProcess->ThreadList;
+    NextEntry = ListHead->Flink;
+
+    /* Loop the list */
+    while (NextEntry != ListHead)
+    {
+        /* Get the current thread entry */
+        CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Make sure the thread isn't already dead */
+        if (CsrThread->Flags & CsrThreadTerminated) 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);
+    }
+
+    /* 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))
+        {
+            /* Still no token, return the error */
+            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 */
+    if (!(TokenStats = RtlAllocateHeap(CsrHeap, 0, Length)))
+    {
+        /* 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 */
+    if (NT_SUCCESS(Status))
+    {
+        /* Return the LUID */
+        *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 OPTIONAL)
+{
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_PROCESS CurrentProcess = NULL;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+    /* Acquire the lock */
+    CsrAcquireProcessLock();
+
+    /* Setup the List Pointers */
+    ListHead = &CsrRootProcess->ListLink;
+    NextEntry = ListHead;
+
+    /* Start Loop */
+    while (NextEntry != ListHead)
+    {
+        /* Get the Process */
+        CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
+
+        /* Check for PID Match */
+        if (CurrentProcess->ClientId.UniqueProcess == Pid)
+        {
+            /* Get out of here with success */
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Did the loop find something? */
+    if (NT_SUCCESS(Status))
+    {
+        /* Lock the found process */
+        CurrentProcess->ReferenceCount++;
+    }
+    else
+    {
+        /* Nothing found, release the lock */
+        CsrReleaseProcessLock();
+    }
+
+    /* Return the status and process */
+    if (CsrProcess) *CsrProcess = CurrentProcess;
+    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(PLUID CallerLuid,
+                     ULONG Flags)
+{
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_PROCESS CsrProcess;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    BOOLEAN FirstTry = TRUE;
+    ULONG i;
+    PCSR_SERVER_DLL ServerDll;
+    ULONG Result;
+
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Add shutdown flag */
+    CsrRootProcess->ShutdownFlags |= CsrShutdownSystem;
+
+    /* Get the list pointers */
+    ListHead = &CsrRootProcess->ListLink;
+    NextEntry = ListHead->Flink;
+
+    /* Start the loop */
+    while (NextEntry != ListHead)
+    {
+        /* 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 */
+    CsrSetToShutdownPriority();
+
+    /* Start looping */
+    while (TRUE)
+    {
+        /* Find the next process to shutdown */
+        if (!(CsrProcess = FindProcessForShutdown(CallerLuid)))
+        {
+            /* Done, quit */
+            CsrReleaseProcessLock();
+            Status = STATUS_SUCCESS;
+            goto Quickie;
+         }
+
+        /* Increase reference to process */
+        CsrProcess->ReferenceCount++;
+
+LoopAgain:
+        /* 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 == CsrShutdownNonCsrProcess)
+                {
+                    /* A non-CSR process, the callback didn't touch it */
+                    continue;
+                }
+                else if (Result == CsrShutdownCancelled)
+                {
+                    /* 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;
+            goto LoopAgain;
+        }
+
+        /* We've reached the final loop here, so dereference */
+        if (i == CSR_SERVER_DLL_MAX) CsrLockedDereferenceProcess(CsrProcess);
+    }
+
+Quickie:
+    /* Return to normal priority */
+    CsrSetToNormalPriority();
+    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(PCSR_PROCESS CsrProcess)
+{
+    /* Dereference the process */
+    CsrLockedDereferenceProcess(CsrProcess);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
 /* EOF */
index 0b66dd5..883de7c 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/server.c - CSR server - subsystem default server
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/server.c
+ * PURPOSE:         CSR Server DLL Server Functions
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
+
+/* INCLUDES ******************************************************************/
 #include "srv.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
-typedef NTSTATUS (STDCALL * CSR_SERVER_DLL_INIT_PROC)(ULONG,LPWSTR*);
+/* DATA **********************************************************************/
 
-typedef struct _CSRSRV_SERVER_DLL
+PCSR_API_ROUTINE CsrServerApiDispatchTable[5] =
 {
-       USHORT             ServerIndex;
-       USHORT             Sequence;            // initialization order
-       UNICODE_STRING     DllName;
-       UNICODE_STRING     DllEntryPoint;
-       CSR_SERVER_THREAD  ServerThread;        // NULL ==> inactive
-
-} CSRSRV_SERVER_DLL, *PCSRSRV_SERVER_DLL;
-
-/*=====================================================================
- *     GLOBALS
- *===================================================================*/
-
-CSRSRV_OPTION CsrSrvOption;
-
-HANDLE CsrSrvApiPortHandle = (HANDLE) 0;
-
-/*=====================================================================
- *     LOCALS
- *===================================================================*/
-
-static HANDLE CsrSrvSbApiPortHandle = (HANDLE) 0;
-
-static CSRSRV_SERVER_DLL ServerThread [CSR_SERVER_DLL_MAX];
-
-VOID CALLBACK CsrSrvServerThread (PVOID);
-
-/**********************************************************************
- * CsrSrvRegisterServerDll/1
- */
-NTSTATUS STDCALL CsrSrvRegisterServerDll (PCSR_SERVER_DLL pServerDll)
+    CsrSrvClientConnect,
+    CsrSrvUnusedFunction,
+    CsrSrvUnusedFunction,
+    CsrSrvIdentifyAlertableThread,
+    CsrSrvSetPriorityClass
+};
+
+BOOLEAN CsrServerApiServerValidTable[5] =
 {
-       static USHORT  NextInSequence = 0;
-       USHORT         ServerIndex = 0;
-
-       // 1st call?
-       if (0 == NextInSequence)
-       {
-               RtlZeroMemory (ServerThread, sizeof ServerThread);
-       }
-       // We can not register more than CSR_SERVER_DLL_MAX servers.
-       // Note: # servers >= # DLLs (MS Win32 has 3 servers in 2 DLLs).
-       if (NextInSequence >= CSR_SERVER_DLL_MAX)
-       {
-               return STATUS_NO_MEMORY;
-       }
-       // Validate the ServerIndex from the command line:
-       // it may be 0, 1, 2, or 3.
-       ServerIndex = pServerDll->ServerIndex;
-       if (ServerIndex >= CSR_SERVER_DLL_MAX)
-       {
-               return STATUS_INVALID_PARAMETER;
-       }
-       // Register the DLL server.
-       ServerThread [ServerIndex].ServerIndex = ServerIndex;
-       ServerThread [ServerIndex].Sequence = NextInSequence ++;
-       if (0 != ServerIndex)
-       {
-               RtlDuplicateUnicodeString (1, & pServerDll->DllName,       & ServerThread [ServerIndex].DllName);
-               RtlDuplicateUnicodeString (1, & pServerDll->DllEntryPoint, & ServerThread [ServerIndex].DllEntryPoint);
-       } else {
-               // CSRSRV.DLL own static server thread
-               ServerThread [ServerIndex].ServerThread = CsrSrvServerThread;
-       }
-       return STATUS_SUCCESS;
-}
-/**********************************************************************
- * CsrSrvInitializeServerDll/1                                 PRIVATE
- *
- * NOTE
- *     Code dapted from CsrpInitWin32Csr.
- */
-static NTSTATUS CsrSrvInitializeServerDll (USHORT ServerIndex)
-{
-       NTSTATUS                  Status = STATUS_SUCCESS;
-       HINSTANCE                 hInst;
-       ANSI_STRING               ProcName;
-       CSR_SERVER_DLL_INIT_PROC  InitProc;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-
-       Status = LdrLoadDll (NULL, 0, & ServerThread[ServerIndex].DllName, (PVOID *) &hInst);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV:%s: loading ServerDll '%S' failed (Status=%08lx)\n",
-                       __FUNCTION__, ServerThread[ServerIndex].DllName.Buffer, Status);
-               return Status;
-       }
-       RtlInitAnsiString (& ProcName, "ServerDllInitialization");
-       Status = LdrGetProcedureAddress(hInst, &ProcName, 0, (PVOID *) &InitProc);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV:%s: ServerDll '%S!%s' not found (Status=%08lx)\n",
-                       __FUNCTION__,
-                       ServerThread[ServerIndex].DllName.Buffer,
-                       "ServerDllInitialization",
-                       Status);
-               return Status;
-       }
-       Status = InitProc (0, NULL);
-       if (!NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV:%s: %S.%s failed with Status=%08lx\n",
-                       __FUNCTION__,
-                       ServerThread[ServerIndex].DllName.Buffer,
-                       "ServerDllInitialization",
-                       Status);
-       }
-       return Status;
-}
-
-/**********************************************************************
- * CsrpCreateObjectDirectory/1                                 PRIVATE
- */
-NTSTATUS STDCALL CsrpCreateObjectDirectory (PUNICODE_STRING pObjectDirectory)
+    TRUE,
+    FALSE,
+    TRUE,
+    TRUE,
+    TRUE
+};
+
+PCHAR CsrServerApiNameTable[5] =
 {
-       NTSTATUS           Status = STATUS_SUCCESS;
-       OBJECT_ATTRIBUTES  DirectoryAttributes;
-
-       DPRINT("CSRSRV:%s(%S) called\n", __FUNCTION__, pObjectDirectory->Buffer);
-
-       InitializeObjectAttributes (& DirectoryAttributes,
-                                   pObjectDirectory,
-                                   OBJ_OPENIF,
-                                   NULL,
-                                   NULL);
-
-       Status = NtCreateDirectoryObject (& CsrSrvOption.NameSpace.RootHandle,
-                                         (DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY),
-                                         & DirectoryAttributes);
-       if (NT_SUCCESS(Status))
-       {
-               Status = RtlDuplicateUnicodeString (0, pObjectDirectory, & CsrSrvOption.NameSpace.Root);
-               if (!NT_SUCCESS(Status))
-               {
-                       DPRINT1("CSRSRV:%s: RtlDuplicateUnicodeString failed (Status=0x%08lx)\n",
-                               __FUNCTION__, Status);
-               }
-       } else {
-               DPRINT1("CSRSRV:%s: fatal: NtCreateDirectoryObject failed (Status=0x%08lx)\n",
-                               __FUNCTION__, Status);
-       }       
-       return Status;
-}
-/**********************************************************************
- * CsrSrvBootstrap/0
+    "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
  *
- * DESCRIPTION
- *     This is where a subsystem begins living.
- */
-NTSTATUS STDCALL CsrSrvBootstrap (VOID)
-{
-       NTSTATUS Status = STATUS_SUCCESS;
-       ULONG    ServerIndex = 0;
-       ULONG    ServerSequence = 0;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-
-       CsrSrvSbApiPortHandle = CsrSrvSbApiPortHandle; //FIXME
-       
-       // OBJECT DIRECTORY
-       Status = CsrpCreateObjectDirectory (& CsrSrvOption.NameSpace.Root);
-       if(!NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV:%s: CsrpCreateObjectDirectory failed (Status=%08lx)\n",
-                       __FUNCTION__, Status);
-               return Status;
-       }
-       // SESSIONS
-       Status = CsrSrvInitializeSession ();
-       if(!NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV:%s: CsrSrvInitializeSession failed (Status=%08lx)\n",
-                       __FUNCTION__, Status);
-               return Status;
-       }
-       // PROCESSES
-       // TODO
-       // THREADS
-       // TODO
-       // WAITS
-       // TODO
-       // Hosted servers
-       for (ServerSequence = 0; ServerSequence < CSR_SERVER_DLL_MAX; ServerSequence ++)
-       {
-               for (ServerIndex = 0; (ServerIndex < CSR_SERVER_DLL_MAX); ++ ServerIndex)
-               {
-                       if (ServerSequence == ServerThread [ServerIndex].Sequence)
-                       {
-                               if (NULL == ServerThread [ServerIndex].ServerThread)
-                               {
-                                       Status = CsrSrvInitializeServerDll (ServerIndex);
-                                       if (!NT_SUCCESS(Status))
-                                       {
-                                               DPRINT1("CSRSRV:%s: server thread #%d init failed!\n",
-                                                       __FUNCTION__, ServerIndex);
-                                       }
-                               } else {
-                                       DPRINT1("CSRSRV:%s: server thread #%d initialized more than once!\n",
-                                               __FUNCTION__, ServerIndex);
-                               }
-                       }
-               }
-       }
-       return Status;
-}
-/**********************************************************************
- * CsrSrvServerThread/1
+ * The CsrLoadServerDll routine loads a CSR Server DLL and calls its entrypoint
  *
- * DESCRIPTION
- *     This is actually a function called by the CsrSrvMainServerThread
- *     when the server index is 0. Other server DLLs register their
- *     function with CsrAddStaticServerThread.
- */
-VOID STDCALL CsrSrvServerThread (PVOID x)
+ * @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 = STATUS_SUCCESS;
-       PPORT_MESSAGE  Request = (PPORT_MESSAGE) x;
-       PPORT_MESSAGE  Reply = NULL;
-       ULONG          MessageType = 0;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-
-       MessageType = Request->u2.s2.Type;
-       DPRINT("CSRSRV: %s received a message (Type=%d)\n",
-               __FUNCTION__, MessageType);
-       switch (MessageType)
-       {
-               //TODO
-               default:
-                       Reply = Request;
-                       Status = NtReplyPort (CsrSrvApiPortHandle, Reply);
-                       break;
-       }
+    NTSTATUS Status;
+    ANSI_STRING DllName;
+    UNICODE_STRING TempString;
+    HANDLE hServerDll = NULL;
+    ULONG Size;
+    PCSR_SERVER_DLL ServerDll;
+    STRING EntryPointString;
+    PCSR_SERVER_DLL_INIT_CALLBACK ServerDllInitProcedure;
+
+    /* 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 */
+    RtlInitAnsiString(&DllName, DllString);
+    Status = RtlAnsiStringToUnicodeString(&TempString, &DllName, TRUE);
+
+    /* If we are loading ourselves, don't actually load us */
+    if (ServerId != CSR_SRV_SERVER)
+    {
+        /* Load the DLL */
+        Status = LdrLoadDll(NULL, 0, &TempString, &hServerDll);
+
+        /* 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;
+    if (!(ServerDll = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Size)))
+    {
+        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;
 }
 
-/**********************************************************************
- *     PUBLIC API
- *********************************************************************/
-
-/**********************************************************************
- * CsrAddStaticServerThread/1
- */
-NTSTATUS STDCALL CsrAddStaticServerThread (CSR_SERVER_THREAD ServerThread)
+/*++
+ * @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)
 {
-       static ULONG StaticServerThreadCount = 0;
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, ServerThread);
-
-       if (StaticServerThreadCount > CSR_SERVER_DLL_MAX)
-       {
-               DPRINT1("CSRSRV: subsystem tries to add mode than %d static threads!\n",
-                       CSR_SERVER_DLL_MAX);
-               return STATUS_NO_MEMORY;
-       }
-       if (NT_SUCCESS(Status))
-       {
-               // FIXME: do we need to make it reentrant?
-               ++ StaticServerThreadCount;
-       }
-       return Status;
+    /* 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;
 }
 
-/**********************************************************************
- * CsrCallServerFromServer
- */
-NTSTATUS STDCALL CsrCallServerFromServer ()
+/*++
+ * @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 = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    NTSTATUS Status;
+    PCSR_CLIENT_CONNECT ClientConnect;
+    PCSR_SERVER_DLL ServerDll;
+
+    /* 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)(((PCSR_THREAD)NtCurrentTeb()->CsrClientThread)->Process,
+                                              ClientConnect->ConnectionInfo,
+                                              &ClientConnect->ConnectionInfoSize);
+    }
+    else
+    {
+        /* Assume success */
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Return status */
+    return Status;
 }
 
-/**********************************************************************
- * CsrExecServerThread
- */
-NTSTATUS STDCALL CsrExecServerThread ()
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    PCHAR SizeValue = ParameterValue;
+    ULONG Size;
+    NTSTATUS Status;
+    LARGE_INTEGER SectionSize;
+    ULONG ViewSize = 0;
+    PPEB Peb = NtCurrentPeb();
+
+    /* Find the first comma, and null terminate */
+    while (*SizeValue)
+    {
+        if (*SizeValue == ',')
+        {
+            *SizeValue++ = '\0';
+            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,
+                        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));
+
+    /* Write the values to the PEB */
+    Peb->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
+    Peb->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
+    Peb->ReadOnlyStaticServerData = CsrSrvSharedStaticServerData;
+
+    /* Return */
+    return STATUS_SUCCESS;
 }
 
-/**********************************************************************
- * CsrImpersonateClient
- */
-NTSTATUS STDCALL CsrImpersonateClient ()
+/*++
+ * @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 = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    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;
 }
 
-/**********************************************************************
- * CsrQueryApiPort/0
+/*++
+ * @name CsrSrvIdentifyAlertableThread
+ * @implemented NT4
  *
- * @implemented
- */
-HANDLE STDCALL CsrQueryApiPort (VOID)
+ * 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)
 {
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return CsrSrvApiPortHandle;
-}
+    PCSR_THREAD CsrThread = NtCurrentTeb()->CsrClientThread;
 
-/**********************************************************************
- * CsrRevertToSelf
- */
-NTSTATUS STDCALL CsrRevertToSelf ()
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
-}
+    /* Set the alertable flag */
+    CsrThread->Flags |= CsrThreadAltertable;
 
-/**********************************************************************
- * CsrSetBackgroundPriority
- */
-NTSTATUS STDCALL CsrSetBackgroundPriority ()
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* Return success */
+    return STATUS_SUCCESS;
 }
 
-/**********************************************************************
- * CsrSetCallingSpooler
- */
-NTSTATUS STDCALL CsrSetCallingSpooler ()
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* Deprecated */
+    return STATUS_SUCCESS;
 }
 
-/**********************************************************************
- * CsrSetForegroundPriority
- */
-NTSTATUS STDCALL CsrSetForegroundPriority ()
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* Deprecated */
+    return STATUS_INVALID_PARAMETER;
 }
 
-/**********************************************************************
- * CsrUnhandledExceptionFilter
- */
-NTSTATUS STDCALL CsrUnhandledExceptionFilter ()
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
-}
+/* PUBLIC FUNCTIONS***********************************************************/
 
-/**********************************************************************
- * CsrValidateMessageBuffer
- */
-NTSTATUS STDCALL CsrValidateMessageBuffer ()
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    /* Deprecated */
+    return;
 }
 
-/**********************************************************************
- * CsrValidateMessageString
- */
-NTSTATUS STDCALL CsrValidateMessageString ()
+/*++
+ * @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.
+ *
+ *--*/
+_SEH_FILTER(CsrUnhandledExceptionFilter)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       return Status;
+    struct _EXCEPTION_POINTERS *ExceptionInfo = _SEH_GetExceptionPointers();
+    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] = PtrToUlong(&ErrorSource);
+            ErrorParameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
+            ErrorParameters[2] = PtrToUlong(ExceptionInfo->ExceptionRecord->ExceptionAddress);
+            ErrorParameters[3] = PtrToUlong(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 */
index 59c4eae..5f06e61 100644 (file)
-/* $Id$
+/*
+ * 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,
+    CsrSbForeignSessionComplete,
+    CsrSbForeignSessionComplete,
+    CsrSbCreateProcess,
+    NULL
+};
+
+PCHAR CsrServerSbApiName[5] =
+{
+    "SbCreateSession",
+    "SbTerminateSEssion",
+    "SbForeignSessionComplete",
+    "SbCreateProcess",
+    "Unknown Csr Sb Api Number"
+};
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrInitializeNtSessions
  *
- * subsys/csr/csrsrv/session.c - CSR server - session management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
+ * The CsrInitializeNtSessions routine sets up support for CSR Sessions.
  *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
+ * @param None
  *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
  *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
+ * @remarks None.
  *
- * --------------------------------------------------------------------
- */
-#include "srv.h"
+ *--*/
+NTSTATUS
+NTAPI
+CsrInitializeNtSessions(VOID)
+{
+    NTSTATUS Status;
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
 
-//#define NDEBUG
-#include <debug.h>
+    /* Initialize the Session List */
+    InitializeListHead(&CsrNtSessionList);
 
-//TODO: when CsrSrvSessionsFlag is FALSE, create just one session and
-//TODO: fail for more sessions requests.
+    /* Initialize the Session Lock */
+    Status = RtlInitializeCriticalSection(&CsrNtSessionLock);
+    return Status;
+}
 
-/* LOCALS */
+/*++
+ * @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(ULONG SessionId)
+{
+    PCSR_NT_SESSION NtSession;
 
-struct {
-       RTL_CRITICAL_SECTION Lock;
-       HANDLE Heap;
-       ULONG LastUnusedId;
-} Session;
+    /* Allocate an NT Session Object */
+    NtSession = RtlAllocateHeap(CsrHeap,
+                                0,
+                                sizeof(CSR_NT_SESSION));
 
+    /* Setup the Session Object */
+    if (NtSession)
+    {
+        NtSession->SessionId = SessionId;
+        NtSession->ReferenceCount = 1;
 
+        /* Insert it into the Session List */
+        CsrAcquireNtSessionLock();
+        InsertHeadList(&CsrNtSessionList, &NtSession->SessionList);
+        CsrReleaseNtSessionLock();
+    }
 
-NTSTATUS STDCALL CsrSrvInitializeSession (VOID)
-{
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       Status = RtlInitializeCriticalSection (& Session.Lock);
-       if (NT_SUCCESS(Status))
-       {
-               Session.Heap = RtlCreateHeap (HEAP_GROWABLE,
-                                               NULL,
-                                               65536,
-                                               65536,
-                                               NULL,
-                                               NULL);
-               if (NULL == Session.Heap)
-               {
-                       RtlDeleteCriticalSection (& Session.Lock);
-                       Status = STATUS_NO_MEMORY;
-               }
-               Session.LastUnusedId = 0;
-       }
-       return Status;
+    /* Return the Session (or NULL) */
+    return NtSession;
 }
 
-static NTSTATUS STDCALL CsrpCreateSessionDirectories (PCSR_SESSION pCsrSession)
+/*++
+ * @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(PCSR_NT_SESSION Session)
 {
-       NTSTATUS           Status = STATUS_SUCCESS;
-       CHAR               SessionIdBuffer [8];
-       ANSI_STRING        SessionIdNameA;
-       UNICODE_STRING     SessionIdNameW;
-       UNICODE_STRING     SessionDirectoryName;
-       OBJECT_ATTRIBUTES  DirectoryAttributes;
-       HANDLE             DirectoryHAndle;
-
-       DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, pCsrSession);
-
-       sprintf (SessionIdBuffer, "\\Sessions\\%ld", pCsrSession->SessionId);
-       RtlInitAnsiString (& SessionIdNameA, SessionIdBuffer);
-       RtlAnsiStringToUnicodeString (& SessionIdNameW, & SessionIdNameA, TRUE);
-       RtlCopyUnicodeString (& SessionDirectoryName, & CsrSrvOption.NameSpace.Root);
-       RtlAppendUnicodeStringToString (& SessionDirectoryName, & SessionIdNameW);
-
-       DPRINT("CSRSRV: %s(%08lx): %S\n", __FUNCTION__, pCsrSession,
-                       SessionDirectoryName.Buffer);
-
-       InitializeObjectAttributes (& DirectoryAttributes,
-                                       & SessionDirectoryName,
-                                       OBJ_OPENIF,
-                                       NULL,
-                                       NULL);
-       Status = NtCreateDirectoryObject (& DirectoryHAndle,
-                                         (DIRECTORY_CREATE_OBJECT|DIRECTORY_CREATE_SUBDIRECTORY),
-                                         & DirectoryAttributes);
-       if (NT_SUCCESS(Status))
-       {
-               DPRINT1("CSRSRV: session %ld root directory not created (Status=%08lx)\n",
-                               pCsrSession->SessionId, Status);
-       }
-       // TODO
-       return Status;
+    /* Acquire the lock */
+    CsrAcquireNtSessionLock();
+
+    /* Increase the reference count */
+    Session->ReferenceCount++;
+
+    /* Release the lock */
+    CsrReleaseNtSessionLock();
 }
 
-static NTSTATUS STDCALL CsrpDestroySessionDirectories (PCSR_SESSION pCsrSession)
+/*++
+ * @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(PCSR_NT_SESSION Session,
+                        NTSTATUS ExitStatus)
 {
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return STATUS_NOT_IMPLEMENTED;
+    /* Acquire the lock */
+    CsrAcquireNtSessionLock();
+
+    /* Dereference the Session Object */
+    if (!(--Session->ReferenceCount))
+    {
+        /* Remove it from the list */
+        RemoveEntryList(&Session->SessionList);
+
+        /* 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();
+    }
 }
 
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
 
-NTSTATUS STDCALL CsrDestroySession (PCSR_SESSION pCsrSession)
+/* 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_MESSAGE ApiMessage)
 {
-       NTSTATUS Status = STATUS_SUCCESS;
-
-       DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, pCsrSession);
-       
-       if (NULL == pCsrSession)
-       {
-               Status = STATUS_INVALID_PARAMETER;
-       } else {
-               Status = CsrShutdownProcesses (pCsrSession);
-               Status = CsrpDestroySessionDirectories (pCsrSession);
-               RtlDestroyHeap (pCsrSession->Heap);
-               RtlFreeHeap (Session.Heap, 0, pCsrSession);
-       }
-       return Status;
+    PSB_CREATE_SESSION CreateSession = &ApiMessage->SbCreateSession;
+    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 */
+    if (!(CsrProcess = CsrAllocateProcess()))
+    {
+        /* Fail */
+        ApiMessage->Status = STATUS_NO_MEMORY;
+        CsrReleaseProcessLock();
+        return TRUE;
+    }
+
+    /* Setup Process Data */
+    CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId;
+    CsrProcess->ProcessHandle = hProcess;
+
+    /* 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();
+
+        return (BOOLEAN)Status;
+    }
+
+    /* Allocate a new Thread */
+    if (!(CsrThread = CsrAllocateThread(CsrProcess)))
+    {
+        /* Fail the request */
+        CsrDeallocateProcess(CsrProcess);
+        ApiMessage->Status = STATUS_NO_MEMORY;
+        CsrReleaseProcessLock();
+        return TRUE;
+    }
+
+    /* Setup the Thread Object */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = CreateSession->ProcessInfo.ClientId;
+    CsrThread->ThreadHandle = hThread;
+    CsrThread->Flags = 0;
+
+    /* Insert it into the Process List */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Allocate a new Session */
+    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->Status = NtResumeThread(hThread, NULL);
+
+    /* Release lock and return */
+    CsrReleaseProcessLock();
+    return TRUE;
 }
 
-NTSTATUS STDCALL CsrCreateSession (PCSR_SESSION * ppCsrSession)
+/*++
+ * @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_MESSAGE ApiMessage)
 {
-       NTSTATUS      Status = STATUS_SUCCESS;
-       PCSR_SESSION  pCsrSession = NULL;
-
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       if (NULL == ppCsrSession)
-       {
-               Status = STATUS_INVALID_PARAMETER;
-       } else {
-               RtlEnterCriticalSection (& Session.Lock);
-               pCsrSession = RtlAllocateHeap (Session.Heap,
-                                               HEAP_ZERO_MEMORY,
-                                               sizeof (CSR_SESSION));
-               if (NULL == pCsrSession)
-               {
-                       Status = STATUS_NO_MEMORY;
-               } else {
-                       pCsrSession->SessionId = Session.LastUnusedId ++;
-                       Status = CsrpCreateSessionDirectories (pCsrSession);
-                       if(NT_SUCCESS(Status))
-                       {
-                               pCsrSession->Heap = RtlCreateHeap(HEAP_GROWABLE,
-                                                                 NULL,
-                                                                 65536,
-                                                                 65536,
-                                                                 NULL,
-                                                                 NULL);
-                               if (NULL == pCsrSession->Heap)
-                               {
-                                       Status = STATUS_NO_MEMORY;
-                                       CsrpDestroySessionDirectories (pCsrSession);
-                                       -- Session.LastUnusedId;
-                               }
-                       }
-               }
-               RtlLeaveCriticalSection (& Session.Lock);       
-       }
-       return Status;
+    /* Deprecated/Unimplemented in NT */
+    ApiMessage->Status = STATUS_NOT_IMPLEMENTED;
+    return TRUE;
 }
-
 /* EOF */
index 283e8f5..d1b0550 100644 (file)
-#if !defined(_INCLUDE_CSR_CSRSRV_SRV_H)
-#define _INCLUDE_CSR_CSRSRV_SRV_H
+#ifndef _CSRSRV_H
+#define _CSRSRV_H
 
 /* PSDK/NDK Headers */
+#define NTOS_MODE_USER
 #include <stdio.h>
 #include <windows.h>
-
-#define NTOS_MODE_USER
 #include <ndk/ntndk.h>
 
-/* CSR Headers */
+/* CSR Header */
 #include <csr/server.h>
 
-/* Maximum number of hosted servers, included the one in csrsrv.dll */
+/* PSEH for SEH Support */
+#include <pseh/pseh.h>
+
+/* DEFINES *******************************************************************/
+
 #define CSR_SERVER_DLL_MAX 4
 
-typedef enum {
-       CSRSST_NONE=0,
-       CSRSST_TEXT,
-       CSRSST_WINDOWS,
-       CSRSST_MAX
-       
-} CSR_SUBSYSTEM_TYPE, * PCSR_SUBSYSTEM_TYPE;
-
-typedef struct _CSR_SERVER_DLL
-{
-       USHORT ServerIndex;
-       USHORT Unused;
-       UNICODE_STRING DllName;
-       UNICODE_STRING DllEntryPoint;
-} CSR_SERVER_DLL, * PCSR_SERVER_DLL;
-
-/* dllmain.c */
-extern HANDLE CsrSrvDllHandle;
-
-/* process.c */
-
-/* server.c */
-typedef struct
-{
-       struct {
-               UNICODE_STRING      Root;
-               HANDLE              RootHandle;
-       } NameSpace;
-       CSR_SUBSYSTEM_TYPE  SubSystemType;
-       struct {
-               USHORT              RequestCount;
-               USHORT              MaxRequestCount;
-       } Threads;
-       struct {
-               BOOL                ProfileControl;
-               BOOL                Windows;
-               BOOL                Sessions;
-       } Flag;
-       USHORT PortSharedSectionSize;
-       struct {
-               USHORT InteractiveDesktopHeapSize;
-               USHORT NonInteractiveDesktopHeapSize;
-       } Heap;
-} CSRSRV_OPTION, * PCSRSRV_OPTION;
-
-extern CSRSRV_OPTION CsrSrvOption;
-extern HANDLE CsrSrvApiPortHandle;
-
-NTSTATUS STDCALL CsrSrvRegisterServerDll (PCSR_SERVER_DLL);
-NTSTATUS STDCALL CsrSrvBootstrap (VOID);
-
-/* session.c */
-NTSTATUS STDCALL CsrSrvInitializeSession (VOID);
-
-
-#endif /* !def _INCLUDE_CSR_CSRSRV_SRV_H */
+#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 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"\\"
+
+/* 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];
+
+/* FUNCTIONS *****************************************************************/
+
+/* FIXME: Public APIs should go in the CSR Server Include */
+NTSTATUS
+NTAPI
+CsrLoadServerDll(
+    IN PCHAR DllString,
+    IN PCHAR EntryPoint,
+    IN ULONG ServerId
+);
+
+NTSTATUS
+NTAPI
+CsrCreateSessionObjectDirectory(IN ULONG SessionId);
+
+NTSTATUS
+NTAPI
+CsrCreateObjectDirectory(IN PCHAR ObjectDirectory);
+
+NTSTATUS
+NTAPI
+CsrSrvCreateSharedSection(IN PCHAR ParameterValue);
+
+NTSTATUS
+NTAPI
+CsrInitializeNtSessions(VOID);
+
+NTSTATUS
+NTAPI
+CsrInitializeProcesses(VOID);
+
+NTSTATUS
+NTAPI
+CsrApiPortInitialize(VOID);
+
+NTSTATUS
+NTAPI
+CsrSbApiPortInitialize(VOID);
+
+BOOLEAN
+NTAPI
+CsrSbCreateSession(IN PSB_API_MESSAGE ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrSbForeignSessionComplete(IN PSB_API_MESSAGE ApiMessage);
+
+BOOLEAN
+NTAPI
+CsrSbCreateProcess(IN PSB_API_MESSAGE 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);
+
+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_MESSAGE 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
+);
+
+_SEH_FILTER(CsrUnhandledExceptionFilter);
+
+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/subsys/csr/csrsrv/status.h b/reactos/subsys/csr/csrsrv/status.h
new file mode 100644 (file)
index 0000000..f2ded0f
--- /dev/null
@@ -0,0 +1,111 @@
+/*\r
+ * CSRSRV Status \r
+ */\r
+\r
+/* Organization\r
+ *\r
+ * api.c     - Handles the LPC Reply/Request Threads which wait on Sb and Csr APIs.\r
+ *             Also in charge of creating those threads and setting up the ports.\r
+ *             Finally, it provides external APIs for validating the API buffers\r
+ *             and doing server-to-server API calls.\r
+ *\r
+ * init.c    - Handles initialization of CSRSRV, including command-line parsing,\r
+ *             loading the Server DLLs, creating the Session Directories, setting\r
+ *             up the DosDevices Object Directory, and initializing each component.\r
+ *\r
+ * process.c - Handles all internal functions dealing with the CSR Process Object,\r
+ *             including de/allocation, de/referencing, un/locking, prority, and \r
+ *             lookups. Also handles all external APIs which touch the CSR Process Object.\r
+ *\r
+ * server.c  - Handles all internal functions related to loading and managing Server\r
+ *             DLLs, as well as the routines handling the Shared Static Memory Section.\r
+ *             Holds the API Dispatch/Valid/Name Tables and the public CSR_SERVER API\r
+ *             interface. Also home of the SEH handler.\r
+ *\r
+ * session.c - Handles all internal functions dealing with the CSR Session Object,\r
+ *             including de/allocation, de/referencing, and un/locking. Holds the SB API\r
+ *             Dispatch/Name Tables and the public CsrSv API Interface for commmunication\r
+ *             with the Session Manager.\r
+ *\r
+ * thread.c  - Handles all internal functions dealing with the CSR Thread Object,\r
+ *             including de/allocation, de/referencing, un/locking, impersonation, and\r
+ *             lookups. Also handles all external APIs which touch the CSR Thread Object.\r
+ *\r
+ * wait.c   -  Handles all internal functions dealing with the CSR Wait Object,\r
+ *             including de/allocation, de/referencing and un/locking. Also implements\r
+ *             the external Wait API for creating, removing and/or notifying waits.\r
+ */\r
+\r
+/* Exported APIs, their location, and their status\r
+ * CsrAddStaticServerThread    753E679E 1  - server.c  - IMPLEMENTED\r
+ * CsrCallServerFromServer     753E4FD9 2  - api.c     - IMPLEMENTED\r
+ * CsrConnectToUser            753E4E48 3  - api.c     - IMPLEMENTED\r
+ * CsrCreateProcess            753E6FD3 4  - process.c - IMPLEMENTED\r
+ * CsrCreateRemoteThread       753E73BD 5  - thread.c  - IMPLEMENTED\r
+ * CsrCreateThread             753E72DA 6  - thread.c  - IMPLEMENTED\r
+ * CsrCreateWait               753E770E 7  - wait.c    - IMPLEMENTED\r
+ * CsrDebugProcess             753E7682 8  - process.c - IMPLEMENTED\r
+ * CsrDebugProcessStop         753E768A 9  - process.c - IMPLEMENTED\r
+ * CsrDereferenceProcess       753E6281 10 - process.c - IMPLEMENTED\r
+ * CsrDereferenceThread        753E6964 11 - thread.c  - IMPLEMENTED\r
+ * CsrDereferenceWait          753E7886 12 - wait.c    - IMPLEMENTED\r
+ * CsrDestroyProcess           753E7225 13 - process.c - IMPLEMENTED\r
+ * CsrDestroyThread            753E7478 14 - thread.c  - IMPLEMENTED\r
+ * CsrExecServerThread         753E6841 15 - thread.c  - IMPLEMENTED\r
+ * CsrGetProcessLuid           753E632F 16 - process.c - IMPLEMENTED\r
+ * CsrImpersonateClient        753E60F8 17 - thread.c  - IMPLEMENTED\r
+ * CsrLockProcessByClientId    753E668F 18 - process.c - IMPLEMENTED\r
+ * CsrLockThreadByClientId     753E6719 19 - thread.c  - IMPLEMENTED\r
+ * CsrMoveSatisfiedWait        753E7909 20 - wait.c    - IMPLEMENTED\r
+ * CsrNotifyWait               753E782F 21 - wait.c    - IMPLEMENTED\r
+ * CsrPopulateDosDevices       753E37A5 22 - init.c    - IMPLEMENTED\r
+ * CsrQueryApiPort             753E4E42 23 - api.c     - IMPLEMENTED\r
+ * CsrReferenceThread          753E61E5 24 - thread.c  - IMPLEMENTED\r
+ * CsrRevertToSelf             753E615A 25 - thread.c  - IMPLEMENTED\r
+ * CsrServerInitialization     753E3D75 26 - server.c  - IMPLEMENTED\r
+ * CsrSetBackgroundPriority    753E5E87 27 - process.c - IMPLEMENTED\r
+ * CsrSetCallingSpooler        753E6425 28 - server.c  - IMPLEMENTED\r
+ * CsrSetForegroundPriority    753E5E67 29 - process.c - IMPLEMENTED\r
+ * CsrShutdownProcesses        753E7547 30 - process.c - IMPLEMENTED\r
+ * CsrUnhandledExceptionFilter 753E3FE3 31 - server.c  - IMPLEMENTED\r
+ * CsrUnlockProcess            753E66FD 32 - process.c - IMPLEMENTED\r
+ * CsrUnlockThread             753E7503 33 - thread.c  - IMPLEMENTED\r
+ * CsrValidateMessageBuffer    753E528D 34 - api.c     - IMPLEMENTED\r
+ * CsrValidateMessageString    753E5323 35 - api.c     - UNIMPLEMENTED\r
+ */\r
+\r
+/* Public CSR API Interface Status (server.c)\r
+ * CsrSrvClientConnect                                 - IMPLEMENTED\r
+ * CsrSrvUnusedFunction                                - IMPLEMENTED\r
+ * CsrSrvIdentifyAlertableThread                       - IMPLEMENTED\r
+ * CsrSrvSetPriorityClass                              - IMPLEMENTED\r
+ */\r
+\r
+/* Public SB API Interface Status (session.c)\r
+ * CsrSbCreateSession                                  - IMPLEMENTED\r
+ * CsrSbForeignSessionComplete                         - IMPLEMENTED\r
+ * CsrSbTerminateSession                               - IMPLEMENTED\r
+ * CsrSbCreateProcess                                  - UNIMPLEMENTED\r
+ */\r
+\r
+/* What's missing:\r
+ *\r
+ * - SMSS needs to be partly re-written to match some things done here.\r
+ *   Among other things, SmConnectToSm, SmCompleteSession and the other\r
+ *   Sm* Exported APIs have to be properly implemented, as well as the\r
+ *   callback calling and SM LPC APIs. [NOT DONE]\r
+ *\r
+ * - NTDLL needs to get the Csr* routines properly implemented. [DONE!]\r
+ *\r
+ * - KERNEL32, USER32 need to register with their servers properly.\r
+ *   Additionally, user32 needs to have ClientThreadStartup implemented\r
+ *   properly and do the syscall NtUserInitialize (I think) which also\r
+ *   needs to be implemented in win32k.sys. All this should be less then\r
+ *   100 lines of code. [KERNEL32 50% DONE, USER32 NOT DONE]\r
+ *\r
+ * - The skeleton code for winsrv and basesrv which connects with CSR/CSRSRV\r
+ *   needs to be written. [NOT DONE]\r
+ *\r
+ * - The kernel's LPC implementation needs to be made compatible. [NOT DONE]\r
+ */\r
+\r
index c06c539..ca7c632 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/thread.c - CSR server - thread management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/thread.c
+ * PURPOSE:         CSR Server DLL Thread Implementation
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  */
+
+/* INCLUDES ******************************************************************/
+
 #include "srv.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
+/* DATA **********************************************************************/
+
+LIST_ENTRY CsrThreadHashTable[256];
+SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
+{
+    sizeof(SECURITY_QUALITY_OF_SERVICE),
+    SecurityImpersonation,
+    SECURITY_STATIC_TRACKING,
+    FALSE
+};
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+/*++
+ * @name CsrAllocateThread
+ *
+ * The CsrAllocateThread routine allocates a new CSR Thread object.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process which will contain this CSR Thread.
+ *
+ * @return Pointer to the newly allocated CSR Thread.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
+{
+    PCSR_THREAD CsrThread;
+
+    /* Allocate the structure */
+    CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
+    if (!CsrThread) return(NULL);
+
+    /* Reference the Thread and Process */
+    CsrThread->ReferenceCount++;
+    CsrProcess->ReferenceCount++;
+
+    /* Set the Parent Process */
+    CsrThread->Process = CsrProcess;
+
+    /* Return Thread */
+    return CsrThread;
+}
+
+/*++
+ * @name CsrLocateThreadByClientId
+ *
+ * The CsrLocateThreadByClientId routine locates the CSR Thread and,
+ * optionally, its parent CSR Process, corresponding to a Client ID.
+ *
+ * @param Process
+ *        Optional pointer to a CSR Process pointer which will contain
+ *        the CSR Thread's parent.
+ *
+ * @param ClientId
+ *        Pointer to a Client ID structure containing the Unique Thread ID
+ *        to look up.
+ *
+ * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
+ *         none was found.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL,
+                          IN PCLIENT_ID ClientId)
+{
+    ULONG i;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD FoundThread;
+
+    /* Hash the Thread */
+    i = CsrHashThread(ClientId->UniqueThread);
+    
+    /* Set the list pointers */
+    ListHead = &CsrThreadHashTable[i];
+    NextEntry = ListHead->Flink;
+
+    /* Star the loop */
+    while (NextEntry != ListHead)
+    {
+        /* Get the thread */
+        FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
+
+        /* Compare the CID */
+        if (FoundThread->ClientId.UniqueThread == ClientId->UniqueThread)
+        {
+            /* Match found, return the process */
+            *Process = FoundThread->Process;
+
+            /* Return thread too */
+            return FoundThread;
+        }
+
+        /* Next */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Nothing found */
+    return NULL;
+}
+
+/*++
+ * @name CsrLocateThreadInProcess
+ *
+ * The CsrLocateThreadInProcess routine locates the CSR Thread 
+ * corresponding to a Client ID inside a specific CSR Process.
+ *
+ * @param Process
+ *        Optional pointer to the CSR Process which contains the CSR Thread
+ *        that will be looked up.
+ *
+ * @param ClientId
+ *        Pointer to a Client ID structure containing the Unique Thread ID
+ *        to look up.
+ *
+ * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
+ *         none was found.
+ *
+ * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
+ *          CsrRootProcess.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL,
+                         IN PCLIENT_ID Cid)
+{
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD FoundThread = NULL;
+
+    /* Use the Root Process if none was specified */
+    if (!CsrProcess) CsrProcess = CsrRootProcess;
+
+    /* Save the List pointers */
+    ListHead = &CsrProcess->ThreadList;
+    NextEntry = ListHead->Flink;
+
+    /* Start the Loop */
+    while (NextEntry != NextEntry)
+    {
+        /* Get Thread Entry */
+        FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
+
+        /* Check for TID Match */
+        if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Return what we found */
+    return FoundThread;
+}
+
+/*++
+ * @name CsrInsertThread
+ *
+ * The CsrInsertThread routine inserts a CSR Thread into its parent's
+ * Thread List and into the Thread Hash Table.
+ *
+ * @param Process
+ *        Pointer to the CSR Process containing this CSR Thread.
+ *
+ * @param Thread
+ *        Pointer to the CSR Thread to be inserted.
+ *
+ * @return None.
+ *
+ * @remarks None.
+ *
+ *--*/
+VOID
+NTAPI
+CsrInsertThread(IN PCSR_PROCESS Process,
+                IN PCSR_THREAD Thread)
+{
+    ULONG i;
+
+    /* Insert it into the Regular List */
+    InsertTailList(&Process->ThreadList, &Thread->Link);
+
+    /* Increase Thread Count */
+    Process->ThreadCount++;
+
+    /* Hash the Thread */
+    i = CsrHashThread(Thread->ClientId.UniqueThread);
+
+    /* Insert it there too */
+    InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
+}
+
+/*++
+ * @name CsrDeallocateThread
+ *
+ * The CsrDeallocateThread frees the memory associated with a CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to be freed.
+ *
+ * @return None.
+ *
+ * @remarks Do not call this routine. It is reserved for the internal
+ *          thread management routines when a CSR Thread has been cleanly
+ *          dereferenced and killed.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDeallocateThread(IN PCSR_THREAD CsrThread)
+{
+    /* Free the process object from the heap */
+    RtlFreeHeap(CsrHeap, 0, CsrThread);
+}
+
+/*++
+ * @name CsrLockedDereferenceThread
+ *
+ * The CsrLockedDereferenceThread derefences a CSR Thread while the
+ * Process Lock is already being held.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to be dereferenced.
+ *
+ * @return None.
+ *
+ * @remarks This routine will return with the Process Lock held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrLockedDereferenceThread(PCSR_THREAD CsrThread)
+{
+    /* Decrease reference count */
+    if (!(--CsrThread->ReferenceCount))
+    {
+        /* Call the generic cleanup code */
+        CsrThreadRefcountZero(CsrThread);
+        CsrAcquireProcessLock();
+    }
+}
+
+/*++
+ * @name CsrRemoveThread
+ *
+ * The CsrRemoveThread function undoes a CsrInsertThread operation and
+ * removes the CSR Thread from the the Hash Table and Thread List.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to remove.  
+ *
+ * @return None.
+ *
+ * @remarks If this CSR Thread is the last one inside a CSR Process, the
+ *          parent will be dereferenced and the CsrProcessLastThreadTerminated
+ *          flag will be set.
+ *
+ *          After executing this routine, the CSR Thread will have the
+ *          CsrThreadInTermination flag set.
+ *
+ *--*/
+VOID
+NTAPI
+CsrRemoveThread(IN PCSR_THREAD CsrThread)
+{
+    /* Remove it from the List */
+    RemoveEntryList(&CsrThread->Link);
+
+    /* Decreate the thread count of the process */
+    CsrThread->Process->ThreadCount--;
+
+    /* Remove it from the Hash List as well */
+    if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
+
+    /* Check if this is the last Thread */
+    if (!CsrThread->Process->ThreadCount)
+    {
+        /* Check if it's not already been marked for deletion */
+        if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
+        {
+            /* Let everyone know this process is about to lose the thread */
+            CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
+
+            /* Reference the Process */
+            CsrLockedDereferenceProcess(CsrThread->Process);
+        }
+    }
+
+    /* Mark the thread for deletion */
+    CsrThread->Flags |= CsrThreadInTermination;
+}
+
+/*++
+ * @name CsrThreadRefcountZero
+ *
+ * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
+ * all its active references. It removes and de-allocates the CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread that is to be deleted.
+ *
+ * @return None.
+ *
+ * @remarks Do not call this routine. It is reserved for the internal
+ *          thread management routines when a CSR Thread has lost all
+ *          its references.
+ *
+ *          This routine is called with the Process Lock held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
+{
+    PCSR_PROCESS CsrProcess = CsrThread->Process;
+
+    /* Remove this thread */
+    CsrRemoveThread(CsrThread);
+
+    /* Release the Process Lock */
+    CsrReleaseProcessLock();
+
+    /* Close the NT Thread Handle */
+    NtClose(CsrThread->ThreadHandle);
+    
+    /* De-allocate the CSR Thread Object */
+    CsrDeallocateThread(CsrThread);
+
+    /* Remove a reference from the process */
+    CsrDereferenceProcess(CsrProcess);
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
+/*++
+ * @name CsrAddStaticServerThread
+ * @implemented NT4
+ *
+ * The CsrAddStaticServerThread routine adds a new CSR Thread to the
+ * CSR Server Process (CsrRootProcess).
+ *
+ * @param hThread
+ *        Handle to an existing NT Thread to which to associate this
+ *        CSR Thread.
+ *
+ * @param ClientId
+ *        Pointer to the Client ID structure of the NT Thread to associate
+ *        with this CSR Thread.
+ *
+ * @param ThreadFlags
+ *        Initial CSR Thread Flags to associate to this CSR Thread. Usually
+ *        CsrThreadIsServerThread.
+ *
+ * @return Pointer to the newly allocated CSR Thread.
+ *
+ * @remarks None.
+ *
+ *--*/
+PCSR_THREAD
+NTAPI
+CsrAddStaticServerThread(IN HANDLE hThread,
+                         IN PCLIENT_ID ClientId,
+                         IN ULONG ThreadFlags)
+{
+    PCSR_THREAD CsrThread;
+
+    /* Get the Lock */
+    CsrAcquireProcessLock();
+
+    /* Allocate the Server Thread */
+    if ((CsrThread = CsrAllocateThread(CsrRootProcess)))
+    {
+        /* Setup the Object */
+        CsrThread->ThreadHandle = hThread;
+        CsrThread->ClientId = *ClientId;
+        CsrThread->Flags = ThreadFlags;
+
+        /* Insert it into the Thread List */
+        InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
+
+        /* Increment the thread count */
+        CsrRootProcess->ThreadCount++;
+    }
+
+    /* Release the Process Lock and return */
+    CsrReleaseProcessLock();
+    return CsrThread;
+}
+
+/*++
+ * @name CsrCreateRemoteThread
+ * @implemented NT4
+ *
+ * The CsrCreateRemoteThread routine creates a CSR Thread object for
+ * an NT Thread which is not part of the current NT Process.
+ *
+ * @param hThread
+ *        Handle to an existing NT Thread to which to associate this
+ *        CSR Thread.
+ *
+ * @param ClientId
+ *        Pointer to the Client ID structure of the NT Thread to associate
+ *        with this CSR Thread.  
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateRemoteThread(IN HANDLE hThread,
+                      IN PCLIENT_ID ClientId)
+{
+    NTSTATUS Status;
+    HANDLE ThreadHandle;
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS CsrProcess;
+    KERNEL_USER_TIMES KernelTimes;
+
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Get the Thread Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      (PVOID)&KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+
+    /* Lock the Owner Process */
+    Status = CsrLockProcessByClientId(&ClientId->UniqueProcess,
+                                      &CsrProcess);
+
+    /* Make sure the thread didn't terminate */
+    if (KernelTimes.ExitTime.QuadPart)
+    {
+        /* Unlock the process and return */
+        CsrUnlockProcess(CsrProcess);
+        return STATUS_THREAD_IS_TERMINATING;
+    }
+
+    /* Allocate a CSR Thread Structure */
+    if (!(CsrThread = CsrAllocateThread(CsrProcess)))
+    {
+        DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
+        CsrUnlockProcess(CsrProcess);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Duplicate the Thread Handle */
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               hThread,
+                               NtCurrentProcess(),
+                               &ThreadHandle,
+                               0,
+                               0,
+                               DUPLICATE_SAME_ACCESS);
+    /* Allow failure */
+    if (!NT_SUCCESS(Status)) ThreadHandle = hThread;
+
+    /* Save the data we have */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = *ClientId;
+    CsrThread->ThreadHandle = ThreadHandle;
+    CsrThread->Flags = 0;
 
-NTSTATUS STDCALL CsrCreateRemoteThread ()
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Release the lock and return */
+    CsrUnlockProcess(CsrProcess);
+    return STATUS_SUCCESS;
+}
+
+/*++
+ * @name CsrCreateThread
+ * @implemented NT4
+ *
+ * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
+ *
+ * @param CsrProcess
+ *        Pointer to the CSR Process which will contain the CSR Thread.
+ *
+ * @param hThread
+ *        Handle to an existing NT Thread to which to associate this
+ *        CSR Thread.
+ *
+ * @param ClientId
+ *        Pointer to the Client ID structure of the NT Thread to associate
+ *        with this CSR Thread.   
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrCreateThread(IN PCSR_PROCESS CsrProcess,
+                IN HANDLE hThread,
+                IN PCLIENT_ID ClientId)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS CurrentProcess;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+    CLIENT_ID CurrentCid;
+    KERNEL_USER_TIMES KernelTimes;
+
+    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+
+    /* Get the current thread and CID */
+    CurrentCid = CurrentThread->ClientId;
+
+    /* Acquire the Process Lock */
+    CsrAcquireProcessLock();
+
+    /* Get the current Process and make sure the Thread is valid with this CID */
+    CurrentThread = CsrLocateThreadByClientId(&CurrentProcess,
+                                              &CurrentCid);
+
+    /* Something is wrong if we get an empty thread back */
+    if (!CurrentThread)
+    {
+        DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
+        CsrReleaseProcessLock();
+        return STATUS_THREAD_IS_TERMINATING;
+    }
+
+    /* Get the Thread Create Time */
+    Status = NtQueryInformationThread(hThread,
+                                      ThreadTimes,
+                                      (PVOID)&KernelTimes,
+                                      sizeof(KernelTimes),
+                                      NULL);
+
+    /* Allocate a CSR Thread Structure */
+    if (!(CsrThread = CsrAllocateThread(CsrProcess)))
+    {
+        DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Save the data we have */
+    CsrThread->CreateTime = KernelTimes.CreateTime;
+    CsrThread->ClientId = *ClientId;
+    CsrThread->ThreadHandle = hThread;
+    CsrThread->Flags = 0;
+
+    /* Insert the Thread into the Process */
+    CsrInsertThread(CsrProcess, CsrThread);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS STDCALL CsrCreateThread (PCSR_PROCESS pCsrProcess, PCSR_THREAD *ppCsrThread)
+/*++
+ * @name CsrDereferenceThread
+ * @implemented NT4
+ *
+ * The CsrDereferenceThread routine removes a reference from a CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to dereference.
+ *
+ * @return None.
+ *
+ * @remarks If the reference count has reached zero (ie: the CSR Thread has
+ *          no more active references), it will be deleted.
+ *
+ *--*/
+VOID
+NTAPI
+CsrDereferenceThread(PCSR_THREAD CsrThread)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       PCSR_THREAD pCsrThread = NULL;
-       PCSR_SESSION pCsrSession = NULL;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
 
-       if (NULL == pCsrProcess || NULL == ppCsrThread)
-       {
-               return STATUS_INVALID_PARAMETER;
-       }
-       pCsrSession = pCsrProcess->NtSession;
-       pCsrThread = RtlAllocateHeap (pCsrSession->Heap,
-                                       HEAP_ZERO_MEMORY,
-                                       sizeof (CSR_THREAD));
-       if (NULL == pCsrThread)
-       {
-               DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
-               return STATUS_NO_MEMORY;
-       }
-       pCsrThread->Process = pCsrProcess;      
-       return Status;
+    /* Decrease reference count */
+    if (!(--CsrThread->ReferenceCount))
+    {
+        /* Call the generic cleanup code */
+        CsrThreadRefcountZero(CsrThread);
+    }
+    else
+    {
+        /* Just release the lock */
+        CsrReleaseProcessLock();
+    }
 }
 
-NTSTATUS STDCALL CsrDereferenceThread (PCSR_THREAD pCsrThread)
+/*++
+ * @name CsrExecServerThread
+ * @implemented NT4
+ *
+ * The CsrExecServerThread routine creates an NT Thread and then
+ * initializes a CSR Thread for it.
+ *
+ * @param ThreadHandler
+ *        Pointer to the thread's startup routine.
+ *
+ * @param Flags
+ *        Initial CSR Thread Flags to set to the CSR Thread.    
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks This routine is similar to CsrAddStaticServerThread, but it
+ *          also creates an NT Thread instead of expecting one to already
+ *          exist.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrExecServerThread(IN PVOID ThreadHandler,
+                    IN ULONG Flags)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    PCSR_THREAD CsrThread;
+    HANDLE hThread;
+    CLIENT_ID ClientId;
+    NTSTATUS Status;
+
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Allocate a CSR Thread in the Root Process */
+    if (!(CsrThread = CsrAllocateThread(CsrRootProcess)))
+    {
+        /* Fail */
+        CsrReleaseProcessLock();
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Create the Thread */
+    Status = RtlCreateUserThread(NtCurrentProcess(),
+                                 NULL,
+                                 FALSE,
+                                 0,
+                                 0,
+                                 0,
+                                 ThreadHandler,
+                                 NULL,
+                                 &hThread,
+                                 &ClientId);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        CsrDeallocateThread(CsrThread);
+        CsrReleaseProcessLock();
+        return Status;
+    }
+
+    /* Setup the Thread Object */
+    CsrThread->ThreadHandle = hThread;
+    CsrThread->ClientId = ClientId;
+    CsrThread->Flags = Flags;
+
+    /* Insert it into the Thread List */
+    InsertHeadList(&CsrRootProcess->ThreadList, &CsrThread->Link);
+
+    /* Increase the thread count */
+    CsrRootProcess->ThreadCount++;
+
+    /* Return */
+    CsrReleaseProcessLock();
+    return Status;
 }
 
-NTSTATUS STDCALL CsrDestroyThread (PCSR_THREAD pCsrThread)
+/*++
+ * @name CsrDestroyThread
+ * @implemented NT4
+ *
+ * The CsrDestroyThread routine destroys the CSR Thread corresponding to 
+ * a given Thread ID.
+ *
+ * @param Cid
+ *        Pointer to the Client ID Structure corresponding to the CSR
+ *        Thread which is about to be destroyed. 
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
+ *         if the CSR Thread is already terminating.
+ *
+ * @remarks None.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrDestroyThread(IN PCLIENT_ID Cid)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    CLIENT_ID ClientId = *Cid;
+    PCSR_THREAD CsrThread;
+    PCSR_PROCESS CsrProcess;
+
+    /* Acquire lock */
+    CsrAcquireProcessLock();
+
+    /* Find the thread */
+    CsrThread = CsrLocateThreadByClientId(&CsrProcess,
+                                          &ClientId);
+
+    /* Make sure we got one back, and that it's not already gone */
+    if (!CsrThread || CsrThread->Flags & CsrThreadTerminated)
+    {
+        /* Release the lock and return failure */
+        CsrReleaseProcessLock();
+        return STATUS_THREAD_IS_TERMINATING;
+    }
+
+    /* Set the terminated flag */
+    CsrThread->Flags |= CsrThreadTerminated;
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Do we have an active wait block? */
+    if (CsrThread->WaitBlock)
+    {
+        /* Notify waiters of termination */
+        CsrNotifyWaitBlock(CsrThread->WaitBlock,
+                           NULL,
+                           NULL,
+                           NULL,
+                           CsrProcessTerminating,
+                           TRUE);
+    }
+
+    /* Release the Wait Lock */
+    CsrReleaseWaitLock();
+
+    /* Dereference the thread */
+    CsrLockedDereferenceThread(CsrThread);
+
+    /* Release the Process Lock and return success */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
-NTSTATUS STDCALL CsrLockThreadByClientId ()
+/*++
+ * @name CsrImpersonateClient
+ * @implemented NT4
+ *
+ * The CsrImpersonateClient will impersonate the given CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread to impersonate.    
+ *
+ * @return TRUE if impersionation suceeded, false otherwise.
+ *
+ * @remarks Impersonation can be recursive.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrImpersonateClient(IN PCSR_THREAD CsrThread)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+
+    /* Use the current thread if none given */
+    if (!CsrThread) CsrThread = CurrentThread;
+
+    /* Still no thread, something is wrong */
+    if (!CsrThread)
+    {
+        /* Failure */
+        return FALSE;
+    }
+
+    /* Make the call */
+    Status = NtImpersonateThread(NtCurrentThread(),
+                                 CsrThread->ThreadHandle,
+                                 &CsrSecurityQos);
+
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failure */
+        return FALSE;
+    }
+
+    /* Increase the impersonation count for the current thread */
+    if (CurrentThread) ++CurrentThread->ImpersonationCount;
+
+    /* Return Success */
+    return TRUE;
 }
 
-NTSTATUS STDCALL CsrReferenceThread (PCSR_THREAD pCsrThread)
+/*++
+ * @name CsrRevertToSelf
+ * @implemented NT4
+ *
+ * The CsrRevertToSelf routine will attempt to remove an active impersonation.
+ *
+ * @param None.  
+ *
+ * @return TRUE if the reversion was succesful, false otherwise.
+ *
+ * @remarks Impersonation can be recursive; as such, the impersonation token
+ *          will only be deleted once the CSR Thread's impersonaton count
+ *          has reached zero.
+ *
+ *--*/
+BOOLEAN
+NTAPI
+CsrRevertToSelf(VOID)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    NTSTATUS Status;
+    PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
+    HANDLE ImpersonationToken = NULL;
+
+    /* Check if we have a Current Thread */
+    if (CurrentThread)
+    {
+        /* Make sure impersonation is on */
+        if (!CurrentThread->ImpersonationCount)
+        {
+            return FALSE;
+        }
+        else if (--CurrentThread->ImpersonationCount > 0)
+        {
+            /* Success; impersonation count decreased but still not zero */
+            return TRUE;
+        }
+    }
+
+    /* Impersonation has been totally removed, revert to ourselves */
+    Status = NtSetInformationThread(NtCurrentThread(),
+                                    ThreadImpersonationToken,
+                                    &ImpersonationToken,
+                                    sizeof(HANDLE));
+
+    /* Return TRUE or FALSE */
+    return NT_SUCCESS(Status);
 }
 
-NTSTATUS STDCALL CsrUnlockThread (PCSR_THREAD pCsrThread)
+/*++
+ * @name CsrLockThreadByClientId
+ * @implemented NT4
+ *
+ * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
+ * to the given Thread ID and optionally returns it.
+ *
+ * @param Tid
+ *        Thread ID corresponding to the CSR Thread which will be locked.
+ *
+ * @param CsrThread
+ *        Optional pointer to a CSR Thread pointer which will hold the
+ *        CSR Thread corresponding to the given Thread ID.
+ *
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
+ *         othwerwise.
+ *
+ * @remarks Locking a CSR Thread is defined as acquiring an extra
+ *          reference to it and returning with the Process Lock held.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrLockThreadByClientId(IN HANDLE Tid,
+                        OUT PCSR_THREAD *CsrThread OPTIONAL)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_THREAD CurrentThread = NULL;
+    NTSTATUS Status = STATUS_UNSUCCESSFUL;
+    ULONG i;
+
+    /* Acquire the lock */
+    CsrAcquireProcessLock();
+
+    /* Convert to Hash */
+    i = CsrHashThread(Tid);
+
+    /* Setup the List Pointers */
+    ListHead = &CsrThreadHashTable[i];
+    NextEntry = ListHead;
+
+    /* Start Loop */
+    while (NextEntry != ListHead)
+    {
+        /* Get the Process */
+        CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
+
+        /* Check for PID Match */
+        if ((CurrentThread->ClientId.UniqueThread == Tid) &&
+            !(CurrentThread->Flags & CsrThreadTerminated))
+        {
+            /* Get out of here with success */
+            Status = STATUS_SUCCESS;
+            break;
+        }
+
+        /* Next entry */
+        NextEntry = NextEntry->Flink;
+    }
+
+    /* Did the loop find something? */
+    if (NT_SUCCESS(Status))
+    {
+        /* Reference the found thread */
+        CurrentThread->ReferenceCount++;
+    }
+    else
+    {
+        /* Nothing found, release the lock */
+        CsrReleaseProcessLock();
+    }
+
+    /* Return the status and thread */
+    if (CsrThread) *CsrThread = CurrentThread;
+    return Status;
+}
+
+/*++
+ * @name CsrReferenceThread
+ * @implemented NT4
+ *
+ * The CsrReferenceThread routine increases the active reference count of 
+ * a CSR Thread.
+ *
+ * @param CsrThread
+ *        Pointer to the CSR Thread whose reference count will be increased. 
+ *
+ * @return None.
+ *
+ * @remarks Do not use this routine if the Process Lock is already held.
+ *
+ *--*/
+VOID
+NTAPI
+CsrReferenceThread(PCSR_THREAD CsrThread)
+{
+    /* Acquire process lock */
+    CsrAcquireProcessLock();
+
+    /* Increment reference count */
+    CsrThread->ReferenceCount++;
+
+    /* Release the lock */
+    CsrReleaseProcessLock();
+}
+
+/*++
+ * @name CsrUnlockThread
+ * @implemented NT4
+ *
+ * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
+ *
+ * @param CsrThread
+ *        Pointer to a previously locked CSR Thread. 
+ *
+ * @return STATUS_SUCCESS.
+ *
+ * @remarks This routine must be called with the Process Lock held.
+ *
+ *--*/
+NTSTATUS
+NTAPI
+CsrUnlockThread(PCSR_THREAD CsrThread)
+{
+    /* Dereference the Thread */
+    CsrLockedDereferenceThread(CsrThread);
+
+    /* Release the lock and return */
+    CsrReleaseProcessLock();
+    return STATUS_SUCCESS;
 }
 
 /* EOF */
index e836407..08a8402 100644 (file)
-/* $Id$
- *
- * subsys/csr/csrsrv/wait.c - CSR server - wait management
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS CSR Sub System
+ * FILE:            subsys/csr/csrsrv/wait.c
+ * PURPOSE:         CSR Server DLL Wait Implementation
+ * PROGRAMMERS:     Emanuele Aliberti
+ *                  Alex Ionescu (alex@relsoft.net)
  */
+
+/* INCLUDES ******************************************************************/
+
 #include "srv.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
-/*=====================================================================
- *     PUBLIC API
- *===================================================================*/
+/* DATA **********************************************************************/
+
+RTL_CRITICAL_SECTION CsrWaitListsLock;
 
-NTSTATUS STDCALL CsrCreateWait (PCSR_THREAD pCsrThread, PCSR_WAIT * ppCsrWait)
+/* 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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    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 */
+    if (!(WaitBlock = RtlAllocateHeap(CsrHeap, 0, Size)))
+    {
+        /* Fail */
+        WaitApiMessage->Status = STATUS_NO_MEMORY;
+        return FALSE;
+    }
+
+    /* Initialize it */
+    WaitBlock->Size = Size;
+    WaitBlock->WaitThread = CsrWaitThread;
+    WaitBlock->WaitContext = WaitContext;
+    WaitBlock->WaitFunction = WaitFunction;
+    InitializeListHead(&WaitBlock->UserWaitList);
+    InitializeListHead(&WaitBlock->WaitList);
+
+    /* Copy the message */
+    RtlMoveMemory(&WaitBlock->WaitApiMessage,
+                  WaitApiMessage,
+                  WaitApiMessage->Header.u1.s1.TotalLength);
+
+    /* Return the block */
+    *NewWaitBlock = WaitBlock;
+    return TRUE;
 }
 
-NTSTATUS STDCALL CsrDereferenceWait (PCSR_WAIT pCsrWait)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    /* 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;
 }
 
-NTSTATUS STDCALL CsrMoveSatisfiedWait (PCSR_WAIT pCsrWait)
+/* 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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    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 && (CsrWaitThread->Flags & CsrThreadTerminated))
+    {
+        /* Fail the wait */
+        CsrWaitThread->WaitBlock = NULL;
+        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;
 }
 
-NTSTATUS STDCALL CsrNotifyWait (PCSR_WAIT pCsrWait)
+/*++
+ * @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)
 {
-       NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
-       
-       DPRINT("CSRSRV: %s called\n", __FUNCTION__);
-       
-       return Status;
+    PLIST_ENTRY ListHead, NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Acquire the Process and Wait Locks */
+    CsrAcquireProcessLock();
+    CsrAcquireWaitLock();
+
+    /* Set the list pointers */
+    ListHead = WaitList;
+    NextEntry = ListHead->Flink;
+
+    /* Start the loop */
+    while (NextEntry != ListHead)
+    {
+        /* 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 ListHead, NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Set the List pointers */
+    ListHead = WaitList;
+    NextEntry = ListHead->Flink;
+
+    /* Start looping */
+    while (NextEntry != ListHead)
+    {
+        /* 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 ListHead, NextEntry;
+    PCSR_WAIT_BLOCK WaitBlock;
+    BOOLEAN NotifySuccess = FALSE;
+
+    /* Acquire the Wait Lock */
+    CsrAcquireWaitLock();
+
+    /* Set the List pointers */
+    ListHead = WaitList;
+    NextEntry = ListHead->Flink;
+
+    /* Start looping */
+    while (NextEntry != ListHead)
+    {
+        /* 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 */
index bbb96de..c488521 100644 (file)
-/* $Id$
- *
- * main.c - Client/Server Runtime - entry point
- * 
- * ReactOS Operating System
- * 
- * --------------------------------------------------------------------
- *
- * This software is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING.LIB. If not, write
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
- *
- * --------------------------------------------------------------------
- * 
- *     19990417 (Emanuele Aliberti)
- *             Do nothing native application skeleton
- *     19990528 (Emanuele Aliberti)
- *             Compiled successfully with egcs 1.1.2
- *     19990605 (Emanuele Aliberti)
- *             First standalone run under ReactOS (it
- *             actually does nothing but running).
- *     20050329 (Emanuele Aliberti)
- *             C/S run-time moved to CSRSRV.DLL
- *             Win32 emulation moved to server DLLs basesrv+winsrv
- *             (previously code was already in win32csr.dll)
+/*
+ * 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)
  */
-#include "csr.h"
+
+/* INCLUDES ******************************************************************/
+
+#include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
 
 #define NDEBUG
 #include <debug.h>
 
-COMMAND_LINE_ARGUMENT Argument;
-
-/* never fail or so */
+/* PRIVATE FUNCTIONS *********************************************************/
 
-VOID STDCALL CsrpSetDefaultProcessHardErrorMode (VOID)
+VOID
+NTAPI
+CsrpSetDefaultProcessHardErrorMode (VOID)
 {
-    DWORD DefaultHardErrorMode = 0; 
-    NtSetInformationProcess (NtCurrentProcess(),
-                            ProcessDefaultHardErrorMode,
-                            & DefaultHardErrorMode,
-                            sizeof DefaultHardErrorMode);
-}
+    ULONG DefaultHardErrorMode = 0;
 
-/* Native process' entry point */
+    /* Disable hard errors */
+    NtSetInformationProcess(NtCurrentProcess(),
+                            ProcessDefaultHardErrorMode,
+                            &DefaultHardErrorMode,
+                            sizeof(DefaultHardErrorMode);
+}
 
-VOID STDCALL NtProcessStartup (PPEB Peb)
+int
+_cdecl
+main(int argc,
+     char *argv[],
+     char *envp[],
+     int DebugFlag)
 {
-  NTSTATUS  Status = STATUS_SUCCESS;
+    KPRIORITY BasePriority = (8 + 1) + 4;
+    NTSTATUS Status;
+    ULONG Response;
+
+    /* 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();
 
-  /*
-   *   Parse the command line.
-   */
-  Status = CsrParseCommandLine (Peb, & Argument);
-  if (STATUS_SUCCESS != Status)
-  {
-    DPRINT1("CSR: %s: CsrParseCommandLine failed (Status=0x%08lx)\n",
-       __FUNCTION__, Status);
-  }
-  /*
-   *   Initialize the environment subsystem server.
-   */
-  Status = CsrServerInitialization (Argument.Count, Argument.Vector);
-  if (!NT_SUCCESS(Status))
-  {
-    /* FATAL! */
-    DPRINT1("CSR: %s: CSRSRV!CsrServerInitialization failed (Status=0x%08lx)\n",
-       __FUNCTION__, Status);
+    /* If this is Session 0, make sure killing us bugchecks the system */
+    if (!NtCurrentPeb()->SessionId) RtlSetProcessIsCritical(TRUE, NULL, FALSE);
 
-    CsrFreeCommandLine (Peb, & Argument);
-    /*
-     * Tell the SM we failed. If we are a required
-     * subsystem, SM will halt the system.
-     */
-    NtTerminateProcess (NtCurrentProcess(), Status);
-  }
-  /*
-   *   The server booted OK: never stop on error!
-   */
-  CsrpSetDefaultProcessHardErrorMode ();
-  /*
-   *   Cleanup command line
-   */
-  CsrFreeCommandLine (Peb, & Argument);        
-  /*
-   *   Terminate the current thread only (server's
-   *   threads that serve the LPC port continue
-   *   running and keep the process alive).
-   */
-  NtTerminateThread (NtCurrentThread(), Status);
+    /* Kill this thread. CSRSRV keeps us going */
+    NtTerminateThread (NtCurrentThread(), Status);
+    return 0;
 }
 
 /* EOF */