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