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