Reactos
at master 1601 lines 42 kB view raw
1/* 2 * COPYRIGHT: See COPYING in the top level directory 3 * LICENSE: See LGPL.txt in the top level directory 4 * PROJECT: ReactOS system libraries 5 * FILE: reactos/lib/psapi/misc/win32.c 6 * PURPOSE: Win32 interfaces for PSAPI 7 * PROGRAMMER: KJK::Hyperion <noog@libero.it> 8 * Thomas Weidenmueller <w3seek@reactos.com> 9 * Pierre Schweitzer <pierre@reactos.org> 10 * UPDATE HISTORY: 11 * 10/06/2002: Created 12 */ 13 14#include <stdarg.h> 15 16#define WIN32_NO_STATUS 17#include <windef.h> 18#include <winbase.h> 19#include <winnls.h> 20#define NTOS_MODE_USER 21#include <ndk/exfuncs.h> 22#include <ndk/mmfuncs.h> 23#include <ndk/psfuncs.h> 24#include <ndk/rtlfuncs.h> 25 26#include <psapi.h> 27 28#include <pseh/pseh2.h> 29 30#define NDEBUG 31#include <debug.h> 32 33#define MAX_MODULES 0x2710 // Matches 10.000 modules 34#define INIT_MEMORY_SIZE 0x1000 // Matches 4kB 35 36/* INTERNAL *******************************************************************/ 37 38/* 39 * @implemented 40 */ 41static BOOL NTAPI 42FindDeviceDriver(IN PVOID ImageBase, 43 OUT PRTL_PROCESS_MODULE_INFORMATION MatchingModule) 44{ 45 NTSTATUS Status; 46 DWORD i, RequiredSize; 47 PRTL_PROCESS_MODULES Information; 48 RTL_PROCESS_MODULE_INFORMATION Module; 49 /* By default, to prevent too many reallocations, we already make room for 4 modules */ 50 DWORD Size = sizeof(RTL_PROCESS_MODULES) + 3 * sizeof(RTL_PROCESS_MODULE_INFORMATION); 51 52 while (TRUE) 53 { 54 /* Allocate a buffer to hold modules information */ 55 Information = LocalAlloc(LMEM_FIXED, Size); 56 if (!Information) 57 { 58 SetLastError(ERROR_NO_SYSTEM_RESOURCES); 59 return FALSE; 60 } 61 62 /* Query information */ 63 Status = NtQuerySystemInformation(SystemModuleInformation, Information, Size, &RequiredSize); 64 if (!NT_SUCCESS(Status)) 65 { 66 /* Free the current buffer */ 67 LocalFree(Information); 68 69 /* If it was not a length mismatch (ie, buffer too small), just leave */ 70 if (Status != STATUS_INFO_LENGTH_MISMATCH) 71 { 72 SetLastError(RtlNtStatusToDosError(Status)); 73 return FALSE; 74 } 75 76 /* Try again with the required size */ 77 Size = RequiredSize; 78 continue; 79 } 80 81 /* No modules returned? Leave */ 82 if (Information->NumberOfModules == 0) 83 { 84 break; 85 } 86 87 /* Try to find which module matches the base address given */ 88 for (i = 0; i < Information->NumberOfModules; ++i) 89 { 90 Module = Information->Modules[i]; 91 if (Module.ImageBase == ImageBase) 92 { 93 /* Copy the matching module and leave */ 94 memcpy(MatchingModule, &Module, sizeof(Module)); 95 LocalFree(Information); 96 return TRUE; 97 } 98 } 99 100 /* If we arrive here, it means we were not able to find matching base address */ 101 break; 102 } 103 104 /* Release and leave */ 105 LocalFree(Information); 106 SetLastError(ERROR_INVALID_HANDLE); 107 108 return FALSE; 109} 110 111/* 112 * @implemented 113 */ 114static BOOL NTAPI 115FindModule(IN HANDLE hProcess, 116 IN HMODULE hModule OPTIONAL, 117 OUT PLDR_DATA_TABLE_ENTRY Module) 118{ 119 DWORD Count; 120 NTSTATUS Status; 121 PPEB_LDR_DATA LoaderData; 122 PLIST_ENTRY ListHead, ListEntry; 123 PROCESS_BASIC_INFORMATION ProcInfo; 124 125 /* Query the process information to get its PEB address */ 126 Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); 127 if (!NT_SUCCESS(Status)) 128 { 129 SetLastError(RtlNtStatusToDosError(Status)); 130 return FALSE; 131 } 132 133 /* If no module was provided, get base as module */ 134 if (hModule == NULL) 135 { 136 if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->ImageBaseAddress, &hModule, sizeof(hModule), NULL)) 137 { 138 return FALSE; 139 } 140 } 141 142 /* Read loader data address from PEB */ 143 if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) 144 { 145 return FALSE; 146 } 147 148 if (LoaderData == NULL) 149 { 150 SetLastError(ERROR_INVALID_HANDLE); 151 return FALSE; 152 } 153 154 /* Store list head address */ 155 ListHead = &(LoaderData->InMemoryOrderModuleList); 156 157 /* Read first element in the modules list */ 158 if (!ReadProcessMemory(hProcess, 159 &(LoaderData->InMemoryOrderModuleList.Flink), 160 &ListEntry, 161 sizeof(ListEntry), 162 NULL)) 163 { 164 return FALSE; 165 } 166 167 Count = 0; 168 169 /* Loop on the modules */ 170 while (ListEntry != ListHead) 171 { 172 /* Load module data */ 173 if (!ReadProcessMemory(hProcess, 174 CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks), 175 Module, 176 sizeof(*Module), 177 NULL)) 178 { 179 return FALSE; 180 } 181 182 /* Does that match the module we're looking for? */ 183 if (Module->DllBase == hModule) 184 { 185 return TRUE; 186 } 187 188 ++Count; 189 if (Count > MAX_MODULES) 190 { 191 break; 192 } 193 194 /* Get to next listed module */ 195 ListEntry = Module->InMemoryOrderLinks.Flink; 196 } 197 198 SetLastError(ERROR_INVALID_HANDLE); 199 return FALSE; 200} 201 202typedef struct _INTERNAL_ENUM_PAGE_FILES_CONTEXT 203{ 204 LPVOID lpContext; 205 PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine; 206 DWORD dwErrCode; 207} INTERNAL_ENUM_PAGE_FILES_CONTEXT, *PINTERNAL_ENUM_PAGE_FILES_CONTEXT; 208 209/* 210 * @implemented 211 */ 212static BOOL CALLBACK 213CallBackConvertToAscii(LPVOID pContext, 214 PENUM_PAGE_FILE_INFORMATION pPageFileInfo, 215 LPCWSTR lpFilename) 216{ 217 BOOL Ret; 218 SIZE_T Len; 219 LPSTR AnsiFileName; 220 PINTERNAL_ENUM_PAGE_FILES_CONTEXT Context = (PINTERNAL_ENUM_PAGE_FILES_CONTEXT)pContext; 221 222 Len = wcslen(lpFilename); 223 224 /* Alloc space for the ANSI string */ 225 AnsiFileName = LocalAlloc(LMEM_FIXED, (Len * sizeof(CHAR)) + sizeof(ANSI_NULL)); 226 if (AnsiFileName == NULL) 227 { 228 Context->dwErrCode = RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES); 229 return FALSE; 230 } 231 232 /* Convert string to ANSI */ 233 if (WideCharToMultiByte(CP_ACP, 0, lpFilename, -1, AnsiFileName, (Len * sizeof(CHAR)) + sizeof(ANSI_NULL), NULL, NULL) == 0) 234 { 235 Context->dwErrCode = GetLastError(); 236 LocalFree(AnsiFileName); 237 return FALSE; 238 } 239 240 /* And finally call "real" callback */ 241 Ret = Context->pCallbackRoutine(Context->lpContext, pPageFileInfo, AnsiFileName); 242 LocalFree(AnsiFileName); 243 244 return Ret; 245} 246 247/* 248 * @implemented 249 */ 250BOOL 251WINAPI 252EmptyWorkingSet(HANDLE hProcess) 253{ 254 SYSTEM_INFO SystemInfo; 255 QUOTA_LIMITS QuotaLimits; 256 NTSTATUS Status; 257 258 GetSystemInfo(&SystemInfo); 259 260 /* Query the working set */ 261 Status = NtQueryInformationProcess(hProcess, 262 ProcessQuotaLimits, 263 &QuotaLimits, 264 sizeof(QuotaLimits), 265 NULL); 266 267 if (!NT_SUCCESS(Status)) 268 { 269 SetLastError(RtlNtStatusToDosError(Status)); 270 return FALSE; 271 } 272 273 /* Empty the working set */ 274 QuotaLimits.MinimumWorkingSetSize = -1; 275 QuotaLimits.MaximumWorkingSetSize = -1; 276 277 /* Set the working set */ 278 Status = NtSetInformationProcess(hProcess, 279 ProcessQuotaLimits, 280 &QuotaLimits, 281 sizeof(QuotaLimits)); 282 if (!NT_SUCCESS(Status) && Status != STATUS_PRIVILEGE_NOT_HELD) 283 { 284 SetLastError(RtlNtStatusToDosError(Status)); 285 return FALSE; 286 } 287 288 return TRUE; 289} 290 291 292/* 293 * @implemented 294 */ 295BOOL 296WINAPI 297EnumDeviceDrivers(LPVOID *lpImageBase, 298 DWORD cb, 299 LPDWORD lpcbNeeded) 300{ 301 NTSTATUS Status; 302 DWORD NewSize, Count; 303 PRTL_PROCESS_MODULES Information; 304 /* By default, to prevent too many reallocations, we already make room for 4 modules */ 305 DWORD Size = sizeof(RTL_PROCESS_MODULES) + 3 * sizeof(RTL_PROCESS_MODULE_INFORMATION); 306 307 do 308 { 309 /* Allocate a buffer to hold modules information */ 310 Information = LocalAlloc(LMEM_FIXED, Size); 311 if (!Information) 312 { 313 SetLastError(ERROR_NO_SYSTEM_RESOURCES); 314 return FALSE; 315 } 316 317 /* Query information */ 318 Status = NtQuerySystemInformation(SystemModuleInformation, Information, Size, &Count); 319 /* In case of an error */ 320 if (!NT_SUCCESS(Status)) 321 { 322 /* Save the amount of output modules */ 323 NewSize = Information->NumberOfModules; 324 /* And free buffer */ 325 LocalFree(Information); 326 327 /* If it was not a length mismatch (ie, buffer too small), just leave */ 328 if (Status != STATUS_INFO_LENGTH_MISMATCH) 329 { 330 SetLastError(RtlNtStatusToDosError(Status)); 331 return FALSE; 332 } 333 334 /* Compute new size length */ 335 ASSERT(Size >= sizeof(RTL_PROCESS_MODULES)); 336 NewSize *= sizeof(RTL_PROCESS_MODULE_INFORMATION); 337 NewSize += sizeof(ULONG); 338 ASSERT(NewSize >= sizeof(RTL_PROCESS_MODULES)); 339 /* Check whether it is really bigger - otherwise, leave */ 340 if (NewSize < Size) 341 { 342 ASSERT(NewSize > Size); 343 SetLastError(RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)); 344 return FALSE; 345 } 346 347 /* Loop again with that new buffer */ 348 Size = NewSize; 349 continue; 350 } 351 352 /* End of allocation loop */ 353 break; 354 } while (TRUE); 355 356 _SEH2_TRY 357 { 358 for (Count = 0; Count < Information->NumberOfModules && Count < cb / sizeof(LPVOID); ++Count) 359 { 360 lpImageBase[Count] = Information->Modules[Count].ImageBase; 361 } 362 363 *lpcbNeeded = Information->NumberOfModules * sizeof(LPVOID); 364 } 365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 366 { 367 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 368 _SEH2_YIELD(return FALSE); 369 } 370 _SEH2_END; 371 372 return TRUE; 373} 374 375 376/* 377 * @implemented 378 */ 379BOOL 380WINAPI 381EnumProcesses(DWORD *lpidProcess, 382 DWORD cb, 383 LPDWORD lpcbNeeded) 384{ 385 NTSTATUS Status; 386 DWORD Size = MAXSHORT, Count; 387 PSYSTEM_PROCESS_INFORMATION ProcInfo; 388 PSYSTEM_PROCESS_INFORMATION ProcInfoArray; 389 390 /* First of all, query all the processes */ 391 do 392 { 393 ProcInfoArray = LocalAlloc(LMEM_FIXED, Size); 394 if (ProcInfoArray == NULL) 395 { 396 return FALSE; 397 } 398 399 Status = NtQuerySystemInformation(SystemProcessInformation, ProcInfoArray, Size, NULL); 400 if (Status == STATUS_INFO_LENGTH_MISMATCH) 401 { 402 LocalFree(ProcInfoArray); 403 Size += MAXSHORT; 404 continue; 405 } 406 407 break; 408 } 409 while (TRUE); 410 411 if (!NT_SUCCESS(Status)) 412 { 413 LocalFree(ProcInfoArray); 414 SetLastError(RtlNtStatusToDosError(Status)); 415 return FALSE; 416 } 417 418 /* Then, loop to output data */ 419 Count = 0; 420 ProcInfo = ProcInfoArray; 421 422 _SEH2_TRY 423 { 424 do 425 { 426 /* It may sound weird, but actually MS only updated Count on 427 * successful write. So, it cannot measure the amount of space needed! 428 * This is really tricky. 429 */ 430 if (Count < cb / sizeof(DWORD)) 431 { 432 lpidProcess[Count] = HandleToUlong(ProcInfo->UniqueProcessId); 433 Count++; 434 } 435 436 if (ProcInfo->NextEntryOffset == 0) 437 { 438 break; 439 } 440 441 ProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcInfo + ProcInfo->NextEntryOffset); 442 } 443 while (TRUE); 444 445 *lpcbNeeded = Count * sizeof(DWORD); 446 } 447 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 448 { 449 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 450 LocalFree(ProcInfoArray); 451 _SEH2_YIELD(return FALSE); 452 } 453 _SEH2_END; 454 455 LocalFree(ProcInfoArray); 456 return TRUE; 457} 458 459 460/* 461 * @implemented 462 */ 463BOOL 464WINAPI 465EnumProcessModules(HANDLE hProcess, 466 HMODULE *lphModule, 467 DWORD cb, 468 LPDWORD lpcbNeeded) 469{ 470 NTSTATUS Status; 471 DWORD NbOfModules, Count; 472 PPEB_LDR_DATA LoaderData; 473 PLIST_ENTRY ListHead, ListEntry; 474 PROCESS_BASIC_INFORMATION ProcInfo; 475 LDR_DATA_TABLE_ENTRY CurrentModule; 476 477 /* Query the process information to get its PEB address */ 478 Status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof(ProcInfo), NULL); 479 if (!NT_SUCCESS(Status)) 480 { 481 SetLastError(RtlNtStatusToDosError(Status)); 482 return FALSE; 483 } 484 485 if (ProcInfo.PebBaseAddress == NULL) 486 { 487 SetLastError(RtlNtStatusToDosError(STATUS_PARTIAL_COPY)); 488 return FALSE; 489 } 490 491 /* Read loader data address from PEB */ 492 if (!ReadProcessMemory(hProcess, &ProcInfo.PebBaseAddress->Ldr, &LoaderData, sizeof(LoaderData), NULL)) 493 { 494 return FALSE; 495 } 496 497 /* Store list head address */ 498 ListHead = &LoaderData->InLoadOrderModuleList; 499 500 /* Read first element in the modules list */ 501 if (!ReadProcessMemory(hProcess, &LoaderData->InLoadOrderModuleList.Flink, &ListEntry, sizeof(ListEntry), NULL)) 502 { 503 return FALSE; 504 } 505 506 NbOfModules = cb / sizeof(HMODULE); 507 Count = 0; 508 509 /* Loop on the modules */ 510 while (ListEntry != ListHead) 511 { 512 /* Load module data */ 513 if (!ReadProcessMemory(hProcess, 514 CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), 515 &CurrentModule, 516 sizeof(CurrentModule), 517 NULL)) 518 { 519 return FALSE; 520 } 521 522 /* Check if we can output module, do it if so */ 523 if (Count < NbOfModules) 524 { 525 _SEH2_TRY 526 { 527 lphModule[Count] = CurrentModule.DllBase; 528 } 529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 530 { 531 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 532 _SEH2_YIELD(return FALSE); 533 } 534 _SEH2_END; 535 } 536 537 ++Count; 538 if (Count > MAX_MODULES) 539 { 540 SetLastError(ERROR_INVALID_HANDLE); 541 return FALSE; 542 } 543 544 /* Get to next listed module */ 545 ListEntry = CurrentModule.InLoadOrderLinks.Flink; 546 } 547 548 _SEH2_TRY 549 { 550 *lpcbNeeded = Count * sizeof(HMODULE); 551 } 552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 553 { 554 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 555 _SEH2_YIELD(return FALSE); 556 } 557 _SEH2_END; 558 559 return TRUE; 560} 561 562 563/* 564 * @implemented 565 */ 566DWORD 567WINAPI 568GetDeviceDriverBaseNameA(LPVOID ImageBase, 569 LPSTR lpBaseName, 570 DWORD nSize) 571{ 572 SIZE_T Len, LenWithNull; 573 RTL_PROCESS_MODULE_INFORMATION Module; 574 575 /* Get the associated device driver to the base address */ 576 if (!FindDeviceDriver(ImageBase, &Module)) 577 { 578 return 0; 579 } 580 581 /* And copy as much as possible to output buffer. 582 * Try to add 1 to the len, to copy the null char as well. 583 */ 584 Len = 585 LenWithNull = strlen(&Module.FullPathName[Module.OffsetToFileName]) + 1; 586 if (Len > nSize) 587 { 588 Len = nSize; 589 } 590 591 memcpy(lpBaseName, &Module.FullPathName[Module.OffsetToFileName], Len); 592 /* In case we copied null char, remove it from final len */ 593 if (Len == LenWithNull) 594 { 595 --Len; 596 } 597 598 return Len; 599} 600 601 602/* 603 * @implemented 604 */ 605DWORD 606WINAPI 607GetDeviceDriverFileNameA(LPVOID ImageBase, 608 LPSTR lpFilename, 609 DWORD nSize) 610{ 611 SIZE_T Len, LenWithNull; 612 RTL_PROCESS_MODULE_INFORMATION Module; 613 614 /* Get the associated device driver to the base address */ 615 if (!FindDeviceDriver(ImageBase, &Module)) 616 { 617 return 0; 618 } 619 620 /* And copy as much as possible to output buffer. 621 * Try to add 1 to the len, to copy the null char as well. 622 */ 623 Len = 624 LenWithNull = strlen(Module.FullPathName) + 1; 625 if (Len > nSize) 626 { 627 Len = nSize; 628 } 629 630 memcpy(lpFilename, Module.FullPathName, Len); 631 /* In case we copied null char, remove it from final len */ 632 if (Len == LenWithNull) 633 { 634 --Len; 635 } 636 637 return Len; 638} 639 640 641/* 642 * @implemented 643 */ 644DWORD 645WINAPI 646GetDeviceDriverBaseNameW(LPVOID ImageBase, 647 LPWSTR lpBaseName, 648 DWORD nSize) 649{ 650 DWORD Len; 651 LPSTR BaseName; 652 653 /* Allocate internal buffer for conversion */ 654 BaseName = LocalAlloc(LMEM_FIXED, nSize); 655 if (BaseName == 0) 656 { 657 return 0; 658 } 659 660 /* Call A API */ 661 Len = GetDeviceDriverBaseNameA(ImageBase, BaseName, nSize); 662 if (Len == 0) 663 { 664 LocalFree(BaseName); 665 return 0; 666 } 667 668 /* And convert output */ 669 if (MultiByteToWideChar(CP_ACP, 0, BaseName, (Len < nSize) ? Len + 1 : Len, lpBaseName, nSize) == 0) 670 { 671 LocalFree(BaseName); 672 return 0; 673 } 674 675 LocalFree(BaseName); 676 return Len; 677} 678 679 680/* 681 * @implemented 682 */ 683DWORD 684WINAPI 685GetDeviceDriverFileNameW(LPVOID ImageBase, 686 LPWSTR lpFilename, 687 DWORD nSize) 688{ 689 DWORD Len; 690 LPSTR FileName; 691 692 /* Allocate internal buffer for conversion */ 693 FileName = LocalAlloc(LMEM_FIXED, nSize); 694 if (FileName == 0) 695 { 696 return 0; 697 } 698 699 /* Call A API */ 700 Len = GetDeviceDriverFileNameA(ImageBase, FileName, nSize); 701 if (Len == 0) 702 { 703 LocalFree(FileName); 704 return 0; 705 } 706 707 /* And convert output */ 708 if (MultiByteToWideChar(CP_ACP, 0, FileName, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize) == 0) 709 { 710 LocalFree(FileName); 711 return 0; 712 } 713 714 LocalFree(FileName); 715 return Len; 716} 717 718 719/* 720 * @implemented 721 */ 722DWORD 723WINAPI 724GetMappedFileNameA(HANDLE hProcess, 725 LPVOID lpv, 726 LPSTR lpFilename, 727 DWORD nSize) 728{ 729 DWORD Len; 730 LPWSTR FileName; 731 732 DPRINT("GetMappedFileNameA(%p, %p, %p, %lu)\n", hProcess, lpv, lpFilename, nSize); 733 734 /* Allocate internal buffer for conversion */ 735 FileName = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); 736 if (FileName == NULL) 737 { 738 return 0; 739 } 740 741 /* Call W API */ 742 Len = GetMappedFileNameW(hProcess, lpv, FileName, nSize); 743 744 /* And convert output */ 745 if (WideCharToMultiByte(CP_ACP, 0, FileName, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize, NULL, NULL) == 0) 746 { 747 Len = 0; 748 } 749 750 LocalFree(FileName); 751 return Len; 752} 753 754 755/* 756 * @implemented 757 */ 758DWORD 759WINAPI 760GetMappedFileNameW(HANDLE hProcess, 761 LPVOID lpv, 762 LPWSTR lpFilename, 763 DWORD nSize) 764{ 765 DWORD Len; 766 SIZE_T OutSize; 767 NTSTATUS Status; 768 struct 769 { 770 MEMORY_SECTION_NAME; 771 WCHAR CharBuffer[MAX_PATH]; 772 } SectionName; 773 774 DPRINT("GetMappedFileNameW(%p, %p, %p, %lu)\n", hProcess, lpv, lpFilename, nSize); 775 776 /* If no buffer, no need to keep going on */ 777 if (nSize == 0) 778 { 779 SetLastError(ERROR_INSUFFICIENT_BUFFER); 780 return 0; 781 } 782 783 /* Query section name */ 784 Status = NtQueryVirtualMemory(hProcess, lpv, MemorySectionName, 785 &SectionName, sizeof(SectionName), &OutSize); 786 if (!NT_SUCCESS(Status)) 787 { 788 SetLastError(RtlNtStatusToDosError(Status)); 789 return 0; 790 } 791 792 /* Prepare to copy file name */ 793 Len = 794 OutSize = SectionName.SectionFileName.Length / sizeof(WCHAR); 795 if (OutSize + 1 > nSize) 796 { 797 Len = nSize - 1; 798 OutSize = nSize; 799 SetLastError(ERROR_INSUFFICIENT_BUFFER); 800 } 801 else 802 { 803 SetLastError(ERROR_SUCCESS); 804 } 805 806 /* Copy, zero and return */ 807 memcpy(lpFilename, SectionName.SectionFileName.Buffer, Len * sizeof(WCHAR)); 808 lpFilename[Len] = 0; 809 810 return OutSize; 811} 812 813 814/* 815 * @implemented 816 */ 817DWORD 818WINAPI 819GetModuleBaseNameA(HANDLE hProcess, 820 HMODULE hModule, 821 LPSTR lpBaseName, 822 DWORD nSize) 823{ 824 DWORD Len; 825 PWSTR BaseName; 826 827 /* Allocate internal buffer for conversion */ 828 BaseName = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); 829 if (BaseName == NULL) 830 { 831 return 0; 832 } 833 834 /* Call W API */ 835 Len = GetModuleBaseNameW(hProcess, hModule, BaseName, nSize); 836 /* And convert output */ 837 if (WideCharToMultiByte(CP_ACP, 0, BaseName, (Len < nSize) ? Len + 1 : Len, lpBaseName, nSize, NULL, NULL) == 0) 838 { 839 Len = 0; 840 } 841 842 LocalFree(BaseName); 843 844 return Len; 845} 846 847 848/* 849 * @implemented 850 */ 851DWORD 852WINAPI 853GetModuleBaseNameW(HANDLE hProcess, 854 HMODULE hModule, 855 LPWSTR lpBaseName, 856 DWORD nSize) 857{ 858 DWORD Len; 859 LDR_DATA_TABLE_ENTRY Module; 860 861 /* Get the matching module */ 862 if (!FindModule(hProcess, hModule, &Module)) 863 { 864 return 0; 865 } 866 867 /* Get the maximum len we have/can write in given size */ 868 Len = Module.BaseDllName.Length + sizeof(UNICODE_NULL); 869 if (nSize * sizeof(WCHAR) < Len) 870 { 871 Len = nSize * sizeof(WCHAR); 872 } 873 874 /* Read string */ 875 if (!ReadProcessMemory(hProcess, (&Module.BaseDllName)->Buffer, lpBaseName, Len, NULL)) 876 { 877 return 0; 878 } 879 880 /* If we are at the end of the string, prepare to override to nullify string */ 881 if (Len == Module.BaseDllName.Length + sizeof(UNICODE_NULL)) 882 { 883 Len -= sizeof(UNICODE_NULL); 884 } 885 886 /* Nullify at the end if needed */ 887 if (Len >= nSize * sizeof(WCHAR)) 888 { 889 if (nSize) 890 { 891 ASSERT(nSize >= sizeof(UNICODE_NULL)); 892 lpBaseName[nSize - 1] = UNICODE_NULL; 893 } 894 } 895 /* Otherwise, nullify at last written char */ 896 else 897 { 898 ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); 899 lpBaseName[Len / sizeof(WCHAR)] = UNICODE_NULL; 900 } 901 902 return Len / sizeof(WCHAR); 903} 904 905 906/* 907 * @implemented 908 */ 909DWORD 910WINAPI 911GetModuleFileNameExA(HANDLE hProcess, 912 HMODULE hModule, 913 LPSTR lpFilename, 914 DWORD nSize) 915{ 916 DWORD Len; 917 PWSTR Filename; 918 919 /* Allocate internal buffer for conversion */ 920 Filename = LocalAlloc(LMEM_FIXED, nSize * sizeof(WCHAR)); 921 if (Filename == NULL) 922 { 923 return 0; 924 } 925 926 /* Call W API */ 927 Len = GetModuleFileNameExW(hProcess, hModule, Filename, nSize); 928 /* And convert output */ 929 if (WideCharToMultiByte(CP_ACP, 0, Filename, (Len < nSize) ? Len + 1 : Len, lpFilename, nSize, NULL, NULL) == 0) 930 { 931 Len = 0; 932 } 933 934 LocalFree(Filename); 935 936 return Len; 937} 938 939 940/* 941 * @implemented 942 */ 943DWORD 944WINAPI 945GetModuleFileNameExW(HANDLE hProcess, 946 HMODULE hModule, 947 LPWSTR lpFilename, 948 DWORD nSize) 949{ 950 DWORD Len; 951 LDR_DATA_TABLE_ENTRY Module; 952 953 /* Get the matching module */ 954 if (!FindModule(hProcess, hModule, &Module)) 955 { 956 return 0; 957 } 958 959 /* Get the maximum len we have/can write in given size */ 960 Len = Module.FullDllName.Length + sizeof(UNICODE_NULL); 961 if (nSize * sizeof(WCHAR) < Len) 962 { 963 Len = nSize * sizeof(WCHAR); 964 } 965 966 /* Read string */ 967 if (!ReadProcessMemory(hProcess, (&Module.FullDllName)->Buffer, lpFilename, Len, NULL)) 968 { 969 return 0; 970 } 971 972 /* If we are at the end of the string, prepare to override to nullify string */ 973 if (Len == Module.FullDllName.Length + sizeof(UNICODE_NULL)) 974 { 975 Len -= sizeof(UNICODE_NULL); 976 } 977 978 /* Nullify at the end if needed */ 979 if (Len >= nSize * sizeof(WCHAR)) 980 { 981 if (nSize) 982 { 983 ASSERT(nSize >= sizeof(UNICODE_NULL)); 984 lpFilename[nSize - 1] = UNICODE_NULL; 985 } 986 } 987 /* Otherwise, nullify at last written char */ 988 else 989 { 990 ASSERT(Len + sizeof(UNICODE_NULL) <= nSize * sizeof(WCHAR)); 991 lpFilename[Len / sizeof(WCHAR)] = UNICODE_NULL; 992 } 993 994 return Len / sizeof(WCHAR); 995} 996 997 998/* 999 * @implemented 1000 */ 1001BOOL 1002WINAPI 1003GetModuleInformation(HANDLE hProcess, 1004 HMODULE hModule, 1005 LPMODULEINFO lpmodinfo, 1006 DWORD cb) 1007{ 1008 MODULEINFO LocalInfo; 1009 LDR_DATA_TABLE_ENTRY Module; 1010 1011 /* Check output size */ 1012 if (cb < sizeof(MODULEINFO)) 1013 { 1014 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1015 return FALSE; 1016 } 1017 1018 /* Get the matching module */ 1019 if (!FindModule(hProcess, hModule, &Module)) 1020 { 1021 return FALSE; 1022 } 1023 1024 /* Get a local copy first, to check for valid pointer once */ 1025 LocalInfo.lpBaseOfDll = hModule; 1026 LocalInfo.SizeOfImage = Module.SizeOfImage; 1027 LocalInfo.EntryPoint = Module.EntryPoint; 1028 1029 /* Attempt to copy to output */ 1030 _SEH2_TRY 1031 { 1032 memcpy(lpmodinfo, &LocalInfo, sizeof(LocalInfo)); 1033 } 1034 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1035 { 1036 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 1037 _SEH2_YIELD(return FALSE); 1038 } 1039 _SEH2_END; 1040 1041 return TRUE; 1042} 1043 1044 1045/* 1046 * @implemented 1047 */ 1048BOOL 1049WINAPI 1050InitializeProcessForWsWatch(HANDLE hProcess) 1051{ 1052 NTSTATUS Status; 1053 1054 /* Simply forward the call */ 1055 Status = NtSetInformationProcess(hProcess, 1056 ProcessWorkingSetWatch, 1057 NULL, 1058 0); 1059 /* In case the function returns this, MS considers the call as a success */ 1060 if (NT_SUCCESS(Status) || Status == STATUS_PORT_ALREADY_SET || Status == STATUS_ACCESS_DENIED) 1061 { 1062 return TRUE; 1063 } 1064 1065 SetLastError(RtlNtStatusToDosError(Status)); 1066 return FALSE; 1067} 1068 1069 1070/* 1071 * @implemented 1072 */ 1073BOOL 1074WINAPI 1075GetWsChanges(HANDLE hProcess, 1076 PPSAPI_WS_WATCH_INFORMATION lpWatchInfo, 1077 DWORD cb) 1078{ 1079 NTSTATUS Status; 1080 1081 /* Simply forward the call */ 1082 Status = NtQueryInformationProcess(hProcess, 1083 ProcessWorkingSetWatch, 1084 lpWatchInfo, 1085 cb, 1086 NULL); 1087 if(!NT_SUCCESS(Status)) 1088 { 1089 SetLastError(RtlNtStatusToDosError(Status)); 1090 return FALSE; 1091 } 1092 1093 return TRUE; 1094} 1095 1096 1097/* 1098 * @implemented 1099 */ 1100DWORD 1101WINAPI 1102GetProcessImageFileNameW(HANDLE hProcess, 1103 LPWSTR lpImageFileName, 1104 DWORD nSize) 1105{ 1106 PUNICODE_STRING ImageFileName; 1107 SIZE_T BufferSize; 1108 NTSTATUS Status; 1109 DWORD Len; 1110 1111 /* Allocate string big enough to hold name */ 1112 BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); 1113 ImageFileName = LocalAlloc(LMEM_FIXED, BufferSize); 1114 if (ImageFileName == NULL) 1115 { 1116 return 0; 1117 } 1118 1119 /* Query name */ 1120 Status = NtQueryInformationProcess(hProcess, 1121 ProcessImageFileName, 1122 ImageFileName, 1123 BufferSize, 1124 NULL); 1125 /* Len mismatch => buffer too small */ 1126 if (Status == STATUS_INFO_LENGTH_MISMATCH) 1127 { 1128 Status = STATUS_BUFFER_TOO_SMALL; 1129 } 1130 if (!NT_SUCCESS(Status)) 1131 { 1132 SetLastError(RtlNtStatusToDosError(Status)); 1133 LocalFree(ImageFileName); 1134 return 0; 1135 } 1136 1137 /* Copy name and null-terminate if possible */ 1138 memcpy(lpImageFileName, ImageFileName->Buffer, ImageFileName->Length); 1139 Len = ImageFileName->Length / sizeof(WCHAR); 1140 if (Len < nSize) 1141 { 1142 lpImageFileName[Len] = UNICODE_NULL; 1143 } 1144 1145 LocalFree(ImageFileName); 1146 return Len; 1147} 1148 1149 1150/* 1151 * @implemented 1152 */ 1153DWORD 1154WINAPI 1155GetProcessImageFileNameA(HANDLE hProcess, 1156 LPSTR lpImageFileName, 1157 DWORD nSize) 1158{ 1159 PUNICODE_STRING ImageFileName; 1160 SIZE_T BufferSize; 1161 NTSTATUS Status; 1162 DWORD Len; 1163 1164 /* Allocate string big enough to hold name */ 1165 BufferSize = sizeof(UNICODE_STRING) + (nSize * sizeof(WCHAR)); 1166 ImageFileName = LocalAlloc(LMEM_FIXED, BufferSize); 1167 if (ImageFileName == NULL) 1168 { 1169 return 0; 1170 } 1171 1172 /* Query name */ 1173 Status = NtQueryInformationProcess(hProcess, 1174 ProcessImageFileName, 1175 ImageFileName, 1176 BufferSize, 1177 NULL); 1178 /* Len mismatch => buffer too small */ 1179 if (Status == STATUS_INFO_LENGTH_MISMATCH) 1180 { 1181 Status = STATUS_BUFFER_TOO_SMALL; 1182 } 1183 if (!NT_SUCCESS(Status)) 1184 { 1185 SetLastError(RtlNtStatusToDosError(Status)); 1186 LocalFree(ImageFileName); 1187 return 0; 1188 } 1189 1190 /* Copy name */ 1191 Len = WideCharToMultiByte(CP_ACP, 0, ImageFileName->Buffer, 1192 ImageFileName->Length, lpImageFileName, nSize, NULL, NULL); 1193 /* If conversion was successful, don't return len with added \0 */ 1194 if (Len != 0) 1195 { 1196 Len -= sizeof(ANSI_NULL); 1197 } 1198 1199 LocalFree(ImageFileName); 1200 return Len; 1201} 1202 1203 1204/* 1205 * @implemented 1206 */ 1207BOOL 1208WINAPI 1209EnumPageFilesA(PENUM_PAGE_FILE_CALLBACKA pCallbackRoutine, 1210 LPVOID lpContext) 1211{ 1212 BOOL Ret; 1213 INTERNAL_ENUM_PAGE_FILES_CONTEXT Context; 1214 1215 Context.dwErrCode = ERROR_SUCCESS; 1216 Context.lpContext = lpContext; 1217 Context.pCallbackRoutine = pCallbackRoutine; 1218 1219 /* Call W with our own callback for W -> A conversions */ 1220 Ret = EnumPageFilesW(CallBackConvertToAscii, &Context); 1221 /* If we succeed but we have error code, fail and set error */ 1222 if (Ret && Context.dwErrCode != ERROR_SUCCESS) 1223 { 1224 Ret = FALSE; 1225 SetLastError(Context.dwErrCode); 1226 } 1227 1228 return Ret; 1229} 1230 1231 1232/* 1233 * @implemented 1234 */ 1235BOOL 1236WINAPI 1237EnumPageFilesW(PENUM_PAGE_FILE_CALLBACKW pCallbackRoutine, 1238 LPVOID lpContext) 1239{ 1240 PWSTR Colon; 1241 NTSTATUS Status; 1242 DWORD Size = INIT_MEMORY_SIZE, Needed; 1243 ENUM_PAGE_FILE_INFORMATION Information; 1244 PSYSTEM_PAGEFILE_INFORMATION PageFileInfoArray, PageFileInfo; 1245 1246 /* First loop till we have all the information about page files */ 1247 do 1248 { 1249 PageFileInfoArray = LocalAlloc(LMEM_FIXED, Size); 1250 if (PageFileInfoArray == NULL) 1251 { 1252 SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES)); 1253 return FALSE; 1254 } 1255 1256 Status = NtQuerySystemInformation(SystemPageFileInformation, PageFileInfoArray, Size, &Needed); 1257 if (NT_SUCCESS(Status)) 1258 { 1259 break; 1260 } 1261 1262 LocalFree(PageFileInfoArray); 1263 1264 /* In case we have unexpected status, quit */ 1265 if (Status != STATUS_INFO_LENGTH_MISMATCH) 1266 { 1267 SetLastError(RtlNtStatusToDosError(Status)); 1268 return FALSE; 1269 } 1270 1271 /* If needed size is smaller than actual size, guess it's something to add to our current size */ 1272 if (Needed <= Size) 1273 { 1274 Size += Needed; 1275 } 1276 /* Otherwise, take it as size to allocate */ 1277 else 1278 { 1279 Size = Needed; 1280 } 1281 } 1282 while (TRUE); 1283 1284 /* Start browsing all our entries */ 1285 PageFileInfo = PageFileInfoArray; 1286 do 1287 { 1288 /* Ensure we really have an entry */ 1289 if (Needed < sizeof(SYSTEM_PAGEFILE_INFORMATION)) 1290 { 1291 break; 1292 } 1293 1294 /* Prepare structure to hand to the user */ 1295 Information.Reserved = 0; 1296 Information.cb = sizeof(Information); 1297 Information.TotalSize = PageFileInfo->TotalSize; 1298 Information.TotalInUse = PageFileInfo->TotalInUse; 1299 Information.PeakUsage = PageFileInfo->PeakUsage; 1300 1301 /* Search for colon */ 1302 Colon = wcschr(PageFileInfo->PageFileName.Buffer, L':'); 1303 /* If it's found and not at the begin of the string */ 1304 if (Colon != 0 && Colon != PageFileInfo->PageFileName.Buffer) 1305 { 1306 /* We can call the user callback routine with the colon */ 1307 --Colon; 1308 pCallbackRoutine(lpContext, &Information, Colon); 1309 } 1310 1311 /* If no next entry, then, it's over */ 1312 if (PageFileInfo->NextEntryOffset == 0 || PageFileInfo->NextEntryOffset > Needed) 1313 { 1314 break; 1315 } 1316 1317 /* Jump to next entry while keeping accurate bytes left count */ 1318 Needed -= PageFileInfo->NextEntryOffset; 1319 PageFileInfo = (PSYSTEM_PAGEFILE_INFORMATION)((ULONG_PTR)PageFileInfo + PageFileInfo->NextEntryOffset); 1320 } 1321 while (TRUE); 1322 1323 LocalFree(PageFileInfoArray); 1324 return TRUE; 1325} 1326 1327 1328/* 1329 * @implemented 1330 */ 1331BOOL 1332WINAPI 1333GetPerformanceInfo(PPERFORMANCE_INFORMATION pPerformanceInformation, 1334 DWORD cb) 1335{ 1336 NTSTATUS Status; 1337 SYSTEM_BASIC_INFORMATION SystemBasicInfo; 1338 SYSTEM_PERFORMANCE_INFORMATION SystemPerfInfo; 1339 SYSTEM_FILECACHE_INFORMATION SystemFileCacheInfo; 1340 PSYSTEM_PROCESS_INFORMATION ProcInfoArray, SystemProcInfo; 1341 DWORD Size = INIT_MEMORY_SIZE, Needed, ProcCount, ThreadsCount, HandleCount; 1342 1343 /* Validate output buffer */ 1344 if (cb < sizeof(PERFORMANCE_INFORMATION)) 1345 { 1346 SetLastError(RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)); 1347 return FALSE; 1348 } 1349 1350 /* First, gather as many information about the system as possible */ 1351 Status = NtQuerySystemInformation(SystemBasicInformation, 1352 &SystemBasicInfo, 1353 sizeof(SystemBasicInfo), 1354 NULL); 1355 if (!NT_SUCCESS(Status)) 1356 { 1357 SetLastError(RtlNtStatusToDosError(Status)); 1358 return FALSE; 1359 } 1360 1361 Status = NtQuerySystemInformation(SystemPerformanceInformation, 1362 &SystemPerfInfo, 1363 sizeof(SystemPerfInfo), 1364 NULL); 1365 if (!NT_SUCCESS(Status)) 1366 { 1367 SetLastError(RtlNtStatusToDosError(Status)); 1368 return FALSE; 1369 } 1370 1371 Status = NtQuerySystemInformation(SystemFileCacheInformation, 1372 &SystemFileCacheInfo, 1373 sizeof(SystemFileCacheInfo), 1374 NULL); 1375 if (!NT_SUCCESS(Status)) 1376 { 1377 SetLastError(RtlNtStatusToDosError(Status)); 1378 return FALSE; 1379 } 1380 1381 /* Then loop till we have all the information about processes */ 1382 do 1383 { 1384 ProcInfoArray = LocalAlloc(LMEM_FIXED, Size); 1385 if (ProcInfoArray == NULL) 1386 { 1387 SetLastError(RtlNtStatusToDosError(STATUS_INSUFFICIENT_RESOURCES)); 1388 return FALSE; 1389 } 1390 1391 Status = NtQuerySystemInformation(SystemProcessInformation, 1392 ProcInfoArray, 1393 Size, 1394 &Needed); 1395 if (NT_SUCCESS(Status)) 1396 { 1397 break; 1398 } 1399 1400 LocalFree(ProcInfoArray); 1401 1402 /* In case we have unexpected status, quit */ 1403 if (Status != STATUS_INFO_LENGTH_MISMATCH) 1404 { 1405 SetLastError(RtlNtStatusToDosError(Status)); 1406 return FALSE; 1407 } 1408 1409 /* If needed size is smaller than actual size, guess it's something to add to our current size */ 1410 if (Needed <= Size) 1411 { 1412 Size += Needed; 1413 } 1414 /* Otherwise, take it as size to allocate */ 1415 else 1416 { 1417 Size = Needed; 1418 } 1419 } while (TRUE); 1420 1421 /* Start browsing all our entries */ 1422 ProcCount = 0; 1423 HandleCount = 0; 1424 ThreadsCount = 0; 1425 SystemProcInfo = ProcInfoArray; 1426 do 1427 { 1428 /* Ensure we really have an entry */ 1429 if (Needed < sizeof(SYSTEM_PROCESS_INFORMATION)) 1430 { 1431 break; 1432 } 1433 1434 /* Sum procs, threads and handles */ 1435 ++ProcCount; 1436 ThreadsCount += SystemProcInfo->NumberOfThreads; 1437 HandleCount += SystemProcInfo->HandleCount; 1438 1439 /* If no next entry, then, it's over */ 1440 if (SystemProcInfo->NextEntryOffset == 0 || SystemProcInfo->NextEntryOffset > Needed) 1441 { 1442 break; 1443 } 1444 1445 /* Jump to next entry while keeping accurate bytes left count */ 1446 Needed -= SystemProcInfo->NextEntryOffset; 1447 SystemProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)SystemProcInfo + SystemProcInfo->NextEntryOffset); 1448 } 1449 while (TRUE); 1450 1451 LocalFree(ProcInfoArray); 1452 1453 /* Output data */ 1454 pPerformanceInformation->CommitTotal = SystemPerfInfo.CommittedPages; 1455 pPerformanceInformation->CommitLimit = SystemPerfInfo.CommitLimit; 1456 pPerformanceInformation->CommitPeak = SystemPerfInfo.PeakCommitment; 1457 pPerformanceInformation->PhysicalTotal = SystemBasicInfo.NumberOfPhysicalPages; 1458 pPerformanceInformation->PhysicalAvailable = SystemPerfInfo.AvailablePages; 1459 pPerformanceInformation->SystemCache = SystemFileCacheInfo.CurrentSizeIncludingTransitionInPages; 1460 pPerformanceInformation->KernelNonpaged = SystemPerfInfo.NonPagedPoolPages; 1461 pPerformanceInformation->PageSize = SystemBasicInfo.PageSize; 1462 pPerformanceInformation->cb = sizeof(PERFORMANCE_INFORMATION); 1463 pPerformanceInformation->KernelTotal = SystemPerfInfo.PagedPoolPages + SystemPerfInfo.NonPagedPoolPages; 1464 pPerformanceInformation->KernelPaged = SystemPerfInfo.PagedPoolPages; 1465 pPerformanceInformation->HandleCount = HandleCount; 1466 pPerformanceInformation->ProcessCount = ProcCount; 1467 pPerformanceInformation->ThreadCount = ThreadsCount; 1468 1469 return TRUE; 1470} 1471 1472 1473/* 1474 * @implemented 1475 */ 1476BOOL 1477WINAPI 1478GetProcessMemoryInfo(HANDLE Process, 1479 PPROCESS_MEMORY_COUNTERS ppsmemCounters, 1480 DWORD cb) 1481{ 1482 NTSTATUS Status; 1483 VM_COUNTERS_EX Counters; 1484 1485 /* Validate output size 1486 * It can be either PROCESS_MEMORY_COUNTERS or PROCESS_MEMORY_COUNTERS_EX 1487 */ 1488 if (cb < sizeof(PROCESS_MEMORY_COUNTERS)) 1489 { 1490 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1491 return FALSE; 1492 } 1493 1494 _SEH2_TRY 1495 { 1496 ppsmemCounters->PeakPagefileUsage = 0; 1497 1498 /* Query counters */ 1499 Status = NtQueryInformationProcess(Process, 1500 ProcessVmCounters, 1501 &Counters, 1502 sizeof(Counters), 1503 NULL); 1504 if (!NT_SUCCESS(Status)) 1505 { 1506 SetLastError(RtlNtStatusToDosError(Status)); 1507 _SEH2_YIELD(return FALSE); 1508 } 1509 1510 /* Properly set cb, according to what we received */ 1511 if (cb >= sizeof(PROCESS_MEMORY_COUNTERS_EX)) 1512 { 1513 ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS_EX); 1514 } 1515 else 1516 { 1517 ppsmemCounters->cb = sizeof(PROCESS_MEMORY_COUNTERS); 1518 } 1519 1520 /* Output data */ 1521 ppsmemCounters->PageFaultCount = Counters.PageFaultCount; 1522 ppsmemCounters->PeakWorkingSetSize = Counters.PeakWorkingSetSize; 1523 ppsmemCounters->WorkingSetSize = Counters.WorkingSetSize; 1524 ppsmemCounters->QuotaPeakPagedPoolUsage = Counters.QuotaPeakPagedPoolUsage; 1525 ppsmemCounters->QuotaPagedPoolUsage = Counters.QuotaPagedPoolUsage; 1526 ppsmemCounters->QuotaPeakNonPagedPoolUsage = Counters.QuotaPeakNonPagedPoolUsage; 1527 ppsmemCounters->QuotaNonPagedPoolUsage = Counters.QuotaNonPagedPoolUsage; 1528 ppsmemCounters->PagefileUsage = Counters.PagefileUsage; 1529 ppsmemCounters->PeakPagefileUsage = Counters.PeakPagefileUsage; 1530 /* And if needed, additional field for _EX version */ 1531 if (cb >= sizeof(PROCESS_MEMORY_COUNTERS_EX)) 1532 { 1533 ((PPROCESS_MEMORY_COUNTERS_EX)ppsmemCounters)->PrivateUsage = Counters.PrivateUsage; 1534 } 1535 } 1536 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1537 { 1538 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode())); 1539 _SEH2_YIELD(return FALSE); 1540 } 1541 _SEH2_END; 1542 1543 return TRUE; 1544} 1545 1546 1547/* 1548 * @implemented 1549 */ 1550BOOL 1551WINAPI 1552QueryWorkingSet(HANDLE hProcess, 1553 PVOID pv, 1554 DWORD cb) 1555{ 1556 NTSTATUS Status; 1557 1558 /* Simply forward the call */ 1559 Status = NtQueryVirtualMemory(hProcess, 1560 NULL, 1561 MemoryWorkingSetList, 1562 pv, 1563 cb, 1564 NULL); 1565 if (!NT_SUCCESS(Status)) 1566 { 1567 SetLastError(RtlNtStatusToDosError(Status)); 1568 return FALSE; 1569 } 1570 1571 return TRUE; 1572} 1573 1574/* 1575 * @implemented 1576 */ 1577BOOL 1578WINAPI 1579QueryWorkingSetEx(IN HANDLE hProcess, 1580 IN OUT PVOID pv, 1581 IN DWORD cb) 1582{ 1583 NTSTATUS Status; 1584 1585 /* Simply forward the call */ 1586 Status = NtQueryVirtualMemory(hProcess, 1587 NULL, 1588 MemoryWorkingSetExList, 1589 pv, 1590 cb, 1591 NULL); 1592 if (!NT_SUCCESS(Status)) 1593 { 1594 SetLastError(RtlNtStatusToDosError(Status)); 1595 return FALSE; 1596 } 1597 1598 return TRUE; 1599} 1600 1601/* EOF */