1 /* $Id: create.c,v 1.47 2002/08/08 17:54:12 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/process/create.c
6 * PURPOSE: Process functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
12 /* INCLUDES ****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <kernel32/proc.h>
17 #include <kernel32/thread.h>
20 #include <napi/i386/segment.h>
21 #include <ntdll/ldr.h>
23 #include <ntdll/base.h>
24 #include <ntdll/rtl.h>
25 #include <csrss/csrss.h>
26 #include <ntdll/csr.h>
29 #include <kernel32/kernel32.h>
30 #include <kernel32/error.h>
32 /* FUNCTIONS ****************************************************************/
35 CreateProcessA (LPCSTR lpApplicationName
,
37 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
38 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
39 WINBOOL bInheritHandles
,
40 DWORD dwCreationFlags
,
42 LPCSTR lpCurrentDirectory
,
43 LPSTARTUPINFOA lpStartupInfo
,
44 LPPROCESS_INFORMATION lpProcessInformation
)
46 * FUNCTION: The CreateProcess function creates a new process and its
47 * primary thread. The new process executes the specified executable file
50 * lpApplicationName = Pointer to name of executable module
51 * lpCommandLine = Pointer to command line string
52 * lpProcessAttributes = Process security attributes
53 * lpThreadAttributes = Thread security attributes
54 * bInheritHandles = Handle inheritance flag
55 * dwCreationFlags = Creation flags
56 * lpEnvironment = Pointer to new environment block
57 * lpCurrentDirectory = Pointer to current directory name
58 * lpStartupInfo = Pointer to startup info
59 * lpProcessInformation = Pointer to process information
62 PWCHAR lpEnvironmentW
= NULL
;
63 UNICODE_STRING ApplicationNameU
;
64 UNICODE_STRING CurrentDirectoryU
;
65 UNICODE_STRING CommandLineU
;
66 ANSI_STRING ApplicationName
;
67 ANSI_STRING CurrentDirectory
;
68 ANSI_STRING CommandLine
;
70 CHAR TempCurrentDirectoryA
[256];
72 DPRINT("CreateProcessA(%s)\n", lpApplicationName
);
73 DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, "
74 "lpStartupInfo %x, lpProcessInformation %x\n", dwCreationFlags
,
75 lpEnvironment
, lpCurrentDirectory
, lpStartupInfo
, lpProcessInformation
);
79 PCHAR ptr
= lpEnvironment
;
81 UNICODE_STRING EnvironmentU
;
82 ANSI_STRING EnvironmentA
;
85 RtlInitAnsiString(&EnvironmentA
, ptr
);
87 len
+= RtlAnsiStringToUnicodeSize(&EnvironmentA
) + sizeof(WCHAR
);
89 len
+= RtlOemStringToUnicodeSize(&EnvironmentA
) + sizeof(WCHAR
);
90 ptr
+= EnvironmentA
.MaximumLength
;
93 lpEnvironmentW
= (PWCHAR
)RtlAllocateHeap(GetProcessHeap(),
94 HEAP_GENERATE_EXCEPTIONS
|HEAP_ZERO_MEMORY
,
96 if (lpEnvironmentW
== NULL
)
101 EnvironmentU
.Buffer
= lpEnvironmentW
;
102 EnvironmentU
.Length
= 0;
103 EnvironmentU
.MaximumLength
= len
;
106 RtlInitAnsiString(&EnvironmentA
, ptr
);
108 RtlAnsiStringToUnicodeString(&EnvironmentU
, &EnvironmentA
, FALSE
);
110 RtlOemStringToUnicodeString(&EnvironmentU
, &EnvironmentA
, FALSE
);
111 ptr
+= EnvironmentA
.MaximumLength
;
112 EnvironmentU
.Buffer
+= (EnvironmentU
.Length
/ sizeof(WCHAR
) + 1);
113 EnvironmentU
.MaximumLength
-= (EnvironmentU
.Length
+ sizeof(WCHAR
));
114 EnvironmentU
.Length
= 0;
117 EnvironmentU
.Buffer
[0] = 0;
120 RtlInitAnsiString (&CommandLine
,
122 RtlInitAnsiString (&ApplicationName
,
123 (LPSTR
)lpApplicationName
);
124 if (lpCurrentDirectory
!= NULL
)
126 RtlInitAnsiString (&CurrentDirectory
,
127 (LPSTR
)lpCurrentDirectory
);
130 /* convert ansi (or oem) strings to unicode */
133 RtlAnsiStringToUnicodeString (&CommandLineU
, &CommandLine
, TRUE
);
134 RtlAnsiStringToUnicodeString (&ApplicationNameU
, &ApplicationName
, TRUE
);
135 if (lpCurrentDirectory
!= NULL
)
136 RtlAnsiStringToUnicodeString (&CurrentDirectoryU
, &CurrentDirectory
, TRUE
);
140 RtlOemStringToUnicodeString (&CommandLineU
, &CommandLine
, TRUE
);
141 RtlOemStringToUnicodeString (&ApplicationNameU
, &ApplicationName
, TRUE
);
142 if (lpCurrentDirectory
!= NULL
)
143 RtlOemStringToUnicodeString (&CurrentDirectoryU
, &CurrentDirectory
, TRUE
);
146 Result
= CreateProcessW (ApplicationNameU
.Buffer
,
153 (lpCurrentDirectory
== NULL
) ? NULL
: CurrentDirectoryU
.Buffer
,
154 (LPSTARTUPINFOW
)lpStartupInfo
,
155 lpProcessInformation
);
157 RtlFreeUnicodeString (&ApplicationNameU
);
158 RtlFreeUnicodeString (&CommandLineU
);
159 if (lpCurrentDirectory
!= NULL
)
160 RtlFreeUnicodeString (&CurrentDirectoryU
);
164 RtlFreeHeap(GetProcessHeap(), 0, lpEnvironmentW
);
172 KlCreateFirstThread(HANDLE ProcessHandle
,
173 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
176 LPTHREAD_START_ROUTINE lpStartAddress
,
177 DWORD dwCreationFlags
,
182 OBJECT_ATTRIBUTES ObjectAttributes
;
184 CONTEXT ThreadContext
;
185 INITIAL_TEB InitialTeb
;
186 BOOLEAN CreateSuspended
= FALSE
;
187 ULONG OldPageProtection
;
189 ULONG InitialStack
[5];
191 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
192 ObjectAttributes
.RootDirectory
= NULL
;
193 ObjectAttributes
.ObjectName
= NULL
;
194 ObjectAttributes
.Attributes
= 0;
195 if (lpThreadAttributes
!= NULL
)
197 if (lpThreadAttributes
->bInheritHandle
)
198 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
199 ObjectAttributes
.SecurityDescriptor
=
200 lpThreadAttributes
->lpSecurityDescriptor
;
202 ObjectAttributes
.SecurityQualityOfService
= NULL
;
204 if ((dwCreationFlags
& CREATE_SUSPENDED
) == CREATE_SUSPENDED
)
205 CreateSuspended
= TRUE
;
207 CreateSuspended
= FALSE
;
209 InitialTeb
.StackReserve
= (StackReserve
< 0x100000) ? 0x100000 : StackReserve
;
210 /* FIXME: use correct commit size */
212 InitialTeb
.StackCommit
= (StackCommit
< PAGESIZE
) ? PAGESIZE
: StackCommit
;
214 InitialTeb
.StackCommit
= InitialTeb
.StackReserve
- PAGESIZE
;
216 /* size of guard page */
217 InitialTeb
.StackCommit
+= PAGESIZE
;
220 InitialTeb
.StackAllocate
= NULL
;
221 Status
= NtAllocateVirtualMemory(ProcessHandle
,
222 &InitialTeb
.StackAllocate
,
224 &InitialTeb
.StackReserve
,
227 if (!NT_SUCCESS(Status
))
229 DPRINT("Error reserving stack space!\n");
230 SetLastErrorByStatus(Status
);
234 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
235 InitialTeb
.StackAllocate
, InitialTeb
.StackReserve
);
237 InitialTeb
.StackBase
= (PVOID
)((ULONG
)InitialTeb
.StackAllocate
+ InitialTeb
.StackReserve
);
238 InitialTeb
.StackLimit
= (PVOID
)((ULONG
)InitialTeb
.StackBase
- InitialTeb
.StackCommit
);
240 DPRINT("StackBase: %p StackCommit: %p\n",
241 InitialTeb
.StackBase
, InitialTeb
.StackCommit
);
243 /* Commit stack page(s) */
244 Status
= NtAllocateVirtualMemory(ProcessHandle
,
245 &InitialTeb
.StackLimit
,
247 &InitialTeb
.StackCommit
,
250 if (!NT_SUCCESS(Status
))
252 /* release the stack space */
253 NtFreeVirtualMemory(ProcessHandle
,
254 InitialTeb
.StackAllocate
,
255 &InitialTeb
.StackReserve
,
258 DPRINT("Error comitting stack page(s)!\n");
259 SetLastErrorByStatus(Status
);
263 DPRINT("StackLimit: %p\n",
264 InitialTeb
.StackLimit
);
266 /* Protect guard page */
267 Status
= NtProtectVirtualMemory(ProcessHandle
,
268 InitialTeb
.StackLimit
,
270 PAGE_GUARD
| PAGE_READWRITE
,
272 if (!NT_SUCCESS(Status
))
274 /* release the stack space */
275 NtFreeVirtualMemory(ProcessHandle
,
276 InitialTeb
.StackAllocate
,
277 &InitialTeb
.StackReserve
,
280 DPRINT("Error comitting guard page!\n");
281 SetLastErrorByStatus(Status
);
285 memset(&ThreadContext
,0,sizeof(CONTEXT
));
286 ThreadContext
.Eip
= (ULONG
)lpStartAddress
;
287 ThreadContext
.SegGs
= USER_DS
;
288 ThreadContext
.SegFs
= USER_DS
;
289 ThreadContext
.SegEs
= USER_DS
;
290 ThreadContext
.SegDs
= USER_DS
;
291 ThreadContext
.SegCs
= USER_CS
;
292 ThreadContext
.SegSs
= USER_DS
;
293 ThreadContext
.Esp
= (ULONG
)InitialTeb
.StackBase
- 20;
294 ThreadContext
.EFlags
= (1<<1) + (1<<9);
296 DPRINT("ThreadContext.Eip %x\n",ThreadContext
.Eip
);
299 * Write in the initial stack.
302 InitialStack
[1] = PEB_BASE
;
303 Status
= ZwWriteVirtualMemory(ProcessHandle
,
304 (PVOID
)ThreadContext
.Esp
,
306 sizeof(InitialStack
),
308 if (!NT_SUCCESS(Status
))
310 DPRINT1("Failed to write initial stack.\n");
314 Status
= NtCreateThread(&ThreadHandle
,
322 if (!NT_SUCCESS(Status
))
324 NtFreeVirtualMemory(ProcessHandle
,
325 InitialTeb
.StackAllocate
,
326 &InitialTeb
.StackReserve
,
328 SetLastErrorByStatus(Status
);
332 if (lpThreadId
!= NULL
)
334 memcpy(lpThreadId
, &ClientId
.UniqueThread
,sizeof(ULONG
));
337 return(ThreadHandle
);
341 KlMapFile(LPCWSTR lpApplicationName
)
344 IO_STATUS_BLOCK IoStatusBlock
;
345 UNICODE_STRING ApplicationNameString
;
346 OBJECT_ATTRIBUTES ObjectAttributes
;
347 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
354 * Find the application name
357 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpApplicationName
,
358 &ApplicationNameString
,
363 DPRINT("ApplicationName %S\n",ApplicationNameString
.Buffer
);
365 InitializeObjectAttributes(&ObjectAttributes
,
366 &ApplicationNameString
,
367 OBJ_CASE_INSENSITIVE
,
372 * Try to open the executable
375 Status
= NtOpenFile(&hFile
,
376 SYNCHRONIZE
|FILE_EXECUTE
|FILE_READ_DATA
,
379 FILE_SHARE_DELETE
|FILE_SHARE_READ
,
380 FILE_SYNCHRONOUS_IO_NONALERT
|FILE_NON_DIRECTORY_FILE
);
382 RtlFreeUnicodeString (&ApplicationNameString
);
384 if (!NT_SUCCESS(Status
))
386 DPRINT("Failed to open file\n");
387 SetLastErrorByStatus (Status
);
391 Status
= NtCreateSection(&hSection
,
400 if (!NT_SUCCESS(Status
))
402 DPRINT("Failed to create section\n");
403 SetLastErrorByStatus (Status
);
411 KlInitPeb (HANDLE ProcessHandle
,
412 PRTL_USER_PROCESS_PARAMETERS Ppb
,
413 PVOID
* ImageBaseAddress
)
420 PVOID ParentEnv
= NULL
;
423 ULONG EnvSize
= 0, EnvSize1
= 0;
425 /* create the Environment */
426 if (Ppb
->Environment
!= NULL
)
428 ParentEnv
= Ppb
->Environment
;
435 EnvSize
= (PVOID
)ptr
- ParentEnv
;
437 else if (NtCurrentPeb()->ProcessParameters
->Environment
!= NULL
)
439 MEMORY_BASIC_INFORMATION MemInfo
;
440 ParentEnv
= NtCurrentPeb()->ProcessParameters
->Environment
;
442 Status
= NtQueryVirtualMemory (NtCurrentProcess (),
444 MemoryBasicInformation
,
446 sizeof(MEMORY_BASIC_INFORMATION
),
448 if (!NT_SUCCESS(Status
))
452 EnvSize
= MemInfo
.RegionSize
;
454 DPRINT("EnvironmentSize %ld\n", EnvSize
);
456 /* allocate and initialize new environment block */
460 Status
= NtAllocateVirtualMemory(ProcessHandle
,
464 MEM_RESERVE
| MEM_COMMIT
,
466 if (!NT_SUCCESS(Status
))
471 NtWriteVirtualMemory(ProcessHandle
,
480 PpbSize
= Ppb
->MaximumLength
;
481 Status
= NtAllocateVirtualMemory(ProcessHandle
,
485 MEM_RESERVE
| MEM_COMMIT
,
487 if (!NT_SUCCESS(Status
))
492 DPRINT("Ppb->MaximumLength %x\n", Ppb
->MaximumLength
);
493 NtWriteVirtualMemory(ProcessHandle
,
499 /* write pointer to environment */
500 Offset
= FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS
, Environment
);
501 NtWriteVirtualMemory(ProcessHandle
,
502 (PVOID
)(PpbBase
+ Offset
),
507 /* write pointer to process parameter block */
508 Offset
= FIELD_OFFSET(PEB
, ProcessParameters
);
509 NtWriteVirtualMemory(ProcessHandle
,
510 (PVOID
)(PEB_BASE
+ Offset
),
515 /* Read image base address. */
516 Offset
= FIELD_OFFSET(PEB
, ImageBaseAddress
);
517 NtReadVirtualMemory(ProcessHandle
,
518 (PVOID
)(PEB_BASE
+ Offset
),
523 return(STATUS_SUCCESS
);
528 CreateProcessW(LPCWSTR lpApplicationName
,
529 LPWSTR lpCommandLine
,
530 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
531 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
532 WINBOOL bInheritHandles
,
533 DWORD dwCreationFlags
,
534 LPVOID lpEnvironment
,
535 LPCWSTR lpCurrentDirectory
,
536 LPSTARTUPINFOW lpStartupInfo
,
537 LPPROCESS_INFORMATION lpProcessInformation
)
539 HANDLE hSection
, hProcess
, hThread
;
541 LPTHREAD_START_ROUTINE lpStartAddress
= NULL
;
542 WCHAR ImagePathName
[256];
543 UNICODE_STRING ImagePathName_U
;
544 PROCESS_BASIC_INFORMATION ProcessBasicInfo
;
546 PRTL_USER_PROCESS_PARAMETERS Ppb
;
547 UNICODE_STRING CommandLine_U
;
548 CSRSS_API_REQUEST CsrRequest
;
549 CSRSS_API_REPLY CsrReply
;
550 CHAR ImageFileName
[8];
553 ANSI_STRING ProcedureName
;
554 UNICODE_STRING CurrentDirectory_U
;
555 SECTION_IMAGE_INFORMATION Sii
;
556 WCHAR TempCurrentDirectoryW
[256];
557 WCHAR TempApplicationNameW
[256];
558 WCHAR TempCommandLineNameW
[256];
559 UNICODE_STRING RuntimeInfo_U
;
560 PVOID ImageBaseAddress
;
562 DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
563 lpApplicationName
, lpCommandLine
);
565 if (lpApplicationName
!= NULL
&& lpApplicationName
[0] != 0)
567 wcscpy (TempApplicationNameW
, lpApplicationName
);
568 i
= wcslen(TempApplicationNameW
);
569 if (TempApplicationNameW
[i
- 1] == L
'.')
571 TempApplicationNameW
[i
- 1] = 0;
575 s
= max(wcsrchr(TempApplicationNameW
, L
'\\'), wcsrchr(TempApplicationNameW
, L
'/'));
578 s
= TempApplicationNameW
;
584 e
= wcsrchr(s
, L
'.');
588 e
= wcsrchr(s
, L
'.');
592 else if (lpCommandLine
!= NULL
&& lpCommandLine
[0] != 0)
594 if (lpCommandLine
[0] == L
'"')
596 wcscpy(TempApplicationNameW
, &lpCommandLine
[0]);
597 s
= wcschr(TempApplicationNameW
, L
'"');
606 wcscpy(TempApplicationNameW
, lpCommandLine
);
607 s
= wcschr(TempApplicationNameW
, L
' ');
613 s
= max(wcsrchr(TempApplicationNameW
, L
'\\'), wcsrchr(TempApplicationNameW
, L
'/'));
616 s
= TempApplicationNameW
;
618 s
= wcsrchr(TempApplicationNameW
, L
'.');
620 wcscat(TempApplicationNameW
, L
".exe");
627 if (!SearchPathW(NULL
, TempApplicationNameW
, NULL
, sizeof(ImagePathName
), ImagePathName
, &s
))
632 e
= wcsrchr(s
, L
'.');
633 if (e
!= NULL
&& (!_wcsicmp(e
, L
".bat") || !_wcsicmp(e
, L
".cmd")))
635 // the command is a batch file
636 if (lpApplicationName
!= NULL
&& lpApplicationName
[0])
638 // FIXME: use COMSPEC for the command interpreter
639 wcscpy(TempCommandLineNameW
, L
"cmd /c ");
640 wcscat(TempCommandLineNameW
, lpApplicationName
);
641 lpCommandLine
= TempCommandLineNameW
;
642 wcscpy(TempApplicationNameW
, L
"cmd.exe");
643 if (!SearchPathW(NULL
, TempApplicationNameW
, NULL
, sizeof(ImagePathName
), ImagePathName
, &s
))
655 * Store the image file name for the process
662 for (i
= 0; i
< 8; i
++)
664 ImageFileName
[i
] = (CHAR
)(s
[i
]);
672 * Process the application name and command line
674 RtlInitUnicodeString(&ImagePathName_U
, ImagePathName
);
675 RtlInitUnicodeString(&CommandLine_U
, lpCommandLine
);
677 DPRINT("ImagePathName_U %S\n", ImagePathName_U
.Buffer
);
678 DPRINT("CommandLine_U %S\n", CommandLine_U
.Buffer
);
680 /* Initialize the current directory string */
681 if (lpCurrentDirectory
!= NULL
)
683 RtlInitUnicodeString(&CurrentDirectory_U
,
688 GetCurrentDirectoryW(256, TempCurrentDirectoryW
);
689 RtlInitUnicodeString(&CurrentDirectory_U
,
690 TempCurrentDirectoryW
);
695 * Create a section for the executable
698 hSection
= KlMapFile (ImagePathName
);
699 if (hSection
== NULL
)
705 * Create a new process
707 Status
= NtCreateProcess(&hProcess
,
717 if (lpStartupInfo
->lpReserved2
)
719 ULONG i
, Count
= *(ULONG
*)lpStartupInfo
->lpReserved2
;
722 PRTL_USER_PROCESS_PARAMETERS CurrPpb
= NtCurrentPeb()->ProcessParameters
;
726 * ROUND_UP(xxx,2) + 2 is a dirty hack. RtlCreateProcessParameters assumes that
727 * the runtimeinfo is a unicode string and use RtlCopyUnicodeString for duplication.
728 * If is possible that this function overwrite the last information in runtimeinfo
729 * with the null terminator for the unicode string.
731 RuntimeInfo_U
.Length
= RuntimeInfo_U
.MaximumLength
= ROUND_UP(lpStartupInfo
->cbReserved2
, 2) + 2;
732 RuntimeInfo_U
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, RuntimeInfo_U
.Length
);
733 memcpy(RuntimeInfo_U
.Buffer
, lpStartupInfo
->lpReserved2
, lpStartupInfo
->cbReserved2
);
740 RtlCreateProcessParameters(&Ppb
,
743 lpCurrentDirectory
? &CurrentDirectory_U
: NULL
,
749 lpStartupInfo
&& lpStartupInfo
->lpReserved2
? &RuntimeInfo_U
: NULL
);
751 if (lpStartupInfo
&& lpStartupInfo
->lpReserved2
)
752 RtlFreeHeap(GetProcessHeap(), 0, RuntimeInfo_U
.Buffer
);
756 * Translate some handles for the new process
758 if (Ppb
->CurrentDirectory
.Handle
)
760 Status
= NtDuplicateObject (NtCurrentProcess(),
761 Ppb
->CurrentDirectory
.Handle
,
763 &Ppb
->CurrentDirectory
.Handle
,
766 DUPLICATE_SAME_ACCESS
);
769 if (Ppb
->ConsoleHandle
)
771 Status
= NtDuplicateObject (NtCurrentProcess(),
777 DUPLICATE_SAME_ACCESS
);
781 * Get some information about the executable
783 Status
= ZwQuerySection(hSection
,
784 SectionImageInformation
,
794 * Get some information about the process
796 ZwQueryInformationProcess(hProcess
,
797 ProcessBasicInformation
,
799 sizeof(ProcessBasicInfo
),
801 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
802 ProcessBasicInfo
.UniqueProcessId
);
803 lpProcessInformation
->dwProcessId
= ProcessBasicInfo
.UniqueProcessId
;
806 * Tell the csrss server we are creating a new process
808 CsrRequest
.Type
= CSRSS_CREATE_PROCESS
;
809 CsrRequest
.Data
.CreateProcessRequest
.NewProcessId
=
810 ProcessBasicInfo
.UniqueProcessId
;
811 CsrRequest
.Data
.CreateProcessRequest
.Flags
= dwCreationFlags
;
812 Status
= CsrClientCallServer(&CsrRequest
,
814 sizeof(CSRSS_API_REQUEST
),
815 sizeof(CSRSS_API_REPLY
));
816 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrReply
.Status
))
818 DbgPrint("Failed to tell csrss about new process. Expect trouble.\n");
821 // Set the child console handles
822 Ppb
->InputHandle
= NtCurrentPeb()->ProcessParameters
->InputHandle
;
823 Ppb
->OutputHandle
= NtCurrentPeb()->ProcessParameters
->OutputHandle
;
824 Ppb
->ErrorHandle
= NtCurrentPeb()->ProcessParameters
->ErrorHandle
;
826 if (lpStartupInfo
&& (lpStartupInfo
->dwFlags
& STARTF_USESTDHANDLES
))
828 if (lpStartupInfo
->hStdInput
)
829 Ppb
->InputHandle
= lpStartupInfo
->hStdInput
;
830 if (lpStartupInfo
->hStdOutput
)
831 Ppb
->OutputHandle
= lpStartupInfo
->hStdOutput
;
832 if (lpStartupInfo
->hStdError
)
833 Ppb
->ErrorHandle
= lpStartupInfo
->hStdError
;
836 if (IsConsoleHandle(Ppb
->InputHandle
))
838 Ppb
->InputHandle
= CsrReply
.Data
.CreateProcessReply
.InputHandle
;
842 DPRINT("Duplicate input handle\n");
843 Status
= NtDuplicateObject (NtCurrentProcess(),
849 DUPLICATE_SAME_ACCESS
);
850 if(!NT_SUCCESS(Status
))
852 DPRINT("NtDuplicateObject failed, status %x\n", Status
);
856 if (IsConsoleHandle(Ppb
->OutputHandle
))
858 Ppb
->OutputHandle
= CsrReply
.Data
.CreateProcessReply
.OutputHandle
;
862 DPRINT("Duplicate output handle\n");
863 Status
= NtDuplicateObject (NtCurrentProcess(),
869 DUPLICATE_SAME_ACCESS
);
870 if(!NT_SUCCESS(Status
))
872 DPRINT("NtDuplicateObject failed, status %x\n", Status
);
875 if (IsConsoleHandle(Ppb
->ErrorHandle
))
877 Ppb
->ErrorHandle
= CsrReply
.Data
.CreateProcessReply
.OutputHandle
;
881 DPRINT("Duplicate error handle\n");
882 Status
= NtDuplicateObject (NtCurrentProcess(),
888 DUPLICATE_SAME_ACCESS
);
889 if(!NT_SUCCESS(Status
))
891 DPRINT("NtDuplicateObject failed, status %x\n", Status
);
896 * Create Process Environment Block
898 DPRINT("Creating peb\n");
900 KlInitPeb(hProcess
, Ppb
, &ImageBaseAddress
);
902 RtlDestroyProcessParameters (Ppb
);
904 Status
= NtSetInformationProcess(hProcess
,
905 ProcessImageFileName
,
909 * Create the thread for the kernel
911 DPRINT("Creating thread for process\n");
912 hThread
= KlCreateFirstThread(hProcess
,
916 ImageBaseAddress
+ (ULONG
)Sii
.EntryPoint
,
918 &lpProcessInformation
->dwThreadId
);
924 lpProcessInformation
->hProcess
= hProcess
;
925 lpProcessInformation
->hThread
= hThread
;