-/* $Id$
- *
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS system libraries
- * FILE: lib/ntdll/rtl/process.c
- * PURPOSE: Process functions
- * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
- * UPDATE HISTORY:
- * Created 01/11/98
+/*
+ * 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 <ddk/ntddk.h>
-#include <napi/i386/segment.h>
-#include <ntdll/ldr.h>
-#include <ntdll/base.h>
-#include <ntdll/rtl.h>
+#include <rtl.h>
#define NDEBUG
-#include <ntdll/ntdll.h>
-
-/* FUNCTIONS ****************************************************************/
+#include <debug.h>
+/* INTERNAL FUNCTIONS *******************************************************/
-static NTSTATUS
+NTSTATUS
+NTAPI
RtlpMapFile(PUNICODE_STRING ImageFileName,
- PRTL_USER_PROCESS_PARAMETERS Ppb,
- ULONG Attributes,
- PHANDLE Section)
+ ULONG Attributes,
+ PHANDLE Section)
{
- HANDLE hFile;
- IO_STATUS_BLOCK IoStatusBlock;
- OBJECT_ATTRIBUTES ObjectAttributes;
- PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
- NTSTATUS Status;
-
- hFile = NULL;
-
- RtlDeNormalizeProcessParams (Ppb);
-
-// DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
-
- InitializeObjectAttributes(&ObjectAttributes,
- ImageFileName,
- Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
- NULL,
- SecurityDescriptor);
-
- RtlNormalizeProcessParams (Ppb);
-
- /*
- * Try to open the executable
- */
-
- 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))
- {
- return(Status);
- }
-
- Status = ZwCreateSection(Section,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_EXECUTE,
- SEC_IMAGE,
- hFile);
- ZwClose(hFile);
-
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- return(STATUS_SUCCESS);
+ 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\n");
+ 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\n");
+ }
+
+ ZwClose(hFile);
+ return Status;
}
-static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
- PRTL_USER_PROCESS_PARAMETERS Ppb,
- PVOID* ImageBaseAddress)
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS
+NTAPI
+RtlpInitEnvironment(HANDLE ProcessHandle,
+ PPEB Peb,
+ PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
{
- NTSTATUS Status;
- PVOID PpbBase;
- ULONG PpbSize;
- ULONG BytesWritten;
- ULONG Offset;
- PVOID EnvPtr = NULL;
- ULONG EnvSize = 0;
-
- /* create the Environment */
- if (Ppb->Environment != NULL)
- {
- MEMORY_BASIC_INFORMATION MemInfo;
-
- Status = ZwQueryVirtualMemory (NtCurrentProcess (),
- Ppb->Environment,
- MemoryBasicInformation,
- &MemInfo,
- sizeof(MEMORY_BASIC_INFORMATION),
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- EnvSize = MemInfo.RegionSize;
- }
- DPRINT("EnvironmentSize %ld\n", EnvSize);
-
- /* allocate and initialize new environment block */
- if (EnvSize != 0)
- {
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &EnvPtr,
- 0,
- &EnvSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- ZwWriteVirtualMemory(ProcessHandle,
- EnvPtr,
- Ppb->Environment,
- EnvSize,
- &BytesWritten);
- }
- DPRINT("EnvironmentPointer %p\n", EnvPtr);
-
- /* create the PPB */
- PpbBase = NULL;
- PpbSize = Ppb->AllocationSize;
-
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &PpbBase,
- 0,
- &PpbSize,
- MEM_RESERVE | MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
-
- DPRINT("Ppb->MaximumLength %x\n", Ppb->AllocationSize);
-
- /* write process parameters block*/
- RtlDeNormalizeProcessParams (Ppb);
- ZwWriteVirtualMemory(ProcessHandle,
- PpbBase,
- Ppb,
- Ppb->AllocationSize,
-
- &BytesWritten);
- RtlNormalizeProcessParams (Ppb);
-
- /* write pointer to environment */
- Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
- ZwWriteVirtualMemory(ProcessHandle,
- (PVOID)(PpbBase + Offset),
- &EnvPtr,
- sizeof(EnvPtr),
- &BytesWritten);
-
- /* write pointer to process parameter block */
- Offset = FIELD_OFFSET(PEB, ProcessParameters);
- ZwWriteVirtualMemory(ProcessHandle,
- (PVOID)(PEB_BASE + Offset),
- &PpbBase,
- sizeof(PpbBase),
- &BytesWritten);
-
- /* Read image base address. */
- Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
- ZwReadVirtualMemory(ProcessHandle,
- (PVOID)(PEB_BASE + Offset),
- ImageBaseAddress,
- sizeof(PVOID),
- &BytesWritten);
-
- return(STATUS_SUCCESS);
+ NTSTATUS Status;
+ PVOID BaseAddress = NULL;
+ SIZE_T EnviroSize;
+ SIZE_T Size;
+ PWCHAR Environment = 0;
+ DPRINT("RtlpInitEnvironment (hProcess: %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;
+ 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 */
+ ZwWriteVirtualMemory(ProcessHandle,
+ BaseAddress,
+ ProcessParameters,
+ ProcessParameters->Length,
+ NULL);
+
+ /* Write pointer to Parameter Block */
+ ZwWriteVirtualMemory(ProcessHandle,
+ &Peb->ProcessParameters,
+ &BaseAddress,
+ sizeof(BaseAddress),
+ NULL);
+
+ /* Return */
+ return STATUS_SUCCESS;
}
-
/*
* @implemented
*
* - 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.
+ * - Attributes are object attribute flags used when opening the ImageFileName.
* Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
*
* -Gunnar
*/
-NTSTATUS STDCALL
-RtlCreateUserProcess(
- 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_PROCESS_INFO ProcessInfo
- )
+NTSTATUS
+NTAPI
+RtlCreateUserProcess(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 CurDir 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 */
+ 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;
+ }
+
+ /* Create Process Environment */
+ RtlpInitEnvironment(ProcessInfo->ProcessHandle,
+ ProcessBasicInfo.PebBaseAddress,
+ ProcessParameters);
+
+ /* 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
+ */
+PVOID
+NTAPI
+RtlEncodePointer(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
+ */
+PVOID
+NTAPI
+RtlDecodePointer(IN PVOID Pointer)
{
- HANDLE hSection;
- NTSTATUS Status;
- PROCESS_BASIC_INFORMATION ProcessBasicInfo;
- ULONG retlen;
- SECTION_IMAGE_INFORMATION Sii;
- ULONG ResultLength;
- PVOID ImageBaseAddress;
-
- DPRINT("RtlCreateUserProcess\n");
-
- Status = RtlpMapFile(ImageFileName,
- ProcessParameters,
- Attributes,
- &hSection);
- if( !NT_SUCCESS( Status ) )
- return Status;
-
- /*
- * Create a new process
- */
- if (ParentProcess == NULL)
- ParentProcess = NtCurrentProcess();
-
- Status = ZwCreateProcess(&(ProcessInfo->ProcessHandle),
- PROCESS_ALL_ACCESS,
- NULL,
- ParentProcess,
- InheritHandles,
- hSection,
- DebugPort,
- ExceptionPort);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(hSection);
- return(Status);
- }
-
- /*
- * Get some information about the process
- */
- ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
- ProcessBasicInformation,
- &ProcessBasicInfo,
- sizeof(ProcessBasicInfo),
- &retlen);
- DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
- ProcessBasicInfo.UniqueProcessId);
- ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
-
- /*
- * Create Process Environment Block
- */
- DPRINT("Creating peb\n");
- KlInitPeb(ProcessInfo->ProcessHandle,
- ProcessParameters,
- &ImageBaseAddress);
-
- Status = ZwQuerySection(hSection,
- SectionImageInformation,
- &Sii,
- sizeof(Sii),
- &ResultLength);
- if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
- {
- DPRINT("Failed to get section image information.\n");
- ZwClose(hSection);
- return(Status);
- }
-
- DPRINT("Creating thread for process\n");
- Status = RtlCreateUserThread(
- ProcessInfo->ProcessHandle,
- NULL,
- TRUE, /* CreateSuspended? */
- 0,
- &Sii.StackReserve,
- &Sii.StackCommit,
- ImageBaseAddress + (ULONG)Sii.EntryPoint,
- (PVOID)PEB_BASE,
- &ProcessInfo->ThreadHandle,
- &ProcessInfo->ClientId
- );
-
- ZwClose(hSection);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT("Failed to create thread\n");
- return(Status);
- }
-
- return(STATUS_SUCCESS);
+ return RtlEncodePointer(Pointer);
}
+/*
+ * @unimplemented
+ */
+PVOID
+NTAPI
+RtlEncodeSystemPointer(IN PVOID Pointer)
+{
+ UNIMPLEMENTED;
+ return NULL;
+}
+/*
+ * @implemented
+ *
+ * NOTES:
+ * Implementation based on the documentation from:
+ * http://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/peb/setprocessiscritical.htm
+ */
+NTSTATUS
+NTAPI
+RtlSetProcessIsCritical(IN BOOLEAN NewValue,
+ OUT PBOOLEAN OldValue OPTIONAL,
+ IN BOOLEAN NeedBreaks)
+{
+ ULONG BreakOnTermination = FALSE;
+
+ if (OldValue)
+ *OldValue = FALSE;
+
+ /* Fail, if the critical breaks flag is required but is not set */
+ if (NeedBreaks == TRUE &&
+ !(NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS))
+ return STATUS_UNSUCCESSFUL;
+
+ 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));
+}
-/* EOF */
+ULONG
+NTAPI
+RtlGetCurrentProcessorNumber(VOID)
+{
+ /* Forward to kernel */
+ return NtGetCurrentProcessorNumber();
+}