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