Updated the minix driver
[reactos.git] / reactos / lib / ntdll / rtl / process.c
1 /* $Id: process.c,v 1.18 2000/03/22 18:35:51 dwelch Exp $
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 <ddk/ntddk.h>
15 #include <internal/i386/segment.h>
16 #include <ntdll/ldr.h>
17 #include <internal/teb.h>
18 #include <ntdll/base.h>
19 #include <ntdll/rtl.h>
20
21 #define NDEBUG
22 #include <ntdll/ntdll.h>
23
24 /* FUNCTIONS ****************************************************************/
25
26 #define STACK_TOP (0xb0000000)
27
28 HANDLE STDCALL KlCreateFirstThread(HANDLE ProcessHandle,
29 DWORD dwStackSize,
30 LPTHREAD_START_ROUTINE lpStartAddress,
31 DWORD dwCreationFlags,
32 PCLIENT_ID ClientId)
33 {
34 NTSTATUS Status;
35 HANDLE ThreadHandle;
36 OBJECT_ATTRIBUTES ObjectAttributes;
37 CONTEXT ThreadContext;
38 INITIAL_TEB InitialTeb;
39 BOOLEAN CreateSuspended = FALSE;
40 PVOID BaseAddress;
41 CLIENT_ID Cid;
42
43 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
44 ObjectAttributes.RootDirectory = NULL;
45 ObjectAttributes.ObjectName = NULL;
46 ObjectAttributes.Attributes = 0;
47 ObjectAttributes.SecurityQualityOfService = NULL;
48
49 if (dwCreationFlags & CREATE_SUSPENDED)
50 CreateSuspended = TRUE;
51 else
52 CreateSuspended = FALSE;
53
54
55 BaseAddress = (PVOID)(STACK_TOP - dwStackSize);
56 Status = NtAllocateVirtualMemory(ProcessHandle,
57 &BaseAddress,
58 0,
59 (PULONG)&dwStackSize,
60 MEM_COMMIT,
61 PAGE_READWRITE);
62 if (!NT_SUCCESS(Status))
63 {
64 DPRINT("Failed to allocate stack\n");
65 return(NULL);
66 }
67
68 memset(&ThreadContext,0,sizeof(CONTEXT));
69 ThreadContext.Eip = (ULONG)lpStartAddress;
70 ThreadContext.SegGs = USER_DS;
71 ThreadContext.SegFs = USER_DS;
72 ThreadContext.SegEs = USER_DS;
73 ThreadContext.SegDs = USER_DS;
74 ThreadContext.SegCs = USER_CS;
75 ThreadContext.SegSs = USER_DS;
76 ThreadContext.Esp = STACK_TOP - 20;
77 ThreadContext.EFlags = (1<<1) + (1<<9);
78
79 DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
80
81 Status = NtCreateThread(&ThreadHandle,
82 THREAD_ALL_ACCESS,
83 &ObjectAttributes,
84 ProcessHandle,
85 &Cid,
86 &ThreadContext,
87 &InitialTeb,
88 CreateSuspended);
89 if (ClientId != NULL)
90 {
91 memcpy(&ClientId->UniqueThread, &Cid.UniqueThread, sizeof(ULONG));
92 }
93
94 return(ThreadHandle);
95 }
96
97 static NTSTATUS RtlpMapFile(
98 PRTL_USER_PROCESS_PARAMETERS Ppb,
99 //PUNICODE_STRING ApplicationName,
100 PHANDLE Section,
101 PCHAR ImageFileName)
102 {
103 HANDLE hFile;
104 IO_STATUS_BLOCK IoStatusBlock;
105 OBJECT_ATTRIBUTES ObjectAttributes;
106 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
107 NTSTATUS Status;
108 PWCHAR s;
109 PWCHAR e;
110 ULONG i;
111
112 hFile = NULL;
113
114 RtlDeNormalizeProcessParams (Ppb);
115
116 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
117
118 InitializeObjectAttributes(&ObjectAttributes,
119 // ApplicationName,
120 &(Ppb->ImagePathName),
121 OBJ_CASE_INSENSITIVE,
122 NULL,
123 SecurityDescriptor);
124
125 RtlNormalizeProcessParams (Ppb);
126
127 /*
128 *
129 */
130 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
131 // DbgPrint("ImagePathName %S\n", Ppb->ImagePathName.Buffer);
132 s = wcsrchr(Ppb->ImagePathName.Buffer, '\\');
133 if (s == NULL)
134 {
135 s = Ppb->ImagePathName.Buffer;
136 }
137 else
138 {
139 s++;
140 }
141 e = wcschr(s, '.');
142 if (e != NULL)
143 {
144 *e = 0;
145 }
146 for (i = 0; i < 8; i++)
147 {
148 ImageFileName[i] = (CHAR)(s[i]);
149 }
150 if (e != NULL)
151 {
152 *e = '.';
153 }
154
155 /*
156 * Try to open the executable
157 */
158
159 Status = NtOpenFile(&hFile,
160 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
161 &ObjectAttributes,
162 &IoStatusBlock,
163 FILE_SHARE_DELETE|FILE_SHARE_READ,
164 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
165
166 if (!NT_SUCCESS(Status))
167 {
168 return(Status);
169 }
170
171 Status = NtCreateSection(Section,
172 SECTION_ALL_ACCESS,
173 NULL,
174 NULL,
175 PAGE_EXECUTE,
176 SEC_IMAGE,
177 hFile);
178 NtClose(hFile);
179
180 if (!NT_SUCCESS(Status))
181 {
182 return(Status);
183 }
184
185 return(STATUS_SUCCESS);
186 }
187
188 static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
189 PRTL_USER_PROCESS_PARAMETERS Ppb)
190 {
191 NTSTATUS Status;
192 PVOID PpbBase;
193 ULONG PpbSize;
194 ULONG BytesWritten;
195 ULONG Offset;
196 PVOID EnvPtr = NULL;
197 ULONG EnvSize = 0;
198
199
200 /* create the Environment */
201 if (Ppb->Environment != NULL)
202 {
203 MEMORY_BASIC_INFORMATION MemInfo;
204
205 Status = NtQueryVirtualMemory (NtCurrentProcess (),
206 Ppb->Environment,
207 MemoryBasicInformation,
208 &MemInfo,
209 sizeof(MEMORY_BASIC_INFORMATION),
210 NULL);
211 if (!NT_SUCCESS(Status))
212 {
213 return Status;
214 }
215 EnvSize = MemInfo.RegionSize;
216 }
217 DPRINT("EnvironmentSize %ld\n", EnvSize);
218
219 /* allocate and initialize new environment block */
220 if (EnvSize != 0)
221 {
222 Status = NtAllocateVirtualMemory(ProcessHandle,
223 &EnvPtr,
224 0,
225 &EnvSize,
226 MEM_COMMIT,
227 PAGE_READWRITE);
228 if (!NT_SUCCESS(Status))
229 {
230 return(Status);
231 }
232
233 NtWriteVirtualMemory(ProcessHandle,
234 EnvPtr,
235 Ppb->Environment,
236 EnvSize,
237 &BytesWritten);
238 }
239 DPRINT("EnvironmentPointer %p\n", EnvPtr);
240
241 /* create the PPB */
242 PpbBase = (PVOID)PEB_STARTUPINFO;
243 PpbSize = Ppb->MaximumLength;
244 Status = NtAllocateVirtualMemory(ProcessHandle,
245 &PpbBase,
246 0,
247 &PpbSize,
248 MEM_COMMIT,
249 PAGE_READWRITE);
250 if (!NT_SUCCESS(Status))
251 {
252 return(Status);
253 }
254
255 DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
256
257 /* write process parameters block*/
258 RtlDeNormalizeProcessParams (Ppb);
259 NtWriteVirtualMemory(ProcessHandle,
260 PpbBase,
261 Ppb,
262 Ppb->MaximumLength,
263 &BytesWritten);
264 RtlNormalizeProcessParams (Ppb);
265
266 /* write pointer to environment */
267 Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
268 NtWriteVirtualMemory(ProcessHandle,
269 (PVOID)(PpbBase + Offset),
270 &EnvPtr,
271 sizeof(EnvPtr),
272 &BytesWritten);
273
274 /* write pointer to process parameter block */
275 Offset = FIELD_OFFSET(PEB, ProcessParameters);
276 NtWriteVirtualMemory(ProcessHandle,
277 (PVOID)(PEB_BASE + Offset),
278 &PpbBase,
279 sizeof(PpbBase),
280 &BytesWritten);
281
282 return(STATUS_SUCCESS);
283 }
284
285 NTSTATUS
286 STDCALL
287 RtlCreateUserProcess (
288 PUNICODE_STRING CommandLine, // verified
289 ULONG Unknown2,
290 PRTL_USER_PROCESS_PARAMETERS Ppb, // verified
291 PSECURITY_DESCRIPTOR ProcessSd,
292 PSECURITY_DESCRIPTOR ThreadSd,
293 WINBOOL bInheritHandles,
294 DWORD dwCreationFlags,
295 ULONG Unknown8,
296 ULONG Unknown9,
297 PRTL_USER_PROCESS_INFO ProcessInfo // verified
298 )
299 {
300 HANDLE hSection;
301 HANDLE hThread;
302 NTSTATUS Status;
303 LPTHREAD_START_ROUTINE lpStartAddress = NULL;
304 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
305 ULONG retlen;
306 CHAR ImageFileName[8];
307
308 DPRINT("RtlCreateUserProcess\n");
309
310 // Status = RtlpMapFile(CommandLine,
311 Status = RtlpMapFile(Ppb,
312 &hSection,
313 ImageFileName);
314
315 /*
316 * Create a new process
317 */
318
319 Status = NtCreateProcess(&(ProcessInfo->ProcessHandle),
320 PROCESS_ALL_ACCESS,
321 NULL,
322 NtCurrentProcess(),
323 bInheritHandles,
324 hSection,
325 NULL,
326 NULL);
327 if (!NT_SUCCESS(Status))
328 {
329 return(Status);
330 }
331
332 /*
333 * Get some information about the process
334 */
335
336 ZwQueryInformationProcess(ProcessInfo->ProcessHandle,
337 ProcessBasicInformation,
338 &ProcessBasicInfo,
339 sizeof(ProcessBasicInfo),
340 &retlen);
341 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
342 ProcessBasicInfo.UniqueProcessId);
343 ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
344
345 Status = NtSetInformationProcess(ProcessInfo->ProcessHandle,
346 ProcessImageFileName,
347 ImageFileName,
348 8);
349
350 /*
351 * Create Process Environment Block
352 */
353 DPRINT("Creating peb\n");
354 KlInitPeb(ProcessInfo->ProcessHandle, Ppb);
355
356 DPRINT("Creating thread for process\n");
357 lpStartAddress = (LPTHREAD_START_ROUTINE)
358 ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(NTDLL_BASE))->
359 AddressOfEntryPoint +
360 ((PIMAGE_OPTIONAL_HEADER)OPTHDROFFSET(NTDLL_BASE))->ImageBase;
361
362 hThread = KlCreateFirstThread(ProcessInfo->ProcessHandle,
363 // Headers.OptionalHeader.SizeOfStackReserve,
364 0x200000,
365 lpStartAddress,
366 dwCreationFlags,
367 &(ProcessInfo->ClientId));
368 if (hThread == NULL)
369 {
370 DPRINT("Failed to create thread\n");
371 return(STATUS_UNSUCCESSFUL);
372 }
373 return(STATUS_SUCCESS);
374 }
375
376 /* EOF */