2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/kernel32/proc/proc.c
5 * PURPOSE: Process functions
6 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
11 /* INCLUDES ****************************************************************/
15 #include <kernel32/proc.h>
16 #include <kernel32/thread.h>
23 #include <kernel32/kernel32.h>
25 /* GLOBALS *****************************************************************/
27 static NT_PEB
*CurrentPeb
;
30 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle
;
32 VOID
RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle
);
34 /* FUNCTIONS ****************************************************************/
36 WINBOOL STDCALL
GetProcessId(HANDLE hProcess
, LPDWORD lpProcessId
);
38 NT_PEB
*GetCurrentPeb(VOID
)
40 if ( CurrentPeb
!= NULL
)
42 else // hack to be able to return a process environment any time.
46 HANDLE STDCALL
GetCurrentProcess(VOID
)
48 return (HANDLE
)NtCurrentProcess();
51 HANDLE STDCALL
GetCurrentThread(VOID
)
53 return (HANDLE
)NtCurrentThread();
56 DWORD STDCALL
GetCurrentProcessId(VOID
)
58 return (DWORD
)(GetTeb()->Cid
).UniqueProcess
;
61 WINBOOL STDCALL
GetExitCodeProcess(HANDLE hProcess
, LPDWORD lpExitCode
)
64 PROCESS_BASIC_INFORMATION ProcessBasic
;
67 errCode
= NtQueryInformationProcess(hProcess
,
68 ProcessBasicInformation
,
70 sizeof(PROCESS_BASIC_INFORMATION
),
72 if (!NT_SUCCESS(errCode
))
74 SetLastError(RtlNtStatusToDosError(errCode
));
77 memcpy( lpExitCode
,&ProcessBasic
.ExitStatus
,sizeof(DWORD
));
81 WINBOOL STDCALL
GetProcessId(HANDLE hProcess
, LPDWORD lpProcessId
)
84 PROCESS_BASIC_INFORMATION ProcessBasic
;
87 errCode
= NtQueryInformationProcess(hProcess
,
88 ProcessBasicInformation
,
90 sizeof(PROCESS_BASIC_INFORMATION
),
92 if (!NT_SUCCESS(errCode
))
94 SetLastError(RtlNtStatusToDosError(errCode
));
97 memcpy( lpProcessId
,&ProcessBasic
.UniqueProcessId
,sizeof(DWORD
));
101 PWSTR
InternalAnsiToUnicode(PWSTR Out
, LPCSTR In
, ULONG MaxLength
)
112 while ((*In
)!=0 && i
< MaxLength
)
123 WINBOOL STDCALL
CreateProcessA(LPCSTR lpApplicationName
,
125 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
126 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
127 WINBOOL bInheritHandles
,
128 DWORD dwCreationFlags
,
129 LPVOID lpEnvironment
,
130 LPCSTR lpCurrentDirectory
,
131 LPSTARTUPINFO lpStartupInfo
,
132 LPPROCESS_INFORMATION lpProcessInformation
)
134 * FUNCTION: The CreateProcess function creates a new process and its
135 * primary thread. The new process executes the specified executable file
138 * lpApplicationName = Pointer to name of executable module
139 * lpCommandLine = Pointer to command line string
140 * lpProcessAttributes = Process security attributes
141 * lpThreadAttributes = Thread security attributes
142 * bInheritHandles = Handle inheritance flag
143 * dwCreationFlags = Creation flags
144 * lpEnvironment = Pointer to new environment block
145 * lpCurrentDirectory = Pointer to current directory name
146 * lpStartupInfo = Pointer to startup info
147 * lpProcessInformation = Pointer to process information
150 WCHAR ApplicationNameW
[MAX_PATH
];
151 WCHAR CommandLineW
[MAX_PATH
];
152 WCHAR CurrentDirectoryW
[MAX_PATH
];
153 PWSTR PApplicationNameW
;
155 PWSTR PCurrentDirectoryW
;
158 DPRINT("CreateProcessA\n");
160 PApplicationNameW
= InternalAnsiToUnicode(ApplicationNameW
,
163 PCommandLineW
= InternalAnsiToUnicode(CommandLineW
,
166 PCurrentDirectoryW
= InternalAnsiToUnicode(CurrentDirectoryW
,
169 return CreateProcessW(PApplicationNameW
,
178 lpProcessInformation
);
182 WINBOOL STDCALL
CreateProcessW(LPCWSTR lpApplicationName
,
183 LPWSTR lpCommandLine
,
184 LPSECURITY_ATTRIBUTES lpProcessAttributes
,
185 LPSECURITY_ATTRIBUTES lpThreadAttributes
,
186 WINBOOL bInheritHandles
,
187 DWORD dwCreationFlags
,
188 LPVOID lpEnvironment
,
189 LPCWSTR lpCurrentDirectory
,
190 LPSTARTUPINFO lpStartupInfo
,
191 LPPROCESS_INFORMATION lpProcessInformation
)
193 HANDLE hFile
, hSection
, hProcess
, hThread
;
194 KPRIORITY PriorityClass
;
195 OBJECT_ATTRIBUTES ObjectAttributes
;
196 IO_STATUS_BLOCK IoStatusBlock
;
197 BOOLEAN CreateSuspended
;
199 UNICODE_STRING ApplicationNameString
;
200 LPTHREAD_START_ROUTINE lpStartAddress
= NULL
;
201 LPVOID lpParameter
= NULL
;
202 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
203 WCHAR TempApplicationName
[255];
204 WCHAR TempFileName
[255];
205 WCHAR TempDirectoryName
[255];
209 LARGE_INTEGER SectionOffset
;
211 DPRINT("CreateProcessW(lpApplicationName '%w', lpCommandLine '%w')\n",
212 lpApplicationName
,lpCommandLine
);
217 * Find the application name
219 TempApplicationName
[0] = '\\';
220 TempApplicationName
[1] = '?';
221 TempApplicationName
[2] = '?';
222 TempApplicationName
[3] = '\\';
223 TempApplicationName
[4] = 0;
225 DPRINT("TempApplicationName '%w'\n",TempApplicationName
);
227 if (lpApplicationName
!= NULL
)
229 wcscpy(TempFileName
, lpApplicationName
);
231 DPRINT("TempFileName '%w'\n",TempFileName
);
235 wcscpy(TempFileName
, lpCommandLine
);
237 DPRINT("TempFileName '%w'\n",TempFileName
);
239 for (i
=0; TempFileName
[i
]!=' ' && TempFileName
[i
] != 0; i
++);
243 if (TempFileName
[1] != ':')
245 GetCurrentDirectoryW(MAX_PATH
,TempDirectoryName
);
246 wcscat(TempApplicationName
,TempDirectoryName
);
248 wcscat(TempApplicationName
,TempFileName
);
250 RtlInitUnicodeString(&ApplicationNameString
, TempApplicationName
);
252 DPRINT("ApplicationName %w\n",ApplicationNameString
.Buffer
);
254 InitializeObjectAttributes(&ObjectAttributes
,
255 &ApplicationNameString
,
256 OBJ_CASE_INSENSITIVE
,
261 * Try to open the executable
264 errCode
= NtOpenFile(&hFile
,
265 SYNCHRONIZE
|FILE_EXECUTE
|FILE_READ_DATA
,
268 FILE_SHARE_DELETE
|FILE_SHARE_READ
,
269 FILE_SYNCHRONOUS_IO_NONALERT
|FILE_NON_DIRECTORY_FILE
);
271 if ( !NT_SUCCESS(errCode
) )
273 SetLastError(RtlNtStatusToDosError(errCode
));
277 errCode
= NtCreateSection(&hSection
,
286 if ( !NT_SUCCESS(errCode
) )
288 SetLastError(RtlNtStatusToDosError(errCode
));
292 errCode
= NtCreateProcess(&hProcess
,
301 BaseAddress
= (PVOID
)0x10000;
302 LARGE_INTEGER_QUAD_PART(SectionOffset
) = 0;
304 NtMapViewOfSection(hSection
,
318 if ( !NT_SUCCESS(errCode
) )
320 SetLastError(RtlNtStatusToDosError(errCode
));
325 PriorityClass
= NORMAL_PRIORITY_CLASS
;
326 NtSetInformationProcess(hProcess
,
331 DPRINT("Creating thread for process\n");
332 lpStartAddress
= BaseAddress
;
333 hThread
= CreateRemoteThread(hProcess
,
339 &lpProcessInformation
->dwThreadId
);
341 if ( hThread
== NULL
)
344 lpProcessInformation
->hProcess
= hProcess
;
345 lpProcessInformation
->hThread
= hThread
;
347 GetProcessId(hProcess
,&lpProcessInformation
->dwProcessId
);
354 HANDLE STDCALL
OpenProcess(DWORD dwDesiredAccess
,
355 WINBOOL bInheritHandle
,
359 HANDLE ProcessHandle
;
360 OBJECT_ATTRIBUTES ObjectAttributes
;
363 ClientId
.UniqueProcess
= (HANDLE
)dwProcessId
;
364 ObjectAttributes
.Length
= sizeof(OBJECT_ATTRIBUTES
);
365 ObjectAttributes
.RootDirectory
= (HANDLE
)NULL
;
366 ObjectAttributes
.SecurityDescriptor
= NULL
;
367 ObjectAttributes
.SecurityQualityOfService
= NULL
;
369 if ( bInheritHandle
== TRUE
)
370 ObjectAttributes
.Attributes
= OBJ_INHERIT
;
372 ObjectAttributes
.Attributes
= 0;
374 errCode
= NtOpenProcess(&ProcessHandle
,
378 if (!NT_SUCCESS(errCode
))
380 SetLastError(RtlNtStatusToDosError(errCode
));
383 return ProcessHandle
;
398 UINT
WinExec (LPCSTR lpCmdLine
, UINT uCmdShow
)
400 STARTUPINFO StartupInfo
;
401 PROCESS_INFORMATION ProcessInformation
;
405 StartupInfo
.cb
= sizeof(STARTUPINFO
);
406 StartupInfo
.wShowWindow
= uCmdShow
;
407 StartupInfo
.dwFlags
= 0;
409 hInst
= (HINSTANCE
)CreateProcessA(NULL
,
418 &ProcessInformation
);
421 dosErr
= GetLastError();
424 if ( lpfnGlobalRegisterWaitForInputIdle
!= NULL
)
425 lpfnGlobalRegisterWaitForInputIdle(ProcessInformation
.hProcess
,10000);
426 NtClose(ProcessInformation
.hProcess
);
427 NtClose(ProcessInformation
.hThread
);
433 VOID
RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle
)
435 lpfnGlobalRegisterWaitForInputIdle
= lpfnRegisterWaitForInputIdle
;
439 DWORD STDCALL
WaitForInputIdle(HANDLE hProcess
,
440 DWORD dwMilliseconds
)
451 SleepEx(dwMilliseconds
,FALSE
);
458 DWORD dwMilliseconds
,
465 Interval
.LowPart
= dwMilliseconds
* 1000;
466 Interval
.HighPart
= 0;
467 errCode
= NtDelayExecution(bAlertable
,&Interval
);
468 if ( !NT_SUCCESS(errCode
) ) {
469 SetLastError(RtlNtStatusToDosError(errCode
));
482 LPSTARTUPINFO lpStartupInfo
485 NT_PEB
*pPeb
= GetCurrentPeb();
487 if (lpStartupInfo
== NULL
) {
488 SetLastError(ERROR_INVALID_PARAMETER
);
492 lpStartupInfo
->cb
= sizeof(STARTUPINFO
);
493 lstrcpyW(lpStartupInfo
->lpDesktop
, pPeb
->StartupInfo
->Desktop
);
494 lstrcpyW(lpStartupInfo
->lpTitle
, pPeb
->StartupInfo
->Title
);
495 lpStartupInfo
->dwX
= pPeb
->StartupInfo
->dwX
;
496 lpStartupInfo
->dwY
= pPeb
->StartupInfo
->dwY
;
497 lpStartupInfo
->dwXSize
= pPeb
->StartupInfo
->dwXSize
;
498 lpStartupInfo
->dwYSize
= pPeb
->StartupInfo
->dwYSize
;
499 lpStartupInfo
->dwXCountChars
= pPeb
->StartupInfo
->dwXCountChars
;
500 lpStartupInfo
->dwYCountChars
= pPeb
->StartupInfo
->dwYCountChars
;
501 lpStartupInfo
->dwFillAttribute
= pPeb
->StartupInfo
->dwFillAttribute
;
502 lpStartupInfo
->dwFlags
= pPeb
->StartupInfo
->dwFlags
;
503 lpStartupInfo
->wShowWindow
= pPeb
->StartupInfo
->wShowWindow
;
504 //lpStartupInfo->cbReserved2 = pPeb->StartupInfo->cbReserved;
505 //lpStartupInfo->lpReserved = pPeb->StartupInfo->lpReserved1;
506 //lpStartupInfo->lpReserved2 = pPeb->StartupInfo->lpReserved2;
508 lpStartupInfo
->hStdInput
= pPeb
->StartupInfo
->hStdInput
;
509 lpStartupInfo
->hStdOutput
= pPeb
->StartupInfo
->hStdOutput
;
510 lpStartupInfo
->hStdError
= pPeb
->StartupInfo
->hStdError
;
524 LPSTARTUPINFO lpStartupInfo
527 NT_PEB
*pPeb
= GetCurrentPeb();
529 if (lpStartupInfo
== NULL
) {
530 SetLastError(ERROR_INVALID_PARAMETER
);
535 lpStartupInfo
->cb
= sizeof(STARTUPINFO
);
538 while ((pPeb
->StartupInfo
->Desktop
[i
])!=0 && i
< MAX_PATH
)
540 lpStartupInfo
->lpDesktop
[i
] = (unsigned char)pPeb
->StartupInfo
->Desktop
[i
];
543 lpStartupInfo
->lpDesktop
[i
] = 0;
546 while ((pPeb
->StartupInfo
->Title
[i
])!=0 && i
< MAX_PATH
)
548 lpStartupInfo
->lpTitle
[i
] = (unsigned char)pPeb
->StartupInfo
->Title
[i
];
551 lpStartupInfo
->lpTitle
[i
] = 0;
553 lpStartupInfo
->dwX
= pPeb
->StartupInfo
->dwX
;
554 lpStartupInfo
->dwY
= pPeb
->StartupInfo
->dwY
;
555 lpStartupInfo
->dwXSize
= pPeb
->StartupInfo
->dwXSize
;
556 lpStartupInfo
->dwYSize
= pPeb
->StartupInfo
->dwYSize
;
557 lpStartupInfo
->dwXCountChars
= pPeb
->StartupInfo
->dwXCountChars
;
558 lpStartupInfo
->dwYCountChars
= pPeb
->StartupInfo
->dwYCountChars
;
559 lpStartupInfo
->dwFillAttribute
= pPeb
->StartupInfo
->dwFillAttribute
;
560 lpStartupInfo
->dwFlags
= pPeb
->StartupInfo
->dwFlags
;
561 lpStartupInfo
->wShowWindow
= pPeb
->StartupInfo
->wShowWindow
;
562 //lpStartupInfo->cbReserved2 = pPeb->StartupInfo->cbReserved;
563 //lpStartupInfo->lpReserved = pPeb->StartupInfo->lpReserved1;
564 //lpStartupInfo->lpReserved2 = pPeb->StartupInfo->lpReserved2;
566 lpStartupInfo
->hStdInput
= pPeb
->StartupInfo
->hStdInput
;
567 lpStartupInfo
->hStdOutput
= pPeb
->StartupInfo
->hStdOutput
;
568 lpStartupInfo
->hStdError
= pPeb
->StartupInfo
->hStdError
;
575 FlushInstructionCache(
579 LPCVOID lpBaseAddress
,
584 errCode
= NtFlushInstructionCache(hProcess
,(PVOID
)lpBaseAddress
,dwSize
);
585 if ( !NT_SUCCESS(errCode
) ) {
586 SetLastError(RtlNtStatusToDosError(errCode
));
592 VOID STDCALL
ExitProcess(UINT uExitCode
)
594 NtTerminateProcess(NtCurrentProcess() ,uExitCode
);
604 WCHAR MessageTextW
[MAX_PATH
];
607 while ((*lpMessageText
)!=0 && i
< 35)
609 MessageTextW
[i
] = *lpMessageText
;
615 return FatalAppExitW(uAction
,MessageTextW
);
620 VOID STDCALL
FatalAppExitW(UINT uAction
, LPCWSTR lpMessageText
)