2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/process.c
5 * PURPOSE: Process functions
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
7 * Ariadne (ariadne@xs4all.nl)
11 /* INCLUDES ****************************************************************/
18 /* INTERNAL FUNCTIONS *******************************************************/
22 RtlpMapFile(PUNICODE_STRING ImageFileName
,
26 OBJECT_ATTRIBUTES ObjectAttributes
;
29 IO_STATUS_BLOCK IoStatusBlock
;
31 /* Open the Image File */
32 InitializeObjectAttributes(&ObjectAttributes
,
34 Attributes
& (OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
),
37 Status
= ZwOpenFile(&hFile
,
38 SYNCHRONIZE
| FILE_EXECUTE
| FILE_READ_DATA
,
41 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
42 FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
43 if (!NT_SUCCESS(Status
))
45 DPRINT1("Failed to read image file from disk, Status = 0x%08X\n", Status
);
49 /* Now create a section for this image */
50 Status
= ZwCreateSection(Section
,
57 if (!NT_SUCCESS(Status
))
59 DPRINT1("Failed to create section for image file, Status = 0x%08X\n", Status
);
66 /* FUNCTIONS ****************************************************************/
70 RtlpInitEnvironment(HANDLE ProcessHandle
,
72 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
)
75 PVOID BaseAddress
= NULL
;
78 PWCHAR Environment
= NULL
;
79 DPRINT("RtlpInitEnvironment(ProcessHandle: %p, Peb: %p Params: %p)\n",
80 ProcessHandle
, Peb
, ProcessParameters
);
82 /* Give the caller 1MB if he requested it */
83 if (ProcessParameters
->Flags
& RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
)
85 /* Give 1MB starting at 0x4 */
86 BaseAddress
= (PVOID
)4;
87 EnviroSize
= (1024 * 1024) - 256;
88 Status
= ZwAllocateVirtualMemory(ProcessHandle
,
94 if (!NT_SUCCESS(Status
))
96 DPRINT1("Failed to reserve 1MB of space \n");
101 /* Find the end of the Enviroment Block */
102 if ((Environment
= (PWCHAR
)ProcessParameters
->Environment
))
104 while (*Environment
++) while (*Environment
++);
106 /* Calculate the size of the block */
107 EnviroSize
= (ULONG
)((ULONG_PTR
)Environment
-
108 (ULONG_PTR
)ProcessParameters
->Environment
);
110 /* Allocate and Initialize new Environment Block */
112 Status
= ZwAllocateVirtualMemory(ProcessHandle
,
116 MEM_RESERVE
| MEM_COMMIT
,
118 if (!NT_SUCCESS(Status
))
120 DPRINT1("Failed to allocate Environment Block\n");
124 /* Write the Environment Block */
125 ZwWriteVirtualMemory(ProcessHandle
,
127 ProcessParameters
->Environment
,
132 ProcessParameters
->Environment
= BaseAddress
;
135 /* Now allocate space for the Parameter Block */
137 Size
= ProcessParameters
->MaximumLength
;
138 Status
= ZwAllocateVirtualMemory(ProcessHandle
,
144 if (!NT_SUCCESS(Status
))
146 DPRINT1("Failed to allocate Parameter Block\n");
150 /* Write the Parameter Block */
151 Status
= ZwWriteVirtualMemory(ProcessHandle
,
154 ProcessParameters
->Length
,
156 if (!NT_SUCCESS(Status
))
158 DPRINT1("Failed to write the Parameter Block\n");
162 /* Write pointer to Parameter Block */
163 Status
= ZwWriteVirtualMemory(ProcessHandle
,
164 &Peb
->ProcessParameters
,
168 if (!NT_SUCCESS(Status
))
170 DPRINT1("Failed to write pointer to Parameter Block\n");
175 return STATUS_SUCCESS
;
181 * Creates a process and its initial thread.
184 * - The first thread is created suspended, so it needs a manual resume!!!
185 * - If ParentProcess is NULL, current process is used
186 * - ProcessParameters must be normalized
187 * - Attributes are object attribute flags used when opening the ImageFileName.
188 * Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
194 RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName
,
196 IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters
,
197 IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL
,
198 IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL
,
199 IN HANDLE ParentProcess OPTIONAL
,
200 IN BOOLEAN InheritHandles
,
201 IN HANDLE DebugPort OPTIONAL
,
202 IN HANDLE ExceptionPort OPTIONAL
,
203 OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo
)
207 PROCESS_BASIC_INFORMATION ProcessBasicInfo
;
208 OBJECT_ATTRIBUTES ObjectAttributes
;
209 UNICODE_STRING DebugString
= RTL_CONSTANT_STRING(L
"\\WindowsSS");
210 DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName
);
212 /* Map and Load the File */
213 Status
= RtlpMapFile(ImageFileName
,
216 if (!NT_SUCCESS(Status
))
218 DPRINT1("Could not map process image\n");
222 /* Clean out the current directory handle if we won't use it */
223 if (!InheritHandles
) ProcessParameters
->CurrentDirectory
.Handle
= NULL
;
225 /* Use us as parent if none other specified */
226 if (!ParentProcess
) ParentProcess
= NtCurrentProcess();
228 /* Initialize the Object Attributes */
229 InitializeObjectAttributes(&ObjectAttributes
,
233 ProcessSecurityDescriptor
);
236 * If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
239 if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG
) &&
240 (wcsstr(ImageFileName
->Buffer
, L
"csrss")))
242 ObjectAttributes
.ObjectName
= &DebugString
;
245 /* Create Kernel Process Object */
246 Status
= ZwCreateProcess(&ProcessInfo
->ProcessHandle
,
254 if (!NT_SUCCESS(Status
))
256 DPRINT1("Could not create Kernel Process Object\n");
261 /* Get some information on the image */
262 Status
= ZwQuerySection(hSection
,
263 SectionImageInformation
,
264 &ProcessInfo
->ImageInformation
,
265 sizeof(SECTION_IMAGE_INFORMATION
),
267 if (!NT_SUCCESS(Status
))
269 DPRINT1("Could not query Section Info\n");
270 ZwClose(ProcessInfo
->ProcessHandle
);
275 /* Get some information about the process */
276 Status
= ZwQueryInformationProcess(ProcessInfo
->ProcessHandle
,
277 ProcessBasicInformation
,
279 sizeof(ProcessBasicInfo
),
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("Could not query Process Info\n");
284 ZwClose(ProcessInfo
->ProcessHandle
);
289 /* Duplicate the standard handles */
290 Status
= STATUS_SUCCESS
;
293 if (ProcessParameters
->StandardInput
)
295 Status
= ZwDuplicateObject(ParentProcess
,
296 ProcessParameters
->StandardInput
,
297 ProcessInfo
->ProcessHandle
,
298 &ProcessParameters
->StandardInput
,
301 DUPLICATE_SAME_ACCESS
|
302 DUPLICATE_SAME_ATTRIBUTES
);
303 if (!NT_SUCCESS(Status
))
309 if (ProcessParameters
->StandardOutput
)
311 Status
= ZwDuplicateObject(ParentProcess
,
312 ProcessParameters
->StandardOutput
,
313 ProcessInfo
->ProcessHandle
,
314 &ProcessParameters
->StandardOutput
,
317 DUPLICATE_SAME_ACCESS
|
318 DUPLICATE_SAME_ATTRIBUTES
);
319 if (!NT_SUCCESS(Status
))
325 if (ProcessParameters
->StandardError
)
327 Status
= ZwDuplicateObject(ParentProcess
,
328 ProcessParameters
->StandardError
,
329 ProcessInfo
->ProcessHandle
,
330 &ProcessParameters
->StandardError
,
333 DUPLICATE_SAME_ACCESS
|
334 DUPLICATE_SAME_ATTRIBUTES
);
335 if (!NT_SUCCESS(Status
))
343 if (!NT_SUCCESS(Status
))
345 ZwClose(ProcessInfo
->ProcessHandle
);
351 if (!NT_SUCCESS(Status
))
354 /* Create Process Environment */
355 Status
= RtlpInitEnvironment(ProcessInfo
->ProcessHandle
,
356 ProcessBasicInfo
.PebBaseAddress
,
358 if (!NT_SUCCESS(Status
))
360 DPRINT1("Could not Create Process Environment\n");
361 ZwClose(ProcessInfo
->ProcessHandle
);
366 /* Create the first Thread */
367 Status
= RtlCreateUserThread(ProcessInfo
->ProcessHandle
,
368 ThreadSecurityDescriptor
,
370 ProcessInfo
->ImageInformation
.ZeroBits
,
371 ProcessInfo
->ImageInformation
.MaximumStackSize
,
372 ProcessInfo
->ImageInformation
.CommittedStackSize
,
373 ProcessInfo
->ImageInformation
.TransferAddress
,
374 ProcessBasicInfo
.PebBaseAddress
,
375 &ProcessInfo
->ThreadHandle
,
376 &ProcessInfo
->ClientId
);
377 if (!NT_SUCCESS(Status
))
379 DPRINT1("Could not Create Thread\n");
380 ZwClose(ProcessInfo
->ProcessHandle
);
381 ZwClose(hSection
); /* Don't try to optimize this on top! */
385 /* Close the Section Handle and return */
387 return STATUS_SUCCESS
;
395 RtlEncodePointer(IN PVOID Pointer
)
400 Status
= ZwQueryInformationProcess(NtCurrentProcess(),
405 if(!NT_SUCCESS(Status
))
407 DPRINT1("Failed to receive the process cookie! Status: 0x%lx\n", Status
);
411 return (PVOID
)((ULONG_PTR
)Pointer
^ Cookie
);
419 RtlDecodePointer(IN PVOID Pointer
)
421 return RtlEncodePointer(Pointer
);
429 RtlEncodeSystemPointer(IN PVOID Pointer
)
431 return (PVOID
)((ULONG_PTR
)Pointer
^ SharedUserData
->Cookie
);
439 RtlDecodeSystemPointer(IN PVOID Pointer
)
441 return RtlEncodeSystemPointer(Pointer
);
448 * Implementation based on the documentation from:
449 * http://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/peb/setprocessiscritical.htm
453 RtlSetProcessIsCritical(IN BOOLEAN NewValue
,
454 OUT PBOOLEAN OldValue OPTIONAL
,
455 IN BOOLEAN NeedBreaks
)
457 ULONG BreakOnTermination
;
459 /* Initialize to FALSE */
460 if (OldValue
) *OldValue
= FALSE
;
462 /* Fail, if the critical breaks flag is required but is not set */
464 !(NtCurrentPeb()->NtGlobalFlag
& FLG_ENABLE_SYSTEM_CRIT_BREAKS
))
466 return STATUS_UNSUCCESSFUL
;
469 /* Check if the caller wants the old value */
472 /* Query and return the old break on termination flag for the process */
473 ZwQueryInformationProcess(NtCurrentProcess(),
474 ProcessBreakOnTermination
,
478 *OldValue
= (BOOLEAN
)BreakOnTermination
;
481 /* Set the break on termination flag for the process */
482 BreakOnTermination
= NewValue
;
483 return ZwSetInformationProcess(NtCurrentProcess(),
484 ProcessBreakOnTermination
,
491 RtlGetCurrentProcessorNumber(VOID
)
493 /* Forward to kernel */
494 return NtGetCurrentProcessorNumber();