Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries * FILE: lib/rtl/process.c * PURPOSE: Process functions * PROGRAMMER: Alex Ionescu (alex@relsoft.net) * Ariadne (ariadne@xs4all.nl) * Eric Kohl */
/* INCLUDES ****************************************************************/
#include <rtl.h>
#define NDEBUG#include <debug.h>
/* INTERNAL FUNCTIONS *******************************************************/
NTSTATUSNTAPIRtlpMapFile(PUNICODE_STRING ImageFileName, ULONG Attributes, PHANDLE Section){ OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE hFile = NULL; IO_STATUS_BLOCK IoStatusBlock;
/* Open the Image File */ InitializeObjectAttributes(&ObjectAttributes, ImageFileName, Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT), NULL, NULL); Status = ZwOpenFile(&hFile, SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to read image file from disk, Status = 0x%08X\n", Status); return Status; }
/* Now create a section for this image */ Status = ZwCreateSection(Section, SECTION_ALL_ACCESS, NULL, NULL, PAGE_EXECUTE, SEC_IMAGE, hFile); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create section for image file, Status = 0x%08X\n", Status); }
ZwClose(hFile); return Status;}
/* FUNCTIONS ****************************************************************/
NTSTATUSNTAPIRtlpInitEnvironment(HANDLE ProcessHandle, PPEB Peb, PRTL_USER_PROCESS_PARAMETERS ProcessParameters){ NTSTATUS Status; PVOID BaseAddress = NULL; SIZE_T EnviroSize; SIZE_T Size; PWCHAR Environment = NULL; DPRINT("RtlpInitEnvironment(ProcessHandle: %p, Peb: %p Params: %p)\n", ProcessHandle, Peb, ProcessParameters);
/* Give the caller 1MB if he requested it */ if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB) { /* Give 1MB starting at 0x4 */ BaseAddress = (PVOID)4; EnviroSize = (1024 * 1024) - 256; Status = ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, 0, &EnviroSize, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to reserve 1MB of space\n"); return Status; } }
/* Find the end of the Enviroment Block */ if ((Environment = (PWCHAR)ProcessParameters->Environment)) { while (*Environment++) while (*Environment++);
/* Calculate the size of the block */ EnviroSize = (ULONG)((ULONG_PTR)Environment - (ULONG_PTR)ProcessParameters->Environment);
/* Allocate and Initialize new Environment Block */ Size = EnviroSize; Status = ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, 0, &Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to allocate Environment Block\n"); return Status; }
/* Write the Environment Block */ ZwWriteVirtualMemory(ProcessHandle, BaseAddress, ProcessParameters->Environment, EnviroSize, NULL);
/* Save pointer */ ProcessParameters->Environment = BaseAddress; }
/* Now allocate space for the Parameter Block */ BaseAddress = NULL; Size = ProcessParameters->MaximumLength; Status = ZwAllocateVirtualMemory(ProcessHandle, &BaseAddress, 0, &Size, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to allocate Parameter Block\n"); return Status; }
/* Write the Parameter Block */ Status = ZwWriteVirtualMemory(ProcessHandle, BaseAddress, ProcessParameters, ProcessParameters->Length, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to write the Parameter Block\n"); return Status; }
/* Write pointer to Parameter Block */ Status = ZwWriteVirtualMemory(ProcessHandle, &Peb->ProcessParameters, &BaseAddress, sizeof(BaseAddress), NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to write pointer to Parameter Block\n"); return Status; }
/* Return */ return STATUS_SUCCESS;}
/* * @implemented * * Creates a process and its initial thread. * * NOTES: * - The first thread is created suspended, so it needs a manual resume!!! * - If ParentProcess is NULL, current process is used * - ProcessParameters must be normalized * - Attributes are object attribute flags used when opening the ImageFileName. * Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE. * * -Gunnar */NTSTATUSNTAPIRtlCreateUserProcess(IN PUNICODE_STRING ImageFileName, IN ULONG Attributes, IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters, IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, IN HANDLE ParentProcess OPTIONAL, IN BOOLEAN InheritHandles, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL, OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo){ NTSTATUS Status; HANDLE hSection; PROCESS_BASIC_INFORMATION ProcessBasicInfo; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS"); DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
/* Map and Load the File */ Status = RtlpMapFile(ImageFileName, Attributes, &hSection); if (!NT_SUCCESS(Status)) { DPRINT1("Could not map process image\n"); return Status; }
/* Clean out the current directory handle if we won't use it */ if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
/* Use us as parent if none other specified */ if (!ParentProcess) ParentProcess = NtCurrentProcess();
/* Initialize the Object Attributes */ InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, ProcessSecurityDescriptor);
/* * If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the * watch of WindowsSS */ if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) && (wcsstr(ImageFileName->Buffer, L"csrss"))) { ObjectAttributes.ObjectName = &DebugString; }
/* Create Kernel Process Object */ Status = ZwCreateProcess(&ProcessInfo->ProcessHandle, PROCESS_ALL_ACCESS, &ObjectAttributes, ParentProcess, InheritHandles, hSection, DebugPort, ExceptionPort); if (!NT_SUCCESS(Status)) { DPRINT1("Could not create Kernel Process Object\n"); ZwClose(hSection); return Status; }
/* Get some information on the image */ Status = ZwQuerySection(hSection, SectionImageInformation, &ProcessInfo->ImageInformation, sizeof(SECTION_IMAGE_INFORMATION), NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Could not query Section Info\n"); ZwClose(ProcessInfo->ProcessHandle); ZwClose(hSection); return Status; }
/* Get some information about the process */ Status = ZwQueryInformationProcess(ProcessInfo->ProcessHandle, ProcessBasicInformation, &ProcessBasicInfo, sizeof(ProcessBasicInfo), NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Could not query Process Info\n"); ZwClose(ProcessInfo->ProcessHandle); ZwClose(hSection); return Status; }
/* Duplicate the standard handles */ Status = STATUS_SUCCESS; _SEH2_TRY { if (ProcessParameters->StandardInput) { Status = ZwDuplicateObject(ParentProcess, ProcessParameters->StandardInput, ProcessInfo->ProcessHandle, &ProcessParameters->StandardInput, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } }
if (ProcessParameters->StandardOutput) { Status = ZwDuplicateObject(ParentProcess, ProcessParameters->StandardOutput, ProcessInfo->ProcessHandle, &ProcessParameters->StandardOutput, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } }
if (ProcessParameters->StandardError) { Status = ZwDuplicateObject(ParentProcess, ProcessParameters->StandardError, ProcessInfo->ProcessHandle, &ProcessParameters->StandardError, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); if (!NT_SUCCESS(Status)) { _SEH2_LEAVE; } } } _SEH2_FINALLY { if (!NT_SUCCESS(Status)) { ZwClose(ProcessInfo->ProcessHandle); ZwClose(hSection); } } _SEH2_END;
if (!NT_SUCCESS(Status)) return Status;
/* Create Process Environment */ Status = RtlpInitEnvironment(ProcessInfo->ProcessHandle, ProcessBasicInfo.PebBaseAddress, ProcessParameters); if (!NT_SUCCESS(Status)) { DPRINT1("Could not Create Process Environment\n"); ZwClose(ProcessInfo->ProcessHandle); ZwClose(hSection); return Status; }
/* Create the first Thread */ Status = RtlCreateUserThread(ProcessInfo->ProcessHandle, ThreadSecurityDescriptor, TRUE, ProcessInfo->ImageInformation.ZeroBits, ProcessInfo->ImageInformation.MaximumStackSize, ProcessInfo->ImageInformation.CommittedStackSize, ProcessInfo->ImageInformation.TransferAddress, ProcessBasicInfo.PebBaseAddress, &ProcessInfo->ThreadHandle, &ProcessInfo->ClientId); if (!NT_SUCCESS(Status)) { DPRINT1("Could not Create Thread\n"); ZwClose(ProcessInfo->ProcessHandle); ZwClose(hSection); /* Don't try to optimize this on top! */ return Status; }
/* Close the Section Handle and return */ ZwClose(hSection); return STATUS_SUCCESS;}
/* * @implemented */PVOIDNTAPIRtlEncodePointer(IN PVOID Pointer){ ULONG Cookie; NTSTATUS Status;
Status = ZwQueryInformationProcess(NtCurrentProcess(), ProcessCookie, &Cookie, sizeof(Cookie), NULL); if(!NT_SUCCESS(Status)) { DPRINT1("Failed to receive the process cookie! Status: 0x%lx\n", Status); return Pointer; }
return (PVOID)((ULONG_PTR)Pointer ^ Cookie);}
/* * @implemented */PVOIDNTAPIRtlDecodePointer(IN PVOID Pointer){ return RtlEncodePointer(Pointer);}
/* * @implemented */PVOIDNTAPIRtlEncodeSystemPointer(IN PVOID Pointer){ return (PVOID)((ULONG_PTR)Pointer ^ SharedUserData->Cookie);}
/* * @implemented */PVOIDNTAPIRtlDecodeSystemPointer(IN PVOID Pointer){ return RtlEncodeSystemPointer(Pointer);}
/* * @implemented * * NOTES: * Implementation based on the documentation from: * http://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/peb/setprocessiscritical.htm */NTSTATUS__cdeclRtlSetProcessIsCritical(IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN NeedBreaks){ ULONG BreakOnTermination;
/* Initialize to FALSE */ if (OldValue) *OldValue = FALSE;
/* Fail, if the critical breaks flag is required but is not set */ if ((NeedBreaks) && !(NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS)) { return STATUS_UNSUCCESSFUL; }
/* Check if the caller wants the old value */ if (OldValue) { /* Query and return the old break on termination flag for the process */ ZwQueryInformationProcess(NtCurrentProcess(), ProcessBreakOnTermination, &BreakOnTermination, sizeof(ULONG), NULL); *OldValue = (BOOLEAN)BreakOnTermination; }
/* Set the break on termination flag for the process */ BreakOnTermination = NewValue; return ZwSetInformationProcess(NtCurrentProcess(), ProcessBreakOnTermination, &BreakOnTermination, sizeof(ULONG));}
ULONGNTAPIRtlGetCurrentProcessorNumber(VOID){ /* Forward to kernel */ return NtGetCurrentProcessorNumber();}
_IRQL_requires_max_(APC_LEVEL)ULONGNTAPIRtlRosGetAppcompatVersion(VOID){ /* Get the current PEB */ PPEB Peb = RtlGetCurrentPeb(); if (Peb == NULL) { /* Default to Server 2003 */ return _WIN32_WINNT_WS03; }
/* Calculate OS version from PEB fields */ return (Peb->OSMajorVersion << 8) | Peb->OSMinorVersion;}