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