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);
77 if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT))
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,
152 dwCreationFlags & CREATE_UNICODE_ENVIRONMENT ? lpEnvironment : lpEnvironmentW,
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);
171 struct __EXCEPTION_RECORD;
174 EXCEPTION_DISPOSITION
177 struct _EXCEPTION_RECORD *ExceptionRecord,
178 void * EstablisherFrame,
179 struct _CONTEXT *ContextRecord,
180 void * DispatcherContext )
182 DPRINT("Process terminated abnormally...\n");
184 if (/* FIXME: */ TRUE) /* Not a service */
193 /* We should not get to here */
194 return ExceptionContinueSearch;
198 BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress,
203 __try1(_except_handler)
205 uExitCode = (lpStartAddress)((PVOID)lpParameter);
210 ExitThread(uExitCode);
215 KlCreateFirstThread(HANDLE ProcessHandle,
216 LPSECURITY_ATTRIBUTES lpThreadAttributes,
219 LPTHREAD_START_ROUTINE lpStartAddress,
220 DWORD dwCreationFlags,
225 OBJECT_ATTRIBUTES ObjectAttributes;
227 CONTEXT ThreadContext;
228 INITIAL_TEB InitialTeb;
229 BOOLEAN CreateSuspended = FALSE;
230 ULONG OldPageProtection;
232 ULONG InitialStack[6];
234 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
235 ObjectAttributes.RootDirectory = NULL;
236 ObjectAttributes.ObjectName = NULL;
237 ObjectAttributes.Attributes = 0;
238 if (lpThreadAttributes != NULL)
240 if (lpThreadAttributes->bInheritHandle)
241 ObjectAttributes.Attributes = OBJ_INHERIT;
242 ObjectAttributes.SecurityDescriptor =
243 lpThreadAttributes->lpSecurityDescriptor;
245 ObjectAttributes.SecurityQualityOfService = NULL;
247 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
248 CreateSuspended = TRUE;
250 CreateSuspended = FALSE;
252 InitialTeb.StackReserve = (StackReserve < 0x100000) ? 0x100000 : StackReserve;
253 /* FIXME: use correct commit size */
255 InitialTeb.StackCommit = (StackCommit < PAGE_SIZE) ? PAGE_SIZE : StackCommit;
257 InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
259 /* size of guard page */
260 InitialTeb.StackCommit += PAGE_SIZE;
263 InitialTeb.StackAllocate = NULL;
264 Status = NtAllocateVirtualMemory(ProcessHandle,
265 &InitialTeb.StackAllocate,
267 &InitialTeb.StackReserve,
270 if (!NT_SUCCESS(Status))
272 DPRINT("Error reserving stack space!\n");
273 SetLastErrorByStatus(Status);
277 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
278 InitialTeb.StackAllocate, InitialTeb.StackReserve);
280 InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
281 InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
283 DPRINT("StackBase: %p StackCommit: %p\n",
284 InitialTeb.StackBase, InitialTeb.StackCommit);
286 /* Commit stack page(s) */
287 Status = NtAllocateVirtualMemory(ProcessHandle,
288 &InitialTeb.StackLimit,
290 &InitialTeb.StackCommit,
293 if (!NT_SUCCESS(Status))
295 /* release the stack space */
296 NtFreeVirtualMemory(ProcessHandle,
297 InitialTeb.StackAllocate,
298 &InitialTeb.StackReserve,
301 DPRINT("Error comitting stack page(s)!\n");
302 SetLastErrorByStatus(Status);
303 return(INVALID_HANDLE_VALUE);
306 DPRINT("StackLimit: %p\n",
307 InitialTeb.StackLimit);
309 /* Protect guard page */
310 Status = NtProtectVirtualMemory(ProcessHandle,
311 InitialTeb.StackLimit,
313 PAGE_GUARD | PAGE_READWRITE,
315 if (!NT_SUCCESS(Status))
317 /* release the stack space */
318 NtFreeVirtualMemory(ProcessHandle,
319 InitialTeb.StackAllocate,
320 &InitialTeb.StackReserve,
323 DPRINT("Error comitting guard page!\n");
324 SetLastErrorByStatus(Status);
325 return(INVALID_HANDLE_VALUE);
328 memset(&ThreadContext,0,sizeof(CONTEXT));
329 ThreadContext.Eip = (ULONG)BaseProcessStart;
330 ThreadContext.SegGs = USER_DS;
331 ThreadContext.SegFs = USER_DS;
332 ThreadContext.SegEs = USER_DS;
333 ThreadContext.SegDs = USER_DS;
334 ThreadContext.SegCs = USER_CS;
335 ThreadContext.SegSs = USER_DS;
336 ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 6*4;
337 ThreadContext.EFlags = (1<<1) + (1<<9);
339 DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
342 * Write in the initial stack.
345 InitialStack[1] = (DWORD)lpStartAddress;
346 InitialStack[2] = PEB_BASE;
348 Status = ZwWriteVirtualMemory(ProcessHandle,
349 (PVOID)ThreadContext.Esp,
351 sizeof(InitialStack),
353 if (!NT_SUCCESS(Status))
355 DPRINT1("Failed to write initial stack.\n");
356 return(INVALID_HANDLE_VALUE);
359 Status = NtCreateThread(&ThreadHandle,
367 if (!NT_SUCCESS(Status))
369 NtFreeVirtualMemory(ProcessHandle,
370 InitialTeb.StackAllocate,
371 &InitialTeb.StackReserve,
373 SetLastErrorByStatus(Status);
374 return(INVALID_HANDLE_VALUE);
377 if (lpThreadId != NULL)
379 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
382 return(ThreadHandle);
386 KlMapFile(LPCWSTR lpApplicationName)
389 IO_STATUS_BLOCK IoStatusBlock;
390 UNICODE_STRING ApplicationNameString;
391 OBJECT_ATTRIBUTES ObjectAttributes;
392 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
399 * Find the application name
402 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpApplicationName,
403 &ApplicationNameString,
408 DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer);
410 InitializeObjectAttributes(&ObjectAttributes,
411 &ApplicationNameString,
412 OBJ_CASE_INSENSITIVE,
417 * Try to open the executable
420 Status = NtOpenFile(&hFile,
421 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
424 FILE_SHARE_DELETE|FILE_SHARE_READ,
425 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
427 RtlFreeUnicodeString (&ApplicationNameString);
429 if (!NT_SUCCESS(Status))
431 DPRINT("Failed to open file\n");
432 SetLastErrorByStatus (Status);
436 Status = NtCreateSection(&hSection,
445 if (!NT_SUCCESS(Status))
447 DPRINT("Failed to create section\n");
448 SetLastErrorByStatus (Status);
456 KlInitPeb (HANDLE ProcessHandle,
457 PRTL_USER_PROCESS_PARAMETERS Ppb,
458 PVOID* ImageBaseAddress)
465 PVOID ParentEnv = NULL;
468 ULONG EnvSize = 0, EnvSize1 = 0;
470 /* create the Environment */
471 if (Ppb->Environment != NULL)
473 ParentEnv = Ppb->Environment;
480 EnvSize = (PVOID)ptr - ParentEnv;
482 else if (NtCurrentPeb()->ProcessParameters->Environment != NULL)
484 MEMORY_BASIC_INFORMATION MemInfo;
485 ParentEnv = NtCurrentPeb()->ProcessParameters->Environment;
487 Status = NtQueryVirtualMemory (NtCurrentProcess (),
489 MemoryBasicInformation,
491 sizeof(MEMORY_BASIC_INFORMATION),
493 if (!NT_SUCCESS(Status))
497 EnvSize = MemInfo.RegionSize;
499 DPRINT("EnvironmentSize %ld\n", EnvSize);
501 /* allocate and initialize new environment block */
505 Status = NtAllocateVirtualMemory(ProcessHandle,
509 MEM_RESERVE | MEM_COMMIT,
511 if (!NT_SUCCESS(Status))
516 NtWriteVirtualMemory(ProcessHandle,
525 PpbSize = Ppb->AllocationSize;
526 Status = NtAllocateVirtualMemory(ProcessHandle,
530 MEM_RESERVE | MEM_COMMIT,
532 if (!NT_SUCCESS(Status))
537 DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
538 NtWriteVirtualMemory(ProcessHandle,
544 /* write pointer to environment */
545 Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
546 NtWriteVirtualMemory(ProcessHandle,
547 (PVOID)(PpbBase + Offset),
552 /* write pointer to process parameter block */
553 Offset = FIELD_OFFSET(PEB, ProcessParameters);
554 NtWriteVirtualMemory(ProcessHandle,
555 (PVOID)(PEB_BASE + Offset),
560 /* Read image base address. */
561 Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
562 NtReadVirtualMemory(ProcessHandle,
563 (PVOID)(PEB_BASE + Offset),
568 return(STATUS_SUCCESS);
573 CreateProcessW(LPCWSTR lpApplicationName,
574 LPWSTR lpCommandLine,
575 LPSECURITY_ATTRIBUTES lpProcessAttributes,
576 LPSECURITY_ATTRIBUTES lpThreadAttributes,
577 WINBOOL bInheritHandles,
578 DWORD dwCreationFlags,
579 LPVOID lpEnvironment,
580 LPCWSTR lpCurrentDirectory,
581 LPSTARTUPINFOW lpStartupInfo,
582 LPPROCESS_INFORMATION lpProcessInformation)
584 HANDLE hSection, hProcess, hThread;
586 LPTHREAD_START_ROUTINE lpStartAddress = NULL;
587 WCHAR ImagePathName[256];
588 UNICODE_STRING ImagePathName_U;
589 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
591 PRTL_USER_PROCESS_PARAMETERS Ppb;
592 UNICODE_STRING CommandLine_U;
593 CSRSS_API_REQUEST CsrRequest;
594 CSRSS_API_REPLY CsrReply;
595 CHAR ImageFileName[8];
598 ANSI_STRING ProcedureName;
599 UNICODE_STRING CurrentDirectory_U;
600 SECTION_IMAGE_INFORMATION Sii;
601 WCHAR TempCurrentDirectoryW[256];
602 WCHAR TempApplicationNameW[256];
603 WCHAR TempCommandLineNameW[256];
604 UNICODE_STRING RuntimeInfo_U;
605 PVOID ImageBaseAddress;
607 DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
608 lpApplicationName, lpCommandLine);
610 if (lpApplicationName != NULL && lpApplicationName[0] != 0)
612 wcscpy (TempApplicationNameW, lpApplicationName);
613 i = wcslen(TempApplicationNameW);
614 if (TempApplicationNameW[i - 1] == L'.')
616 TempApplicationNameW[i - 1] = 0;
620 s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/'));
623 s = TempApplicationNameW;
629 e = wcsrchr(s, L'.');
633 e = wcsrchr(s, L'.');
637 else if (lpCommandLine != NULL && lpCommandLine[0] != 0)
639 if (lpCommandLine[0] == L'"')
641 wcscpy(TempApplicationNameW, &lpCommandLine[0]);
642 s = wcschr(TempApplicationNameW, L'"');
651 wcscpy(TempApplicationNameW, lpCommandLine);
652 s = wcschr(TempApplicationNameW, L' ');
658 s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/'));
661 s = TempApplicationNameW;
663 s = wcsrchr(s, L'.');
665 wcscat(TempApplicationNameW, L".exe");
672 if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
677 e = wcsrchr(s, L'.');
678 if (e != NULL && (!_wcsicmp(e, L".bat") || !_wcsicmp(e, L".cmd")))
680 // the command is a batch file
681 if (lpApplicationName != NULL && lpApplicationName[0])
683 // FIXME: use COMSPEC for the command interpreter
684 wcscpy(TempCommandLineNameW, L"cmd /c ");
685 wcscat(TempCommandLineNameW, lpApplicationName);
686 lpCommandLine = TempCommandLineNameW;
687 wcscpy(TempApplicationNameW, L"cmd.exe");
688 if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
700 * Store the image file name for the process
707 for (i = 0; i < 8; i++)
709 ImageFileName[i] = (CHAR)(s[i]);
717 * Process the application name and command line
719 RtlInitUnicodeString(&ImagePathName_U, ImagePathName);
720 RtlInitUnicodeString(&CommandLine_U, lpCommandLine);
722 DPRINT("ImagePathName_U %S\n", ImagePathName_U.Buffer);
723 DPRINT("CommandLine_U %S\n", CommandLine_U.Buffer);
725 /* Initialize the current directory string */
726 if (lpCurrentDirectory != NULL)
728 RtlInitUnicodeString(&CurrentDirectory_U,
733 GetCurrentDirectoryW(256, TempCurrentDirectoryW);
734 RtlInitUnicodeString(&CurrentDirectory_U,
735 TempCurrentDirectoryW);
740 * Create a section for the executable
743 hSection = KlMapFile (ImagePathName);
744 if (hSection == NULL)
750 * Create a new process
752 Status = NtCreateProcess(&hProcess,
762 if (lpStartupInfo->lpReserved2)
764 ULONG i, Count = *(ULONG*)lpStartupInfo->lpReserved2;
767 PRTL_USER_PROCESS_PARAMETERS CurrPpb = NtCurrentPeb()->ProcessParameters;
771 * ROUND_UP(xxx,2) + 2 is a dirty hack. RtlCreateProcessParameters assumes that
772 * the runtimeinfo is a unicode string and use RtlCopyUnicodeString for duplication.
773 * If is possible that this function overwrite the last information in runtimeinfo
774 * with the null terminator for the unicode string.
776 RuntimeInfo_U.Length = RuntimeInfo_U.MaximumLength = ROUND_UP(lpStartupInfo->cbReserved2, 2) + 2;
777 RuntimeInfo_U.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, RuntimeInfo_U.Length);
778 memcpy(RuntimeInfo_U.Buffer, lpStartupInfo->lpReserved2, lpStartupInfo->cbReserved2);
785 RtlCreateProcessParameters(&Ppb,
788 lpCurrentDirectory ? &CurrentDirectory_U : NULL,
794 lpStartupInfo && lpStartupInfo->lpReserved2 ? &RuntimeInfo_U : NULL);
796 if (lpStartupInfo && lpStartupInfo->lpReserved2)
797 RtlFreeHeap(GetProcessHeap(), 0, RuntimeInfo_U.Buffer);
801 * Translate some handles for the new process
803 if (Ppb->CurrentDirectoryHandle)
805 Status = NtDuplicateObject (NtCurrentProcess(),
806 Ppb->CurrentDirectoryHandle,
808 &Ppb->CurrentDirectoryHandle,
811 DUPLICATE_SAME_ACCESS);
816 Status = NtDuplicateObject (NtCurrentProcess(),
822 DUPLICATE_SAME_ACCESS);
826 * Get some information about the executable
828 Status = ZwQuerySection(hSection,
829 SectionImageInformation,
839 * Get some information about the process
841 ZwQueryInformationProcess(hProcess,
842 ProcessBasicInformation,
844 sizeof(ProcessBasicInfo),
846 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
847 ProcessBasicInfo.UniqueProcessId);
848 lpProcessInformation->dwProcessId = ProcessBasicInfo.UniqueProcessId;
851 * Tell the csrss server we are creating a new process
853 CsrRequest.Type = CSRSS_CREATE_PROCESS;
854 CsrRequest.Data.CreateProcessRequest.NewProcessId =
855 ProcessBasicInfo.UniqueProcessId;
856 CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
857 Status = CsrClientCallServer(&CsrRequest,
859 sizeof(CSRSS_API_REQUEST),
860 sizeof(CSRSS_API_REPLY));
861 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
863 DbgPrint("Failed to tell csrss about new process. Expect trouble.\n");
866 // Set the child console handles
867 Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
868 Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
869 Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
871 if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
873 if (lpStartupInfo->hStdInput)
874 Ppb->hStdInput = lpStartupInfo->hStdInput;
875 if (lpStartupInfo->hStdOutput)
876 Ppb->hStdOutput = lpStartupInfo->hStdOutput;
877 if (lpStartupInfo->hStdError)
878 Ppb->hStdError = lpStartupInfo->hStdError;
881 if (IsConsoleHandle(Ppb->hStdInput))
883 Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
887 DPRINT("Duplicate input handle\n");
888 Status = NtDuplicateObject (NtCurrentProcess(),
894 DUPLICATE_SAME_ACCESS);
895 if(!NT_SUCCESS(Status))
897 DPRINT("NtDuplicateObject failed, status %x\n", Status);
901 if (IsConsoleHandle(Ppb->hStdOutput))
903 Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
907 DPRINT("Duplicate output handle\n");
908 Status = NtDuplicateObject (NtCurrentProcess(),
914 DUPLICATE_SAME_ACCESS);
915 if(!NT_SUCCESS(Status))
917 DPRINT("NtDuplicateObject failed, status %x\n", Status);
920 if (IsConsoleHandle(Ppb->hStdError))
922 Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;
926 DPRINT("Duplicate error handle\n");
927 Status = NtDuplicateObject (NtCurrentProcess(),
933 DUPLICATE_SAME_ACCESS);
934 if(!NT_SUCCESS(Status))
936 DPRINT("NtDuplicateObject failed, status %x\n", Status);
941 * Initialize some other fields in the PPB
945 Ppb->dwFlags = lpStartupInfo->dwFlags;
946 if (Ppb->dwFlags & STARTF_USESHOWWINDOW)
948 Ppb->wShowWindow = lpStartupInfo->wShowWindow;
952 Ppb->wShowWindow = SW_SHOWDEFAULT;
954 Ppb->dwX = lpStartupInfo->dwX;
955 Ppb->dwY = lpStartupInfo->dwY;
956 Ppb->dwXSize = lpStartupInfo->dwXSize;
957 Ppb->dwYSize = lpStartupInfo->dwYSize;
958 Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute;
966 * Create Process Environment Block
968 DPRINT("Creating peb\n");
970 KlInitPeb(hProcess, Ppb, &ImageBaseAddress);
972 RtlDestroyProcessParameters (Ppb);
974 Status = NtSetInformationProcess(hProcess,
975 ProcessImageFileName,
979 * Create the thread for the kernel
981 DPRINT("Creating thread for process\n");
982 hThread = KlCreateFirstThread(hProcess,
986 ImageBaseAddress + (ULONG)Sii.EntryPoint,
988 &lpProcessInformation->dwThreadId);
989 if (hThread == INVALID_HANDLE_VALUE)
994 lpProcessInformation->hProcess = hProcess;
995 lpProcessInformation->hThread = hThread;