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