Fix indentation and coding style. No code changes.
[reactos.git] / reactos / dll / win32 / 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 #define NDEBUG
17 #include <debug.h>
18
19
20 typedef INT (WINAPI *MessageBoxW_Proc) (HWND, LPCWSTR, LPCWSTR, UINT);
21
22 /* GLOBALS *******************************************************************/
23
24 WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
25
26 LPSTARTUPINFOA lpLocalStartupInfo = NULL;
27
28 VOID WINAPI
29 RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle);
30
31 /* FUNCTIONS ****************************************************************/
32
33 /*
34 * @implemented
35 */
36 BOOL
37 WINAPI
38 GetProcessAffinityMask(HANDLE hProcess,
39 LPDWORD lpProcessAffinityMask,
40 LPDWORD lpSystemAffinityMask)
41 {
42 PROCESS_BASIC_INFORMATION ProcessInfo;
43 SYSTEM_BASIC_INFORMATION SystemInfo;
44 NTSTATUS Status;
45
46 Status = NtQuerySystemInformation(SystemBasicInformation,
47 &SystemInfo,
48 sizeof(SystemInfo),
49 NULL);
50 if (!NT_SUCCESS(Status))
51 {
52 SetLastErrorByStatus(Status);
53 return FALSE;
54 }
55
56 Status = NtQueryInformationProcess(hProcess,
57 ProcessBasicInformation,
58 (PVOID)&ProcessInfo,
59 sizeof(PROCESS_BASIC_INFORMATION),
60 NULL);
61 if (!NT_SUCCESS(Status))
62 {
63 SetLastErrorByStatus(Status);
64 return FALSE;
65 }
66
67 *lpProcessAffinityMask = (DWORD)ProcessInfo.AffinityMask;
68 *lpSystemAffinityMask = (DWORD)SystemInfo.ActiveProcessorsAffinityMask;
69
70 return TRUE;
71 }
72
73
74 /*
75 * @implemented
76 */
77 BOOL
78 WINAPI
79 SetProcessAffinityMask(HANDLE hProcess,
80 DWORD dwProcessAffinityMask)
81 {
82 NTSTATUS Status;
83
84 Status = NtSetInformationProcess(hProcess,
85 ProcessAffinityMask,
86 (PVOID)&dwProcessAffinityMask,
87 sizeof(DWORD));
88 if (!NT_SUCCESS(Status))
89 {
90 SetLastErrorByStatus(Status);
91 return FALSE;
92 }
93
94 return TRUE;
95 }
96
97
98 /*
99 * @implemented
100 */
101 BOOL
102 WINAPI
103 GetProcessShutdownParameters(LPDWORD lpdwLevel,
104 LPDWORD lpdwFlags)
105 {
106 CSR_API_MESSAGE CsrRequest;
107 ULONG Request;
108 NTSTATUS Status;
109
110 Request = GET_SHUTDOWN_PARAMETERS;
111 Status = CsrClientCallServer(&CsrRequest,
112 NULL,
113 MAKE_CSR_API(Request, CSR_NATIVE),
114 sizeof(CSR_API_MESSAGE));
115 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
116 {
117 SetLastErrorByStatus(Status);
118 return FALSE;
119 }
120
121 *lpdwLevel = CsrRequest.Data.GetShutdownParametersRequest.Level;
122 *lpdwFlags = CsrRequest.Data.GetShutdownParametersRequest.Flags;
123
124 return TRUE;
125 }
126
127
128 /*
129 * @implemented
130 */
131 BOOL
132 WINAPI
133 SetProcessShutdownParameters(DWORD dwLevel,
134 DWORD dwFlags)
135 {
136 CSR_API_MESSAGE CsrRequest;
137 ULONG Request;
138 NTSTATUS Status;
139
140 CsrRequest.Data.SetShutdownParametersRequest.Level = dwLevel;
141 CsrRequest.Data.SetShutdownParametersRequest.Flags = dwFlags;
142
143 Request = SET_SHUTDOWN_PARAMETERS;
144 Status = CsrClientCallServer(&CsrRequest,
145 NULL,
146 MAKE_CSR_API(Request, CSR_NATIVE),
147 sizeof(CSR_API_MESSAGE));
148 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
149 {
150 SetLastErrorByStatus(Status);
151 return FALSE;
152 }
153
154 return TRUE;
155 }
156
157
158 /*
159 * @implemented
160 */
161 BOOL
162 WINAPI
163 GetProcessWorkingSetSize(HANDLE hProcess,
164 PSIZE_T lpMinimumWorkingSetSize,
165 PSIZE_T lpMaximumWorkingSetSize)
166 {
167 QUOTA_LIMITS QuotaLimits;
168 NTSTATUS Status;
169
170 Status = NtQueryInformationProcess(hProcess,
171 ProcessQuotaLimits,
172 &QuotaLimits,
173 sizeof(QUOTA_LIMITS),
174 NULL);
175 if (!NT_SUCCESS(Status))
176 {
177 SetLastErrorByStatus(Status);
178 return FALSE;
179 }
180
181 *lpMinimumWorkingSetSize = QuotaLimits.MinimumWorkingSetSize;
182 *lpMaximumWorkingSetSize = QuotaLimits.MaximumWorkingSetSize;
183
184 return TRUE;
185 }
186
187
188 /*
189 * @implemented
190 */
191 BOOL
192 WINAPI
193 SetProcessWorkingSetSize(HANDLE hProcess,
194 SIZE_T dwMinimumWorkingSetSize,
195 SIZE_T dwMaximumWorkingSetSize)
196 {
197 QUOTA_LIMITS QuotaLimits;
198 NTSTATUS Status;
199
200 QuotaLimits.MinimumWorkingSetSize = dwMinimumWorkingSetSize;
201 QuotaLimits.MaximumWorkingSetSize = dwMaximumWorkingSetSize;
202
203 Status = NtSetInformationProcess(hProcess,
204 ProcessQuotaLimits,
205 &QuotaLimits,
206 sizeof(QUOTA_LIMITS));
207 if (!NT_SUCCESS(Status))
208 {
209 SetLastErrorByStatus(Status);
210 return FALSE;
211 }
212
213 return TRUE;
214 }
215
216
217 /*
218 * @implemented
219 */
220 BOOL
221 WINAPI
222 GetProcessTimes(HANDLE hProcess,
223 LPFILETIME lpCreationTime,
224 LPFILETIME lpExitTime,
225 LPFILETIME lpKernelTime,
226 LPFILETIME lpUserTime)
227 {
228 KERNEL_USER_TIMES Kut;
229 NTSTATUS Status;
230
231 Status = NtQueryInformationProcess(hProcess,
232 ProcessTimes,
233 &Kut,
234 sizeof(Kut),
235 NULL);
236 if (!NT_SUCCESS(Status))
237 {
238 SetLastErrorByStatus(Status);
239 return FALSE;
240 }
241
242 lpCreationTime->dwLowDateTime = Kut.CreateTime.u.LowPart;
243 lpCreationTime->dwHighDateTime = Kut.CreateTime.u.HighPart;
244
245 lpExitTime->dwLowDateTime = Kut.ExitTime.u.LowPart;
246 lpExitTime->dwHighDateTime = Kut.ExitTime.u.HighPart;
247
248 lpKernelTime->dwLowDateTime = Kut.KernelTime.u.LowPart;
249 lpKernelTime->dwHighDateTime = Kut.KernelTime.u.HighPart;
250
251 lpUserTime->dwLowDateTime = Kut.UserTime.u.LowPart;
252 lpUserTime->dwHighDateTime = Kut.UserTime.u.HighPart;
253
254 return TRUE;
255 }
256
257
258 /*
259 * @implemented
260 */
261 HANDLE
262 WINAPI
263 GetCurrentProcess(VOID)
264 {
265 return (HANDLE)NtCurrentProcess();
266 }
267
268
269 /*
270 * @implemented
271 */
272 HANDLE
273 WINAPI
274 GetCurrentThread(VOID)
275 {
276 return (HANDLE)NtCurrentThread();
277 }
278
279
280 /*
281 * @implemented
282 */
283 DWORD
284 WINAPI
285 GetCurrentProcessId(VOID)
286 {
287 return (DWORD)GetTeb()->ClientId.UniqueProcess;
288 }
289
290
291 /*
292 * @implemented
293 */
294 BOOL
295 WINAPI
296 GetExitCodeProcess(HANDLE hProcess,
297 LPDWORD lpExitCode)
298 {
299 PROCESS_BASIC_INFORMATION ProcessBasic;
300 NTSTATUS Status;
301
302 Status = NtQueryInformationProcess(hProcess,
303 ProcessBasicInformation,
304 &ProcessBasic,
305 sizeof(PROCESS_BASIC_INFORMATION),
306 NULL);
307 if (!NT_SUCCESS(Status))
308 {
309 SetLastErrorByStatus(Status);
310 return FALSE;
311 }
312
313 *lpExitCode = (DWORD)ProcessBasic.ExitStatus;
314
315 return TRUE;
316 }
317
318
319 /*
320 * @implemented
321 */
322 DWORD
323 WINAPI
324 GetProcessId(HANDLE Process)
325 {
326 PROCESS_BASIC_INFORMATION ProcessBasic;
327 NTSTATUS Status;
328
329 Status = NtQueryInformationProcess(Process,
330 ProcessBasicInformation,
331 &ProcessBasic,
332 sizeof(PROCESS_BASIC_INFORMATION),
333 NULL);
334 if (!NT_SUCCESS(Status))
335 {
336 SetLastErrorByStatus(Status);
337 return 0;
338 }
339
340 return (DWORD)ProcessBasic.UniqueProcessId;
341 }
342
343
344 /*
345 * @implemented
346 */
347 HANDLE
348 WINAPI
349 OpenProcess(DWORD dwDesiredAccess,
350 BOOL bInheritHandle,
351 DWORD dwProcessId)
352 {
353 NTSTATUS errCode;
354 HANDLE ProcessHandle;
355 OBJECT_ATTRIBUTES ObjectAttributes;
356 CLIENT_ID ClientId;
357
358 ClientId.UniqueProcess = (HANDLE)dwProcessId;
359 ClientId.UniqueThread = 0;
360
361 InitializeObjectAttributes(&ObjectAttributes,
362 NULL,
363 (bInheritHandle ? OBJ_INHERIT : 0),
364 NULL,
365 NULL);
366
367 errCode = NtOpenProcess(&ProcessHandle,
368 dwDesiredAccess,
369 &ObjectAttributes,
370 &ClientId);
371 if (!NT_SUCCESS(errCode))
372 {
373 SetLastErrorByStatus(errCode);
374 return NULL;
375 }
376
377 return ProcessHandle;
378 }
379
380
381 /*
382 * @implemented
383 */
384 UINT
385 WINAPI
386 WinExec(LPCSTR lpCmdLine,
387 UINT uCmdShow)
388 {
389 STARTUPINFOA StartupInfo;
390 PROCESS_INFORMATION ProcessInformation;
391 DWORD dosErr;
392
393 RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
394 StartupInfo.cb = sizeof(STARTUPINFOA);
395 StartupInfo.wShowWindow = (WORD)uCmdShow;
396 StartupInfo.dwFlags = 0;
397
398 if (!CreateProcessA(NULL,
399 (PVOID)lpCmdLine,
400 NULL,
401 NULL,
402 FALSE,
403 0,
404 NULL,
405 NULL,
406 &StartupInfo,
407 &ProcessInformation))
408 {
409 dosErr = GetLastError();
410 return dosErr < 32 ? dosErr : ERROR_BAD_FORMAT;
411 }
412
413 if (NULL != lpfnGlobalRegisterWaitForInputIdle)
414 {
415 lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess,
416 10000);
417 }
418
419 NtClose(ProcessInformation.hProcess);
420 NtClose(ProcessInformation.hThread);
421
422 return 33; /* Something bigger than 31 means success. */
423 }
424
425
426 /*
427 * @implemented
428 */
429 VOID
430 WINAPI
431 RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle)
432 {
433 lpfnGlobalRegisterWaitForInputIdle = lpfnRegisterWaitForInputIdle;
434 return;
435 }
436
437 /*
438 * @implemented
439 */
440 VOID
441 WINAPI
442 GetStartupInfoW(LPSTARTUPINFOW lpStartupInfo)
443 {
444 PRTL_USER_PROCESS_PARAMETERS Params;
445
446 if (lpStartupInfo == NULL)
447 {
448 SetLastError(ERROR_INVALID_PARAMETER);
449 return;
450 }
451
452 Params = NtCurrentPeb()->ProcessParameters;
453
454 lpStartupInfo->cb = sizeof(STARTUPINFOW);
455 lpStartupInfo->lpDesktop = Params->DesktopInfo.Buffer;
456 lpStartupInfo->lpTitle = Params->WindowTitle.Buffer;
457 lpStartupInfo->dwX = Params->StartingX;
458 lpStartupInfo->dwY = Params->StartingY;
459 lpStartupInfo->dwXSize = Params->CountX;
460 lpStartupInfo->dwYSize = Params->CountY;
461 lpStartupInfo->dwXCountChars = Params->CountCharsX;
462 lpStartupInfo->dwYCountChars = Params->CountCharsY;
463 lpStartupInfo->dwFillAttribute = Params->FillAttribute;
464 lpStartupInfo->dwFlags = Params->WindowFlags;
465 lpStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
466 lpStartupInfo->cbReserved2 = Params->RuntimeData.Length;
467 lpStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
468
469 lpStartupInfo->hStdInput = Params->StandardInput;
470 lpStartupInfo->hStdOutput = Params->StandardOutput;
471 lpStartupInfo->hStdError = Params->StandardError;
472 }
473
474
475 /*
476 * @implemented
477 */
478 VOID
479 WINAPI
480 GetStartupInfoA(LPSTARTUPINFOA lpStartupInfo)
481 {
482 PRTL_USER_PROCESS_PARAMETERS Params;
483 ANSI_STRING AnsiString;
484
485 if (lpStartupInfo == NULL)
486 {
487 SetLastError(ERROR_INVALID_PARAMETER);
488 return;
489 }
490
491 Params = NtCurrentPeb ()->ProcessParameters;
492
493 RtlAcquirePebLock ();
494
495 /* FIXME - not thread-safe */
496 if (lpLocalStartupInfo == NULL)
497 {
498 /* create new local startup info (ansi) */
499 lpLocalStartupInfo = RtlAllocateHeap(RtlGetProcessHeap(),
500 0,
501 sizeof(STARTUPINFOA));
502 if (lpLocalStartupInfo == NULL)
503 {
504 RtlReleasePebLock();
505 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
506 return;
507 }
508
509 lpLocalStartupInfo->cb = sizeof(STARTUPINFOA);
510
511 /* copy window title string */
512 RtlUnicodeStringToAnsiString(&AnsiString,
513 &Params->WindowTitle,
514 TRUE);
515 lpLocalStartupInfo->lpTitle = AnsiString.Buffer;
516
517 /* copy desktop info string */
518 RtlUnicodeStringToAnsiString(&AnsiString,
519 &Params->DesktopInfo,
520 TRUE);
521 lpLocalStartupInfo->lpDesktop = AnsiString.Buffer;
522
523 /* copy shell info string */
524 RtlUnicodeStringToAnsiString(&AnsiString,
525 &Params->ShellInfo,
526 TRUE);
527 lpLocalStartupInfo->lpReserved = AnsiString.Buffer;
528
529 lpLocalStartupInfo->dwX = Params->StartingX;
530 lpLocalStartupInfo->dwY = Params->StartingY;
531 lpLocalStartupInfo->dwXSize = Params->CountX;
532 lpLocalStartupInfo->dwYSize = Params->CountY;
533 lpLocalStartupInfo->dwXCountChars = Params->CountCharsX;
534 lpLocalStartupInfo->dwYCountChars = Params->CountCharsY;
535 lpLocalStartupInfo->dwFillAttribute = Params->FillAttribute;
536 lpLocalStartupInfo->dwFlags = Params->WindowFlags;
537 lpLocalStartupInfo->wShowWindow = (WORD)Params->ShowWindowFlags;
538 lpLocalStartupInfo->cbReserved2 = Params->RuntimeData.Length;
539 lpLocalStartupInfo->lpReserved2 = (LPBYTE)Params->RuntimeData.Buffer;
540
541 lpLocalStartupInfo->hStdInput = Params->StandardInput;
542 lpLocalStartupInfo->hStdOutput = Params->StandardOutput;
543 lpLocalStartupInfo->hStdError = Params->StandardError;
544 }
545
546 RtlReleasePebLock();
547
548 /* copy local startup info data to external startup info */
549 memcpy(lpStartupInfo,
550 lpLocalStartupInfo,
551 sizeof(STARTUPINFOA));
552 }
553
554
555 /*
556 * @implemented
557 */
558 BOOL
559 WINAPI
560 FlushInstructionCache(HANDLE hProcess,
561 LPCVOID lpBaseAddress,
562 DWORD dwSize)
563 {
564 NTSTATUS Status;
565
566 Status = NtFlushInstructionCache(hProcess,
567 (PVOID)lpBaseAddress,
568 dwSize);
569 if (!NT_SUCCESS(Status))
570 {
571 SetLastErrorByStatus(Status);
572 return FALSE;
573 }
574
575 return TRUE;
576 }
577
578
579 /*
580 * @implemented
581 */
582 VOID
583 WINAPI
584 ExitProcess(UINT uExitCode)
585 {
586 CSR_API_MESSAGE CsrRequest;
587 ULONG Request;
588 NTSTATUS Status;
589
590 /* kill sibling threads ... we want to be alone at this point */
591 NtTerminateProcess(NULL, 0);
592
593 /* unload all dll's */
594 LdrShutdownProcess();
595
596 /* notify csrss of process termination */
597 Request = TERMINATE_PROCESS;
598 Status = CsrClientCallServer(&CsrRequest,
599 NULL,
600 MAKE_CSR_API(Request, CSR_NATIVE),
601 sizeof(CSR_API_MESSAGE));
602 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
603 {
604 DPRINT("Failed to tell csrss about terminating process\n");
605 }
606
607 NtTerminateProcess(NtCurrentProcess (),
608 uExitCode);
609
610 /* should never get here */
611 ASSERT(0);
612 while(1);
613 }
614
615
616 /*
617 * @implemented
618 */
619 BOOL
620 WINAPI
621 TerminateProcess(HANDLE hProcess,
622 UINT uExitCode)
623 {
624 NTSTATUS Status;
625
626 if (hProcess == NULL)
627 {
628 return FALSE;
629 }
630
631 Status = NtTerminateProcess(hProcess, uExitCode);
632 if (NT_SUCCESS(Status))
633 {
634 return TRUE;
635 }
636
637 SetLastErrorByStatus(Status);
638 return FALSE;
639 }
640
641
642 /*
643 * @unimplemented
644 */
645 VOID
646 WINAPI
647 FatalAppExitA(UINT uAction,
648 LPCSTR lpMessageText)
649 {
650 UNICODE_STRING MessageTextU;
651 ANSI_STRING MessageText;
652
653 RtlInitAnsiString(&MessageText, (LPSTR)lpMessageText);
654
655 RtlAnsiStringToUnicodeString(&MessageTextU,
656 &MessageText,
657 TRUE);
658
659 FatalAppExitW(uAction, MessageTextU.Buffer);
660
661 RtlFreeUnicodeString(&MessageTextU);
662 }
663
664
665 /*
666 * @unimplemented
667 */
668 VOID
669 WINAPI
670 FatalAppExitW(UINT uAction,
671 LPCWSTR lpMessageText)
672 {
673 static const WCHAR szUser32[] = L"user32.dll\0";
674
675 HMODULE hModule = GetModuleHandleW(szUser32);
676 MessageBoxW_Proc pMessageBoxW = NULL;
677
678 DPRINT1("AppExit\n");
679
680 if (hModule)
681 pMessageBoxW = (MessageBoxW_Proc)GetProcAddress(hModule, "MessageBoxW");
682
683 if (pMessageBoxW)
684 pMessageBoxW(0, lpMessageText, NULL, MB_SYSTEMMODAL | MB_OK);
685 else
686 DPRINT1("%s\n", lpMessageText);
687
688 ExitProcess(0);
689 }
690
691
692 /*
693 * @implemented
694 */
695 VOID
696 WINAPI
697 FatalExit(int ExitCode)
698 {
699 ExitProcess(ExitCode);
700 }
701
702
703 /*
704 * @implemented
705 */
706 DWORD
707 WINAPI
708 GetPriorityClass(HANDLE hProcess)
709 {
710 NTSTATUS Status;
711 PROCESS_PRIORITY_CLASS PriorityClass;
712
713 Status = NtQueryInformationProcess(hProcess,
714 ProcessPriorityClass,
715 &PriorityClass,
716 sizeof(PROCESS_PRIORITY_CLASS),
717 NULL);
718 if(NT_SUCCESS(Status))
719 {
720 switch(PriorityClass.PriorityClass)
721 {
722 case PROCESS_PRIORITY_CLASS_IDLE:
723 return IDLE_PRIORITY_CLASS;
724
725 case PROCESS_PRIORITY_CLASS_BELOW_NORMAL:
726 return BELOW_NORMAL_PRIORITY_CLASS;
727
728 case PROCESS_PRIORITY_CLASS_NORMAL:
729 return NORMAL_PRIORITY_CLASS;
730
731 case PROCESS_PRIORITY_CLASS_ABOVE_NORMAL:
732 return ABOVE_NORMAL_PRIORITY_CLASS;
733
734 case PROCESS_PRIORITY_CLASS_HIGH:
735 return HIGH_PRIORITY_CLASS;
736
737 case PROCESS_PRIORITY_CLASS_REALTIME:
738 return REALTIME_PRIORITY_CLASS;
739
740 default:
741 return NORMAL_PRIORITY_CLASS;
742 }
743 }
744
745 SetLastErrorByStatus(Status);
746 return FALSE;
747 }
748
749
750 /*
751 * @implemented
752 */
753 BOOL
754 WINAPI
755 SetPriorityClass(HANDLE hProcess,
756 DWORD dwPriorityClass)
757 {
758 NTSTATUS Status;
759 PROCESS_PRIORITY_CLASS PriorityClass;
760
761 switch (dwPriorityClass)
762 {
763 case IDLE_PRIORITY_CLASS:
764 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE;
765 break;
766
767 case BELOW_NORMAL_PRIORITY_CLASS:
768 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL;
769 break;
770
771 case NORMAL_PRIORITY_CLASS:
772 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL;
773 break;
774
775 case ABOVE_NORMAL_PRIORITY_CLASS:
776 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL;
777 break;
778
779 case HIGH_PRIORITY_CLASS:
780 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH;
781 break;
782
783 case REALTIME_PRIORITY_CLASS:
784 PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME;
785 break;
786
787 default:
788 SetLastError(ERROR_INVALID_PARAMETER);
789 return FALSE;
790 }
791
792 PriorityClass.Foreground = FALSE;
793
794 Status = NtSetInformationProcess(hProcess,
795 ProcessPriorityClass,
796 &PriorityClass,
797 sizeof(PROCESS_PRIORITY_CLASS));
798 if (!NT_SUCCESS(Status))
799 {
800 SetLastErrorByStatus(Status);
801 return FALSE;
802 }
803
804 return TRUE;
805 }
806
807
808 /*
809 * @implemented
810 */
811 DWORD
812 WINAPI
813 GetProcessVersion(DWORD ProcessId)
814 {
815 DWORD Version = 0;
816 PIMAGE_NT_HEADERS NtHeader = NULL;
817 IMAGE_NT_HEADERS NtHeaders;
818 IMAGE_DOS_HEADER DosHeader;
819 PROCESS_BASIC_INFORMATION ProcessBasicInfo;
820 PVOID BaseAddress = NULL;
821 HANDLE ProcessHandle = NULL;
822 NTSTATUS Status;
823 SIZE_T Count;
824 PEB Peb;
825
826 _SEH2_TRY
827 {
828 if (0 == ProcessId || GetCurrentProcessId() == ProcessId)
829 {
830 /* Caller's */
831 BaseAddress = (PVOID) NtCurrentPeb()->ImageBaseAddress;
832 NtHeader = RtlImageNtHeader(BaseAddress);
833
834 Version = (NtHeader->OptionalHeader.MajorOperatingSystemVersion << 16) |
835 (NtHeader->OptionalHeader.MinorOperatingSystemVersion);
836 }
837 else
838 {
839 /* Other process */
840 ProcessHandle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
841 FALSE,
842 ProcessId);
843
844 if (!ProcessHandle) return 0;
845
846 Status = NtQueryInformationProcess(ProcessHandle,
847 ProcessBasicInformation,
848 &ProcessBasicInfo,
849 sizeof(ProcessBasicInfo),
850 NULL);
851 if (!NT_SUCCESS(Status))
852 goto Error;
853
854 Status = NtReadVirtualMemory(ProcessHandle,
855 ProcessBasicInfo.PebBaseAddress,
856 &Peb,
857 sizeof(Peb),
858 &Count);
859 if (!NT_SUCCESS(Status) || Count != sizeof(Peb))
860 goto Error;
861
862 memset(&DosHeader, 0, sizeof(DosHeader));
863 Status = NtReadVirtualMemory(ProcessHandle,
864 Peb.ImageBaseAddress,
865 &DosHeader,
866 sizeof(DosHeader),
867 &Count);
868
869 if (!NT_SUCCESS(Status) || Count != sizeof(DosHeader))
870 goto Error;
871
872 if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE)
873 goto Error;
874
875 memset(&NtHeaders, 0, sizeof(NtHeaders));
876 Status = NtReadVirtualMemory(ProcessHandle,
877 (char *)Peb.ImageBaseAddress + DosHeader.e_lfanew,
878 &NtHeaders,
879 sizeof(NtHeaders),
880 &Count);
881
882 if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders))
883 goto Error;
884
885 if (NtHeaders.Signature != IMAGE_NT_SIGNATURE)
886 goto Error;
887
888 Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
889 NtHeaders.OptionalHeader.MajorSubsystemVersion);
890
891 Error:
892 if (!NT_SUCCESS(Status))
893 {
894 SetLastErrorByStatus(Status);
895 }
896 }
897 }
898 _SEH2_FINALLY
899 {
900 if (ProcessHandle)
901 CloseHandle(ProcessHandle);
902 }
903 _SEH2_END;
904
905 return Version;
906 }
907
908
909 /*
910 * @implemented
911 */
912 BOOL
913 WINAPI
914 GetProcessIoCounters(HANDLE hProcess,
915 PIO_COUNTERS lpIoCounters)
916 {
917 NTSTATUS Status;
918
919 Status = NtQueryInformationProcess(hProcess,
920 ProcessIoCounters,
921 lpIoCounters,
922 sizeof(IO_COUNTERS),
923 NULL);
924 if (!NT_SUCCESS(Status))
925 {
926 SetLastErrorByStatus(Status);
927 return FALSE;
928 }
929
930 return TRUE;
931 }
932
933
934 /*
935 * @implemented
936 */
937 BOOL
938 WINAPI
939 GetProcessPriorityBoost(HANDLE hProcess,
940 PBOOL pDisablePriorityBoost)
941 {
942 NTSTATUS Status;
943 ULONG PriorityBoost;
944
945 Status = NtQueryInformationProcess(hProcess,
946 ProcessPriorityBoost,
947 &PriorityBoost,
948 sizeof(ULONG),
949 NULL);
950 if (NT_SUCCESS(Status))
951 {
952 *pDisablePriorityBoost = PriorityBoost;
953 return TRUE;
954 }
955
956 SetLastErrorByStatus(Status);
957 return FALSE;
958 }
959
960
961 /*
962 * @implemented
963 */
964 BOOL
965 WINAPI
966 SetProcessPriorityBoost(HANDLE hProcess,
967 BOOL bDisablePriorityBoost)
968 {
969 NTSTATUS Status;
970 ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
971
972 Status = NtSetInformationProcess(hProcess,
973 ProcessPriorityBoost,
974 &PriorityBoost,
975 sizeof(ULONG));
976 if (!NT_SUCCESS(Status))
977 {
978 SetLastErrorByStatus(Status);
979 return FALSE;
980 }
981
982 return TRUE;
983 }
984
985
986 /*
987 * @implemented
988 */
989 BOOL
990 WINAPI
991 GetProcessHandleCount(HANDLE hProcess,
992 PDWORD pdwHandleCount)
993 {
994 ULONG phc;
995 NTSTATUS Status;
996
997 Status = NtQueryInformationProcess(hProcess,
998 ProcessHandleCount,
999 &phc,
1000 sizeof(ULONG),
1001 NULL);
1002 if(NT_SUCCESS(Status))
1003 {
1004 *pdwHandleCount = phc;
1005 return TRUE;
1006 }
1007
1008 SetLastErrorByStatus(Status);
1009 return FALSE;
1010 }
1011
1012
1013 /*
1014 * @implemented
1015 */
1016 BOOL
1017 WINAPI
1018 IsWow64Process(HANDLE hProcess,
1019 PBOOL Wow64Process)
1020 {
1021 ULONG pbi;
1022 NTSTATUS Status;
1023
1024 Status = NtQueryInformationProcess(hProcess,
1025 ProcessWow64Information,
1026 &pbi,
1027 sizeof(pbi),
1028 NULL);
1029 if (!NT_SUCCESS(Status))
1030 {
1031 SetLastError(RtlNtStatusToDosError(Status));
1032 return FALSE;
1033 }
1034
1035 *Wow64Process = (pbi != 0);
1036
1037 return TRUE;
1038 }
1039
1040
1041 /*
1042 * @implemented
1043 */
1044 BOOL
1045 WINAPI
1046 QueryFullProcessImageNameW(HANDLE hProcess,
1047 DWORD dwFlags,
1048 LPWSTR lpExeName,
1049 PDWORD pdwSize)
1050 {
1051 BYTE Buffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)];
1052 UNICODE_STRING *DynamicBuffer = NULL;
1053 UNICODE_STRING *Result = NULL;
1054 NTSTATUS Status;
1055 DWORD Needed;
1056
1057 Status = NtQueryInformationProcess(hProcess,
1058 ProcessImageFileName,
1059 Buffer,
1060 sizeof(Buffer) - sizeof(WCHAR),
1061 &Needed);
1062 if (Status == STATUS_INFO_LENGTH_MISMATCH)
1063 {
1064 DynamicBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Needed + sizeof(WCHAR));
1065 if (!DynamicBuffer)
1066 {
1067 SetLastErrorByStatus(STATUS_NO_MEMORY);
1068 return FALSE;
1069 }
1070
1071 Status = NtQueryInformationProcess(hProcess,
1072 ProcessImageFileName,
1073 (LPBYTE)DynamicBuffer,
1074 Needed,
1075 &Needed);
1076 Result = DynamicBuffer;
1077 }
1078 else
1079 Result = (PUNICODE_STRING)Buffer;
1080
1081 if (!NT_SUCCESS(Status))
1082 goto Cleanup;
1083
1084 if (Result->Length / sizeof(WCHAR) + 1 > *pdwSize)
1085 {
1086 Status = STATUS_BUFFER_TOO_SMALL;
1087 goto Cleanup;
1088 }
1089
1090 *pdwSize = Result->Length / sizeof(WCHAR);
1091 memcpy(lpExeName, Result->Buffer, Result->Length);
1092 lpExeName[*pdwSize] = 0;
1093
1094 Cleanup:
1095 RtlFreeHeap(RtlGetProcessHeap(), 0, DynamicBuffer);
1096
1097 if (!NT_SUCCESS(Status))
1098 {
1099 SetLastErrorByStatus(Status);
1100 }
1101
1102 return !Status;
1103 }
1104
1105
1106 /*
1107 * @implemented
1108 */
1109 BOOL
1110 WINAPI
1111 QueryFullProcessImageNameA(HANDLE hProcess,
1112 DWORD dwFlags,
1113 LPSTR lpExeName,
1114 PDWORD pdwSize)
1115 {
1116 DWORD pdwSizeW = *pdwSize;
1117 BOOL Result;
1118 LPWSTR lpExeNameW;
1119
1120 lpExeNameW = RtlAllocateHeap(RtlGetProcessHeap(),
1121 HEAP_ZERO_MEMORY,
1122 *pdwSize * sizeof(WCHAR));
1123 if (!lpExeNameW)
1124 {
1125 SetLastErrorByStatus(STATUS_NO_MEMORY);
1126 return FALSE;
1127 }
1128
1129 Result = QueryFullProcessImageNameW(hProcess, dwFlags, lpExeNameW, &pdwSizeW);
1130
1131 if (Result)
1132 Result = (0 != WideCharToMultiByte(CP_ACP, 0,
1133 lpExeNameW,
1134 -1,
1135 lpExeName,
1136 *pdwSize,
1137 NULL, NULL));
1138
1139 if (Result)
1140 *pdwSize = strlen(lpExeName);
1141
1142 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExeNameW);
1143 return Result;
1144 }
1145
1146 /* EOF */