migrate substitution keywords to SVN
[reactos.git] / reactos / lib / ntdll / rtl / process.c
1 /* $Id$
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 <windows.h>
16 #include <napi/i386/segment.h>
17 #include <ntdll/ldr.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 static NTSTATUS RtlpCreateFirstThread
27 (
28 HANDLE ProcessHandle,
29 ULONG StackReserve,
30 ULONG StackCommit,
31 LPTHREAD_START_ROUTINE lpStartAddress,
32 PCLIENT_ID ClientId,
33 PHANDLE ThreadHandle
34 )
35 {
36 return RtlCreateUserThread
37 (
38 ProcessHandle,
39 NULL,
40 FALSE,
41 0,
42 &StackReserve,
43 &StackCommit,
44 lpStartAddress,
45 (PVOID)PEB_BASE,
46 ThreadHandle,
47 ClientId
48 );
49 }
50
51 static NTSTATUS
52 RtlpMapFile(PUNICODE_STRING ImageFileName,
53 PRTL_USER_PROCESS_PARAMETERS Ppb,
54 ULONG Attributes,
55 PHANDLE Section)
56 {
57 HANDLE hFile;
58 IO_STATUS_BLOCK IoStatusBlock;
59 OBJECT_ATTRIBUTES ObjectAttributes;
60 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
61 NTSTATUS Status;
62
63 hFile = NULL;
64
65 RtlDeNormalizeProcessParams (Ppb);
66
67 // DbgPrint("ImagePathName %x\n", Ppb->ImagePathName.Buffer);
68
69 InitializeObjectAttributes(&ObjectAttributes,
70 ImageFileName,
71 Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT),
72 NULL,
73 SecurityDescriptor);
74
75 RtlNormalizeProcessParams (Ppb);
76
77 /*
78 * Try to open the executable
79 */
80
81 Status = NtOpenFile(&hFile,
82 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
83 &ObjectAttributes,
84 &IoStatusBlock,
85 FILE_SHARE_DELETE|FILE_SHARE_READ,
86 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
87
88 if (!NT_SUCCESS(Status))
89 {
90 return(Status);
91 }
92
93 Status = NtCreateSection(Section,
94 SECTION_ALL_ACCESS,
95 NULL,
96 NULL,
97 PAGE_EXECUTE,
98 SEC_IMAGE,
99 hFile);
100 NtClose(hFile);
101
102 if (!NT_SUCCESS(Status))
103 {
104 return(Status);
105 }
106
107 return(STATUS_SUCCESS);
108 }
109
110 static NTSTATUS KlInitPeb (HANDLE ProcessHandle,
111 PRTL_USER_PROCESS_PARAMETERS Ppb,
112 PVOID* ImageBaseAddress)
113 {
114 NTSTATUS Status;
115 PVOID PpbBase;
116 ULONG PpbSize;
117 ULONG BytesWritten;
118 ULONG Offset;
119 PVOID EnvPtr = NULL;
120 ULONG EnvSize = 0;
121
122 /* create the Environment */
123 if (Ppb->Environment != NULL)
124 {
125 MEMORY_BASIC_INFORMATION MemInfo;
126
127 Status = NtQueryVirtualMemory (NtCurrentProcess (),
128 Ppb->Environment,
129 MemoryBasicInformation,
130 &MemInfo,
131 sizeof(MEMORY_BASIC_INFORMATION),
132 NULL);
133 if (!NT_SUCCESS(Status))
134 {
135 return Status;
136 }
137 EnvSize = MemInfo.RegionSize;
138 }
139 DPRINT("EnvironmentSize %ld\n", EnvSize);
140
141 /* allocate and initialize new environment block */
142 if (EnvSize != 0)
143 {
144 Status = NtAllocateVirtualMemory(ProcessHandle,
145 &EnvPtr,
146 0,
147 &EnvSize,
148 MEM_RESERVE | MEM_COMMIT,
149 PAGE_READWRITE);
150 if (!NT_SUCCESS(Status))
151 {
152 return(Status);
153 }
154
155 NtWriteVirtualMemory(ProcessHandle,
156 EnvPtr,
157 Ppb->Environment,
158 EnvSize,
159 &BytesWritten);
160 }
161 DPRINT("EnvironmentPointer %p\n", EnvPtr);
162
163 /* create the PPB */
164 PpbBase = NULL;
165 PpbSize = Ppb->AllocationSize;
166
167 Status = NtAllocateVirtualMemory(ProcessHandle,
168 &PpbBase,
169 0,
170 &PpbSize,
171 MEM_RESERVE | MEM_COMMIT,
172 PAGE_READWRITE);
173 if (!NT_SUCCESS(Status))
174 {
175 return(Status);
176 }
177
178 DPRINT("Ppb->MaximumLength %x\n", Ppb->AllocationSize);
179
180 /* write process parameters block*/
181 RtlDeNormalizeProcessParams (Ppb);
182 NtWriteVirtualMemory(ProcessHandle,
183 PpbBase,
184 Ppb,
185 Ppb->AllocationSize,
186
187 &BytesWritten);
188 RtlNormalizeProcessParams (Ppb);
189
190 /* write pointer to environment */
191 Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
192 NtWriteVirtualMemory(ProcessHandle,
193 (PVOID)(PpbBase + Offset),
194 &EnvPtr,
195 sizeof(EnvPtr),
196 &BytesWritten);
197
198 /* write pointer to process parameter block */
199 Offset = FIELD_OFFSET(PEB, ProcessParameters);
200 NtWriteVirtualMemory(ProcessHandle,
201 (PVOID)(PEB_BASE + Offset),
202 &PpbBase,
203 sizeof(PpbBase),
204 &BytesWritten);
205
206 /* Read image base address. */
207 Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
208 NtReadVirtualMemory(ProcessHandle,
209 (PVOID)(PEB_BASE + Offset),
210 ImageBaseAddress,
211 sizeof(PVOID),
212 &BytesWritten);
213
214 return(STATUS_SUCCESS);
215 }
216
217 /*
218 * @implemented
219 */
220 NTSTATUS STDCALL
221 RtlCreateUserProcess(PUNICODE_STRING ImageFileName,
222 ULONG Attributes,
223 PRTL_USER_PROCESS_PARAMETERS ProcessParameters,
224 PSECURITY_DESCRIPTOR ProcessSecurityDescriptor,
225 PSECURITY_DESCRIPTOR ThreadSecurityDescriptor,
226 HANDLE ParentProcess,
227 BOOLEAN CurrentDirectory,
228 HANDLE DebugPort,
229 HANDLE ExceptionPort,
230 PRTL_PROCESS_INFO ProcessInfo)
231 {
232 HANDLE hSection;
233 NTSTATUS Status;
234 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
235 ULONG retlen;
236 SECTION_IMAGE_INFORMATION Sii;
237 ULONG ResultLength;
238 PVOID ImageBaseAddress;
239
240 DPRINT("RtlCreateUserProcess\n");
241
242 Status = RtlpMapFile(ImageFileName,
243 ProcessParameters,
244 Attributes,
245 &hSection);
246 if( !NT_SUCCESS( Status ) )
247 return Status;
248
249 /*
250 * Create a new process
251 */
252 if (ParentProcess == NULL)
253 ParentProcess = NtCurrentProcess();
254
255 Status = NtCreateProcess(&(ProcessInfo->ProcessHandle),
256 PROCESS_ALL_ACCESS,
257 NULL,
258 ParentProcess,
259 CurrentDirectory,
260 hSection,
261 DebugPort,
262 ExceptionPort);
263 if (!NT_SUCCESS(Status))
264 {
265 NtClose(hSection);
266 return(Status);
267 }
268
269 /*
270 * Get some information about the process
271 */
272 NtQueryInformationProcess(ProcessInfo->ProcessHandle,
273 ProcessBasicInformation,
274 &ProcessBasicInfo,
275 sizeof(ProcessBasicInfo),
276 &retlen);
277 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
278 ProcessBasicInfo.UniqueProcessId);
279 ProcessInfo->ClientId.UniqueProcess = (HANDLE)ProcessBasicInfo.UniqueProcessId;
280
281 /*
282 * Create Process Environment Block
283 */
284 DPRINT("Creating peb\n");
285 KlInitPeb(ProcessInfo->ProcessHandle,
286 ProcessParameters,
287 &ImageBaseAddress);
288
289 Status = NtQuerySection(hSection,
290 SectionImageInformation,
291 &Sii,
292 sizeof(Sii),
293 &ResultLength);
294 if (!NT_SUCCESS(Status) || ResultLength != sizeof(Sii))
295 {
296 DPRINT("Failed to get section image information.\n");
297 NtClose(hSection);
298 return(Status);
299 }
300
301 DPRINT("Creating thread for process\n");
302 Status = RtlpCreateFirstThread(ProcessInfo->ProcessHandle,
303 Sii.StackReserve,
304 Sii.StackCommit,
305 ImageBaseAddress + (ULONG)Sii.EntryPoint,
306 &ProcessInfo->ClientId,
307 &ProcessInfo->ThreadHandle);
308
309 NtClose(hSection);
310
311 if (!NT_SUCCESS(Status))
312 {
313 DPRINT("Failed to create thread\n");
314 return(Status);
315 }
316
317 return(STATUS_SUCCESS);
318 }
319
320 /* EOF */