3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/proc/proc.c
6 * PURPOSE: Process functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
12 /* INCLUDES ****************************************************************/
19 typedef INT (WINAPI
*MessageBoxW_Proc
) (HWND
, LPCWSTR
, LPCWSTR
, UINT
);
21 /* GLOBALS *******************************************************************/
23 static UNICODE_STRING CommandLineStringW
;
24 static ANSI_STRING CommandLineStringA
;
25 UNICODE_STRING BasePathVariableName
= RTL_CONSTANT_STRING(L
"PATH");
27 static BOOL bCommandLineInitialized
= FALSE
;
29 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle
;
31 LPSTARTUPINFOA lpLocalStartupInfo
= NULL
;
34 RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle
);
36 PLDR_DATA_TABLE_ENTRY BasepExeLdrEntry
;
38 #define CMD_STRING L"cmd /c "
40 extern __declspec(noreturn
)
43 ConsoleControlDispatcher(DWORD CodeAndFlag
);
45 /* FUNCTIONS ****************************************************************/
48 LONG
BaseExceptionFilter(EXCEPTION_POINTERS
*ExceptionInfo
)
50 LONG ExceptionDisposition
= EXCEPTION_EXECUTE_HANDLER
;
51 LPTOP_LEVEL_EXCEPTION_FILTER RealFilter
;
52 RealFilter
= RtlDecodePointer(GlobalTopLevelExceptionFilter
);
54 if (RealFilter
!= NULL
)
58 ExceptionDisposition
= RealFilter(ExceptionInfo
);
60 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
65 if ((ExceptionDisposition
== EXCEPTION_CONTINUE_SEARCH
|| ExceptionDisposition
== EXCEPTION_EXECUTE_HANDLER
) &&
66 RealFilter
!= UnhandledExceptionFilter
)
68 ExceptionDisposition
= UnhandledExceptionFilter(ExceptionInfo
);
71 return ExceptionDisposition
;
76 BaseProcessStartup(PPROCESS_START_ROUTINE lpStartAddress
)
80 DPRINT("BaseProcessStartup(..) - setting up exception frame.\n");
84 /* Set our Start Address */
85 NtSetInformationThread(NtCurrentThread(),
86 ThreadQuerySetWin32StartAddress
,
88 sizeof(PPROCESS_START_ROUTINE
));
90 /* Call the Start Routine */
91 uExitCode
= (lpStartAddress
)();
93 _SEH2_EXCEPT(BaseExceptionFilter(_SEH2_GetExceptionInformation()))
95 /* Get the SEH Error */
96 uExitCode
= _SEH2_GetExceptionCode();
100 /* Exit the Process with our error */
101 ExitProcess(uExitCode
);
105 * Tells CSR that a new process was created
109 BasepNotifyCsrOfCreation(ULONG dwCreationFlags
,
111 IN BOOL InheritHandles
)
113 ULONG Request
= CREATE_PROCESS
;
114 CSR_API_MESSAGE CsrRequest
;
117 DPRINT("BasepNotifyCsrOfCreation: Process: %lx, Flags %lx\n",
118 ProcessId
, dwCreationFlags
);
120 /* Fill out the request */
121 CsrRequest
.Data
.CreateProcessRequest
.NewProcessId
= ProcessId
;
122 CsrRequest
.Data
.CreateProcessRequest
.Flags
= dwCreationFlags
;
123 CsrRequest
.Data
.CreateProcessRequest
.bInheritHandles
= InheritHandles
;
126 Status
= CsrClientCallServer(&CsrRequest
,
128 MAKE_CSR_API(Request
, CSR_NATIVE
),
129 sizeof(CSR_API_MESSAGE
));
130 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrRequest
.Status
))
132 DPRINT1("Failed to tell csrss about new process\n");
133 return CsrRequest
.Status
;
137 return STATUS_SUCCESS
;
142 BasepNotifyCsrOfThread(IN HANDLE ThreadHandle
,
143 IN PCLIENT_ID ClientId
)
145 ULONG Request
= CREATE_THREAD
;
146 CSR_API_MESSAGE CsrRequest
;
149 DPRINT("BasepNotifyCsrOfThread: Thread: %lx, Handle %lx\n",
150 ClientId
->UniqueThread
, ThreadHandle
);
152 /* Fill out the request */
153 CsrRequest
.Data
.CreateThreadRequest
.ClientId
= *ClientId
;
154 CsrRequest
.Data
.CreateThreadRequest
.ThreadHandle
= ThreadHandle
;
157 Status
= CsrClientCallServer(&CsrRequest
,
159 MAKE_CSR_API(Request
, CSR_NATIVE
),
160 sizeof(CSR_API_MESSAGE
));
161 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrRequest
.Status
))
163 DPRINT1("Failed to tell csrss about new thread\n");
164 return CsrRequest
.Status
;
168 return STATUS_SUCCESS
;
172 * Creates the first Thread in a Proces
176 BasepCreateFirstThread(HANDLE ProcessHandle
,
177 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
178 PSECTION_IMAGE_INFORMATION SectionImageInfo
,
181 OBJECT_ATTRIBUTES LocalObjectAttributes
;
182 POBJECT_ATTRIBUTES ObjectAttributes
;
184 INITIAL_TEB InitialTeb
;
188 DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle
);
190 /* Create the Thread's Stack */
191 BaseCreateStack(ProcessHandle
,
192 SectionImageInfo
->MaximumStackSize
,
193 SectionImageInfo
->CommittedStackSize
,
196 /* Create the Thread's Context */
197 BaseInitializeContext(&Context
,
199 SectionImageInfo
->TransferAddress
,
200 InitialTeb
.StackBase
,
203 /* Convert the thread attributes */
204 ObjectAttributes
= BaseFormatObjectAttributes(&LocalObjectAttributes
,
208 /* Create the Kernel Thread Object */
209 Status
= NtCreateThread(&hThread
,
217 if (!NT_SUCCESS(Status
))
222 Status
= BasepNotifyCsrOfThread(hThread
, ClientId
);
223 if (!NT_SUCCESS(Status
))
233 * Converts ANSI to Unicode Environment
237 BasepConvertUnicodeEnvironment(OUT SIZE_T
* EnvSize
,
238 IN PVOID lpEnvironment
)
242 UNICODE_STRING UnicodeEnv
;
245 DPRINT("BasepConvertUnicodeEnvironment\n");
247 /* Scan the environment to calculate its Unicode size */
248 AnsiEnv
.Buffer
= pcScan
= (PCHAR
)lpEnvironment
;
251 pcScan
+= strlen(pcScan
) + 1;
254 /* Create our ANSI String */
255 if (pcScan
== (PCHAR
)lpEnvironment
)
257 AnsiEnv
.Length
= 2 * sizeof(CHAR
);
262 AnsiEnv
.Length
= (USHORT
)((ULONG_PTR
)pcScan
- (ULONG_PTR
)lpEnvironment
+ sizeof(CHAR
));
264 AnsiEnv
.MaximumLength
= AnsiEnv
.Length
+ 1;
266 /* Allocate memory for the Unicode Environment */
267 UnicodeEnv
.Buffer
= NULL
;
268 *EnvSize
= AnsiEnv
.MaximumLength
* sizeof(WCHAR
);
269 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
270 (PVOID
)&UnicodeEnv
.Buffer
,
276 if (!NT_SUCCESS(Status
))
278 SetLastError(Status
);
283 /* Use the allocated size */
284 UnicodeEnv
.MaximumLength
= (USHORT
)*EnvSize
;
287 RtlAnsiStringToUnicodeString(&UnicodeEnv
, &AnsiEnv
, FALSE
);
288 return UnicodeEnv
.Buffer
;
292 * Converts a Win32 Priority Class to NT
296 BasepConvertPriorityClass(IN ULONG dwCreationFlags
)
300 if(dwCreationFlags
& IDLE_PRIORITY_CLASS
)
302 ReturnClass
= PROCESS_PRIORITY_CLASS_IDLE
;
304 else if(dwCreationFlags
& BELOW_NORMAL_PRIORITY_CLASS
)
306 ReturnClass
= PROCESS_PRIORITY_CLASS_BELOW_NORMAL
;
308 else if(dwCreationFlags
& NORMAL_PRIORITY_CLASS
)
310 ReturnClass
= PROCESS_PRIORITY_CLASS_NORMAL
;
312 else if(dwCreationFlags
& ABOVE_NORMAL_PRIORITY_CLASS
)
314 ReturnClass
= PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
;
316 else if(dwCreationFlags
& HIGH_PRIORITY_CLASS
)
318 ReturnClass
= PROCESS_PRIORITY_CLASS_HIGH
;
320 else if(dwCreationFlags
& REALTIME_PRIORITY_CLASS
)
322 /* Check for Privilege First */
323 if (BasepIsRealtimeAllowed(TRUE
))
325 ReturnClass
= PROCESS_PRIORITY_CLASS_REALTIME
;
329 ReturnClass
= PROCESS_PRIORITY_CLASS_HIGH
;
334 ReturnClass
= PROCESS_PRIORITY_CLASS_INVALID
;
341 * Duplicates a standard handle and writes it where requested.
345 BasepDuplicateAndWriteHandle(IN HANDLE ProcessHandle
,
346 IN HANDLE StandardHandle
,
350 HANDLE DuplicatedHandle
;
353 DPRINT("BasepDuplicateAndWriteHandle. hProcess: %lx, Handle: %lx,"
354 "Address: %p\n", ProcessHandle
, StandardHandle
, Address
);
356 /* Don't touch Console Handles */
357 if (IsConsoleHandle(StandardHandle
)) return;
359 /* Duplicate the handle */
360 Status
= NtDuplicateObject(NtCurrentProcess(),
364 DUPLICATE_SAME_ACCESS
| DUPLICATE_SAME_ATTRIBUTES
,
367 if (NT_SUCCESS(Status
))
370 NtWriteVirtualMemory(ProcessHandle
,
380 BasepCopyHandles(IN PRTL_USER_PROCESS_PARAMETERS Params
,
381 IN PRTL_USER_PROCESS_PARAMETERS PebParams
,
382 IN BOOL InheritHandles
)
384 DPRINT("BasepCopyHandles %p %p, %d\n", Params
, PebParams
, InheritHandles
);
386 /* Copy the handle if we are inheriting or if it's a console handle */
387 if ((InheritHandles
) || (IsConsoleHandle(PebParams
->StandardInput
)))
389 Params
->StandardInput
= PebParams
->StandardInput
;
392 if ((InheritHandles
) || (IsConsoleHandle(PebParams
->StandardOutput
)))
394 Params
->StandardOutput
= PebParams
->StandardOutput
;
397 if ((InheritHandles
) || (IsConsoleHandle(PebParams
->StandardError
)))
399 Params
->StandardError
= PebParams
->StandardError
;
405 BasePushProcessParameters(IN HANDLE ProcessHandle
,
407 IN LPWSTR ApplicationPathName
,
408 IN LPWSTR lpCurrentDirectory
,
409 IN LPWSTR lpCommandLine
,
410 IN LPVOID lpEnvironment
,
412 IN LPSTARTUPINFOW StartupInfo
,
413 IN DWORD CreationFlags
,
414 IN BOOL InheritHandles
)
416 WCHAR FullPath
[MAX_PATH
+ 5];
418 LPWSTR DllPathString
;
419 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
420 PRTL_USER_PROCESS_PARAMETERS RemoteParameters
= NULL
;
421 UNICODE_STRING DllPath
, ImageName
, CommandLine
, CurrentDirectory
;
426 UNICODE_STRING Desktop
, Shell
, Runtime
, Title
;
427 PPEB OurPeb
= NtCurrentPeb();
428 LPVOID Environment
= lpEnvironment
;
429 DPRINT("BasePushProcessParameters\n");
431 /* Get the full path name */
432 Size
= GetFullPathNameW(ApplicationPathName
,
436 if ((Size
) && (Size
<= (MAX_PATH
+ 4)))
438 /* Get the DLL Path */
439 DllPathString
= BaseComputeProcessDllPath(ApplicationPathName
,
441 if (!DllPathString
) return STATUS_NO_MEMORY
;
443 /* Initialize Strings */
444 RtlInitUnicodeString(&DllPath
, DllPathString
);
445 RtlInitUnicodeString(&ImageName
, ApplicationPathName
);
449 /* Get the DLL Path */
450 DllPathString
= BaseComputeProcessDllPath(FullPath
, Environment
);
451 if (!DllPathString
) return STATUS_NO_MEMORY
;
453 /* Initialize Strings */
454 RtlInitUnicodeString(&DllPath
, DllPathString
);
455 RtlInitUnicodeString(&ImageName
, FullPath
);
457 DPRINT("DllPath: %wZ, ImageName: %wZ\n", DllPath
, ImageName
);
459 /* Initialize Strings */
460 RtlInitUnicodeString(&CommandLine
, lpCommandLine
);
461 RtlInitUnicodeString(&CurrentDirectory
, lpCurrentDirectory
);
463 /* Initialize more Strings from the Startup Info */
464 if (StartupInfo
->lpDesktop
)
466 RtlInitUnicodeString(&Desktop
, StartupInfo
->lpDesktop
);
470 RtlInitUnicodeString(&Desktop
, L
"");
472 if (StartupInfo
->lpReserved
)
474 RtlInitUnicodeString(&Shell
, StartupInfo
->lpReserved
);
478 RtlInitUnicodeString(&Shell
, L
"");
480 if (StartupInfo
->lpTitle
)
482 RtlInitUnicodeString(&Title
, StartupInfo
->lpTitle
);
486 RtlInitUnicodeString(&Title
, ApplicationPathName
);
489 /* This one is special because the length can differ */
490 Runtime
.Buffer
= (LPWSTR
)StartupInfo
->lpReserved2
;
491 Runtime
.MaximumLength
= Runtime
.Length
= StartupInfo
->cbReserved2
;
493 /* Create the Parameter Block */
494 DPRINT("Creating Process Parameters: %wZ %wZ %wZ %wZ %wZ %wZ %wZ\n",
495 &ImageName
, &DllPath
, &CommandLine
, &Desktop
, &Title
, &Shell
,
497 Status
= RtlCreateProcessParameters(&ProcessParameters
,
501 &CurrentDirectory
: NULL
,
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("Failed to create process parameters!\n");
514 /* Clear the current directory handle if not inheriting */
515 if (!InheritHandles
) ProcessParameters
->CurrentDirectory
.Handle
= NULL
;
517 /* Save pointer and start lookup */
518 Environment
= ScanChar
= ProcessParameters
->Environment
;
521 /* Find the environment size */
522 while (*ScanChar
) ScanChar
+= wcslen(ScanChar
) + 1;
523 EnviroSize
= (ULONG_PTR
)ScanChar
- (ULONG_PTR
)Environment
;
524 DPRINT("EnvironmentSize %ld\n", EnviroSize
);
526 /* Allocate and Initialize new Environment Block */
528 ProcessParameters
->Environment
= NULL
;
529 Status
= ZwAllocateVirtualMemory(ProcessHandle
,
530 (PVOID
*)&ProcessParameters
->Environment
,
535 if (!NT_SUCCESS(Status
))
537 DPRINT1("Failed to allocate Environment Block\n");
541 /* Write the Environment Block */
542 Status
= ZwWriteVirtualMemory(ProcessHandle
,
543 ProcessParameters
->Environment
,
547 if (!NT_SUCCESS(Status
))
549 DPRINT1("Failed to write Environment Block\n");
554 /* Write new parameters */
555 ProcessParameters
->StartingX
= StartupInfo
->dwX
;
556 ProcessParameters
->StartingY
= StartupInfo
->dwY
;
557 ProcessParameters
->CountX
= StartupInfo
->dwXSize
;
558 ProcessParameters
->CountY
= StartupInfo
->dwYSize
;
559 ProcessParameters
->CountCharsX
= StartupInfo
->dwXCountChars
;
560 ProcessParameters
->CountCharsY
= StartupInfo
->dwYCountChars
;
561 ProcessParameters
->FillAttribute
= StartupInfo
->dwFillAttribute
;
562 ProcessParameters
->WindowFlags
= StartupInfo
->dwFlags
;
563 ProcessParameters
->ShowWindowFlags
= StartupInfo
->wShowWindow
;
565 /* Write the handles only if we have to */
566 if (StartupInfo
->dwFlags
&
567 (STARTF_USESTDHANDLES
| STARTF_USEHOTKEY
| STARTF_SHELLPRIVATE
))
569 DPRINT("Using Standard Handles\n");
570 ProcessParameters
->StandardInput
= StartupInfo
->hStdInput
;
571 ProcessParameters
->StandardOutput
= StartupInfo
->hStdOutput
;
572 ProcessParameters
->StandardError
= StartupInfo
->hStdError
;
575 /* Use Special Flags for ConDllInitialize in Kernel32 */
576 if (CreationFlags
& DETACHED_PROCESS
)
578 ProcessParameters
->ConsoleHandle
= HANDLE_DETACHED_PROCESS
;
580 else if (CreationFlags
& CREATE_NO_WINDOW
)
582 ProcessParameters
->ConsoleHandle
= HANDLE_CREATE_NO_WINDOW
;
584 else if (CreationFlags
& CREATE_NEW_CONSOLE
)
586 ProcessParameters
->ConsoleHandle
= HANDLE_CREATE_NEW_CONSOLE
;
590 /* Inherit our Console Handle */
591 ProcessParameters
->ConsoleHandle
= OurPeb
->ProcessParameters
->ConsoleHandle
;
593 /* Is the shell trampling on our Handles? */
594 if (!(StartupInfo
->dwFlags
&
595 (STARTF_USESTDHANDLES
| STARTF_USEHOTKEY
| STARTF_SHELLPRIVATE
)))
597 /* Use handles from PEB, if inheriting or they are console */
598 DPRINT("Copying handles from parent\n");
599 BasepCopyHandles(ProcessParameters
,
600 OurPeb
->ProcessParameters
,
605 /* Also set the Console Flag */
606 if ((CreationFlags
& CREATE_NEW_PROCESS_GROUP
) &&
607 (!(CreationFlags
& CREATE_NEW_CONSOLE
)))
609 ProcessParameters
->ConsoleFlags
= 1;
612 /* See if the first 1MB should be reserved */
613 if ((ULONG_PTR
)ApplicationPathName
& 1)
615 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
618 /* See if the first 16MB should be reserved */
619 if ((ULONG_PTR
)ApplicationPathName
& 2)
621 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_RESERVE_16MB
;
624 /* Allocate memory for the parameter block */
625 Size
= ProcessParameters
->Length
;
626 Status
= NtAllocateVirtualMemory(ProcessHandle
,
627 (PVOID
*)&RemoteParameters
,
632 if (!NT_SUCCESS(Status
))
634 DPRINT1("Failed to allocate Parameters Block\n");
638 /* Set the allocated size */
639 ProcessParameters
->MaximumLength
= Size
;
641 /* Handle some Parameter Flags */
642 ProcessParameters
->Flags
|= (CreationFlags
& PROFILE_USER
) ?
643 RTL_USER_PROCESS_PARAMETERS_PROFILE_USER
: 0;
644 ProcessParameters
->Flags
|= (CreationFlags
& PROFILE_KERNEL
) ?
645 RTL_USER_PROCESS_PARAMETERS_PROFILE_KERNEL
: 0;
646 ProcessParameters
->Flags
|= (CreationFlags
& PROFILE_SERVER
) ?
647 RTL_USER_PROCESS_PARAMETERS_PROFILE_SERVER
: 0;
648 ProcessParameters
->Flags
|= (NtCurrentPeb()->ProcessParameters
->Flags
&
649 RTL_USER_PROCESS_PARAMETERS_DISABLE_HEAP_CHECKS
);
651 /* Write the Parameter Block */
652 Status
= NtWriteVirtualMemory(ProcessHandle
,
655 ProcessParameters
->Length
,
657 if (!NT_SUCCESS(Status
))
659 DPRINT1("Failed to write Parameters Block\n");
663 /* Write the PEB Pointer */
664 Status
= NtWriteVirtualMemory(ProcessHandle
,
665 &Peb
->ProcessParameters
,
669 if (!NT_SUCCESS(Status
))
671 DPRINT1("Failed to write Parameters Block\n");
675 /* FIXME: Write Peb->ImageSubSystem */
679 RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath
.Buffer
);
680 RtlDestroyProcessParameters(ProcessParameters
);
682 DPRINT("Completed\n");
683 return STATUS_SUCCESS
;
688 InitCommandLines(VOID
)
690 PRTL_USER_PROCESS_PARAMETERS Params
;
692 /* get command line */
693 Params
= NtCurrentPeb()->ProcessParameters
;
694 RtlNormalizeProcessParams (Params
);
696 /* initialize command line buffers */
697 CommandLineStringW
.Length
= Params
->CommandLine
.Length
;
698 CommandLineStringW
.MaximumLength
= CommandLineStringW
.Length
+ sizeof(WCHAR
);
699 CommandLineStringW
.Buffer
= RtlAllocateHeap(GetProcessHeap(),
700 HEAP_GENERATE_EXCEPTIONS
| HEAP_ZERO_MEMORY
,
701 CommandLineStringW
.MaximumLength
);
702 if (CommandLineStringW
.Buffer
== NULL
)
707 RtlInitAnsiString(&CommandLineStringA
, NULL
);
709 /* Copy command line */
710 RtlCopyUnicodeString(&CommandLineStringW
,
711 &(Params
->CommandLine
));
712 CommandLineStringW
.Buffer
[CommandLineStringW
.Length
/ sizeof(WCHAR
)] = 0;
714 /* convert unicode string to ansi (or oem) */
716 RtlUnicodeStringToAnsiString(&CommandLineStringA
,
720 RtlUnicodeStringToOemString(&CommandLineStringA
,
724 CommandLineStringA
.Buffer
[CommandLineStringA
.Length
] = 0;
726 bCommandLineInitialized
= TRUE
;
734 GetProcessAffinityMask(HANDLE hProcess
,
735 PDWORD_PTR lpProcessAffinityMask
,
736 PDWORD_PTR lpSystemAffinityMask
)
738 PROCESS_BASIC_INFORMATION ProcessInfo
;
739 SYSTEM_BASIC_INFORMATION SystemInfo
;
742 Status
= NtQuerySystemInformation(SystemBasicInformation
,
746 if (!NT_SUCCESS(Status
))
748 BaseSetLastNTError(Status
);
752 Status
= NtQueryInformationProcess(hProcess
,
753 ProcessBasicInformation
,
755 sizeof(PROCESS_BASIC_INFORMATION
),
757 if (!NT_SUCCESS(Status
))
759 BaseSetLastNTError(Status
);
763 *lpProcessAffinityMask
= (DWORD
)ProcessInfo
.AffinityMask
;
764 *lpSystemAffinityMask
= (DWORD
)SystemInfo
.ActiveProcessorsAffinityMask
;
775 SetProcessAffinityMask(HANDLE hProcess
,
776 DWORD_PTR dwProcessAffinityMask
)
780 Status
= NtSetInformationProcess(hProcess
,
782 (PVOID
)&dwProcessAffinityMask
,
784 if (!NT_SUCCESS(Status
))
786 BaseSetLastNTError(Status
);
799 GetProcessShutdownParameters(LPDWORD lpdwLevel
,
802 CSR_API_MESSAGE CsrRequest
;
806 Request
= GET_SHUTDOWN_PARAMETERS
;
807 Status
= CsrClientCallServer(&CsrRequest
,
809 MAKE_CSR_API(Request
, CSR_NATIVE
),
810 sizeof(CSR_API_MESSAGE
));
811 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrRequest
.Status
))
813 BaseSetLastNTError(Status
);
817 *lpdwLevel
= CsrRequest
.Data
.GetShutdownParametersRequest
.Level
;
818 *lpdwFlags
= CsrRequest
.Data
.GetShutdownParametersRequest
.Flags
;
829 SetProcessShutdownParameters(DWORD dwLevel
,
832 CSR_API_MESSAGE CsrRequest
;
836 CsrRequest
.Data
.SetShutdownParametersRequest
.Level
= dwLevel
;
837 CsrRequest
.Data
.SetShutdownParametersRequest
.Flags
= dwFlags
;
839 Request
= SET_SHUTDOWN_PARAMETERS
;
840 Status
= CsrClientCallServer(&CsrRequest
,
842 MAKE_CSR_API(Request
, CSR_NATIVE
),
843 sizeof(CSR_API_MESSAGE
));
844 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrRequest
.Status
))
846 BaseSetLastNTError(Status
);
859 GetProcessWorkingSetSize(HANDLE hProcess
,
860 PSIZE_T lpMinimumWorkingSetSize
,
861 PSIZE_T lpMaximumWorkingSetSize
)
863 QUOTA_LIMITS QuotaLimits
;
866 Status
= NtQueryInformationProcess(hProcess
,
869 sizeof(QUOTA_LIMITS
),
871 if (!NT_SUCCESS(Status
))
873 BaseSetLastNTError(Status
);
877 *lpMinimumWorkingSetSize
= QuotaLimits
.MinimumWorkingSetSize
;
878 *lpMaximumWorkingSetSize
= QuotaLimits
.MaximumWorkingSetSize
;
889 SetProcessWorkingSetSize(HANDLE hProcess
,
890 SIZE_T dwMinimumWorkingSetSize
,
891 SIZE_T dwMaximumWorkingSetSize
)
893 QUOTA_LIMITS QuotaLimits
;
896 QuotaLimits
.MinimumWorkingSetSize
= dwMinimumWorkingSetSize
;
897 QuotaLimits
.MaximumWorkingSetSize
= dwMaximumWorkingSetSize
;
899 Status
= NtSetInformationProcess(hProcess
,
902 sizeof(QUOTA_LIMITS
));
903 if (!NT_SUCCESS(Status
))
905 BaseSetLastNTError(Status
);
918 GetProcessTimes(HANDLE hProcess
,
919 LPFILETIME lpCreationTime
,
920 LPFILETIME lpExitTime
,
921 LPFILETIME lpKernelTime
,
922 LPFILETIME lpUserTime
)
924 KERNEL_USER_TIMES Kut
;
927 Status
= NtQueryInformationProcess(hProcess
,
932 if (!NT_SUCCESS(Status
))
934 BaseSetLastNTError(Status
);
938 lpCreationTime
->dwLowDateTime
= Kut
.CreateTime
.u
.LowPart
;
939 lpCreationTime
->dwHighDateTime
= Kut
.CreateTime
.u
.HighPart
;
941 lpExitTime
->dwLowDateTime
= Kut
.ExitTime
.u
.LowPart
;
942 lpExitTime
->dwHighDateTime
= Kut
.ExitTime
.u
.HighPart
;
944 lpKernelTime
->dwLowDateTime
= Kut
.KernelTime
.u
.LowPart
;
945 lpKernelTime
->dwHighDateTime
= Kut
.KernelTime
.u
.HighPart
;
947 lpUserTime
->dwLowDateTime
= Kut
.UserTime
.u
.LowPart
;
948 lpUserTime
->dwHighDateTime
= Kut
.UserTime
.u
.HighPart
;
959 GetCurrentProcess(VOID
)
961 return (HANDLE
)NtCurrentProcess();
970 GetCurrentThread(VOID
)
972 return (HANDLE
)NtCurrentThread();
981 GetCurrentProcessId(VOID
)
983 return HandleToUlong(GetTeb()->ClientId
.UniqueProcess
);
992 GetExitCodeProcess(HANDLE hProcess
,
995 PROCESS_BASIC_INFORMATION ProcessBasic
;
998 Status
= NtQueryInformationProcess(hProcess
,
999 ProcessBasicInformation
,
1001 sizeof(PROCESS_BASIC_INFORMATION
),
1003 if (!NT_SUCCESS(Status
))
1005 BaseSetLastNTError(Status
);
1009 *lpExitCode
= (DWORD
)ProcessBasic
.ExitStatus
;
1020 GetProcessId(HANDLE Process
)
1022 PROCESS_BASIC_INFORMATION ProcessBasic
;
1025 Status
= NtQueryInformationProcess(Process
,
1026 ProcessBasicInformation
,
1028 sizeof(PROCESS_BASIC_INFORMATION
),
1030 if (!NT_SUCCESS(Status
))
1032 BaseSetLastNTError(Status
);
1036 return (DWORD
)ProcessBasic
.UniqueProcessId
;
1045 OpenProcess(DWORD dwDesiredAccess
,
1046 BOOL bInheritHandle
,
1050 HANDLE ProcessHandle
;
1051 OBJECT_ATTRIBUTES ObjectAttributes
;
1054 ClientId
.UniqueProcess
= UlongToHandle(dwProcessId
);
1055 ClientId
.UniqueThread
= 0;
1057 InitializeObjectAttributes(&ObjectAttributes
,
1059 (bInheritHandle
? OBJ_INHERIT
: 0),
1063 errCode
= NtOpenProcess(&ProcessHandle
,
1067 if (!NT_SUCCESS(errCode
))
1069 BaseSetLastNTError(errCode
);
1073 return ProcessHandle
;
1082 WinExec(LPCSTR lpCmdLine
,
1085 STARTUPINFOA StartupInfo
;
1086 PROCESS_INFORMATION ProcessInformation
;
1089 RtlZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
1090 StartupInfo
.cb
= sizeof(STARTUPINFOA
);
1091 StartupInfo
.wShowWindow
= (WORD
)uCmdShow
;
1092 StartupInfo
.dwFlags
= 0;
1094 if (!CreateProcessA(NULL
,
1103 &ProcessInformation
))
1105 dosErr
= GetLastError();
1106 return dosErr
< 32 ? dosErr
: ERROR_BAD_FORMAT
;
1109 if (NULL
!= lpfnGlobalRegisterWaitForInputIdle
)
1111 lpfnGlobalRegisterWaitForInputIdle(ProcessInformation
.hProcess
,
1115 NtClose(ProcessInformation
.hProcess
);
1116 NtClose(ProcessInformation
.hThread
);
1118 return 33; /* Something bigger than 31 means success. */
1127 RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle
)
1129 lpfnGlobalRegisterWaitForInputIdle
= lpfnRegisterWaitForInputIdle
;
1138 GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo
)
1140 PRTL_USER_PROCESS_PARAMETERS Params
;
1142 if (lpStartupInfo
== NULL
)
1144 SetLastError(ERROR_INVALID_PARAMETER
);
1148 Params
= NtCurrentPeb()->ProcessParameters
;
1150 lpStartupInfo
->cb
= sizeof(STARTUPINFOW
);
1151 lpStartupInfo
->lpDesktop
= Params
->DesktopInfo
.Buffer
;
1152 lpStartupInfo
->lpTitle
= Params
->WindowTitle
.Buffer
;
1153 lpStartupInfo
->dwX
= Params
->StartingX
;
1154 lpStartupInfo
->dwY
= Params
->StartingY
;
1155 lpStartupInfo
->dwXSize
= Params
->CountX
;
1156 lpStartupInfo
->dwYSize
= Params
->CountY
;
1157 lpStartupInfo
->dwXCountChars
= Params
->CountCharsX
;
1158 lpStartupInfo
->dwYCountChars
= Params
->CountCharsY
;
1159 lpStartupInfo
->dwFillAttribute
= Params
->FillAttribute
;
1160 lpStartupInfo
->dwFlags
= Params
->WindowFlags
;
1161 lpStartupInfo
->wShowWindow
= (WORD
)Params
->ShowWindowFlags
;
1162 lpStartupInfo
->cbReserved2
= Params
->RuntimeData
.Length
;
1163 lpStartupInfo
->lpReserved2
= (LPBYTE
)Params
->RuntimeData
.Buffer
;
1165 lpStartupInfo
->hStdInput
= Params
->StandardInput
;
1166 lpStartupInfo
->hStdOutput
= Params
->StandardOutput
;
1167 lpStartupInfo
->hStdError
= Params
->StandardError
;
1176 GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo
)
1178 PRTL_USER_PROCESS_PARAMETERS Params
;
1179 ANSI_STRING AnsiString
;
1181 if (lpStartupInfo
== NULL
)
1183 SetLastError(ERROR_INVALID_PARAMETER
);
1187 Params
= NtCurrentPeb ()->ProcessParameters
;
1189 RtlAcquirePebLock ();
1191 /* FIXME - not thread-safe */
1192 if (lpLocalStartupInfo
== NULL
)
1194 /* create new local startup info (ansi) */
1195 lpLocalStartupInfo
= RtlAllocateHeap(RtlGetProcessHeap(),
1197 sizeof(STARTUPINFOA
));
1198 if (lpLocalStartupInfo
== NULL
)
1200 RtlReleasePebLock();
1201 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1205 lpLocalStartupInfo
->cb
= sizeof(STARTUPINFOA
);
1207 /* copy window title string */
1208 RtlUnicodeStringToAnsiString(&AnsiString
,
1209 &Params
->WindowTitle
,
1211 lpLocalStartupInfo
->lpTitle
= AnsiString
.Buffer
;
1213 /* copy desktop info string */
1214 RtlUnicodeStringToAnsiString(&AnsiString
,
1215 &Params
->DesktopInfo
,
1217 lpLocalStartupInfo
->lpDesktop
= AnsiString
.Buffer
;
1219 /* copy shell info string */
1220 RtlUnicodeStringToAnsiString(&AnsiString
,
1223 lpLocalStartupInfo
->lpReserved
= AnsiString
.Buffer
;
1225 lpLocalStartupInfo
->dwX
= Params
->StartingX
;
1226 lpLocalStartupInfo
->dwY
= Params
->StartingY
;
1227 lpLocalStartupInfo
->dwXSize
= Params
->CountX
;
1228 lpLocalStartupInfo
->dwYSize
= Params
->CountY
;
1229 lpLocalStartupInfo
->dwXCountChars
= Params
->CountCharsX
;
1230 lpLocalStartupInfo
->dwYCountChars
= Params
->CountCharsY
;
1231 lpLocalStartupInfo
->dwFillAttribute
= Params
->FillAttribute
;
1232 lpLocalStartupInfo
->dwFlags
= Params
->WindowFlags
;
1233 lpLocalStartupInfo
->wShowWindow
= (WORD
)Params
->ShowWindowFlags
;
1234 lpLocalStartupInfo
->cbReserved2
= Params
->RuntimeData
.Length
;
1235 lpLocalStartupInfo
->lpReserved2
= (LPBYTE
)Params
->RuntimeData
.Buffer
;
1237 lpLocalStartupInfo
->hStdInput
= Params
->StandardInput
;
1238 lpLocalStartupInfo
->hStdOutput
= Params
->StandardOutput
;
1239 lpLocalStartupInfo
->hStdError
= Params
->StandardError
;
1242 RtlReleasePebLock();
1244 /* copy local startup info data to external startup info */
1245 memcpy(lpStartupInfo
,
1247 sizeof(STARTUPINFOA
));
1256 FlushInstructionCache(HANDLE hProcess
,
1257 LPCVOID lpBaseAddress
,
1262 Status
= NtFlushInstructionCache(hProcess
,
1263 (PVOID
)lpBaseAddress
,
1265 if (!NT_SUCCESS(Status
))
1267 BaseSetLastNTError(Status
);
1280 ExitProcess(UINT uExitCode
)
1282 CSR_API_MESSAGE CsrRequest
;
1286 /* kill sibling threads ... we want to be alone at this point */
1287 NtTerminateProcess(NULL
, 0);
1289 /* unload all dll's */
1290 LdrShutdownProcess();
1292 /* notify csrss of process termination */
1293 Request
= TERMINATE_PROCESS
;
1294 Status
= CsrClientCallServer(&CsrRequest
,
1296 MAKE_CSR_API(Request
, CSR_NATIVE
),
1297 sizeof(CSR_API_MESSAGE
));
1298 if (!NT_SUCCESS(Status
) || !NT_SUCCESS(CsrRequest
.Status
))
1300 DPRINT("Failed to tell csrss about terminating process\n");
1303 NtTerminateProcess(NtCurrentProcess (),
1306 /* should never get here */
1317 TerminateProcess(HANDLE hProcess
,
1322 if (hProcess
== NULL
)
1327 Status
= NtTerminateProcess(hProcess
, uExitCode
);
1328 if (NT_SUCCESS(Status
))
1333 BaseSetLastNTError(Status
);
1343 FatalAppExitA(UINT uAction
,
1344 LPCSTR lpMessageText
)
1346 UNICODE_STRING MessageTextU
;
1347 ANSI_STRING MessageText
;
1349 RtlInitAnsiString(&MessageText
, (LPSTR
)lpMessageText
);
1351 RtlAnsiStringToUnicodeString(&MessageTextU
,
1355 FatalAppExitW(uAction
, MessageTextU
.Buffer
);
1357 RtlFreeUnicodeString(&MessageTextU
);
1366 FatalAppExitW(UINT uAction
,
1367 LPCWSTR lpMessageText
)
1369 static const WCHAR szUser32
[] = L
"user32.dll\0";
1371 HMODULE hModule
= GetModuleHandleW(szUser32
);
1372 MessageBoxW_Proc pMessageBoxW
= NULL
;
1374 DPRINT1("AppExit\n");
1377 pMessageBoxW
= (MessageBoxW_Proc
)GetProcAddress(hModule
, "MessageBoxW");
1380 pMessageBoxW(0, lpMessageText
, NULL
, MB_SYSTEMMODAL
| MB_OK
);
1382 DPRINT1("%s\n", lpMessageText
);
1393 FatalExit(int ExitCode
)
1395 ExitProcess(ExitCode
);
1404 GetPriorityClass(HANDLE hProcess
)
1407 PROCESS_PRIORITY_CLASS PriorityClass
;
1409 Status
= NtQueryInformationProcess(hProcess
,
1410 ProcessPriorityClass
,
1412 sizeof(PROCESS_PRIORITY_CLASS
),
1414 if(NT_SUCCESS(Status
))
1416 switch(PriorityClass
.PriorityClass
)
1418 case PROCESS_PRIORITY_CLASS_IDLE
:
1419 return IDLE_PRIORITY_CLASS
;
1421 case PROCESS_PRIORITY_CLASS_BELOW_NORMAL
:
1422 return BELOW_NORMAL_PRIORITY_CLASS
;
1424 case PROCESS_PRIORITY_CLASS_NORMAL
:
1425 return NORMAL_PRIORITY_CLASS
;
1427 case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
:
1428 return ABOVE_NORMAL_PRIORITY_CLASS
;
1430 case PROCESS_PRIORITY_CLASS_HIGH
:
1431 return HIGH_PRIORITY_CLASS
;
1433 case PROCESS_PRIORITY_CLASS_REALTIME
:
1434 return REALTIME_PRIORITY_CLASS
;
1437 return NORMAL_PRIORITY_CLASS
;
1441 BaseSetLastNTError(Status
);
1451 SetPriorityClass(HANDLE hProcess
,
1452 DWORD dwPriorityClass
)
1455 PROCESS_PRIORITY_CLASS PriorityClass
;
1457 switch (dwPriorityClass
)
1459 case IDLE_PRIORITY_CLASS
:
1460 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_IDLE
;
1463 case BELOW_NORMAL_PRIORITY_CLASS
:
1464 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_BELOW_NORMAL
;
1467 case NORMAL_PRIORITY_CLASS
:
1468 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_NORMAL
;
1471 case ABOVE_NORMAL_PRIORITY_CLASS
:
1472 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
;
1475 case HIGH_PRIORITY_CLASS
:
1476 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_HIGH
;
1479 case REALTIME_PRIORITY_CLASS
:
1480 PriorityClass
.PriorityClass
= PROCESS_PRIORITY_CLASS_REALTIME
;
1484 SetLastError(ERROR_INVALID_PARAMETER
);
1488 PriorityClass
.Foreground
= FALSE
;
1490 Status
= NtSetInformationProcess(hProcess
,
1491 ProcessPriorityClass
,
1493 sizeof(PROCESS_PRIORITY_CLASS
));
1494 if (!NT_SUCCESS(Status
))
1496 BaseSetLastNTError(Status
);
1509 GetProcessVersion(DWORD ProcessId
)
1512 PIMAGE_NT_HEADERS NtHeader
= NULL
;
1513 IMAGE_NT_HEADERS NtHeaders
;
1514 IMAGE_DOS_HEADER DosHeader
;
1515 PROCESS_BASIC_INFORMATION ProcessBasicInfo
;
1516 PVOID BaseAddress
= NULL
;
1517 HANDLE ProcessHandle
= NULL
;
1524 if (0 == ProcessId
|| GetCurrentProcessId() == ProcessId
)
1527 BaseAddress
= (PVOID
) NtCurrentPeb()->ImageBaseAddress
;
1528 NtHeader
= RtlImageNtHeader(BaseAddress
);
1530 Version
= (NtHeader
->OptionalHeader
.MajorOperatingSystemVersion
<< 16) |
1531 (NtHeader
->OptionalHeader
.MinorOperatingSystemVersion
);
1536 ProcessHandle
= OpenProcess(PROCESS_VM_READ
| PROCESS_QUERY_INFORMATION
,
1540 if (!ProcessHandle
) return 0;
1542 Status
= NtQueryInformationProcess(ProcessHandle
,
1543 ProcessBasicInformation
,
1545 sizeof(ProcessBasicInfo
),
1548 if (!NT_SUCCESS(Status
)) goto Error
;
1550 Status
= NtReadVirtualMemory(ProcessHandle
,
1551 ProcessBasicInfo
.PebBaseAddress
,
1556 if (!NT_SUCCESS(Status
) || Count
!= sizeof(Peb
)) goto Error
;
1558 memset(&DosHeader
, 0, sizeof(DosHeader
));
1559 Status
= NtReadVirtualMemory(ProcessHandle
,
1560 Peb
.ImageBaseAddress
,
1565 if (!NT_SUCCESS(Status
) || Count
!= sizeof(DosHeader
)) goto Error
;
1566 if (DosHeader
.e_magic
!= IMAGE_DOS_SIGNATURE
) goto Error
;
1568 memset(&NtHeaders
, 0, sizeof(NtHeaders
));
1569 Status
= NtReadVirtualMemory(ProcessHandle
,
1570 (char *)Peb
.ImageBaseAddress
+ DosHeader
.e_lfanew
,
1575 if (!NT_SUCCESS(Status
) || Count
!= sizeof(NtHeaders
)) goto Error
;
1576 if (NtHeaders
.Signature
!= IMAGE_NT_SIGNATURE
) goto Error
;
1578 Version
= MAKELONG(NtHeaders
.OptionalHeader
.MinorSubsystemVersion
,
1579 NtHeaders
.OptionalHeader
.MajorSubsystemVersion
);
1582 if (!NT_SUCCESS(Status
))
1584 BaseSetLastNTError(Status
);
1590 if (ProcessHandle
) CloseHandle(ProcessHandle
);
1603 GetProcessIoCounters(HANDLE hProcess
,
1604 PIO_COUNTERS lpIoCounters
)
1608 Status
= NtQueryInformationProcess(hProcess
,
1611 sizeof(IO_COUNTERS
),
1613 if (!NT_SUCCESS(Status
))
1615 BaseSetLastNTError(Status
);
1628 GetProcessPriorityBoost(HANDLE hProcess
,
1629 PBOOL pDisablePriorityBoost
)
1632 ULONG PriorityBoost
;
1634 Status
= NtQueryInformationProcess(hProcess
,
1635 ProcessPriorityBoost
,
1639 if (NT_SUCCESS(Status
))
1641 *pDisablePriorityBoost
= PriorityBoost
;
1645 BaseSetLastNTError(Status
);
1655 SetProcessPriorityBoost(HANDLE hProcess
,
1656 BOOL bDisablePriorityBoost
)
1659 ULONG PriorityBoost
= (bDisablePriorityBoost
? TRUE
: FALSE
); /* prevent setting values other than 1 and 0 */
1661 Status
= NtSetInformationProcess(hProcess
,
1662 ProcessPriorityBoost
,
1665 if (!NT_SUCCESS(Status
))
1667 BaseSetLastNTError(Status
);
1680 GetProcessHandleCount(HANDLE hProcess
,
1681 PDWORD pdwHandleCount
)
1686 Status
= NtQueryInformationProcess(hProcess
,
1691 if(NT_SUCCESS(Status
))
1693 *pdwHandleCount
= phc
;
1697 BaseSetLastNTError(Status
);
1707 IsWow64Process(HANDLE hProcess
,
1713 Status
= NtQueryInformationProcess(hProcess
,
1714 ProcessWow64Information
,
1718 if (!NT_SUCCESS(Status
))
1720 SetLastError(RtlNtStatusToDosError(Status
));
1724 *Wow64Process
= (pbi
!= 0);
1734 GetCommandLineA(VOID
)
1736 DPRINT("CommandLine \'%s\'\n", CommandLineStringA
.Buffer
);
1737 return CommandLineStringA
.Buffer
;
1746 GetCommandLineW(VOID
)
1748 DPRINT("CommandLine \'%S\'\n", CommandLineStringW
.Buffer
);
1749 return CommandLineStringW
.Buffer
;
1757 ReadProcessMemory(IN HANDLE hProcess
,
1758 IN LPCVOID lpBaseAddress
,
1761 OUT SIZE_T
* lpNumberOfBytesRead
)
1766 Status
= NtReadVirtualMemory(hProcess
,
1767 (PVOID
)lpBaseAddress
,
1770 lpNumberOfBytesRead
);
1771 if (!NT_SUCCESS(Status
))
1774 BaseSetLastNTError (Status
);
1778 /* Return success */
1787 WriteProcessMemory(IN HANDLE hProcess
,
1788 IN LPVOID lpBaseAddress
,
1789 IN LPCVOID lpBuffer
,
1791 OUT SIZE_T
*lpNumberOfBytesWritten
)
1799 /* Set parameters for protect call */
1801 Base
= lpBaseAddress
;
1803 /* Check the current status */
1804 Status
= NtProtectVirtualMemory(hProcess
,
1807 PAGE_EXECUTE_READWRITE
,
1809 if (NT_SUCCESS(Status
))
1811 /* Check if we are unprotecting */
1812 UnProtect
= OldValue
& (PAGE_READWRITE
|
1814 PAGE_EXECUTE_READWRITE
|
1815 PAGE_EXECUTE_WRITECOPY
) ? FALSE
: TRUE
;
1818 /* Set the new protection */
1819 Status
= NtProtectVirtualMemory(hProcess
,
1825 /* Write the memory */
1826 Status
= NtWriteVirtualMemory(hProcess
,
1830 lpNumberOfBytesWritten
);
1831 if (!NT_SUCCESS(Status
))
1834 BaseSetLastNTError(Status
);
1838 /* Flush the ITLB */
1839 NtFlushInstructionCache(hProcess
, lpBaseAddress
, nSize
);
1844 /* Check if we were read only */
1845 if ((OldValue
& PAGE_NOACCESS
) || (OldValue
& PAGE_READONLY
))
1847 /* Restore protection and fail */
1848 NtProtectVirtualMemory(hProcess
,
1853 BaseSetLastNTError(STATUS_ACCESS_VIOLATION
);
1857 /* Otherwise, do the write */
1858 Status
= NtWriteVirtualMemory(hProcess
,
1862 lpNumberOfBytesWritten
);
1864 /* And restore the protection */
1865 NtProtectVirtualMemory(hProcess
,
1870 if (!NT_SUCCESS(Status
))
1873 BaseSetLastNTError(STATUS_ACCESS_VIOLATION
);
1877 /* Flush the ITLB */
1878 NtFlushInstructionCache(hProcess
, lpBaseAddress
, nSize
);
1885 BaseSetLastNTError(Status
);
1895 ProcessIdToSessionId(IN DWORD dwProcessId
,
1896 OUT DWORD
*pSessionId
)
1898 PROCESS_SESSION_INFORMATION SessionInformation
;
1899 OBJECT_ATTRIBUTES ObjectAttributes
;
1901 HANDLE ProcessHandle
;
1904 if (IsBadWritePtr(pSessionId
, sizeof(DWORD
)))
1906 SetLastError(ERROR_INVALID_PARAMETER
);
1910 ClientId
.UniqueProcess
= UlongToHandle(dwProcessId
);
1911 ClientId
.UniqueThread
= 0;
1913 InitializeObjectAttributes(&ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1915 Status
= NtOpenProcess(&ProcessHandle
,
1916 PROCESS_QUERY_INFORMATION
,
1919 if (NT_SUCCESS(Status
))
1921 Status
= NtQueryInformationProcess(ProcessHandle
,
1922 ProcessSessionInformation
,
1923 &SessionInformation
,
1924 sizeof(SessionInformation
),
1926 NtClose(ProcessHandle
);
1928 if (NT_SUCCESS(Status
))
1930 *pSessionId
= SessionInformation
.SessionId
;
1935 BaseSetLastNTError(Status
);
1941 SetProcessWorkingSetSizeEx(IN HANDLE hProcess
,
1942 IN SIZE_T dwMinimumWorkingSetSize
,
1943 IN SIZE_T dwMaximumWorkingSetSize
,
1953 GetProcessWorkingSetSizeEx(IN HANDLE hProcess
,
1954 OUT PSIZE_T lpMinimumWorkingSetSize
,
1955 OUT PSIZE_T lpMaximumWorkingSetSize
,
1967 CreateProcessInternalW(HANDLE hToken
,
1968 LPCWSTR lpApplicationName
,
1969 LPWSTR lpCommandLine
,
1970 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
1971 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
1972 BOOL bInheritHandles
,
1973 DWORD dwCreationFlags
,
1974 LPVOID lpEnvironment
,
1975 LPCWSTR lpCurrentDirectory
,
1976 LPSTARTUPINFOW lpStartupInfo
,
1977 LPPROCESS_INFORMATION lpProcessInformation
,
1981 PROCESS_PRIORITY_CLASS PriorityClass
;
1982 BOOLEAN FoundQuotes
= FALSE
;
1983 BOOLEAN QuotesNeeded
= FALSE
;
1984 BOOLEAN CmdLineIsAppName
= FALSE
;
1985 UNICODE_STRING ApplicationName
= { 0, 0, NULL
};
1986 OBJECT_ATTRIBUTES LocalObjectAttributes
;
1987 POBJECT_ATTRIBUTES ObjectAttributes
;
1988 HANDLE hSection
= NULL
, hProcess
= NULL
, hThread
= NULL
, hDebug
= NULL
;
1989 SECTION_IMAGE_INFORMATION SectionImageInfo
;
1990 LPWSTR CurrentDirectory
= NULL
;
1991 LPWSTR CurrentDirectoryPart
;
1992 PROCESS_BASIC_INFORMATION ProcessBasicInfo
;
1993 STARTUPINFOW StartupInfo
;
1995 LPWSTR BatchCommandLine
;
1996 ULONG CmdLineLength
;
1997 UNICODE_STRING CommandLineString
;
1999 LPWSTR QuotedCmdLine
= NULL
;
2001 LPWSTR NullBuffer
= NULL
;
2002 LPWSTR NameBuffer
= NULL
;
2006 BOOLEAN SearchDone
= FALSE
;
2007 BOOLEAN Escape
= FALSE
;
2009 PPEB OurPeb
= NtCurrentPeb();
2014 /* FIXME should process
2015 * HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
2016 * key (see http://blogs.msdn.com/oldnewthing/archive/2005/12/19/505449.aspx)
2019 DPRINT("CreateProcessW: lpApplicationName: %S lpCommandLine: %S"
2020 " lpEnvironment: %p lpCurrentDirectory: %S dwCreationFlags: %lx\n",
2021 lpApplicationName
, lpCommandLine
, lpEnvironment
, lpCurrentDirectory
,
2024 /* Flags we don't handle yet */
2025 if (dwCreationFlags
& CREATE_SEPARATE_WOW_VDM
)
2027 DPRINT1("CREATE_SEPARATE_WOW_VDM not handled\n");
2029 if (dwCreationFlags
& CREATE_SHARED_WOW_VDM
)
2031 DPRINT1("CREATE_SHARED_WOW_VDM not handled\n");
2033 if (dwCreationFlags
& CREATE_FORCEDOS
)
2035 DPRINT1("CREATE_FORCEDOS not handled\n");
2038 /* Fail on this flag, it's only valid with the WithLogonW function */
2039 if (dwCreationFlags
& CREATE_PRESERVE_CODE_AUTHZ_LEVEL
)
2041 DPRINT1("Invalid flag used\n");
2042 SetLastError(ERROR_INVALID_PARAMETER
);
2046 /* This combination is illegal (see MSDN) */
2047 if ((dwCreationFlags
& (DETACHED_PROCESS
| CREATE_NEW_CONSOLE
)) ==
2048 (DETACHED_PROCESS
| CREATE_NEW_CONSOLE
))
2050 DPRINT1("Invalid flag combo used\n");
2051 SetLastError(ERROR_INVALID_PARAMETER
);
2055 /* Another illegal combo */
2056 if ((dwCreationFlags
& (CREATE_SEPARATE_WOW_VDM
| CREATE_SHARED_WOW_VDM
)) ==
2057 (CREATE_SEPARATE_WOW_VDM
| CREATE_SHARED_WOW_VDM
))
2059 DPRINT1("Invalid flag combo used\n");
2060 SetLastError(ERROR_INVALID_PARAMETER
);
2064 if (lpCurrentDirectory
)
2066 if ((GetFileAttributesW(lpCurrentDirectory
) == INVALID_FILE_ATTRIBUTES
) ||
2067 !(GetFileAttributesW(lpCurrentDirectory
) & FILE_ATTRIBUTE_DIRECTORY
))
2069 SetLastError(ERROR_DIRECTORY
);
2075 * We're going to modify and mask out flags and stuff in lpStartupInfo,
2076 * so we'll use our own local copy for that.
2078 StartupInfo
= *lpStartupInfo
;
2080 /* FIXME: Use default Separate/Shared VDM Flag */
2082 /* If we are inside a Job, use Separate VDM so it won't escape the Job */
2083 if (!(dwCreationFlags
& CREATE_SEPARATE_WOW_VDM
))
2085 if (NtIsProcessInJob(NtCurrentProcess(), NULL
))
2087 /* Remove the shared flag and add the separate flag. */
2088 dwCreationFlags
= (dwCreationFlags
&~ CREATE_SHARED_WOW_VDM
) |
2089 CREATE_SEPARATE_WOW_VDM
;
2094 * According to some sites, ShellExecuteEx uses an undocumented flag to
2095 * send private handle data (such as HMONITOR or HICON). See:
2096 * www.catch22.net/tuts/undoc01.asp. This implies that we can't use the
2097 * standard handles anymore since we'd be overwriting this private data
2099 if ((StartupInfo
.dwFlags
& STARTF_USESTDHANDLES
) &&
2100 (StartupInfo
.dwFlags
& (STARTF_USEHOTKEY
| STARTF_SHELLPRIVATE
)))
2102 StartupInfo
.dwFlags
&= ~STARTF_USESTDHANDLES
;
2105 /* Start by zeroing out the fields */
2106 RtlZeroMemory(lpProcessInformation
, sizeof(PROCESS_INFORMATION
));
2108 /* Easy stuff first, convert the process priority class */
2109 PriorityClass
.Foreground
= FALSE
;
2110 PriorityClass
.PriorityClass
= (UCHAR
)BasepConvertPriorityClass(dwCreationFlags
);
2114 /* Search for escape sequences */
2115 ScanString
= lpCommandLine
;
2116 while (NULL
!= (ScanString
= wcschr(ScanString
, L
'^')))
2119 if (*ScanString
== L
'\"' || *ScanString
== L
'^' || *ScanString
== L
'\"')
2127 /* Get the application name and do all the proper formating necessary */
2129 /* See if we have an application name (oh please let us have one!) */
2130 if (!lpApplicationName
)
2132 /* The fun begins */
2133 NameBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
2135 MAX_PATH
* sizeof(WCHAR
));
2136 if (NameBuffer
== NULL
)
2138 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2142 /* This is all we have to work with :( */
2143 lpApplicationName
= lpCommandLine
;
2145 /* Initialize our friends at the beginning */
2146 NullBuffer
= (LPWSTR
)lpApplicationName
;
2147 ScanString
= (LPWSTR
)lpApplicationName
;
2149 /* We will start by looking for a quote */
2150 if (*ScanString
== L
'\"')
2152 /* That was quick */
2155 /* Advance past quote */
2157 lpApplicationName
= ScanString
;
2159 /* Find the closing quote */
2162 if (*ScanString
== L
'\"' && *(ScanString
- 1) != L
'^')
2165 NullBuffer
= ScanString
;
2172 NullBuffer
= ScanString
;
2177 /* No quotes, so we'll be looking for white space */
2179 /* Reset the pointer */
2180 lpApplicationName
= lpCommandLine
;
2182 /* Find whitespace of Tab */
2185 if (*ScanString
== ' ' || *ScanString
== '\t')
2188 NullBuffer
= ScanString
;
2194 NullBuffer
= ScanString
;
2198 /* Set the Null Buffer */
2199 SaveChar
= *NullBuffer
;
2200 *NullBuffer
= UNICODE_NULL
;
2202 /* Do a search for the file */
2203 DPRINT("Ready for SearchPathW: %S\n", lpApplicationName
);
2204 RetVal
= SearchPathW(NULL
,
2209 NULL
) * sizeof(WCHAR
);
2211 /* Did it find something? */
2214 /* Get file attributes */
2215 ULONG Attributes
= GetFileAttributesW(NameBuffer
);
2216 if (Attributes
& FILE_ATTRIBUTE_DIRECTORY
)
2218 /* Give it a length of 0 to fail, this was a directory. */
2224 RetVal
+= sizeof(WCHAR
);
2228 /* Now check if we have a file, and if the path size is OK */
2229 if (!RetVal
|| RetVal
>= (MAX_PATH
* sizeof(WCHAR
)))
2234 /* We failed, try to get the Path Type */
2235 DPRINT("SearchPathW failed. Retval: %ld\n", RetVal
);
2236 PathType
= RtlDetermineDosPathNameType_U(lpApplicationName
);
2238 /* If it's not relative, try to get the error */
2239 if (PathType
!= RtlPathTypeRelative
)
2241 /* This should fail, and give us a detailed LastError */
2242 hFile
= CreateFileW(lpApplicationName
,
2244 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2247 FILE_ATTRIBUTE_NORMAL
,
2250 /* Did it actually NOT fail? */
2251 if (hFile
!= INVALID_HANDLE_VALUE
)
2253 /* Fake the error */
2255 BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND
);
2260 /* Immediately set the error */
2261 BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND
);
2264 /* Did we already fail once? */
2267 SetLastError(Error
);
2271 /* Not yet, cache it */
2272 Error
= GetLastError();
2275 /* Put back the command line */
2276 *NullBuffer
= SaveChar
;
2277 lpApplicationName
= NameBuffer
;
2280 * If the search isn't done and we still have cmdline
2281 * then start over. Ex: c:\ha ha ha\haha.exe
2283 if (*ScanString
&& !SearchDone
)
2285 /* Move in the buffer */
2287 NullBuffer
= ScanString
;
2289 /* We will have to add a quote, since there is a space*/
2290 QuotesNeeded
= TRUE
;
2292 /* And we will also fake the fact we found one */
2299 /* We totally failed */
2303 /* Put back the command line */
2304 *NullBuffer
= SaveChar
;
2305 lpApplicationName
= NameBuffer
;
2306 DPRINT("SearchPathW suceeded (%ld): %S\n", RetVal
, NameBuffer
);
2308 else if (!lpCommandLine
|| *lpCommandLine
== UNICODE_NULL
)
2310 /* We have an app name (good!) but no command line */
2311 CmdLineIsAppName
= TRUE
;
2312 lpCommandLine
= (LPWSTR
)lpApplicationName
;
2315 /* At this point the name has been toyed with enough to be openable */
2316 Status
= BasepMapFile(lpApplicationName
, &hSection
, &ApplicationName
);
2318 /* Check for failure */
2319 if (!NT_SUCCESS(Status
))
2321 /* Could be a non-PE File */
2324 /* Check if the Kernel tells us it's not even valid MZ */
2325 case STATUS_INVALID_IMAGE_NE_FORMAT
:
2326 case STATUS_INVALID_IMAGE_PROTECT
:
2327 case STATUS_INVALID_IMAGE_NOT_MZ
:
2330 /* If it's a DOS app, use VDM */
2331 if ((BasepCheckDosApp(&ApplicationName
)))
2333 DPRINT1("Launching VDM...\n");
2334 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer
);
2335 RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName
.Buffer
);
2336 return CreateProcessW(L
"ntvdm.exe",
2337 (LPWSTR
)((ULONG_PTR
)lpApplicationName
), /* FIXME: Buffer must be writable!!! */
2338 lpProcessAttributes
,
2345 lpProcessInformation
);
2348 /* It's a batch file */
2349 Extension
= &ApplicationName
.Buffer
[ApplicationName
.Length
/
2352 /* Make sure the extensions are correct */
2353 if (_wcsnicmp(Extension
, L
".bat", 4) && _wcsnicmp(Extension
, L
".cmd", 4))
2355 SetLastError(ERROR_BAD_EXE_FORMAT
);
2359 /* Calculate the length of the command line */
2360 CmdLineLength
= wcslen(CMD_STRING
) + wcslen(lpCommandLine
) + 1;
2362 /* If we found quotes, then add them into the length size */
2363 if (CmdLineIsAppName
|| FoundQuotes
) CmdLineLength
+= 2;
2364 CmdLineLength
*= sizeof(WCHAR
);
2366 /* Allocate space for the new command line */
2367 BatchCommandLine
= RtlAllocateHeap(RtlGetProcessHeap(),
2370 if (BatchCommandLine
== NULL
)
2372 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2377 wcscpy(BatchCommandLine
, CMD_STRING
);
2378 if (CmdLineIsAppName
|| FoundQuotes
)
2380 wcscat(BatchCommandLine
, L
"\"");
2382 wcscat(BatchCommandLine
, lpCommandLine
);
2383 if (CmdLineIsAppName
|| FoundQuotes
)
2385 wcscat(BatchCommandLine
, L
"\"");
2388 /* Create it as a Unicode String */
2389 RtlInitUnicodeString(&CommandLineString
, BatchCommandLine
);
2391 /* Set the command line to this */
2392 lpCommandLine
= CommandLineString
.Buffer
;
2393 lpApplicationName
= NULL
;
2396 RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName
.Buffer
);
2397 ApplicationName
.Buffer
= NULL
;
2401 case STATUS_INVALID_IMAGE_WIN_16
:
2403 /* It's a Win16 Image, use VDM */
2404 DPRINT1("Launching VDM...\n");
2405 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer
);
2406 RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName
.Buffer
);
2407 return CreateProcessW(L
"ntvdm.exe",
2408 (LPWSTR
)((ULONG_PTR
)lpApplicationName
), /* FIXME: Buffer must be writable!!! */
2409 lpProcessAttributes
,
2416 lpProcessInformation
);
2418 case STATUS_OBJECT_NAME_NOT_FOUND
:
2419 case STATUS_OBJECT_PATH_NOT_FOUND
:
2420 BaseSetLastNTError(Status
);
2424 /* Invalid Image Type */
2425 SetLastError(ERROR_BAD_EXE_FORMAT
);
2430 /* Use our desktop if we didn't get any */
2431 if (!StartupInfo
.lpDesktop
)
2433 StartupInfo
.lpDesktop
= OurPeb
->ProcessParameters
->DesktopInfo
.Buffer
;
2436 /* FIXME: Check if Application is allowed to run */
2438 /* FIXME: Allow CREATE_SEPARATE only for WOW Apps, once we have that. */
2440 /* Get some information about the executable */
2441 Status
= ZwQuerySection(hSection
,
2442 SectionImageInformation
,
2444 sizeof(SectionImageInfo
),
2446 if(!NT_SUCCESS(Status
))
2448 DPRINT1("Unable to get SectionImageInformation, status 0x%x\n", Status
);
2449 BaseSetLastNTError(Status
);
2453 /* Don't execute DLLs */
2454 if (SectionImageInfo
.ImageCharacteristics
& IMAGE_FILE_DLL
)
2456 DPRINT1("Can't execute a DLL\n");
2457 SetLastError(ERROR_BAD_EXE_FORMAT
);
2461 /* FIXME: Check for Debugger */
2463 /* FIXME: Check if Machine Type and SubSys Version Match */
2465 /* We don't support POSIX or anything else for now */
2466 if (IMAGE_SUBSYSTEM_WINDOWS_GUI
!= SectionImageInfo
.SubSystemType
&&
2467 IMAGE_SUBSYSTEM_WINDOWS_CUI
!= SectionImageInfo
.SubSystemType
)
2469 DPRINT1("Invalid subsystem %d\n", SectionImageInfo
.SubSystemType
);
2470 SetLastError(ERROR_BAD_EXE_FORMAT
);
2474 if (IMAGE_SUBSYSTEM_WINDOWS_GUI
== SectionImageInfo
.SubSystemType
)
2476 /* Do not create a console for GUI applications */
2477 dwCreationFlags
&= ~CREATE_NEW_CONSOLE
;
2478 dwCreationFlags
|= DETACHED_PROCESS
;
2481 /* Initialize the process object attributes */
2482 ObjectAttributes
= BaseFormatObjectAttributes(&LocalObjectAttributes
,
2483 lpProcessAttributes
,
2486 /* Check if we're going to be debugged */
2487 if (dwCreationFlags
& DEBUG_PROCESS
)
2489 /* FIXME: Set process flag */
2492 /* Check if we're going to be debugged */
2493 if (dwCreationFlags
& (DEBUG_PROCESS
| DEBUG_ONLY_THIS_PROCESS
))
2495 /* Connect to DbgUi */
2496 Status
= DbgUiConnectToDbg();
2497 if (!NT_SUCCESS(Status
))
2499 DPRINT1("Failed to connect to DbgUI!\n");
2500 BaseSetLastNTError(Status
);
2504 /* Get the debug object */
2505 hDebug
= DbgUiGetThreadDebugObject();
2507 /* Check if only this process will be debugged */
2508 if (dwCreationFlags
& DEBUG_ONLY_THIS_PROCESS
)
2510 /* FIXME: Set process flag */
2514 /* Create the Process */
2515 Status
= NtCreateProcess(&hProcess
,
2519 (BOOLEAN
)bInheritHandles
,
2523 if (!NT_SUCCESS(Status
))
2525 DPRINT1("Unable to create process, status 0x%x\n", Status
);
2526 BaseSetLastNTError(Status
);
2530 if (PriorityClass
.PriorityClass
!= PROCESS_PRIORITY_CLASS_INVALID
)
2533 Status
= NtSetInformationProcess(hProcess
,
2534 ProcessPriorityClass
,
2536 sizeof(PROCESS_PRIORITY_CLASS
));
2537 if(!NT_SUCCESS(Status
))
2539 DPRINT1("Unable to set new process priority, status 0x%x\n", Status
);
2540 BaseSetLastNTError(Status
);
2545 /* Set Error Mode */
2546 if (dwCreationFlags
& CREATE_DEFAULT_ERROR_MODE
)
2548 ULONG ErrorMode
= SEM_FAILCRITICALERRORS
;
2549 NtSetInformationProcess(hProcess
,
2550 ProcessDefaultHardErrorMode
,
2555 /* Convert the directory to a full path */
2556 if (lpCurrentDirectory
)
2558 /* Allocate a buffer */
2559 CurrentDirectory
= RtlAllocateHeap(RtlGetProcessHeap(),
2561 (MAX_PATH
+ 1) * sizeof(WCHAR
));
2562 if (CurrentDirectory
== NULL
)
2564 DPRINT1("Cannot allocate memory for directory name\n");
2565 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2569 /* Get the length */
2570 if (GetFullPathNameW(lpCurrentDirectory
,
2573 &CurrentDirectoryPart
) > MAX_PATH
)
2575 DPRINT1("Directory name too long\n");
2576 SetLastError(ERROR_DIRECTORY
);
2581 /* Insert quotes if needed */
2582 if (QuotesNeeded
|| CmdLineIsAppName
)
2584 /* Allocate a buffer */
2585 QuotedCmdLine
= RtlAllocateHeap(RtlGetProcessHeap(),
2587 (wcslen(lpCommandLine
) + 2 + 1) *
2589 if (QuotedCmdLine
== NULL
)
2591 DPRINT1("Cannot allocate memory for quoted command line\n");
2592 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2596 /* Copy the first quote */
2597 wcscpy(QuotedCmdLine
, L
"\"");
2599 /* Save a null char */
2602 SaveChar
= *NullBuffer
;
2603 *NullBuffer
= UNICODE_NULL
;
2606 /* Add the command line and the finishing quote */
2607 wcscat(QuotedCmdLine
, lpCommandLine
);
2608 wcscat(QuotedCmdLine
, L
"\"");
2610 /* Add the null char */
2613 *NullBuffer
= SaveChar
;
2614 wcscat(QuotedCmdLine
, NullBuffer
);
2617 DPRINT("Quoted CmdLine: %S\n", QuotedCmdLine
);
2622 if (QuotedCmdLine
== NULL
)
2624 QuotedCmdLine
= RtlAllocateHeap(RtlGetProcessHeap(),
2626 (wcslen(lpCommandLine
) + 1) * sizeof(WCHAR
));
2627 if (QuotedCmdLine
== NULL
)
2629 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2632 wcscpy(QuotedCmdLine
, lpCommandLine
);
2635 ScanString
= QuotedCmdLine
;
2636 while (NULL
!= (ScanString
= wcschr(ScanString
, L
'^')))
2639 if (*ScanString
== L
'\"' || *ScanString
== L
'^' || *ScanString
== L
'\\')
2641 memmove(ScanString
-1, ScanString
, wcslen(ScanString
) * sizeof(WCHAR
) + sizeof(WCHAR
));
2646 /* Get the Process Information */
2647 Status
= NtQueryInformationProcess(hProcess
,
2648 ProcessBasicInformation
,
2650 sizeof(ProcessBasicInfo
),
2653 /* Convert the environment */
2654 if(lpEnvironment
&& !(dwCreationFlags
& CREATE_UNICODE_ENVIRONMENT
))
2656 lpEnvironment
= BasepConvertUnicodeEnvironment(&EnvSize
, lpEnvironment
);
2657 if (!lpEnvironment
) goto Cleanup
;
2660 /* Create Process Environment */
2661 RemotePeb
= ProcessBasicInfo
.PebBaseAddress
;
2662 Status
= BasePushProcessParameters(hProcess
,
2664 (LPWSTR
)lpApplicationName
,
2666 (QuotesNeeded
|| CmdLineIsAppName
|| Escape
) ?
2667 QuotedCmdLine
: lpCommandLine
,
2674 /* Cleanup Environment */
2675 if (lpEnvironment
&& !(dwCreationFlags
& CREATE_UNICODE_ENVIRONMENT
))
2677 RtlDestroyEnvironment(lpEnvironment
);
2680 if (!NT_SUCCESS(Status
))
2682 DPRINT1("Could not initialize Process Environment\n");
2683 BaseSetLastNTError(Status
);
2687 /* Close the section */
2691 /* Duplicate the handles if needed */
2692 if (!bInheritHandles
&& !(StartupInfo
.dwFlags
& STARTF_USESTDHANDLES
) &&
2693 SectionImageInfo
.SubSystemType
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
2695 PRTL_USER_PROCESS_PARAMETERS RemoteParameters
;
2697 /* Get the remote parameters */
2698 Status
= NtReadVirtualMemory(hProcess
,
2699 &RemotePeb
->ProcessParameters
,
2703 if (!NT_SUCCESS(Status
))
2705 DPRINT1("Failed to read memory\n");
2709 /* Duplicate and write the handles */
2710 BasepDuplicateAndWriteHandle(hProcess
,
2711 OurPeb
->ProcessParameters
->StandardInput
,
2712 &RemoteParameters
->StandardInput
);
2713 BasepDuplicateAndWriteHandle(hProcess
,
2714 OurPeb
->ProcessParameters
->StandardOutput
,
2715 &RemoteParameters
->StandardOutput
);
2716 BasepDuplicateAndWriteHandle(hProcess
,
2717 OurPeb
->ProcessParameters
->StandardError
,
2718 &RemoteParameters
->StandardError
);
2722 Status
= BasepNotifyCsrOfCreation(dwCreationFlags
,
2723 (HANDLE
)ProcessBasicInfo
.UniqueProcessId
,
2726 if (!NT_SUCCESS(Status
))
2728 DPRINT1("CSR Notification Failed\n");
2729 BaseSetLastNTError(Status
);
2733 /* Create the first thread */
2734 DPRINT("Creating thread for process (EntryPoint = 0x%p)\n",
2735 SectionImageInfo
.TransferAddress
);
2736 hThread
= BasepCreateFirstThread(hProcess
,
2741 if (hThread
== NULL
)
2743 DPRINT1("Could not create Initial Thread\n");
2744 /* FIXME - set last error code */
2748 if (!(dwCreationFlags
& CREATE_SUSPENDED
))
2750 NtResumeThread(hThread
, &Dummy
);
2754 lpProcessInformation
->dwProcessId
= (DWORD
)ClientId
.UniqueProcess
;
2755 lpProcessInformation
->dwThreadId
= (DWORD
)ClientId
.UniqueThread
;
2756 lpProcessInformation
->hProcess
= hProcess
;
2757 lpProcessInformation
->hThread
= hThread
;
2758 DPRINT("hThread[%p]: %p inside hProcess[%p]: %p\n", hThread
,
2759 ClientId
.UniqueThread
, ClientId
.UniqueProcess
, hProcess
);
2760 hProcess
= hThread
= NULL
;
2764 /* De-allocate heap strings */
2765 if (NameBuffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer
);
2766 if (ApplicationName
.Buffer
)
2767 RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName
.Buffer
);
2768 if (CurrentDirectory
) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDirectory
);
2769 if (QuotedCmdLine
) RtlFreeHeap(RtlGetProcessHeap(), 0, QuotedCmdLine
);
2771 /* Kill any handles still alive */
2772 if (hSection
) NtClose(hSection
);
2775 /* We don't know any more details then this */
2776 NtTerminateProcess(hProcess
, STATUS_UNSUCCESSFUL
);
2779 if (hProcess
) NtClose(hProcess
);
2781 /* Return Success */
2790 CreateProcessW(LPCWSTR lpApplicationName
,
2791 LPWSTR lpCommandLine
,
2792 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
2793 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
2794 BOOL bInheritHandles
,
2795 DWORD dwCreationFlags
,
2796 LPVOID lpEnvironment
,
2797 LPCWSTR lpCurrentDirectory
,
2798 LPSTARTUPINFOW lpStartupInfo
,
2799 LPPROCESS_INFORMATION lpProcessInformation
)
2801 /* Call the internal (but exported) version */
2802 return CreateProcessInternalW(0,
2805 lpProcessAttributes
,
2812 lpProcessInformation
,
2821 CreateProcessInternalA(HANDLE hToken
,
2822 LPCSTR lpApplicationName
,
2823 LPSTR lpCommandLine
,
2824 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
2825 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
2826 BOOL bInheritHandles
,
2827 DWORD dwCreationFlags
,
2828 LPVOID lpEnvironment
,
2829 LPCSTR lpCurrentDirectory
,
2830 LPSTARTUPINFOA lpStartupInfo
,
2831 LPPROCESS_INFORMATION lpProcessInformation
,
2834 PUNICODE_STRING CommandLine
= NULL
;
2835 UNICODE_STRING DummyString
;
2836 UNICODE_STRING LiveCommandLine
;
2837 UNICODE_STRING ApplicationName
;
2838 UNICODE_STRING CurrentDirectory
;
2840 STARTUPINFOW StartupInfo
;
2842 DPRINT("dwCreationFlags %x, lpEnvironment %x, lpCurrentDirectory %x, "
2843 "lpStartupInfo %x, lpProcessInformation %x\n",
2844 dwCreationFlags
, lpEnvironment
, lpCurrentDirectory
,
2845 lpStartupInfo
, lpProcessInformation
);
2847 /* Copy Startup Info */
2848 RtlMoveMemory(&StartupInfo
, lpStartupInfo
, sizeof(*lpStartupInfo
));
2850 /* Initialize all strings to nothing */
2851 LiveCommandLine
.Buffer
= NULL
;
2852 DummyString
.Buffer
= NULL
;
2853 ApplicationName
.Buffer
= NULL
;
2854 CurrentDirectory
.Buffer
= NULL
;
2855 StartupInfo
.lpDesktop
= NULL
;
2856 StartupInfo
.lpReserved
= NULL
;
2857 StartupInfo
.lpTitle
= NULL
;
2859 /* Convert the Command line */
2862 /* If it's too long, then we'll have a problem */
2863 if ((strlen(lpCommandLine
) + 1) * sizeof(WCHAR
) <
2864 NtCurrentTeb()->StaticUnicodeString
.MaximumLength
)
2866 /* Cache it in the TEB */
2867 CommandLine
= Basep8BitStringToStaticUnicodeString(lpCommandLine
);
2871 /* Use a dynamic version */
2872 Basep8BitStringToDynamicUnicodeString(&LiveCommandLine
,
2878 /* The logic below will use CommandLine, so we must make it valid */
2879 CommandLine
= &DummyString
;
2882 /* Convert the Name and Directory */
2883 if (lpApplicationName
)
2885 Basep8BitStringToDynamicUnicodeString(&ApplicationName
,
2888 if (lpCurrentDirectory
)
2890 Basep8BitStringToDynamicUnicodeString(&CurrentDirectory
,
2891 lpCurrentDirectory
);
2894 /* Now convert Startup Strings */
2895 if (lpStartupInfo
->lpReserved
)
2897 BasepAnsiStringToHeapUnicodeString(lpStartupInfo
->lpReserved
,
2898 &StartupInfo
.lpReserved
);
2900 if (lpStartupInfo
->lpDesktop
)
2902 BasepAnsiStringToHeapUnicodeString(lpStartupInfo
->lpDesktop
,
2903 &StartupInfo
.lpDesktop
);
2905 if (lpStartupInfo
->lpTitle
)
2907 BasepAnsiStringToHeapUnicodeString(lpStartupInfo
->lpTitle
,
2908 &StartupInfo
.lpTitle
);
2911 /* Call the Unicode function */
2912 bRetVal
= CreateProcessInternalW(hToken
,
2913 ApplicationName
.Buffer
,
2914 LiveCommandLine
.Buffer
?
2915 LiveCommandLine
.Buffer
: CommandLine
->Buffer
,
2916 lpProcessAttributes
,
2921 CurrentDirectory
.Buffer
,
2923 lpProcessInformation
,
2927 RtlFreeUnicodeString(&ApplicationName
);
2928 RtlFreeUnicodeString(&LiveCommandLine
);
2929 RtlFreeUnicodeString(&CurrentDirectory
);
2930 RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo
.lpDesktop
);
2931 RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo
.lpReserved
);
2932 RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo
.lpTitle
);
2934 /* Return what Unicode did */
2939 * FUNCTION: The CreateProcess function creates a new process and its
2940 * primary thread. The new process executes the specified executable file
2943 * lpApplicationName = Pointer to name of executable module
2944 * lpCommandLine = Pointer to command line string
2945 * lpProcessAttributes = Process security attributes
2946 * lpThreadAttributes = Thread security attributes
2947 * bInheritHandles = Handle inheritance flag
2948 * dwCreationFlags = Creation flags
2949 * lpEnvironment = Pointer to new environment block
2950 * lpCurrentDirectory = Pointer to current directory name
2951 * lpStartupInfo = Pointer to startup info
2952 * lpProcessInformation = Pointer to process information
2958 CreateProcessA(LPCSTR lpApplicationName
,
2959 LPSTR lpCommandLine
,
2960 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
2961 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
2962 BOOL bInheritHandles
,
2963 DWORD dwCreationFlags
,
2964 LPVOID lpEnvironment
,
2965 LPCSTR lpCurrentDirectory
,
2966 LPSTARTUPINFOA lpStartupInfo
,
2967 LPPROCESS_INFORMATION lpProcessInformation
)
2969 /* Call the internal (but exported) version */
2970 return CreateProcessInternalA(0,
2973 lpProcessAttributes
,
2980 lpProcessInformation
,