summaryrefslogtreecommitdiffstats
path: root/private/csr
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/csr
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/csr/dirs25
-rw-r--r--private/csr/inc/csr.h66
-rw-r--r--private/csr/server/alpha/evpair.s63
-rw-r--r--private/csr/server/alpha/sources3
-rw-r--r--private/csr/server/apiinit.c174
-rw-r--r--private/csr/server/apilistn.c65
-rw-r--r--private/csr/server/apireqst.c1077
-rw-r--r--private/csr/server/csrdebug.c1028
-rw-r--r--private/csr/server/csrsrv.h603
-rw-r--r--private/csr/server/csrsrv.src38
-rw-r--r--private/csr/server/csrss.c107
-rw-r--r--private/csr/server/csrss.rc10
-rw-r--r--private/csr/server/i386/sources1
-rw-r--r--private/csr/server/makefile6
-rw-r--r--private/csr/server/mips/sources1
-rw-r--r--private/csr/server/ppc/sources2
-rw-r--r--private/csr/server/process.c2002
-rw-r--r--private/csr/server/sbapi.c171
-rw-r--r--private/csr/server/sbinit.c100
-rw-r--r--private/csr/server/sbreqst.c175
-rw-r--r--private/csr/server/semphore30
-rw-r--r--private/csr/server/session.c95
-rw-r--r--private/csr/server/sources62
-rw-r--r--private/csr/server/srvinit.c580
-rw-r--r--private/csr/server/srvloadr.c423
-rw-r--r--private/csr/server/wait.c254
26 files changed, 7161 insertions, 0 deletions
diff --git a/private/csr/dirs b/private/csr/dirs
new file mode 100644
index 000000000..ed20d8c56
--- /dev/null
+++ b/private/csr/dirs
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=server
+
+OPTIONAL_DIRS=
diff --git a/private/csr/inc/csr.h b/private/csr/inc/csr.h
new file mode 100644
index 000000000..fe844e02a
--- /dev/null
+++ b/private/csr/inc/csr.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ csr.h
+
+Abstract:
+
+ Include file that defines all the common data types and constants for
+ the Client-Server Runtime (CSR) SubSystem
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+
+//
+// Include NT Definitions.
+//
+
+#include "nt.h"
+#include "ntrtl.h"
+#include "nturtl.h"
+#include "string.h"
+
+#define GetModuleHandle GetModuleHandleA
+
+//
+// Define debugging flag as false if not defined already.
+//
+
+#ifndef DBG
+#define DBG 0
+#endif
+
+
+//
+// Define IF_DEBUG macro that can be used to enable debugging code that is
+// optimized out if the debugging flag is false.
+//
+
+#if DBG
+#define IF_DEBUG if (TRUE)
+#else
+#define IF_DEBUG if (FALSE)
+#endif
+
+//
+// Common types and constant definitions
+//
+
+typedef enum _CSRP_API_NUMBER {
+ CsrpNullApiCall = 0, // CSRSRV_FIRST_API_NUMBER defined in ntcsrmsg.h
+ CsrpClientConnect,
+ CsrpThreadConnect,
+ CsrpProfileControl,
+ CsrpIdentifyAlertable,
+ CsrpSetPriorityClass,
+ CsrpMaxApiNumber
+} CSRP_API_NUMBER, *PCSRP_API_NUMBER;
diff --git a/private/csr/server/alpha/evpair.s b/private/csr/server/alpha/evpair.s
new file mode 100644
index 000000000..a8e7fcd63
--- /dev/null
+++ b/private/csr/server/alpha/evpair.s
@@ -0,0 +1,63 @@
+// TITLE("Fast Event Pair Support")
+//++
+//
+// Copyright (c) 1992 Microsoft Corporation
+// Copyright (c) 1993 Digital Equipement Corporation
+//
+// Module Name:
+//
+// evpair.s
+//
+// Abstract:
+//
+// This module contains the system call interface for the fast event pair
+// system service that is used from the server side.
+//
+// Author:
+//
+// David N. Cutler (davec) 29-Oct-1992
+// Joe Notarangelo 20-Feb-1993
+//
+// Environment:
+//
+// Kernel mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksalpha.h"
+
+ SBTTL("Set High Wait Low Thread")
+//++
+//
+// NTSTATUS
+// XySetHighWaitLowThread (
+// )
+//
+// Routine Description:
+//
+// This function calls the fast evnet pair system service.
+//
+// N.B. The return from this routine is directly to the caller.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// STATUS_NO_EVENT_PAIR is returned if no event pair is associated with
+// the current thread. Otherwise, the status of the wait operation is
+// returned as the function value.
+//
+//
+//--
+
+ LEAF_ENTRY(XySetHighWaitLowThread)
+
+ ldil v0, SET_HIGH_WAIT_LOW // set system service number
+ SYSCALL // call system service
+
+ .end XySetHighWaitLowThread
+
diff --git a/private/csr/server/alpha/sources b/private/csr/server/alpha/sources
new file mode 100644
index 000000000..a04f9d731
--- /dev/null
+++ b/private/csr/server/alpha/sources
@@ -0,0 +1,3 @@
+ALPHA_LNKFLAGS=-stack:98304,8192
+
+ALPHA_SOURCES=alpha\evpair.s
diff --git a/private/csr/server/apiinit.c b/private/csr/server/apiinit.c
new file mode 100644
index 000000000..6e539dbd5
--- /dev/null
+++ b/private/csr/server/apiinit.c
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ apiinit.c
+
+Abstract:
+
+ This module contains the code to initialize the ApiPort of the
+ Server side of the Client-Server Runtime Subsystem to the Session
+ Manager SubSystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+static SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
+
+NTSTATUS
+CsrApiPortInitialize( VOID )
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG i;
+ HANDLE Thread;
+ CLIENT_ID ClientId;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD ServerThread;
+ HANDLE EventHandle;
+ ULONG Length;
+ PSID SeWorldSid;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ PACL Dacl;
+
+ Length = CsrDirectoryName.Length +
+ sizeof( CSR_API_PORT_NAME ) +
+ sizeof( OBJ_NAME_PATH_SEPARATOR );
+ CsrApiPortName.Buffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( INIT_TAG ), Length );
+ if (CsrApiPortName.Buffer == NULL) {
+ return( STATUS_NO_MEMORY );
+ }
+ CsrApiPortName.Length = 0;
+ CsrApiPortName.MaximumLength = (USHORT)Length;
+ RtlAppendUnicodeStringToString( &CsrApiPortName, &CsrDirectoryName );
+ RtlAppendUnicodeToString( &CsrApiPortName, L"\\" );
+ RtlAppendUnicodeToString( &CsrApiPortName, CSR_API_PORT_NAME );
+
+ IF_CSR_DEBUG( INIT ) {
+ DbgPrint( "CSRSS: Creating %wZ port and associated threads\n",
+ &CsrApiPortName );
+ DbgPrint( "CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
+ sizeof( CSR_API_CONNECTINFO ),
+ sizeof( CSR_API_MSG )
+ );
+ }
+
+ //
+ // create a security descriptor that allows all access
+ //
+
+ SeWorldSid = RtlAllocateHeap( CsrHeap, MAKE_TAG( TMP_TAG ), RtlLengthRequiredSid( 1 ) );
+ RtlInitializeSid( SeWorldSid, &WorldSidAuthority, 1 );
+ *(RtlSubAuthoritySid( SeWorldSid, 0 )) = SECURITY_WORLD_RID;
+
+ Length = SECURITY_DESCRIPTOR_MIN_LENGTH +
+ (ULONG)sizeof(ACL) +
+ (ULONG)sizeof(ACCESS_ALLOWED_ACE) +
+ RtlLengthSid( SeWorldSid ) +
+ 8; // The 8 is just for good measure
+ SecurityDescriptor = RtlAllocateHeap( CsrHeap, MAKE_TAG( TMP_TAG ), Length);
+ ASSERT( SecurityDescriptor != NULL );
+
+ Dacl = (PACL)((PCHAR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+ RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
+ RtlCreateAcl( Dacl, Length - SECURITY_DESCRIPTOR_MIN_LENGTH, ACL_REVISION2);
+
+ RtlAddAccessAllowedAce (
+ Dacl,
+ ACL_REVISION2,
+ PORT_ALL_ACCESS,
+ SeWorldSid
+ );
+ RtlSetDaclSecurityDescriptor (
+ SecurityDescriptor,
+ TRUE,
+ Dacl,
+ FALSE
+ );
+
+ InitializeObjectAttributes( &ObjectAttributes, &CsrApiPortName, 0,
+ NULL, SecurityDescriptor );
+ Status = NtCreatePort( &CsrApiPort,
+ &ObjectAttributes,
+ sizeof( CSR_API_CONNECTINFO ),
+ sizeof( CSR_API_MSG ),
+ 4096 * 16
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // clean up security stuff
+ //
+
+ RtlFreeHeap( CsrHeap, 0, SeWorldSid );
+ RtlFreeHeap( CsrHeap, 0, SecurityDescriptor );
+
+ //
+ // use same port for exception handling.
+ //
+
+ CsrExceptionPort = CsrApiPort;
+
+ Status = NtCreateEvent(&EventHandle,
+ EVENT_ALL_ACCESS,
+ NULL,
+ SynchronizationEvent,
+ FALSE
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Create the inital request thread
+ //
+
+ Status = RtlCreateUserThread( NtCurrentProcess(),
+ NULL,
+ TRUE,
+ 0,
+ 0,
+ 0,
+ CsrApiRequestThread,
+ (PVOID)EventHandle,
+ &Thread,
+ &ClientId
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+ CsrAddStaticServerThread(Thread,&ClientId,CSR_STATIC_API_THREAD);
+
+ ListHead = &CsrRootProcess->ThreadList;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ ServerThread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
+ Status = NtResumeThread( ServerThread->ThreadHandle, NULL );
+ if (ServerThread->Flags & CSR_STATIC_API_THREAD) {
+ Status = NtWaitForSingleObject(EventHandle,FALSE,NULL);
+ ASSERT( NT_SUCCESS( Status ) );
+ }
+ ListNext = ListNext->Flink;
+ }
+ NtClose(EventHandle);
+
+
+ return( Status );
+}
+
+HANDLE
+CsrQueryApiPort(VOID)
+{
+ return CsrApiPort;
+}
+
diff --git a/private/csr/server/apilistn.c b/private/csr/server/apilistn.c
new file mode 100644
index 000000000..4e817b5b6
--- /dev/null
+++ b/private/csr/server/apilistn.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ apilistn.c
+
+Abstract:
+
+ This module contains the Listen thread procedure for the Server side
+ of the Client-Server Runtime Subsystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+NTSTATUS
+CsrApiListenThread(
+ IN PVOID Parameter
+ )
+{
+ NTSTATUS Status;
+ CONNECTION_REQUEST ConnectionRequest;
+ CSR_API_CONNECTINFO ConnectionInformation;
+ ULONG ConnectionInformationLength;
+
+ while (TRUE) {
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: Listening for connections to ApiPort\n" );
+ }
+
+ ConnectionInformationLength = sizeof( ConnectionInformation );
+ ConnectionRequest.Length = sizeof( ConnectionRequest );
+ Status = NtListenPort( CsrApiPort,
+ &ConnectionRequest,
+ (PVOID)&ConnectionInformation,
+ &ConnectionInformationLength
+ );
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: Listen failed - Status == %X\n",
+ Status
+ );
+ }
+ break;
+ }
+
+ }
+
+ //
+ // Explicitly terminate this thread if we fail in the listen loop.
+ //
+
+ NtTerminateThread( NtCurrentThread(), Status );
+
+ return( Status ); // Remove no return value warning.
+ Parameter; // Remove unreferenced parameter warning.
+}
diff --git a/private/csr/server/apireqst.c b/private/csr/server/apireqst.c
new file mode 100644
index 000000000..fdfcb51b3
--- /dev/null
+++ b/private/csr/server/apireqst.c
@@ -0,0 +1,1077 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ apireqst.c
+
+Abstract:
+
+ This module contains the Request thread procedure for the Server side
+ of the Client-Server Runtime Subsystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+NTSTATUS
+CsrApiHandleConnectionRequest(
+ IN PCSR_API_MSG Message
+ );
+
+EXCEPTION_DISPOSITION
+CsrUnhandledExceptionFilter(
+ struct _EXCEPTION_POINTERS *ExceptionInfo
+ );
+
+ULONG CsrpDynamicThreadTotal;
+ULONG CsrpStaticThreadCount;
+
+PCSR_THREAD CsrConnectToUser( VOID )
+{
+ static BOOLEAN (*ClientThreadSetupRoutine)(VOID) = NULL;
+ NTSTATUS Status;
+ ANSI_STRING DllName;
+ UNICODE_STRING DllName_U;
+ STRING ProcedureName;
+ HANDLE UserClientModuleHandle;
+ PTEB Teb;
+ PCSR_THREAD Thread;
+ BOOLEAN fConnected;
+
+ if (ClientThreadSetupRoutine == NULL) {
+ RtlInitAnsiString(&DllName, "user32");
+ Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE);
+ ASSERT(NT_SUCCESS(Status));
+ Status = LdrGetDllHandle(
+ UNICODE_NULL,
+ NULL,
+ &DllName_U,
+ (PVOID *)&UserClientModuleHandle
+ );
+
+ RtlFreeUnicodeString(&DllName_U);
+
+ if ( NT_SUCCESS(Status) ) {
+ RtlInitString(&ProcedureName,"ClientThreadSetup");
+ Status = LdrGetProcedureAddress(
+ UserClientModuleHandle,
+ &ProcedureName,
+ 0L,
+ (PVOID *)&ClientThreadSetupRoutine
+ );
+ ASSERT(NT_SUCCESS(Status));
+ }
+ }
+
+ try {
+ fConnected = ClientThreadSetupRoutine();
+ } except (EXCEPTION_EXECUTE_HANDLER) {
+ fConnected = FALSE;
+ }
+ if (!fConnected) {
+ IF_DEBUG {
+ DbgPrint("CSRSS: CsrConnectToUser failed\n");
+ }
+ return NULL;
+ }
+
+ /*
+ * Set up CSR_THREAD pointer in the TEB
+ */
+ Teb = NtCurrentTeb();
+ Thread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
+ if (Thread)
+ Teb->CsrClientThread = Thread;
+
+ return Thread;
+}
+
+NTSTATUS
+CsrpCheckRequestThreads(VOID)
+{
+ //
+ // See if we need to create a new thread for api requests.
+ //
+ // Don't create a thread if we're in the middle of debugger
+ // initialization, which would cause the thread to be
+ // lost to the debugger.
+ //
+ // If we are not a dynamic api request thread, then decrement
+ // the static thread count. If it underflows, then create a temporary
+ // request thread
+ //
+
+ if ( !--CsrpStaticThreadCount && !CsrpServerDebugInitialize ) {
+
+ if ( CsrpDynamicThreadTotal < CsrMaxApiRequestThreads ) {
+
+ HANDLE QuickThread;
+ CLIENT_ID ClientId;
+ NTSTATUS CreateStatus;
+
+ //
+ // If we are ready to create quick threads, then create one
+ //
+
+ CreateStatus = RtlCreateUserThread(
+ NtCurrentProcess(),
+ NULL,
+ TRUE,
+ 0,
+ 0,
+ 0,
+ CsrApiRequestThread,
+ NULL,
+ &QuickThread,
+ &ClientId
+ );
+
+ if ( NT_SUCCESS(CreateStatus) ) {
+ CsrpStaticThreadCount++;
+ CsrpDynamicThreadTotal++;
+ if ( CsrAddStaticServerThread(QuickThread,&ClientId,CSR_STATIC_API_THREAD) ) {
+ NtResumeThread(QuickThread,NULL);
+ }
+ else {
+ CsrpStaticThreadCount--;
+ CsrpDynamicThreadTotal--;
+ NtTerminateThread(QuickThread,0);
+ NtClose(QuickThread);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+NTSTATUS
+CsrApiRequestThread(
+ IN PVOID Parameter
+ )
+{
+ NTSTATUS Status;
+ PCSR_PROCESS Process;
+ PCSR_THREAD Thread;
+ PCSR_THREAD MyThread;
+ CSR_API_MSG ReceiveMsg;
+ PCSR_API_MSG ReplyMsg;
+ HANDLE ReplyPortHandle;
+ PCSR_SERVER_DLL LoadedServerDll;
+ PTEB Teb;
+ ULONG ServerDllIndex;
+ ULONG ApiTableIndex;
+ CSR_REPLY_STATUS ReplyStatus;
+ ULONG i;
+ PVOID PortContext;
+ USHORT MessageType;
+ ULONG ApiNumber;
+ PLPC_CLIENT_DIED_MSG CdMsg;
+
+ Teb = NtCurrentTeb();
+ ReplyMsg = NULL;
+ ReplyPortHandle = CsrApiPort;
+
+// Initialize GDI accelerators. It's really pretty hokey that these are
+// done here, but there's no DLL init called for these threads!
+// (Also see SRVQUICK.C.)
+
+ Teb->GdiClientPID = PID_SERVERLPC;
+ Teb->GdiClientTID = (ULONG) Teb->ClientId.UniqueThread;
+
+ //
+ // Try to connect to USER.
+ //
+
+ while (!CsrConnectToUser()) {
+ LARGE_INTEGER TimeOut;
+
+ //
+ // The connect failed. The best thing to do is sleep for
+ // 30 seconds and retry the connect. Clear the
+ // initialized bit in the TEB so the retry can
+ // succeed.
+ //
+
+ Teb->Win32ClientInfo[0] = 0;
+ TimeOut.QuadPart = Int32x32To64(30000, -10000);
+ NtDelayExecution(FALSE, &TimeOut);
+ }
+ MyThread = Teb->CsrClientThread;
+
+ if ( Parameter ) {
+ Status = NtSetEvent((HANDLE)Parameter,NULL);
+ ASSERT( NT_SUCCESS( Status ) );
+ CsrpStaticThreadCount++;
+ CsrpDynamicThreadTotal++;
+ }
+
+ while (TRUE) {
+ NtCurrentTeb()->RealClientId = NtCurrentTeb()->ClientId;
+#if DBG
+ if ( NtCurrentTeb()->CountOfOwnedCriticalSections != 0 ) {
+ DbgPrint("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n",
+ NtCurrentTeb()->CountOfOwnedCriticalSections
+ );
+ DbgPrint("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n",&ReceiveMsg,ReplyMsg);
+ DbgBreakPoint();
+ }
+
+#endif // DBG
+
+ Status = NtReplyWaitReceivePort( ReplyPortHandle,
+ &PortContext,
+ (PPORT_MESSAGE)ReplyMsg,
+ (PPORT_MESSAGE)&ReceiveMsg
+ );
+ if (Status != 0) {
+ if (NT_SUCCESS( Status )) {
+ continue; // Try again if alerted or a failure
+ }
+
+ IF_DEBUG {
+ if (Status == STATUS_INVALID_CID ||
+ Status == STATUS_UNSUCCESSFUL ||
+ (Status == STATUS_INVALID_HANDLE &&
+ ReplyPortHandle != CsrApiPort
+ )
+ ) {
+ }
+ else {
+ DbgPrint( "CSRSS: ReceivePort failed - Status == %X\n", Status );
+ DbgPrint( "CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPortHandle, CsrApiPort );
+ }
+ }
+
+ //
+ // Ignore if client went away.
+ //
+
+ ReplyMsg = NULL;
+ ReplyPortHandle = CsrApiPort;
+ continue;
+ }
+
+ NtCurrentTeb()->RealClientId = ReceiveMsg.h.ClientId;
+ MessageType = ReceiveMsg.h.u2.s2.Type;
+
+ //
+ // Check to see if this is a connection request and handle
+ //
+
+ if (MessageType == LPC_CONNECTION_REQUEST) {
+ CsrApiHandleConnectionRequest( &ReceiveMsg );
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+
+ //
+ // Check to see if this is a debug message and handle
+ //
+
+ if ( MessageType == LPC_DEBUG_EVENT ) {
+ DbgSsHandleKmApiMsg((PDBGKM_APIMSG)&ReceiveMsg,NULL);
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+
+
+ //
+ // We must acquire the process structure lock before we look up
+ // the API thread.
+ //
+
+ AcquireProcessStructureLock();
+
+ //
+ // Lookup the client thread structure using the client id
+ //
+
+ Thread = CsrLocateThreadByClientId( &Process,
+ &ReceiveMsg.h.ClientId
+ );
+
+ if (!Thread) {
+ ReleaseProcessStructureLock();
+ if ( MessageType == LPC_EXCEPTION ) {
+ ReplyMsg = &ReceiveMsg;
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg->ReturnValue = DBG_CONTINUE;
+ }
+ else
+ if ( MessageType == LPC_CLIENT_DIED ||
+ MessageType == LPC_PORT_CLOSED
+ ) {
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+ else {
+
+ //
+ // This must be a non-csr thread calling us. Tell it
+ // to get lost. (unless this is a hard error)
+ //
+
+ if (MessageType == LPC_ERROR_EVENT) {
+ PHARDERROR_MSG m;
+
+ m = (PHARDERROR_MSG)&ReceiveMsg;
+ m->Response = (ULONG)ResponseNotHandled;
+
+ //
+ // Only call the handler if there are other
+ // request threads available to handle
+ // message processing.
+ //
+
+ if (NT_SUCCESS(CsrpCheckRequestThreads())) {
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->HardErrorRoutine) {
+
+ (*LoadedServerDll->HardErrorRoutine)( Thread,
+ m );
+ if (m->Response != (ULONG)ResponseNotHandled)
+ break;
+ }
+ }
+ ++CsrpStaticThreadCount;
+ }
+
+ if (m->Response == (ULONG)-1) {
+
+ //
+ // Hard error handler will directly reply to the client
+ //
+
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+ else {
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = &ReceiveMsg;
+ }
+
+ }
+ else {
+ ReplyPortHandle = CsrApiPort;
+ if ( MessageType == LPC_REQUEST ) {
+ ReplyMsg = &ReceiveMsg;
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ }
+ else if (MessageType == LPC_DATAGRAM) {
+ //
+ // If this is a datagram, make the api call
+ //
+
+ ApiNumber = ReceiveMsg.ApiNumber;
+ ServerDllIndex =
+ CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber );
+ if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
+ (LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]) == NULL
+ ) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
+ ServerDllIndex, LoadedServerDll
+ );
+ DbgBreakPoint();
+ }
+
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+ else {
+ ApiTableIndex =
+ CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) -
+ LoadedServerDll->ApiNumberBase;
+ if (ApiTableIndex >= LoadedServerDll->MaxApiNumber ) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid ApiTableIndex for %Z\n",
+ LoadedServerDll->ApiNumberBase + ApiTableIndex,
+ &LoadedServerDll->ModuleName
+ );
+ }
+
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+ }
+
+#if DBG
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
+ NtCurrentTeb()->ClientId.UniqueThread,
+ ReceiveMsg.h.ClientId.UniqueProcess,
+ ReceiveMsg.h.ClientId.UniqueThread,
+ LoadedServerDll->ApiNameTable[ ApiTableIndex ],
+ Thread
+ );
+ }
+#endif // DBG
+
+ ReceiveMsg.ReturnValue = (ULONG)STATUS_SUCCESS;
+
+ try {
+
+ CsrpCheckRequestThreads();
+
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+
+ (*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(
+ &ReceiveMsg,
+ &ReplyStatus
+ );
+ ++CsrpStaticThreadCount;
+ }
+ except ( CsrUnhandledExceptionFilter( GetExceptionInformation() ) ){
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+ }
+ else {
+ ReplyMsg = NULL;
+ }
+ }
+ }
+ continue;
+ }
+
+ //
+ // See if this is a client died message. If so,
+ // callout and then teardown thread/process structures.
+ // this is how ExitThread is seen by CSR.
+ //
+ // LPC_CLIENT_DIED is caused by ExitProcess. ExitProcess
+ // calls TerminateProcess, which terminates all of the process's
+ // threads except the caller. this termination generates
+ // LPC_CLIENT_DIED.
+ //
+
+ ReplyPortHandle = CsrApiPort;
+
+ if (MessageType != LPC_REQUEST) {
+
+ if (MessageType == LPC_CLIENT_DIED) {
+
+ CdMsg = (PLPC_CLIENT_DIED_MSG)&ReceiveMsg;
+ if (CdMsg->CreateTime.QuadPart == Thread->CreateTime.QuadPart) {
+ ReplyPortHandle = Thread->Process->ClientPort;
+
+ CsrLockedReferenceThread(Thread);
+ Status = CsrDestroyThread( &ReceiveMsg.h.ClientId );
+
+ //
+ // if this thread is it, then we also need to dereference
+ // the process since it will not be going through the
+ // normal destroy process path.
+ //
+
+ if ( Process->ThreadCount == 1 ) {
+ CsrDestroyProcess(&Thread->ClientId,0);
+ }
+ CsrLockedDereferenceThread(Thread);
+ }
+ ReleaseProcessStructureLock();
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+
+ CsrLockedReferenceThread(Thread);
+ ReleaseProcessStructureLock();
+
+ //
+ // if this is an exception message, terminate the process
+ //
+
+ if (MessageType == LPC_EXCEPTION) {
+ PDBGKM_APIMSG m;
+
+ NtTerminateProcess(Process->ProcessHandle,STATUS_ABANDONED);
+ Status = CsrDestroyProcess( &ReceiveMsg.h.ClientId,STATUS_ABANDONED );
+ m = (PDBGKM_APIMSG)&ReceiveMsg;
+ m->ReturnedStatus = DBG_CONTINUE;
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = &ReceiveMsg;
+ CsrDereferenceThread(Thread);
+ continue;
+ }
+
+ //
+ // If this is a hard error message, return return to caller
+ //
+
+ if (MessageType == LPC_ERROR_EVENT) {
+ PHARDERROR_MSG m;
+
+ m = (PHARDERROR_MSG)&ReceiveMsg;
+ m->Response = (ULONG)ResponseNotHandled;
+
+ //
+ // Only call the handler if there are other
+ // request threads available to handle
+ // message processing.
+ //
+
+ if (NT_SUCCESS(CsrpCheckRequestThreads())) {
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->HardErrorRoutine) {
+
+ (*LoadedServerDll->HardErrorRoutine)( Thread,
+ m );
+ if (m->Response != (ULONG)ResponseNotHandled) {
+ break;
+ }
+ }
+ }
+ ++CsrpStaticThreadCount;
+ }
+
+ if (m->Response == (ULONG)-1) {
+
+ //
+ // Hard error handler will directly reply to the client
+ //
+
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+ else {
+ CsrDereferenceThread(Thread);
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = &ReceiveMsg;
+ }
+ continue;
+ }
+
+ CsrDereferenceThread(Thread);
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ continue;
+ }
+
+ CsrLockedReferenceThread(Thread);
+ ReleaseProcessStructureLock();
+
+ ApiNumber = ReceiveMsg.ApiNumber;
+ ServerDllIndex =
+ CSR_APINUMBER_TO_SERVERDLLINDEX( ApiNumber );
+ if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
+ (LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]) == NULL
+ ) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
+ ServerDllIndex, LoadedServerDll
+ );
+ DbgBreakPoint();
+ }
+
+ ReplyMsg = &ReceiveMsg;
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ CsrDereferenceThread(Thread);
+ continue;
+ }
+ else {
+ ApiTableIndex =
+ CSR_APINUMBER_TO_APITABLEINDEX( ApiNumber ) -
+ LoadedServerDll->ApiNumberBase;
+ if (ApiTableIndex >= LoadedServerDll->MaxApiNumber ) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid ApiTableIndex for %Z\n",
+ LoadedServerDll->ApiNumberBase + ApiTableIndex,
+ &LoadedServerDll->ModuleName
+ );
+ DbgBreakPoint();
+ }
+
+ ReplyMsg = &ReceiveMsg;
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ CsrDereferenceThread(Thread);
+ continue;
+ }
+ }
+
+#if 0//DBG
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
+ NtCurrentTeb()->ClientId.UniqueThread,
+ ReceiveMsg.h.ClientId.UniqueProcess,
+ ReceiveMsg.h.ClientId.UniqueThread,
+ LoadedServerDll->ApiNameTable[ ApiTableIndex ],
+ Thread
+ );
+ }
+#endif // DBG
+
+ ReceiveMsg.ReturnValue = (ULONG)STATUS_SUCCESS;
+ if (ReceiveMsg.CaptureBuffer != NULL) {
+ if (!CsrCaptureArguments( Thread, &ReceiveMsg )) {
+ ReplyPortHandle = Thread->Process->ClientPort;
+ CsrDereferenceThread(Thread);
+ goto failit;
+ }
+ }
+
+ try {
+
+ CsrpCheckRequestThreads();
+
+ Teb->CsrClientThread = (PVOID)Thread;
+
+ ReplyMsg = &ReceiveMsg;
+ ReplyPortHandle = Thread->Process->ClientPort;
+
+ ReplyStatus = CsrReplyImmediate;
+ ReplyMsg->ReturnValue =
+ (*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(
+ &ReceiveMsg,
+ &ReplyStatus
+ );
+ ++CsrpStaticThreadCount;
+
+ Teb->CsrClientThread = (PVOID)MyThread;
+
+ if (ReplyStatus == CsrReplyImmediate) {
+ //
+ // free captured arguments if a capture buffer was allocated
+ // AND we're replying to the message now (no wait block has
+ // been created).
+ //
+
+ if (ReplyMsg && ReceiveMsg.CaptureBuffer != NULL) {
+ CsrReleaseCapturedArguments( &ReceiveMsg );
+ }
+ CsrDereferenceThread(Thread);
+ }
+ else if (ReplyStatus == CsrClientDied) {
+ NtReplyPort( ReplyPortHandle,
+ (PPORT_MESSAGE)ReplyMsg
+ );
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ CsrDereferenceThread(Thread);
+ }
+ else if (ReplyStatus == CsrReplyPending) {
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+ else {
+ if (ReplyMsg && ReceiveMsg.CaptureBuffer != NULL) {
+ CsrReleaseCapturedArguments( &ReceiveMsg );
+ }
+ CsrDereferenceThread(Thread);
+ }
+
+ }
+ except ( CsrUnhandledExceptionFilter( GetExceptionInformation() ) ){
+ ReplyPortHandle = CsrApiPort;
+ ReplyMsg = NULL;
+ }
+failit:
+ ;
+ }
+
+ NtTerminateThread( NtCurrentThread(), Status );
+ return( Status );
+}
+
+NTSTATUS
+CsrCallServerFromServer(
+ PCSR_API_MSG ReceiveMsg,
+ PCSR_API_MSG ReplyMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This function dispatches an API call the same way CsrApiRequestThread
+ does, but it does it as a direct call, not an LPC connect. It is used
+ by the csr dll when the server is calling a dll function. We don't
+ worry about process serialization here because none of the process APIs
+ can be called from the server.
+
+Arguments:
+
+ ReceiveMessage - Pointer to the API request message received.
+
+ ReplyMessage - Pointer to the API request message to return.
+
+Return Value:
+
+ Status Code
+
+--*/
+
+{
+
+ ULONG ServerDllIndex;
+ ULONG ApiTableIndex;
+ PCSR_SERVER_DLL LoadedServerDll;
+ PTEB Teb;
+ CSR_REPLY_STATUS ReplyStatus;
+
+ Teb = NtCurrentTeb();
+ ServerDllIndex =
+ CSR_APINUMBER_TO_SERVERDLLINDEX( ReceiveMsg->ApiNumber );
+ if (ServerDllIndex >= CSR_MAX_SERVER_DLL ||
+ (LoadedServerDll = CsrLoadedServerDll[ ServerDllIndex ]) == NULL
+ ) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
+ ServerDllIndex, LoadedServerDll
+ );
+ // DbgBreakPoint();
+ }
+
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ return STATUS_ILLEGAL_FUNCTION;
+ }
+ else {
+ ApiTableIndex =
+ CSR_APINUMBER_TO_APITABLEINDEX( ReceiveMsg->ApiNumber ) -
+ LoadedServerDll->ApiNumberBase;
+ if (ApiTableIndex >= LoadedServerDll->MaxApiNumber ||
+ (LoadedServerDll->ApiServerValidTable &&
+ !LoadedServerDll->ApiServerValidTable[ ApiTableIndex ])) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an invalid API to call from the server.\n",
+ LoadedServerDll->ApiNumberBase + ApiTableIndex,
+ (LoadedServerDll->ApiNameTable &&
+ LoadedServerDll->ApiNameTable[ ApiTableIndex ]
+ ) ? LoadedServerDll->ApiNameTable[ ApiTableIndex ]
+ : "*** UNKNOWN ***",
+ &LoadedServerDll->ModuleName
+ );
+ DbgBreakPoint();
+ }
+
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ return STATUS_ILLEGAL_FUNCTION;
+ }
+ }
+
+#if 0//DBG
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: %s Api Request received from server process\n",
+ LoadedServerDll->ApiNameTable[ ApiTableIndex ]
+ );
+ }
+#endif // DBG
+ try {
+ ReplyMsg->ReturnValue =
+ (*(LoadedServerDll->ApiDispatchTable[ ApiTableIndex ]))(
+ ReceiveMsg,
+ &ReplyStatus
+ );
+ } except( EXCEPTION_EXECUTE_HANDLER ) {
+ ReplyMsg->ReturnValue = (ULONG)STATUS_ACCESS_VIOLATION;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN
+CsrCaptureArguments(
+ IN PCSR_THREAD t,
+ IN PCSR_API_MSG m
+ )
+{
+ PCSR_CAPTURE_HEADER ClientCaptureBuffer;
+ PCSR_CAPTURE_HEADER ServerCaptureBuffer;
+ PULONG PointerOffsets;
+ ULONG PointerDelta, Length, CountPointers, Pointer;
+
+ try {
+ ClientCaptureBuffer = m->CaptureBuffer;
+ Length = ClientCaptureBuffer->Length;
+ if ((PCH)ClientCaptureBuffer < t->Process->ClientViewBase ||
+ ((PCH)ClientCaptureBuffer + Length) >= t->Process->ClientViewBounds
+ ) {
+ IF_DEBUG {
+ DbgPrint( "*** CSRSS: CaptureBuffer outside of ClientView\n" );
+ DbgBreakPoint();
+ }
+
+ m->ReturnValue = (ULONG)STATUS_INVALID_PARAMETER;
+ return( FALSE );
+ }
+ }
+ except ( EXCEPTION_EXECUTE_HANDLER ) {
+ m->ReturnValue = (ULONG)STATUS_INVALID_PARAMETER;
+ return( FALSE );
+ }
+
+ ServerCaptureBuffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( CAPTURE_TAG ), Length );
+ if (ServerCaptureBuffer == NULL) {
+ m->ReturnValue = (ULONG)STATUS_NO_MEMORY;
+ return( FALSE );
+ }
+
+ RtlMoveMemory( ServerCaptureBuffer, ClientCaptureBuffer, Length );
+ PointerDelta = (ULONG)ServerCaptureBuffer - (ULONG)ClientCaptureBuffer;
+
+ ServerCaptureBuffer->MessagePointerOffsets = (PULONG)
+ ((PCHAR)ServerCaptureBuffer->MessagePointerOffsets + PointerDelta);
+ PointerOffsets = ServerCaptureBuffer->MessagePointerOffsets;
+ CountPointers = ServerCaptureBuffer->CountMessagePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)m;
+ if ((PCH)*(PULONG)Pointer >= t->Process->ClientViewBase &&
+ (PCH)*(PULONG)Pointer < t->Process->ClientViewBounds
+ ) {
+ *(PULONG)Pointer += PointerDelta;
+ }
+ else {
+ IF_DEBUG {
+ DbgPrint( "*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n" );
+ DbgBreakPoint();
+ }
+
+ m->ReturnValue = (ULONG)STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ ServerCaptureBuffer->CapturePointerOffsets = (PULONG)
+ ((PCHAR)ServerCaptureBuffer->CapturePointerOffsets + PointerDelta);
+ PointerOffsets = ServerCaptureBuffer->CapturePointerOffsets;
+ CountPointers = ServerCaptureBuffer->CountCapturePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)ServerCaptureBuffer;
+ if ((PCH)*(PULONG)Pointer >= t->Process->ClientViewBase &&
+ (PCH)*(PULONG)Pointer < t->Process->ClientViewBounds
+ ) {
+ *(PULONG)Pointer += PointerDelta;
+ }
+ else {
+ IF_DEBUG {
+ DbgPrint( "*** CSRSS: CaptureBuffer CapturePointer outside of ClientView\n" );
+ DbgBreakPoint();
+ }
+
+ m->ReturnValue = (ULONG)STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ if (m->ReturnValue != STATUS_SUCCESS) {
+ RtlFreeHeap( CsrHeap, 0, ServerCaptureBuffer );
+ return( FALSE );
+ }
+ else {
+ ServerCaptureBuffer->RelatedCaptureBuffer = ClientCaptureBuffer;
+ m->CaptureBuffer = ServerCaptureBuffer;
+ return( TRUE );
+ }
+}
+
+VOID
+CsrReleaseCapturedArguments(
+ IN PCSR_API_MSG m
+ )
+{
+ PCSR_CAPTURE_HEADER ClientCaptureBuffer;
+ PCSR_CAPTURE_HEADER ServerCaptureBuffer;
+ PULONG PointerOffsets;
+ ULONG PointerDelta, CountPointers, Pointer;
+
+ ServerCaptureBuffer = m->CaptureBuffer;
+ ClientCaptureBuffer = ServerCaptureBuffer->RelatedCaptureBuffer;
+ if (ServerCaptureBuffer == NULL) {
+ return;
+ }
+ ServerCaptureBuffer->RelatedCaptureBuffer = NULL;
+
+ PointerDelta = (ULONG)ClientCaptureBuffer - (ULONG)ServerCaptureBuffer;
+
+ ServerCaptureBuffer->MessagePointerOffsets = (PULONG)
+ ((PCHAR)ServerCaptureBuffer->MessagePointerOffsets + PointerDelta);
+ PointerOffsets = ServerCaptureBuffer->MessagePointerOffsets;
+ CountPointers = ServerCaptureBuffer->CountMessagePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)m;
+ *(PULONG)Pointer += PointerDelta;
+ }
+ }
+
+ ServerCaptureBuffer->CapturePointerOffsets = (PULONG)
+ ((PCHAR)ServerCaptureBuffer->CapturePointerOffsets + PointerDelta);
+ PointerOffsets = ServerCaptureBuffer->CapturePointerOffsets;
+ CountPointers = ServerCaptureBuffer->CountCapturePointers;
+ while (CountPointers--) {
+ Pointer = *PointerOffsets++;
+ if (Pointer != 0) {
+ Pointer += (ULONG)ServerCaptureBuffer;
+ *(PULONG)Pointer += PointerDelta;
+ }
+ }
+
+ RtlMoveMemory( ClientCaptureBuffer,
+ ServerCaptureBuffer,
+ ServerCaptureBuffer->Length
+ );
+
+ RtlFreeHeap( CsrHeap, 0, ServerCaptureBuffer );
+
+ return;
+}
+
+
+
+ULONG
+CsrSrvNullApiCall(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ )
+{
+ PCSR_NULLAPICALL_MSG a = (PCSR_NULLAPICALL_MSG)&m->u.ApiMessageData;
+ ULONG i, j;
+ LONG CountArguments;
+ PCHAR *Arguments;
+
+ CountArguments = a->CountArguments;
+ if (CountArguments > 0) {
+ Arguments = a->Arguments;
+ j = 0;
+ for (i=0; i<(ULONG)CountArguments; i++) {
+ if (Arguments[ i ] != NULL && *Arguments[ i ] != '\0') {
+ j++;
+ }
+ }
+ }
+ else {
+ j = 0;
+ CountArguments = -CountArguments;
+ Arguments = (PCHAR *)(&a->FastArguments[ 0 ]);
+ for (i=0; i<(ULONG)CountArguments; i++) {
+ if (Arguments[ i ]) {
+ j++;
+ }
+ }
+ }
+
+ return( 0 );
+ ReplyStatus; // get rid of unreferenced parameter warning message
+}
+
+
+NTSTATUS
+CsrApiHandleConnectionRequest(
+ IN PCSR_API_MSG Message
+ )
+{
+ NTSTATUS Status;
+ REMOTE_PORT_VIEW ClientView;
+ BOOLEAN AcceptConnection;
+ HANDLE PortHandle;
+ PCSR_PROCESS Process;
+ PCSR_THREAD Thread;
+ PCSR_API_CONNECTINFO ConnectionInformation;
+
+ ConnectionInformation = &Message->ConnectionRequest;
+ AcceptConnection = FALSE;
+
+ AcquireProcessStructureLock();
+ Thread = CsrLocateThreadByClientId( NULL, &Message->h.ClientId );
+ if (Thread != NULL && (Process = Thread->Process) != NULL) {
+ Status = NtDuplicateObject( NtCurrentProcess(),
+ CsrObjectDirectory,
+ Process->ProcessHandle,
+ &ConnectionInformation->ObjectDirectory,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS |
+ DUPLICATE_SAME_ATTRIBUTES
+ );
+ if (NT_SUCCESS( Status )) {
+ Status = CsrSrvAttachSharedSection( Process,
+ ConnectionInformation
+ );
+ if (NT_SUCCESS( Status )) {
+
+#if DBG
+ ConnectionInformation->DebugFlags = CsrDebug;
+#endif
+ AcceptConnection = TRUE;
+ }
+ }
+ }
+
+ ReleaseProcessStructureLock();
+
+ ClientView.Length = sizeof( ClientView );
+ ClientView.ViewSize = 0;
+ ClientView.ViewBase = 0;
+ Status = NtAcceptConnectPort( &PortHandle,
+ AcceptConnection ? (PVOID)Process->SequenceNumber : 0,
+ &Message->h,
+ AcceptConnection,
+ NULL,
+ &ClientView
+ );
+ if (NT_SUCCESS( Status ) && AcceptConnection) {
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: ClientId: %lx.%lx has ClientView: Base=%lx, Size=%lx\n",
+ Message->h.ClientId.UniqueProcess,
+ Message->h.ClientId.UniqueThread,
+ ClientView.ViewBase,
+ ClientView.ViewSize
+ );
+ }
+
+ Process->ClientPort = PortHandle;
+ Process->ClientViewBase = (PCH)ClientView.ViewBase;
+ Process->ClientViewBounds = (PCH)ClientView.ViewBase +
+ ClientView.ViewSize;
+ Status = NtCompleteConnectPort( PortHandle );
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: NtCompleteConnectPort - failed. Status == %X\n",
+ Status
+ );
+ }
+ // FIX, FIX - need to destroy Session
+ }
+ }
+ else {
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: NtAcceptConnectPort - failed. Status == %X\n",
+ Status
+ );
+ }
+ }
+ else {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: Rejecting Connection Request from ClientId: %lx.%lx\n",
+ Message->h.ClientId.UniqueProcess,
+ Message->h.ClientId.UniqueThread
+ );
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/private/csr/server/csrdebug.c b/private/csr/server/csrdebug.c
new file mode 100644
index 000000000..a5ea1c93f
--- /dev/null
+++ b/private/csr/server/csrdebug.c
@@ -0,0 +1,1028 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ csrdebug.c
+
+Abstract:
+
+ This module implements CSR Debug Services.
+
+Author:
+
+ Mark Lucovsky (markl) 02-Apr-1991
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+#include "ntrtl.h"
+#define WIN32_CONSOLE_APP
+#include <windows.h>
+#include <ntsdexts.h>
+
+PCSR_PROCESS CsrDebugProcessPtr;
+BOOLEAN fWin32ServerDebugger = FALSE;
+CLIENT_ID ClientIdWin32ServerDebugger;
+
+PIMAGE_DEBUG_DIRECTORY
+CsrpLocateDebugSection(
+ IN HANDLE ProcessHandle,
+ IN PVOID Base
+ );
+
+NTSTATUS
+CsrDebugProcess(
+ IN ULONG TargetProcessId,
+ IN PCLIENT_ID DebugUserInterface,
+ IN PCSR_ATTACH_COMPLETE_ROUTINE AttachCompleteRoutine
+ )
+{
+
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_PROCESS Process;
+ NTSTATUS Status;
+ BOOLEAN ProcessFound = FALSE;
+ HANDLE ProcessHandle;
+
+ //
+ // only allow CSR debugging if it has not been disabled in the
+ // ntglobalflag
+ //
+
+ if ( TargetProcessId == -1 ) {
+ if (!(RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG)) {
+ KdPrint(( "CSRSRV: CSR Debugging not enabled - NtGlobalFlag == %x\n", RtlGetNtGlobalFlags()));
+ return STATUS_ACCESS_DENIED;
+ }
+ }
+
+ //
+ // Locate the target process
+ //
+
+ AcquireProcessStructureLock();
+
+ ListHead = &CsrRootProcess->ListLink;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Process = CONTAINING_RECORD( ListNext, CSR_PROCESS, ListLink );
+ if (Process->ClientId.UniqueProcess == (HANDLE)TargetProcessId
+ || (TargetProcessId == -1 && CsrDebugProcessPtr == NULL)
+ ) {
+ ProcessFound = TRUE;
+ if ( TargetProcessId == -1 ) {
+
+ CsrpServerDebugInitialize = TRUE;
+
+ Process = CsrInitializeCsrDebugProcess(NULL);
+
+ //
+ // Mark the process as being debugged
+ //
+
+ Process->DebugFlags = CSR_DEBUG_THIS_PROCESS;
+ Process->DebugUserInterface = *DebugUserInterface;
+
+ fWin32ServerDebugger = TRUE;
+ ClientIdWin32ServerDebugger = *DebugUserInterface;
+ }
+ else {
+
+ //
+ // Mark the process as being debugged
+ //
+
+ Process->DebugFlags = CSR_DEBUG_THIS_PROCESS;
+ Process->DebugUserInterface = *DebugUserInterface;
+
+ Process = CsrInitializeCsrDebugProcess(Process);
+ }
+ if ( !Process ) {
+ ReleaseProcessStructureLock();
+ return STATUS_NO_MEMORY;
+ }
+
+ CsrSuspendProcess(Process);
+
+ if ( TargetProcessId != -1 ) {
+
+ //
+ // Process is being debugged, so set up debug port
+ //
+
+ Status = NtSetInformationProcess(
+ Process->ProcessHandle,
+ ProcessDebugPort,
+ (PVOID)&CsrApiPort,
+ sizeof(HANDLE)
+ );
+ if ( !NT_SUCCESS(Status) ){
+ CsrResumeProcess(Process);
+ CsrTeardownCsrDebugProcess(Process);
+ ReleaseProcessStructureLock();
+ return Status;
+ }
+ }
+ else {
+ ProcessHandle = Process->ProcessHandle;
+ }
+
+ break;
+ }
+ ListNext = ListNext->Flink;
+ }
+ ReleaseProcessStructureLock();
+
+ if ( !ProcessFound ) {
+ return( STATUS_UNSUCCESSFUL );
+ }
+
+
+ Status = CsrSendProcessAndThreadEvents(Process,AttachCompleteRoutine);
+ CsrResumeProcess(Process);
+ CsrTeardownCsrDebugProcess(Process);
+
+ CsrpServerDebugInitialize = FALSE;
+
+ if ( NT_SUCCESS(Status) ) {
+ if ( TargetProcessId == -1 ) {
+ NtSetInformationProcess(
+ ProcessHandle,
+ ProcessDebugPort,
+ (PVOID)&CsrSmApiPort,
+ sizeof(HANDLE)
+ );
+ NtClose(ProcessHandle);
+ DbgBreakPoint();
+ }
+ }
+ return Status;
+}
+
+
+NTSTATUS
+CsrSendProcessAndThreadEvents(
+ IN PCSR_PROCESS Process,
+ IN PCSR_ATTACH_COMPLETE_ROUTINE AttachCompleteRoutine
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure sends the create process and create thread
+ debug events to the debug subsystem.
+
+Arguments:
+
+ Process - Supplies the address of the process being debugged.
+
+ AttachCompleteRoutine - Supplies the address of the function in the
+ clients address space that is remote called to cause entry into
+ the debugger.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PPEB Peb;
+ NTSTATUS Status;
+ PROCESS_BASIC_INFORMATION BasicInfo;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ LDR_DATA_TABLE_ENTRY LdrEntryData;
+ PLIST_ENTRY LdrHead,LdrNext;
+ PPEB_LDR_DATA Ldr;
+ PLIST_ENTRY ThreadListHead, ThreadListNext;
+ PCSR_THREAD Thread, FirstThread;
+ DBGKM_APIMSG m;
+ PDBGKM_CREATE_THREAD CreateThreadArgs;
+ PDBGKM_CREATE_PROCESS CreateProcessArgs;
+ PDBGKM_LOAD_DLL LoadDllArgs;
+ PVOID ImageBaseAddress;
+ HANDLE ReplyEvent;
+
+ Status = NtCreateEvent(
+ &ReplyEvent,
+ EVENT_ALL_ACCESS,
+ NULL,
+ SynchronizationEvent,
+ FALSE
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ return Status;
+ }
+
+ Status = NtQueryInformationProcess(
+ Process->ProcessHandle,
+ ProcessBasicInformation,
+ &BasicInfo,
+ sizeof(BasicInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+
+ Peb = BasicInfo.PebBaseAddress;
+
+ //
+ // Ldr = Peb->Ldr
+ //
+
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ &Peb->Ldr,
+ &Ldr,
+ sizeof(Ldr),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+
+ LdrHead = &Ldr->InLoadOrderModuleList;
+
+ //
+ // LdrNext = Head->Flink;
+ //
+
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ &LdrHead->Flink,
+ &LdrNext,
+ sizeof(LdrNext),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+
+ if ( LdrNext != LdrHead ) {
+
+ //
+ // This is the entry data for the image.
+ //
+
+ LdrEntry = CONTAINING_RECORD(LdrNext,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ LdrEntry,
+ &LdrEntryData,
+ sizeof(LdrEntryData),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ &Peb->ImageBaseAddress,
+ &ImageBaseAddress,
+ sizeof(ImageBaseAddress),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+
+ LdrNext = LdrEntryData.InLoadOrderLinks.Flink;
+
+ }
+ else {
+ LdrEntry = NULL;
+ }
+
+ FirstThread = NULL;
+
+ ThreadListHead = &Process->ThreadList;
+ ThreadListNext = ThreadListHead->Flink;
+ while (ThreadListNext != ThreadListHead) {
+ Thread = CONTAINING_RECORD( ThreadListNext, CSR_THREAD, Link );
+
+ if ( !FirstThread ) {
+ FirstThread = Thread;
+
+ //
+ // Send the CreateProcess Message
+ //
+
+ CreateThreadArgs = &m.u.CreateProcessInfo.InitialThread;
+ CreateThreadArgs->SubSystemKey = 0;
+
+ CreateProcessArgs = &m.u.CreateProcessInfo;
+ CreateProcessArgs->SubSystemKey = 0;
+
+ CsrComputeImageInformation(
+ Process,
+ &LdrEntryData,
+ &CreateProcessArgs->BaseOfImage,
+ &CreateProcessArgs->DebugInfoFileOffset,
+ &CreateProcessArgs->DebugInfoSize
+ );
+
+ CsrOpenLdrEntry(
+ FirstThread,
+ Process,
+ &LdrEntryData,
+ &CreateProcessArgs->FileHandle
+ );
+
+ CreateThreadArgs->StartAddress = NULL;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmCreateProcessApi,sizeof(*CreateProcessArgs));
+
+ m.h.ClientId = Thread->ClientId;
+ DbgSsHandleKmApiMsg(&m,ReplyEvent);
+ Status = NtWaitForSingleObject(ReplyEvent,FALSE,NULL);
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+ }
+ else {
+
+ //
+ // Send the CreateThread Message
+ //
+
+ CreateThreadArgs = &m.u.CreateThread;
+ CreateThreadArgs->SubSystemKey = 0;
+ CreateThreadArgs->StartAddress = NULL;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmCreateThreadApi,sizeof(*CreateThreadArgs));
+
+ m.h.ClientId = Thread->ClientId;
+
+ DbgSsHandleKmApiMsg(&m,ReplyEvent);
+ Status = NtWaitForSingleObject(ReplyEvent,FALSE,NULL);
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+ }
+ ThreadListNext = ThreadListNext->Flink;
+ }
+
+ //
+ // Send all of the load module messages
+ //
+
+ while ( LdrNext != LdrHead ) {
+ LdrEntry = CONTAINING_RECORD(LdrNext,LDR_DATA_TABLE_ENTRY,InLoadOrderLinks);
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ LdrEntry,
+ &LdrEntryData,
+ sizeof(LdrEntryData),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+
+ LoadDllArgs = &m.u.LoadDll;
+
+ CsrComputeImageInformation(
+ Process,
+ &LdrEntryData,
+ &LoadDllArgs->BaseOfDll,
+ &LoadDllArgs->DebugInfoFileOffset,
+ &LoadDllArgs->DebugInfoSize
+ );
+
+ CsrOpenLdrEntry(
+ FirstThread,
+ Process,
+ &LdrEntryData,
+ &LoadDllArgs->FileHandle
+ );
+ if ( LoadDllArgs->FileHandle ) {
+ DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs));
+ m.h.ClientId = FirstThread->ClientId;
+ DbgSsHandleKmApiMsg(&m,ReplyEvent);
+ Status = NtWaitForSingleObject(ReplyEvent,FALSE,NULL);
+ if ( !NT_SUCCESS(Status) ) {
+ goto bail;
+ }
+ }
+
+ LdrNext = LdrEntryData.InLoadOrderLinks.Flink;
+ }
+bail:
+ NtClose(ReplyEvent);
+ return Status;
+}
+
+VOID
+CsrComputeImageInformation(
+ IN PCSR_PROCESS Process,
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ OUT PVOID *BaseOfImage,
+ OUT PULONG DebugInfoFileOffset,
+ OUT PULONG DebugInfoSize
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to compute the image base and
+ debug information from a ldr entry.
+
+Arguments:
+
+ Process - Supplies the address of the process whose context this
+ information is to be calculated from.
+
+ LdrEntry - Supplies the address of the loader data table entry
+ whose info is being computed relative to. This pointer is
+ valid in the callers (current) context.
+
+ BaseOfImage - Returns the image's base.
+
+ DebugInfoFileOffset - Returns the offset of the debug info.
+
+ DebugInfoSize - Returns the size of the debug info.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PIMAGE_DEBUG_DIRECTORY pDebugDir;
+ IMAGE_DEBUG_DIRECTORY DebugDir;
+ IMAGE_COFF_SYMBOLS_HEADER DebugInfo;
+ NTSTATUS Status;
+
+ *BaseOfImage = LdrEntry->DllBase;
+
+ pDebugDir = CsrpLocateDebugSection(
+ Process->ProcessHandle,
+ LdrEntry->DllBase
+ );
+
+ *DebugInfoFileOffset = 0;
+ *DebugInfoSize = 0;
+ if ( pDebugDir ) {
+
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ pDebugDir,
+ &DebugDir,
+ sizeof(IMAGE_DEBUG_DIRECTORY),
+ NULL
+ );
+
+ if ( !NT_SUCCESS(Status) ) {
+ return;
+ }
+
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ (PVOID)((ULONG)LdrEntry->DllBase + DebugDir.AddressOfRawData),
+ &DebugInfo,
+ sizeof(IMAGE_COFF_SYMBOLS_HEADER),
+ NULL
+ );
+
+ if ( !NT_SUCCESS(Status) ) {
+ return;
+ }
+
+ *DebugInfoFileOffset = DebugDir.PointerToRawData + DebugInfo.LvaToFirstSymbol;
+ *DebugInfoSize = DebugInfo.NumberOfSymbols;
+ }
+ else {
+ *DebugInfoFileOffset = 0;
+ *DebugInfoSize = 0;
+ }
+}
+
+PIMAGE_DEBUG_DIRECTORY
+CsrpLocateDebugSection(
+ IN HANDLE ProcessHandle,
+ IN PVOID Base
+ )
+
+{
+ PVOID ImageHeaderRawData;
+ PIMAGE_DOS_HEADER DosHeaderRawData;
+ PIMAGE_NT_HEADERS NtHeaders;
+ ULONG AllocSize, Addr;
+ NTSTATUS Status;
+
+ //
+ // Allocate a buffer, and read the image header from the
+ // target process
+ //
+
+ DosHeaderRawData = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ),
+ sizeof(IMAGE_DOS_HEADER));
+
+ if ( !DosHeaderRawData ) {
+ return NULL;
+ }
+
+ Status = NtReadVirtualMemory(
+ ProcessHandle,
+ Base,
+ DosHeaderRawData,
+ sizeof(IMAGE_DOS_HEADER),
+ NULL
+ );
+
+ AllocSize = DosHeaderRawData->e_lfanew + sizeof(IMAGE_NT_HEADERS);
+ RtlFreeHeap(RtlProcessHeap(), 0, DosHeaderRawData);
+
+ if ( !NT_SUCCESS(Status) ) {
+ return NULL;
+ }
+
+ ImageHeaderRawData = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), AllocSize);
+ if ( !ImageHeaderRawData ) {
+ return NULL;
+ }
+ Status = NtReadVirtualMemory(
+ ProcessHandle,
+ Base,
+ ImageHeaderRawData,
+ AllocSize,
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ){
+ RtlFreeHeap(RtlProcessHeap(),0,ImageHeaderRawData);
+ return NULL;
+ }
+
+ NtHeaders = RtlImageNtHeader(ImageHeaderRawData);
+ if ( NtHeaders ) {
+ Addr = (ULONG)NtHeaders->OptionalHeader.DataDirectory
+ [IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+
+ if ( Addr ) {
+ Addr += (ULONG)Base;
+ }
+ }
+ else {
+ Addr = 0;
+ }
+
+ RtlFreeHeap(RtlProcessHeap(),0,ImageHeaderRawData);
+ return((PIMAGE_DEBUG_DIRECTORY)Addr);
+}
+
+VOID
+CsrOpenLdrEntry(
+ IN PCSR_THREAD Thread,
+ IN PCSR_PROCESS Process,
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ OUT PHANDLE FileHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This function opens a handle to the image/dll file described
+ by the ldr entry in the context of the specified process.
+
+Arguments:
+
+ Thread - Supplies the address of the first thread in the process
+
+ Process - Supplies the address of the process whose context this
+ file is to be opened in.
+
+ LdrEntry - Supplies the address of the loader data table entry
+ whose file is to be opened.
+
+ FileHandle - Returns a handle to the associated file
+ valid in the context of the process being attached to.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UNICODE_STRING DosName;
+ UNICODE_STRING FileName;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES Obja;
+ HANDLE LocalHandle;
+ IO_STATUS_BLOCK IoStatusBlock;
+ BOOLEAN TranslationStatus;
+ NTSTATUS ImpersonationStatus;
+ HANDLE NewToken;
+
+ *FileHandle = NULL;
+ DosName.Length = LdrEntry->FullDllName.Length;
+ DosName.MaximumLength = LdrEntry->FullDllName.MaximumLength;
+ DosName.Buffer = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TMP_TAG ), DosName.MaximumLength);
+ if ( !DosName.Buffer ) {
+ return;
+ }
+
+ Status = NtReadVirtualMemory(
+ Process->ProcessHandle,
+ LdrEntry->FullDllName.Buffer,
+ DosName.Buffer,
+ DosName.MaximumLength,
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ RtlFreeHeap(RtlProcessHeap(),0,DosName.Buffer);
+ return;
+ }
+
+ //
+ // special case CSR
+ //
+ if ( RtlDetermineDosPathNameType_U(DosName.Buffer) == RtlPathTypeRooted ) {
+ InitializeObjectAttributes(
+ &Obja,
+ &DosName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = NtOpenFile(
+ &LocalHandle,
+ (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+
+ RtlFreeHeap(RtlProcessHeap(),0,DosName.Buffer);
+ if ( !NT_SUCCESS(Status) ) {
+ return;
+ }
+
+ //
+ // The file is open in our context. Dup this to target processes context
+ // so that dbgss can dup it to the user interface
+ //
+
+ Status = NtDuplicateObject(
+ NtCurrentProcess(),
+ LocalHandle,
+ Process->ProcessHandle,
+ FileHandle,
+ 0L,
+ 0L,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES |
+ DUPLICATE_CLOSE_SOURCE
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ *FileHandle = NULL;
+ }
+ return;
+ }
+
+ TranslationStatus = RtlDosPathNameToNtPathName_U(
+ DosName.Buffer,
+ &FileName,
+ NULL,
+ NULL
+ );
+
+ if ( !TranslationStatus ) {
+ RtlFreeHeap(RtlProcessHeap(),0,DosName.Buffer);
+ return;
+ }
+
+ InitializeObjectAttributes(
+ &Obja,
+ &FileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = NtOpenFile(
+ &LocalHandle,
+ (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+ if ( !NT_SUCCESS(Status) && Thread ) {
+ ImpersonationStatus = NtImpersonateThread(
+ NtCurrentThread(),
+ Thread->ThreadHandle,
+ &CsrSecurityQos
+ );
+ if ( NT_SUCCESS(ImpersonationStatus) ) {
+ Status = NtOpenFile(
+ &LocalHandle,
+ (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+
+ NewToken = NULL;
+ ImpersonationStatus = NtSetInformationThread(
+ NtCurrentThread(),
+ ThreadImpersonationToken,
+ (PVOID)&NewToken,
+ (ULONG)sizeof(HANDLE)
+ );
+ ASSERT( NT_SUCCESS(ImpersonationStatus) );
+ }
+ }
+ RtlFreeHeap(RtlProcessHeap(),0,DosName.Buffer);
+ RtlFreeHeap(RtlProcessHeap(),0,FileName.Buffer);
+ if ( !NT_SUCCESS(Status) ) {
+ return;
+ }
+
+ //
+ // The file is open in our context. Dup this to target processes context
+ // so that dbgss can dup it to the user interface
+ //
+
+ Status = NtDuplicateObject(
+ NtCurrentProcess(),
+ LocalHandle,
+ Process->ProcessHandle,
+ FileHandle,
+ 0L,
+ 0L,
+ DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES |
+ DUPLICATE_CLOSE_SOURCE
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ *FileHandle = NULL;
+ return;
+ }
+}
+
+
+VOID
+CsrSuspendProcess(
+ IN PCSR_PROCESS Process
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure is called when doing a debug attach to suspend all
+ threads within the effected process.
+
+Arguments:
+
+ Process - Supplies the address of the process to suspend.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD Thread;
+ NTSTATUS Status;
+
+ if ( Process == CsrDebugProcessPtr ) {
+ return;
+ }
+
+ //
+ // Now walk through the processes thread list and
+ // suspend all of its threads.
+ //
+
+ ListHead = &Process->ThreadList;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
+ NtSuspendThread(Thread->ThreadHandle,NULL);
+ ListNext = ListNext->Flink;
+ }
+}
+
+
+VOID
+CsrResumeProcess(
+ IN PCSR_PROCESS Process
+ )
+
+/*++
+
+Routine Description:
+
+ This procedure is called when doing a debug attach to resume all
+ threads within the effected process.
+
+Arguments:
+
+ Process - Supplies the address of the process to resume.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD Thread;
+ NTSTATUS Status;
+
+ if ( Process == CsrDebugProcessPtr ) {
+ return;
+ }
+
+ //
+ // Now walk through the processes thread list and
+ // suspend all of its threads.
+ //
+
+ ListHead = &Process->ThreadList;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
+ NtResumeThread(Thread->ThreadHandle,NULL);
+ ListNext = ListNext->Flink;
+ }
+}
+
+PCSR_PROCESS
+CsrInitializeCsrDebugProcess(
+ PCSR_PROCESS TargetProcess
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to build a side process tree to use when
+ doing debug attaches.
+
+ After the attach completes, this structure is torn down.
+
+Arguments:
+
+ Process - Supplies the address of the process to attach to. A value of
+ NULL indicates CSR.
+
+Return Value:
+
+ Returns the address of the dummy CSR process.
+
+--*/
+
+{
+ PCSR_PROCESS Process;
+ OBJECT_ATTRIBUTES Obja;
+ PCSR_THREAD Thread;
+ PLIST_ENTRY ProcessListHead, ProcessListNext;
+ PLIST_ENTRY ThreadListHead, ThreadListNext;
+ PCSR_THREAD ThreadPtr;
+ PCSR_PROCESS ProcessPtr;
+ THREAD_BASIC_INFORMATION BasicInfo;
+ NTSTATUS Status;
+ PCSR_THREAD ServerThread;
+
+ Process = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( PROCESS_TAG ),sizeof(*Process));
+ if (!Process) {
+ return NULL;
+ }
+
+ if ( TargetProcess == NULL ) {
+ CsrDebugProcessPtr = Process;
+ InitializeListHead(&Process->ThreadList);
+ Process->ClientId = NtCurrentTeb()->ClientId;
+
+ InitializeObjectAttributes(
+ &Obja,
+ NULL,
+ 0,
+ NULL,
+ NULL
+ );
+ Status = NtOpenProcess(
+ &Process->ProcessHandle,
+ PROCESS_ALL_ACCESS,
+ &Obja,
+ &Process->ClientId
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ RtlFreeHeap(RtlProcessHeap(),0,Process);
+ return NULL;
+ }
+
+ //
+ // Compute the threads. This is cumbersome. First we have to
+ // locate the static threads, then walk through the entire structure
+ // looking for threads with associated server threads.
+ //
+
+ ThreadListHead = &CsrRootProcess->ThreadList;
+ ThreadListNext = ThreadListHead->Flink;
+ while (ThreadListNext != ThreadListHead) {
+ ServerThread = CONTAINING_RECORD( ThreadListNext, CSR_THREAD, Link );
+ Thread = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( PROCESS_TAG ),sizeof(*Thread));
+ if ( Thread ) {
+ Thread->ClientId = ServerThread->ClientId;
+ Thread->ThreadHandle = ServerThread->ThreadHandle;
+ InsertTailList( &Process->ThreadList, &Thread->Link );
+ }
+ ThreadListNext = ThreadListNext->Flink;
+ }
+
+ }
+ else {
+
+ //
+ // Regular non-csr process attach... Just copy the thread and
+ // process to a new set of structures
+ //
+
+ InitializeListHead(&Process->ThreadList);
+ Process->ClientId = TargetProcess->ClientId;
+ Process->ProcessHandle = TargetProcess->ProcessHandle;
+
+ ThreadListHead = &TargetProcess->ThreadList;
+ ThreadListNext = ThreadListHead->Flink;
+ while (ThreadListNext != ThreadListHead) {
+ ThreadPtr = CONTAINING_RECORD( ThreadListNext, CSR_THREAD, Link );
+ Thread = RtlAllocateHeap(RtlProcessHeap(),MAKE_TAG( PROCESS_TAG ),sizeof(*Thread));
+ if ( Thread ) {
+ Thread->ThreadHandle = ThreadPtr->ThreadHandle;
+ Thread->ClientId = ThreadPtr->ClientId;
+ InsertTailList( &Process->ThreadList, &Thread->Link );
+ }
+ ThreadListNext = ThreadListNext->Flink;
+ }
+ }
+ return Process;
+}
+
+VOID
+CsrTeardownCsrDebugProcess(
+ PCSR_PROCESS TargetProcess
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called after a debug attach to
+ a process is complete
+
+ It's purpose is to tear down the structure created in the
+ initialization phase.
+
+Arguments:
+
+ TargetProcess - Supplies the address of the process to teardown.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCSR_PROCESS Process;
+ PLIST_ENTRY ThreadListHead, ThreadListNext;
+ PCSR_THREAD ThreadPtr;
+ NTSTATUS Status;
+
+ if ( TargetProcess == CsrDebugProcessPtr ) {
+ CsrDebugProcessPtr = (PCSR_PROCESS)-1;
+ }
+ Process = TargetProcess;
+
+
+ ThreadListHead = &Process->ThreadList;
+ ThreadListNext = ThreadListHead->Flink;
+ while (ThreadListNext != ThreadListHead) {
+ ThreadPtr = CONTAINING_RECORD( ThreadListNext, CSR_THREAD, Link );
+ ThreadListNext = ThreadListNext->Flink;
+ RemoveEntryList(&ThreadPtr->Link);
+ RtlFreeHeap(RtlProcessHeap(),0,ThreadPtr);
+ }
+
+ RtlFreeHeap(RtlProcessHeap(),0,Process);
+}
diff --git a/private/csr/server/csrsrv.h b/private/csr/server/csrsrv.h
new file mode 100644
index 000000000..b3adefafd
--- /dev/null
+++ b/private/csr/server/csrsrv.h
@@ -0,0 +1,603 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ csrsrv.h
+
+Abstract:
+
+ Main include file for Server side of the Client Server Runtime (CSR)
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+//
+// Include definitions common between the Client and Server portions.
+//
+
+#include "csr.h"
+
+//
+// Include definitions specific to the Server portion.
+//
+
+#include "ntcsrsrv.h"
+#include "ntdbg.h"
+
+//
+// Define debugging flags and macro for testing them. All debug code
+// should be contained within a IF_CSR_DEBUG macro call so that when
+// the system is compiled with debug code disabled, none of the code
+// is generated.
+//
+
+#if DBG
+#define CSR_DEBUG_INIT 0x00000001
+#define CSR_DEBUG_LPC 0x00000002
+#define CSR_DEBUG_FLAG3 0x00000004
+#define CSR_DEBUG_FLAG4 0x00000008
+#define CSR_DEBUG_FLAG5 0x00000010
+#define CSR_DEBUG_FLAG6 0x00000020
+#define CSR_DEBUG_FLAG7 0x00000040
+#define CSR_DEBUG_FLAG8 0x00000080
+#define CSR_DEBUG_FLAG9 0x00000100
+#define CSR_DEBUG_FLAG10 0x00000200
+#define CSR_DEBUG_FLAG11 0x00000400
+#define CSR_DEBUG_FLAG12 0x00000800
+#define CSR_DEBUG_FLAG13 0x00001000
+#define CSR_DEBUG_FLAG14 0x00002000
+#define CSR_DEBUG_FLAG15 0x00004000
+#define CSR_DEBUG_FLAG16 0x00008000
+#define CSR_DEBUG_FLAG17 0x00010000
+#define CSR_DEBUG_FLAG18 0x00020000
+#define CSR_DEBUG_FLAG19 0x00040000
+#define CSR_DEBUG_FLAG20 0x00080000
+#define CSR_DEBUG_FLAG21 0x00100000
+#define CSR_DEBUG_FLAG22 0x00200000
+#define CSR_DEBUG_FLAG23 0x00400000
+#define CSR_DEBUG_FLAG24 0x00800000
+#define CSR_DEBUG_FLAG25 0x01000000
+#define CSR_DEBUG_FLAG26 0x02000000
+#define CSR_DEBUG_FLAG27 0x04000000
+#define CSR_DEBUG_FLAG28 0x08000000
+#define CSR_DEBUG_FLAG29 0x10000000
+#define CSR_DEBUG_FLAG30 0x20000000
+#define CSR_DEBUG_FLAG31 0x40000000
+#define CSR_DEBUG_FLAG32 0x80000000
+
+ULONG CsrDebug;
+
+#define IF_CSR_DEBUG( ComponentFlag ) \
+ if (CsrDebug & (CSR_DEBUG_ ## ComponentFlag))
+
+
+#else
+#define IF_CSR_DEBUG( ComponentFlag ) if (FALSE)
+
+#endif
+
+#if DBG
+
+#define CSRSS_PROTECT_HANDLES 1
+
+BOOLEAN
+ProtectHandle(
+ HANDLE hObject
+ );
+
+BOOLEAN
+UnProtectHandle(
+ HANDLE hObject
+ );
+
+#else
+
+#define CSRSS_PROTECT_HANDLES 0
+
+#define ProtectHandle( hObject )
+#define UnProtectHandle( hObject )
+
+#endif
+
+
+BOOLEAN CsrProfileControl;
+
+//
+// Event indicating the csr server has completed initialization.
+//
+
+HANDLE CsrInitializationEvent;
+
+//
+// Include NT Session Manager and Debug SubSystem Interfaces
+
+#include <ntsm.h>
+#include <ntdbg.h>
+typedef BOOLEAN (*PSB_API_ROUTINE)( IN PSBAPIMSG SbApiMsg );
+
+//
+// Global data accessed by Client-Server Runtime Server
+//
+
+ULONG CsrSubSystemType;
+
+#if DBG
+ULONG CsrDebugFlag;
+#endif // DBG
+
+PVOID CsrHeap;
+
+HANDLE CsrObjectDirectory;
+
+#define CSR_SBAPI_PORT_NAME L"SbApiPort"
+
+UNICODE_STRING CsrDirectoryName;
+UNICODE_STRING CsrApiPortName;
+UNICODE_STRING CsrSbApiPortName;
+
+HANDLE CsrApiPort;
+HANDLE CsrSbApiPort;
+HANDLE CsrSmApiPort;
+HANDLE CsrExceptionPort;
+
+ULONG CsrMaxApiRequestThreads;
+BOOLEAN CsrpServerDebugInitialize;
+
+#define CSR_MAX_THREADS 16
+
+#define CSR_STATIC_API_THREAD 0x00000010
+
+PCSR_THREAD CsrSbApiRequestThreadPtr;
+
+LIST_ENTRY CsrZombieThreadList;
+
+//
+// GDI PID codes. (See WINGDIP.H)
+//
+
+#define PID_PUBLIC 0
+#define PID_CURRENT 1
+#define PID_NOOWNER 2
+#define PID_TERMINATION 3
+#define PID_SERVERLPC 4
+
+#define FIRST_SEQUENCE_COUNT 5
+
+//
+// Routines defined in srvinit.c
+//
+
+//
+// The CsrNtSysInfo global variable contains NT specific constants of
+// interest, such as page size, allocation granularity, etc. It is filled
+// in once during process initialization.
+//
+
+SYSTEM_BASIC_INFORMATION CsrNtSysInfo;
+
+#define ROUND_UP_TO_PAGES(SIZE) (((ULONG)(SIZE) + CsrNtSysInfo.PageSize - 1) & ~(CsrNtSysInfo.PageSize - 1))
+#define ROUND_DOWN_TO_PAGES(SIZE) (((ULONG)(SIZE)) & ~(CsrNtSysInfo.PageSize - 1))
+
+#define QUAD_ALIGN(VALUE) ( ((ULONG)(VALUE) + 7) & ~7 )
+
+NTSTATUS
+CsrParseServerCommandLine(
+ IN ULONG argc,
+ IN PCH argv[]
+ );
+
+NTSTATUS
+CsrServerDllInitialization(
+ IN PCSR_SERVER_DLL LoadedServerDll
+ );
+
+NTSTATUS
+CsrSrvProfileControl(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ );
+
+NTSTATUS
+CsrEnablePrivileges(
+ VOID
+ );
+
+
+//
+// Routines define in srvdebug.c
+//
+
+#if DBG
+
+#else
+
+#endif // DBG
+
+
+
+//
+// Routines defined in sbinit.c
+//
+
+NTSTATUS
+CsrSbApiPortInitialize( VOID );
+
+
+VOID
+CsrSbApiPortTerminate(
+ NTSTATUS Status
+ );
+
+//
+// Routines defined in sbreqst.c
+//
+
+NTSTATUS
+CsrSbApiRequestThread(
+ IN PVOID Parameter
+ );
+
+//
+// Routines defined in sbapi.c
+//
+
+BOOLEAN
+CsrSbCreateSession(
+ IN PSBAPIMSG Msg
+ );
+
+BOOLEAN
+CsrSbTerminateSession(
+ IN PSBAPIMSG Msg
+ );
+
+BOOLEAN
+CsrSbForeignSessionComplete(
+ IN PSBAPIMSG Msg
+ );
+
+//
+// Routines defined in session.c
+//
+
+RTL_CRITICAL_SECTION CsrNtSessionLock;
+LIST_ENTRY CsrNtSessionList;
+
+#define LockNtSessionList() RtlEnterCriticalSection( &CsrNtSessionLock )
+#define UnlockNtSessionList() RtlLeaveCriticalSection( &CsrNtSessionLock )
+
+NTSTATUS
+CsrInitializeNtSessionList( VOID );
+
+PCSR_NT_SESSION
+CsrAllocateNtSession(
+ ULONG SessionId
+ );
+
+VOID
+CsrReferenceNtSession(
+ PCSR_NT_SESSION Session
+ );
+
+VOID
+CsrDereferenceNtSession(
+ PCSR_NT_SESSION Session,
+ NTSTATUS ExitStatus
+ );
+
+
+//
+// Routines defined in apiinit.c
+//
+
+NTSTATUS
+CsrApiPortInitialize( VOID );
+
+
+//
+// Routines defined in apireqst.c
+//
+
+NTSTATUS
+CsrApiRequestThread(
+ IN PVOID Parameter
+ );
+
+BOOLEAN
+CsrCaptureArguments(
+ IN PCSR_THREAD t,
+ IN PCSR_API_MSG m
+ );
+
+VOID
+CsrReleaseCapturedArguments(
+ IN PCSR_API_MSG m
+ );
+
+ULONG
+CsrSrvNullApiCall(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ );
+
+
+//
+// Routines and data defined in srvloadr.c
+//
+
+#define CSR_MAX_SERVER_DLL 16
+
+PCSR_SERVER_DLL CsrLoadedServerDll[ CSR_MAX_SERVER_DLL ];
+
+ULONG CsrTotalPerProcessDataLength;
+ULONG CsrTotalPerThreadDataLength;
+HANDLE CsrSrvSharedSection;
+ULONG CsrSrvSharedSectionSize;
+PVOID CsrSrvSharedSectionBase;
+PVOID CsrSrvSharedSectionHeap;
+PVOID *CsrSrvSharedStaticServerData;
+
+NTSTATUS
+CsrLoadServerDll(
+ IN PCH ModuleName,
+ IN PCH InitRoutineString,
+ IN ULONG ServerDllIndex
+ );
+
+ULONG
+CsrSrvClientConnect(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ );
+
+
+NTSTATUS
+CsrSrvCreateSharedSection(
+ IN PCH SizeParameter
+ );
+
+
+NTSTATUS
+CsrSrvAttachSharedSection(
+ IN PCSR_PROCESS Process OPTIONAL,
+ OUT PCSR_API_CONNECTINFO p
+ );
+
+//
+// Routines and data defined in process.c
+//
+
+//
+// The CsrProcessStructureLock critical section protects all of the link
+// fields of the Windows Process objects. You must own this lock to examine
+// or modify any of the following fields of the CSR_PROCESS structure:
+//
+// ListLink
+//
+// It also protects the following variables:
+//
+// CsrRootProcess
+//
+
+RTL_CRITICAL_SECTION CsrProcessStructureLock;
+#define AcquireProcessStructureLock() RtlEnterCriticalSection( &CsrProcessStructureLock )
+#define ReleaseProcessStructureLock() RtlLeaveCriticalSection( &CsrProcessStructureLock )
+
+//
+// The following is a dummy process that acts as the root of the Windows Process
+// Structure. It has a ClientId of -1.-1 so it does not conflict with actual
+// Windows Processes. All processes created via the session manager are children
+// of this process, as are all orphaned processes. The ListLink field of this
+// process is the head of a list of all Windows Processes.
+//
+
+PCSR_PROCESS CsrRootProcess;
+
+//
+// reference/dereference thread are public in ntcsrsrv.h
+//
+
+VOID
+CsrReferenceProcess(
+ PCSR_PROCESS p
+ );
+
+VOID
+CsrLockedReferenceProcess(
+ PCSR_PROCESS p
+ );
+
+VOID
+CsrLockedReferenceThread(
+ PCSR_THREAD t
+ );
+
+VOID
+CsrLockedDereferenceProcess(
+ PCSR_PROCESS p
+ );
+
+VOID
+CsrLockedDereferenceThread(
+ PCSR_THREAD t
+ );
+
+NTSTATUS
+CsrInitializeProcessStructure( VOID );
+
+PCSR_PROCESS
+CsrAllocateProcess( VOID );
+
+VOID
+CsrDeallocateProcess(
+ IN PCSR_PROCESS Process
+ );
+
+VOID
+CsrInsertProcess(
+ IN PCSR_PROCESS ParentProcess,
+ IN PCSR_PROCESS CallingProcess,
+ IN PCSR_PROCESS Process
+ );
+
+VOID
+CsrRemoveProcess(
+ IN PCSR_PROCESS Process
+ );
+
+NTSTATUS
+CsrSetProcessContext(
+ IN PCSR_PROCESS Process,
+ IN PCSR_THREAD Thread,
+ IN BOOLEAN StartedBySm
+ );
+
+PCSR_THREAD
+CsrAllocateThread(
+ IN PCSR_PROCESS Process
+ );
+
+VOID
+CsrDeallocateThread(
+ IN PCSR_THREAD Thread
+ );
+
+VOID
+CsrInitializeThreadData(
+ IN PCSR_THREAD Thread,
+ IN PCSR_THREAD CallingThread OPTIONAL
+ );
+
+VOID
+CsrInsertThread(
+ IN PCSR_PROCESS Process,
+ IN PCSR_THREAD Thread
+ );
+
+VOID
+CsrRemoveThread(
+ IN PCSR_THREAD Thread
+ );
+
+PCSR_THREAD
+CsrLocateThreadByClientId(
+ OUT PCSR_PROCESS *Process,
+ IN PCLIENT_ID ClientId
+ );
+
+NTSTATUS
+CsrUiLookup(
+ IN PCLIENT_ID AppClientId,
+ OUT PCLIENT_ID DebugUiClientId
+ );
+
+NTSTATUS
+CsrSrvIdentifyAlertableThread(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ );
+
+NTSTATUS
+CsrSrvSetPriorityClass(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ );
+
+
+//
+// Routines and data defined in csrdebug.c
+//
+
+VOID
+CsrSuspendProcess(
+ IN PCSR_PROCESS Process
+ );
+
+VOID
+CsrResumeProcess(
+ IN PCSR_PROCESS Process
+ );
+
+NTSTATUS
+CsrSendProcessAndThreadEvents(
+ IN PCSR_PROCESS Process,
+ IN PCSR_ATTACH_COMPLETE_ROUTINE AttachCompleteRoutine
+ );
+
+VOID
+CsrComputeImageInformation(
+ IN PCSR_PROCESS Process,
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ OUT PVOID *BaseOfImage,
+ OUT PULONG DebugInfoFileOffset,
+ OUT PULONG DebugInfoSize
+ );
+
+VOID
+CsrOpenLdrEntry(
+ IN PCSR_THREAD Thread,
+ IN PCSR_PROCESS Process,
+ IN PLDR_DATA_TABLE_ENTRY LdrEntry,
+ OUT PHANDLE FileHandle
+ );
+
+PCSR_PROCESS
+CsrInitializeCsrDebugProcess(
+ PCSR_PROCESS TargetProcess
+ );
+
+VOID
+CsrTeardownCsrDebugProcess(
+ PCSR_PROCESS TargetProcess
+ );
+
+
+
+//
+// Routines and data defined in wait.c
+//
+
+#define AcquireWaitListsLock() RtlEnterCriticalSection( &CsrWaitListsLock )
+#define ReleaseWaitListsLock() RtlLeaveCriticalSection( &CsrWaitListsLock )
+
+RTL_CRITICAL_SECTION CsrWaitListsLock;
+extern SECURITY_QUALITY_OF_SERVICE CsrSecurityQos;
+
+BOOLEAN
+CsrInitializeWait(
+ IN CSR_WAIT_ROUTINE WaitRoutine,
+ IN PCSR_THREAD WaitingThread,
+ IN OUT PCSR_API_MSG WaitReplyMessage,
+ IN PVOID WaitParameter,
+ OUT PCSR_WAIT_BLOCK *WaitBlockPtr
+ );
+
+BOOLEAN
+CsrNotifyWaitBlock(
+ IN PCSR_WAIT_BLOCK WaitBlock,
+ IN PLIST_ENTRY WaitQueue,
+ IN PVOID SatisfyParameter1,
+ IN PVOID SatisfyParameter2,
+ IN ULONG WaitFlags,
+ IN BOOLEAN DereferenceThread
+ );
+
+ULONG CsrBaseTag;
+ULONG CsrSharedBaseTag;
+
+#define MAKE_TAG( t ) (RTL_HEAP_MAKE_TAG( CsrBaseTag, t ))
+
+#define TMP_TAG 0
+#define INIT_TAG 1
+#define CAPTURE_TAG 2
+#define PROCESS_TAG 3
+
+#define MAKE_SHARED_TAG( t ) (RTL_HEAP_MAKE_TAG( CsrSharedBaseTag, t ))
+#define SHR_INIT_TAG 0
diff --git a/private/csr/server/csrsrv.src b/private/csr/server/csrsrv.src
new file mode 100644
index 000000000..a3135ca84
--- /dev/null
+++ b/private/csr/server/csrsrv.src
@@ -0,0 +1,38 @@
+LIBRARY CSRSRV
+
+DESCRIPTION 'Client-Server Runtime Subsystem - Server Stubs'
+
+EXPORTS
+ CsrServerInitialization
+ CsrCreateProcess
+ CsrCreateThread
+ CsrCreateRemoteThread
+ CsrDestroyProcess
+ CsrDestroyThread
+ CsrCallServerFromServer
+ CsrGetApiPorts
+ CsrCreateWait
+ CsrNotifyWait
+ CsrDestroyWait
+ CsrDebugProcess
+ CsrAddStaticServerThread
+ CsrReferenceThread
+ CsrDereferenceThread
+ CsrLockProcessByClientId
+ CsrUnlockProcess
+ CsrLockThreadByClientId
+ CsrUnlockThread
+ CsrLocateThreadInProcess
+ CsrDereferenceWait
+ CsrComputePriorityClass
+ CsrShutdownProcesses
+ CsrGetProcessLuid
+ CsrDereferenceProcess
+ CsrImpersonateClient
+ CsrRevertToSelf
+ CsrSetForegroundPriority
+ CsrSetBackgroundPriority
+ CsrSetCallingSpooler
+ CsrQueryApiPort
+ CsrConnectToUser
+ CsrUnhandledExceptionFilter
diff --git a/private/csr/server/csrss.c b/private/csr/server/csrss.c
new file mode 100644
index 000000000..cb5f592ec
--- /dev/null
+++ b/private/csr/server/csrss.c
@@ -0,0 +1,107 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ csrss.c
+
+Abstract:
+
+ This is the main startup module for the Server side of the Client
+ Server Runtime Subsystem (CSRSS)
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+VOID
+DisableErrorPopups(
+ VOID
+ )
+{
+
+ ULONG NewMode;
+
+ NewMode = 0;
+ NtSetInformationProcess(
+ NtCurrentProcess(),
+ ProcessDefaultHardErrorMode,
+ (PVOID) &NewMode,
+ sizeof(NewMode)
+ );
+}
+
+int
+_cdecl
+main(
+ IN ULONG argc,
+ IN PCH argv[],
+ IN PCH envp[],
+ IN ULONG DebugFlag OPTIONAL
+ )
+{
+ NTSTATUS status;
+ ULONG ErrorResponse;
+ KPRIORITY SetBasePriority;
+
+ SetBasePriority = FOREGROUND_BASE_PRIORITY + 4;
+ NtSetInformationProcess(
+ NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID) &SetBasePriority,
+ sizeof(SetBasePriority)
+ );
+
+ //
+ // Give IOPL to the server so GDI and the display drivers can access the
+ // video registers.
+ //
+
+ status = NtSetInformationProcess( NtCurrentProcess(),
+ ProcessUserModeIOPL,
+ NULL,
+ 0 );
+
+ if (!NT_SUCCESS( status )) {
+
+ IF_DEBUG {
+
+ DbgPrint( "CSRSS: Unable to give IOPL to the server. status == %X\n",
+ status);
+ }
+
+ status = NtRaiseHardError( (NTSTATUS)STATUS_IO_PRIVILEGE_FAILED,
+ 0,
+ 0,
+ NULL,
+ OptionOk,
+ &ErrorResponse
+ );
+ }
+
+ status = CsrServerInitialization( argc, argv );
+
+ if (!NT_SUCCESS( status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: Unable to initialize server. status == %X\n",
+ status
+ );
+ }
+
+ NtTerminateProcess( NtCurrentProcess(), status );
+ }
+ DisableErrorPopups();
+ NtTerminateThread( NtCurrentThread(), status );
+ return( 0 );
+}
diff --git a/private/csr/server/csrss.rc b/private/csr/server/csrss.rc
new file mode 100644
index 000000000..e838c0237
--- /dev/null
+++ b/private/csr/server/csrss.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Client Server Runtime Process"
+#define VER_INTERNALNAME_STR "CSRSrv.DLL and CSRSS.Exe"
+#define VER_ORIGINALFILENAME_STR "CSRSrv.DLL and CSRSS.Exe"
+
+#include "common.ver"
diff --git a/private/csr/server/i386/sources b/private/csr/server/i386/sources
new file mode 100644
index 000000000..e55485376
--- /dev/null
+++ b/private/csr/server/i386/sources
@@ -0,0 +1 @@
+386_LNKFLAGS=-stack:65536,8192
diff --git a/private/csr/server/makefile b/private/csr/server/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/csr/server/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/csr/server/mips/sources b/private/csr/server/mips/sources
new file mode 100644
index 000000000..1fdb5b447
--- /dev/null
+++ b/private/csr/server/mips/sources
@@ -0,0 +1 @@
+MIPS_LNKFLAGS=-stack:65536,8192
diff --git a/private/csr/server/ppc/sources b/private/csr/server/ppc/sources
new file mode 100644
index 000000000..2bf092a8d
--- /dev/null
+++ b/private/csr/server/ppc/sources
@@ -0,0 +1,2 @@
+PPC_LNKFLAGS=-stack:65536,8192
+
diff --git a/private/csr/server/process.c b/private/csr/server/process.c
new file mode 100644
index 000000000..2de0c513a
--- /dev/null
+++ b/private/csr/server/process.c
@@ -0,0 +1,2002 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ process.c
+
+Abstract:
+
+ This module contains the worker routines called to create and
+ maintain the application process structure for the Client-Server
+ Runtime Subsystem to the Session Manager SubSystem.
+
+Author:
+
+ Steve Wood (stevewo) 10-Oct-1990
+
+Revision History:
+
+--*/
+
+
+#include "csrsrv.h"
+
+// ProcessSequenceCount will never be a value less than FIRST_SEQUENCE_COUNT
+// currently GDI needs 0 - 4 to be reserved.
+
+ULONG ProcessSequenceCount = FIRST_SEQUENCE_COUNT;
+
+
+#define THREAD_HASH_SIZE 256
+#define THREAD_ID_TO_HASH(id) ((ULONG)(id)&(THREAD_HASH_SIZE-1))
+LIST_ENTRY CsrThreadHashTable[THREAD_HASH_SIZE];
+
+LIST_ENTRY CsrZombieThreadList;
+
+
+SECURITY_QUALITY_OF_SERVICE CsrSecurityQos = {
+ sizeof(SECURITY_QUALITY_OF_SERVICE), SecurityImpersonation,
+ SECURITY_DYNAMIC_TRACKING, FALSE
+};
+
+PCSR_PROCESS
+FindProcessForShutdown(
+ PLUID CallerLuid
+ );
+
+VOID
+CsrpSetToNormalPriority(
+ VOID
+ )
+{
+
+ KPRIORITY SetBasePriority;
+
+ SetBasePriority = FOREGROUND_BASE_PRIORITY + 4;
+ NtSetInformationProcess(
+ NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID) &SetBasePriority,
+ sizeof(SetBasePriority)
+ );
+}
+
+VOID
+CsrpSetToShutdownPriority(
+ VOID
+ )
+{
+
+ KPRIORITY SetBasePriority;
+
+ SetBasePriority = FOREGROUND_BASE_PRIORITY + 6;
+ NtSetInformationProcess(
+ NtCurrentProcess(),
+ ProcessBasePriority,
+ (PVOID) &SetBasePriority,
+ sizeof(SetBasePriority)
+ );
+}
+
+VOID
+CsrpComputePriority(
+ IN ULONG PriorityClass,
+ OUT PUCHAR ProcessPriorityClass
+ )
+{
+ if ( PriorityClass & CSR_NORMAL_PRIORITY_CLASS ) {
+ *ProcessPriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
+ }
+ else if ( PriorityClass & CSR_IDLE_PRIORITY_CLASS ) {
+ *ProcessPriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
+ }
+ else if ( PriorityClass & CSR_HIGH_PRIORITY_CLASS ) {
+ *ProcessPriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
+ }
+ else if ( PriorityClass & CSR_REALTIME_PRIORITY_CLASS ) {
+ *ProcessPriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
+ }
+ else {
+ *ProcessPriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
+ }
+}
+
+ULONG
+CsrComputePriorityClass(
+ IN PCSR_PROCESS Process
+ )
+{
+ ULONG ReturnValue;
+
+ if ( Process->PriorityClass == PROCESS_PRIORITY_CLASS_NORMAL ) {
+ ReturnValue = CSR_NORMAL_PRIORITY_CLASS;
+ }
+ else if ( Process->PriorityClass == PROCESS_PRIORITY_CLASS_IDLE ) {
+ ReturnValue = CSR_IDLE_PRIORITY_CLASS;
+ }
+ else if ( Process->PriorityClass == PROCESS_PRIORITY_CLASS_HIGH ) {
+ ReturnValue = CSR_HIGH_PRIORITY_CLASS;
+ }
+ else if ( Process->PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME ) {
+ ReturnValue = CSR_REALTIME_PRIORITY_CLASS;
+ }
+ else {
+ ReturnValue = 0;
+ }
+ return ReturnValue;
+}
+VOID
+CsrSetForegroundPriority(
+ IN PCSR_PROCESS Process
+ )
+{
+ PROCESS_PRIORITY_CLASS PriorityClass;
+
+ //
+ // priority seperation is set 0, 1, 2 as the process
+ //
+
+ if ( (ULONG)Process <= 2 ) {
+ ULONG PrioritySeperation;
+
+ PrioritySeperation = (ULONG)Process;
+ NtSetSystemInformation(
+ SystemPrioritySeperation,
+ &PrioritySeperation,
+ sizeof(ULONG)
+ );
+ return;
+ }
+
+ PriorityClass.Foreground = TRUE;
+ PriorityClass.PriorityClass = Process->PriorityClass;
+
+ NtSetInformationProcess(
+ Process->ProcessHandle,
+ ProcessPriorityClass,
+ (PVOID)&PriorityClass,
+ sizeof(PriorityClass)
+ );
+}
+
+VOID
+CsrSetBackgroundPriority(
+ IN PCSR_PROCESS Process
+ )
+{
+ PROCESS_PRIORITY_CLASS PriorityClass;
+
+ PriorityClass.Foreground = FALSE;
+ PriorityClass.PriorityClass = Process->PriorityClass;
+
+ NtSetInformationProcess(
+ Process->ProcessHandle,
+ ProcessPriorityClass,
+ (PVOID)&PriorityClass,
+ sizeof(PriorityClass)
+ );
+}
+
+
+NTSTATUS
+CsrInitializeProcessStructure( VOID )
+{
+ NTSTATUS Status;
+ ULONG i;
+
+ Status = RtlInitializeCriticalSection( &CsrProcessStructureLock );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ CsrRootProcess = NULL;
+ CsrRootProcess = CsrAllocateProcess();
+ ASSERT( CsrRootProcess != NULL );
+ InitializeListHead( &CsrRootProcess->ListLink );
+ CsrRootProcess->ProcessHandle = (HANDLE)0xFFFFFFFF;
+ CsrRootProcess->ClientId = NtCurrentTeb()->ClientId;
+ for ( i=0; i<THREAD_HASH_SIZE; i++ ) {
+ InitializeListHead(&CsrThreadHashTable[i]);
+ }
+ InitializeListHead(&CsrZombieThreadList);
+ Status = RtlInitializeCriticalSection( &CsrWaitListsLock );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ return( Status );
+}
+
+
+PCSR_PROCESS
+CsrAllocateProcess( VOID )
+{
+ PCSR_PROCESS Process;
+ ULONG ProcessSize;
+
+ //
+ // Allocate an Windows Process Object. At the end of the process
+ // structure is an array of pointers to each server DLL's per process
+ // data. The per process data is contained in the memory after the
+ // array.
+ //
+
+ ProcessSize = QUAD_ALIGN(sizeof( CSR_PROCESS ) +
+ (CSR_MAX_SERVER_DLL * sizeof(PVOID))) + CsrTotalPerProcessDataLength;
+ Process = (PCSR_PROCESS)RtlAllocateHeap( CsrHeap, MAKE_TAG( PROCESS_TAG ),
+ ProcessSize
+ );
+ ASSERT( Process != NULL );
+ if (Process == NULL) {
+ return( NULL );
+ }
+
+ //
+ // Initialize the fields of the process object
+ //
+
+ RtlZeroMemory( Process, ProcessSize);
+
+ //
+ // grab the ProcessSequenceNumber and increment it, making sure that it
+ // is never less than FIRST_SEQUENCE_COUNT.
+ //
+
+ Process->SequenceNumber = ProcessSequenceCount++;
+
+ if (ProcessSequenceCount < FIRST_SEQUENCE_COUNT)
+ ProcessSequenceCount = FIRST_SEQUENCE_COUNT;
+
+ Process->PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
+
+ CsrLockedReferenceProcess(Process);
+
+ InitializeListHead( &Process->ThreadList );
+ return( Process );
+}
+
+
+VOID
+CsrDeallocateProcess(
+ IN PCSR_PROCESS Process
+ )
+{
+ RtlFreeHeap( CsrHeap, 0, Process );
+}
+
+VOID
+CsrInsertProcess(
+ IN PCSR_PROCESS ParentProcess,
+ IN PCSR_PROCESS CallingProcess,
+ IN PCSR_PROCESS Process
+ )
+// NOTE: the process structure lock must be held when calling this routine
+{
+ PCSR_SERVER_DLL LoadedServerDll;
+ ULONG i;
+
+ Process->Parent = ParentProcess;
+ InsertTailList( &CsrRootProcess->ListLink, &Process->ListLink );
+
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->AddProcessRoutine) {
+ (*LoadedServerDll->AddProcessRoutine)( CallingProcess, Process );
+ }
+ }
+}
+
+
+VOID
+CsrRemoveProcess(
+ IN PCSR_PROCESS Process
+ )
+// NOTE: the process structure lock must be held when calling this routine
+{
+ PCSR_SERVER_DLL LoadedServerDll;
+ ULONG i;
+
+ RemoveEntryList( &Process->ListLink );
+ ReleaseProcessStructureLock();
+
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->DisconnectRoutine) {
+ (LoadedServerDll->DisconnectRoutine)( Process );
+ }
+ }
+
+}
+
+NTSTATUS
+CsrSetProcessContext(
+ IN PCSR_PROCESS Process,
+ IN PCSR_THREAD Thread,
+ IN BOOLEAN StartedBySm
+ )
+{
+#if 0
+ Process->InitialPebCsrData.Length = sizeof( Process->InitialPebCsrData );
+ Process->InitialPebCsrData.StartedBySm = StartedBySm;
+#endif
+
+ return( STATUS_SUCCESS );
+}
+
+NTSTATUS
+CsrCreateProcess(
+ IN HANDLE ProcessHandle,
+ IN HANDLE ThreadHandle,
+ IN PCLIENT_ID ClientId,
+ IN PCSR_NT_SESSION Session,
+ IN ULONG DebugFlags,
+ IN PCLIENT_ID DebugUserInterface OPTIONAL
+ )
+{
+ PCSR_PROCESS Process;
+ PCSR_THREAD Thread;
+ NTSTATUS Status;
+ ULONG i;
+ PVOID ProcessDataPtr;
+ CLIENT_ID CallingClientId;
+ PCSR_THREAD CallingThread;
+ PCSR_PROCESS CallingProcess;
+ KERNEL_USER_TIMES TimeInfo;
+
+ CallingThread = CSR_SERVER_QUERYCLIENTTHREAD();
+
+ //
+ // remember the client id of the calling process.
+ //
+
+ CallingClientId = CallingThread->ClientId;
+
+ AcquireProcessStructureLock();
+
+ //
+ // look for calling thread.
+ //
+
+ CallingThread = CsrLocateThreadByClientId( &CallingProcess,
+ &CallingClientId
+ );
+ if (CallingThread == NULL) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+
+ Process = CsrAllocateProcess();
+ if (Process == NULL) {
+ Status = STATUS_NO_MEMORY;
+ ReleaseProcessStructureLock();
+ return( Status );
+ }
+
+ //
+ // copy per-process data from parent to child
+ //
+
+ CallingProcess = (CSR_SERVER_QUERYCLIENTTHREAD())->Process;
+ ProcessDataPtr = (PVOID)QUAD_ALIGN(&Process->ServerDllPerProcessData[CSR_MAX_SERVER_DLL]);
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ if (CsrLoadedServerDll[i] != NULL && CsrLoadedServerDll[i]->PerProcessDataLength) {
+ Process->ServerDllPerProcessData[i] = ProcessDataPtr;
+ RtlMoveMemory(ProcessDataPtr,
+ CallingProcess->ServerDllPerProcessData[i],
+ CsrLoadedServerDll[i]->PerProcessDataLength
+ );
+ ProcessDataPtr = (PVOID)QUAD_ALIGN((ULONG)ProcessDataPtr + CsrLoadedServerDll[i]->PerProcessDataLength);
+ }
+ else {
+ Process->ServerDllPerProcessData[i] = NULL;
+ }
+ }
+
+ Status = NtSetInformationProcess(
+ ProcessHandle,
+ ProcessExceptionPort,
+ (PVOID)&CsrApiPort,
+ sizeof(HANDLE)
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( STATUS_NO_MEMORY );
+ }
+ ASSERT(NT_SUCCESS(Status));
+
+ CsrpComputePriority(
+ DebugFlags,
+ &Process->PriorityClass
+ );
+
+ //
+ // If we are creating a process group, the group leader has the same
+ // process id and sequence number of itself. If the leader dies and
+ // his pid is recycled, the sequence number mismatch will prevent it
+ // from being viewed as a group leader.
+ //
+
+ if ( DebugFlags & CSR_CREATE_PROCESS_GROUP ) {
+ Process->ProcessGroupId = (ULONG)ClientId->UniqueProcess;
+ Process->ProcessGroupSequence = Process->SequenceNumber;
+ }
+ else {
+ Process->ProcessGroupId = CallingProcess->ProcessGroupId;
+ Process->ProcessGroupSequence = CallingProcess->ProcessGroupSequence;
+ }
+
+ if ( DebugFlags & CSR_PROCESS_CONSOLEAPP ) {
+ Process->Flags |= CSR_PROCESS_CONSOLEAPP;
+ }
+
+ DebugFlags &= ~(CSR_PROCESS_CONSOLEAPP | CSR_NORMAL_PRIORITY_CLASS|CSR_IDLE_PRIORITY_CLASS|CSR_HIGH_PRIORITY_CLASS|CSR_REALTIME_PRIORITY_CLASS|CSR_CREATE_PROCESS_GROUP);
+
+ if ( !DebugFlags && CallingProcess->DebugFlags & CSR_DEBUG_PROCESS_TREE ) {
+ Process->DebugFlags = CSR_DEBUG_PROCESS_TREE;
+ Process->DebugUserInterface = CallingProcess->DebugUserInterface;
+ }
+ if ( DebugFlags & (CSR_DEBUG_THIS_PROCESS | CSR_DEBUG_PROCESS_TREE) &&
+ ARGUMENT_PRESENT(DebugUserInterface) ) {
+ Process->DebugFlags = DebugFlags;
+ Process->DebugUserInterface = *DebugUserInterface;
+ }
+
+
+ if ( Process->DebugFlags ) {
+
+ //
+ // Process is being debugged, so set up debug port
+ //
+
+ Status = NtSetInformationProcess(
+ ProcessHandle,
+ ProcessDebugPort,
+ (PVOID)&CsrApiPort,
+ sizeof(HANDLE)
+ );
+ ASSERT(NT_SUCCESS(Status));
+ if ( !NT_SUCCESS(Status) ) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( STATUS_NO_MEMORY );
+ }
+ }
+ //
+ // capture the thread's createtime so that we can use
+ // this as a sequence number
+ //
+
+ Status = NtQueryInformationThread(
+ ThreadHandle,
+ ThreadTimes,
+ (PVOID)&TimeInfo,
+ sizeof(TimeInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( Status );
+ }
+
+ Thread = CsrAllocateThread( Process );
+ if (Thread == NULL) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( STATUS_NO_MEMORY );
+ }
+
+ CsrInitializeThreadData(Thread, CSR_SERVER_QUERYCLIENTTHREAD());
+
+ Thread->CreateTime = TimeInfo.CreateTime;
+
+ Thread->ClientId = *ClientId;
+ Thread->ThreadHandle = ThreadHandle;
+
+ProtectHandle(ThreadHandle);
+
+ Thread->Flags = 0;
+ CsrInsertThread( Process, Thread );
+
+ CsrReferenceNtSession(Session);
+ Process->NtSession = Session;
+
+ Process->ClientId = *ClientId;
+ Process->ProcessHandle = ProcessHandle;
+
+ CsrSetBackgroundPriority(Process);
+
+ Process->ShutdownLevel = 0x00000280;
+
+ CsrInsertProcess( NULL, (CSR_SERVER_QUERYCLIENTTHREAD())->Process, Process );
+ ReleaseProcessStructureLock();
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CsrDestroyProcess(
+ IN PCLIENT_ID ClientId,
+ IN NTSTATUS ExitStatus
+ )
+{
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD DyingThread;
+ PCSR_PROCESS DyingProcess;
+
+ CLIENT_ID DyingClientId;
+
+ DyingClientId = *ClientId;
+
+ AcquireProcessStructureLock();
+
+
+ DyingThread = CsrLocateThreadByClientId( &DyingProcess,
+ &DyingClientId
+ );
+ if (DyingThread == NULL) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+
+ //
+ // prevent multiple destroys from causing problems. Scottlu and Markl
+ // beleive all known race conditions are now fixed. This is simply a
+ // precaution since we know that if this happens we process reference
+ // count underflow
+ //
+
+ if ( DyingProcess->Flags & CSR_PROCESS_DESTROYED ) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+
+ DyingProcess->Flags |= CSR_PROCESS_DESTROYED;
+
+ ListHead = &DyingProcess->ThreadList;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ DyingThread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
+ ListNext = ListNext->Flink;
+ if ( DyingThread->Flags & CSR_THREAD_DESTROYED ) {
+ continue;
+ }
+ else {
+ DyingThread->Flags |= CSR_THREAD_DESTROYED;
+ }
+ AcquireWaitListsLock();
+ if (DyingThread->WaitBlock != NULL) {
+ CsrNotifyWaitBlock(DyingThread->WaitBlock,
+ NULL,
+ NULL,
+ NULL,
+ CSR_PROCESS_TERMINATING,
+ TRUE
+ );
+ }
+ ReleaseWaitListsLock();
+ CsrLockedDereferenceThread(DyingThread);
+ }
+
+ ReleaseProcessStructureLock();
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CsrCreateThread(
+ IN PCSR_PROCESS Process,
+ IN HANDLE ThreadHandle,
+ IN PCLIENT_ID ClientId
+ )
+{
+ PCSR_THREAD Thread;
+ CLIENT_ID CallingClientId;
+ PCSR_THREAD CallingThread;
+ PCSR_PROCESS CallingProcess;
+ KERNEL_USER_TIMES TimeInfo;
+ NTSTATUS Status;
+
+ CallingThread = CSR_SERVER_QUERYCLIENTTHREAD();
+
+ //
+ // remember the client id of the calling process.
+ //
+
+ CallingClientId = CallingThread->ClientId;
+
+ AcquireProcessStructureLock();
+
+ //
+ // look for calling thread.
+ //
+
+ CallingThread = CsrLocateThreadByClientId( &CallingProcess,
+ &CallingClientId
+ );
+ if (CallingThread == NULL) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+
+ Status = NtQueryInformationThread(
+ ThreadHandle,
+ ThreadTimes,
+ (PVOID)&TimeInfo,
+ sizeof(TimeInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ ReleaseProcessStructureLock();
+ return( Status );
+ }
+
+ Thread = CsrAllocateThread( Process );
+ if (Thread == NULL) {
+ ReleaseProcessStructureLock();
+ return( STATUS_NO_MEMORY );
+ }
+
+ CsrInitializeThreadData(Thread, CallingThread);
+
+ Thread->CreateTime = TimeInfo.CreateTime;
+
+ Thread->ClientId = *ClientId;
+ Thread->ThreadHandle = ThreadHandle;
+
+ProtectHandle(ThreadHandle);
+
+ Thread->Flags = 0;
+ CsrInsertThread( Process, Thread );
+ ReleaseProcessStructureLock();
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CsrCreateRemoteThread(
+ IN HANDLE ThreadHandle,
+ IN PCLIENT_ID ClientId
+ )
+{
+ PCSR_THREAD Thread;
+ PCSR_PROCESS Process;
+ NTSTATUS Status;
+ HANDLE hThread;
+ KERNEL_USER_TIMES TimeInfo;
+
+ Status = NtQueryInformationThread(
+ ThreadHandle,
+ ThreadTimes,
+ (PVOID)&TimeInfo,
+ sizeof(TimeInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ return( Status );
+ }
+
+ Status = CsrLockProcessByClientId( ClientId->UniqueProcess,
+ &Process
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ //
+ // Don't create the thread structure if the thread
+ // has already terminated.
+ //
+
+ if ( TimeInfo.ExitTime.QuadPart != 0 ) {
+ CsrUnlockProcess( Process );
+ return( STATUS_THREAD_IS_TERMINATING );
+ }
+
+ Thread = CsrAllocateThread( Process );
+ if (Thread == NULL) {
+ CsrUnlockProcess( Process );
+ return( STATUS_NO_MEMORY );
+ }
+ Status = NtDuplicateObject(
+ NtCurrentProcess(),
+ ThreadHandle,
+ NtCurrentProcess(),
+ &hThread,
+ 0L,
+ 0L,
+ DUPLICATE_SAME_ACCESS
+ );
+ if (!NT_SUCCESS(Status)) {
+ hThread = ThreadHandle;
+ }
+
+ CsrInitializeThreadData(Thread, NULL);
+
+ Thread->CreateTime = TimeInfo.CreateTime;
+
+ Thread->ClientId = *ClientId;
+ Thread->ThreadHandle = hThread;
+
+ProtectHandle(hThread);
+
+ Thread->Flags = 0;
+ CsrInsertThread( Process, Thread );
+ CsrUnlockProcess( Process );
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+CsrDestroyThread(
+ IN PCLIENT_ID ClientId
+ )
+{
+ CLIENT_ID DyingClientId;
+ PCSR_THREAD DyingThread;
+ PCSR_PROCESS DyingProcess;
+
+ DyingClientId = *ClientId;
+
+ AcquireProcessStructureLock();
+
+ DyingThread = CsrLocateThreadByClientId( &DyingProcess,
+ &DyingClientId
+ );
+ if (DyingThread == NULL) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+
+ if ( DyingThread->Flags & CSR_THREAD_DESTROYED ) {
+ ReleaseProcessStructureLock();
+ return STATUS_THREAD_IS_TERMINATING;
+ }
+ else {
+ DyingThread->Flags |= CSR_THREAD_DESTROYED;
+ }
+
+ AcquireWaitListsLock();
+ if (DyingThread->WaitBlock != NULL) {
+ CsrNotifyWaitBlock(DyingThread->WaitBlock,
+ NULL,
+ NULL,
+ NULL,
+ CSR_PROCESS_TERMINATING,
+ TRUE
+ );
+ }
+ ReleaseWaitListsLock();
+ CsrLockedDereferenceThread(DyingThread);
+
+ ReleaseProcessStructureLock();
+ return STATUS_SUCCESS;
+}
+
+
+PCSR_THREAD
+CsrAllocateThread(
+ IN PCSR_PROCESS Process
+ )
+{
+ PCSR_THREAD Thread;
+ ULONG ThreadSize;
+
+ //
+ // Allocate an Windows Thread Object. At the end of the thread
+ // structure is an array of pointers to each server DLL's per thread
+ // data. The per thread data is contained in the memory after the
+ // array.
+ //
+ //
+
+ ThreadSize = QUAD_ALIGN(sizeof( CSR_THREAD ) +
+ (CSR_MAX_SERVER_DLL * sizeof(PVOID))) + CsrTotalPerThreadDataLength;
+ Thread = (PCSR_THREAD)RtlAllocateHeap( CsrHeap, MAKE_TAG( PROCESS_TAG ),
+ ThreadSize
+ );
+ if (Thread == NULL) {
+ return( NULL );
+ }
+
+ //
+ // Initialize the fields of the thread object
+ //
+
+ RtlZeroMemory( Thread, ThreadSize );
+
+ CsrLockedReferenceThread(Thread);
+ CsrLockedReferenceProcess(Process);
+ Thread->Process = Process;
+
+ return( Thread );
+}
+
+
+VOID
+CsrDeallocateThread(
+ IN PCSR_THREAD Thread
+ )
+{
+ ASSERT (Thread->WaitBlock == NULL);
+ RtlFreeHeap( CsrHeap, 0, Thread );
+}
+
+
+VOID
+CsrInitializeThreadData(
+ IN PCSR_THREAD Thread,
+ IN PCSR_THREAD CallingThread
+ )
+{
+ PVOID ThreadDataPtr;
+ ULONG i;
+
+ //
+ // if there is a parent, copy per-thread data from parent to child
+ //
+
+ ThreadDataPtr = (PVOID)QUAD_ALIGN(&Thread->ServerDllPerThreadData[CSR_MAX_SERVER_DLL]);
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ if (CsrLoadedServerDll[i] != NULL && CsrLoadedServerDll[i]->PerThreadDataLength) {
+ Thread->ServerDllPerThreadData[i] = ThreadDataPtr;
+ if (CallingThread) {
+ RtlMoveMemory(ThreadDataPtr,
+ CallingThread->ServerDllPerThreadData[i],
+ CsrLoadedServerDll[i]->PerThreadDataLength
+ );
+ }
+ ThreadDataPtr = (PVOID)QUAD_ALIGN((ULONG)ThreadDataPtr + CsrLoadedServerDll[i]->PerThreadDataLength);
+ }
+ else {
+ Thread->ServerDllPerThreadData[i] = NULL;
+ }
+ }
+}
+
+VOID
+CsrInsertThread(
+ IN PCSR_PROCESS Process,
+ IN PCSR_THREAD Thread
+ )
+
+// NOTE: the process structure lock must be held exclusively while calling this routine
+
+{
+ PCSR_SERVER_DLL LoadedServerDll;
+ ULONG i;
+
+ InsertTailList( &Process->ThreadList, &Thread->Link );
+ Process->ThreadCount++;
+ i = THREAD_ID_TO_HASH(Thread->ClientId.UniqueThread);
+ InsertHeadList( &CsrThreadHashTable[i], &Thread->HashLinks);
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->AddThreadRoutine) {
+ (*LoadedServerDll->AddThreadRoutine)( Thread );
+ }
+ }
+}
+
+VOID
+CsrRemoveThread(
+ IN PCSR_THREAD Thread
+ )
+
+
+{
+ PCSR_SERVER_DLL LoadedServerDll;
+ ULONG i;
+
+ RemoveEntryList( &Thread->Link );
+ Thread->Process->ThreadCount--;
+ if (Thread->HashLinks.Flink)
+ RemoveEntryList( &Thread->HashLinks );
+
+ //
+ // if this is the last thread, then make sure we undo the reference
+ // that this thread had on the process.
+ //
+
+ if ( Thread->Process->ThreadCount == 0 ) {
+ if ( !(Thread->Process->Flags & CSR_PROCESS_LASTTHREADOK) ) {
+ Thread->Process->Flags |= CSR_PROCESS_LASTTHREADOK;
+ CsrLockedDereferenceProcess(Thread->Process);
+ }
+ }
+
+ //
+ // Set the termination thread *before* calling the delete thread routines
+ // in each server .dll. Need to set this ahead of time because USER looks
+ // at this flag from the context of a thread that gets woken up by this
+ // thread while calling DeleteThreadRoutine.
+ //
+
+ Thread->Flags |= CSR_THREAD_TERMINATING;
+
+ //
+ // Set the reference count before the structure lock is released.
+ // This will prevent gui threads from deleting the thread
+ // structure during cleanup.
+ //
+
+ Thread->ReferenceCount = 1;
+
+ ReleaseProcessStructureLock();
+
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->DeleteThreadRoutine) {
+
+ (*LoadedServerDll->DeleteThreadRoutine)( Thread );
+ }
+ }
+
+ //
+ // Reset the refcount so gui threads can free the thread structure.
+ //
+
+ AcquireProcessStructureLock();
+ Thread->ReferenceCount = 0;
+}
+
+
+NTSTATUS
+CsrLockProcessByClientId(
+ IN HANDLE UniqueProcessId,
+ OUT PCSR_PROCESS *Process
+ )
+{
+ NTSTATUS Status;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_PROCESS ProcessPtr;
+
+
+ AcquireProcessStructureLock();
+
+ if (ARGUMENT_PRESENT(Process)) {
+ *Process = NULL;
+ }
+
+ Status = STATUS_UNSUCCESSFUL;
+ ListHead = &CsrRootProcess->ListLink;
+ ListNext = ListHead;
+ do {
+ ProcessPtr = CONTAINING_RECORD( ListNext, CSR_PROCESS, ListLink );
+ if (ProcessPtr->ClientId.UniqueProcess == UniqueProcessId) {
+ Status = STATUS_SUCCESS;
+ break;
+ }
+ ListNext = ListNext->Flink;
+ } while (ListNext != ListHead);
+
+ if (NT_SUCCESS( Status )) {
+ CsrLockedReferenceProcess(ProcessPtr);
+ *Process = ProcessPtr;
+ }
+ else {
+ ReleaseProcessStructureLock();
+ }
+
+ return( Status );
+}
+
+NTSTATUS
+CsrUnlockProcess(
+ IN PCSR_PROCESS Process
+ )
+{
+ CsrLockedDereferenceProcess( Process );
+ ReleaseProcessStructureLock();
+ return( STATUS_SUCCESS );
+}
+
+NTSTATUS
+CsrLockThreadByClientId(
+ IN HANDLE UniqueThreadId,
+ OUT PCSR_THREAD *Thread
+ )
+{
+ NTSTATUS Status;
+ ULONG Index;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD ThreadPtr;
+ CLIENT_ID ClientId;
+
+ AcquireProcessStructureLock();
+
+ if (ARGUMENT_PRESENT(Thread)) {
+ *Thread = NULL;
+ }
+
+ Index = THREAD_ID_TO_HASH(UniqueThreadId);
+
+ ListHead = &CsrThreadHashTable[Index];
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ ThreadPtr = CONTAINING_RECORD( ListNext, CSR_THREAD, HashLinks );
+ if ( ThreadPtr->ClientId.UniqueThread == UniqueThreadId &&
+ !(ThreadPtr->Flags & CSR_THREAD_DESTROYED) ) {
+ break;
+ }
+ ListNext = ListNext->Flink;
+ }
+ if (ListNext == ListHead)
+ ThreadPtr = NULL;
+
+ if (ThreadPtr != NULL) {
+ Status = STATUS_SUCCESS;
+ CsrLockedReferenceThread(ThreadPtr);
+ *Thread = ThreadPtr;
+ }
+ else {
+ Status = STATUS_UNSUCCESSFUL;
+ ReleaseProcessStructureLock();
+ }
+
+ return( Status );
+}
+
+NTSTATUS
+CsrUnlockThread(
+ IN PCSR_THREAD Thread
+ )
+{
+ CsrLockedDereferenceThread( Thread );
+ ReleaseProcessStructureLock();
+ return( STATUS_SUCCESS );
+}
+
+PCSR_THREAD
+CsrLocateThreadByClientId(
+ OUT PCSR_PROCESS *Process OPTIONAL,
+ IN PCLIENT_ID ClientId
+ )
+
+// NOTE: process structure lock must be held while calling this routine
+
+{
+ ULONG Index;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD Thread;
+
+ Index = THREAD_ID_TO_HASH(ClientId->UniqueThread);
+
+ if (ARGUMENT_PRESENT(Process)) {
+ *Process = NULL;
+ }
+ ListHead = &CsrThreadHashTable[Index];
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, HashLinks );
+ if ( Thread->ClientId.UniqueThread == ClientId->UniqueThread &&
+ Thread->ClientId.UniqueProcess == ClientId->UniqueProcess ) {
+ if (ARGUMENT_PRESENT(Process)) {
+ *Process = Thread->Process;
+ }
+ return Thread;
+ }
+ ListNext = ListNext->Flink;
+ }
+ return NULL;
+}
+
+PCSR_THREAD
+CsrLocateThreadInProcess(
+ IN PCSR_PROCESS Process OPTIONAL,
+ IN PCLIENT_ID ClientId
+ )
+
+// NOTE: process structure lock must be held while calling this routine
+
+{
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_THREAD Thread;
+
+ if (Process == NULL)
+ Process = CsrRootProcess;
+
+ ListHead = &Process->ThreadList;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Thread = CONTAINING_RECORD( ListNext, CSR_THREAD, Link );
+ if (Thread->ClientId.UniqueThread == ClientId->UniqueThread) {
+ return( Thread );
+ }
+
+ ListNext = ListNext->Flink;
+ }
+
+ return( NULL );
+}
+
+BOOLEAN
+CsrImpersonateClient(
+ IN PCSR_THREAD Thread
+ )
+{
+ NTSTATUS Status;
+ PCSR_THREAD CallingThread;
+
+ CallingThread = CSR_SERVER_QUERYCLIENTTHREAD();
+
+ if (Thread == NULL) {
+ Thread = CallingThread;
+ }
+
+ if (Thread == NULL) {
+ return FALSE;
+ }
+
+ if (!NT_SUCCESS(Status = NtImpersonateThread(NtCurrentThread(),
+ Thread->ThreadHandle, &CsrSecurityQos))) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: Can't impersonate client thread - Status = %lx\n",
+ Status
+ );
+ if (Status != STATUS_BAD_IMPERSONATION_LEVEL)
+ DbgBreakPoint();
+ }
+ return FALSE;
+ }
+
+ //
+ // Keep track of recursion by printer drivers
+ //
+
+ if (CallingThread != NULL)
+ ++CallingThread->ImpersonateCount;
+
+ return TRUE;
+}
+
+BOOLEAN
+CsrRevertToSelf( VOID )
+{
+ HANDLE NewToken;
+ NTSTATUS Status;
+ PCSR_THREAD CallingThread;
+
+ CallingThread = CSR_SERVER_QUERYCLIENTTHREAD();
+
+ //
+ // Keep track of recursion by printer drivers
+ //
+
+ if (CallingThread != NULL) {
+ if (CallingThread->ImpersonateCount == 0) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: CsrRevertToSelf called while not impersonating\n" );
+ DbgBreakPoint();
+ }
+ return FALSE;
+ }
+ if (--CallingThread->ImpersonateCount > 0)
+ return TRUE;
+ }
+
+ NewToken = NULL;
+ Status = NtSetInformationThread(
+ NtCurrentThread(),
+ ThreadImpersonationToken,
+ (PVOID)&NewToken,
+ (ULONG)sizeof(HANDLE)
+ );
+ ASSERT( NT_SUCCESS(Status) );
+
+ return NT_SUCCESS(Status);
+}
+
+NTSTATUS
+CsrUiLookup(
+ IN PCLIENT_ID AppClientId,
+ OUT PCLIENT_ID DebugUiClientId
+ )
+{
+ PCSR_THREAD Thread;
+ NTSTATUS Status;
+
+ Status = STATUS_UNSUCCESSFUL;
+ AcquireProcessStructureLock();
+ Thread = CsrLocateThreadByClientId( NULL, AppClientId );
+ if ( Thread ) {
+ if ( Thread->Process->DebugFlags ) {
+ *DebugUiClientId = Thread->Process->DebugUserInterface;
+ Status = STATUS_SUCCESS;
+ }
+ }
+#if DEVL
+ else {
+ extern PCSR_PROCESS CsrDebugProcessPtr;
+
+ if (AppClientId->UniqueProcess ==
+ NtCurrentTeb()->ClientId.UniqueProcess &&
+ CsrDebugProcessPtr && CsrDebugProcessPtr != (PCSR_PROCESS)-1) {
+ *DebugUiClientId = CsrDebugProcessPtr->DebugUserInterface;
+ Status = STATUS_SUCCESS;
+ }
+ }
+#endif // DEVL
+ ReleaseProcessStructureLock();
+ return Status;
+}
+
+PVOID
+CsrAddStaticServerThread(
+ IN HANDLE ThreadHandle,
+ IN PCLIENT_ID ClientId,
+ IN ULONG Flags
+ )
+
+/*++
+
+Routine Description:
+
+ This function must be called by client DLL's whenever they create a
+ thread that runs in the context of CSR. This function is not called
+ for server threads that are attached to a client in the "server
+ handle" field. This function replaces the old static thread tables.
+
+Arguments:
+
+ ThreadHandle - Supplies a handle to the thread.
+
+ ClientId - Supplies the address of the thread's client id.
+
+ Flags - Not Used.
+
+Return Value:
+
+ Returns the address of the static server thread created by this
+ function.
+
+--*/
+
+{
+ PCSR_THREAD Thread;
+
+ ASSERT(CsrRootProcess != NULL);
+ AcquireProcessStructureLock();
+ Thread = CsrAllocateThread(CsrRootProcess);
+ if ( Thread ) {
+
+ CsrInitializeThreadData(Thread, NULL);
+
+ Thread->ThreadHandle = ThreadHandle;
+
+ProtectHandle(ThreadHandle);
+
+ Thread->ClientId = *ClientId;
+ Thread->Flags = Flags;
+ InsertTailList(&CsrRootProcess->ThreadList, &Thread->Link);
+ CsrRootProcess->ThreadCount++;
+ }
+ ReleaseProcessStructureLock();
+ return (PVOID)Thread;
+}
+
+NTSTATUS
+CsrSrvIdentifyAlertableThread(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ )
+{
+ PCSR_THREAD t;
+
+ t = CSR_SERVER_QUERYCLIENTTHREAD();
+ t->Flags |= CSR_ALERTABLE_THREAD;
+ return STATUS_SUCCESS;
+ m;ReplyStatus; // get rid of unreferenced parameter warning message
+}
+
+
+NTSTATUS
+CsrSrvSetPriorityClass(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ )
+{
+ NTSTATUS Status;
+ PCSR_SETPRIORITY_CLASS_MSG a = (PCSR_SETPRIORITY_CLASS_MSG)&m->u.ApiMessageData;
+ HANDLE TargetProcess;
+ PCSR_THREAD t;
+ PROCESS_BASIC_INFORMATION BasicInfo;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_PROCESS ProcessPtr;
+ KPRIORITY ForegroundPriority,BackgroundPriority;
+ PROCESS_PRIORITY_CLASS PriorityClass;
+
+ t = CSR_SERVER_QUERYCLIENTTHREAD();
+
+ //
+ // Get a handle to the process whose priority we are planning to
+ // change.
+ //
+
+ Status = NtDuplicateObject(
+ t->Process->ProcessHandle,
+ a->ProcessHandle,
+ NtCurrentProcess(),
+ &TargetProcess,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ m->ReturnValue = Status;
+ return Status;
+ }
+
+ //
+ // Now that we have a handle to the process, get its process
+ // id so we can look it up
+ //
+
+ Status = NtQueryInformationProcess(
+ TargetProcess,
+ ProcessBasicInformation,
+ (PVOID)&BasicInfo,
+ sizeof(BasicInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ NtClose(TargetProcess);
+ m->ReturnValue = Status;
+ return Status;
+ }
+
+ //
+ // The process id is now in hand. Now we have to locate the CSR
+ // process with this ID. To do this, we need to drop our current
+ // locks and scan the process table while holding the process
+ // structure lock
+ //
+
+ AcquireProcessStructureLock();
+
+ ListHead = &CsrRootProcess->ListLink;
+ ListNext = ListHead->Flink;
+ Status = STATUS_ACCESS_DENIED;
+ while (ListNext != ListHead) {
+ ProcessPtr = CONTAINING_RECORD( ListNext, CSR_PROCESS, ListLink );
+ if (ProcessPtr->ClientId.UniqueProcess == (HANDLE)BasicInfo.UniqueProcessId) {
+
+ //
+ // The process was found. Now set or get its priority
+ //
+ // I guess we need to know if it is currently in the
+ // foreground or backgroud ! For now (until I add a CsrSetFg)
+ // I will just assign it to the background
+ //
+
+ if ( a->PriorityClass ) {
+
+ //
+ // Compute the base priorities for the
+ // process and call NT to set its base.
+ //
+
+ CsrpComputePriority(
+ a->PriorityClass,
+ &PriorityClass.PriorityClass
+ );
+
+ PriorityClass.Foreground = FALSE;
+
+ Status = NtSetInformationProcess(
+ ProcessPtr->ProcessHandle,
+ ProcessPriorityClass,
+ (PVOID)&PriorityClass,
+ sizeof(PriorityClass)
+ );
+
+ if ( NT_SUCCESS(Status) ) {
+ ProcessPtr->PriorityClass = PriorityClass.PriorityClass;
+ }
+ }
+ else {
+
+ //
+ // We are trying to get the processes priority
+ //
+
+ a->PriorityClass = CsrComputePriorityClass(ProcessPtr);
+ if ( a->PriorityClass ) {
+ Status = STATUS_SUCCESS;
+ }
+ }
+ break;
+ }
+ ListNext = ListNext->Flink;
+ }
+
+ ReleaseProcessStructureLock();
+
+ NtClose(TargetProcess);
+
+ m->ReturnValue = Status;
+ return Status;
+}
+
+
+VOID
+CsrReferenceProcess(
+ PCSR_PROCESS p
+ )
+{
+ AcquireProcessStructureLock();
+ p->ReferenceCount++;
+
+ ReleaseProcessStructureLock();
+}
+
+VOID
+CsrReferenceThread(
+ PCSR_THREAD t
+ )
+{
+ AcquireProcessStructureLock();
+ t->ReferenceCount++;
+ ReleaseProcessStructureLock();
+}
+
+VOID
+CsrProcessRefcountZero(
+ PCSR_PROCESS p
+ )
+{
+ CsrRemoveProcess(p);
+ if (p->NtSession) {
+ CsrDereferenceNtSession(p->NtSession,0);
+ }
+
+ //
+ // process might not have made it through dll init routine.
+ //
+
+ if ( p->ClientPort ) {
+ NtClose(p->ClientPort);
+ }
+ NtClose(p->ProcessHandle );
+ CsrDeallocateProcess(p);
+}
+
+VOID
+CsrDereferenceProcess(
+ PCSR_PROCESS p
+ )
+{
+ LONG LockCount;
+ AcquireProcessStructureLock();
+
+ LockCount = --(p->ReferenceCount);
+
+ASSERT(LockCount >= 0);
+ if ( !LockCount ) {
+ CsrProcessRefcountZero(p);
+ }
+ else {
+ ReleaseProcessStructureLock();
+ }
+}
+
+VOID
+CsrThreadRefcountZero(
+ PCSR_THREAD t
+ )
+{
+ PCSR_PROCESS p;
+ NTSTATUS Status;
+
+ p = t->Process;
+
+ CsrRemoveThread(t);
+
+ ReleaseProcessStructureLock();
+
+UnProtectHandle(t->ThreadHandle);
+ Status = NtClose(t->ThreadHandle);
+ ASSERT(NT_SUCCESS(Status));
+ CsrDeallocateThread(t);
+
+ CsrDereferenceProcess(p);
+}
+
+VOID
+CsrDereferenceThread(
+ PCSR_THREAD t
+ )
+{
+ LONG LockCount;
+ AcquireProcessStructureLock();
+
+ LockCount = --(t->ReferenceCount);
+
+ ASSERT(LockCount >= 0);
+ if ( !LockCount ) {
+ CsrThreadRefcountZero(t);
+ }
+ else {
+ ReleaseProcessStructureLock();
+ }
+}
+
+VOID
+CsrLockedReferenceProcess(
+ PCSR_PROCESS p
+ )
+{
+ p->ReferenceCount++;
+
+}
+
+VOID
+CsrLockedReferenceThread(
+ PCSR_THREAD t
+ )
+{
+ t->ReferenceCount++;
+}
+
+VOID
+CsrLockedDereferenceProcess(
+ PCSR_PROCESS p
+ )
+{
+ LONG LockCount;
+
+ LockCount = --(p->ReferenceCount);
+
+ ASSERT(LockCount >= 0);
+ if ( !LockCount ) {
+ AcquireProcessStructureLock();
+ CsrProcessRefcountZero(p);
+ }
+}
+
+VOID
+CsrLockedDereferenceThread(
+ PCSR_THREAD t
+ )
+{
+ LONG LockCount;
+
+ LockCount = --(t->ReferenceCount);
+
+ ASSERT(LockCount >= 0);
+ if ( !LockCount ) {
+ AcquireProcessStructureLock();
+ CsrThreadRefcountZero(t);
+ }
+}
+
+//
+// This routine will shutdown processes so either a logoff or a shutdown can
+// occur. This simply calls the shutdown process handlers for each .dll until
+// one .dll recognizes this process and will shut it down. Only the processes
+// with the passed sid are shutdown.
+//
+
+NTSTATUS
+CsrShutdownProcesses(
+ PLUID CallerLuid,
+ ULONG Flags
+ )
+{
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_PROCESS Process;
+ ULONG i;
+ PCSR_SERVER_DLL LoadedServerDll;
+ ULONG Command;
+ BOOLEAN fFirstPass;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+#ifdef DEVL
+ BOOLEAN fFindDebugger;
+ extern BOOLEAN fWin32ServerDebugger;
+ extern CLIENT_ID ClientIdWin32ServerDebugger;
+
+ //
+ // Remember if we need to look for a debugger debugging the win32 server.
+ // We can't close this down because it'll hang the system.
+ //
+ fFindDebugger = fWin32ServerDebugger;
+#endif // DEVL
+
+ //
+ // Question: how do we avoid processes starting when we're in shutdown
+ // mode? Can't just set a global because this'll mean no processes can
+ // start. Probably need to do it based on the security context of the
+ // user shutting down.
+ //
+
+ AcquireProcessStructureLock();
+
+ //
+ // Mark the root process as system context.
+ //
+
+ CsrRootProcess->ShutdownFlags |= SHUTDOWN_SYSTEMCONTEXT;
+
+ //
+ // Clear all the bits indicating that shutdown has visited this process.
+ //
+
+ ListHead = &CsrRootProcess->ListLink;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Process = CONTAINING_RECORD(ListNext, CSR_PROCESS, ListLink);
+ Process->Flags &= ~CSR_PROCESS_SHUTDOWNSKIP;
+ Process->ShutdownFlags = 0;
+ ListNext = ListNext->Flink;
+ }
+ try {
+ CsrpSetToShutdownPriority();
+ while (TRUE) {
+
+ //
+ // Find the next process to shutdown.
+ //
+
+ Process = FindProcessForShutdown(CallerLuid);
+
+ if (Process == NULL) {
+ ReleaseProcessStructureLock();
+ Status = STATUS_SUCCESS;
+ goto ExitLoop;
+ }
+
+ //
+ // If this process is debugging the server, don't shut it down or
+ // else the system will hang.
+ //
+#ifdef DEVL
+ if (fFindDebugger) {
+ if (Process->ClientId.UniqueProcess ==
+ ClientIdWin32ServerDebugger.UniqueProcess) {
+ Process->Flags |= CSR_PROCESS_SHUTDOWNSKIP;
+ Process->ShutdownFlags |= SHUTDOWN_SYSTEMCONTEXT;
+ fFindDebugger = FALSE;
+ continue;
+ }
+ }
+#endif // DEVL
+
+ CsrLockedReferenceProcess(Process);
+
+ fFirstPass = TRUE;
+TryAgain:
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->ShutdownProcessRoutine) {
+
+ //
+ // Release process structure lock before calling off.
+ // CSR_PROCESS structure is still reference counted.
+ //
+ ReleaseProcessStructureLock();
+ Command = (*LoadedServerDll->ShutdownProcessRoutine)(
+ Process, Flags, fFirstPass);
+ AcquireProcessStructureLock();
+
+ if (Command == SHUTDOWN_KNOWN_PROCESS) {
+ //
+ // Process structure is unlocked.
+ //
+ break;
+ }
+ if (Command == SHUTDOWN_UNKNOWN_PROCESS) {
+ //
+ // Process structure is locked.
+ //
+ continue;
+ }
+ if (Command == SHUTDOWN_CANCEL) {
+#if DBG
+ if (Flags & 4) {
+ DbgPrint("Process %x cancelled forced shutdown (Dll = %d)\n",
+ Process->ClientId.UniqueProcess, i);
+ DbgBreakPoint();
+ }
+#endif
+ //
+ // Unlock process structure.
+ //
+ ReleaseProcessStructureLock();
+ Status = STATUS_CANCELLED;
+ goto ExitLoop;
+ }
+ }
+ }
+
+ //
+ // No subsystem has an exact match. Now go through them again and
+ // let them know there was no exact match. Some .dll should terminate
+ // it for us (most likely, console).
+ //
+
+ if (fFirstPass && Command == SHUTDOWN_UNKNOWN_PROCESS) {
+ fFirstPass = FALSE;
+ goto TryAgain;
+ }
+
+ //
+ // Dereference this process structure if nothing knows about it
+ // we hit the end of our loop.
+ //
+ if (i == CSR_MAX_SERVER_DLL)
+ CsrLockedDereferenceProcess(Process);
+
+ }
+ExitLoop:;
+ }
+ finally {
+ CsrpSetToNormalPriority();
+ return Status;
+ }
+}
+
+PCSR_PROCESS
+FindProcessForShutdown(
+ PLUID CallerLuid
+ )
+{
+ LUID ProcessLuid;
+ LUID SystemLuid = SYSTEM_LUID;
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_PROCESS Process;
+ PCSR_PROCESS ProcessT;
+ PCSR_THREAD Thread;
+ ULONG dwLevel;
+ BOOLEAN fEqual;
+ NTSTATUS Status;
+
+ ProcessT = NULL;
+ dwLevel = 0;
+
+ ListHead = &CsrRootProcess->ListLink;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ Process = CONTAINING_RECORD(ListNext, CSR_PROCESS, ListLink);
+ ListNext = ListNext->Flink;
+
+ //
+ // If we've visited this process already, then skip it.
+ //
+
+ if (Process->Flags & CSR_PROCESS_SHUTDOWNSKIP)
+ continue;
+
+ //
+ // See if this process is running under the passed sid. If not, mark
+ // it as visited and continue.
+ //
+
+ Status = CsrGetProcessLuid(Process->ProcessHandle, &ProcessLuid);
+ if (Status == STATUS_ACCESS_DENIED && Process->ThreadCount > 0) {
+
+ //
+ // Impersonate one of the threads and try again.
+ //
+ Thread = CONTAINING_RECORD( Process->ThreadList.Flink,
+ CSR_THREAD, Link );
+ if (NT_SUCCESS(CsrImpersonateClient(Thread))) {
+ Status = CsrGetProcessLuid(NULL, &ProcessLuid);
+ CsrRevertToSelf();
+ }
+ }
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // We don't have access to this process' luid, so skip it
+ //
+
+ Process->Flags |= CSR_PROCESS_SHUTDOWNSKIP;
+ continue;
+ }
+
+ //
+ // is it equal to the system context luid? If so, we want to
+ // remember this because we don't terminate this process:
+ // we only notify them.
+ //
+
+ fEqual = RtlEqualLuid(&ProcessLuid,&SystemLuid);
+ if (fEqual) {
+ Process->ShutdownFlags |= SHUTDOWN_SYSTEMCONTEXT;
+ }
+
+ //
+ // See if this process's luid is the same as the luid we're supposed
+ // to shut down (CallerSid).
+ //
+
+ if (!fEqual) {
+ fEqual = RtlEqualLuid(&ProcessLuid, CallerLuid);
+ }
+
+ //
+ // If not equal to either, mark it as such and return
+ //
+
+ if (!fEqual) {
+ Process->ShutdownFlags |= SHUTDOWN_OTHERCONTEXT;
+ }
+
+ if (Process->ShutdownLevel > dwLevel) {
+ dwLevel = Process->ShutdownLevel;
+ ProcessT = Process;
+ }
+ }
+
+ if (ProcessT != NULL) {
+ ProcessT->Flags |= CSR_PROCESS_SHUTDOWNSKIP;
+ return ProcessT;
+ }
+
+ return NULL;
+}
+
+NTSTATUS
+CsrGetProcessLuid(
+ HANDLE ProcessHandle,
+ PLUID LuidProcess
+ )
+{
+ HANDLE UserToken = NULL;
+ PTOKEN_STATISTICS pStats;
+ ULONG BytesRequired;
+ NTSTATUS Status, CloseStatus;
+
+ if (ProcessHandle == NULL) {
+
+ //
+ // Check for a thread token first
+ //
+
+ Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE,
+ &UserToken);
+
+ if (!NT_SUCCESS(Status)) {
+ if (Status != STATUS_NO_TOKEN)
+ return Status;
+
+ //
+ // No thread token, go to the process
+ //
+
+ ProcessHandle = NtCurrentProcess();
+ UserToken = NULL;
+ }
+ }
+
+ if (UserToken == NULL) {
+ Status = NtOpenProcessToken(ProcessHandle, TOKEN_QUERY, &UserToken);
+ if (!NT_SUCCESS(Status))
+ return Status;
+ }
+
+ Status = NtQueryInformationToken(
+ UserToken, // Handle
+ TokenStatistics, // TokenInformationClass
+ NULL, // TokenInformation
+ 0, // TokenInformationLength
+ &BytesRequired // ReturnLength
+ );
+
+ if (Status != STATUS_BUFFER_TOO_SMALL) {
+ NtClose(UserToken);
+ return Status;
+ }
+
+ //
+ // Allocate space for the user info
+ //
+
+ pStats = (PTOKEN_STATISTICS)RtlAllocateHeap(CsrHeap, MAKE_TAG( TMP_TAG ), BytesRequired);
+ if (pStats == NULL) {
+ NtClose(UserToken);
+ return Status;
+ }
+
+ //
+ // Read in the user info
+ //
+
+ Status = NtQueryInformationToken(
+ UserToken, // Handle
+ TokenStatistics, // TokenInformationClass
+ pStats, // TokenInformation
+ BytesRequired, // TokenInformationLength
+ &BytesRequired // ReturnLength
+ );
+
+ //
+ // We're finished with the token handle
+ //
+
+ CloseStatus = NtClose(UserToken);
+ ASSERT(NT_SUCCESS(CloseStatus));
+
+ //
+ // Return the authentication LUID
+ //
+
+ *LuidProcess = pStats->AuthenticationId;
+
+ RtlFreeHeap(CsrHeap, 0, pStats);
+ return Status;
+}
+
+VOID
+CsrSetCallingSpooler(
+ BOOLEAN fSet)
+{
+
+ //
+ // Obsolete function that may be called by third part drivers.
+ //
+ return;
+
+ fSet;
+}
+
+#if CSRSS_PROTECT_HANDLES
+BOOLEAN
+ProtectHandle(
+ HANDLE hObject
+ )
+{
+ NTSTATUS Status;
+ OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
+
+ Status = NtQueryObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo ),
+ NULL
+ );
+ if (NT_SUCCESS( Status )) {
+ HandleInfo.ProtectFromClose = TRUE;
+
+ Status = NtSetInformationObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo )
+ );
+ if (NT_SUCCESS( Status )) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOLEAN
+UnProtectHandle(
+ HANDLE hObject
+ )
+{
+ NTSTATUS Status;
+ OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
+
+ Status = NtQueryObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo ),
+ NULL
+ );
+ if (NT_SUCCESS( Status )) {
+ HandleInfo.ProtectFromClose = FALSE;
+
+ Status = NtSetInformationObject( hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof( HandleInfo )
+ );
+ if (NT_SUCCESS( Status )) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
diff --git a/private/csr/server/sbapi.c b/private/csr/server/sbapi.c
new file mode 100644
index 000000000..d2936e51c
--- /dev/null
+++ b/private/csr/server/sbapi.c
@@ -0,0 +1,171 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sbapi.c
+
+Abstract:
+
+ This module contains the implementations of the Sb API calls exported
+ by the Server side of the Client-Server Runtime Subsystem to the
+ Session Manager SubSystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+VOID
+CsrpComputePriority(
+ IN ULONG PriorityClass,
+ OUT PUCHAR ProcessPriorityClass
+
+ );
+
+BOOLEAN
+CsrSbCreateSession(
+ IN PSBAPIMSG Msg
+ )
+{
+ PSBCREATESESSION a = &Msg->u.CreateSession;
+ PCSR_PROCESS Process;
+ PCSR_THREAD Thread;
+ PVOID ProcessDataPtr;
+ ULONG i;
+ NTSTATUS Status;
+ HANDLE ProcessHandle;
+ HANDLE ThreadHandle;
+ KERNEL_USER_TIMES TimeInfo;
+
+
+ ProcessHandle = a->ProcessInformation.Process;
+ ThreadHandle = a->ProcessInformation.Thread;
+
+ AcquireProcessStructureLock();
+ Process = CsrAllocateProcess();
+ if (Process == NULL) {
+ Msg->ReturnedStatus = STATUS_NO_MEMORY;
+ ReleaseProcessStructureLock();
+ return( TRUE );
+ }
+
+ Status = NtSetInformationProcess(
+ ProcessHandle,
+ ProcessExceptionPort,
+ &CsrApiPort,
+ sizeof(HANDLE)
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( (BOOLEAN)STATUS_NO_MEMORY );
+ }
+
+ CsrpComputePriority(
+ CSR_NORMAL_PRIORITY_CLASS,
+ &Process->PriorityClass
+ );
+
+ CsrSetBackgroundPriority(Process);
+
+ //
+ // capture the thread's createtime so that we can use
+ // this as a sequence number
+ //
+
+ Status = NtQueryInformationThread(
+ ThreadHandle,
+ ThreadTimes,
+ (PVOID)&TimeInfo,
+ sizeof(TimeInfo),
+ NULL
+ );
+ if ( !NT_SUCCESS(Status) ) {
+ CsrDeallocateProcess( Process );
+ ReleaseProcessStructureLock();
+ return( (BOOLEAN)Status );
+ }
+
+ Thread = CsrAllocateThread( Process );
+ if (Thread == NULL) {
+ CsrDeallocateProcess( Process );
+ Msg->ReturnedStatus = STATUS_NO_MEMORY;
+ ReleaseProcessStructureLock();
+ return( TRUE );
+ }
+
+ CsrInitializeThreadData(Thread, NULL);
+
+ Thread->CreateTime = TimeInfo.CreateTime;
+ Thread->ClientId = a->ProcessInformation.ClientId;
+ Thread->ThreadHandle = a->ProcessInformation.Thread;
+
+ProtectHandle(Thread->ThreadHandle);
+
+ Thread->Flags = 0;
+ CsrInsertThread( Process, Thread );
+
+ //
+ // this needs a little more thought
+ //
+ Process->NtSession = CsrAllocateNtSession( a->SessionId );
+
+ Process->ClientId = a->ProcessInformation.ClientId;
+ Process->ProcessHandle = a->ProcessInformation.Process;
+
+ //
+ // initialize each DLL's per process data area.
+ //
+
+ ProcessDataPtr = (PVOID)QUAD_ALIGN(&Process->ServerDllPerProcessData[CSR_MAX_SERVER_DLL]);
+ for (i=0;i<CSR_MAX_SERVER_DLL;i++) {
+ if (CsrLoadedServerDll[i] != NULL && CsrLoadedServerDll[i]->PerProcessDataLength) {
+ Process->ServerDllPerProcessData[i] = ProcessDataPtr;
+ ProcessDataPtr = (PVOID)QUAD_ALIGN((ULONG)ProcessDataPtr + CsrLoadedServerDll[i]->PerProcessDataLength);
+ }
+ else {
+ Process->ServerDllPerProcessData[i] = NULL;
+ }
+ }
+
+ CsrSetProcessContext( Process,
+ Thread,
+ TRUE
+ );
+
+ CsrInsertProcess( NULL, NULL, Process );
+ Msg->ReturnedStatus = NtResumeThread( a->ProcessInformation.Thread,
+ NULL
+ );
+ ReleaseProcessStructureLock();
+ return( TRUE );
+}
+
+BOOLEAN
+CsrSbTerminateSession(
+ IN PSBAPIMSG Msg
+ )
+{
+ PSBTERMINATESESSION a = &Msg->u.TerminateSession;
+
+ Msg->ReturnedStatus = STATUS_NOT_IMPLEMENTED;
+ return( TRUE );
+}
+
+BOOLEAN
+CsrSbForeignSessionComplete(
+ IN PSBAPIMSG Msg
+ )
+{
+ PSBFOREIGNSESSIONCOMPLETE a = &Msg->u.ForeignSessionComplete;
+
+ Msg->ReturnedStatus = STATUS_NOT_IMPLEMENTED;
+ return( TRUE );
+}
diff --git a/private/csr/server/sbinit.c b/private/csr/server/sbinit.c
new file mode 100644
index 000000000..f45e618e3
--- /dev/null
+++ b/private/csr/server/sbinit.c
@@ -0,0 +1,100 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sbinit.c
+
+Abstract:
+
+ This module contains the code to initialize the SbApiPort of the
+ Server side of the Client-Server Runtime Subsystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+NTSTATUS
+CsrSbApiPortInitialize( VOID )
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ HANDLE Thread;
+ CLIENT_ID ClientId;
+ ULONG n;
+
+ n = CsrDirectoryName.Length +
+ sizeof( CSR_SBAPI_PORT_NAME ) +
+ sizeof( OBJ_NAME_PATH_SEPARATOR );
+ CsrSbApiPortName.Buffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( INIT_TAG ), n );
+ if (CsrSbApiPortName.Buffer == NULL) {
+ return( STATUS_NO_MEMORY );
+ }
+ CsrSbApiPortName.Length = 0;
+ CsrSbApiPortName.MaximumLength = (USHORT)n;
+ RtlAppendUnicodeStringToString( &CsrSbApiPortName, &CsrDirectoryName );
+ RtlAppendUnicodeToString( &CsrSbApiPortName, L"\\" );
+ RtlAppendUnicodeToString( &CsrSbApiPortName, CSR_SBAPI_PORT_NAME );
+
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: Creating %wZ port and associated thread\n",
+ &CsrSbApiPortName );
+ }
+
+ InitializeObjectAttributes( &ObjectAttributes, &CsrSbApiPortName, 0,
+ NULL, NULL );
+ Status = NtCreatePort( &CsrSbApiPort,
+ &ObjectAttributes,
+ sizeof( SBCONNECTINFO ),
+ sizeof( SBAPIMSG ),
+ sizeof( SBAPIMSG ) * 32
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ Status = RtlCreateUserThread( NtCurrentProcess(),
+ NULL,
+ TRUE,
+ 0,
+ 0,
+ 0,
+ CsrSbApiRequestThread,
+ NULL,
+ &Thread,
+ &ClientId
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+ CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(Thread,&ClientId,0);
+
+ Status = NtResumeThread( Thread, NULL );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ return( Status );
+}
+
+
+VOID
+CsrSbApiPortTerminate(
+ NTSTATUS Status
+ )
+{
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: Closing Sb port and associated thread\n" );
+ }
+ NtTerminateThread( CsrSbApiRequestThreadPtr->ThreadHandle,
+ Status
+ );
+
+ NtClose( CsrSbApiPort );
+ NtClose( CsrSmApiPort );
+}
diff --git a/private/csr/server/sbreqst.c b/private/csr/server/sbreqst.c
new file mode 100644
index 000000000..b6e44c10a
--- /dev/null
+++ b/private/csr/server/sbreqst.c
@@ -0,0 +1,175 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sbreqst.c
+
+Abstract:
+
+ This module contains the Server Request thread procedure for the Sb
+ API calls exported by the Server side of the Client-Server Runtime
+ Subsystem to the Session Manager SubSystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+PSB_API_ROUTINE CsrServerSbApiDispatch[ SbMaxApiNumber+1 ] = {
+ CsrSbCreateSession,
+ CsrSbTerminateSession,
+ CsrSbForeignSessionComplete,
+ NULL
+};
+
+#if DBG
+PSZ CsrServerSbApiName[ SbMaxApiNumber+1 ] = {
+ "SbCreateSession",
+ "SbTerminateSession",
+ "SbForeignSessionComplete",
+ "Unknown Csr Sb Api Number"
+};
+#endif // DBG
+
+
+NTSTATUS
+CsrSbApiHandleConnectionRequest(
+ IN PSBAPIMSG Message
+ );
+
+NTSTATUS
+CsrSbApiRequestThread(
+ IN PVOID Parameter
+ )
+{
+ NTSTATUS Status;
+ SBAPIMSG ReceiveMsg;
+ PSBAPIMSG ReplyMsg;
+
+ ReplyMsg = NULL;
+ while (TRUE) {
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: Sb Api Request Thread waiting...\n" );
+ }
+ Status = NtReplyWaitReceivePort( CsrSbApiPort,
+ NULL,
+ (PPORT_MESSAGE)ReplyMsg,
+ (PPORT_MESSAGE)&ReceiveMsg
+ );
+
+ if (Status != 0) {
+ if (NT_SUCCESS( Status )) {
+ continue; // Try again if alerted or a failure
+ }
+ else {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: ReceivePort failed - Status == %X\n", Status );
+ }
+ break;
+ }
+ }
+
+ //
+ // Check to see if this is a connection request and handle
+ //
+
+ if (ReceiveMsg.h.u2.s2.Type == LPC_CONNECTION_REQUEST) {
+ CsrSbApiHandleConnectionRequest( &ReceiveMsg );
+ ReplyMsg = NULL;
+ continue;
+ }
+
+ if ((ULONG)ReceiveMsg.ApiNumber >= SbMaxApiNumber) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: %lx is invalid Sb ApiNumber\n",
+ ReceiveMsg.ApiNumber
+ );
+ }
+
+ ReceiveMsg.ApiNumber = SbMaxApiNumber;
+ }
+
+#if DBG
+ IF_CSR_DEBUG( LPC ) {
+ DbgPrint( "CSRSS: %s Sb Api Request received from %lx.%lx\n",
+ CsrServerSbApiName[ ReceiveMsg.ApiNumber ],
+ ReceiveMsg.h.ClientId.UniqueProcess,
+ ReceiveMsg.h.ClientId.UniqueThread
+ );
+ }
+#endif // DBG
+
+ ReplyMsg = &ReceiveMsg;
+ if (ReceiveMsg.ApiNumber < SbMaxApiNumber) {
+ if (!(*CsrServerSbApiDispatch[ ReceiveMsg.ApiNumber ])( &ReceiveMsg )) {
+ ReplyMsg = NULL;
+ }
+ }
+ else {
+ ReplyMsg->ReturnedStatus = STATUS_NOT_IMPLEMENTED;
+ }
+
+#if DBG
+ IF_CSR_DEBUG( LPC ) {
+ if (ReplyMsg != NULL) {
+ DbgPrint( "CSRSS: %s Sb Api sending %lx status reply to %lx.%lx\n",
+ CsrServerSbApiName[ ReceiveMsg.ApiNumber ],
+ ReplyMsg->ReturnedStatus,
+ ReplyMsg->h.ClientId.UniqueProcess,
+ ReplyMsg->h.ClientId.UniqueThread
+ );
+ }
+ }
+#endif // DBG
+ }
+
+ NtTerminateThread( NtCurrentThread(), Status );
+
+ return( Status ); // Remove no return value warning.
+ Parameter; // Remove unreferenced parameter warning.
+}
+
+NTSTATUS
+CsrSbApiHandleConnectionRequest(
+ IN PSBAPIMSG Message
+ )
+{
+ NTSTATUS st;
+ REMOTE_PORT_VIEW ClientView;
+ HANDLE CommunicationPort;
+
+ //
+ // The protocol for a subsystem is to connect to the session manager,
+ // then to listen and accept a connection from the session manager
+ //
+
+ ClientView.Length = sizeof(ClientView);
+ st = NtAcceptConnectPort(
+ &CommunicationPort,
+ NULL,
+ (PPORT_MESSAGE)Message,
+ TRUE,
+ NULL,
+ &ClientView
+ );
+
+ if ( !NT_SUCCESS(st) ) {
+ KdPrint(("CSRSS: Sb Accept Connection failed %lx\n",st));
+ return st;
+ }
+
+ st = NtCompleteConnectPort(CommunicationPort);
+
+ if ( !NT_SUCCESS(st) ) {
+ KdPrint(("CSRSS: Sb Complete Connection failed %lx\n",st));
+ }
+
+ return st;
+}
diff --git a/private/csr/server/semphore b/private/csr/server/semphore
new file mode 100644
index 000000000..df3ef3edd
--- /dev/null
+++ b/private/csr/server/semphore
@@ -0,0 +1,30 @@
+To prevent deadlock, semaphores must be taken in the following
+order:
+
+ ProcessStructureLock
+ ProcessLock
+ ThreadLock
+ CurrentConsoleLock
+ ConsoleHandleTableLock
+ ConsoleLock
+ ReadCountLock (console)
+ WaitListsLock
+
+
+ProcessStructureLock -
+ must be held to change process or thread structure.
+ held while traversing process/thread tree. always must be held
+ when calling CsrLocateThreadByClientId.
+
+ProcessLock -
+ must be held exclusively to destroy a process
+ can be held shared or exclusive.
+ held shared for during of an api call so that process isn't destroyed
+ by another process during call.
+ held exclusively means that no one else can access contents
+
+ThreadLock -
+ must be held exclusively to destroy a thread
+ can be held shared or exclusive.
+ held shared for during of an api call so that thread isn't destroyed
+ by another thread during call.
diff --git a/private/csr/server/session.c b/private/csr/server/session.c
new file mode 100644
index 000000000..729d9a8ba
--- /dev/null
+++ b/private/csr/server/session.c
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ session.c
+
+Abstract:
+
+ This module contains the worker routines called by the Sb API
+ Request routines in sbapi.c to create and delete sessions. Also
+ called whenever an application process creates a new child process
+ within the same session.
+
+Author:
+
+ Steve Wood (stevewo) 08-Oct-1990
+
+Revision History:
+
+--*/
+
+
+#include "csrsrv.h"
+
+NTSTATUS
+CsrInitializeNtSessionList( VOID )
+{
+ NTSTATUS Status;
+
+ InitializeListHead( &CsrNtSessionList );
+
+ Status = RtlInitializeCriticalSection( &CsrNtSessionLock );
+ return( Status );
+}
+
+
+PCSR_NT_SESSION
+CsrAllocateNtSession(
+ ULONG SessionId
+ )
+{
+ PCSR_NT_SESSION Session;
+
+ Session = RtlAllocateHeap( CsrHeap, MAKE_TAG( PROCESS_TAG ), sizeof( CSR_NT_SESSION ) );
+ ASSERT( Session != NULL );
+
+ if (Session != NULL) {
+ Session->SessionId = SessionId;
+ Session->ReferenceCount = 1;
+ LockNtSessionList();
+ InsertHeadList( &CsrNtSessionList, &Session->SessionLink );
+ UnlockNtSessionList();
+ }
+
+ return( Session );
+}
+
+VOID
+CsrReferenceNtSession(
+ PCSR_NT_SESSION Session
+ )
+{
+ LockNtSessionList();
+
+ ASSERT( !IsListEmpty( &Session->SessionLink ) );
+ ASSERT( Session->SessionId != 0 );
+ ASSERT( Session->ReferenceCount != 0 );
+ Session->ReferenceCount++;
+ UnlockNtSessionList();
+}
+
+VOID
+CsrDereferenceNtSession(
+ PCSR_NT_SESSION Session,
+ NTSTATUS ExitStatus
+ )
+{
+ LockNtSessionList();
+
+ ASSERT( !IsListEmpty( &Session->SessionLink ) );
+ ASSERT( Session->SessionId != 0 );
+ ASSERT( Session->ReferenceCount != 0 );
+
+ if (--Session->ReferenceCount == 0) {
+ RemoveEntryList( &Session->SessionLink );
+ UnlockNtSessionList();
+ SmSessionComplete(CsrSmApiPort,Session->SessionId,ExitStatus);
+ RtlFreeHeap( CsrHeap, 0, Session );
+ }
+ else {
+ UnlockNtSessionList();
+ }
+}
diff --git a/private/csr/server/sources b/private/csr/server/sources
new file mode 100644
index 000000000..6b4e11410
--- /dev/null
+++ b/private/csr/server/sources
@@ -0,0 +1,62 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=csr
+MINORCOMP=server
+
+TARGETNAME=csrsrv
+TARGETPATH=obj
+TARGETPATHLIB=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\smdll.lib
+
+INCLUDES=..\inc
+
+USE_NTDLL=1
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+C_DEFINES=$(C_DEFINES) -D_CSRSRV_
+
+BACKGROUND_USE=1
+
+SOURCES=srvinit.c \
+ srvloadr.c \
+ sbinit.c \
+ sbreqst.c \
+ sbapi.c \
+ apiinit.c \
+ apireqst.c \
+ session.c \
+ process.c \
+ csrdebug.c \
+ csrss.rc \
+ wait.c
+
+DLLDEF=obj\*\csrsrv.def
+
+UMTYPE=ntss
+UMAPPL=csrss
+UMLIBS=$(BASEDIR)\public\sdk\lib\*\csrsrv.lib obj\*\csrss.res
+COFFBASE=csrss
diff --git a/private/csr/server/srvinit.c b/private/csr/server/srvinit.c
new file mode 100644
index 000000000..5cd909496
--- /dev/null
+++ b/private/csr/server/srvinit.c
@@ -0,0 +1,580 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ srvinit.c
+
+Abstract:
+
+ This is the main initialization module for the Server side of the Client
+ Server Runtime Subsystem (CSRSS)
+
+Author:
+
+ Steve Wood (stevewo) 08-Oct-1990
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+PCSR_API_ROUTINE CsrServerApiDispatchTable[ CsrpMaxApiNumber ] = {
+ (PCSR_API_ROUTINE)CsrSrvNullApiCall,
+ (PCSR_API_ROUTINE)CsrSrvClientConnect,
+ (PCSR_API_ROUTINE)NULL,
+ (PCSR_API_ROUTINE)CsrSrvProfileControl,
+ (PCSR_API_ROUTINE)CsrSrvIdentifyAlertableThread,
+ (PCSR_API_ROUTINE)CsrSrvSetPriorityClass
+};
+
+BOOLEAN CsrServerApiServerValidTable[ CsrpMaxApiNumber ] = {
+ TRUE, // CsrSrvNullApiCall,
+ TRUE, // CsrSrvClientConnect,
+ FALSE, // CsrSrvThreadConnect,
+ TRUE, // CsrSrvProfileControl,
+ TRUE, // CsrSrvIdentifyAlertableThread
+ TRUE // CsrSrvSetPriorityClass
+};
+
+#if DBG
+PSZ CsrServerApiNameTable[ CsrpMaxApiNumber ] = {
+ "NullApiCall",
+ "ClientConnect",
+ "ThreadConnect",
+ "ProfileControl",
+ "IdentifyAlertableThread",
+ "SetPriorityClass"
+};
+#endif // DBG
+
+NTSTATUS
+CsrSetProcessSecurity(
+ VOID
+ );
+
+NTSTATUS
+CsrServerInitialization(
+ IN ULONG argc,
+ IN PCH argv[]
+ )
+{
+ NTSTATUS Status;
+ ULONG i;
+ PVOID ProcessDataPtr;
+ PTEB Teb;
+ PCSR_SERVER_DLL LoadedServerDll;
+
+// Initialize GDI accelerators. This thread ends up in GDI doing graphics,
+// courtesy of USER! (Also see SRVQUICK.C, APIREQST.C)
+
+ Teb = NtCurrentTeb();
+ Teb->GdiClientPID = PID_SERVERLPC;
+ Teb->GdiClientTID = (ULONG) Teb->ClientId.UniqueThread;
+
+ Status = NtCreateEvent(&CsrInitializationEvent,
+ EVENT_ALL_ACCESS,
+ NULL,
+ SynchronizationEvent,
+ FALSE
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Save away system information in a global variable
+ //
+
+ Status = NtQuerySystemInformation( SystemBasicInformation,
+ &CsrNtSysInfo,
+ sizeof( CsrNtSysInfo ),
+ NULL
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Use the process heap for memory allocation.
+ //
+
+ CsrHeap = RtlProcessHeap();
+ CsrBaseTag = RtlCreateTagHeap( CsrHeap,
+ 0,
+ L"CSRSS!",
+ L"TMP\0"
+ L"INIT\0"
+ L"CAPTURE\0"
+ L"PROCESS\0"
+ );
+
+
+ //
+ // Set up CSRSS process security
+ //
+
+ Status = CsrSetProcessSecurity();
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Initialize the Session List
+ //
+
+ Status = CsrInitializeNtSessionList();
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Initialize the Process List
+ //
+
+ Status = CsrInitializeProcessStructure();
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Process the command line arguments
+ //
+
+ Status = CsrParseServerCommandLine( argc, argv );
+ ASSERT( NT_SUCCESS( Status ) );
+
+
+ //
+ // Fix up per-process data for root process
+ //
+
+ ProcessDataPtr = (PCSR_PROCESS)RtlAllocateHeap( CsrHeap,
+ MAKE_TAG( PROCESS_TAG ) | HEAP_ZERO_MEMORY,
+ CsrTotalPerProcessDataLength
+ );
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->PerProcessDataLength) {
+ CsrRootProcess->ServerDllPerProcessData[i] = ProcessDataPtr;
+ ProcessDataPtr = (PVOID)QUAD_ALIGN((ULONG)ProcessDataPtr + LoadedServerDll->PerProcessDataLength);
+ }
+ else {
+ CsrRootProcess->ServerDllPerProcessData[i] = NULL;
+ }
+ }
+
+ //
+ // Let server dlls know about the root process.
+ //
+
+ for (i=0; i<CSR_MAX_SERVER_DLL; i++) {
+ LoadedServerDll = CsrLoadedServerDll[ i ];
+ if (LoadedServerDll && LoadedServerDll->AddProcessRoutine) {
+ (*LoadedServerDll->AddProcessRoutine)( NULL, CsrRootProcess );
+ }
+ }
+
+ //
+ // Initialize the Windows Server API Port, and one or more
+ // request threads.
+ //
+
+ CsrpServerDebugInitialize = FALSE;
+
+ Status = CsrApiPortInitialize();
+ ASSERT( NT_SUCCESS( Status ) );
+
+ Status = DbgSsInitialize( CsrApiPort, CsrUiLookup , NULL, NULL );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Initialize the Server Session Manager API Port and one
+ // request thread.
+ //
+
+ Status = CsrSbApiPortInitialize();
+ ASSERT( NT_SUCCESS( Status ) );
+
+ //
+ // Connect to the session manager so we can start foreign sessions
+ //
+
+ Status = SmConnectToSm( &CsrSbApiPortName,
+ CsrSbApiPort,
+ CsrSubSystemType,
+ &CsrSmApiPort
+ );
+ ASSERT( NT_SUCCESS( Status ) );
+
+ Status = NtSetEvent(CsrInitializationEvent,NULL);
+ ASSERT( NT_SUCCESS( Status ) );
+ NtClose(CsrInitializationEvent);
+
+ Status = NtSetDefaultHardErrorPort(CsrApiPort);
+ return( Status );
+}
+
+// BUGBUG this routine should go away when we get exportable DLL data
+NTSTATUS
+CsrGetApiPorts(
+ OUT PHANDLE SbApiPort OPTIONAL,
+ OUT PHANDLE SmApiPort OPTIONAL
+ )
+{
+ if (ARGUMENT_PRESENT(SbApiPort)) {
+ *SbApiPort = CsrSbApiPort;
+ }
+ if (ARGUMENT_PRESENT(SmApiPort)) {
+ *SmApiPort = CsrSmApiPort;
+ }
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+CsrParseServerCommandLine(
+ IN ULONG argc,
+ IN PCH argv[]
+ )
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG i, ServerDllIndex;
+ PCH KeyName, KeyValue, s;
+ PCH InitRoutine;
+
+ CsrTotalPerProcessDataLength = 0;
+ CsrTotalPerThreadDataLength = 0;
+ CsrSubSystemType = IMAGE_SUBSYSTEM_WINDOWS_GUI;
+ CsrObjectDirectory = NULL;
+ CsrMaxApiRequestThreads = CSR_MAX_THREADS;
+
+ for (i=1; i<argc ; i++) {
+ KeyName = argv[ i ];
+ KeyValue = NULL;
+ while (*KeyName) {
+ if (*KeyName == '=') {
+ *KeyName++ = '\0';
+ KeyValue = KeyName;
+ break;
+ }
+
+ KeyName++;
+ }
+ KeyName = argv[ i ];
+
+ if (!_stricmp( KeyName, "ObjectDirectory" )) {
+ ANSI_STRING AnsiString;
+
+ //
+ // Create an object directory in the object name space with the
+ // name specified. It will be the root for all object names
+ // created by the Server side of the Client Server Runtime
+ // SubSystem.
+ //
+
+ RtlInitString( &AnsiString, KeyValue );
+ Status = RtlAnsiStringToUnicodeString( &CsrDirectoryName, &AnsiString, TRUE );
+ ASSERT(NT_SUCCESS(Status));
+ InitializeObjectAttributes( &ObjectAttributes,
+ &CsrDirectoryName,
+ OBJ_PERMANENT | OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+ Status = NtCreateDirectoryObject( &CsrObjectDirectory,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes
+ );
+ if (!NT_SUCCESS( Status )) {
+ break;
+ }
+ }
+ else
+ if (!_stricmp( KeyName, "SubSystemType" )) {
+ }
+ else
+ if (!_stricmp( KeyName, "MaxRequestThreads" )) {
+ Status = RtlCharToInteger( KeyValue,
+ (ULONG)NULL,
+ &CsrMaxApiRequestThreads
+ );
+ }
+ else
+ if (!_stricmp( KeyName, "RequestThreads" )) {
+#if 0
+ Status = RtlCharToInteger( KeyValue,
+ (ULONG)NULL,
+ &CsrNumberApiRequestThreads
+ );
+#else
+ //
+ // wait until hive change !
+ //
+
+ Status = STATUS_SUCCESS;
+
+#endif
+ }
+ else
+ if (!_stricmp( KeyName, "ProfileControl" )) {
+ if(!_stricmp( KeyValue, "On" )) {
+ CsrProfileControl = TRUE;
+ }
+ else {
+ CsrProfileControl = FALSE;
+ }
+ }
+ else
+ if (!_stricmp( KeyName, "SharedSection" )) {
+ Status = CsrSrvCreateSharedSection( KeyValue );
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: *** Invalid syntax for %s=%s (Status == %X)\n",
+ KeyName,
+ KeyValue,
+ Status
+ );
+ }
+ }
+ Status = CsrLoadServerDll( "CSRSS", NULL, CSRSRV_SERVERDLL_INDEX );
+ }
+ else
+ if (!_stricmp( KeyName, "ServerDLL" )) {
+ s = KeyValue;
+ InitRoutine = NULL;
+
+ Status = STATUS_INVALID_PARAMETER;
+ while (*s) {
+ if ((*s == ':') && (InitRoutine == NULL)) {
+ *s++ = '\0';
+ InitRoutine = s;
+ }
+
+ if (*s++ == ',') {
+ Status = RtlCharToInteger ( s, 10, &ServerDllIndex );
+ if (NT_SUCCESS( Status )) {
+ s[ -1 ] = '\0';
+ }
+
+ break;
+ }
+ }
+
+ if (!NT_SUCCESS( Status )) {
+ IF_DEBUG {
+ DbgPrint( "CSRSS: *** Invalid syntax for ServerDll=%s (Status == %X)\n",
+ KeyValue,
+ Status
+ );
+ }
+ }
+ else {
+ IF_CSR_DEBUG( INIT) {
+ DbgPrint( "CSRSS: Loading ServerDll=%s:%s\n", KeyValue, InitRoutine );
+ }
+
+ Status = CsrLoadServerDll( KeyValue, InitRoutine, ServerDllIndex);
+
+ IF_DEBUG {
+ if (!NT_SUCCESS( Status )) {
+ DbgPrint( "CSRSS: *** Failed loading ServerDll=%s (Status == %X)\n",
+ KeyValue,
+ Status
+ );
+ }
+ }
+ }
+ }
+ else
+ //
+ // This is a temporary hack until Windows & Console are friends.
+ //
+ if (!_stricmp( KeyName, "Windows" )) {
+ }
+ else {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ return( Status );
+}
+
+
+NTSTATUS
+CsrServerDllInitialization(
+ IN PCSR_SERVER_DLL LoadedServerDll
+ )
+{
+ PVOID SharedHeap;
+ PCSR_FAST_ANSI_OEM_TABLES XlateTables;
+ PVOID p;
+ NTSTATUS Status;
+
+ LoadedServerDll->ApiNumberBase = CSRSRV_FIRST_API_NUMBER;
+ LoadedServerDll->MaxApiNumber = CsrpMaxApiNumber;
+ LoadedServerDll->ApiDispatchTable = CsrServerApiDispatchTable;
+ LoadedServerDll->ApiServerValidTable = CsrServerApiServerValidTable;
+#if DBG
+ LoadedServerDll->ApiNameTable = CsrServerApiNameTable;
+#else
+ LoadedServerDll->ApiNameTable = NULL;
+#endif
+ LoadedServerDll->PerProcessDataLength = 0;
+ LoadedServerDll->PerThreadDataLength = 0;
+ LoadedServerDll->ConnectRoutine = NULL;
+ LoadedServerDll->DisconnectRoutine = NULL;
+
+
+ SharedHeap = LoadedServerDll->SharedStaticServerData;
+
+ XlateTables = RtlAllocateHeap(SharedHeap, MAKE_SHARED_TAG( SHR_INIT_TAG ), sizeof(CSR_FAST_ANSI_OEM_TABLES));
+ if ( !XlateTables ) {
+ return STATUS_NO_MEMORY;
+ }
+
+ LoadedServerDll->SharedStaticServerData = (PVOID)XlateTables;
+
+ return( STATUS_SUCCESS );
+}
+
+NTSTATUS
+CsrSrvProfileControl(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ )
+{
+ return STATUS_INVALID_PARAMETER;
+}
+
+
+
+
+NTSTATUS
+CsrSetProcessSecurity(
+ VOID
+ )
+{
+ HANDLE Token;
+ NTSTATUS Status;
+ PTOKEN_USER User;
+ ULONG LengthSid, Length;
+ PSECURITY_DESCRIPTOR SecurityDescriptor;
+ PACL Dacl;
+
+ //
+ // Open the token and get the system sid
+ //
+
+ Status = NtOpenProcessToken( NtCurrentProcess(),
+ TOKEN_QUERY,
+ &Token
+ );
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ NtQueryInformationToken( Token,
+ TokenUser,
+ NULL,
+ 0,
+ &Length
+ );
+ User = (PTOKEN_USER)RtlAllocateHeap( CsrHeap,
+ MAKE_TAG( PROCESS_TAG ) | HEAP_ZERO_MEMORY,
+ Length
+ );
+ ASSERT( User != NULL );
+ Status = NtQueryInformationToken( Token,
+ TokenUser,
+ User,
+ Length,
+ &Length
+ );
+
+ NtClose( Token );
+ if (!NT_SUCCESS(Status)) {
+ RtlFreeHeap( CsrHeap, 0, User );
+ return Status;
+ }
+ LengthSid = RtlLengthSid( User->User.Sid );
+
+ //
+ // Allocate a buffer to hold the SD
+ //
+
+ SecurityDescriptor = RtlAllocateHeap( CsrHeap,
+ MAKE_TAG( PROCESS_TAG ) | HEAP_ZERO_MEMORY,
+ SECURITY_DESCRIPTOR_MIN_LENGTH +
+ sizeof(ACL) + LengthSid +
+ sizeof(ACCESS_ALLOWED_ACE)
+ );
+ ASSERT( SecurityDescriptor != NULL );
+ Dacl = (PACL)((PCHAR)SecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
+
+
+ //
+ // Create the SD
+ //
+
+ Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
+ SECURITY_DESCRIPTOR_REVISION);
+ if (!NT_SUCCESS(Status)) {
+ IF_DEBUG {
+ DbgPrint("CSRSS: SD creation failed - status = %lx\n", Status);
+ }
+ goto error_cleanup;
+ }
+ RtlCreateAcl( Dacl,
+ sizeof(ACL) + LengthSid + sizeof(ACCESS_ALLOWED_ACE),
+ ACL_REVISION2
+ );
+ Status = RtlAddAccessAllowedAce( Dacl,
+ ACL_REVISION,
+ ( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION |
+ PROCESS_DUP_HANDLE | PROCESS_TERMINATE | PROCESS_SET_PORT |
+ READ_CONTROL | PROCESS_QUERY_INFORMATION ),
+ User->User.Sid
+ );
+ if (!NT_SUCCESS(Status)) {
+ IF_DEBUG {
+ DbgPrint("CSRSS: ACE creation failed - status = %lx\n", Status);
+ }
+ goto error_cleanup;
+ }
+
+
+ //
+ // Set DACL to NULL to deny all access
+ //
+
+ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
+ TRUE,
+ Dacl,
+ FALSE);
+ if (!NT_SUCCESS(Status)) {
+ IF_DEBUG {
+ DbgPrint("CSRSS: set DACL failed - status = %lx\n", Status);
+ }
+ goto error_cleanup;
+ }
+
+ //
+ // Put the DACL onto the process
+ //
+
+ Status = NtSetSecurityObject(NtCurrentProcess(),
+ DACL_SECURITY_INFORMATION,
+ SecurityDescriptor);
+ if (!NT_SUCCESS(Status)) {
+ IF_DEBUG {
+ DbgPrint("CSRSS: set process DACL failed - status = %lx\n", Status);
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+error_cleanup:
+ RtlFreeHeap( CsrHeap, 0, SecurityDescriptor );
+ RtlFreeHeap( CsrHeap, 0, User );
+
+ return Status;
+}
diff --git a/private/csr/server/srvloadr.c b/private/csr/server/srvloadr.c
new file mode 100644
index 000000000..67b3bd65c
--- /dev/null
+++ b/private/csr/server/srvloadr.c
@@ -0,0 +1,423 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ srvloadr.c
+
+Abstract:
+
+ This is the server DLL loader module for the Server side of the Client
+ Server Runtime Subsystem (CSRSS)
+
+Author:
+
+ Steve Wood (stevewo) 08-Oct-1990
+
+Environment:
+
+ User Mode Only
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+EXCEPTION_DISPOSITION
+CsrUnhandledExceptionFilter(
+ struct _EXCEPTION_POINTERS *ExceptionInfo
+ )
+{
+
+ UNICODE_STRING UnicodeParameter;
+ ULONG Parameters[ 4 ];
+ ULONG Response;
+ BOOLEAN WasEnabled;
+ NTSTATUS Status;
+
+ //
+ // Terminating will cause sm's wait to sense that we crashed. This will
+ // result in a clean shutdown due to sm's hard error logic
+ //
+
+ //
+ // We are hosed, so raise a fata system error to shutdown the system.
+ // (Basically a user mode KeBugCheck).
+ //
+
+ Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
+ (BOOLEAN)TRUE,
+ TRUE,
+ &WasEnabled
+ );
+
+ if (Status == STATUS_NO_TOKEN) {
+
+ //
+ // No thread token, use the process token
+ //
+
+ Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
+ (BOOLEAN)TRUE,
+ FALSE,
+ &WasEnabled
+ );
+ }
+
+ RtlInitUnicodeString( &UnicodeParameter, L"Windows SubSystem" );
+ Parameters[ 0 ] = (ULONG)&UnicodeParameter;
+ Parameters[ 1 ] = (ULONG)ExceptionInfo->ExceptionRecord->ExceptionCode;
+ Parameters[ 2 ] = (ULONG)ExceptionInfo->ExceptionRecord->ExceptionAddress;
+ Parameters[ 3 ] = (ULONG)ExceptionInfo->ContextRecord;
+ Status = NtRaiseHardError( STATUS_SYSTEM_PROCESS_TERMINATED,
+ 4,
+ 1,
+ Parameters,
+ OptionShutdownSystem,
+ &Response
+ );
+
+ //
+ // If this returns, giveup
+ //
+
+ NtTerminateProcess(NtCurrentProcess(),ExceptionInfo->ExceptionRecord->ExceptionCode);
+
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+
+NTSTATUS
+CsrLoadServerDll(
+ IN PCH ModuleName,
+ IN PCH InitRoutineString,
+ IN ULONG ServerDllIndex
+ )
+{
+ NTSTATUS Status;
+ ANSI_STRING ModuleNameString;
+ UNICODE_STRING ModuleNameString_U;
+ HANDLE ModuleHandle;
+ PCSR_SERVER_DLL LoadedServerDll;
+ STRING ProcedureNameString;
+ PCSR_SERVER_DLL_INIT_ROUTINE ServerDllInitialization;
+ ULONG n;
+
+ if (ServerDllIndex > CSR_MAX_SERVER_DLL) {
+ return( STATUS_TOO_MANY_NAMES );
+ }
+
+ if (CsrLoadedServerDll[ ServerDllIndex ] != NULL) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ RtlInitAnsiString( &ModuleNameString, ModuleName );
+ Status = RtlAnsiStringToUnicodeString(&ModuleNameString_U, &ModuleNameString, TRUE);
+ ASSERT(NT_SUCCESS(Status));
+ if (ServerDllIndex != CSRSRV_SERVERDLL_INDEX) {
+ Status = LdrLoadDll( UNICODE_NULL, NULL, &ModuleNameString_U, &ModuleHandle );
+ if ( !NT_SUCCESS(Status) ) {
+
+ PUNICODE_STRING ErrorStrings[2];
+ UNICODE_STRING ErrorDllPath;
+ ULONG ErrorResponse;
+ NTSTATUS ErrorStatus;
+
+ ErrorStrings[0] = &ModuleNameString_U;
+ ErrorStrings[1] = &ErrorDllPath;
+ RtlInitUnicodeString(&ErrorDllPath,L"Default Load Path");
+
+ //
+ // need to get image name
+ //
+
+ ErrorStatus = NtRaiseHardError(
+ (NTSTATUS)STATUS_DLL_NOT_FOUND,
+ 2,
+ 0x00000003,
+ (PULONG)ErrorStrings,
+ OptionOk,
+ &ErrorResponse
+ );
+
+ }
+ RtlFreeUnicodeString(&ModuleNameString_U);
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+ }
+ else {
+ ModuleHandle = NULL;
+ }
+
+ n = sizeof( *LoadedServerDll ) + ModuleNameString.MaximumLength;
+
+ LoadedServerDll = RtlAllocateHeap( CsrHeap, MAKE_TAG( INIT_TAG ), n );
+ if (LoadedServerDll == NULL) {
+ if (ModuleHandle != NULL) {
+ LdrUnloadDll( ModuleHandle );
+ }
+
+ return( STATUS_NO_MEMORY );
+ }
+
+ RtlZeroMemory( LoadedServerDll, n );
+ LoadedServerDll->SharedStaticServerData = CsrSrvSharedSectionHeap;
+ LoadedServerDll->Length = n;
+ LoadedServerDll->CsrInitializationEvent = CsrInitializationEvent;
+ LoadedServerDll->ModuleName.Length = ModuleNameString.Length;
+ LoadedServerDll->ModuleName.MaximumLength = ModuleNameString.MaximumLength;
+ LoadedServerDll->ModuleName.Buffer = (PCH)(LoadedServerDll+1);
+ if (ModuleNameString.Length != 0) {
+ strncpy( LoadedServerDll->ModuleName.Buffer,
+ ModuleNameString.Buffer,
+ ModuleNameString.Length
+ );
+ }
+
+ LoadedServerDll->ServerDllIndex = ServerDllIndex;
+ LoadedServerDll->ModuleHandle = ModuleHandle;
+
+ if (ModuleHandle != NULL) {
+
+ RtlInitString(
+ &ProcedureNameString,
+ (InitRoutineString == NULL) ? "ServerDllInitialization" : InitRoutineString);
+
+ Status = LdrGetProcedureAddress( ModuleHandle,
+ &ProcedureNameString,
+ (ULONG) NULL,
+ (PVOID *) &ServerDllInitialization
+ );
+ }
+ else {
+ ServerDllInitialization = CsrServerDllInitialization;
+ Status = STATUS_SUCCESS;
+ }
+
+ if (NT_SUCCESS( Status )) {
+ try {
+ Status = (*ServerDllInitialization)( LoadedServerDll );
+ }
+ except ( CsrUnhandledExceptionFilter( GetExceptionInformation() ) ){
+ Status = GetExceptionCode();
+ }
+ if (NT_SUCCESS( Status )) {
+ CsrTotalPerProcessDataLength += QUAD_ALIGN(LoadedServerDll->PerProcessDataLength);
+ CsrTotalPerThreadDataLength += QUAD_ALIGN(LoadedServerDll->PerThreadDataLength);
+
+ CsrLoadedServerDll[ LoadedServerDll->ServerDllIndex ] =
+ LoadedServerDll;
+ if ( LoadedServerDll->SharedStaticServerData != CsrSrvSharedSectionHeap ) {
+ CsrSrvSharedStaticServerData[LoadedServerDll->ServerDllIndex] = LoadedServerDll->SharedStaticServerData;
+ }
+ }
+ else {
+ if (ModuleHandle != NULL) {
+ LdrUnloadDll( ModuleHandle );
+ }
+
+ RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
+ }
+ }
+ else {
+ if (ModuleHandle != NULL) {
+ LdrUnloadDll( ModuleHandle );
+ }
+
+ RtlFreeHeap( CsrHeap, 0, LoadedServerDll );
+ }
+
+ return( Status );
+}
+
+
+ULONG
+CsrSrvClientConnect(
+ IN OUT PCSR_API_MSG m,
+ IN OUT PCSR_REPLY_STATUS ReplyStatus
+ )
+{
+ NTSTATUS Status;
+ PCSR_CLIENTCONNECT_MSG a = (PCSR_CLIENTCONNECT_MSG)&m->u.ApiMessageData;
+ PCSR_SERVER_DLL LoadedServerDll;
+
+ *ReplyStatus = CsrReplyImmediate;
+
+ if (a->ServerDllIndex > CSR_MAX_SERVER_DLL) {
+ return( (ULONG)STATUS_TOO_MANY_NAMES );
+ }
+ else
+ if (CsrLoadedServerDll[ a->ServerDllIndex ] == NULL) {
+ return( (ULONG)STATUS_INVALID_PARAMETER );
+ }
+ else {
+ LoadedServerDll = CsrLoadedServerDll[ a->ServerDllIndex ];
+
+ if (LoadedServerDll->ConnectRoutine) {
+
+ Status = (LoadedServerDll->ConnectRoutine)(
+ (CSR_SERVER_QUERYCLIENTTHREAD())->Process,
+ a->ConnectionInformation,
+ &a->ConnectionInformationLength
+ );
+ }
+ else {
+ Status = STATUS_SUCCESS;
+ }
+ }
+
+ return( (ULONG)Status );
+}
+
+
+NTSTATUS
+CsrSrvCreateSharedSection(
+ IN PCH SizeParameter
+ )
+{
+ NTSTATUS Status;
+ LARGE_INTEGER SectionSize;
+ ULONG ViewSize;
+ ULONG HandleTableSize;
+ ULONG HeapSize;
+ PCH s;
+
+ s = SizeParameter;
+ while (*s) {
+ if (*s == ',') {
+ *s++ = '\0';
+ break;
+ }
+ else {
+ s++;
+ }
+ }
+
+
+ if (!*s) {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ Status = RtlCharToInteger( SizeParameter,
+ (ULONG)NULL,
+ &HandleTableSize
+ );
+ if (NT_SUCCESS( Status )) {
+ Status = RtlCharToInteger( SizeParameter,
+ (ULONG)NULL,
+ &HeapSize
+ );
+ }
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+
+ HandleTableSize = ROUND_UP_TO_PAGES( HandleTableSize * 1024 );
+ HeapSize = ROUND_UP_TO_PAGES( HeapSize * 1024 );
+ CsrSrvSharedSectionSize = HandleTableSize + HeapSize;
+
+ SectionSize.LowPart = CsrSrvSharedSectionSize;
+ SectionSize.HighPart = 0;
+ Status = NtCreateSection( &CsrSrvSharedSection,
+ SECTION_ALL_ACCESS,
+ (POBJECT_ATTRIBUTES) NULL,
+ &SectionSize,
+ PAGE_EXECUTE_READWRITE,
+ SEC_BASED | SEC_RESERVE,
+ (HANDLE) NULL
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+
+ ViewSize = 0;
+ CsrSrvSharedSectionBase = NULL;
+ Status = NtMapViewOfSection( CsrSrvSharedSection,
+ NtCurrentProcess(),
+ &CsrSrvSharedSectionBase,
+ 0, // Zerobits?
+ 0,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ MEM_TOP_DOWN,
+ PAGE_EXECUTE_READWRITE
+ );
+ if (!NT_SUCCESS( Status )) {
+ NtClose( CsrSrvSharedSection );
+ return( Status );
+ }
+ CsrSrvSharedSectionHeap = (PVOID)
+ ((ULONG)CsrSrvSharedSectionBase + HandleTableSize );
+
+ if (RtlCreateHeap( HEAP_ZERO_MEMORY | HEAP_CLASS_7,
+ CsrSrvSharedSectionHeap,
+ HeapSize,
+ 4*1024,
+ 0,
+ 0
+ ) == NULL
+ ) {
+ NtUnmapViewOfSection( NtCurrentProcess(),
+ CsrSrvSharedSectionBase
+ );
+ NtClose( CsrSrvSharedSection );
+ return( STATUS_NO_MEMORY );
+ }
+
+ CsrSharedBaseTag = RtlCreateTagHeap( CsrSrvSharedSectionHeap,
+ 0,
+ L"CSRSHR!",
+ L"!CSRSHR\0"
+ L"INIT\0"
+ );
+ CsrSrvSharedStaticServerData = (PVOID *)RtlAllocateHeap(
+ CsrSrvSharedSectionHeap,
+ MAKE_SHARED_TAG( SHR_INIT_TAG ),
+ CSR_MAX_SERVER_DLL * sizeof(PVOID)
+ );
+
+ NtCurrentPeb()->ReadOnlySharedMemoryBase = CsrSrvSharedSectionBase;
+ NtCurrentPeb()->ReadOnlySharedMemoryHeap = CsrSrvSharedSectionHeap;
+ NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)CsrSrvSharedStaticServerData;
+
+ return( STATUS_SUCCESS );
+}
+
+
+NTSTATUS
+CsrSrvAttachSharedSection(
+ IN PCSR_PROCESS Process OPTIONAL,
+ OUT PCSR_API_CONNECTINFO p
+ )
+{
+ NTSTATUS Status;
+ ULONG ViewSize;
+
+ if (ARGUMENT_PRESENT( Process )) {
+ ViewSize = 0;
+ Status = NtMapViewOfSection( CsrSrvSharedSection,
+ Process->ProcessHandle,
+ &CsrSrvSharedSectionBase,
+ 0,
+ 0,
+ NULL,
+ &ViewSize,
+ ViewUnmap,
+ SEC_NO_CHANGE,
+ PAGE_EXECUTE_READ
+ );
+ if (!NT_SUCCESS( Status )) {
+ return( Status );
+ }
+ }
+
+ p->SharedSectionBase = CsrSrvSharedSectionBase;
+ p->SharedSectionHeap = CsrSrvSharedSectionHeap;
+ p->SharedStaticServerData = CsrSrvSharedStaticServerData;
+
+ return( STATUS_SUCCESS );
+}
diff --git a/private/csr/server/wait.c b/private/csr/server/wait.c
new file mode 100644
index 000000000..c2da3f237
--- /dev/null
+++ b/private/csr/server/wait.c
@@ -0,0 +1,254 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ wait.c
+
+Abstract:
+
+ This module contains the primitives to implement the Wait functions
+ on the Server side of the Client-Server Runtime Subsystem to the
+ Session Manager SubSystem.
+
+Author:
+
+ Steve Wood (stevewo) 8-Oct-1990
+
+Revision History:
+
+--*/
+
+#include "csrsrv.h"
+
+BOOLEAN
+CsrInitializeWait(
+ IN CSR_WAIT_ROUTINE WaitRoutine,
+ IN PCSR_THREAD WaitingThread,
+ IN OUT PCSR_API_MSG WaitReplyMessage,
+ IN PVOID WaitParameter,
+ OUT PCSR_WAIT_BLOCK *WaitBlockPtr
+ )
+
+{
+ ULONG Length;
+ PCSR_WAIT_BLOCK WaitBlock;
+
+ Length = sizeof( *WaitBlock ) - sizeof( WaitBlock->WaitReplyMessage ) +
+ WaitReplyMessage->h.u1.s1.TotalLength;
+
+ WaitBlock = RtlAllocateHeap( CsrHeap, MAKE_TAG( PROCESS_TAG ), Length );
+ if (WaitBlock == NULL) {
+ WaitReplyMessage->ReturnValue = (ULONG)STATUS_NO_MEMORY;
+ return( FALSE );
+ }
+
+ WaitBlock->Length = Length;
+ WaitBlock->WaitingThread = WaitingThread;
+ WaitBlock->WaitParameter = WaitParameter;
+ WaitingThread->WaitBlock = WaitBlock;
+ WaitBlock->WaitRoutine = WaitRoutine;
+ WaitBlock->UserLink.Flink = WaitBlock->UserLink.Blink = NULL;
+ WaitBlock->Link.Flink = WaitBlock->Link.Blink = NULL;
+ RtlMoveMemory( &WaitBlock->WaitReplyMessage,
+ WaitReplyMessage,
+ WaitReplyMessage->h.u1.s1.TotalLength
+ );
+ *WaitBlockPtr = WaitBlock;
+ return TRUE;
+}
+
+BOOLEAN
+CsrCreateWait(
+ IN PLIST_ENTRY WaitQueue,
+ IN CSR_WAIT_ROUTINE WaitRoutine,
+ IN PCSR_THREAD WaitingThread,
+ IN OUT PCSR_API_MSG WaitReplyMessage,
+ IN PVOID WaitParameter,
+ IN PLIST_ENTRY UserLinkListHead OPTIONAL
+ )
+{
+ PCSR_WAIT_BLOCK WaitBlock;
+
+ if (!CsrInitializeWait( WaitRoutine,
+ WaitingThread,
+ WaitReplyMessage,
+ WaitParameter,
+ &WaitBlock
+ )
+ ) {
+ return FALSE;
+ }
+
+ AcquireWaitListsLock();
+
+ if ( WaitingThread && (WaitingThread->Flags & CSR_THREAD_DESTROYED) ) {
+ WaitingThread->WaitBlock = NULL;
+ RtlFreeHeap( CsrHeap, 0, WaitBlock );
+ ReleaseWaitListsLock();
+ return FALSE;
+ }
+
+ InsertTailList( WaitQueue, &WaitBlock->Link );
+
+ if ( ARGUMENT_PRESENT(UserLinkListHead) ) {
+ InsertTailList( UserLinkListHead, &WaitBlock->UserLink );
+ }
+
+ ReleaseWaitListsLock();
+ return( TRUE );
+}
+
+
+BOOLEAN
+CsrNotifyWaitBlock(
+ IN PCSR_WAIT_BLOCK WaitBlock,
+ IN PLIST_ENTRY WaitQueue,
+ IN PVOID SatisfyParameter1,
+ IN PVOID SatisfyParameter2,
+ IN ULONG WaitFlags,
+ IN BOOLEAN DereferenceThread
+ )
+{
+ if ((*WaitBlock->WaitRoutine)( WaitQueue,
+ WaitBlock->WaitingThread,
+ &WaitBlock->WaitReplyMessage,
+ WaitBlock->WaitParameter,
+ SatisfyParameter1,
+ SatisfyParameter2,
+ WaitFlags
+ )
+ ) {
+
+ //
+ // we don't take any locks other than the waitlist lock
+ // because the only thing we have to worry about is the thread
+ // going away beneath us and that's prevented by having
+ // DestroyThread and DestroyProcess take the waitlist lock.
+ //
+
+ WaitBlock->WaitingThread->WaitBlock = NULL;
+ if (WaitBlock->WaitReplyMessage.CaptureBuffer != NULL) {
+ CsrReleaseCapturedArguments(&WaitBlock->WaitReplyMessage);
+ }
+ NtReplyPort( WaitBlock->WaitingThread->Process->ClientPort,
+ (PPORT_MESSAGE)&WaitBlock->WaitReplyMessage
+ );
+
+ if (DereferenceThread) {
+ if ( WaitBlock->Link.Flink ) {
+ RemoveEntryList( &WaitBlock->Link );
+ }
+ if ( WaitBlock->UserLink.Flink ) {
+ RemoveEntryList( &WaitBlock->UserLink );
+ }
+ CsrDereferenceThread(WaitBlock->WaitingThread);
+ RtlFreeHeap( CsrHeap, 0, WaitBlock );
+ }
+ else {
+
+ //
+ // indicate that this wait has been satisfied. when the
+ // console unwinds to the point where it can release the
+ // console lock, it will dereference the thread.
+ //
+
+ WaitBlock->WaitRoutine = NULL;
+ }
+ return( TRUE );
+ }
+ else {
+ return( FALSE );
+ }
+}
+
+BOOLEAN
+CsrNotifyWait(
+ IN PLIST_ENTRY WaitQueue,
+ IN BOOLEAN SatisfyAll,
+ IN PVOID SatisfyParameter1,
+ IN PVOID SatisfyParameter2
+ )
+{
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_WAIT_BLOCK WaitBlock;
+ BOOLEAN Result;
+
+ Result = FALSE;
+
+ AcquireWaitListsLock();
+
+ ListHead = WaitQueue;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
+ ListNext = ListNext->Flink;
+ if (WaitBlock->WaitRoutine) {
+ Result |= CsrNotifyWaitBlock( WaitBlock,
+ WaitQueue,
+ SatisfyParameter1,
+ SatisfyParameter2,
+ 0,
+ FALSE
+ );
+ if (!SatisfyAll) {
+ break;
+ }
+ }
+ }
+
+ ReleaseWaitListsLock();
+ return( Result );
+}
+
+VOID
+CsrDereferenceWait(
+ IN PLIST_ENTRY WaitQueue
+ )
+{
+ PLIST_ENTRY ListHead, ListNext;
+ PCSR_WAIT_BLOCK WaitBlock;
+
+ AcquireProcessStructureLock();
+ AcquireWaitListsLock();
+
+ ListHead = WaitQueue;
+ ListNext = ListHead->Flink;
+ while (ListNext != ListHead) {
+ WaitBlock = CONTAINING_RECORD( ListNext, CSR_WAIT_BLOCK, Link );
+ ListNext = ListNext->Flink;
+ if (!WaitBlock->WaitRoutine) {
+ if ( WaitBlock->Link.Flink ) {
+ RemoveEntryList( &WaitBlock->Link );
+ }
+ if ( WaitBlock->UserLink.Flink ) {
+ RemoveEntryList( &WaitBlock->UserLink );
+ }
+ CsrDereferenceThread(WaitBlock->WaitingThread);
+ RtlFreeHeap( CsrHeap, 0, WaitBlock );
+ }
+ }
+
+ ReleaseWaitListsLock();
+ ReleaseProcessStructureLock();
+}
+
+VOID
+CsrDestroyWait(
+ IN PCSR_WAIT_BLOCK WaitBlock
+ )
+{
+ AcquireWaitListsLock();
+
+ WaitBlock->WaitingThread->WaitBlock = NULL;
+ RemoveEntryList( &WaitBlock->Link );
+
+ if ( WaitBlock->UserLink.Flink ) {
+ RemoveEntryList( &WaitBlock->UserLink );
+ }
+
+ ReleaseWaitListsLock();
+
+ RtlFreeHeap( CsrHeap, 0, WaitBlock );
+}