1 /* $Id: process.c,v 1.30 2002/09/08 10:23:06 chorns Exp $
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)
12 /* INCLUDES ****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <napi/i386/segment.h>
16 #include <ntdll/ldr.h>
17 #include <ntdll/base.h>
18 #include <ntdll/rtl.h>
21 #include <ntdll/ntdll.h>
23 /* FUNCTIONS ****************************************************************/
26 RtlpCreateFirstThread(HANDLE ProcessHandle
,
29 LPTHREAD_START_ROUTINE lpStartAddress
,
34 OBJECT_ATTRIBUTES ObjectAttributes
;
35 CONTEXT ThreadContext
;
36 INITIAL_TEB InitialTeb
;
37 ULONG OldPageProtection
;
39 ULONG InitialStack
[5];
42 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
43 ObjectAttributes
.RootDirectory
= NULL
;
44 ObjectAttributes
.ObjectName
= NULL
;
45 ObjectAttributes
.Attributes
= 0;
46 ObjectAttributes
.SecurityQualityOfService
= NULL
;
48 if (StackReserve
> 0x100000)
49 InitialTeb
.StackReserve
= StackReserve
;
51 InitialTeb
.StackReserve
= 0x100000; /* 1MByte */
55 if (StackCommit
> PAGESIZE
)
56 InitialTeb
.StackCommit
= StackCommit
;
58 InitialTeb
.StackCommit
= PAGESIZE
;
60 InitialTeb
.StackCommit
= InitialTeb
.StackReserve
- PAGESIZE
;
62 /* add guard page size */
63 InitialTeb
.StackCommit
+= PAGESIZE
;
66 InitialTeb
.StackAllocate
= NULL
;
67 Status
= NtAllocateVirtualMemory(ProcessHandle
,
68 &InitialTeb
.StackAllocate
,
70 &InitialTeb
.StackReserve
,
73 if (!NT_SUCCESS(Status
))
75 DPRINT("Error reserving stack space!\n");
79 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
80 InitialTeb
.StackAllocate
, InitialTeb
.StackReserve
);
82 InitialTeb
.StackBase
= (PVOID
)((ULONG
)InitialTeb
.StackAllocate
+ InitialTeb
.StackReserve
);
83 InitialTeb
.StackLimit
= (PVOID
)((ULONG
)InitialTeb
.StackBase
- InitialTeb
.StackCommit
);
85 DPRINT("StackBase: %p StackCommit: 0x%lX\n",
86 InitialTeb
.StackBase
, InitialTeb
.StackCommit
);
89 Status
= NtAllocateVirtualMemory(ProcessHandle
,
90 &InitialTeb
.StackLimit
,
92 &InitialTeb
.StackCommit
,
95 if (!NT_SUCCESS(Status
))
97 /* release the stack space */
98 NtFreeVirtualMemory(ProcessHandle
,
99 InitialTeb
.StackAllocate
,
100 &InitialTeb
.StackReserve
,
103 DPRINT("Error comitting stack page(s)!\n");
107 DPRINT("StackLimit: %p\n", InitialTeb
.StackLimit
);
109 /* Protect guard page */
110 Status
= NtProtectVirtualMemory(ProcessHandle
,
111 InitialTeb
.StackLimit
,
113 PAGE_GUARD
| PAGE_READWRITE
,
115 if (!NT_SUCCESS(Status
))
117 /* release the stack space */
118 NtFreeVirtualMemory(ProcessHandle
,
119 InitialTeb
.StackAllocate
,
120 &InitialTeb
.StackReserve
,
123 DPRINT("Error comitting guard page!\n");
127 memset(&ThreadContext
,0,sizeof(CONTEXT
));
128 ThreadContext
.Eip
= (ULONG
)lpStartAddress
;
129 ThreadContext
.SegGs
= USER_DS
;
130 ThreadContext
.SegFs
= TEB_SELECTOR
;
131 ThreadContext
.SegEs
= USER_DS
;
132 ThreadContext
.SegDs
= USER_DS
;
133 ThreadContext
.SegCs
= USER_CS
;
134 ThreadContext
.SegSs
= USER_DS
;
135 ThreadContext
.Esp
= (ULONG
)InitialTeb
.StackBase
- 20;
136 ThreadContext
.EFlags
= (1<<1) + (1<<9);
138 DPRINT("ThreadContext.Eip %x\n",ThreadContext
.Eip
);
141 * Write in the initial stack.
144 InitialStack
[1] = PEB_BASE
;
145 Status
= ZwWriteVirtualMemory(ProcessHandle
,
146 (PVOID
)ThreadContext
.Esp
,
148 sizeof(InitialStack
),
150 if (!NT_SUCCESS(Status
))
152 DPRINT1("Failed to write initial stack.\n");
156 Status
= NtCreateThread(ThreadHandle
,
164 if (!NT_SUCCESS(Status
))
166 NtFreeVirtualMemory(ProcessHandle
,
167 InitialTeb
.StackAllocate
,
168 &InitialTeb
.StackReserve
,
173 if (ClientId
!= NULL
)
175 memcpy(&ClientId
->UniqueThread
, &Cid
.UniqueThread
, sizeof(ULONG
));
178 return(STATUS_SUCCESS
);
182 RtlpMapFile(PRTL_USER_PROCESS_PARAMETERS Ppb
,
188 IO_STATUS_BLOCK IoStatusBlock
;
189 OBJECT_ATTRIBUTES ObjectAttributes
;
190 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
198 RtlDeNormalizeProcessParams (Ppb
);
200 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
202 InitializeObjectAttributes(&ObjectAttributes
,
203 &(Ppb
->ImagePathName
),
204 Attributes
& (OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
),
208 RtlNormalizeProcessParams (Ppb
);
213 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
214 // DbgPrint("ImagePathName %S\n", Ppb->ImagePathName.Buffer);
215 s
= wcsrchr(Ppb
->ImagePathName
.Buffer
, '\\');
218 s
= Ppb
->ImagePathName
.Buffer
;
229 for (i
= 0; i
< 8; i
++)
231 ImageFileName
[i
] = (CHAR
)(s
[i
]);
239 * Try to open the executable
242 Status
= NtOpenFile(&hFile
,
243 SYNCHRONIZE
|FILE_EXECUTE
|FILE_READ_DATA
,
246 FILE_SHARE_DELETE
|FILE_SHARE_READ
,
247 FILE_SYNCHRONOUS_IO_NONALERT
|FILE_NON_DIRECTORY_FILE
);
249 if (!NT_SUCCESS(Status
))
254 Status
= NtCreateSection(Section
,
263 if (!NT_SUCCESS(Status
))
268 return(STATUS_SUCCESS
);
271 static NTSTATUS
KlInitPeb (HANDLE ProcessHandle
,
272 PRTL_USER_PROCESS_PARAMETERS Ppb
,
273 PVOID
* ImageBaseAddress
)
283 /* create the Environment */
284 if (Ppb
->Environment
!= NULL
)
286 MEMORY_BASIC_INFORMATION MemInfo
;
288 Status
= NtQueryVirtualMemory (NtCurrentProcess (),
290 MemoryBasicInformation
,
292 sizeof(MEMORY_BASIC_INFORMATION
),
294 if (!NT_SUCCESS(Status
))
298 EnvSize
= MemInfo
.RegionSize
;
300 DPRINT("EnvironmentSize %ld\n", EnvSize
);
302 /* allocate and initialize new environment block */
305 Status
= NtAllocateVirtualMemory(ProcessHandle
,
309 MEM_RESERVE
| MEM_COMMIT
,
311 if (!NT_SUCCESS(Status
))
316 NtWriteVirtualMemory(ProcessHandle
,
322 DPRINT("EnvironmentPointer %p\n", EnvPtr
);
326 PpbSize
= Ppb
->MaximumLength
;
327 Status
= NtAllocateVirtualMemory(ProcessHandle
,
331 MEM_RESERVE
| MEM_COMMIT
,
333 if (!NT_SUCCESS(Status
))
338 DPRINT("Ppb->MaximumLength %x\n", Ppb
->MaximumLength
);
340 /* write process parameters block*/
341 RtlDeNormalizeProcessParams (Ppb
);
342 NtWriteVirtualMemory(ProcessHandle
,
347 RtlNormalizeProcessParams (Ppb
);
349 /* write pointer to environment */
350 Offset
= FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS
, Environment
);
351 NtWriteVirtualMemory(ProcessHandle
,
352 (PVOID
)(PpbBase
+ Offset
),
357 /* write pointer to process parameter block */
358 Offset
= FIELD_OFFSET(PEB
, ProcessParameters
);
359 NtWriteVirtualMemory(ProcessHandle
,
360 (PVOID
)(PEB_BASE
+ Offset
),
365 /* Read image base address. */
366 Offset
= FIELD_OFFSET(PEB
, ImageBaseAddress
);
367 NtReadVirtualMemory(ProcessHandle
,
368 (PVOID
)(PEB_BASE
+ Offset
),
373 return(STATUS_SUCCESS
);
378 RtlCreateUserProcess(PUNICODE_STRING ImageFileName
,
380 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
,
381 PSECURITY_DESCRIPTOR ProcessSecurityDescriptor
,
382 PSECURITY_DESCRIPTOR ThreadSecurityDescriptor
,
383 HANDLE ParentProcess
,
384 BOOLEAN CurrentDirectory
,
386 HANDLE ExceptionPort
,
387 PRTL_PROCESS_INFO ProcessInfo
)
391 LPTHREAD_START_ROUTINE lpStartAddress
= NULL
;
392 PROCESS_BASIC_INFORMATION ProcessBasicInfo
;
395 ANSI_STRING ProcedureName
;
396 SECTION_IMAGE_INFORMATION Sii
;
398 PVOID ImageBaseAddress
;
400 DPRINT("RtlCreateUserProcess\n");
402 Status
= RtlpMapFile(ProcessParameters
,
406 if( !NT_SUCCESS( Status
) )
410 * Create a new process
412 if (ParentProcess
== NULL
)
413 ParentProcess
= NtCurrentProcess();
415 Status
= NtCreateProcess(&(ProcessInfo
->ProcessHandle
),
423 if (!NT_SUCCESS(Status
))
430 * Get some information about the process
432 NtQueryInformationProcess(ProcessInfo
->ProcessHandle
,
433 ProcessBasicInformation
,
435 sizeof(ProcessBasicInfo
),
437 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
438 ProcessBasicInfo
.UniqueProcessId
);
439 ProcessInfo
->ClientId
.UniqueProcess
= (HANDLE
)ProcessBasicInfo
.UniqueProcessId
;
441 Status
= NtSetInformationProcess(ProcessInfo
->ProcessHandle
,
442 ProcessImageFileName
,
447 * Create Process Environment Block
449 DPRINT("Creating peb\n");
450 KlInitPeb(ProcessInfo
->ProcessHandle
,
454 Status
= NtQuerySection(hSection
,
455 SectionImageInformation
,
459 if (!NT_SUCCESS(Status
) || ResultLength
!= sizeof(Sii
))
461 DPRINT("Failed to get section image information.\n");
466 DPRINT("Creating thread for process\n");
467 Status
= RtlpCreateFirstThread(ProcessInfo
->ProcessHandle
,
470 ImageBaseAddress
+ (ULONG
)Sii
.EntryPoint
,
471 &ProcessInfo
->ClientId
,
472 &ProcessInfo
->ThreadHandle
);
473 if (!NT_SUCCESS(Status
))
475 DPRINT("Failed to create thread\n");
480 return(STATUS_SUCCESS
);