ec70933891b525b7870c86ca14729a00757b40b5
[reactos.git] / reactos / lib / rtl / process.c
1 /* $Id$
2 *
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)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include "rtl.h"
15
16 #define NDEBUG
17 #include <debug.h>
18
19 /* INTERNAL FUNCTIONS *******************************************************/
20
21 NTSTATUS
22 STDCALL
23 RtlpMapFile(PUNICODE_STRING ImageFileName,
24 ULONG Attributes,
25 PHANDLE Section)
26 {
27 OBJECT_ATTRIBUTES ObjectAttributes;
28 NTSTATUS Status;
29 HANDLE hFile = NULL;
30 IO_STATUS_BLOCK IoStatusBlock;
31
32 /* Open the Image File */
33 InitializeObjectAttributes(&ObjectAttributes,
34 ImageFileName,
35 Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
36 NULL,
37 NULL);
38 Status = ZwOpenFile(&hFile,
39 SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,
40 &ObjectAttributes,
41 &IoStatusBlock,
42 FILE_SHARE_DELETE | FILE_SHARE_READ,
43 FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
44 if (!NT_SUCCESS(Status))
45 {
46 DPRINT1("Failed to read image file from disk\n");
47 return(Status);
48 }
49
50 /* Now create a section for this image */
51 Status = ZwCreateSection(Section,
52 SECTION_ALL_ACCESS,
53 NULL,
54 NULL,
55 PAGE_EXECUTE,
56 SEC_IMAGE,
57 hFile);
58 if (!NT_SUCCESS(Status))
59 {
60 DPRINT1("Failed to create section for image file\n");
61 }
62
63 ZwClose(hFile);
64 return Status;
65 }
66
67 /* FUNCTIONS ****************************************************************/
68
69 NTSTATUS
70 STDCALL
71 RtlpInitEnvironment(HANDLE ProcessHandle,
72 PPEB Peb,
73 PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
74 {
75 NTSTATUS Status;
76 PVOID BaseAddress = NULL;
77 ULONG EnviroSize;
78 ULONG Size;
79 PWCHAR Environment = 0;
80
81 DPRINT("RtlpInitEnvironment (hProcess: %lx, Peb: %p Params: %p)\n",
82 ProcessHandle, Peb, ProcessParameters);
83
84 /* Give the caller 1MB if he requested it */
85 if (ProcessParameters->Flags & PPF_RESERVE_1MB)
86 {
87 /* Give 1MB starting at 0x4 */
88 BaseAddress = (PVOID)4;
89 EnviroSize = 1024 * 1024;
90 Status = ZwAllocateVirtualMemory(ProcessHandle,
91 &BaseAddress,
92 0,
93 &EnviroSize,
94 MEM_RESERVE,
95 PAGE_READWRITE);
96 if (!NT_SUCCESS(Status))
97 {
98 DPRINT1("Failed to reserve 1MB of space \n");
99 return(Status);
100 }
101 }
102
103 /* Find the end of the Enviroment Block */
104 if ((Environment = (PWCHAR)ProcessParameters->Environment))
105 {
106 while (*Environment++) while (*Environment++);
107
108 /* Calculate the size of the block */
109 EnviroSize = (ULONG)((ULONG_PTR)Environment -
110 (ULONG_PTR)ProcessParameters->Environment);
111 DPRINT("EnvironmentSize %ld\n", EnviroSize);
112
113 /* Allocate and Initialize new Environment Block */
114 Size = EnviroSize;
115 Status = ZwAllocateVirtualMemory(ProcessHandle,
116 &BaseAddress,
117 0,
118 &Size,
119 MEM_RESERVE | MEM_COMMIT,
120 PAGE_READWRITE);
121 if (!NT_SUCCESS(Status))
122 {
123 DPRINT1("Failed to allocate Environment Block\n");
124 return(Status);
125 }
126
127 /* Write the Environment Block */
128 ZwWriteVirtualMemory(ProcessHandle,
129 BaseAddress,
130 ProcessParameters->Environment,
131 EnviroSize,
132 NULL);
133
134 /* Save pointer */
135 ProcessParameters->Environment = BaseAddress;
136 }
137
138 DPRINT("EnvironmentPointer %p\n", BaseAddress);
139 DPRINT("Ppb->MaximumLength %x\n", ProcessParameters->MaximumLength);
140
141 /* Now allocate space for the Parameter Block */
142 BaseAddress = NULL;
143 Size = ProcessParameters->MaximumLength;
144 Status = ZwAllocateVirtualMemory(ProcessHandle,
145 &BaseAddress,
146 0,
147 &Size,
148 MEM_COMMIT,
149 PAGE_READWRITE);
150 if (!NT_SUCCESS(Status))
151 {
152 DPRINT1("Failed to allocate Parameter Block\n");
153 return(Status);
154 }
155
156 /* Write the Parameter Block */
157 ZwWriteVirtualMemory(ProcessHandle,
158 BaseAddress,
159 ProcessParameters,
160 ProcessParameters->Length,
161 NULL);
162
163 /* Write pointer to Parameter Block */
164 ZwWriteVirtualMemory(ProcessHandle,
165 &Peb->ProcessParameters,
166 &BaseAddress,
167 sizeof(BaseAddress),
168 NULL);
169
170 /* Return */
171 return STATUS_SUCCESS;
172 }
173
174 /*
175 * @implemented
176 *
177 * Creates a process and its initial thread.
178 *
179 * NOTES:
180 * - The first thread is created suspended, so it needs a manual resume!!!
181 * - If ParentProcess is NULL, current process is used
182 * - ProcessParameters must be normalized
183 * - Attributes are object attribute flags used when opening the ImageFileName.
184 * Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
185 *
186 * -Gunnar
187 */
188 NTSTATUS
189 STDCALL
190 RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName,
191 IN ULONG Attributes,
192 IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
193 IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
194 IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
195 IN HANDLE ParentProcess OPTIONAL,
196 IN BOOLEAN InheritHandles,
197 IN HANDLE DebugPort OPTIONAL,
198 IN HANDLE ExceptionPort OPTIONAL,
199 OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo)
200 {
201 NTSTATUS Status;
202 HANDLE hSection;
203 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
204 OBJECT_ATTRIBUTES ObjectAttributes;
205
206 DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
207
208 /* Map and Load the File */
209 Status = RtlpMapFile(ImageFileName,
210 Attributes,
211 &hSection);
212 if(!NT_SUCCESS(Status))
213 {
214 DPRINT1("Could not map process image\n");
215 return Status;
216 }
217
218 /* Clean out the CurDir Handle if we won't use it */
219 if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
220
221 /* Use us as parent if none other specified */
222 if (!ParentProcess) ParentProcess = NtCurrentProcess();
223
224 /* Initialize the Object Attributes */
225 InitializeObjectAttributes(&ObjectAttributes,
226 NULL,
227 0,
228 NULL,
229 ProcessSecurityDescriptor);
230
231 /*
232 * If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
233 * watch of WindowsSS
234 */
235 if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) &&
236 (wcsstr(ImageFileName->Buffer, L"csrss")))
237 {
238 UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS");
239 InitializeObjectAttributes(&ObjectAttributes,
240 &DebugString,
241 0,
242 NULL,
243 ProcessSecurityDescriptor);
244 }
245
246
247 /* Create Kernel Process Object */
248 Status = ZwCreateProcess(&ProcessInfo->ProcessHandle,
249 PROCESS_ALL_ACCESS,
250 &ObjectAttributes,
251 ParentProcess,
252 InheritHandles,
253 hSection,
254 DebugPort,
255 ExceptionPort);
256 if (!NT_SUCCESS(Status))
257 {
258 DPRINT1("Could not create Kernel Process Object\n");
259 ZwClose(hSection);
260 return(Status);
261 }
262
263 /* Get some information on the image */
264 Status = ZwQuerySection(hSection,
265 SectionImageInformation,
266 &ProcessInfo->ImageInformation,
267 sizeof(SECTION_IMAGE_INFORMATION),
268 NULL);
269 if (!NT_SUCCESS(Status))
270 {
271 DPRINT1("Could not query Section Info\n");
272 ZwClose(ProcessInfo->ProcessHandle);
273 ZwClose(hSection);
274 return(Status);
275 }
276
277 /* Get some information about the process */
278 ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
279 ProcessBasicInformation,
280 &ProcessBasicInfo,
281 sizeof(ProcessBasicInfo),
282 NULL);
283 if (!NT_SUCCESS(Status))
284 {
285 DPRINT1("Could not query Process Info\n");
286 ZwClose(ProcessInfo->ProcessHandle);
287 ZwClose(hSection);
288 return(Status);
289 }
290
291 /* Create Process Environment */
292 RtlpInitEnvironment(ProcessInfo->ProcessHandle,
293 ProcessBasicInfo.PebBaseAddress,
294 ProcessParameters);
295
296 /* Create the first Thread */
297 Status = RtlCreateUserThread(ProcessInfo->ProcessHandle,
298 ThreadSecurityDescriptor,
299 TRUE,
300 ProcessInfo->ImageInformation.ZeroBits,
301 ProcessInfo->ImageInformation.MaximumStackSize,
302 ProcessInfo->ImageInformation.CommittedStackSize,
303 ProcessInfo->ImageInformation.TransferAddress,
304 ProcessBasicInfo.PebBaseAddress,
305 &ProcessInfo->ThreadHandle,
306 &ProcessInfo->ClientId);
307 if (!NT_SUCCESS(Status))
308 {
309 DPRINT1("Could not Create Thread\n");
310 ZwClose(ProcessInfo->ProcessHandle);
311 ZwClose(hSection); /* Don't try to optimize this on top! */
312 return Status;
313 }
314
315 /* Close the Section Handle and return */
316 ZwClose(hSection);
317 return STATUS_SUCCESS;
318 }
319
320 /* EOF */