Implemented dll detach on thread termination
[reactos.git] / reactos / lib / kernel32 / process / proc.c
1 /* $Id: proc.c,v 1.35 2000/09/05 13:52:30 ekohl 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
288 STDCALL
289 SleepEx (
290 DWORD dwMilliseconds,
291 BOOL bAlertable
292 )
293 {
294 TIME Interval;
295 NTSTATUS errCode;
296
297 Interval.QuadPart = dwMilliseconds * 1000;
298
299 errCode = NtDelayExecution (bAlertable, & Interval);
300 if (!NT_SUCCESS(errCode))
301 {
302 SetLastErrorByStatus (errCode);
303 return -1;
304 }
305 return 0;
306 }
307
308
309 VOID
310 STDCALL
311 GetStartupInfoW (
312 LPSTARTUPINFOW lpStartupInfo
313 )
314 {
315 PRTL_USER_PROCESS_PARAMETERS Params;
316
317 if (lpStartupInfo == NULL)
318 {
319 SetLastError(ERROR_INVALID_PARAMETER);
320 return;
321 }
322
323 Params = NtCurrentPeb ()->ProcessParameters;
324
325 lpStartupInfo->cb = sizeof(STARTUPINFOW);
326 lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
327 lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
328 lpStartupInfo->dwX = Params->StartingX;
329 lpStartupInfo->dwY = Params->StartingY;
330 lpStartupInfo->dwXSize = Params->CountX;
331 lpStartupInfo->dwYSize = Params->CountY;
332 lpStartupInfo->dwXCountChars = Params->CountCharsX;
333 lpStartupInfo->dwYCountChars = Params->CountCharsY;
334 lpStartupInfo->dwFillAttribute = Params->FillAttribute;
335 lpStartupInfo->dwFlags = Params->Flags;
336 lpStartupInfo->wShowWindow = Params->ShowWindowFlags;
337 lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
338 lpStartupInfo->cbReserved2 = Params->RuntimeData.Length;
339 lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
340
341 lpStartupInfo->hStdInput = Params->InputHandle;
342 lpStartupInfo->hStdOutput = Params->OutputHandle;
343 lpStartupInfo->hStdError = Params->ErrorHandle;
344 }
345
346
347 VOID
348 STDCALL
349 GetStartupInfoA (
350 LPSTARTUPINFOA lpStartupInfo
351 )
352 {
353 PRTL_USER_PROCESS_PARAMETERS Params;
354 ANSI_STRING AnsiString;
355
356 if (lpStartupInfo == NULL)
357 {
358 SetLastError(ERROR_INVALID_PARAMETER);
359 return;
360 }
361
362 Params = NtCurrentPeb ()->ProcessParameters;
363
364 RtlAcquirePebLock ();
365
366 if (lpLocalStartupInfo == NULL)
367 {
368 /* create new local startup info (ansi) */
369 lpLocalStartupInfo = RtlAllocateHeap (RtlGetProcessHeap (),
370 0,
371 sizeof(STARTUPINFOA));
372
373 lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
374
375 /* copy window title string */
376 RtlUnicodeStringToAnsiString (&AnsiString,
377 &Params->WindowTitle,
378 TRUE);
379 lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
380
381 /* copy desktop info string */
382 RtlUnicodeStringToAnsiString (&AnsiString,
383 &Params->DesktopInfo,
384 TRUE);
385 lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
386
387 /* copy shell info string */
388 RtlUnicodeStringToAnsiString (&AnsiString,
389 &Params->ShellInfo,
390 TRUE);
391 lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
392
393 lpLocalStartupInfo->dwX = Params->StartingX;
394 lpLocalStartupInfo->dwY = Params->StartingY;
395 lpLocalStartupInfo->dwXSize = Params->CountX;
396 lpLocalStartupInfo->dwYSize = Params->CountY;
397 lpLocalStartupInfo->dwXCountChars = Params->CountCharsX;
398 lpLocalStartupInfo->dwYCountChars = Params->CountCharsY;
399 lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute;
400 lpLocalStartupInfo->dwFlags = Params->Flags;
401 lpLocalStartupInfo->wShowWindow = Params->ShowWindowFlags;
402 lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length;
403 lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
404
405 lpLocalStartupInfo->hStdInput = Params->InputHandle;
406 lpLocalStartupInfo->hStdOutput = Params->OutputHandle;
407 lpLocalStartupInfo->hStdError = Params->ErrorHandle;
408 }
409
410 RtlReleasePebLock ();
411
412 /* copy local startup info data to external startup info */
413 memcpy (lpStartupInfo,
414 lpLocalStartupInfo,
415 sizeof(STARTUPINFOA));
416 }
417
418
419 BOOL
420 STDCALL
421 FlushInstructionCache (
422 HANDLE hProcess,
423 LPCVOID lpBaseAddress,
424 DWORD dwSize
425 )
426 {
427 NTSTATUS errCode;
428
429 errCode = NtFlushInstructionCache (
430 hProcess,
431 (PVOID) lpBaseAddress,
432 dwSize);
433 if (!NT_SUCCESS(errCode))
434 {
435 SetLastErrorByStatus (errCode);
436 return FALSE;
437 }
438 return TRUE;
439 }
440
441
442 VOID
443 STDCALL
444 ExitProcess (
445 UINT uExitCode
446 )
447 {
448 /* unload all dll's */
449 LdrShutdownProcess ();
450
451 /* FIXME: notify csrss of process termination */
452
453 NtTerminateProcess (NtCurrentProcess (),
454 uExitCode);
455 }
456
457
458 WINBOOL
459 STDCALL
460 TerminateProcess (
461 HANDLE hProcess,
462 UINT uExitCode
463 )
464 {
465 NTSTATUS errCode;
466
467 errCode = NtTerminateProcess (hProcess, uExitCode);
468 if (!NT_SUCCESS(errCode))
469 {
470 SetLastErrorByStatus (errCode);
471 return FALSE;
472 }
473 return TRUE;
474 }
475
476
477 VOID
478 STDCALL
479 FatalAppExitA (
480 UINT uAction,
481 LPCSTR lpMessageText
482 )
483 {
484 UNICODE_STRING MessageTextU;
485 ANSI_STRING MessageText;
486
487 RtlInitAnsiString (& MessageText,
488 (LPSTR) lpMessageText);
489
490 RtlAnsiStringToUnicodeString (& MessageTextU,
491 & MessageText,
492 TRUE);
493
494 FatalAppExitW (uAction,
495 MessageTextU.Buffer);
496
497 RtlFreeUnicodeString (&MessageTextU);
498 }
499
500
501 VOID
502 STDCALL
503 FatalAppExitW (
504 UINT uAction,
505 LPCWSTR lpMessageText
506 )
507 {
508 return;
509 }
510
511
512 VOID
513 STDCALL
514 FatalExit (
515 int ExitCode
516 )
517 {
518 ExitProcess(ExitCode);
519 }
520
521
522 DWORD
523 STDCALL
524 GetPriorityClass (
525 HANDLE hProcess
526 )
527 {
528 HANDLE hProcessTmp;
529 DWORD CsrPriorityClass;
530 NTSTATUS Status;
531
532 Status = NtDuplicateObject (
533 GetCurrentProcess(),
534 hProcess,
535 GetCurrentProcess(),
536 & hProcessTmp,
537 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
538 FALSE,
539 0
540 );
541 if (!NT_SUCCESS(Status))
542 {
543 SetLastErrorByStatus (Status);
544 return (0); /* ERROR */
545 }
546 /* Ask CSRSS to set it */
547 CsrSetPriorityClass (
548 hProcessTmp,
549 & CsrPriorityClass
550 );
551 NtClose (hProcessTmp);
552 /* Translate CSR->W32 priorities */
553 switch (CsrPriorityClass)
554 {
555 case CSR_PRIORITY_CLASS_NORMAL:
556 return (NORMAL_PRIORITY_CLASS); /* 32 */
557 case CSR_PRIORITY_CLASS_IDLE:
558 return (IDLE_PRIORITY_CLASS); /* 64 */
559 case CSR_PRIORITY_CLASS_HIGH:
560 return (HIGH_PRIORITY_CLASS); /* 128 */
561 case CSR_PRIORITY_CLASS_REALTIME:
562 return (REALTIME_PRIORITY_CLASS); /* 256 */
563 }
564 SetLastError (ERROR_ACCESS_DENIED);
565 return (0); /* ERROR */
566 }
567
568
569
570 WINBOOL
571 STDCALL
572 SetPriorityClass (
573 HANDLE hProcess,
574 DWORD dwPriorityClass
575 )
576 {
577 HANDLE hProcessTmp;
578 DWORD CsrPriorityClass;
579 NTSTATUS Status;
580
581 switch (dwPriorityClass)
582 {
583 case NORMAL_PRIORITY_CLASS: /* 32 */
584 CsrPriorityClass = CSR_PRIORITY_CLASS_NORMAL;
585 break;
586 case IDLE_PRIORITY_CLASS: /* 64 */
587 CsrPriorityClass = CSR_PRIORITY_CLASS_IDLE;
588 break;
589 case HIGH_PRIORITY_CLASS: /* 128 */
590 CsrPriorityClass = CSR_PRIORITY_CLASS_HIGH;
591 break;
592 case REALTIME_PRIORITY_CLASS: /* 256 */
593 CsrPriorityClass = CSR_PRIORITY_CLASS_REALTIME;
594 break;
595 default:
596 SetLastError (ERROR_INVALID_PARAMETER);
597 return (FALSE);
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 (FALSE); /* ERROR */
612 }
613 /* Ask CSRSS to set it */
614 Status = CsrSetPriorityClass (
615 hProcessTmp,
616 & CsrPriorityClass
617 );
618 NtClose (hProcessTmp);
619 if (!NT_SUCCESS(Status))
620 {
621 SetLastErrorByStatus (Status);
622 return (FALSE);
623 }
624 return (TRUE);
625 }
626
627
628 /* EOF */