Move kernekl32-internal declarations from global include directory to local one.
[reactos.git] / reactos / lib / kernel32 / process / proc.c
1 /* $Id: proc.c,v 1.59 2004/01/23 21:16:04 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 <k32.h>
15
16
17 #define NDEBUG
18 #include "../include/debug.h"
19
20
21 /* GLOBALS *******************************************************************/
22
23 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
24
25 LPSTARTUPINFOA lpLocalStartupInfo = NULL;
26
27 VOID STDCALL
28 RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
29
30 BOOL STDCALL
31 InternalGetProcessId (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 BOOL 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 BOOL 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 BOOL 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 BOOL 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 BOOL 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 BOOL 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 BOOL STDCALL
293 InternalGetProcessId(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 BOOL 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 = -((ULONGLONG)dwMilliseconds * 10000);
455 }
456 else
457 {
458 /* Approximately 292000 years hence */
459 Interval.QuadPart = -0x7FFFFFFFFFFFFFFFLL;
460 }
461
462 errCode = NtDelayExecution (bAlertable, &Interval);
463 if (!NT_SUCCESS(errCode))
464 {
465 SetLastErrorByStatus (errCode);
466 return -1;
467 }
468 return 0;
469 }
470
471
472 /*
473 * @implemented
474 */
475 VOID STDCALL
476 GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
477 {
478 PRTL_USER_PROCESS_PARAMETERS Params;
479
480 if (lpStartupInfo == NULL)
481 {
482 SetLastError(ERROR_INVALID_PARAMETER);
483 return;
484 }
485
486 Params = NtCurrentPeb()->ProcessParameters;
487
488 lpStartupInfo->cb = sizeof(STARTUPINFOW);
489 lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
490 lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
491 lpStartupInfo->dwX = Params->dwX;
492 lpStartupInfo->dwY = Params->dwY;
493 lpStartupInfo->dwXSize = Params->dwXSize;
494 lpStartupInfo->dwYSize = Params->dwYSize;
495 lpStartupInfo->dwXCountChars = Params->dwXCountChars;
496 lpStartupInfo->dwYCountChars = Params->dwYCountChars;
497 lpStartupInfo->dwFillAttribute = Params->dwFillAttribute;
498 lpStartupInfo->dwFlags = Params->dwFlags;
499 lpStartupInfo->wShowWindow = Params->wShowWindow;
500 lpStartupInfo->lpReserved = Params->ShellInfo.Buffer;
501 lpStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
502 lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
503
504 lpStartupInfo->hStdInput = Params->hStdInput;
505 lpStartupInfo->hStdOutput = Params->hStdOutput;
506 lpStartupInfo->hStdError = Params->hStdError;
507 }
508
509
510 /*
511 * @implemented
512 */
513 VOID STDCALL
514 GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
515 {
516 PRTL_USER_PROCESS_PARAMETERS Params;
517 ANSI_STRING AnsiString;
518
519 if (lpStartupInfo == NULL)
520 {
521 SetLastError(ERROR_INVALID_PARAMETER);
522 return;
523 }
524
525 Params = NtCurrentPeb ()->ProcessParameters;
526
527 RtlAcquirePebLock ();
528
529 if (lpLocalStartupInfo == NULL)
530 {
531 /* create new local startup info (ansi) */
532 lpLocalStartupInfo = RtlAllocateHeap (RtlGetProcessHeap (),
533 0,
534 sizeof(STARTUPINFOA));
535
536 lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
537
538 /* copy window title string */
539 RtlUnicodeStringToAnsiString (&AnsiString,
540 &Params->WindowTitle,
541 TRUE);
542 lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
543
544 /* copy desktop info string */
545 RtlUnicodeStringToAnsiString (&AnsiString,
546 &Params->DesktopInfo,
547 TRUE);
548 lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
549
550 /* copy shell info string */
551 RtlUnicodeStringToAnsiString (&AnsiString,
552 &Params->ShellInfo,
553 TRUE);
554 lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
555
556 lpLocalStartupInfo->dwX = Params->dwX;
557 lpLocalStartupInfo->dwY = Params->dwY;
558 lpLocalStartupInfo->dwXSize = Params->dwXSize;
559 lpLocalStartupInfo->dwYSize = Params->dwYSize;
560 lpLocalStartupInfo->dwXCountChars = Params->dwXCountChars;
561 lpLocalStartupInfo->dwYCountChars = Params->dwYCountChars;
562 lpLocalStartupInfo->dwFillAttribute = Params->dwFillAttribute;
563 lpLocalStartupInfo->dwFlags = Params->dwFlags;
564 lpLocalStartupInfo->wShowWindow = Params->wShowWindow;
565 lpLocalStartupInfo->cbReserved2 = Params->RuntimeInfo.Length;
566 lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeInfo.Buffer;
567
568 lpLocalStartupInfo->hStdInput = Params->hStdInput;
569 lpLocalStartupInfo->hStdOutput = Params->hStdOutput;
570 lpLocalStartupInfo->hStdError = Params->hStdError;
571 }
572
573 RtlReleasePebLock ();
574
575 /* copy local startup info data to external startup info */
576 memcpy (lpStartupInfo,
577 lpLocalStartupInfo,
578 sizeof(STARTUPINFOA));
579 }
580
581
582 /*
583 * @implemented
584 */
585 BOOL STDCALL
586 FlushInstructionCache (HANDLE hProcess,
587 LPCVOID lpBaseAddress,
588 DWORD dwSize)
589 {
590 NTSTATUS Status;
591
592 Status = NtFlushInstructionCache(hProcess,
593 (PVOID)lpBaseAddress,
594 dwSize);
595 if (!NT_SUCCESS(Status))
596 {
597 SetLastErrorByStatus(Status);
598 return FALSE;
599 }
600 return TRUE;
601 }
602
603
604 /*
605 * @implemented
606 */
607 VOID STDCALL
608 ExitProcess(UINT uExitCode)
609 {
610 CSRSS_API_REQUEST CsrRequest;
611 CSRSS_API_REPLY CsrReply;
612 NTSTATUS Status;
613
614 /* unload all dll's */
615 LdrShutdownProcess ();
616
617 /* notify csrss of process termination */
618 CsrRequest.Type = CSRSS_TERMINATE_PROCESS;
619 Status = CsrClientCallServer(&CsrRequest,
620 &CsrReply,
621 sizeof(CSRSS_API_REQUEST),
622 sizeof(CSRSS_API_REPLY));
623 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
624 {
625 DbgPrint("Failed to tell csrss about terminating process. "
626 "Expect trouble.\n");
627 }
628
629
630 NtTerminateProcess (NtCurrentProcess (),
631 uExitCode);
632
633 /* should never get here */
634 assert(0);
635 while(1);
636 }
637
638
639 /*
640 * @implemented
641 */
642 BOOL STDCALL
643 TerminateProcess (HANDLE hProcess,
644 UINT uExitCode)
645 {
646 NTSTATUS Status;
647
648 Status = NtTerminateProcess (hProcess, uExitCode);
649 if (NT_SUCCESS(Status))
650 {
651 return TRUE;
652 }
653 SetLastErrorByStatus (Status);
654 return FALSE;
655 }
656
657
658 /*
659 * @unimplemented
660 */
661 VOID STDCALL
662 FatalAppExitA (UINT uAction,
663 LPCSTR lpMessageText)
664 {
665 UNICODE_STRING MessageTextU;
666 ANSI_STRING MessageText;
667
668 RtlInitAnsiString (&MessageText, (LPSTR) lpMessageText);
669
670 RtlAnsiStringToUnicodeString (&MessageTextU,
671 &MessageText,
672 TRUE);
673
674 FatalAppExitW (uAction, MessageTextU.Buffer);
675
676 RtlFreeUnicodeString (&MessageTextU);
677 }
678
679
680 /*
681 * @unimplemented
682 */
683 VOID STDCALL
684 FatalAppExitW(UINT uAction,
685 LPCWSTR lpMessageText)
686 {
687 return;
688 }
689
690
691 /*
692 * @implemented
693 */
694 VOID STDCALL
695 FatalExit (int ExitCode)
696 {
697 ExitProcess(ExitCode);
698 }
699
700
701 /*
702 * @implemented
703 */
704 DWORD STDCALL
705 GetPriorityClass (HANDLE hProcess)
706 {
707 HANDLE hProcessTmp;
708 DWORD CsrPriorityClass = 0; // This tells CSRSS we want to GET it!
709 NTSTATUS Status;
710
711 Status =
712 NtDuplicateObject (GetCurrentProcess(),
713 hProcess,
714 GetCurrentProcess(),
715 &hProcessTmp,
716 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
717 FALSE,
718 0);
719 if (!NT_SUCCESS(Status))
720 {
721 SetLastErrorByStatus (Status);
722 return (0); /* ERROR */
723 }
724 /* Ask CSRSS to set it */
725 CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass);
726 NtClose (hProcessTmp);
727 /* Translate CSR->W32 priorities */
728 switch (CsrPriorityClass)
729 {
730 case CSR_PRIORITY_CLASS_NORMAL:
731 return (NORMAL_PRIORITY_CLASS); /* 32 */
732 case CSR_PRIORITY_CLASS_IDLE:
733 return (IDLE_PRIORITY_CLASS); /* 64 */
734 case CSR_PRIORITY_CLASS_HIGH:
735 return (HIGH_PRIORITY_CLASS); /* 128 */
736 case CSR_PRIORITY_CLASS_REALTIME:
737 return (REALTIME_PRIORITY_CLASS); /* 256 */
738 }
739 SetLastError (ERROR_ACCESS_DENIED);
740 return (0); /* ERROR */
741 }
742
743
744 /*
745 * @implemented
746 */
747 BOOL STDCALL
748 SetPriorityClass (HANDLE hProcess,
749 DWORD dwPriorityClass)
750 {
751 HANDLE hProcessTmp;
752 DWORD CsrPriorityClass;
753 NTSTATUS Status;
754
755 switch (dwPriorityClass)
756 {
757 case NORMAL_PRIORITY_CLASS: /* 32 */
758 CsrPriorityClass = CSR_PRIORITY_CLASS_NORMAL;
759 break;
760 case IDLE_PRIORITY_CLASS: /* 64 */
761 CsrPriorityClass = CSR_PRIORITY_CLASS_IDLE;
762 break;
763 case HIGH_PRIORITY_CLASS: /* 128 */
764 CsrPriorityClass = CSR_PRIORITY_CLASS_HIGH;
765 break;
766 case REALTIME_PRIORITY_CLASS: /* 256 */
767 CsrPriorityClass = CSR_PRIORITY_CLASS_REALTIME;
768 break;
769 default:
770 SetLastError (ERROR_INVALID_PARAMETER);
771 return (FALSE);
772 }
773 Status =
774 NtDuplicateObject (GetCurrentProcess(),
775 hProcess,
776 GetCurrentProcess(),
777 &hProcessTmp,
778 (PROCESS_SET_INFORMATION | PROCESS_QUERY_INFORMATION),
779 FALSE,
780 0);
781 if (!NT_SUCCESS(Status))
782 {
783 SetLastErrorByStatus (Status);
784 return (FALSE); /* ERROR */
785 }
786 /* Ask CSRSS to set it */
787 Status = CsrSetPriorityClass (hProcessTmp, &CsrPriorityClass);
788 NtClose (hProcessTmp);
789 if (!NT_SUCCESS(Status))
790 {
791 SetLastErrorByStatus (Status);
792 return (FALSE);
793 }
794 return (TRUE);
795 }
796
797
798 /*
799 * @implemented
800 */
801 DWORD STDCALL
802 GetProcessVersion (DWORD ProcessId)
803 {
804 DWORD Version = 0;
805 PIMAGE_NT_HEADERS NtHeader = NULL;
806 PVOID BaseAddress = NULL;
807
808 /* Caller's */
809 if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
810 {
811 BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
812 NtHeader = RtlImageNtHeader (BaseAddress);
813 if (NULL != NtHeader)
814 {
815 Version =
816 (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
817 (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
818 }
819 }
820 else /* other process */
821 {
822 /* FIXME: open the other process */
823 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
824 }
825 return (Version);
826 }
827
828 /* EOF */