/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Base API Server DLL * FILE: subsystems/win/basesrv/proc.c * PURPOSE: Process and Thread Management * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */ /* INCLUDES *******************************************************************/ #include "basesrv.h" #include "vdm.h" #define NDEBUG #include /* GLOBALS ********************************************************************/ /* User notification procedure to be called when a process is created */ static BASE_PROCESS_CREATE_NOTIFY_ROUTINE UserNotifyProcessCreate = NULL; /* PUBLIC SERVER APIS *********************************************************/ CSR_API(BaseSrvDebugProcess) { /* Deprecated */ return STATUS_UNSUCCESSFUL; } CSR_API(BaseSrvRegisterThread) { DPRINT1("%s not yet implemented\n", __FUNCTION__); return STATUS_NOT_IMPLEMENTED; } CSR_API(BaseSrvSxsCreateActivationContext) { DPRINT1("%s not yet implemented\n", __FUNCTION__); return STATUS_NOT_IMPLEMENTED; } CSR_API(BaseSrvSetTermsrvAppInstallMode) { DPRINT1("%s not yet implemented\n", __FUNCTION__); return STATUS_NOT_IMPLEMENTED; } CSR_API(BaseSrvSetTermsrvClientTimeZone) { DPRINT1("%s not yet implemented\n", __FUNCTION__); return STATUS_NOT_IMPLEMENTED; } CSR_API(BaseSrvGetTempFile) { static UINT BaseGetTempFileUnique = 0; PBASE_GET_TEMP_FILE GetTempFile = &((PBASE_API_MESSAGE)ApiMessage)->Data.GetTempFileRequest; /* Return 16-bits ID */ GetTempFile->UniqueID = (++BaseGetTempFileUnique & 0xFFFF); DPRINT("Returning: %u\n", GetTempFile->UniqueID); return GetTempFile->UniqueID; } CSR_API(BaseSrvCreateProcess) { NTSTATUS Status; PBASE_CREATE_PROCESS CreateProcessRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateProcessRequest; HANDLE ProcessHandle, ThreadHandle; PCSR_THREAD CsrThread; PCSR_PROCESS Process; ULONG Flags = 0, DebugFlags = 0, VdmPower = 0; /* Get the current client thread */ CsrThread = CsrGetClientThread(); ASSERT(CsrThread != NULL); Process = CsrThread->Process; /* Extract the flags out of the process handle */ Flags = (ULONG_PTR)CreateProcessRequest->ProcessHandle & 3; CreateProcessRequest->ProcessHandle = (HANDLE)((ULONG_PTR)CreateProcessRequest->ProcessHandle & ~3); /* Some things should be done if this is a VDM process */ if (CreateProcessRequest->VdmBinaryType) { /* We need to set the VDM power later on */ VdmPower = 1; } /* Duplicate the process handle */ Status = NtDuplicateObject(Process->ProcessHandle, CreateProcessRequest->ProcessHandle, NtCurrentProcess(), &ProcessHandle, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to duplicate process handle: %lx\n", Status); return Status; } /* Duplicate the thread handle */ Status = NtDuplicateObject(Process->ProcessHandle, CreateProcessRequest->ThreadHandle, NtCurrentProcess(), &ThreadHandle, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to duplicate thread handle: %lx\n", Status); NtClose(ProcessHandle); return Status; } /* If this is a VDM process, request VDM power */ if (VdmPower) { Status = NtSetInformationProcess(ProcessHandle, ProcessWx86Information, &VdmPower, sizeof(VdmPower)); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get VDM powers\n"); NtClose(ProcessHandle); NtClose(ThreadHandle); return Status; } } /* Flags conversion. FIXME: More need conversion */ if (CreateProcessRequest->CreationFlags & CREATE_NEW_PROCESS_GROUP) { DebugFlags |= CsrProcessCreateNewGroup; } if ((Flags & 2) == 0) { /* We are launching a console process */ DebugFlags |= CsrProcessIsConsoleApp; } /* FIXME: SxS Stuff */ /* Call CSRSRV to create the CSR_PROCESS structure and the first CSR_THREAD */ Status = CsrCreateProcess(ProcessHandle, ThreadHandle, &CreateProcessRequest->ClientId, Process->NtSession, DebugFlags, NULL); if (Status == STATUS_THREAD_IS_TERMINATING) { DPRINT1("Thread already dead\n"); /* Set the special reply value so we don't reply this message back */ *ReplyCode = CsrReplyDeadClient; return Status; } /* Check for other failures */ if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create process/thread structures: %lx\n", Status); return Status; } /* Call the user notification procedure */ if (UserNotifyProcessCreate) { UserNotifyProcessCreate(CreateProcessRequest->ClientId.UniqueProcess, Process->ClientId.UniqueThread, 0, Flags); } /* Check if this is a VDM process */ if (CreateProcessRequest->VdmBinaryType) { PVDM_CONSOLE_RECORD ConsoleRecord; if (CreateProcessRequest->VdmTask != 0) { /* Get the console record using the task ID */ Status = GetConsoleRecordBySessionId(CreateProcessRequest->VdmTask, &ConsoleRecord); } else { /* Get the console record using the console handle */ Status = BaseSrvGetConsoleRecord(CreateProcessRequest->hVDM, &ConsoleRecord); } /* Check if it failed */ if (!NT_SUCCESS(Status)) return Status; /* Store the process ID of the VDM in the console record */ ConsoleRecord->ProcessId = HandleToUlong(CreateProcessRequest->ClientId.UniqueProcess); } /* Return the result of this operation */ return Status; } CSR_API(BaseSrvCreateThread) { NTSTATUS Status; PBASE_CREATE_THREAD CreateThreadRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.CreateThreadRequest; PCSR_THREAD CurrentThread; HANDLE ThreadHandle; PCSR_PROCESS CsrProcess; /* Get the current CSR thread */ CurrentThread = CsrGetClientThread(); if (!CurrentThread) { DPRINT1("Server Thread TID: [%lx.%lx]\n", CreateThreadRequest->ClientId.UniqueProcess, CreateThreadRequest->ClientId.UniqueThread); return STATUS_SUCCESS; // server-to-server } /* Get the CSR Process for this request */ CsrProcess = CurrentThread->Process; if (CsrProcess->ClientId.UniqueProcess != CreateThreadRequest->ClientId.UniqueProcess) { /* This is a remote thread request -- is it within the server itself? */ if (CreateThreadRequest->ClientId.UniqueProcess == NtCurrentTeb()->ClientId.UniqueProcess) { /* Accept this without any further work */ return STATUS_SUCCESS; } /* Get the real CSR Process for the remote thread's process */ Status = CsrLockProcessByClientId(CreateThreadRequest->ClientId.UniqueProcess, &CsrProcess); if (!NT_SUCCESS(Status)) return Status; } /* Duplicate the thread handle so we can own it */ Status = NtDuplicateObject(CurrentThread->Process->ProcessHandle, CreateThreadRequest->ThreadHandle, NtCurrentProcess(), &ThreadHandle, 0, 0, DUPLICATE_SAME_ACCESS); if (NT_SUCCESS(Status)) { /* Call CSRSRV to tell it about the new thread */ Status = CsrCreateThread(CsrProcess, ThreadHandle, &CreateThreadRequest->ClientId, TRUE); } /* Unlock the process and return */ if (CsrProcess != CurrentThread->Process) CsrUnlockProcess(CsrProcess); return Status; } CSR_API(BaseSrvExitProcess) { PCSR_THREAD CsrThread = CsrGetClientThread(); ASSERT(CsrThread != NULL); /* Set the special reply value so we don't reply this message back */ *ReplyCode = CsrReplyDeadClient; /* Remove the CSR_THREADs and CSR_PROCESS */ return CsrDestroyProcess(&CsrThread->ClientId, (NTSTATUS)((PBASE_API_MESSAGE)ApiMessage)->Data.ExitProcessRequest.uExitCode); } CSR_API(BaseSrvGetProcessShutdownParam) { PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest; PCSR_THREAD CsrThread = CsrGetClientThread(); ASSERT(CsrThread); ShutdownParametersRequest->ShutdownLevel = CsrThread->Process->ShutdownLevel; /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */ ShutdownParametersRequest->ShutdownFlags = CsrThread->Process->ShutdownFlags & SHUTDOWN_NORETRY; return STATUS_SUCCESS; } CSR_API(BaseSrvSetProcessShutdownParam) { PBASE_GETSET_PROCESS_SHUTDOWN_PARAMS ShutdownParametersRequest = &((PBASE_API_MESSAGE)ApiMessage)->Data.ShutdownParametersRequest; PCSR_THREAD CsrThread = CsrGetClientThread(); ASSERT(CsrThread); /* Only SHUTDOWN_NORETRY flag is valid for this API. The other private flags are for CSRSRV/WINSRV only. */ if (ShutdownParametersRequest->ShutdownFlags & ~SHUTDOWN_NORETRY) { /* If there were other flags specified, fail the call */ return STATUS_INVALID_PARAMETER; } CsrThread->Process->ShutdownLevel = ShutdownParametersRequest->ShutdownLevel; /* Notice that all the possible other private flags are reinitialized here */ CsrThread->Process->ShutdownFlags = ShutdownParametersRequest->ShutdownFlags; return STATUS_SUCCESS; } /* PUBLIC API *****************************************************************/ VOID NTAPI BaseSetProcessCreateNotify(IN BASE_PROCESS_CREATE_NOTIFY_ROUTINE ProcessCreateNotifyProc) { /* Set the user notification procedure to be called when a process is created */ UserNotifyProcessCreate = ProcessCreateNotifyProc; } /* EOF */