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