/*++ 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; iPerProcessDataLength) { 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; iAddProcessRoutine) { (*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; iApiNumberBase = 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; }