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 ****************************************************************/
17 #include <kernel32/kernel32.h>
19 /* FUNCTIONS ****************************************************************/
22 CreateProcessA (LPCSTR lpApplicationName,
24 LPSECURITY_ATTRIBUTES lpProcessAttributes,
25 LPSECURITY_ATTRIBUTES lpThreadAttributes,
26 WINBOOL bInheritHandles,
27 DWORD dwCreationFlags,
29 LPCSTR lpCurrentDirectory,
30 LPSTARTUPINFOA lpStartupInfo,
31 LPPROCESS_INFORMATION lpProcessInformation)
33 * FUNCTION: The CreateProcess function creates a new process and its
34 * primary thread. The new process executes the specified executable file
37 * lpApplicationName = Pointer to name of executable module
38 * lpCommandLine = Pointer to command line string
39 * lpProcessAttributes = Process security attributes
40 * lpThreadAttributes = Thread security attributes
41 * bInheritHandles = Handle inheritance flag
42 * dwCreationFlags = Creation flags
43 * lpEnvironment = Pointer to new environment block
44 * lpCurrentDirectory = Pointer to current directory name
45 * lpStartupInfo = Pointer to startup info
46 * lpProcessInformation = Pointer to process information
49 PWCHAR lpEnvironmentW = NULL;
50 UNICODE_STRING ApplicationNameU;
51 UNICODE_STRING CurrentDirectoryU;
52 UNICODE_STRING CommandLineU;
53 ANSI_STRING ApplicationName;
54 ANSI_STRING CurrentDirectory;
55 ANSI_STRING CommandLine;
57 CHAR TempCurrentDirectoryA[256];
59 DPRINT("CreateProcessA(%s)\n", lpApplicationName);
60 DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, "
61 "lpStartupInfo %x, lpProcessInformation %x\n", dwCreationFlags,
62 lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
64 if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT))
66 PCHAR ptr = lpEnvironment;
68 UNICODE_STRING EnvironmentU;
69 ANSI_STRING EnvironmentA;
72 RtlInitAnsiString(&EnvironmentA, ptr);
74 len += RtlAnsiStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR);
76 len += RtlOemStringToUnicodeSize(&EnvironmentA) + sizeof(WCHAR);
77 ptr += EnvironmentA.MaximumLength;
80 lpEnvironmentW = (PWCHAR)RtlAllocateHeap(GetProcessHeap(),
81 HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,
83 if (lpEnvironmentW == NULL)
88 EnvironmentU.Buffer = lpEnvironmentW;
89 EnvironmentU.Length = 0;
90 EnvironmentU.MaximumLength = len;
93 RtlInitAnsiString(&EnvironmentA, ptr);
95 RtlAnsiStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE);
97 RtlOemStringToUnicodeString(&EnvironmentU, &EnvironmentA, FALSE);
98 ptr += EnvironmentA.MaximumLength;
99 EnvironmentU.Buffer += (EnvironmentU.Length / sizeof(WCHAR) + 1);
100 EnvironmentU.MaximumLength -= (EnvironmentU.Length + sizeof(WCHAR));
101 EnvironmentU.Length = 0;
104 EnvironmentU.Buffer[0] = 0;
107 RtlInitAnsiString (&CommandLine,
109 RtlInitAnsiString (&ApplicationName,
110 (LPSTR)lpApplicationName);
111 if (lpCurrentDirectory != NULL)
113 RtlInitAnsiString (&CurrentDirectory,
114 (LPSTR)lpCurrentDirectory);
117 /* convert ansi (or oem) strings to unicode */
120 RtlAnsiStringToUnicodeString (&CommandLineU, &CommandLine, TRUE);
121 RtlAnsiStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE);
122 if (lpCurrentDirectory != NULL)
123 RtlAnsiStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE);
127 RtlOemStringToUnicodeString (&CommandLineU, &CommandLine, TRUE);
128 RtlOemStringToUnicodeString (&ApplicationNameU, &ApplicationName, TRUE);
129 if (lpCurrentDirectory != NULL)
130 RtlOemStringToUnicodeString (&CurrentDirectoryU, &CurrentDirectory, TRUE);
133 Result = CreateProcessW (ApplicationNameU.Buffer,
139 dwCreationFlags & CREATE_UNICODE_ENVIRONMENT ? lpEnvironment : lpEnvironmentW,
140 (lpCurrentDirectory == NULL) ? NULL : CurrentDirectoryU.Buffer,
141 (LPSTARTUPINFOW)lpStartupInfo,
142 lpProcessInformation);
144 RtlFreeUnicodeString (&ApplicationNameU);
145 RtlFreeUnicodeString (&CommandLineU);
146 if (lpCurrentDirectory != NULL)
147 RtlFreeUnicodeString (&CurrentDirectoryU);
151 RtlFreeHeap(GetProcessHeap(), 0, lpEnvironmentW);
157 static int _except_recursion_trap = 0;
160 struct __EXCEPTION_RECORD;
163 EXCEPTION_DISPOSITION
166 struct _EXCEPTION_RECORD *ExceptionRecord,
167 void * EstablisherFrame,
168 struct _CONTEXT *ContextRecord,
169 void * DispatcherContext )
171 DPRINT("Process terminated abnormally...\n");
173 if (++_except_recursion_trap > 3) {
174 DPRINT("_except_handler(...) appears to be recursing.\n");
175 DPRINT("Process HALTED.\n");
179 if (/* FIXME: */ TRUE) /* Not a service */
181 DPRINT(" calling ExitProcess(0) no, lets try ExitThread . . .\n");
187 DPRINT(" calling ExitThread(0) . . .\n");
191 DPRINT(" We should not get to here !!!\n");
192 /* We should not get to here */
193 return ExceptionContinueSearch;
197 BaseProcessStart(LPTHREAD_START_ROUTINE lpStartAddress,
202 DPRINT("\nBaseProcessStart(..) - setting up exception frame.\n\n");
204 __try1(_except_handler)
206 uExitCode = (lpStartAddress)((PVOID)lpParameter);
211 DPRINT("\nBaseProcessStart(..) - cleaned up exception frame.\n\n");
213 ExitThread(uExitCode);
218 KlCreateFirstThread(HANDLE ProcessHandle,
219 LPSECURITY_ATTRIBUTES lpThreadAttributes,
222 LPTHREAD_START_ROUTINE lpStartAddress,
223 DWORD dwCreationFlags,
228 OBJECT_ATTRIBUTES ObjectAttributes;
230 CONTEXT ThreadContext;
231 INITIAL_TEB InitialTeb;
232 BOOLEAN CreateSuspended = FALSE;
233 ULONG OldPageProtection;
235 ULONG InitialStack[6];
237 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
238 ObjectAttributes.RootDirectory = NULL;
239 ObjectAttributes.ObjectName = NULL;
240 ObjectAttributes.Attributes = 0;
241 if (lpThreadAttributes != NULL)
243 if (lpThreadAttributes->bInheritHandle)
244 ObjectAttributes.Attributes = OBJ_INHERIT;
245 ObjectAttributes.SecurityDescriptor =
246 lpThreadAttributes->lpSecurityDescriptor;
248 ObjectAttributes.SecurityQualityOfService = NULL;
250 if ((dwCreationFlags & CREATE_SUSPENDED) == CREATE_SUSPENDED)
251 CreateSuspended = TRUE;
253 CreateSuspended = FALSE;
255 InitialTeb.StackReserve = (StackReserve < 0x100000) ? 0x100000 : StackReserve;
256 /* FIXME: use correct commit size */
258 InitialTeb.StackCommit = (StackCommit < PAGE_SIZE) ? PAGE_SIZE : StackCommit;
260 InitialTeb.StackCommit = InitialTeb.StackReserve - PAGE_SIZE;
262 /* size of guard page */
263 InitialTeb.StackCommit += PAGE_SIZE;
266 InitialTeb.StackAllocate = NULL;
267 Status = NtAllocateVirtualMemory(ProcessHandle,
268 &InitialTeb.StackAllocate,
270 &InitialTeb.StackReserve,
273 if (!NT_SUCCESS(Status))
275 DPRINT("Error reserving stack space!\n");
276 SetLastErrorByStatus(Status);
280 DPRINT("StackAllocate: %p ReserveSize: 0x%lX\n",
281 InitialTeb.StackAllocate, InitialTeb.StackReserve);
283 InitialTeb.StackBase = (PVOID)((ULONG)InitialTeb.StackAllocate + InitialTeb.StackReserve);
284 InitialTeb.StackLimit = (PVOID)((ULONG)InitialTeb.StackBase - InitialTeb.StackCommit);
286 DPRINT("StackBase: %p StackCommit: %p\n",
287 InitialTeb.StackBase, InitialTeb.StackCommit);
289 /* Commit stack page(s) */
290 Status = NtAllocateVirtualMemory(ProcessHandle,
291 &InitialTeb.StackLimit,
293 &InitialTeb.StackCommit,
296 if (!NT_SUCCESS(Status))
298 /* release the stack space */
299 NtFreeVirtualMemory(ProcessHandle,
300 InitialTeb.StackAllocate,
301 &InitialTeb.StackReserve,
304 DPRINT("Error comitting stack page(s)!\n");
305 SetLastErrorByStatus(Status);
306 return(INVALID_HANDLE_VALUE);
309 DPRINT("StackLimit: %p\n",
310 InitialTeb.StackLimit);
312 /* Protect guard page */
313 Status = NtProtectVirtualMemory(ProcessHandle,
314 InitialTeb.StackLimit,
316 PAGE_GUARD | PAGE_READWRITE,
318 if (!NT_SUCCESS(Status))
320 /* release the stack space */
321 NtFreeVirtualMemory(ProcessHandle,
322 InitialTeb.StackAllocate,
323 &InitialTeb.StackReserve,
326 DPRINT("Error comitting guard page!\n");
327 SetLastErrorByStatus(Status);
328 return(INVALID_HANDLE_VALUE);
331 memset(&ThreadContext,0,sizeof(CONTEXT));
332 ThreadContext.Eip = (ULONG)BaseProcessStart;
333 ThreadContext.SegGs = USER_DS;
334 ThreadContext.SegFs = USER_DS;
335 ThreadContext.SegEs = USER_DS;
336 ThreadContext.SegDs = USER_DS;
337 ThreadContext.SegCs = USER_CS;
338 ThreadContext.SegSs = USER_DS;
339 ThreadContext.Esp = (ULONG)InitialTeb.StackBase - 6*4;
340 ThreadContext.EFlags = (1<<1) + (1<<9);
342 DPRINT("ThreadContext.Eip %x\n",ThreadContext.Eip);
345 * Write in the initial stack.
348 InitialStack[1] = (DWORD)lpStartAddress;
349 InitialStack[2] = PEB_BASE;
351 Status = ZwWriteVirtualMemory(ProcessHandle,
352 (PVOID)ThreadContext.Esp,
354 sizeof(InitialStack),
356 if (!NT_SUCCESS(Status))
358 DPRINT1("Failed to write initial stack.\n");
359 return(INVALID_HANDLE_VALUE);
362 Status = NtCreateThread(&ThreadHandle,
370 if (!NT_SUCCESS(Status))
372 NtFreeVirtualMemory(ProcessHandle,
373 InitialTeb.StackAllocate,
374 &InitialTeb.StackReserve,
376 SetLastErrorByStatus(Status);
377 return(INVALID_HANDLE_VALUE);
380 if (lpThreadId != NULL)
382 memcpy(lpThreadId, &ClientId.UniqueThread,sizeof(ULONG));
385 return(ThreadHandle);
389 KlMapFile(LPCWSTR lpApplicationName)
392 IO_STATUS_BLOCK IoStatusBlock;
393 UNICODE_STRING ApplicationNameString;
394 OBJECT_ATTRIBUTES ObjectAttributes;
395 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
402 * Find the application name
405 if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpApplicationName,
406 &ApplicationNameString,
411 DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer);
413 InitializeObjectAttributes(&ObjectAttributes,
414 &ApplicationNameString,
415 OBJ_CASE_INSENSITIVE,
420 * Try to open the executable
423 Status = NtOpenFile(&hFile,
424 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
427 FILE_SHARE_DELETE|FILE_SHARE_READ,
428 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
430 RtlFreeUnicodeString (&ApplicationNameString);
432 if (!NT_SUCCESS(Status))
434 DPRINT("Failed to open file\n");
435 SetLastErrorByStatus (Status);
439 Status = NtCreateSection(&hSection,
448 if (!NT_SUCCESS(Status))
450 DPRINT("Failed to create section\n");
451 SetLastErrorByStatus (Status);
459 KlInitPeb (HANDLE ProcessHandle,
460 PRTL_USER_PROCESS_PARAMETERS Ppb,
461 PVOID* ImageBaseAddress)
468 PVOID ParentEnv = NULL;
471 ULONG EnvSize = 0, EnvSize1 = 0;
473 /* create the Environment */
474 if (Ppb->Environment != NULL)
476 ParentEnv = Ppb->Environment;
483 EnvSize = (PVOID)ptr - ParentEnv;
485 else if (NtCurrentPeb()->ProcessParameters->Environment != NULL)
487 MEMORY_BASIC_INFORMATION MemInfo;
488 ParentEnv = NtCurrentPeb()->ProcessParameters->Environment;
490 Status = NtQueryVirtualMemory (NtCurrentProcess (),
492 MemoryBasicInformation,
494 sizeof(MEMORY_BASIC_INFORMATION),
496 if (!NT_SUCCESS(Status))
500 EnvSize = MemInfo.RegionSize;
502 DPRINT("EnvironmentSize %ld\n", EnvSize);
504 /* allocate and initialize new environment block */
508 Status = NtAllocateVirtualMemory(ProcessHandle,
512 MEM_RESERVE | MEM_COMMIT,
514 if (!NT_SUCCESS(Status))
519 NtWriteVirtualMemory(ProcessHandle,
528 PpbSize = Ppb->AllocationSize;
529 Status = NtAllocateVirtualMemory(ProcessHandle,
533 MEM_RESERVE | MEM_COMMIT,
535 if (!NT_SUCCESS(Status))
540 //DPRINT("Ppb->MaximumLength %x\n", Ppb->MaximumLength);
541 NtWriteVirtualMemory(ProcessHandle,
547 /* write pointer to environment */
548 Offset = FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS, Environment);
549 NtWriteVirtualMemory(ProcessHandle,
550 (PVOID)(PpbBase + Offset),
555 /* write pointer to process parameter block */
556 Offset = FIELD_OFFSET(PEB, ProcessParameters);
557 NtWriteVirtualMemory(ProcessHandle,
558 (PVOID)(PEB_BASE + Offset),
563 /* Read image base address. */
564 Offset = FIELD_OFFSET(PEB, ImageBaseAddress);
565 NtReadVirtualMemory(ProcessHandle,
566 (PVOID)(PEB_BASE + Offset),
571 return(STATUS_SUCCESS);
576 CreateProcessW(LPCWSTR lpApplicationName,
577 LPWSTR lpCommandLine,
578 LPSECURITY_ATTRIBUTES lpProcessAttributes,
579 LPSECURITY_ATTRIBUTES lpThreadAttributes,
580 WINBOOL bInheritHandles,
581 DWORD dwCreationFlags,
582 LPVOID lpEnvironment,
583 LPCWSTR lpCurrentDirectory,
584 LPSTARTUPINFOW lpStartupInfo,
585 LPPROCESS_INFORMATION lpProcessInformation)
587 HANDLE hSection, hProcess, hThread;
589 LPTHREAD_START_ROUTINE lpStartAddress = NULL;
590 WCHAR ImagePathName[256];
591 UNICODE_STRING ImagePathName_U;
592 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
594 PRTL_USER_PROCESS_PARAMETERS Ppb;
595 UNICODE_STRING CommandLine_U;
596 CSRSS_API_REQUEST CsrRequest;
597 CSRSS_API_REPLY CsrReply;
598 CHAR ImageFileName[8];
601 ANSI_STRING ProcedureName;
602 UNICODE_STRING CurrentDirectory_U;
603 SECTION_IMAGE_INFORMATION Sii;
604 WCHAR TempCurrentDirectoryW[256];
605 WCHAR TempApplicationNameW[256];
606 WCHAR TempCommandLineNameW[256];
607 UNICODE_STRING RuntimeInfo_U;
608 PVOID ImageBaseAddress;
610 DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
611 lpApplicationName, lpCommandLine);
613 if (lpApplicationName != NULL && lpApplicationName[0] != 0)
615 wcscpy (TempApplicationNameW, lpApplicationName);
616 i = wcslen(TempApplicationNameW);
617 if (TempApplicationNameW[i - 1] == L'.')
619 TempApplicationNameW[i - 1] = 0;
623 s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/'));
626 s = TempApplicationNameW;
632 e = wcsrchr(s, L'.');
636 e = wcsrchr(s, L'.');
640 else if (lpCommandLine != NULL && lpCommandLine[0] != 0)
642 if (lpCommandLine[0] == L'"')
644 wcscpy(TempApplicationNameW, &lpCommandLine[0]);
645 s = wcschr(TempApplicationNameW, L'"');
654 wcscpy(TempApplicationNameW, lpCommandLine);
655 s = wcschr(TempApplicationNameW, L' ');
661 s = max(wcsrchr(TempApplicationNameW, L'\\'), wcsrchr(TempApplicationNameW, L'/'));
664 s = TempApplicationNameW;
666 s = wcsrchr(s, L'.');
668 wcscat(TempApplicationNameW, L".exe");
675 if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
680 e = wcsrchr(s, L'.');
681 if (e != NULL && (!_wcsicmp(e, L".bat") || !_wcsicmp(e, L".cmd")))
683 // the command is a batch file
684 if (lpApplicationName != NULL && lpApplicationName[0])
686 // FIXME: use COMSPEC for the command interpreter
687 wcscpy(TempCommandLineNameW, L"cmd /c ");
688 wcscat(TempCommandLineNameW, lpApplicationName);
689 lpCommandLine = TempCommandLineNameW;
690 wcscpy(TempApplicationNameW, L"cmd.exe");
691 if (!SearchPathW(NULL, TempApplicationNameW, NULL, sizeof(ImagePathName), ImagePathName, &s))
703 * Store the image file name for the process
710 for (i = 0; i < 8; i++)
712 ImageFileName[i] = (CHAR)(s[i]);
720 * Process the application name and command line
722 RtlInitUnicodeString(&ImagePathName_U, ImagePathName);
723 RtlInitUnicodeString(&CommandLine_U, lpCommandLine);
725 DPRINT("ImagePathName_U %S\n", ImagePathName_U.Buffer);
726 DPRINT("CommandLine_U %S\n", CommandLine_U.Buffer);
728 /* Initialize the current directory string */
729 if (lpCurrentDirectory != NULL)
731 RtlInitUnicodeString(&CurrentDirectory_U,
736 GetCurrentDirectoryW(256, TempCurrentDirectoryW);
737 RtlInitUnicodeString(&CurrentDirectory_U,
738 TempCurrentDirectoryW);
743 * Create a section for the executable
746 hSection = KlMapFile (ImagePathName);
747 if (hSection == NULL)
749 /////////////////////////////////////////
751 * Inspect the image to determine executable flavour
753 IO_STATUS_BLOCK IoStatusBlock;
754 UNICODE_STRING ApplicationNameString;
755 OBJECT_ATTRIBUTES ObjectAttributes;
756 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
757 IMAGE_DOS_HEADER DosHeader;
758 IO_STATUS_BLOCK Iosb;
759 LARGE_INTEGER Offset;
762 DPRINT("Inspecting Image Header for image type id\n");
764 // Find the application name
765 if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpApplicationName,
766 &ApplicationNameString, NULL, NULL)) {
769 DPRINT("ApplicationName %S\n",ApplicationNameString.Buffer);
771 InitializeObjectAttributes(&ObjectAttributes,
772 &ApplicationNameString,
773 OBJ_CASE_INSENSITIVE,
777 // Try to open the executable
778 Status = NtOpenFile(&hFile,
779 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
782 FILE_SHARE_DELETE|FILE_SHARE_READ,
783 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
785 RtlFreeUnicodeString(&ApplicationNameString);
787 if (!NT_SUCCESS(Status)) {
788 DPRINT("Failed to open file\n");
789 SetLastErrorByStatus(Status);
793 // Read the dos header
795 Status = ZwReadFile(hFile,
805 if (!NT_SUCCESS(Status)) {
806 DPRINT("Failed to read from file\n");
807 SetLastErrorByStatus(Status);
810 if (Iosb.Information != sizeof(DosHeader)) {
811 DPRINT("Failed to read dos header from file\n");
812 SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
816 // Check the DOS signature
817 if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
818 DPRINT("Failed dos magic check\n");
819 SetLastErrorByStatus(STATUS_INVALID_IMAGE_FORMAT);
824 DPRINT("Launching VDM...\n");
825 return CreateProcessW(L"ntvdm.exe",
826 (LPWSTR)lpApplicationName,
834 lpProcessInformation);
836 /////////////////////////////////////////
838 * Create a new process
840 Status = NtCreateProcess(&hProcess,
850 if (lpStartupInfo->lpReserved2)
852 ULONG i, Count = *(ULONG*)lpStartupInfo->lpReserved2;
855 PRTL_USER_PROCESS_PARAMETERS CurrPpb = NtCurrentPeb()->ProcessParameters;
859 * ROUND_UP(xxx,2) + 2 is a dirty hack. RtlCreateProcessParameters assumes that
860 * the runtimeinfo is a unicode string and use RtlCopyUnicodeString for duplication.
861 * If is possible that this function overwrite the last information in runtimeinfo
862 * with the null terminator for the unicode string.
864 RuntimeInfo_U.Length = RuntimeInfo_U.MaximumLength = ROUND_UP(lpStartupInfo->cbReserved2, 2) + 2;
865 RuntimeInfo_U.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, RuntimeInfo_U.Length);
866 memcpy(RuntimeInfo_U.Buffer, lpStartupInfo->lpReserved2, lpStartupInfo->cbReserved2);
873 RtlCreateProcessParameters(&Ppb,
876 lpCurrentDirectory ? &CurrentDirectory_U : NULL,
882 lpStartupInfo && lpStartupInfo->lpReserved2 ? &RuntimeInfo_U : NULL);
884 if (lpStartupInfo && lpStartupInfo->lpReserved2)
885 RtlFreeHeap(GetProcessHeap(), 0, RuntimeInfo_U.Buffer);
889 * Translate some handles for the new process
891 if (Ppb->CurrentDirectoryHandle)
893 Status = NtDuplicateObject (NtCurrentProcess(),
894 Ppb->CurrentDirectoryHandle,
896 &Ppb->CurrentDirectoryHandle,
899 DUPLICATE_SAME_ACCESS);
904 Status = NtDuplicateObject (NtCurrentProcess(),
910 DUPLICATE_SAME_ACCESS);
914 * Get some information about the executable
916 Status = ZwQuerySection(hSection,
917 SectionImageInformation,
927 * Get some information about the process
929 ZwQueryInformationProcess(hProcess,
930 ProcessBasicInformation,
932 sizeof(ProcessBasicInfo),
934 DPRINT("ProcessBasicInfo.UniqueProcessId %d\n",
935 ProcessBasicInfo.UniqueProcessId);
936 lpProcessInformation->dwProcessId = ProcessBasicInfo.UniqueProcessId;
939 * Tell the csrss server we are creating a new process
941 CsrRequest.Type = CSRSS_CREATE_PROCESS;
942 CsrRequest.Data.CreateProcessRequest.NewProcessId =
943 ProcessBasicInfo.UniqueProcessId;
944 CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
945 Status = CsrClientCallServer(&CsrRequest,
947 sizeof(CSRSS_API_REQUEST),
948 sizeof(CSRSS_API_REPLY));
949 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
951 DbgPrint("Failed to tell csrss about new process. Expect trouble.\n");
954 // Set the child console handles
955 Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
956 Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
957 Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
959 if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
961 if (lpStartupInfo->hStdInput)
962 Ppb->hStdInput = lpStartupInfo->hStdInput;
963 if (lpStartupInfo->hStdOutput)
964 Ppb->hStdOutput = lpStartupInfo->hStdOutput;
965 if (lpStartupInfo->hStdError)
966 Ppb->hStdError = lpStartupInfo->hStdError;
969 if (IsConsoleHandle(Ppb->hStdInput))
971 Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
975 DPRINT("Duplicate input handle\n");
976 Status = NtDuplicateObject (NtCurrentProcess(),
982 DUPLICATE_SAME_ACCESS);
983 if(!NT_SUCCESS(Status))
985 DPRINT("NtDuplicateObject failed, status %x\n", Status);
989 if (IsConsoleHandle(Ppb->hStdOutput))
991 Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
995 DPRINT("Duplicate output handle\n");
996 Status = NtDuplicateObject (NtCurrentProcess(),
1002 DUPLICATE_SAME_ACCESS);
1003 if(!NT_SUCCESS(Status))
1005 DPRINT("NtDuplicateObject failed, status %x\n", Status);
1008 if (IsConsoleHandle(Ppb->hStdError))
1010 Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;
1014 DPRINT("Duplicate error handle\n");
1015 Status = NtDuplicateObject (NtCurrentProcess(),
1021 DUPLICATE_SAME_ACCESS);
1022 if(!NT_SUCCESS(Status))
1024 DPRINT("NtDuplicateObject failed, status %x\n", Status);
1029 * Initialize some other fields in the PPB
1033 Ppb->dwFlags = lpStartupInfo->dwFlags;
1034 if (Ppb->dwFlags & STARTF_USESHOWWINDOW)
1036 Ppb->wShowWindow = lpStartupInfo->wShowWindow;
1040 Ppb->wShowWindow = SW_SHOWDEFAULT;
1042 Ppb->dwX = lpStartupInfo->dwX;
1043 Ppb->dwY = lpStartupInfo->dwY;
1044 Ppb->dwXSize = lpStartupInfo->dwXSize;
1045 Ppb->dwYSize = lpStartupInfo->dwYSize;
1046 Ppb->dwFillAttribute = lpStartupInfo->dwFillAttribute;
1054 * Create Process Environment Block
1056 DPRINT("Creating peb\n");
1058 KlInitPeb(hProcess, Ppb, &ImageBaseAddress);
1060 RtlDestroyProcessParameters (Ppb);
1062 Status = NtSetInformationProcess(hProcess,
1063 ProcessImageFileName,
1067 * Create the thread for the kernel
1069 DPRINT("Creating thread for process\n");
1070 hThread = KlCreateFirstThread(hProcess,
1074 ImageBaseAddress + (ULONG)Sii.EntryPoint,
1076 &lpProcessInformation->dwThreadId);
1077 if (hThread == INVALID_HANDLE_VALUE)
1082 lpProcessInformation->hProcess = hProcess;
1083 lpProcessInformation->hThread = hThread;