- Implement remaining functions in rtl/i386/math_asm.S
[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 ULONG EnviroSize;
76 ULONG Size;
77 PWCHAR Environment = 0;
78
79 DPRINT("RtlpInitEnvironment (hProcess: %lx, Peb: %p Params: %p)\n",
80 ProcessHandle, Peb, ProcessParameters);
81
82 /* Give the caller 1MB if he requested it */
83 if (ProcessParameters->Flags & RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB)
84 {
85 /* Give 1MB starting at 0x4 */
86 BaseAddress = (PVOID)4;
87 EnviroSize = 1024 * 1024;
88 Status = ZwAllocateVirtualMemory(ProcessHandle,
89 &BaseAddress,
90 0,
91 &EnviroSize,
92 MEM_RESERVE,
93 PAGE_READWRITE);
94 if (!NT_SUCCESS(Status))
95 {
96 DPRINT1("Failed to reserve 1MB of space \n");
97 return(Status);
98 }
99 }
100
101 /* Find the end of the Enviroment Block */
102 if ((Environment = (PWCHAR)ProcessParameters->Environment))
103 {
104 while (*Environment++) while (*Environment++);
105
106 /* Calculate the size of the block */
107 EnviroSize = (ULONG)((ULONG_PTR)Environment -
108 (ULONG_PTR)ProcessParameters->Environment);
109 DPRINT("EnvironmentSize %ld\n", EnviroSize);
110
111 /* Allocate and Initialize new Environment Block */
112 Size = EnviroSize;
113 Status = ZwAllocateVirtualMemory(ProcessHandle,
114 &BaseAddress,
115 0,
116 &Size,
117 MEM_RESERVE | MEM_COMMIT,
118 PAGE_READWRITE);
119 if (!NT_SUCCESS(Status))
120 {
121 DPRINT1("Failed to allocate Environment Block\n");
122 return(Status);
123 }
124
125 /* Write the Environment Block */
126 ZwWriteVirtualMemory(ProcessHandle,
127 BaseAddress,
128 ProcessParameters->Environment,
129 EnviroSize,
130 NULL);
131
132 /* Save pointer */
133 ProcessParameters->Environment = BaseAddress;
134 }
135
136 DPRINT("EnvironmentPointer %p\n", BaseAddress);
137 DPRINT("Ppb->MaximumLength %x\n", ProcessParameters->MaximumLength);
138
139 /* Now allocate space for the Parameter Block */
140 BaseAddress = NULL;
141 Size = ProcessParameters->MaximumLength;
142 Status = ZwAllocateVirtualMemory(ProcessHandle,
143 &BaseAddress,
144 0,
145 &Size,
146 MEM_COMMIT,
147 PAGE_READWRITE);
148 if (!NT_SUCCESS(Status))
149 {
150 DPRINT1("Failed to allocate Parameter Block\n");
151 return(Status);
152 }
153
154 /* Write the Parameter Block */
155 ZwWriteVirtualMemory(ProcessHandle,
156 BaseAddress,
157 ProcessParameters,
158 ProcessParameters->Length,
159 NULL);
160
161 /* Write pointer to Parameter Block */
162 ZwWriteVirtualMemory(ProcessHandle,
163 &Peb->ProcessParameters,
164 &BaseAddress,
165 sizeof(BaseAddress),
166 NULL);
167
168 /* Return */
169 return STATUS_SUCCESS;
170 }
171
172 /*
173 * @implemented
174 *
175 * Creates a process and its initial thread.
176 *
177 * NOTES:
178 * - The first thread is created suspended, so it needs a manual resume!!!
179 * - If ParentProcess is NULL, current process is used
180 * - ProcessParameters must be normalized
181 * - Attributes are object attribute flags used when opening the ImageFileName.
182 * Valid flags are OBJ_INHERIT and OBJ_CASE_INSENSITIVE.
183 *
184 * -Gunnar
185 */
186 NTSTATUS
187 NTAPI
188 RtlCreateUserProcess(IN PUNICODE_STRING ImageFileName,
189 IN ULONG Attributes,
190 IN OUT PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
191 IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL,
192 IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
193 IN HANDLE ParentProcess OPTIONAL,
194 IN BOOLEAN InheritHandles,
195 IN HANDLE DebugPort OPTIONAL,
196 IN HANDLE ExceptionPort OPTIONAL,
197 OUT PRTL_USER_PROCESS_INFORMATION ProcessInfo)
198 {
199 NTSTATUS Status;
200 HANDLE hSection;
201 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
202 OBJECT_ATTRIBUTES ObjectAttributes;
203
204 DPRINT("RtlCreateUserProcess: %wZ\n", ImageFileName);
205
206 /* Map and Load the File */
207 Status = RtlpMapFile(ImageFileName,
208 Attributes,
209 &hSection);
210 if(!NT_SUCCESS(Status))
211 {
212 DPRINT1("Could not map process image\n");
213 return Status;
214 }
215
216 /* Clean out the CurDir Handle if we won't use it */
217 if (!InheritHandles) ProcessParameters->CurrentDirectory.Handle = NULL;
218
219 /* Use us as parent if none other specified */
220 if (!ParentProcess) ParentProcess = NtCurrentProcess();
221
222 /* Initialize the Object Attributes */
223 InitializeObjectAttributes(&ObjectAttributes,
224 NULL,
225 0,
226 NULL,
227 ProcessSecurityDescriptor);
228
229 /*
230 * If FLG_ENABLE_CSRDEBUG is used, then CSRSS is created under the
231 * watch of WindowsSS
232 */
233 if ((RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG) &&
234 (wcsstr(ImageFileName->Buffer, L"csrss")))
235 {
236 UNICODE_STRING DebugString = RTL_CONSTANT_STRING(L"\\WindowsSS");
237 InitializeObjectAttributes(&ObjectAttributes,
238 &DebugString,
239 0,
240 NULL,
241 ProcessSecurityDescriptor);
242 }
243
244
245 /* Create Kernel Process Object */
246 Status = ZwCreateProcess(&ProcessInfo->ProcessHandle,
247 PROCESS_ALL_ACCESS,
248 &ObjectAttributes,
249 ParentProcess,
250 InheritHandles,
251 hSection,
252 DebugPort,
253 ExceptionPort);
254 if (!NT_SUCCESS(Status))
255 {
256 DPRINT1("Could not create Kernel Process Object\n");
257 ZwClose(hSection);
258 return(Status);
259 }
260
261 /* Get some information on the image */
262 Status = ZwQuerySection(hSection,
263 SectionImageInformation,
264 &ProcessInfo->ImageInformation,
265 sizeof(SECTION_IMAGE_INFORMATION),
266 NULL);
267 if (!NT_SUCCESS(Status))
268 {
269 DPRINT1("Could not query Section Info\n");
270 ZwClose(ProcessInfo->ProcessHandle);
271 ZwClose(hSection);
272 return(Status);
273 }
274
275 /* Get some information about the process */
276 ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
277 ProcessBasicInformation,
278 &ProcessBasicInfo,
279 sizeof(ProcessBasicInfo),
280 NULL);
281 if (!NT_SUCCESS(Status))
282 {
283 DPRINT1("Could not query Process Info\n");
284 ZwClose(ProcessInfo->ProcessHandle);
285 ZwClose(hSection);
286 return(Status);
287 }
288
289 /* Create Process Environment */
290 RtlpInitEnvironment(ProcessInfo->ProcessHandle,
291 ProcessBasicInfo.PebBaseAddress,
292 ProcessParameters);
293
294 /* Create the first Thread */
295 Status = RtlCreateUserThread(ProcessInfo->ProcessHandle,
296 ThreadSecurityDescriptor,
297 TRUE,
298 ProcessInfo->ImageInformation.ZeroBits,
299 ProcessInfo->ImageInformation.MaximumStackSize,
300 ProcessInfo->ImageInformation.CommittedStackSize,
301 ProcessInfo->ImageInformation.TransferAddress,
302 ProcessBasicInfo.PebBaseAddress,
303 &ProcessInfo->ThreadHandle,
304 &ProcessInfo->ClientId);
305 if (!NT_SUCCESS(Status))
306 {
307 DPRINT1("Could not Create Thread\n");
308 ZwClose(ProcessInfo->ProcessHandle);
309 ZwClose(hSection); /* Don't try to optimize this on top! */
310 return Status;
311 }
312
313 /* Close the Section Handle and return */
314 ZwClose(hSection);
315 return STATUS_SUCCESS;
316 }
317
318 /*
319 * @implemented
320 */
321 PVOID
322 NTAPI
323 RtlEncodePointer(IN PVOID Pointer)
324 {
325 ULONG Cookie;
326 NTSTATUS Status;
327
328 Status = ZwQueryInformationProcess(NtCurrentProcess(),
329 ProcessCookie,
330 &Cookie,
331 sizeof(Cookie),
332 NULL);
333
334 if(!NT_SUCCESS(Status))
335 {
336 DPRINT1("Failed to receive the process cookie! Status: 0x%x\n", Status);
337 return Pointer;
338 }
339
340 return (PVOID)((ULONG_PTR)Pointer ^ Cookie);
341 }
342
343 /*
344 * @unimplemented
345 */
346 NTSYSAPI
347 VOID
348 NTAPI
349 RtlSetProcessIsCritical(
350 IN BOOLEAN NewValue,
351 OUT PBOOLEAN OldValue OPTIONAL,
352 IN BOOLEAN IsWinlogon)
353 {
354 //TODO
355 }
356
357 /* EOF */