Fixed header inclusion order.
[reactos.git] / reactos / lib / ntdll / rtl / process.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/ntdll/rtl/process.c
5 * PURPOSE: Process functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
7 * UPDATE HISTORY:
8 * Created 01/11/98
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #define WIN32_NO_PEHDR
14 #include <ddk/ntddk.h>
15 #include <wchar.h>
16 #include <string.h>
17 #include <pe.h>
18 #include <internal/i386/segment.h>
19 #include <ntdll/ldr.h>
20 #include <internal/teb.h>
21 #include <ntdll/base.h>
22
23 #define NDEBUG
24 #include <ntdll/ntdll.h>
25
26 /* FUNCTIONS ****************************************************************/
27
28
29 #define STACK_TOP (0xb0000000)
30
31 static HANDLE STDCALL
32 RtlpCreateFirstThread(HANDLE ProcessHandle,
33 PSECURITY_DESCRIPTOR SecurityDescriptor,
34 DWORD dwStackSize,
35 LPTHREAD_START_ROUTINE lpStartAddress,
36 LPVOID lpParameter,
37 DWORD dwCreationFlags,
38 LPDWORD lpThreadId,
39 PWSTR lpCommandLine,
40 HANDLE NTDllSectionHandle,
41 HANDLE SectionHandle,
42 PVOID ImageBase)
43 {
44 NTSTATUS Status;
45 HANDLE ThreadHandle;
46 OBJECT_ATTRIBUTES ObjectAttributes;
47 CLIENT_ID ClientId;
48 CONTEXT ThreadContext;
49 INITIAL_TEB InitialTeb;
50 BOOLEAN CreateSuspended = FALSE;
51 PVOID BaseAddress;
52 ULONG BytesWritten;
53 HANDLE DupNTDllSectionHandle, DupSectionHandle;
54
55 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
56 ObjectAttributes.RootDirectory = NULL;
57 ObjectAttributes.ObjectName = NULL;
58 ObjectAttributes.Attributes = 0;
59 // ObjectAttributes.Attributes = OBJ_INHERIT;
60 ObjectAttributes.SecurityDescriptor = SecurityDescriptor;
61 ObjectAttributes.SecurityQualityOfService = NULL;
62
63 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
64 CreateSuspended = TRUE;
65 else
66 CreateSuspended = FALSE;
67
68
69
70 BaseAddress = (PVOID)(STACK_TOP - dwStackSize);
71 Status = NtAllocateVirtualMemory(ProcessHandle,
72 &BaseAddress,
73 0,
74 (PULONG)&dwStackSize,
75 MEM_COMMIT,
76 PAGE_READWRITE);
77 if (!NT_SUCCESS(Status))
78 {
79 return(NULL);
80 }
81
82
83 memset(&ThreadContext,0,sizeof(CONTEXT));
84 ThreadContext.Eip = (ULONG)lpStartAddress;
85 ThreadContext.SegGs = USER_DS;
86 ThreadContext.SegFs = USER_DS;
87 ThreadContext.SegEs = USER_DS;
88 ThreadContext.SegDs = USER_DS;
89 ThreadContext.SegCs = USER_CS;
90 ThreadContext.SegSs = USER_DS;
91 ThreadContext.Esp = STACK_TOP - 16;
92 ThreadContext.EFlags = (1<<1) + (1<<9);
93
94 DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
95
96 NtDuplicateObject(NtCurrentProcess(),
97 &SectionHandle,
98 ProcessHandle,
99 &DupSectionHandle,
100 0,
101 FALSE,
102 DUPLICATE_SAME_ACCESS);
103 NtDuplicateObject(NtCurrentProcess(),
104 &NTDllSectionHandle,
105 ProcessHandle,
106 &DupNTDllSectionHandle,
107 0,
108 FALSE,
109 DUPLICATE_SAME_ACCESS);
110
111 NtWriteVirtualMemory(ProcessHandle,
112 (PVOID)(STACK_TOP - 4),
113 &DupNTDllSectionHandle,
114 sizeof(DupNTDllSectionHandle),
115 &BytesWritten);
116 NtWriteVirtualMemory(ProcessHandle,
117 (PVOID)(STACK_TOP - 8),
118 &ImageBase,
119 sizeof(ImageBase),
120 &BytesWritten);
121 NtWriteVirtualMemory(ProcessHandle,
122 (PVOID)(STACK_TOP - 12),
123 &DupSectionHandle,
124 sizeof(DupSectionHandle),
125 &BytesWritten);
126
127
128 Status = NtCreateThread(&ThreadHandle,
129 THREAD_ALL_ACCESS,
130 &ObjectAttributes,
131 ProcessHandle,
132 &ClientId,
133 &ThreadContext,
134 &InitialTeb,
135 CreateSuspended);
136 if ( lpThreadId != NULL )
137 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
138
139 return ThreadHandle;
140 }
141
142
143 static NTSTATUS
144 RtlpMapFile(PUNICODE_STRING ApplicationName,
145 PIMAGE_NT_HEADERS Headers,
146 PIMAGE_DOS_HEADER DosHeader,
147 PHANDLE Section)
148 {
149 HANDLE hFile;
150 IO_STATUS_BLOCK IoStatusBlock;
151 LARGE_INTEGER FileOffset;
152 OBJECT_ATTRIBUTES ObjectAttributes;
153 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
154 NTSTATUS Status;
155
156 hFile = NULL;
157 *Section = NULL;
158
159
160 DPRINT("ApplicationName %w\n", ApplicationName->Buffer);
161
162 InitializeObjectAttributes(&ObjectAttributes,
163 ApplicationName,
164 OBJ_CASE_INSENSITIVE,
165 NULL,
166 SecurityDescriptor);
167
168 /*
169 * Try to open the executable
170 */
171
172 Status = NtOpenFile(&hFile,
173 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
174 &ObjectAttributes,
175 &IoStatusBlock,
176 FILE_SHARE_DELETE|FILE_SHARE_READ,
177 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
178
179 if (!NT_SUCCESS(Status))
180 return Status;
181
182 Status = NtReadFile(hFile,
183 NULL,
184 NULL,
185 NULL,
186 &IoStatusBlock,
187 DosHeader,
188 sizeof(IMAGE_DOS_HEADER),
189 NULL,
190 NULL);
191 if (!NT_SUCCESS(Status))
192 return Status;
193
194 FileOffset.u.LowPart = DosHeader->e_lfanew;
195 FileOffset.u.HighPart = 0;
196
197 Status = NtReadFile(hFile,
198 NULL,
199 NULL,
200 NULL,
201 &IoStatusBlock,
202 Headers,
203 sizeof(IMAGE_NT_HEADERS),
204 &FileOffset,
205 NULL);
206 if (!NT_SUCCESS(Status))
207 return Status;
208
209 Status = NtCreateSection(Section,
210 SECTION_ALL_ACCESS,
211 NULL,
212 NULL,
213 PAGE_EXECUTE,
214 SEC_IMAGE,
215 hFile);
216 NtClose(hFile);
217
218 if (!NT_SUCCESS(Status))
219 return Status;
220
221 return STATUS_SUCCESS;
222 }
223
224
225 static NTSTATUS
226 RtlpCreatePeb(HANDLE ProcessHandle, PUNICODE_STRING CommandLine)
227 {
228 NTSTATUS Status;
229 PVOID PebBase;
230 ULONG PebSize;
231 NT_PEB Peb;
232 ULONG BytesWritten;
233 PVOID StartupInfoBase;
234 ULONG StartupInfoSize;
235 PROCESSINFOW StartupInfo;
236
237 PebBase = (PVOID)PEB_BASE;
238 PebSize = 0x1000;
239 Status = NtAllocateVirtualMemory(ProcessHandle,
240 &PebBase,
241 0,
242 &PebSize,
243 MEM_COMMIT,
244 PAGE_READWRITE);
245 if (!NT_SUCCESS(Status))
246 return(Status);
247
248 memset(&Peb, 0, sizeof(Peb));
249 Peb.StartupInfo = (PPROCESSINFOW)PEB_STARTUPINFO;
250
251 NtWriteVirtualMemory(ProcessHandle,
252 (PVOID)PEB_BASE,
253 &Peb,
254 sizeof(Peb),
255 &BytesWritten);
256
257 StartupInfoBase = (PVOID)PEB_STARTUPINFO;
258 StartupInfoSize = 0x1000;
259 Status = NtAllocateVirtualMemory(ProcessHandle,
260 &StartupInfoBase,
261 0,
262 &StartupInfoSize,
263 MEM_COMMIT,
264 PAGE_READWRITE);
265 if (!NT_SUCCESS(Status))
266 return(Status);
267
268 memset(&StartupInfo, 0, sizeof(StartupInfo));
269 wcscpy(StartupInfo.CommandLine, CommandLine->Buffer);
270
271 DPRINT("StartupInfoSize %x\n",StartupInfoSize);
272 NtWriteVirtualMemory(ProcessHandle,
273 (PVOID)PEB_STARTUPINFO,
274 &StartupInfo,
275 StartupInfoSize,
276 &BytesWritten);
277
278 return STATUS_SUCCESS;
279 }
280
281
282 NTSTATUS STDCALL
283 RtlCreateUserProcess(PUNICODE_STRING ApplicationName,
284 PSECURITY_DESCRIPTOR ProcessSd,
285 PSECURITY_DESCRIPTOR ThreadSd,
286 WINBOOL bInheritHandles,
287 DWORD dwCreationFlags,
288 // LPVOID lpEnvironment,
289 // LPCWSTR lpCurrentDirectory,
290 // LPSTARTUPINFO lpStartupInfo,
291 PCLIENT_ID ClientId,
292 PHANDLE ProcessHandle,
293 PHANDLE ThreadHandle)
294 {
295 HANDLE hSection, hProcess, hThread;
296 NTSTATUS Status;
297 LPTHREAD_START_ROUTINE lpStartAddress = NULL;
298 LPVOID lpParameter = NULL;
299 WCHAR TempCommandLine[256];
300 PVOID BaseAddress;
301 LARGE_INTEGER SectionOffset;
302 IMAGE_NT_HEADERS Headers;
303 IMAGE_DOS_HEADER DosHeader;
304 HANDLE NTDllSection;
305 ULONG InitialViewSize;
306 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
307 CLIENT_ID LocalClientId;
308 ULONG retlen;
309
310 DPRINT("RtlCreateUserProcess(ApplicationName '%w')\n",
311 ApplicationName->Buffer);
312
313 Status = RtlpMapFile(ApplicationName,
314 &Headers,
315 &DosHeader,
316 &hSection);
317
318 Status = NtCreateProcess(&hProcess,
319 PROCESS_ALL_ACCESS,
320 NULL,
321 NtCurrentProcess(),
322 bInheritHandles,
323 NULL,
324 NULL,
325 NULL);
326
327 NtQueryInformationProcess(hProcess,
328 ProcessBasicInformation,
329 &ProcessBasicInfo,
330 sizeof(ProcessBasicInfo),
331 &retlen);
332 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
333 ProcessBasicInfo.UniqueProcessId);
334 LocalClientId.UniqueProcess = ProcessBasicInfo.UniqueProcessId;
335
336 /*
337 * Map NT DLL into the process
338 */
339 Status = LdrMapNTDllForProcess(hProcess,
340 &NTDllSection);
341
342 InitialViewSize = DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)
343 + sizeof(IMAGE_SECTION_HEADER) * Headers.FileHeader.NumberOfSections;
344
345 BaseAddress = (PVOID)Headers.OptionalHeader.ImageBase;
346 SectionOffset.QuadPart = 0;
347 Status = NtMapViewOfSection(hSection,
348 hProcess,
349 &BaseAddress,
350 0,
351 InitialViewSize,
352 &SectionOffset,
353 &InitialViewSize,
354 0,
355 MEM_COMMIT,
356 PAGE_READWRITE);
357 if (!NT_SUCCESS(Status))
358 return Status;
359
360 /*
361 *
362 */
363 DPRINT("Creating peb\n");
364 RtlpCreatePeb(hProcess, ApplicationName);
365
366 DPRINT("Creating thread for process\n");
367 lpStartAddress = (LPTHREAD_START_ROUTINE)
368 ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(NTDLL_BASE))->
369 AddressOfEntryPoint +
370 ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(NTDLL_BASE))->ImageBase;
371 hThread = RtlpCreateFirstThread(hProcess,
372 ThreadSd,
373 Headers.OptionalHeader.SizeOfStackReserve,
374 lpStartAddress,
375 lpParameter,
376 dwCreationFlags,
377 &LocalClientId.UniqueThread,
378 TempCommandLine,
379 NTDllSection,
380 hSection,
381 (PVOID)Headers.OptionalHeader.ImageBase);
382
383 if ( hThread == NULL )
384 return Status;
385
386 if (ClientId)
387 {
388 ClientId->UniqueProcess = LocalClientId.UniqueProcess;
389 ClientId->UniqueThread = LocalClientId.UniqueThread;
390 }
391
392 if (ProcessHandle)
393 *ProcessHandle = hProcess;
394
395 if (ThreadHandle)
396 *ThreadHandle = hThread;
397
398 return STATUS_SUCCESS;
399 }
400