3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/ntdll/rtl/process.c
6 * PURPOSE: Process functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
12 /* INCLUDES ****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <napi/i386/segment.h>
16 #include <ntdll/ldr.h>
17 #include <ntdll/base.h>
18 #include <ntdll/rtl.h>
21 #include <ntdll/ntdll.h>
23 /* FUNCTIONS ****************************************************************/
26 RtlpCreateFirstThread(HANDLE ProcessHandle,
29 LPTHREAD_START_ROUTINE lpStartAddress,
34 OBJECT_ATTRIBUTES ObjectAttributes;
35 CONTEXT ThreadContext;
36 INITIAL_TEB InitialTeb;
37 ULONG OldPageProtection;
39 ULONG InitialStack[5];
42 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
43 ObjectAttributes.RootDirectory = NULL;
44 ObjectAttributes.ObjectName = NULL;
45 ObjectAttributes.Attributes = 0;
46 ObjectAttributes.SecurityQualityOfService = NULL;
48 if (StackReserve > 0x100000)
49 InitialTeb.StackReserve = StackReserve;
51 InitialTeb.StackReserve = 0x100000; /* 1MByte */
55 if (StackCommit > PAGE_SIZE)
56 InitialTeb.StackCommit = StackCommit;
58 InitialTeb.StackCommit = PAGE_SIZE;
60 InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
62 /* add guard page size */
63 InitialTeb.StackCommit += PAGE_SIZE;
66 InitialTeb.StackAllocate = NULL;
67 Status = NtAllocateVirtualMemory(ProcessHandle,
68 &InitialTeb.StackAllocate,
70 &InitialTeb.StackReserve,
73 if (!NT_SUCCESS(Status))
75 DPRINT("Error reserving stack space!\n");
79 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
80 InitialTeb.StackAllocate, InitialTeb.StackReserve);
82 InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
83 InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
85 DPRINT("StackBase: %p StackCommit: 0x%lX\n",
86 InitialTeb.StackBase, InitialTeb.StackCommit);
89 Status = NtAllocateVirtualMemory(ProcessHandle,
90 &InitialTeb.StackLimit,
92 &InitialTeb.StackCommit,
95 if (!NT_SUCCESS(Status))
97 /* release the stack space */
98 NtFreeVirtualMemory(ProcessHandle,
99 InitialTeb.StackAllocate,
100 &InitialTeb.StackReserve,
103 DPRINT("Error comitting stack page(s)!\n");
107 DPRINT("StackLimit: %p\n", InitialTeb.StackLimit);
109 /* Protect guard page */
110 Status = NtProtectVirtualMemory(ProcessHandle,
111 InitialTeb.StackLimit,
113 PAGE_GUARD | PAGE_READWRITE,
115 if (!NT_SUCCESS(Status))
117 /* release the stack space */
118 NtFreeVirtualMemory(ProcessHandle,
119 InitialTeb.StackAllocate,
120 &InitialTeb.StackReserve,
123 DPRINT("Error comitting guard page!\n");
127 memset(&ThreadContext,0,sizeof(CONTEXT));
128 ThreadContext.Eip = (ULONG)lpStartAddress;
129 ThreadContext.SegGs = USER_DS;
130 ThreadContext.SegFs = TEB_SELECTOR;
131 ThreadContext.SegEs = USER_DS;
132 ThreadContext.SegDs = USER_DS;
133 ThreadContext.SegCs = USER_CS;
134 ThreadContext.SegSs = USER_DS;
135 ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 20;
136 ThreadContext.EFlags = (1<<1) + (1<<9);
138 DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
141 * Write in the initial stack.
144 InitialStack[1] = PEB_BASE;
145 Status = ZwWriteVirtualMemory(ProcessHandle,
146 (PVOID)ThreadContext.Esp,
148 sizeof(InitialStack),
150 if (!NT_SUCCESS(Status))
152 DPRINT1("Failed to write initial stack.\n");
156 Status = NtCreateThread(ThreadHandle,
164 if (!NT_SUCCESS(Status))
166 NtFreeVirtualMemory(ProcessHandle,
167 InitialTeb.StackAllocate,
168 &InitialTeb.StackReserve,
173 if (ClientId != NULL)
175 memcpy(&ClientId->UniqueThread, &Cid.UniqueThread, sizeof(ULONG));
178 return(STATUS_SUCCESS);
182 RtlpMapFile(PRTL_USER_PROCESS_PARAMETERS Ppb,
188 IO_STATUS_BLOCK IoStatusBlock;
189 OBJECT_ATTRIBUTES ObjectAttributes;
190 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
198 RtlDeNormalizeProcessParams (Ppb);
200 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
202 InitializeObjectAttributes(&ObjectAttributes,
203 &(Ppb->ImagePathName),
204 Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
208 RtlNormalizeProcessParams (Ppb);
213 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
214 // DbgPrint("ImagePathName %S\n", Ppb->ImagePathName.Buffer);
215 s = wcsrchr(Ppb->ImagePathName.Buffer, '\\');
218 s = Ppb->ImagePathName.Buffer;
229 for (i = 0; i < 8; i++)
231 ImageFileName[i] = (CHAR)(s[i]);
239 * Try to open the executable
242 Status = NtOpenFile(&hFile,
243 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
246 FILE_SHARE_DELETE|FILE_SHARE_READ,
247 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
249 if (!NT_SUCCESS(Status))
254 Status = NtCreateSection(Section,
263 if (!NT_SUCCESS(Status))
268 return(STATUS_SUCCESS);
271 static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
272 PRTL_USER_PROCESS_PARAMETERS Ppb,
273 PVOID* ImageBaseAddress)
283 /* create the Environment */
284 if (Ppb->Environment != NULL)
286 MEMORY_BASIC_INFORMATION MemInfo;
288 Status = NtQueryVirtualMemory (NtCurrentProcess (),
290 MemoryBasicInformation,
292 sizeof(MEMORY_BASIC_INFORMATION),
294 if (!NT_SUCCESS(Status))
298 EnvSize = MemInfo.RegionSize;
300 DPRINT("EnvironmentSize %ld\n", EnvSize);
302 /* allocate and initialize new environment block */
305 Status = NtAllocateVirtualMemory(ProcessHandle,
309 MEM_RESERVE | MEM_COMMIT,
311 if (!NT_SUCCESS(Status))
316 NtWriteVirtualMemory(ProcessHandle,
322 DPRINT("EnvironmentPointer %p\n", EnvPtr);
326 PpbSize = Ppb->AllocationSize;
\r
327 Status = NtAllocateVirtualMemory(ProcessHandle,
331 MEM_RESERVE | MEM_COMMIT,
333 if (!NT_SUCCESS(Status))
338 DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
340 /* write process parameters block*/
341 RtlDeNormalizeProcessParams (Ppb);
342 NtWriteVirtualMemory(ProcessHandle,
345 Ppb->AllocationSize,
\r
347 RtlNormalizeProcessParams (Ppb);
349 /* write pointer to environment */
350 Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
351 NtWriteVirtualMemory(ProcessHandle,
352 (PVOID)(PpbBase + Offset),
357 /* write pointer to process parameter block */
358 Offset = FIELD_OFFSET(PEB, ProcessParameters);
359 NtWriteVirtualMemory(ProcessHandle,
360 (PVOID)(PEB_BASE + Offset),
365 /* Read image base address. */
366 Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
367 NtReadVirtualMemory(ProcessHandle,
368 (PVOID)(PEB_BASE + Offset),
373 return(STATUS_SUCCESS);
378 RtlCreateUserProcess(PUNICODE_STRING ImageFileName,
380 PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
381 PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
382 PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
383 HANDLE ParentProcess,
384 BOOLEAN CurrentDirectory,
386 HANDLE ExceptionPort,
387 PRTL_PROCESS_INFO ProcessInfo)
391 LPTHREAD_START_ROUTINE lpStartAddress = NULL;
392 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
395 ANSI_STRING ProcedureName;
396 SECTION_IMAGE_INFORMATION Sii;
398 PVOID ImageBaseAddress;
400 DPRINT("RtlCreateUserProcess\n");
402 Status = RtlpMapFile(ProcessParameters,
406 if( !NT_SUCCESS( Status ) )
410 * Create a new process
412 if (ParentProcess == NULL)
413 ParentProcess = NtCurrentProcess();
415 Status = NtCreateProcess(&(ProcessInfo->ProcessHandle),
423 if (!NT_SUCCESS(Status))
430 * Get some information about the process
432 NtQueryInformationProcess(ProcessInfo->ProcessHandle,
433 ProcessBasicInformation,
435 sizeof(ProcessBasicInfo),
437 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
438 ProcessBasicInfo.UniqueProcessId);
439 ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
441 Status = NtSetInformationProcess(ProcessInfo->ProcessHandle,
442 ProcessImageFileName,
447 * Create Process Environment Block
449 DPRINT("Creating peb\n");
450 KlInitPeb(ProcessInfo->ProcessHandle,
454 Status = NtQuerySection(hSection,
455 SectionImageInformation,
459 if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
461 DPRINT("Failed to get section image information.\n");
466 DPRINT("Creating thread for process\n");
467 Status = RtlpCreateFirstThread(ProcessInfo->ProcessHandle,
470 ImageBaseAddress + (ULONG)Sii.EntryPoint,
471 &ProcessInfo->ClientId,
472 &ProcessInfo->ThreadHandle);
473 if (!NT_SUCCESS(Status))
475 DPRINT("Failed to create thread\n");
480 return(STATUS_SUCCESS);