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