Reverted latest changes.
[reactos.git] / reactos / lib / kernel32 / process / proc.c
1 /* $Id: proc.c,v 1.46 2002/09/08 10:22:45 chorns 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 STDCALL
481 FlushInstructionCache (HANDLE hProcess,
482 LPCVOID lpBaseAddress,
483 DWORD dwSize)
484 {
485 NTSTATUS errCode;
486
487 errCode = NtFlushInstructionCache (hProcess,
488 (PVOID) lpBaseAddress,
489 dwSize);
490 if (!NT_SUCCESS(errCode))
491 {
492 SetLastErrorByStatus (errCode);
493 return FALSE;
494 }
495 return TRUE;
496 }
497
498
499 VOID STDCALL
500 ExitProcess (UINT uExitCode)
501 {
502 CSRSS_API_REQUEST CsrRequest;
503 CSRSS_API_REPLY CsrReply;
504 NTSTATUS Status;
505
506 /* unload all dll's */
507 LdrShutdownProcess ();
508
509 /* notify csrss of process termination */
510 CsrRequest.Type = CSRSS_TERMINATE_PROCESS;
511 Status = CsrClientCallServer(&CsrRequest,
512 &CsrReply,
513 sizeof(CSRSS_API_REQUEST),
514 sizeof(CSRSS_API_REPLY));
515 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
516 {
517 DbgPrint("Failed to tell csrss about terminating process. "
518 "Expect trouble.\n");
519 }
520
521
522 NtTerminateProcess (NtCurrentProcess (),
523 uExitCode);
524 }
525
526
527 WINBOOL STDCALL
528 TerminateProcess (HANDLE hProcess,
529 UINT uExitCode)
530 {
531 NTSTATUS Status = NtTerminateProcess (hProcess, uExitCode);
532
533 if (NT_SUCCESS(Status))
534 {
535 return TRUE;
536 }
537 SetLastErrorByStatus (Status);
538 return FALSE;
539 }
540
541
542 VOID STDCALL
543 FatalAppExitA (UINT uAction,
544 LPCSTR lpMessageText)
545 {
546 UNICODE_STRING MessageTextU;
547 ANSI_STRING MessageText;
548
549 RtlInitAnsiString (&MessageText, (LPSTR) lpMessageText);
550
551 RtlAnsiStringToUnicodeString (&MessageTextU,
552 &MessageText,
553 TRUE);
554
555 FatalAppExitW (uAction, MessageTextU.Buffer);
556
557 RtlFreeUnicodeString (&MessageTextU);
558 }
559
560
561 VOID STDCALL
562 FatalAppExitW (UINT uAction,
563 LPCWSTR lpMessageText)
564 {
565 return;
566 }
567
568
569 VOID STDCALL
570 FatalExit (int ExitCode)
571 {
572 ExitProcess(ExitCode);
573 }
574
575
576 DWORD STDCALL
577 GetPriorityClass (HANDLE hProcess)
578 {
579 HANDLE hProcessTmp;
580 DWORD CsrPriorityClass = 0; // This tells CSRSS we want to GET it!
581 NTSTATUS Status;
582
583 Status =
584 NtDuplicateObject (GetCurrentProcess(),
585 hProcess,
586 GetCurrentProcess(),
587 &hProcessTmp,
588 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
589 FALSE,
590 0);
591 if (!NT_SUCCESS(Status))
592 {
593 SetLastErrorByStatus (Status);
594 return (0); /* ERROR */
595 }
596 /* Ask CSRSS to set it */
597 CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass);
598 NtClose (hProcessTmp);
599 /* Translate CSR->W32 priorities */
600 switch (CsrPriorityClass)
601 {
602 case CSR_PRIORITY_CLASS_NORMAL:
603 return (NORMAL_PRIORITY_CLASS); /* 32 */
604 case CSR_PRIORITY_CLASS_IDLE:
605 return (IDLE_PRIORITY_CLASS); /* 64 */
606 case CSR_PRIORITY_CLASS_HIGH:
607 return (HIGH_PRIORITY_CLASS); /* 128 */
608 case CSR_PRIORITY_CLASS_REALTIME:
609 return (REALTIME_PRIORITY_CLASS); /* 256 */
610 }
611 SetLastError (ERROR_ACCESS_DENIED);
612 return (0); /* ERROR */
613 }
614
615
616
617 WINBOOL STDCALL
618 SetPriorityClass (HANDLE hProcess,
619 DWORD dwPriorityClass)
620 {
621 HANDLE hProcessTmp;
622 DWORD CsrPriorityClass;
623 NTSTATUS Status;
624
625 switch (dwPriorityClass)
626 {
627 case NORMAL_PRIORITY_CLASS: /* 32 */
628 CsrPriorityClass = CSR_PRIORITY_CLASS_NORMAL;
629 break;
630 case IDLE_PRIORITY_CLASS: /* 64 */
631 CsrPriorityClass = CSR_PRIORITY_CLASS_IDLE;
632 break;
633 case HIGH_PRIORITY_CLASS: /* 128 */
634 CsrPriorityClass = CSR_PRIORITY_CLASS_HIGH;
635 break;
636 case REALTIME_PRIORITY_CLASS: /* 256 */
637 CsrPriorityClass = CSR_PRIORITY_CLASS_REALTIME;
638 break;
639 default:
640 SetLastError (ERROR_INVALID_PARAMETER);
641 return (FALSE);
642 }
643 Status =
644 NtDuplicateObject (GetCurrentProcess(),
645 hProcess,
646 GetCurrentProcess(),
647 &hProcessTmp,
648 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
649 FALSE,
650 0);
651 if (!NT_SUCCESS(Status))
652 {
653 SetLastErrorByStatus (Status);
654 return (FALSE); /* ERROR */
655 }
656 /* Ask CSRSS to set it */
657 Status = CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass);
658 NtClose (hProcessTmp);
659 if (!NT_SUCCESS(Status))
660 {
661 SetLastErrorByStatus (Status);
662 return (FALSE);
663 }
664 return (TRUE);
665 }
666
667
668 DWORD STDCALL
669 GetProcessVersion (DWORD ProcessId)
670 {
671 DWORD Version = 0;
672 PIMAGE_NT_HEADERS NtHeader = NULL;
673 PVOID BaseAddress = NULL;
674
675 /* Caller's */
676 if (0 == ProcessId)
677 {
678 BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
679 NtHeader = RtlImageNtHeader (BaseAddress);
680 if (NULL != NtHeader)
681 {
682 Version =
683 (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
684 (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
685 }
686 }
687 else /* other process */
688 {
689 /* FIXME: open the other process */
690 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
691 }
692 return (Version);
693 }
694
695
696
697 /* EOF */