Fixed several bugs
[reactos.git] / reactos / lib / kernel32 / process / proc.c
1 /*
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)
7 * UPDATE HISTORY:
8 * Created 01/11/98
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #define UNICODE
14 #include <windows.h>
15 #include <kernel32/proc.h>
16 #include <kernel32/thread.h>
17 #include <wstring.h>
18 #include <string.h>
19 #include <ddk/rtl.h>
20 #include <ddk/li.h>
21
22 #define NDEBUG
23 #include <kernel32/kernel32.h>
24
25 /* GLOBALS *****************************************************************/
26
27 static NT_PEB *CurrentPeb;
28 static NT_PEB Peb;
29
30 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
31
32 VOID RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
33
34 /* FUNCTIONS ****************************************************************/
35
36 WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId);
37
38 NT_PEB *GetCurrentPeb(VOID)
39 {
40 if ( CurrentPeb != NULL )
41 return CurrentPeb;
42 else // hack to be able to return a process environment any time.
43 return &Peb;
44 }
45
46 HANDLE STDCALL GetCurrentProcess(VOID)
47 {
48 return (HANDLE)NtCurrentProcess();
49 }
50
51 HANDLE STDCALL GetCurrentThread(VOID)
52 {
53 return (HANDLE)NtCurrentThread();
54 }
55
56 DWORD STDCALL GetCurrentProcessId(VOID)
57 {
58 return (DWORD)(GetTeb()->Cid).UniqueProcess;
59 }
60
61 WINBOOL STDCALL GetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode )
62 {
63 NTSTATUS errCode;
64 PROCESS_BASIC_INFORMATION ProcessBasic;
65 ULONG BytesWritten;
66
67 errCode = NtQueryInformationProcess(hProcess,
68 ProcessBasicInformation,
69 &ProcessBasic,
70 sizeof(PROCESS_BASIC_INFORMATION),
71 &BytesWritten);
72 if (!NT_SUCCESS(errCode))
73 {
74 SetLastError(RtlNtStatusToDosError(errCode));
75 return FALSE;
76 }
77 memcpy( lpExitCode ,&ProcessBasic.ExitStatus,sizeof(DWORD));
78 return TRUE;
79 }
80
81 WINBOOL STDCALL GetProcessId(HANDLE hProcess, LPDWORD lpProcessId )
82 {
83 NTSTATUS errCode;
84 PROCESS_BASIC_INFORMATION ProcessBasic;
85 ULONG BytesWritten;
86
87 errCode = NtQueryInformationProcess(hProcess,
88 ProcessBasicInformation,
89 &ProcessBasic,
90 sizeof(PROCESS_BASIC_INFORMATION),
91 &BytesWritten);
92 if (!NT_SUCCESS(errCode))
93 {
94 SetLastError(RtlNtStatusToDosError(errCode));
95 return FALSE;
96 }
97 memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD));
98 return TRUE;
99 }
100
101 PWSTR InternalAnsiToUnicode(PWSTR Out, LPCSTR In, ULONG MaxLength)
102 {
103 ULONG i;
104
105 if (In == NULL)
106 {
107 return(NULL);
108 }
109 else
110 {
111 i = 0;
112 while ((*In)!=0 && i < MaxLength)
113 {
114 Out[i] = *In;
115 In++;
116 i++;
117 }
118 Out[i] = 0;
119 return(Out);
120 }
121 }
122
123 WINBOOL STDCALL CreateProcessA(LPCSTR lpApplicationName,
124 LPSTR lpCommandLine,
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)
133 /*
134 * FUNCTION: The CreateProcess function creates a new process and its
135 * primary thread. The new process executes the specified executable file
136 * ARGUMENTS:
137 *
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
148 */
149 {
150 WCHAR ApplicationNameW[MAX_PATH];
151 WCHAR CommandLineW[MAX_PATH];
152 WCHAR CurrentDirectoryW[MAX_PATH];
153 PWSTR PApplicationNameW;
154 PWSTR PCommandLineW;
155 PWSTR PCurrentDirectoryW;
156 ULONG i;
157
158 DPRINT("CreateProcessA\n");
159
160 PApplicationNameW = InternalAnsiToUnicode(ApplicationNameW,
161 lpApplicationName,
162 MAX_PATH);
163 PCommandLineW = InternalAnsiToUnicode(CommandLineW,
164 lpCommandLine,
165 MAX_PATH);
166 PCurrentDirectoryW = InternalAnsiToUnicode(CurrentDirectoryW,
167 lpCurrentDirectory,
168 MAX_PATH);
169 return CreateProcessW(PApplicationNameW,
170 PCommandLineW,
171 lpProcessAttributes,
172 lpThreadAttributes,
173 bInheritHandles,
174 dwCreationFlags,
175 lpEnvironment,
176 PCurrentDirectoryW,
177 lpStartupInfo,
178 lpProcessInformation);
179 }
180
181
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)
192 {
193 HANDLE hFile, hSection, hProcess, hThread;
194 KPRIORITY PriorityClass;
195 OBJECT_ATTRIBUTES ObjectAttributes;
196 IO_STATUS_BLOCK IoStatusBlock;
197 BOOLEAN CreateSuspended;
198 NTSTATUS errCode;
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];
206 ULONG i;
207 ULONG BaseAddress;
208 ULONG Size;
209 LARGE_INTEGER SectionOffset;
210
211 DPRINT("CreateProcessW(lpApplicationName '%w', lpCommandLine '%w')\n",
212 lpApplicationName,lpCommandLine);
213
214 hFile = NULL;
215
216 /*
217 * Find the application name
218 */
219 TempApplicationName[0] = '\\';
220 TempApplicationName[1] = '?';
221 TempApplicationName[2] = '?';
222 TempApplicationName[3] = '\\';
223 TempApplicationName[4] = 0;
224
225 DPRINT("TempApplicationName '%w'\n",TempApplicationName);
226
227 if (lpApplicationName != NULL)
228 {
229 wcscpy(TempFileName, lpApplicationName);
230
231 DPRINT("TempFileName '%w'\n",TempFileName);
232 }
233 else
234 {
235 wcscpy(TempFileName, lpCommandLine);
236
237 DPRINT("TempFileName '%w'\n",TempFileName);
238
239 for (i=0; TempFileName[i]!=' ' && TempFileName[i] != 0; i++);
240 TempFileName[i]=0;
241
242 }
243 if (TempFileName[1] != ':')
244 {
245 GetCurrentDirectoryW(MAX_PATH,TempDirectoryName);
246 wcscat(TempApplicationName,TempDirectoryName);
247 }
248 wcscat(TempApplicationName,TempFileName);
249
250 RtlInitUnicodeString(&ApplicationNameString, TempApplicationName);
251
252 DPRINT("ApplicationName %w\n",ApplicationNameString.Buffer);
253
254 InitializeObjectAttributes(&ObjectAttributes,
255 &ApplicationNameString,
256 OBJ_CASE_INSENSITIVE,
257 NULL,
258 SecurityDescriptor);
259
260 /*
261 * Try to open the executable
262 */
263
264 errCode = NtOpenFile(&hFile,
265 SYNCHRONIZE|FILE_EXECUTE|FILE_READ_DATA,
266 &ObjectAttributes,
267 &IoStatusBlock,
268 FILE_SHARE_DELETE|FILE_SHARE_READ,
269 FILE_SYNCHRONOUS_IO_NONALERT|FILE_NON_DIRECTORY_FILE);
270
271 if ( !NT_SUCCESS(errCode) )
272 {
273 SetLastError(RtlNtStatusToDosError(errCode));
274 return FALSE;
275 }
276
277 errCode = NtCreateSection(&hSection,
278 SECTION_ALL_ACCESS,
279 NULL,
280 NULL,
281 PAGE_EXECUTE,
282 SEC_IMAGE,
283 hFile);
284 NtClose(hFile);
285
286 if ( !NT_SUCCESS(errCode) )
287 {
288 SetLastError(RtlNtStatusToDosError(errCode));
289 return FALSE;
290 }
291
292 errCode = NtCreateProcess(&hProcess,
293 PROCESS_ALL_ACCESS,
294 NULL,
295 NtCurrentProcess(),
296 bInheritHandles,
297 NULL,
298 NULL,
299 NULL);
300
301 BaseAddress = (PVOID)0x10000;
302 LARGE_INTEGER_QUAD_PART(SectionOffset) = 0;
303 Size = 0x10000;
304 NtMapViewOfSection(hSection,
305 hProcess,
306 &BaseAddress,
307 0,
308 Size,
309 &SectionOffset,
310 &Size,
311 0,
312 MEM_COMMIT,
313 PAGE_READWRITE);
314
315
316 NtClose(hSection);
317
318 if ( !NT_SUCCESS(errCode) )
319 {
320 SetLastError(RtlNtStatusToDosError(errCode));
321 return FALSE;
322 }
323
324 #if 0
325 PriorityClass = NORMAL_PRIORITY_CLASS;
326 NtSetInformationProcess(hProcess,
327 ProcessBasePriority,
328 &PriorityClass,
329 sizeof(KPRIORITY));
330 #endif
331 DPRINT("Creating thread for process\n");
332 lpStartAddress = BaseAddress;
333 hThread = CreateRemoteThread(hProcess,
334 lpThreadAttributes,
335 4096, // 1 page ??
336 lpStartAddress,
337 lpParameter,
338 dwCreationFlags,
339 &lpProcessInformation->dwThreadId);
340
341 if ( hThread == NULL )
342 return FALSE;
343
344 lpProcessInformation->hProcess = hProcess;
345 lpProcessInformation->hThread = hThread;
346
347 GetProcessId(hProcess,&lpProcessInformation->dwProcessId);
348
349 return TRUE;
350 }
351
352
353
354 HANDLE STDCALL OpenProcess(DWORD dwDesiredAccess,
355 WINBOOL bInheritHandle,
356 DWORD dwProcessId)
357 {
358 NTSTATUS errCode;
359 HANDLE ProcessHandle;
360 OBJECT_ATTRIBUTES ObjectAttributes;
361 CLIENT_ID ClientId ;
362
363 ClientId.UniqueProcess = (HANDLE)dwProcessId;
364 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
365 ObjectAttributes.RootDirectory = (HANDLE)NULL;
366 ObjectAttributes.SecurityDescriptor = NULL;
367 ObjectAttributes.SecurityQualityOfService = NULL;
368
369 if ( bInheritHandle == TRUE )
370 ObjectAttributes.Attributes = OBJ_INHERIT;
371 else
372 ObjectAttributes.Attributes = 0;
373
374 errCode = NtOpenProcess(&ProcessHandle,
375 dwDesiredAccess,
376 &ObjectAttributes,
377 &ClientId);
378 if (!NT_SUCCESS(errCode))
379 {
380 SetLastError(RtlNtStatusToDosError(errCode));
381 return NULL;
382 }
383 return ProcessHandle;
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398 UINT WinExec (LPCSTR lpCmdLine, UINT uCmdShow)
399 {
400 STARTUPINFO StartupInfo;
401 PROCESS_INFORMATION ProcessInformation;
402 HINSTANCE hInst;
403 DWORD dosErr;
404
405 StartupInfo.cb = sizeof(STARTUPINFO);
406 StartupInfo.wShowWindow = uCmdShow ;
407 StartupInfo.dwFlags = 0;
408
409 hInst = (HINSTANCE)CreateProcessA(NULL,
410 (PVOID)lpCmdLine,
411 NULL,
412 NULL,
413 FALSE,
414 0,
415 NULL,
416 NULL,
417 &StartupInfo,
418 &ProcessInformation);
419 if ( hInst == NULL )
420 {
421 dosErr = GetLastError();
422 return dosErr;
423 }
424 if ( lpfnGlobalRegisterWaitForInputIdle != NULL )
425 lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,10000);
426 NtClose(ProcessInformation.hProcess);
427 NtClose(ProcessInformation.hThread);
428 return 0;
429 }
430
431
432
433 VOID RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
434 {
435 lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
436 return;
437 }
438
439 DWORD STDCALL WaitForInputIdle(HANDLE hProcess,
440 DWORD dwMilliseconds)
441 {
442 return 0;
443 }
444
445 VOID
446 STDCALL
447 Sleep(
448 DWORD dwMilliseconds
449 )
450 {
451 SleepEx(dwMilliseconds,FALSE);
452 return;
453 }
454
455 DWORD
456 STDCALL
457 SleepEx(
458 DWORD dwMilliseconds,
459 BOOL bAlertable
460 )
461 {
462 TIME Interval;
463 NTSTATUS errCode;
464
465 Interval.LowPart = dwMilliseconds * 1000;
466 Interval.HighPart = 0;
467 errCode = NtDelayExecution(bAlertable,&Interval);
468 if ( !NT_SUCCESS(errCode) ) {
469 SetLastError(RtlNtStatusToDosError(errCode));
470 return -1;
471 }
472 return 0;
473 }
474
475
476
477
478
479 VOID
480 STDCALL
481 GetStartupInfoW(
482 LPSTARTUPINFO lpStartupInfo
483 )
484 {
485 NT_PEB *pPeb = GetCurrentPeb();
486
487 if (lpStartupInfo == NULL ) {
488 SetLastError(ERROR_INVALID_PARAMETER);
489 return;
490 }
491
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;
507
508 lpStartupInfo->hStdInput = pPeb->StartupInfo->hStdInput;
509 lpStartupInfo->hStdOutput = pPeb->StartupInfo->hStdOutput;
510 lpStartupInfo->hStdError = pPeb->StartupInfo->hStdError;
511
512
513
514 return;
515
516
517
518 }
519
520
521 VOID
522 STDCALL
523 GetStartupInfoA(
524 LPSTARTUPINFO lpStartupInfo
525 )
526 {
527 NT_PEB *pPeb = GetCurrentPeb();
528 ULONG i = 0;
529 if (lpStartupInfo == NULL ) {
530 SetLastError(ERROR_INVALID_PARAMETER);
531 return;
532 }
533
534
535 lpStartupInfo->cb = sizeof(STARTUPINFO);
536 i = 0;
537
538 while ((pPeb->StartupInfo->Desktop[i])!=0 && i < MAX_PATH)
539 {
540 lpStartupInfo->lpDesktop[i] = (unsigned char)pPeb->StartupInfo->Desktop[i];
541 i++;
542 }
543 lpStartupInfo->lpDesktop[i] = 0;
544
545 i = 0;
546 while ((pPeb->StartupInfo->Title[i])!=0 && i < MAX_PATH)
547 {
548 lpStartupInfo->lpTitle[i] = (unsigned char)pPeb->StartupInfo->Title[i];
549 i++;
550 }
551 lpStartupInfo->lpTitle[i] = 0;
552
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;
565
566 lpStartupInfo->hStdInput = pPeb->StartupInfo->hStdInput;
567 lpStartupInfo->hStdOutput = pPeb->StartupInfo->hStdOutput;
568 lpStartupInfo->hStdError = pPeb->StartupInfo->hStdError;
569
570 return;
571 }
572
573 BOOL
574 STDCALL
575 FlushInstructionCache(
576
577
578 HANDLE hProcess,
579 LPCVOID lpBaseAddress,
580 DWORD dwSize
581 )
582 {
583 NTSTATUS errCode;
584 errCode = NtFlushInstructionCache(hProcess,(PVOID)lpBaseAddress,dwSize);
585 if ( !NT_SUCCESS(errCode) ) {
586 SetLastError(RtlNtStatusToDosError(errCode));
587 return FALSE;
588 }
589 return TRUE;
590 }
591
592 VOID STDCALL ExitProcess(UINT uExitCode)
593 {
594 NtTerminateProcess(NtCurrentProcess() ,uExitCode);
595 }
596
597 VOID
598 STDCALL
599 FatalAppExitA(
600 UINT uAction,
601 LPCSTR lpMessageText
602 )
603 {
604 WCHAR MessageTextW[MAX_PATH];
605 UINT i;
606 i = 0;
607 while ((*lpMessageText)!=0 && i < 35)
608 {
609 MessageTextW[i] = *lpMessageText;
610 lpMessageText++;
611 i++;
612 }
613 MessageTextW[i] = 0;
614
615 return FatalAppExitW(uAction,MessageTextW);
616 }
617
618
619
620 VOID STDCALL FatalAppExitW(UINT uAction, LPCWSTR lpMessageText)
621 {
622 return;
623 }
624
625