diff --git a/reactos/subsystems/win32/csrss/csrsrv/api/process.c b/reactos/subsystems/win32/csrss/csrsrv/api/process.c index a280d18325c..13c44de0074 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/api/process.c +++ b/reactos/subsystems/win32/csrss/csrsrv/api/process.c @@ -83,7 +83,7 @@ PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId) } if (pProcessData == NULL) { - pProcessData = RtlAllocateHeap(CsrssApiHeap, + pProcessData = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_PROCESS_DATA)); if (pProcessData) @@ -109,7 +109,7 @@ PCSRSS_PROCESS_DATA WINAPI CsrCreateProcessData(HANDLE ProcessId) if (!NT_SUCCESS(Status)) { ProcessData[hash] = pProcessData->next; - RtlFreeHeap(CsrssApiHeap, 0, pProcessData); + RtlFreeHeap(CsrHeap, 0, pProcessData); pProcessData = NULL; } else @@ -187,7 +187,7 @@ NTSTATUS WINAPI CsrFreeProcessData(HANDLE Pid) *pPrevLink = pProcessData->next; - RtlFreeHeap(CsrssApiHeap, 0, pProcessData); + RtlFreeHeap(CsrHeap, 0, pProcessData); UNLOCK; if (Process) { diff --git a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c index 2f771e18f25..a2c70fcf6e5 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c +++ b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c @@ -19,11 +19,18 @@ extern HANDLE hApiPort; -HANDLE CsrssApiHeap = (HANDLE) 0; - static unsigned ApiDefinitionsCount = 0; static PCSRSS_API_DEFINITION ApiDefinitions = NULL; +PCHAR CsrServerSbApiName[5] = +{ + "SbCreateSession", + "SbTerminateSession", + "SbForeignSessionComplete", + "SbCreateProcess", + "Unknown Csr Sb Api Number" +}; + /* FUNCTIONS *****************************************************************/ NTSTATUS FASTCALL @@ -41,7 +48,7 @@ CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions) NewCount++; } - New = RtlAllocateHeap(CsrssApiHeap, 0, + New = RtlAllocateHeap(CsrHeap, 0, (ApiDefinitionsCount + NewCount) * sizeof(CSRSS_API_DEFINITION)); if (NULL == New) @@ -53,7 +60,7 @@ CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions) { RtlCopyMemory(New, ApiDefinitions, ApiDefinitionsCount * sizeof(CSRSS_API_DEFINITION)); - RtlFreeHeap(CsrssApiHeap, 0, ApiDefinitions); + RtlFreeHeap(CsrHeap, 0, ApiDefinitions); } RtlCopyMemory(New + ApiDefinitionsCount, NewDefinitions, NewCount * sizeof(CSRSS_API_DEFINITION)); @@ -180,7 +187,6 @@ CsrSrvCreateSharedSection(IN PCHAR ParameterValue) /* Multiply by 1024 entries and round to page size */ CsrSrvSharedSectionSize = ROUND_UP(Size * 1024, CsrNtSysInfo.PageSize); - DPRINT1("Size: %lx\n", CsrSrvSharedSectionSize); /* Create the Secion */ SectionSize.LowPart = CsrSrvSharedSectionSize; @@ -980,115 +986,391 @@ ClientConnectionThread(HANDLE ServerPort) RtlExitUserThread(STATUS_SUCCESS); } -/********************************************************************** - * NAME - * ServerSbApiPortThread/1 +/* SESSION MANAGER FUNCTIONS**************************************************/ + +/*++ + * @name CsrSbCreateSession * - * DESCRIPTION - * Handle connection requests from SM to the port - * "\Windows\SbApiPort". We will accept only one - * connection request (from the SM). - */ -DWORD WINAPI -ServerSbApiPortThread (HANDLE hSbApiPortListen) + * The CsrSbCreateSession API is called by the Session Manager whenever a new + * session is created. + * + * @param ApiMessage + * Pointer to the Session Manager API Message. + * + * @return TRUE in case of success, FALSE othwerwise. + * + * @remarks The CsrSbCreateSession routine will initialize a new CSR NT + * Session and allocate a new CSR Process for the subsystem process. + * + *--*/ +BOOLEAN +NTAPI +CsrSbCreateSession(IN PSB_API_MSG ApiMessage) { - HANDLE hConnectedPort = (HANDLE) 0; - SB_API_MSG Request; - PVOID Context = NULL; - NTSTATUS Status = STATUS_SUCCESS; - PPORT_MESSAGE Reply = NULL; + PSB_CREATE_SESSION_MSG CreateSession = &ApiMessage->CreateSession; + HANDLE hProcess, hThread; +// PCSR_PROCESS CsrProcess; + NTSTATUS Status; + KERNEL_USER_TIMES KernelTimes; + //PCSR_THREAD CsrThread; + //PVOID ProcessData; + //ULONG i; - DPRINT("CSR: %s called\n", __FUNCTION__); + /* Save the Process and Thread Handles */ + hProcess = CreateSession->ProcessInfo.ProcessHandle; + hThread = CreateSession->ProcessInfo.ThreadHandle; - RtlZeroMemory(&Request, sizeof(PORT_MESSAGE)); - Status = NtListenPort (hSbApiPortListen, & Request.h); +#if 0 + /* Lock the Processes */ + CsrAcquireProcessLock(); + /* Allocate a new process */ + CsrProcess = CsrAllocateProcess(); + if (!CsrProcess) + { + /* Fail */ + ApiMessage->ReturnValue = STATUS_NO_MEMORY; + CsrReleaseProcessLock(); + return TRUE; + } +#endif + + /* Set the exception port */ + Status = NtSetInformationProcess(hProcess, + ProcessExceptionPort, + &hApiPort,//&CsrApiPort, + sizeof(HANDLE)); + + /* Check for success */ if (!NT_SUCCESS(Status)) { - DPRINT1("CSR: %s: NtListenPort(SB) failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - } else { - DPRINT("-- 1\n"); - Status = NtAcceptConnectPort(&hConnectedPort, - NULL, - &Request.h, - TRUE, - NULL, - NULL); - if(!NT_SUCCESS(Status)) + /* Fail the request */ +#if 0 + CsrDeallocateProcess(CsrProcess); + CsrReleaseProcessLock(); +#endif + /* Strange as it seems, NTSTATUSes are actually returned */ + return (BOOLEAN)STATUS_NO_MEMORY; + } + + /* Get the Create Time */ + Status = NtQueryInformationThread(hThread, + ThreadTimes, + &KernelTimes, + sizeof(KERNEL_USER_TIMES), + NULL); + + /* Check for success */ + if (!NT_SUCCESS(Status)) + { + /* Fail the request */ +#if 0 + CsrDeallocateProcess(CsrProcess); + CsrReleaseProcessLock(); +#endif + + /* Strange as it seems, NTSTATUSes are actually returned */ + return (BOOLEAN)Status; + } + + /* Allocate a new Thread */ +#if 0 + CsrThread = CsrAllocateThread(CsrProcess); + if (!CsrThread) + { + /* Fail the request */ + CsrDeallocateProcess(CsrProcess); + CsrReleaseProcessLock(); + + ApiMessage->ReturnValue = STATUS_NO_MEMORY; + return TRUE; + } + + /* Setup the Thread Object */ + CsrThread->CreateTime = KernelTimes.CreateTime; + CsrThread->ClientId = CreateSession->ProcessInfo.ClientId; + CsrThread->ThreadHandle = hThread; + ProtectHandle(hThread); + CsrThread->Flags = 0; + + /* Insert it into the Process List */ + CsrInsertThread(CsrProcess, CsrThread); + + /* Setup Process Data */ + CsrProcess->ClientId = CreateSession->ProcessInfo.ClientId; + CsrProcess->ProcessHandle = hProcess; + CsrProcess->NtSession = CsrAllocateNtSession(CreateSession->SessionId); + + /* Set the Process Priority */ + CsrSetBackgroundPriority(CsrProcess); + + /* Get the first data location */ + ProcessData = &CsrProcess->ServerData[CSR_SERVER_DLL_MAX]; + + /* Loop every DLL */ + for (i = 0; i < CSR_SERVER_DLL_MAX; i++) + { + /* Check if the DLL is loaded and has Process Data */ + if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData) { - DPRINT1("CSR: %s: NtAcceptConnectPort() failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - } else { - DPRINT("-- 2\n"); - Status = NtCompleteConnectPort (hConnectedPort); - if(!NT_SUCCESS(Status)) - { - DPRINT1("CSR: %s: NtCompleteConnectPort() failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - } else { - DPRINT("-- 3\n"); - /* - * Tell the init thread the SM gave the - * green light for boostrapping. - */ - Status = NtSetEvent (hBootstrapOk, NULL); - if(!NT_SUCCESS(Status)) - { - DPRINT1("CSR: %s: NtSetEvent failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - } - /* Wait for messages from the SM */ - DPRINT("-- 4\n"); - while (TRUE) - { - Status = NtReplyWaitReceivePort(hConnectedPort, - Context, - Reply, - &Request.h); - if(!NT_SUCCESS(Status)) - { - DPRINT1("CSR: %s: NtReplyWaitReceivePort failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - break; - } + /* Write the pointer to the data */ + CsrProcess->ServerData[i] = ProcessData; - switch (Request.h.u2.s2.Type) //fix .h PORT_MESSAGE_TYPE(Request)) - { - /* TODO */ - case LPC_PORT_CLOSED: - case LPC_CLIENT_DIED: - DPRINT1("CSR: SMSS died\n"); - Reply = NULL; - break; - - default: - DPRINT1("CSR: %s received message (type=%d)\n", - __FUNCTION__, Request.h.u2.s2.Type); - - if (Request.ApiNumber == SbpCreateSession) - { - DPRINT("Session create... legacy CSRSS resuming thread as minimum work done\n"); - Request.ReturnValue = NtResumeThread(Request.CreateSession.ProcessInfo.ThreadHandle, NULL); - } - else - { - DPRINT1("CSR: %d Not implemented in legacy CSRSS... faking success\n", Request.ApiNumber); - Request.ReturnValue = STATUS_SUCCESS; - } - Reply = &Request.h; - } - DPRINT("-- 5\n"); - } - } + /* Move to the next data location */ + ProcessData = (PVOID)((ULONG_PTR)ProcessData + + CsrLoadedServerDll[i]->SizeOfProcessData); + } + else + { + /* Nothing for this Process */ + CsrProcess->ServerData[i] = NULL; } } - DPRINT("CSR: %s: terminating!\n", __FUNCTION__); - if(hConnectedPort) NtClose (hConnectedPort); - NtClose (hSbApiPortListen); - NtTerminateThread (NtCurrentThread(), Status); - return 0; + /* Insert the Process */ + CsrInsertProcess(NULL, NULL, CsrProcess); +#endif + /* Activate the Thread */ + ApiMessage->ReturnValue = NtResumeThread(hThread, NULL); + + /* Release lock and return */ +// CsrReleaseProcessLock(); + return TRUE; +} + +/*++ + * @name CsrSbForeignSessionComplete + * + * The CsrSbForeignSessionComplete API is called by the Session Manager + * whenever a foreign session is completed (ie: terminated). + * + * @param ApiMessage + * Pointer to the Session Manager API Message. + * + * @return TRUE in case of success, FALSE othwerwise. + * + * @remarks The CsrSbForeignSessionComplete API is not yet implemented. + * + *--*/ +BOOLEAN +NTAPI +CsrSbForeignSessionComplete(IN PSB_API_MSG ApiMessage) +{ + /* Deprecated/Unimplemented in NT */ + ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED; + return TRUE; +} + +/*++ + * @name CsrSbTerminateSession + * + * The CsrSbTerminateSession API is called by the Session Manager + * whenever a foreign session should be destroyed. + * + * @param ApiMessage + * Pointer to the Session Manager API Message. + * + * @return TRUE in case of success, FALSE othwerwise. + * + * @remarks The CsrSbTerminateSession API is not yet implemented. + * + *--*/ +BOOLEAN +NTAPI +CsrSbTerminateSession(IN PSB_API_MSG ApiMessage) +{ + ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED; + return TRUE; +} + +/*++ + * @name CsrSbCreateProcess + * + * The CsrSbCreateProcess API is called by the Session Manager + * whenever a foreign session is created and a new process should be started. + * + * @param ApiMessage + * Pointer to the Session Manager API Message. + * + * @return TRUE in case of success, FALSE othwerwise. + * + * @remarks The CsrSbCreateProcess API is not yet implemented. + * + *--*/ +BOOLEAN +NTAPI +CsrSbCreateProcess(IN PSB_API_MSG ApiMessage) +{ + ApiMessage->ReturnValue = STATUS_NOT_IMPLEMENTED; + return TRUE; +} + +PSB_API_ROUTINE CsrServerSbApiDispatch[5] = +{ + CsrSbCreateSession, + CsrSbTerminateSession, + CsrSbForeignSessionComplete, + CsrSbCreateProcess, + NULL +}; + +/*++ + * @name CsrSbApiHandleConnectionRequest + * + * The CsrSbApiHandleConnectionRequest routine handles and accepts a new + * connection request to the SM API LPC Port. + * + * @param ApiMessage + * Pointer to the incoming CSR API Message which contains the + * connection request. + * + * @return STATUS_SUCCESS in case of success, or status code which caused + * the routine to error. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrSbApiHandleConnectionRequest(IN PSB_API_MSG Message) +{ + NTSTATUS Status; + REMOTE_PORT_VIEW RemotePortView; + HANDLE hPort; + + /* Set the Port View Structure Length */ + RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); + + /* Accept the connection */ + Status = NtAcceptConnectPort(&hPort, + NULL, + (PPORT_MESSAGE)Message, + TRUE, + NULL, + &RemotePortView); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: Sb Accept Connection failed %lx\n", Status); + return Status; + } + + /* Complete the Connection */ + Status = NtCompleteConnectPort(hPort); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: Sb Complete Connection failed %lx\n",Status); + } + + /* Return status */ + return Status; +} + +/*++ + * @name CsrSbApiRequestThread + * + * The CsrSbApiRequestThread routine handles incoming messages or connection + * requests on the SM API LPC Port. + * + * @param Parameter + * System-default user-defined parameter. Unused. + * + * @return The thread exit code, if the thread is terminated. + * + * @remarks Before listening on the port, the routine will first attempt + * to connect to the user subsystem. + * + *--*/ +VOID +NTAPI +CsrSbApiRequestThread(IN PVOID Parameter) +{ + NTSTATUS Status; + SB_API_MSG ReceiveMsg; + PSB_API_MSG ReplyMsg = NULL; + PVOID PortContext; + ULONG MessageType; + + /* Start the loop */ + while (TRUE) + { + /* Wait for a message to come in */ + Status = NtReplyWaitReceivePort(CsrSbApiPort, + &PortContext, + &ReplyMsg->h, + &ReceiveMsg.h); + + /* Check if we didn't get success */ + if (Status != STATUS_SUCCESS) + { + /* If we only got a warning, keep going */ + if (NT_SUCCESS(Status)) continue; + + /* We failed big time, so start out fresh */ + ReplyMsg = NULL; + DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); + continue; + } + + /* Save the message type */ + MessageType = ReceiveMsg.h.u2.s2.Type; + + /* Check if this is a connection request */ + if (MessageType == LPC_CONNECTION_REQUEST) + { + /* Handle connection request */ + CsrSbApiHandleConnectionRequest(&ReceiveMsg); + + /* Start over */ + ReplyMsg = NULL; + continue; + } + + /* Check if the port died */ + if (MessageType == LPC_PORT_CLOSED) + { + /* Close the handle if we have one */ + if (PortContext) NtClose((HANDLE)PortContext); + + /* Client died, start over */ + ReplyMsg = NULL; + continue; + } + else if (MessageType == LPC_CLIENT_DIED) + { + /* Client died, start over */ + ReplyMsg = NULL; + continue; + } + + /* + * It's an API Message, check if it's within limits. If it's not, the + * NT Behaviour is to set this to the Maximum API. + */ + if (ReceiveMsg.ApiNumber > SbpMaxApiNumber) + { + ReceiveMsg.ApiNumber = SbpMaxApiNumber; + DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber); + } + + /* Reuse the message */ + ReplyMsg = &ReceiveMsg; + + /* Make sure that the message is supported */ + if (ReceiveMsg.ApiNumber < SbpMaxApiNumber) + { + /* Call the API */ + if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg)) + { + /* It failed, so return nothing */ + ReplyMsg = NULL; + } + } + else + { + /* We don't support this API Number */ + ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED; + } + } } /* EOF */ diff --git a/reactos/subsystems/win32/csrss/csrsrv/init.c b/reactos/subsystems/win32/csrss/csrsrv/init.c index 1bade90ab9f..d8b6cb796fe 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/init.c +++ b/reactos/subsystems/win32/csrss/csrsrv/init.c @@ -17,12 +17,13 @@ HANDLE CsrHeap = (HANDLE) 0; HANDLE CsrObjectDirectory = (HANDLE) 0; UNICODE_STRING CsrDirectoryName; -extern HANDLE CsrssApiHeap; +UNICODE_STRING CsrSbApiPortName; +HANDLE CsrSbApiPort = 0; +PCSR_THREAD CsrSbApiRequestThreadPtr; static unsigned ServerProcCount; static CSRPLUGIN_SERVER_PROCS *ServerProcs = NULL; +HANDLE CsrSmApiPort; HANDLE hSbApiPort = (HANDLE) 0; -HANDLE hBootstrapOk = (HANDLE) 0; -HANDLE hSmApiPort = (HANDLE) 0; HANDLE hApiPort = (HANDLE) 0; ULONG CsrDebug = 0xFFFFFFFF; ULONG CsrMaxApiRequestThreads; @@ -31,6 +32,8 @@ ULONG SessionId; HANDLE BNOLinksDirectory; HANDLE SessionObjectDirectory; HANDLE DosDevicesDirectory; +HANDLE CsrInitializationEvent; +SYSTEM_BASIC_INFORMATION CsrNtSysInfo; /* PRIVATE FUNCTIONS **********************************************************/ @@ -41,7 +44,7 @@ CsrpAddServerProcs(CSRPLUGIN_SERVER_PROCS *Procs) DPRINT("CSR: %s called\n", __FUNCTION__); - NewProcs = RtlAllocateHeap(CsrssApiHeap, 0, + NewProcs = RtlAllocateHeap(CsrHeap, 0, (ServerProcCount + 1) * sizeof(CSRPLUGIN_SERVER_PROCS)); if (NULL == NewProcs) @@ -52,7 +55,7 @@ CsrpAddServerProcs(CSRPLUGIN_SERVER_PROCS *Procs) { RtlCopyMemory(NewProcs, ServerProcs, ServerProcCount * sizeof(CSRPLUGIN_SERVER_PROCS)); - RtlFreeHeap(CsrssApiHeap, 0, ServerProcs); + RtlFreeHeap(CsrHeap, 0, ServerProcs); } NewProcs[ServerProcCount] = *Procs; ServerProcs = NewProcs; @@ -61,26 +64,6 @@ CsrpAddServerProcs(CSRPLUGIN_SERVER_PROCS *Procs) return STATUS_SUCCESS; } -/********************************************************************** - * CallInitComplete/0 - */ -static BOOL FASTCALL -CallInitComplete(void) -{ - BOOL Ok; - unsigned i; - - DPRINT("CSR: %s called\n", __FUNCTION__); - - Ok = TRUE; - for (i = 0; i < ServerProcCount && Ok; i++) - { - Ok = (*ServerProcs[i].InitCompleteProc)(); - } - - return Ok; -} - BOOL CallHardError(IN PCSRSS_PROCESS_DATA ProcessData, IN PHARDERROR_MSG HardErrorMessage) @@ -167,7 +150,7 @@ CsrpInitWin32Csr (VOID) return Status; } Exports.CsrEnumProcessesProc = CsrEnumProcesses; - if (! (*InitProc)(&ApiDefinitions, &ServerProcs, &Exports, CsrssApiHeap)) + if (! (*InitProc)(&ApiDefinitions, &ServerProcs, &Exports, CsrHeap)) { return STATUS_UNSUCCESSFUL; } @@ -233,12 +216,12 @@ CsrpCreateListenPort (IN LPWSTR Name, *Port, &ServerThread, &ClientId); - + if (ListenThread == (PVOID)ClientConnectionThread) { CsrAddStaticServerThread(ServerThread, &ClientId, 0); } - + NtResumeThread(ServerThread, NULL); NtClose(ServerThread); return Status; @@ -254,94 +237,118 @@ NTSTATUS NTAPI CsrSrvCreateSharedSection(IN PCHAR ParameterValue); -/********************************************************************** - * CsrpCreateHeap/3 - */ -static NTSTATUS -CsrpCreateHeap (VOID) +/*++ + * @name CsrSetProcessSecurity + * + * The CsrSetProcessSecurity routine protects access to the CSRSS process + * from unauthorized tampering. + * + * @param None. + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrSetProcessSecurity(VOID) { - DPRINT("CSR: %s called\n", __FUNCTION__); + NTSTATUS Status; + HANDLE hToken, hProcess = NtCurrentProcess(); + ULONG Length; + PTOKEN_USER TokenInfo = NULL; + PSECURITY_DESCRIPTOR ProcSd = NULL; + PACL Dacl; + PSID UserSid; - CsrHeap = RtlGetProcessHeap(); - CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE, - NULL, - 65536, - 65536, - NULL, - NULL); - if (CsrssApiHeap == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} + /* Open our token */ + Status = NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken); + if (!NT_SUCCESS(Status)) goto Quickie; -/********************************************************************** - * CsrpRegisterSubsystem/3 - */ -BOOLEAN g_ModernSm; -static NTSTATUS -CsrpRegisterSubsystem (VOID) -{ - NTSTATUS Status = STATUS_SUCCESS; - OBJECT_ATTRIBUTES BootstrapOkAttributes; - UNICODE_STRING Name; + /* Get the Token User Length */ + NtQueryInformationToken(hToken, TokenUser, NULL, 0, &Length); - DPRINT("CSR: %s called\n", __FUNCTION__); + /* Allocate space for it */ + TokenInfo = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length); + if (!TokenInfo) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } - /* - * Create the event object the callback port - * thread will signal *if* the SM will - * authorize us to bootstrap. - */ - RtlInitUnicodeString (& Name, L"\\CsrssBooting"); - InitializeObjectAttributes(& BootstrapOkAttributes, - & Name, - 0, NULL, NULL); - Status = NtCreateEvent (& hBootstrapOk, - EVENT_ALL_ACCESS, - & BootstrapOkAttributes, - SynchronizationEvent, - FALSE); - if(!NT_SUCCESS(Status)) - { - DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n", - __FUNCTION__, Status); - return Status; - } - /* - * Let's tell the SM a new environment - * subsystem server is in the system. - */ - RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort"); - DPRINT("CSR: %s: registering with SM for\n IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__); - Status = SmConnectApiPort (& Name, - hSbApiPort, - IMAGE_SUBSYSTEM_WINDOWS_CUI, - & hSmApiPort); + /* Now query the data */ + Status = NtQueryInformationToken(hToken, TokenUser, TokenInfo, Length, &Length); + NtClose(hToken); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Now check the SID Length */ + UserSid = TokenInfo->User.Sid; + Length = RtlLengthSid(UserSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); + + /* Allocate a buffer for the Security Descriptor, with SID and DACL */ + ProcSd = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); + if (!ProcSd) + { + Status = STATUS_NO_MEMORY; + goto Quickie; + } + + /* Set the pointer to the DACL */ + Dacl = (PACL)((ULONG_PTR)ProcSd + SECURITY_DESCRIPTOR_MIN_LENGTH); + + /* Now create the SD itself */ + Status = RtlCreateSecurityDescriptor(ProcSd, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { - Status = SmConnectToSm(&Name, hSbApiPort, IMAGE_SUBSYSTEM_WINDOWS_GUI, &hSmApiPort); - g_ModernSm = TRUE; + DPRINT1("CSRSS: SD creation failed - status = %lx\n", Status); + goto Quickie; } - if(!NT_SUCCESS(Status)) - { - DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n", - __FUNCTION__, Status); - NtClose (hBootstrapOk); - return Status; - } - /* - * Wait for SM to reply OK... If the SM - * won't answer, we hang here forever! - */ - DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__); - Status = NtWaitForSingleObject (hBootstrapOk, - FALSE, - NULL); - NtClose (hBootstrapOk); - return Status; + + /* Create the DACL for it*/ + Status = RtlCreateAcl(Dacl, Length, ACL_REVISION2); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: DACL creation failed - status = %lx\n", Status); + goto Quickie; + } + + /* Create the ACE */ + Status = RtlAddAccessAllowedAce(Dacl, + ACL_REVISION, + PROCESS_VM_READ | PROCESS_VM_WRITE | + PROCESS_VM_OPERATION | PROCESS_DUP_HANDLE | + PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME | + PROCESS_QUERY_INFORMATION | READ_CONTROL, + UserSid); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: ACE creation failed - status = %lx\n", Status); + goto Quickie; + } + + /* Clear the DACL in the SD */ + Status = RtlSetDaclSecurityDescriptor(ProcSd, TRUE, Dacl, FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: set DACL failed - status = %lx\n", Status); + goto Quickie; + } + + /* Write the SD into the Process */ + Status = NtSetSecurityObject(hProcess, DACL_SECURITY_INFORMATION, ProcSd); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSS: set process DACL failed - status = %lx\n", Status); + goto Quickie; + } + + /* Free the memory and return */ +Quickie: + if (ProcSd) RtlFreeHeap(CsrHeap, 0, ProcSd); + RtlFreeHeap(CsrHeap, 0, TokenInfo); + return Status; } /*++ @@ -764,11 +771,9 @@ CsrParseServerCommandLine(IN ULONG ArgumentCount, { /* Split Name and Value */ ParameterName = Arguments[i]; - DPRINT1("Name: %s\n", ParameterName); ParameterValue = NULL; ParameterValue = strchr(ParameterName, '='); if (ParameterValue) *ParameterValue++ = ANSI_NULL; - DPRINT1("Name=%s, Value=%s\n", ParameterName, ParameterValue); /* Check for Object Directory */ if (!_stricmp(ParameterName, "ObjectDirectory")) @@ -898,21 +903,218 @@ CsrParseServerCommandLine(IN ULONG ArgumentCount, return Status; } +/*++ + * @name CsrCreateLocalSystemSD + * + * The CsrCreateLocalSystemSD routine creates a Security Descriptor for + * the local account with PORT_ALL_ACCESS. + * + * @param LocalSystemSd + * Pointer to a pointer to the security descriptor to create. + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrCreateLocalSystemSD(OUT PSECURITY_DESCRIPTOR *LocalSystemSd) +{ + SID_IDENTIFIER_AUTHORITY NtSidAuthority = {SECURITY_NT_AUTHORITY}; + PSID SystemSid; + ULONG Length; + PSECURITY_DESCRIPTOR SystemSd; + PACL Dacl; + NTSTATUS Status; + + /* Initialize the System SID */ + RtlAllocateAndInitializeSid(&NtSidAuthority, 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &SystemSid); + + /* Get the length of the SID */ + Length = RtlLengthSid(SystemSid) + sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); + + /* Allocate a buffer for the Security Descriptor, with SID and DACL */ + SystemSd = RtlAllocateHeap(CsrHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH + Length); + + /* Set the pointer to the DACL */ + Dacl = (PACL)((ULONG_PTR)SystemSd + SECURITY_DESCRIPTOR_MIN_LENGTH); + + /* Now create the SD itself */ + Status = RtlCreateSecurityDescriptor(SystemSd, SECURITY_DESCRIPTOR_REVISION); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + RtlFreeHeap(CsrHeap, 0, SystemSd); + return Status; + } + + /* Create the DACL for it*/ + RtlCreateAcl(Dacl, Length, ACL_REVISION2); + + /* Create the ACE */ + Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, PORT_ALL_ACCESS, SystemSid); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + RtlFreeHeap(CsrHeap, 0, SystemSd); + return Status; + } + + /* Clear the DACL in the SD */ + Status = RtlSetDaclSecurityDescriptor(SystemSd, TRUE, Dacl, FALSE); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + RtlFreeHeap(CsrHeap, 0, SystemSd); + return Status; + } + + /* Free the SID and return*/ + RtlFreeSid(SystemSid); + *LocalSystemSd = SystemSd; + return Status; +} + +/*++ + * @name CsrSbApiPortInitialize + * + * The CsrSbApiPortInitialize routine initializes the LPC Port used for + * communications with the Session Manager (SM) and initializes the static + * thread that will handle connection requests and APIs. + * + * @param None + * + * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL + * othwerwise. + * + * @remarks None. + * + *--*/ +NTSTATUS +NTAPI +CsrSbApiPortInitialize(VOID) +{ + ULONG Size; + PSECURITY_DESCRIPTOR PortSd; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE hRequestThread; + CLIENT_ID ClientId; + + /* Calculate how much space we'll need for the Port Name */ + Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR); + + /* Create the buffer for it */ + CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); + if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY; + + /* Setup the rest of the empty string */ + CsrSbApiPortName.Length = 0; + CsrSbApiPortName.MaximumLength = (USHORT)Size; + + /* Now append the full port name */ + RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName); + RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP); + RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME); + if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName); + + /* Create Security Descriptor for this Port */ + Status = CsrCreateLocalSystemSD(&PortSd); + if (!NT_SUCCESS(Status)) return Status; + + /* Initialize the Attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &CsrSbApiPortName, + 0, + NULL, + PortSd); + + /* Create the Port Object */ + Status = NtCreatePort(&CsrSbApiPort, + &ObjectAttributes, + sizeof(SB_CONNECTION_INFO), + sizeof(SB_API_MSG), + 32 * sizeof(SB_API_MSG)); + if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd); + + if (NT_SUCCESS(Status)) + { + /* Create the Thread to handle the API Requests */ + Status = RtlCreateUserThread(NtCurrentProcess(), + NULL, + TRUE, + 0, + 0, + 0, + (PVOID)CsrSbApiRequestThread, + NULL, + &hRequestThread, + &ClientId); + if (NT_SUCCESS(Status)) + { + /* Add it as a Static Server Thread */ + CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread, + &ClientId, + 0); + + /* Activate it */ + Status = NtResumeThread(hRequestThread, NULL); + } + } + + return Status; +} + /* PUBLIC FUNCTIONS ***********************************************************/ NTSTATUS NTAPI -CsrServerInitialization(ULONG ArgumentCount, - PCHAR Arguments[]) +CsrServerInitialization(IN ULONG ArgumentCount, + IN PCHAR Arguments[]) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status = STATUS_SUCCESS; + DPRINT("CSRSRV: %s called\n", __FUNCTION__); - DPRINT("CSR: %s called\n", __FUNCTION__); - - Status = CsrpCreateHeap(); + /* Create the Init Event */ + Status = NtCreateEvent(&CsrInitializationEvent, + EVENT_ALL_ACCESS, + NULL, + SynchronizationEvent, + FALSE); if (!NT_SUCCESS(Status)) { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateHeap", Status); + DPRINT1("CSRSRV:%s: NtCreateEvent failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; + } + + /* Cache System Basic Information so we don't always request it */ + Status = NtQuerySystemInformation(SystemBasicInformation, + &CsrNtSysInfo, + sizeof(SYSTEM_BASIC_INFORMATION), + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSRV:%s: NtQuerySystemInformation failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; + } + + /* Save our Heap */ + CsrHeap = RtlGetProcessHeap(); + + /* Set our Security Descriptor to protect the process */ + Status = CsrSetProcessSecurity(); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSRV:%s: CsrSetProcessSecurity failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; } /* Parse the command line */ @@ -923,14 +1125,8 @@ CsrServerInitialization(ULONG ArgumentCount, __FUNCTION__, Status); return Status; } - - CsrInitProcessData(); - Status = CsrpCreateListenPort(L"\\Windows\\ApiPort", &hApiPort, (PTHREAD_START_ROUTINE)ClientConnectionThread); - if (!NT_SUCCESS(Status)) - { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateApiPort", Status); - } + CsrInitProcessData(); Status = CsrApiRegisterDefinitions(NativeDefinitions); if (!NT_SUCCESS(Status)) @@ -938,36 +1134,62 @@ CsrServerInitialization(ULONG ArgumentCount, DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrApiRegisterDefinitions", Status); } + Status = CsrpCreateListenPort(L"\\Windows\\ApiPort", &hApiPort, (PTHREAD_START_ROUTINE)ClientConnectionThread); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateApiPort", Status); + } + Status = CsrpInitWin32Csr(); if (!NT_SUCCESS(Status)) { DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpInitWin32Csr", Status); } - Status = CsrpCreateListenPort(L"\\Windows\\SbApiPort", &hSbApiPort, ServerSbApiPortThread); + /* Initialize the API Port for SM communication */ + Status = CsrSbApiPortInitialize(); if (!NT_SUCCESS(Status)) { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateCallbackPort", Status); + DPRINT1("CSRSRV:%s: CsrSbApiPortInitialize failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; } - Status = CsrpRegisterSubsystem(); + /* We're all set! Connect to SM! */ + Status = SmConnectToSm(&CsrSbApiPortName, + CsrSbApiPort, + IMAGE_SUBSYSTEM_WINDOWS_GUI, + &CsrSmApiPort); if (!NT_SUCCESS(Status)) { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpRegisterSubsystem", Status); + DPRINT1("CSRSRV:%s: SmConnectToSm failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; } + /* Finito! Signal the event */ + Status = NtSetEvent(CsrInitializationEvent, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("CSRSRV:%s: NtSetEvent failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; + } + + /* Close the event handle now */ + NtClose(CsrInitializationEvent); + + /* Have us handle Hard Errors */ Status = NtSetDefaultHardErrorPort(hApiPort); if (!NT_SUCCESS(Status)) { - DPRINT1("CSRSRV failed in %s with status %lx\n", "CsrpCreateHardErrorPort", Status); + DPRINT1("CSRSRV:%s: NtSetDefaultHardErrorPort failed (Status=%08lx)\n", + __FUNCTION__, Status); + return Status; } - - if (CallInitComplete()) - { - return STATUS_SUCCESS; - } - - return STATUS_UNSUCCESSFUL; + + /* Return status */ + return Status; } BOOL diff --git a/reactos/subsystems/win32/csrss/include/api.h b/reactos/subsystems/win32/csrss/include/api.h index fab8af89151..a69a78a2fba 100644 --- a/reactos/subsystems/win32/csrss/include/api.h +++ b/reactos/subsystems/win32/csrss/include/api.h @@ -121,14 +121,18 @@ CSR_API(CsrSrvCreateThread); CSR_API(CsrGetShutdownParameters); CSR_API(CsrSetShutdownParameters); +PCSR_THREAD +NTAPI +CsrAllocateThread(IN PCSRSS_PROCESS_DATA CsrProcess); + /* api/wapi.c */ NTSTATUS FASTCALL CsrApiRegisterDefinitions(PCSRSS_API_DEFINITION NewDefinitions); VOID FASTCALL CsrApiCallHandler(PCSRSS_PROCESS_DATA ProcessData, PCSR_API_MESSAGE Request); -DWORD WINAPI ServerSbApiPortThread (PVOID PortHandle); +VOID WINAPI CsrSbApiRequestThread (PVOID PortHandle); VOID NTAPI ClientConnectionThread(HANDLE ServerPort); -extern HANDLE CsrssApiHeap; +extern HANDLE CsrSbApiPort; /* api/process.c */ typedef NTSTATUS (WINAPI *CSRSS_ENUM_PROCESS_PROC)(PCSRSS_PROCESS_DATA ProcessData, diff --git a/reactos/subsystems/win32/csrss/win32csr/dllmain.c b/reactos/subsystems/win32/csrss/win32csr/dllmain.c index b2eb560b75b..f8a4f96c208 100644 --- a/reactos/subsystems/win32/csrss/win32csr/dllmain.c +++ b/reactos/subsystems/win32/csrss/win32csr/dllmain.c @@ -335,14 +335,14 @@ BOOL WINAPI Win32CsrInitialization(PCSRSS_API_DEFINITION *ApiDefinitions, PCSRPLUGIN_SERVER_PROCS ServerProcs, PCSRSS_EXPORTED_FUNCS Exports, - HANDLE CsrssApiHeap) + HANDLE CsrHeap) { HANDLE ServerThread; CLIENT_ID ClientId; NTSTATUS Status; CsrExports = *Exports; - Win32CsrApiHeap = CsrssApiHeap; + Win32CsrApiHeap = CsrHeap; CsrpInitVideo();