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