Minor fixes in KERNEL32.TerminateThread() and in
[reactos.git] / reactos / lib / kernel32 / process / proc.c
1 /* $Id: proc.c,v 1.41 2001/08/15 20:35:38 ea Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ntdll/rtl.h>
16 #include <windows.h>
17 #include <kernel32/proc.h>
18 #include <kernel32/thread.h>
19 #include <kernel32/error.h>
20 #include <wchar.h>
21 #include <string.h>
22 #include <napi/i386/segment.h>
23 #include <napi/teb.h>
24 #include <ntdll/csr.h>
25 #include <ntdll/ldr.h>
26
27
28 #define NDEBUG
29 #include <kernel32/kernel32.h>
30
31
32 /* GLOBALS *******************************************************************/
33
34 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
35
36 LPSTARTUPINFO lpLocalStartupInfo = NULL;
37
38 VOID STDCALL
39 RegisterWaitForInputIdle (WaitForInputIdleType lpfnRegisterWaitForInputIdle);
40
41
42 /* FUNCTIONS ****************************************************************/
43
44 WINBOOL STDCALL
45 GetProcessId (HANDLE hProcess, LPDWORD lpProcessId);
46
47 WINBOOL
48 STDCALL
49 GetProcessAffinityMask (
50 HANDLE hProcess,
51 LPDWORD lpProcessAffinityMask,
52 LPDWORD lpSystemAffinityMask
53 )
54 {
55 if ( (NULL == lpProcessAffinityMask)
56 || (NULL == lpSystemAffinityMask)
57 )
58 {
59 SetLastError(ERROR_BAD_ARGUMENTS);
60 return FALSE;
61 }
62 /* FIXME: check hProcess is actually a process */
63 /* FIXME: query the kernel process object */
64 *lpProcessAffinityMask = 0x00000001;
65 *lpSystemAffinityMask = 0x00000001;
66 return TRUE;
67 }
68
69
70 WINBOOL
71 STDCALL
72 GetProcessShutdownParameters (
73 LPDWORD lpdwLevel,
74 LPDWORD lpdwFlags
75 )
76 {
77 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
78 return FALSE;
79 }
80
81
82 WINBOOL
83 STDCALL
84 GetProcessWorkingSetSize (
85 HANDLE hProcess,
86 LPDWORD lpMinimumWorkingSetSize,
87 LPDWORD lpMaximumWorkingSetSize
88 )
89 {
90 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
91 return FALSE;
92 }
93
94 WINBOOL
95 STDCALL
96 SetProcessShutdownParameters (
97 DWORD dwLevel,
98 DWORD dwFlags
99 )
100 {
101 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
102 return FALSE;
103 }
104
105
106 WINBOOL
107 STDCALL
108 SetProcessWorkingSetSize (
109 HANDLE hProcess,
110 DWORD dwMinimumWorkingSetSize,
111 DWORD dwMaximumWorkingSetSize
112 )
113 {
114 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
115 return FALSE;
116 }
117
118
119 WINBOOL STDCALL
120 GetProcessTimes (HANDLE hProcess,
121 LPFILETIME lpCreationTime,
122 LPFILETIME lpExitTime,
123 LPFILETIME lpKernelTime,
124 LPFILETIME lpUserTime)
125 {
126 NTSTATUS Status;
127 KERNEL_USER_TIMES Kut;
128
129 Status = NtQueryInformationProcess (hProcess,
130 ProcessTimes,
131 &Kut,
132 sizeof(Kut),
133 NULL
134 );
135 if (!NT_SUCCESS(Status))
136 {
137 SetLastErrorByStatus (Status);
138 return (FALSE);
139 }
140
141 lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart;
142 lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart;
143
144 lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart;
145 lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart;
146
147 lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart;
148 lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart;
149
150 lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart;
151 lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart;
152
153 return (TRUE);
154 }
155
156
157 HANDLE STDCALL GetCurrentProcess (VOID)
158 {
159 return((HANDLE)NtCurrentProcess());
160 }
161
162
163 HANDLE STDCALL GetCurrentThread (VOID)
164 {
165 return((HANDLE)NtCurrentThread());
166 }
167
168
169 DWORD STDCALL GetCurrentProcessId (VOID)
170 {
171 return((DWORD)GetTeb()->Cid.UniqueProcess);
172 }
173
174
175 WINBOOL
176 STDCALL
177 GetExitCodeProcess (
178 HANDLE hProcess,
179 LPDWORD lpExitCode
180 )
181 {
182 NTSTATUS errCode;
183 PROCESS_BASIC_INFORMATION ProcessBasic;
184 ULONG BytesWritten;
185
186 errCode = NtQueryInformationProcess(hProcess,
187 ProcessBasicInformation,
188 &ProcessBasic,
189 sizeof(PROCESS_BASIC_INFORMATION),
190 &BytesWritten);
191 if (!NT_SUCCESS(errCode))
192 {
193 SetLastErrorByStatus (errCode);
194 return FALSE;
195 }
196 memcpy(lpExitCode, &ProcessBasic.ExitStatus, sizeof(DWORD));
197 return TRUE;
198 }
199
200
201 WINBOOL
202 STDCALL
203 GetProcessId (
204 HANDLE hProcess,
205 LPDWORD lpProcessId
206 )
207 {
208 NTSTATUS errCode;
209 PROCESS_BASIC_INFORMATION ProcessBasic;
210 ULONG BytesWritten;
211
212 errCode = NtQueryInformationProcess(hProcess,
213 ProcessBasicInformation,
214 &ProcessBasic,
215 sizeof(PROCESS_BASIC_INFORMATION),
216 &BytesWritten);
217 if (!NT_SUCCESS(errCode))
218 {
219 SetLastErrorByStatus (errCode);
220 return FALSE;
221 }
222 memcpy( lpProcessId ,&ProcessBasic.UniqueProcessId,sizeof(DWORD));
223 return TRUE;
224 }
225
226
227 HANDLE
228 STDCALL
229 OpenProcess (
230 DWORD dwDesiredAccess,
231 WINBOOL bInheritHandle,
232 DWORD dwProcessId
233 )
234 {
235 NTSTATUS errCode;
236 HANDLE ProcessHandle;
237 OBJECT_ATTRIBUTES ObjectAttributes;
238 CLIENT_ID ClientId ;
239
240 ClientId.UniqueProcess = (HANDLE)dwProcessId;
241 ClientId.UniqueThread = INVALID_HANDLE_VALUE;
242
243 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
244 ObjectAttributes.RootDirectory = (HANDLE)NULL;
245 ObjectAttributes.SecurityDescriptor = NULL;
246 ObjectAttributes.SecurityQualityOfService = NULL;
247 ObjectAttributes.ObjectName = NULL;
248
249 if (bInheritHandle == TRUE)
250 ObjectAttributes.Attributes = OBJ_INHERIT;
251 else
252 ObjectAttributes.Attributes = 0;
253
254 errCode = NtOpenProcess(&ProcessHandle,
255 dwDesiredAccess,
256 &ObjectAttributes,
257 &ClientId);
258 if (!NT_SUCCESS(errCode))
259 {
260 SetLastErrorByStatus (errCode);
261 return NULL;
262 }
263 return ProcessHandle;
264 }
265
266
267 UINT
268 STDCALL
269 WinExec (
270 LPCSTR lpCmdLine,
271 UINT uCmdShow
272 )
273 {
274 STARTUPINFOA StartupInfo;
275 PROCESS_INFORMATION ProcessInformation;
276 HINSTANCE hInst;
277 DWORD dosErr;
278
279 StartupInfo.cb = sizeof(STARTUPINFOA);
280 StartupInfo.wShowWindow = uCmdShow;
281 StartupInfo.dwFlags = 0;
282
283 hInst = (HINSTANCE)CreateProcessA(NULL,
284 (PVOID)lpCmdLine,
285 NULL,
286 NULL,
287 FALSE,
288 0,
289 NULL,
290 NULL,
291 &StartupInfo,
292 &ProcessInformation);
293 if ( hInst == NULL )
294 {
295 dosErr = GetLastError();
296 return dosErr;
297 }
298 if (NULL != lpfnGlobalRegisterWaitForInputIdle)
299 {
300 lpfnGlobalRegisterWaitForInputIdle (
301 ProcessInformation.hProcess,
302 10000
303 );
304 }
305 NtClose (ProcessInformation.hProcess);
306 NtClose (ProcessInformation.hThread);
307 return 0;
308 }
309
310
311 VOID
312 STDCALL
313 RegisterWaitForInputIdle (
314 WaitForInputIdleType lpfnRegisterWaitForInputIdle
315 )
316 {
317 lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
318 return;
319 }
320
321
322 DWORD
323 STDCALL
324 WaitForInputIdle (
325 HANDLE hProcess,
326 DWORD dwMilliseconds
327 )
328 {
329 return 0;
330 }
331
332
333 VOID
334 STDCALL
335 Sleep (
336 DWORD dwMilliseconds
337 )
338 {
339 SleepEx (dwMilliseconds, FALSE);
340 return;
341 }
342
343
344 DWORD STDCALL
345 SleepEx (DWORD dwMilliseconds,
346 BOOL bAlertable)
347 {
348 TIME Interval;
349 NTSTATUS errCode;
350
351 if (dwMilliseconds != INFINITE)
352 {
353 /*
354 * System time units are 100 nanoseconds (a nanosecond is a billionth of
355 * a second).
356 */
357 Interval.QuadPart = dwMilliseconds;
358 Interval.QuadPart = -(Interval.QuadPart * 10000);
359 }
360 else
361 {
362 /* Approximately 292000 years hence */
363 Interval.QuadPart = -0x7FFFFFFFFFFFFFFF;
364 }
365
366 errCode = NtDelayExecution (bAlertable, &Interval);
367 if (!NT_SUCCESS(errCode))
368 {
369 SetLastErrorByStatus (errCode);
370 return -1;
371 }
372 return 0;
373 }
374
375
376 VOID STDCALL
377 GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
378 {
379 PRTL_USER_PROCESS_PARAMETERS Params;
380
381 if (lpStartupInfo == NULL)
382 {
383 SetLastError(ERROR_INVALID_PARAMETER);
384 return;
385 }
386
387 Params = NtCurrentPeb ()->ProcessParameters;
388
389 lpStartupInfo->cb = sizeof(STARTUPINFOW);
390 lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
391 lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
392 lpStartupInfo->dwX = Params->StartingX;
393 lpStartupInfo->dwY = Params->StartingY;
394 lpStartupInfo->dwXSize = Params->CountX;
395 lpStartupInfo->dwYSize = Params->CountY;
396 lpStartupInfo->dwXCountChars = Params->CountCharsX;
397 lpStartupInfo->dwYCountChars = Params->CountCharsY;
398 lpStartupInfo->dwFillAttribute = Params->FillAttribute;
399 lpStartupInfo->dwFlags = Params->Flags;
400 lpStartupInfo->wShowWindow = Params->ShowWindowFlags;
401 lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
402 lpStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
403 lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
404
405 lpStartupInfo->hStdInput = Params->InputHandle;
406 lpStartupInfo->hStdOutput = Params->OutputHandle;
407 lpStartupInfo->hStdError = Params->ErrorHandle;
408 }
409
410
411 VOID STDCALL
412 GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
413 {
414 PRTL_USER_PROCESS_PARAMETERS Params;
415 ANSI_STRING AnsiString;
416
417 if (lpStartupInfo == NULL)
418 {
419 SetLastError(ERROR_INVALID_PARAMETER);
420 return;
421 }
422
423 Params = NtCurrentPeb ()->ProcessParameters;
424
425 RtlAcquirePebLock ();
426
427 if (lpLocalStartupInfo == NULL)
428 {
429 /* create new local startup info (ansi) */
430 lpLocalStartupInfo = RtlAllocateHeap (RtlGetProcessHeap (),
431 0,
432 sizeof(STARTUPINFOA));
433
434 lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
435
436 /* copy window title string */
437 RtlUnicodeStringToAnsiString (&AnsiString,
438 &Params->WindowTitle,
439 TRUE);
440 lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
441
442 /* copy desktop info string */
443 RtlUnicodeStringToAnsiString (&AnsiString,
444 &Params->DesktopInfo,
445 TRUE);
446 lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
447
448 /* copy shell info string */
449 RtlUnicodeStringToAnsiString (&AnsiString,
450 &Params->ShellInfo,
451 TRUE);
452 lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
453
454 lpLocalStartupInfo->dwX = Params->StartingX;
455 lpLocalStartupInfo->dwY = Params->StartingY;
456 lpLocalStartupInfo->dwXSize = Params->CountX;
457 lpLocalStartupInfo->dwYSize = Params->CountY;
458 lpLocalStartupInfo->dwXCountChars = Params->CountCharsX;
459 lpLocalStartupInfo->dwYCountChars = Params->CountCharsY;
460 lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute;
461 lpLocalStartupInfo->dwFlags = Params->Flags;
462 lpLocalStartupInfo->wShowWindow = Params->ShowWindowFlags;
463 lpLocalStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
464 lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
465
466 lpLocalStartupInfo->hStdInput = Params->InputHandle;
467 lpLocalStartupInfo->hStdOutput = Params->OutputHandle;
468 lpLocalStartupInfo->hStdError = Params->ErrorHandle;
469 }
470
471 RtlReleasePebLock ();
472
473 /* copy local startup info data to external startup info */
474 memcpy (lpStartupInfo,
475 lpLocalStartupInfo,
476 sizeof(STARTUPINFOA));
477 }
478
479
480 BOOL
481 STDCALL
482 FlushInstructionCache (
483 HANDLE hProcess,
484 LPCVOID lpBaseAddress,
485 DWORD dwSize
486 )
487 {
488 NTSTATUS errCode;
489
490 errCode = NtFlushInstructionCache (
491 hProcess,
492 (PVOID) lpBaseAddress,
493 dwSize);
494 if (!NT_SUCCESS(errCode))
495 {
496 SetLastErrorByStatus (errCode);
497 return FALSE;
498 }
499 return TRUE;
500 }
501
502
503 VOID
504 STDCALL
505 ExitProcess (
506 UINT uExitCode
507 )
508 {
509 /* unload all dll's */
510 LdrShutdownProcess ();
511
512 /* FIXME: notify csrss of process termination */
513
514 NtTerminateProcess (NtCurrentProcess (),
515 uExitCode);
516 }
517
518
519 WINBOOL
520 STDCALL
521 TerminateProcess (
522 HANDLE hProcess,
523 UINT uExitCode
524 )
525 {
526 if (0 == hProcess)
527 {
528 SetLastError (ERROR_INVALID_HANDLE);
529 }
530 else
531 {
532 NTSTATUS Status = NtTerminateProcess (hProcess, uExitCode);
533
534 if (NT_SUCCESS(Status))
535 {
536 return TRUE;
537 }
538 SetLastErrorByStatus (Status);
539 }
540 return FALSE;
541 }
542
543
544 VOID
545 STDCALL
546 FatalAppExitA (
547 UINT uAction,
548 LPCSTR lpMessageText
549 )
550 {
551 UNICODE_STRING MessageTextU;
552 ANSI_STRING MessageText;
553
554 RtlInitAnsiString (& MessageText,
555 (LPSTR) lpMessageText);
556
557 RtlAnsiStringToUnicodeString (& MessageTextU,
558 & MessageText,
559 TRUE);
560
561 FatalAppExitW (uAction,
562 MessageTextU.Buffer);
563
564 RtlFreeUnicodeString (&MessageTextU);
565 }
566
567
568 VOID
569 STDCALL
570 FatalAppExitW (
571 UINT uAction,
572 LPCWSTR lpMessageText
573 )
574 {
575 return;
576 }
577
578
579 VOID
580 STDCALL
581 FatalExit (
582 int ExitCode
583 )
584 {
585 ExitProcess(ExitCode);
586 }
587
588
589 DWORD
590 STDCALL
591 GetPriorityClass (
592 HANDLE hProcess
593 )
594 {
595 HANDLE hProcessTmp;
596 DWORD CsrPriorityClass;
597 NTSTATUS Status;
598
599 Status = NtDuplicateObject (
600 GetCurrentProcess(),
601 hProcess,
602 GetCurrentProcess(),
603 & hProcessTmp,
604 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
605 FALSE,
606 0
607 );
608 if (!NT_SUCCESS(Status))
609 {
610 SetLastErrorByStatus (Status);
611 return (0); /* ERROR */
612 }
613 /* Ask CSRSS to set it */
614 CsrSetPriorityClass (
615 hProcessTmp,
616 & CsrPriorityClass
617 );
618 NtClose (hProcessTmp);
619 /* Translate CSR->W32 priorities */
620 switch (CsrPriorityClass)
621 {
622 case CSR_PRIORITY_CLASS_NORMAL:
623 return (NORMAL_PRIORITY_CLASS); /* 32 */
624 case CSR_PRIORITY_CLASS_IDLE:
625 return (IDLE_PRIORITY_CLASS); /* 64 */
626 case CSR_PRIORITY_CLASS_HIGH:
627 return (HIGH_PRIORITY_CLASS); /* 128 */
628 case CSR_PRIORITY_CLASS_REALTIME:
629 return (REALTIME_PRIORITY_CLASS); /* 256 */
630 }
631 SetLastError (ERROR_ACCESS_DENIED);
632 return (0); /* ERROR */
633 }
634
635
636
637 WINBOOL
638 STDCALL
639 SetPriorityClass (
640 HANDLE hProcess,
641 DWORD dwPriorityClass
642 )
643 {
644 HANDLE hProcessTmp;
645 DWORD CsrPriorityClass;
646 NTSTATUS Status;
647
648 switch (dwPriorityClass)
649 {
650 case NORMAL_PRIORITY_CLASS: /* 32 */
651 CsrPriorityClass = CSR_PRIORITY_CLASS_NORMAL;
652 break;
653 case IDLE_PRIORITY_CLASS: /* 64 */
654 CsrPriorityClass = CSR_PRIORITY_CLASS_IDLE;
655 break;
656 case HIGH_PRIORITY_CLASS: /* 128 */
657 CsrPriorityClass = CSR_PRIORITY_CLASS_HIGH;
658 break;
659 case REALTIME_PRIORITY_CLASS: /* 256 */
660 CsrPriorityClass = CSR_PRIORITY_CLASS_REALTIME;
661 break;
662 default:
663 SetLastError (ERROR_INVALID_PARAMETER);
664 return (FALSE);
665 }
666 Status = NtDuplicateObject (
667 GetCurrentProcess(),
668 hProcess,
669 GetCurrentProcess(),
670 & hProcessTmp,
671 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
672 FALSE,
673 0
674 );
675 if (!NT_SUCCESS(Status))
676 {
677 SetLastErrorByStatus (Status);
678 return (FALSE); /* ERROR */
679 }
680 /* Ask CSRSS to set it */
681 Status = CsrSetPriorityClass (
682 hProcessTmp,
683 & CsrPriorityClass
684 );
685 NtClose (hProcessTmp);
686 if (!NT_SUCCESS(Status))
687 {
688 SetLastErrorByStatus (Status);
689 return (FALSE);
690 }
691 return (TRUE);
692 }
693
694
695 DWORD
696 STDCALL
697 GetProcessVersion (
698 DWORD ProcessId
699 )
700 {
701 DWORD Version = 0;
702 PIMAGE_NT_HEADERS NtHeader = NULL;
703 PVOID BaseAddress = NULL;
704
705 /* Caller's */
706 if (0 == ProcessId)
707 {
708 BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
709 NtHeader = RtlImageNtHeader (BaseAddress);
710 if (NULL != NtHeader)
711 {
712 Version =
713 (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16)
714 | (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
715 }
716 }
717 else /* other process */
718 {
719 /* FIXME: open the other process */
720 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
721 }
722 return (Version);
723 }
724
725
726
727 /* EOF */