- Merge from trunk up to r45543
[reactos.git] / 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
852 if (!NT_SUCCESS(Status)) goto Error;
853
854 Status = NtReadVirtualMemory(ProcessHandle,
855 ProcessBasicInfo.PebBaseAddress,
856 &Peb,
857 sizeof(Peb),
858 &Count);
859
860 if (!NT_SUCCESS(Status) || Count != sizeof(Peb)) 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)) goto Error;
870 if (DosHeader.e_magic != IMAGE_DOS_SIGNATURE) goto Error;
871
872 memset(&NtHeaders, 0, sizeof(NtHeaders));
873 Status = NtReadVirtualMemory(ProcessHandle,
874 (char *)Peb.ImageBaseAddress + DosHeader.e_lfanew,
875 &NtHeaders,
876 sizeof(NtHeaders),
877 &Count);
878
879 if (!NT_SUCCESS(Status) || Count != sizeof(NtHeaders)) goto Error;
880 if (NtHeaders.Signature != IMAGE_NT_SIGNATURE) goto Error;
881
882 Version = MAKELONG(NtHeaders.OptionalHeader.MinorSubsystemVersion,
883 NtHeaders.OptionalHeader.MajorSubsystemVersion);
884
885 Error:
886 if (!NT_SUCCESS(Status))
887 {
888 SetLastErrorByStatus(Status);
889 }
890 }
891 }
892 _SEH2_FINALLY
893 {
894 if (ProcessHandle) CloseHandle(ProcessHandle);
895 }
896 _SEH2_END;
897
898 return Version;
899 }
900
901
902 /*
903 * @implemented
904 */
905 BOOL
906 WINAPI
907 GetProcessIoCounters(HANDLE hProcess,
908 PIO_COUNTERS lpIoCounters)
909 {
910 NTSTATUS Status;
911
912 Status = NtQueryInformationProcess(hProcess,
913 ProcessIoCounters,
914 lpIoCounters,
915 sizeof(IO_COUNTERS),
916 NULL);
917 if (!NT_SUCCESS(Status))
918 {
919 SetLastErrorByStatus(Status);
920 return FALSE;
921 }
922
923 return TRUE;
924 }
925
926
927 /*
928 * @implemented
929 */
930 BOOL
931 WINAPI
932 GetProcessPriorityBoost(HANDLE hProcess,
933 PBOOL pDisablePriorityBoost)
934 {
935 NTSTATUS Status;
936 ULONG PriorityBoost;
937
938 Status = NtQueryInformationProcess(hProcess,
939 ProcessPriorityBoost,
940 &PriorityBoost,
941 sizeof(ULONG),
942 NULL);
943 if (NT_SUCCESS(Status))
944 {
945 *pDisablePriorityBoost = PriorityBoost;
946 return TRUE;
947 }
948
949 SetLastErrorByStatus(Status);
950 return FALSE;
951 }
952
953
954 /*
955 * @implemented
956 */
957 BOOL
958 WINAPI
959 SetProcessPriorityBoost(HANDLE hProcess,
960 BOOL bDisablePriorityBoost)
961 {
962 NTSTATUS Status;
963 ULONG PriorityBoost = (bDisablePriorityBoost ? TRUE : FALSE); /* prevent setting values other than 1 and 0 */
964
965 Status = NtSetInformationProcess(hProcess,
966 ProcessPriorityBoost,
967 &PriorityBoost,
968 sizeof(ULONG));
969 if (!NT_SUCCESS(Status))
970 {
971 SetLastErrorByStatus(Status);
972 return FALSE;
973 }
974
975 return TRUE;
976 }
977
978
979 /*
980 * @implemented
981 */
982 BOOL
983 WINAPI
984 GetProcessHandleCount(HANDLE hProcess,
985 PDWORD pdwHandleCount)
986 {
987 ULONG phc;
988 NTSTATUS Status;
989
990 Status = NtQueryInformationProcess(hProcess,
991 ProcessHandleCount,
992 &phc,
993 sizeof(ULONG),
994 NULL);
995 if(NT_SUCCESS(Status))
996 {
997 *pdwHandleCount = phc;
998 return TRUE;
999 }
1000
1001 SetLastErrorByStatus(Status);
1002 return FALSE;
1003 }
1004
1005
1006 /*
1007 * @implemented
1008 */
1009 BOOL
1010 WINAPI
1011 IsWow64Process(HANDLE hProcess,
1012 PBOOL Wow64Process)
1013 {
1014 ULONG pbi;
1015 NTSTATUS Status;
1016
1017 Status = NtQueryInformationProcess(hProcess,
1018 ProcessWow64Information,
1019 &pbi,
1020 sizeof(pbi),
1021 NULL);
1022 if (!NT_SUCCESS(Status))
1023 {
1024 SetLastError(RtlNtStatusToDosError(Status));
1025 return FALSE;
1026 }
1027
1028 *Wow64Process = (pbi != 0);
1029
1030 return TRUE;
1031 }
1032
1033
1034 /*
1035 * @implemented
1036 */
1037 BOOL
1038 WINAPI
1039 QueryFullProcessImageNameW(HANDLE hProcess,
1040 DWORD dwFlags,
1041 LPWSTR lpExeName,
1042 PDWORD pdwSize)
1043 {
1044 BYTE Buffer[sizeof(UNICODE_STRING) + MAX_PATH * sizeof(WCHAR)];
1045 UNICODE_STRING *DynamicBuffer = NULL;
1046 UNICODE_STRING *Result = NULL;
1047 NTSTATUS Status;
1048 DWORD Needed;
1049
1050 Status = NtQueryInformationProcess(hProcess,
1051 ProcessImageFileName,
1052 Buffer,
1053 sizeof(Buffer) - sizeof(WCHAR),
1054 &Needed);
1055 if (Status == STATUS_INFO_LENGTH_MISMATCH)
1056 {
1057 DynamicBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Needed + sizeof(WCHAR));
1058 if (!DynamicBuffer)
1059 {
1060 SetLastErrorByStatus(STATUS_NO_MEMORY);
1061 return FALSE;
1062 }
1063
1064 Status = NtQueryInformationProcess(hProcess,
1065 ProcessImageFileName,
1066 (LPBYTE)DynamicBuffer,
1067 Needed,
1068 &Needed);
1069 Result = DynamicBuffer;
1070 }
1071 else Result = (PUNICODE_STRING)Buffer;
1072
1073 if (!NT_SUCCESS(Status)) goto Cleanup;
1074
1075 if (Result->Length / sizeof(WCHAR) + 1 > *pdwSize)
1076 {
1077 Status = STATUS_BUFFER_TOO_SMALL;
1078 goto Cleanup;
1079 }
1080
1081 *pdwSize = Result->Length / sizeof(WCHAR);
1082 memcpy(lpExeName, Result->Buffer, Result->Length);
1083 lpExeName[*pdwSize] = 0;
1084
1085 Cleanup:
1086 RtlFreeHeap(RtlGetProcessHeap(), 0, DynamicBuffer);
1087
1088 if (!NT_SUCCESS(Status))
1089 {
1090 SetLastErrorByStatus(Status);
1091 }
1092
1093 return !Status;
1094 }
1095
1096
1097 /*
1098 * @implemented
1099 */
1100 BOOL
1101 WINAPI
1102 QueryFullProcessImageNameA(HANDLE hProcess,
1103 DWORD dwFlags,
1104 LPSTR lpExeName,
1105 PDWORD pdwSize)
1106 {
1107 DWORD pdwSizeW = *pdwSize;
1108 BOOL Result;
1109 LPWSTR lpExeNameW;
1110
1111 lpExeNameW = RtlAllocateHeap(RtlGetProcessHeap(),
1112 HEAP_ZERO_MEMORY,
1113 *pdwSize * sizeof(WCHAR));
1114 if (!lpExeNameW)
1115 {
1116 SetLastErrorByStatus(STATUS_NO_MEMORY);
1117 return FALSE;
1118 }
1119
1120 Result = QueryFullProcessImageNameW(hProcess, dwFlags, lpExeNameW, &pdwSizeW);
1121
1122 if (Result)
1123 Result = (0 != WideCharToMultiByte(CP_ACP, 0,
1124 lpExeNameW,
1125 -1,
1126 lpExeName,
1127 *pdwSize,
1128 NULL, NULL));
1129
1130 if (Result)
1131 *pdwSize = strlen(lpExeName);
1132
1133 RtlFreeHeap(RtlGetProcessHeap(), 0, lpExeNameW);
1134 return Result;
1135 }
1136
1137 /* EOF */