1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS system libraries 4 * FILE: dll/win32/kernel32/client/toolhelp.c 5 * PURPOSE: Toolhelp functions 6 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com> 7 * Robert Dickenson (robd@mok.lvcm.com) 8 * 9 * NOTES: Do NOT use the heap functions in here because they 10 * adulterate the heap statistics! 11 * 12 * UPDATE HISTORY: 13 * 10/30/2004 Implemented some parts (w3) 14 * Inspired by the book "Windows NT Native API" 15 * Created 05 January 2003 (robd) 16 */ 17 18 #include <k32.h> 19 20 #define NDEBUG 21 #include <debug.h> 22 23 /* INTERNAL DEFINITIONS *******************************************************/ 24 25 typedef struct _RTLP_HEAP_ENTRY 26 { 27 ULONG Size; 28 USHORT Flags; 29 USHORT Unknown1; /* FIXME */ 30 ULONG Unknown2; /* FIXME */ 31 PVOID Address; 32 } RTLP_HEAP_ENTRY, *PRTLP_HEAP_ENTRY; 33 34 #define CHECK_PARAM_SIZE(ptr, siz) \ 35 if((ptr) == NULL || (ptr)->dwSize != (siz)) \ 36 { \ 37 SetLastError(ERROR_INVALID_PARAMETER); \ 38 return FALSE; \ 39 } 40 41 /* 42 * Tests in win showed that the dwSize field can be greater than the actual size 43 * of the structure for the ansi functions. I found this out by accidently 44 * forgetting to set the dwSize field in a test application and it just didn't 45 * work in ros but in win. 46 */ 47 48 #define CHECK_PARAM_SIZEA(ptr, siz) \ 49 if((ptr) == NULL || (ptr)->dwSize < (siz)) \ 50 { \ 51 SetLastError(ERROR_INVALID_PARAMETER); \ 52 return FALSE; \ 53 } 54 55 #define OffsetToPtr(Snapshot, Offset) \ 56 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset)) 57 58 typedef struct _TH32SNAPSHOT 59 { 60 /* Heap list */ 61 ULONG HeapListCount; 62 ULONG HeapListIndex; 63 ULONG_PTR HeapListOffset; 64 /* Module list */ 65 ULONG ModuleListCount; 66 ULONG ModuleListIndex; 67 ULONG_PTR ModuleListOffset; 68 /* Process list */ 69 ULONG ProcessListCount; 70 ULONG ProcessListIndex; 71 ULONG_PTR ProcessListOffset; 72 /* Thread list */ 73 ULONG ThreadListCount; 74 ULONG ThreadListIndex; 75 ULONG_PTR ThreadListOffset; 76 } TH32SNAPSHOT, *PTH32SNAPSHOT; 77 78 /* INTERNAL FUNCTIONS *********************************************************/ 79 80 static VOID 81 TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug, 82 PRTL_DEBUG_INFORMATION ModuleDebug, 83 PVOID ProcThrdInfo, 84 SIZE_T ProcThrdInfoSize) 85 { 86 if(HeapDebug != NULL) 87 { 88 RtlDestroyQueryDebugBuffer(HeapDebug); 89 } 90 if(ModuleDebug != NULL) 91 { 92 RtlDestroyQueryDebugBuffer(ModuleDebug); 93 } 94 95 if(ProcThrdInfo != NULL) 96 { 97 NtFreeVirtualMemory(NtCurrentProcess(), 98 &ProcThrdInfo, 99 &ProcThrdInfoSize, 100 MEM_RELEASE); 101 } 102 } 103 104 static NTSTATUS 105 TH32CreateSnapshot(DWORD dwFlags, 106 DWORD th32ProcessID, 107 PRTL_DEBUG_INFORMATION *HeapDebug, 108 PRTL_DEBUG_INFORMATION *ModuleDebug, 109 PVOID *ProcThrdInfo, 110 SIZE_T *ProcThrdInfoSize) 111 { 112 NTSTATUS Status = STATUS_SUCCESS; 113 114 *HeapDebug = NULL; 115 *ModuleDebug = NULL; 116 *ProcThrdInfo = NULL; 117 *ProcThrdInfoSize = 0; 118 119 /* 120 * Allocate the debug information for a heap snapshot 121 */ 122 if(dwFlags & TH32CS_SNAPHEAPLIST) 123 { 124 *HeapDebug = RtlCreateQueryDebugBuffer(0, FALSE); 125 if(*HeapDebug != NULL) 126 { 127 Status = RtlQueryProcessDebugInformation(th32ProcessID, 128 RTL_DEBUG_QUERY_HEAPS, 129 *HeapDebug); 130 } 131 else 132 Status = STATUS_UNSUCCESSFUL; 133 } 134 135 /* 136 * Allocate the debug information for a module snapshot 137 */ 138 if(dwFlags & TH32CS_SNAPMODULE && 139 NT_SUCCESS(Status)) 140 { 141 *ModuleDebug = RtlCreateQueryDebugBuffer(0, FALSE); 142 if(*ModuleDebug != NULL) 143 { 144 Status = RtlQueryProcessDebugInformation(th32ProcessID, 145 RTL_DEBUG_QUERY_MODULES, 146 *ModuleDebug); 147 } 148 else 149 Status = STATUS_UNSUCCESSFUL; 150 } 151 152 /* 153 * Allocate enough memory for the system's process list 154 */ 155 156 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD) && 157 NT_SUCCESS(Status)) 158 { 159 for(;;) 160 { 161 (*ProcThrdInfoSize) += 0x10000; 162 Status = NtAllocateVirtualMemory(NtCurrentProcess(), 163 ProcThrdInfo, 164 0, 165 ProcThrdInfoSize, 166 MEM_COMMIT, 167 PAGE_READWRITE); 168 if(!NT_SUCCESS(Status)) 169 { 170 break; 171 } 172 173 Status = NtQuerySystemInformation(SystemProcessInformation, 174 *ProcThrdInfo, 175 *ProcThrdInfoSize, 176 NULL); 177 if(Status == STATUS_INFO_LENGTH_MISMATCH) 178 { 179 NtFreeVirtualMemory(NtCurrentProcess(), 180 ProcThrdInfo, 181 ProcThrdInfoSize, 182 MEM_RELEASE); 183 *ProcThrdInfo = NULL; 184 } 185 else 186 { 187 break; 188 } 189 } 190 } 191 192 /* 193 * Free resources in case of failure! 194 */ 195 196 if(!NT_SUCCESS(Status)) 197 { 198 TH32FreeAllocatedResources(*HeapDebug, 199 *ModuleDebug, 200 *ProcThrdInfo, 201 *ProcThrdInfoSize); 202 } 203 204 return Status; 205 } 206 207 static NTSTATUS 208 TH32CreateSnapshotSectionInitialize(DWORD dwFlags, 209 DWORD th32ProcessID, 210 PRTL_DEBUG_INFORMATION HeapDebug, 211 PRTL_DEBUG_INFORMATION ModuleDebug, 212 PVOID ProcThrdInfo, 213 HANDLE *SectionHandle) 214 { 215 PSYSTEM_PROCESS_INFORMATION ProcessInfo; 216 LPHEAPLIST32 HeapListEntry; 217 LPMODULEENTRY32W ModuleListEntry; 218 LPPROCESSENTRY32W ProcessListEntry; 219 LPTHREADENTRY32 ThreadListEntry; 220 OBJECT_ATTRIBUTES ObjectAttributes; 221 LARGE_INTEGER SSize, SOffset; 222 HANDLE hSection; 223 PTH32SNAPSHOT Snapshot; 224 ULONG_PTR DataOffset; 225 SIZE_T ViewSize; 226 ULONG i, nProcesses = 0, nThreads = 0, nHeaps = 0, nModules = 0; 227 ULONG RequiredSnapshotSize = sizeof(TH32SNAPSHOT); 228 PRTL_PROCESS_HEAPS hi = NULL; 229 PRTL_PROCESS_MODULES mi = NULL; 230 NTSTATUS Status = STATUS_SUCCESS; 231 232 /* 233 * Determine the required size for the heap snapshot 234 */ 235 if(dwFlags & TH32CS_SNAPHEAPLIST) 236 { 237 hi = (PRTL_PROCESS_HEAPS)HeapDebug->Heaps; 238 nHeaps = hi->NumberOfHeaps; 239 RequiredSnapshotSize += nHeaps * sizeof(HEAPLIST32); 240 } 241 242 /* 243 * Determine the required size for the module snapshot 244 */ 245 if(dwFlags & TH32CS_SNAPMODULE) 246 { 247 mi = (PRTL_PROCESS_MODULES)ModuleDebug->Modules; 248 nModules = mi->NumberOfModules; 249 RequiredSnapshotSize += nModules * sizeof(MODULEENTRY32W); 250 } 251 252 /* 253 * Determine the required size for the processes and threads snapshot 254 */ 255 if(dwFlags & (TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD)) 256 { 257 ULONG ProcOffset = 0; 258 259 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; 260 do 261 { 262 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); 263 nProcesses++; 264 nThreads += ProcessInfo->NumberOfThreads; 265 ProcOffset = ProcessInfo->NextEntryOffset; 266 } while(ProcOffset != 0); 267 268 if(dwFlags & TH32CS_SNAPPROCESS) 269 { 270 RequiredSnapshotSize += nProcesses * sizeof(PROCESSENTRY32W); 271 } 272 if(dwFlags & TH32CS_SNAPTHREAD) 273 { 274 RequiredSnapshotSize += nThreads * sizeof(THREADENTRY32); 275 } 276 } 277 278 /* 279 * Create and map the section 280 */ 281 282 SSize.QuadPart = RequiredSnapshotSize; 283 284 InitializeObjectAttributes(&ObjectAttributes, 285 NULL, 286 ((dwFlags & TH32CS_INHERIT) ? OBJ_INHERIT : 0), 287 NULL, 288 NULL); 289 290 Status = NtCreateSection(&hSection, 291 SECTION_ALL_ACCESS, 292 &ObjectAttributes, 293 &SSize, 294 PAGE_READWRITE, 295 SEC_COMMIT, 296 NULL); 297 if(!NT_SUCCESS(Status)) 298 { 299 return Status; 300 } 301 302 SOffset.QuadPart = 0; 303 ViewSize = 0; 304 Snapshot = NULL; 305 306 Status = NtMapViewOfSection(hSection, 307 NtCurrentProcess(), 308 (PVOID*)&Snapshot, 309 0, 310 0, 311 &SOffset, 312 &ViewSize, 313 ViewShare, 314 0, 315 PAGE_READWRITE); 316 if(!NT_SUCCESS(Status)) 317 { 318 NtClose(hSection); 319 return Status; 320 } 321 322 RtlZeroMemory(Snapshot, sizeof(TH32SNAPSHOT)); 323 DataOffset = 0; 324 325 /* 326 * Initialize the section data and fill it with all the data we collected 327 */ 328 329 /* initialize the heap list */ 330 if(dwFlags & TH32CS_SNAPHEAPLIST) 331 { 332 Snapshot->HeapListCount = nHeaps; 333 Snapshot->HeapListOffset = DataOffset; 334 HeapListEntry = (LPHEAPLIST32)OffsetToPtr(Snapshot, DataOffset); 335 for(i = 0; i < nHeaps; i++) 336 { 337 HeapListEntry->dwSize = sizeof(HEAPLIST32); 338 HeapListEntry->th32ProcessID = th32ProcessID; 339 HeapListEntry->th32HeapID = (ULONG_PTR)hi->Heaps[i].BaseAddress; 340 HeapListEntry->dwFlags = hi->Heaps[i].Flags; 341 342 HeapListEntry++; 343 } 344 345 DataOffset += hi->NumberOfHeaps * sizeof(HEAPLIST32); 346 } 347 348 /* initialize the module list */ 349 if(dwFlags & TH32CS_SNAPMODULE) 350 { 351 Snapshot->ModuleListCount = nModules; 352 Snapshot->ModuleListOffset = DataOffset; 353 ModuleListEntry = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, DataOffset); 354 for(i = 0; i < nModules; i++) 355 { 356 ModuleListEntry->dwSize = sizeof(MODULEENTRY32W); 357 ModuleListEntry->th32ModuleID = 1; /* no longer used, always set to one! */ 358 ModuleListEntry->th32ProcessID = th32ProcessID; 359 ModuleListEntry->GlblcntUsage = mi->Modules[i].LoadCount; 360 ModuleListEntry->ProccntUsage = mi->Modules[i].LoadCount; 361 ModuleListEntry->modBaseAddr = (BYTE*)mi->Modules[i].ImageBase; 362 ModuleListEntry->modBaseSize = mi->Modules[i].ImageSize; 363 ModuleListEntry->hModule = (HMODULE)mi->Modules[i].ImageBase; 364 365 MultiByteToWideChar(CP_ACP, 366 0, 367 &mi->Modules[i].FullPathName[mi->Modules[i].OffsetToFileName], 368 -1, 369 ModuleListEntry->szModule, 370 sizeof(ModuleListEntry->szModule) / sizeof(ModuleListEntry->szModule[0])); 371 372 MultiByteToWideChar(CP_ACP, 373 0, 374 mi->Modules[i].FullPathName, 375 -1, 376 ModuleListEntry->szExePath, 377 sizeof(ModuleListEntry->szExePath) / sizeof(ModuleListEntry->szExePath[0])); 378 379 ModuleListEntry++; 380 } 381 382 DataOffset += mi->NumberOfModules * sizeof(MODULEENTRY32W); 383 } 384 385 /* initialize the process list */ 386 if(dwFlags & TH32CS_SNAPPROCESS) 387 { 388 ULONG ProcOffset = 0; 389 390 Snapshot->ProcessListCount = nProcesses; 391 Snapshot->ProcessListOffset = DataOffset; 392 ProcessListEntry = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, DataOffset); 393 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; 394 do 395 { 396 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); 397 398 ProcessListEntry->dwSize = sizeof(PROCESSENTRY32W); 399 ProcessListEntry->cntUsage = 0; /* no longer used */ 400 ProcessListEntry->th32ProcessID = (ULONG_PTR)ProcessInfo->UniqueProcessId; 401 ProcessListEntry->th32DefaultHeapID = 0; /* no longer used */ 402 ProcessListEntry->th32ModuleID = 0; /* no longer used */ 403 ProcessListEntry->cntThreads = ProcessInfo->NumberOfThreads; 404 ProcessListEntry->th32ParentProcessID = (ULONG_PTR)ProcessInfo->InheritedFromUniqueProcessId; 405 ProcessListEntry->pcPriClassBase = ProcessInfo->BasePriority; 406 ProcessListEntry->dwFlags = 0; /* no longer used */ 407 if(ProcessInfo->ImageName.Buffer != NULL) 408 { 409 ULONG ExeFileLength = min(ProcessInfo->ImageName.Length, 410 sizeof(ProcessListEntry->szExeFile) - sizeof(WCHAR)); 411 RtlCopyMemory(ProcessListEntry->szExeFile, 412 ProcessInfo->ImageName.Buffer, 413 ExeFileLength); 414 ProcessListEntry->szExeFile[ExeFileLength / sizeof(WCHAR)] = UNICODE_NULL; 415 } 416 else 417 { 418 lstrcpyW(ProcessListEntry->szExeFile, L"[System Process]"); 419 } 420 421 ProcessListEntry++; 422 423 ProcOffset = ProcessInfo->NextEntryOffset; 424 } while(ProcOffset != 0); 425 426 DataOffset += nProcesses * sizeof(PROCESSENTRY32W); 427 } 428 429 /* initialize the thread list */ 430 if(dwFlags & TH32CS_SNAPTHREAD) 431 { 432 ULONG ProcOffset = 0; 433 434 Snapshot->ThreadListCount = nThreads; 435 Snapshot->ThreadListOffset = DataOffset; 436 ThreadListEntry = (LPTHREADENTRY32)OffsetToPtr(Snapshot, DataOffset); 437 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)ProcThrdInfo; 438 do 439 { 440 PSYSTEM_THREAD_INFORMATION ThreadInfo; 441 ULONG n; 442 443 ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG_PTR)ProcessInfo + ProcOffset); 444 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1); 445 446 for(n = 0; n < ProcessInfo->NumberOfThreads; n++) 447 { 448 ThreadListEntry->dwSize = sizeof(THREADENTRY32); 449 ThreadListEntry->cntUsage = 0; /* no longer used */ 450 ThreadListEntry->th32ThreadID = (ULONG_PTR)ThreadInfo->ClientId.UniqueThread; 451 ThreadListEntry->th32OwnerProcessID = (ULONG_PTR)ThreadInfo->ClientId.UniqueProcess; 452 ThreadListEntry->tpBasePri = ThreadInfo->BasePriority; 453 ThreadListEntry->tpDeltaPri = 0; /* no longer used */ 454 ThreadListEntry->dwFlags = 0; /* no longer used */ 455 456 ThreadInfo++; 457 ThreadListEntry++; 458 } 459 460 ProcOffset = ProcessInfo->NextEntryOffset; 461 } while(ProcOffset != 0); 462 } 463 464 /* 465 * We're done, unmap the view and return the section handle 466 */ 467 468 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 469 470 if(NT_SUCCESS(Status)) 471 { 472 *SectionHandle = hSection; 473 } 474 else 475 { 476 NtClose(hSection); 477 } 478 479 return Status; 480 } 481 482 /* PUBLIC FUNCTIONS ***********************************************************/ 483 484 /* 485 * @implemented 486 */ 487 BOOL 488 WINAPI 489 Heap32First(LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID) 490 { 491 PRTL_DEBUG_INFORMATION DebugInfo; 492 PRTL_HEAP_INFORMATION Heap; 493 PRTLP_HEAP_ENTRY Block, LastBlock; 494 ULONG i; 495 NTSTATUS Status; 496 497 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32)); 498 499 DebugInfo = RtlCreateQueryDebugBuffer(0, 500 FALSE); 501 if (DebugInfo == NULL) 502 { 503 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 504 return FALSE; 505 } 506 507 Status = RtlQueryProcessDebugInformation(th32ProcessID, 508 RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS, 509 DebugInfo); 510 511 if (NT_SUCCESS(Status)) 512 { 513 Status = STATUS_NO_MORE_FILES; 514 515 for (i = 0; 516 i != DebugInfo->Heaps->NumberOfHeaps; 517 i++) 518 { 519 Heap = &DebugInfo->Heaps->Heaps[i]; 520 521 if ((ULONG_PTR)Heap->BaseAddress == th32HeapID) 522 { 523 lphe->hHandle = (HANDLE)Heap->BaseAddress; 524 lphe->dwAddress = 0; 525 lphe->dwBlockSize = 0; 526 lphe->dwFlags = 0; 527 lphe->dwLockCount = 0; 528 lphe->dwResvd = 0; 529 lphe->th32ProcessID = th32ProcessID; 530 lphe->th32HeapID = (ULONG_PTR)Heap->BaseAddress; 531 532 Block = (PRTLP_HEAP_ENTRY)Heap->Entries; 533 LastBlock = Block + Heap->NumberOfEntries; 534 535 while (Block != LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE)) 536 { 537 lphe->dwResvd++; 538 lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead); 539 Block++; 540 } 541 542 if (Block != LastBlock && lphe->dwResvd != 0) 543 { 544 lphe->dwBlockSize = Block->Size; 545 546 if (Block->Flags & 0x2F1) /* FIXME */ 547 lphe->dwFlags = LF32_FIXED; 548 else if (Block->Flags & 0x20) /* FIXME */ 549 lphe->dwFlags = LF32_MOVEABLE; 550 else if (Block->Flags & 0x100) /* FIXME */ 551 lphe->dwFlags = LF32_FREE; 552 553 Status = STATUS_SUCCESS; 554 } 555 556 break; 557 } 558 } 559 } 560 561 RtlDestroyQueryDebugBuffer(DebugInfo); 562 563 if (!NT_SUCCESS(Status)) 564 { 565 BaseSetLastNTError(Status); 566 return FALSE; 567 } 568 569 return TRUE; 570 } 571 572 573 /* 574 * @implemented 575 */ 576 BOOL 577 WINAPI 578 Heap32Next(LPHEAPENTRY32 lphe) 579 { 580 PRTL_DEBUG_INFORMATION DebugInfo; 581 PRTL_HEAP_INFORMATION Heap; 582 PRTLP_HEAP_ENTRY Block, LastBlock; 583 BOOLEAN FoundUncommitted = FALSE; 584 ULONG i; 585 NTSTATUS Status; 586 587 CHECK_PARAM_SIZE(lphe, sizeof(HEAPENTRY32)); 588 589 DebugInfo = RtlCreateQueryDebugBuffer(0, 590 FALSE); 591 if (DebugInfo == NULL) 592 { 593 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 594 return FALSE; 595 } 596 597 Status = RtlQueryProcessDebugInformation(lphe->th32ProcessID, 598 RTL_DEBUG_QUERY_HEAPS | RTL_DEBUG_QUERY_HEAP_BLOCKS, 599 DebugInfo); 600 601 if (NT_SUCCESS(Status)) 602 { 603 Status = STATUS_NO_MORE_FILES; 604 605 for (i = 0; 606 i != DebugInfo->Heaps->NumberOfHeaps; 607 i++) 608 { 609 Heap = &DebugInfo->Heaps->Heaps[i]; 610 611 if ((ULONG_PTR)Heap->BaseAddress == lphe->th32HeapID) 612 { 613 if (++lphe->dwResvd < Heap->NumberOfEntries) 614 { 615 lphe->dwFlags = 0; 616 617 Block = (PRTLP_HEAP_ENTRY)Heap->Entries + lphe->dwResvd; 618 LastBlock = (PRTLP_HEAP_ENTRY)Heap->Entries + Heap->NumberOfEntries; 619 620 while (Block < LastBlock && (Block->Flags & PROCESS_HEAP_UNCOMMITTED_RANGE)) 621 { 622 lphe->dwResvd++; 623 lphe->dwAddress = (ULONG_PTR)((ULONG_PTR)Block->Address + Heap->EntryOverhead); 624 FoundUncommitted = TRUE; 625 Block++; 626 } 627 628 if (Block < LastBlock) 629 { 630 if (!FoundUncommitted) 631 lphe->dwAddress += lphe->dwBlockSize; 632 633 lphe->dwBlockSize = Block->Size; 634 635 if (Block->Flags & 0x2F1) /* FIXME */ 636 lphe->dwFlags = LF32_FIXED; 637 else if (Block->Flags & 0x20) /* FIXME */ 638 lphe->dwFlags = LF32_MOVEABLE; 639 else if (Block->Flags & 0x100) /* FIXME */ 640 lphe->dwFlags = LF32_FREE; 641 642 Status = STATUS_SUCCESS; 643 } 644 } 645 646 break; 647 } 648 } 649 } 650 651 RtlDestroyQueryDebugBuffer(DebugInfo); 652 653 if (!NT_SUCCESS(Status)) 654 { 655 BaseSetLastNTError(Status); 656 return FALSE; 657 } 658 659 return TRUE; 660 661 } 662 663 664 /* 665 * @implemented 666 */ 667 BOOL 668 WINAPI 669 Heap32ListFirst(HANDLE hSnapshot, LPHEAPLIST32 lphl) 670 { 671 PTH32SNAPSHOT Snapshot; 672 LARGE_INTEGER SOffset; 673 SIZE_T ViewSize; 674 NTSTATUS Status; 675 676 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32)); 677 678 SOffset.QuadPart = 0; 679 ViewSize = 0; 680 Snapshot = NULL; 681 682 Status = NtMapViewOfSection(hSnapshot, 683 NtCurrentProcess(), 684 (PVOID*)&Snapshot, 685 0, 686 0, 687 &SOffset, 688 &ViewSize, 689 ViewShare, 690 0, 691 PAGE_READWRITE); 692 if(NT_SUCCESS(Status)) 693 { 694 BOOL Ret; 695 696 if(Snapshot->HeapListCount > 0) 697 { 698 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); 699 Snapshot->HeapListIndex = 1; 700 RtlCopyMemory(lphl, &Entries[0], sizeof(HEAPLIST32)); 701 Ret = TRUE; 702 } 703 else 704 { 705 SetLastError(ERROR_NO_MORE_FILES); 706 Ret = FALSE; 707 } 708 709 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 710 return Ret; 711 } 712 713 BaseSetLastNTError(Status); 714 return FALSE; 715 } 716 717 718 /* 719 * @implemented 720 */ 721 BOOL 722 WINAPI 723 Heap32ListNext(HANDLE hSnapshot, LPHEAPLIST32 lphl) 724 { 725 PTH32SNAPSHOT Snapshot; 726 LARGE_INTEGER SOffset; 727 SIZE_T ViewSize; 728 NTSTATUS Status; 729 730 CHECK_PARAM_SIZE(lphl, sizeof(HEAPLIST32)); 731 732 SOffset.QuadPart = 0; 733 ViewSize = 0; 734 Snapshot = NULL; 735 736 Status = NtMapViewOfSection(hSnapshot, 737 NtCurrentProcess(), 738 (PVOID*)&Snapshot, 739 0, 740 0, 741 &SOffset, 742 &ViewSize, 743 ViewShare, 744 0, 745 PAGE_READWRITE); 746 if(NT_SUCCESS(Status)) 747 { 748 BOOL Ret; 749 750 if(Snapshot->HeapListCount > 0 && 751 Snapshot->HeapListIndex < Snapshot->HeapListCount) 752 { 753 LPHEAPLIST32 Entries = (LPHEAPLIST32)OffsetToPtr(Snapshot, Snapshot->HeapListOffset); 754 RtlCopyMemory(lphl, &Entries[Snapshot->HeapListIndex++], sizeof(HEAPLIST32)); 755 Ret = TRUE; 756 } 757 else 758 { 759 SetLastError(ERROR_NO_MORE_FILES); 760 Ret = FALSE; 761 } 762 763 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 764 return Ret; 765 } 766 767 BaseSetLastNTError(Status); 768 return FALSE; 769 } 770 771 772 /* 773 * @implemented 774 */ 775 BOOL 776 WINAPI 777 Module32First(HANDLE hSnapshot, LPMODULEENTRY32 lpme) 778 { 779 MODULEENTRY32W me; 780 BOOL Ret; 781 782 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32)); 783 784 me.dwSize = sizeof(MODULEENTRY32W); 785 786 Ret = Module32FirstW(hSnapshot, &me); 787 if(Ret) 788 { 789 lpme->th32ModuleID = me.th32ModuleID; 790 lpme->th32ProcessID = me.th32ProcessID; 791 lpme->GlblcntUsage = me.GlblcntUsage; 792 lpme->ProccntUsage = me.ProccntUsage; 793 lpme->modBaseAddr = me.modBaseAddr; 794 lpme->modBaseSize = me.modBaseSize; 795 lpme->hModule = me.hModule; 796 797 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0); 798 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0); 799 } 800 801 return Ret; 802 } 803 804 805 /* 806 * @implemented 807 */ 808 BOOL 809 WINAPI 810 Module32FirstW(HANDLE hSnapshot, LPMODULEENTRY32W lpme) 811 { 812 PTH32SNAPSHOT Snapshot; 813 LARGE_INTEGER SOffset; 814 SIZE_T ViewSize; 815 NTSTATUS Status; 816 817 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W)); 818 819 SOffset.QuadPart = 0; 820 ViewSize = 0; 821 Snapshot = NULL; 822 823 Status = NtMapViewOfSection(hSnapshot, 824 NtCurrentProcess(), 825 (PVOID*)&Snapshot, 826 0, 827 0, 828 &SOffset, 829 &ViewSize, 830 ViewShare, 831 0, 832 PAGE_READWRITE); 833 if(NT_SUCCESS(Status)) 834 { 835 BOOL Ret; 836 837 if(Snapshot->ModuleListCount > 0) 838 { 839 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset); 840 Snapshot->ModuleListIndex = 1; 841 RtlCopyMemory(lpme, &Entries[0], sizeof(MODULEENTRY32W)); 842 Ret = TRUE; 843 } 844 else 845 { 846 SetLastError(ERROR_NO_MORE_FILES); 847 Ret = FALSE; 848 } 849 850 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 851 return Ret; 852 } 853 854 BaseSetLastNTError(Status); 855 return FALSE; 856 } 857 858 859 /* 860 * @implemented 861 */ 862 BOOL 863 WINAPI 864 Module32Next(HANDLE hSnapshot, LPMODULEENTRY32 lpme) 865 { 866 MODULEENTRY32W me; 867 BOOL Ret; 868 869 CHECK_PARAM_SIZEA(lpme, sizeof(MODULEENTRY32)); 870 871 me.dwSize = sizeof(MODULEENTRY32W); 872 873 Ret = Module32NextW(hSnapshot, &me); 874 if(Ret) 875 { 876 lpme->th32ModuleID = me.th32ModuleID; 877 lpme->th32ProcessID = me.th32ProcessID; 878 lpme->GlblcntUsage = me.GlblcntUsage; 879 lpme->ProccntUsage = me.ProccntUsage; 880 lpme->modBaseAddr = me.modBaseAddr; 881 lpme->modBaseSize = me.modBaseSize; 882 lpme->hModule = me.hModule; 883 884 WideCharToMultiByte(CP_ACP, 0, me.szModule, -1, lpme->szModule, sizeof(lpme->szModule), 0, 0); 885 WideCharToMultiByte(CP_ACP, 0, me.szExePath, -1, lpme->szExePath, sizeof(lpme->szExePath), 0, 0); 886 } 887 888 return Ret; 889 } 890 891 892 /* 893 * @implemented 894 */ 895 BOOL 896 WINAPI 897 Module32NextW(HANDLE hSnapshot, LPMODULEENTRY32W lpme) 898 { 899 PTH32SNAPSHOT Snapshot; 900 LARGE_INTEGER SOffset; 901 SIZE_T ViewSize; 902 NTSTATUS Status; 903 904 CHECK_PARAM_SIZE(lpme, sizeof(MODULEENTRY32W)); 905 906 SOffset.QuadPart = 0; 907 ViewSize = 0; 908 Snapshot = NULL; 909 910 Status = NtMapViewOfSection(hSnapshot, 911 NtCurrentProcess(), 912 (PVOID*)&Snapshot, 913 0, 914 0, 915 &SOffset, 916 &ViewSize, 917 ViewShare, 918 0, 919 PAGE_READWRITE); 920 if(NT_SUCCESS(Status)) 921 { 922 BOOL Ret; 923 924 if((Snapshot->ModuleListCount > 0) && 925 (Snapshot->ModuleListIndex < Snapshot->ModuleListCount)) 926 { 927 LPMODULEENTRY32W Entries = (LPMODULEENTRY32W)OffsetToPtr(Snapshot, Snapshot->ModuleListOffset); 928 RtlCopyMemory(lpme, &Entries[Snapshot->ModuleListIndex++], sizeof(MODULEENTRY32W)); 929 Ret = TRUE; 930 } 931 else 932 { 933 SetLastError(ERROR_NO_MORE_FILES); 934 Ret = FALSE; 935 } 936 937 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 938 return Ret; 939 } 940 941 BaseSetLastNTError(Status); 942 return FALSE; 943 } 944 945 946 /* 947 * @implemented 948 */ 949 BOOL 950 WINAPI 951 Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) 952 { 953 PROCESSENTRY32W pe; 954 BOOL Ret; 955 956 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32)); 957 958 pe.dwSize = sizeof(PROCESSENTRY32W); 959 960 Ret = Process32FirstW(hSnapshot, &pe); 961 if(Ret) 962 { 963 lppe->cntUsage = pe.cntUsage; 964 lppe->th32ProcessID = pe.th32ProcessID; 965 lppe->th32DefaultHeapID = pe.th32DefaultHeapID; 966 lppe->th32ModuleID = pe.th32ModuleID; 967 lppe->cntThreads = pe.cntThreads; 968 lppe->th32ParentProcessID = pe.th32ParentProcessID; 969 lppe->pcPriClassBase = pe.pcPriClassBase; 970 lppe->dwFlags = pe.dwFlags; 971 972 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0); 973 } 974 975 return Ret; 976 } 977 978 979 /* 980 * @implemented 981 */ 982 BOOL 983 WINAPI 984 Process32FirstW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) 985 { 986 PTH32SNAPSHOT Snapshot; 987 LARGE_INTEGER SOffset; 988 SIZE_T ViewSize; 989 NTSTATUS Status; 990 991 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W)); 992 993 SOffset.QuadPart = 0; 994 ViewSize = 0; 995 Snapshot = NULL; 996 997 Status = NtMapViewOfSection(hSnapshot, 998 NtCurrentProcess(), 999 (PVOID*)&Snapshot, 1000 0, 1001 0, 1002 &SOffset, 1003 &ViewSize, 1004 ViewShare, 1005 0, 1006 PAGE_READWRITE); 1007 if(NT_SUCCESS(Status)) 1008 { 1009 BOOL Ret; 1010 1011 if(Snapshot->ProcessListCount > 0) 1012 { 1013 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset); 1014 1015 Snapshot->ProcessListIndex = 1; 1016 RtlCopyMemory(lppe, &Entries[0], sizeof(PROCESSENTRY32W)); 1017 Ret = TRUE; 1018 } 1019 else 1020 { 1021 1022 SetLastError(ERROR_NO_MORE_FILES); 1023 Ret = FALSE; 1024 } 1025 1026 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 1027 return Ret; 1028 } 1029 1030 BaseSetLastNTError(Status); 1031 return FALSE; 1032 } 1033 1034 1035 /* 1036 * @implemented 1037 */ 1038 BOOL 1039 WINAPI 1040 Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe) 1041 { 1042 PROCESSENTRY32W pe; 1043 BOOL Ret; 1044 1045 CHECK_PARAM_SIZEA(lppe, sizeof(PROCESSENTRY32)); 1046 1047 pe.dwSize = sizeof(PROCESSENTRY32W); 1048 1049 Ret = Process32NextW(hSnapshot, &pe); 1050 if(Ret) 1051 { 1052 lppe->cntUsage = pe.cntUsage; 1053 lppe->th32ProcessID = pe.th32ProcessID; 1054 lppe->th32DefaultHeapID = pe.th32DefaultHeapID; 1055 lppe->th32ModuleID = pe.th32ModuleID; 1056 lppe->cntThreads = pe.cntThreads; 1057 lppe->th32ParentProcessID = pe.th32ParentProcessID; 1058 lppe->pcPriClassBase = pe.pcPriClassBase; 1059 lppe->dwFlags = pe.dwFlags; 1060 1061 WideCharToMultiByte(CP_ACP, 0, pe.szExeFile, -1, lppe->szExeFile, sizeof(lppe->szExeFile), 0, 0); 1062 } 1063 1064 return Ret; 1065 } 1066 1067 1068 /* 1069 * @implemented 1070 */ 1071 BOOL 1072 WINAPI 1073 Process32NextW(HANDLE hSnapshot, LPPROCESSENTRY32W lppe) 1074 { 1075 PTH32SNAPSHOT Snapshot; 1076 LARGE_INTEGER SOffset; 1077 SIZE_T ViewSize; 1078 NTSTATUS Status; 1079 1080 CHECK_PARAM_SIZE(lppe, sizeof(PROCESSENTRY32W)); 1081 1082 SOffset.QuadPart = 0; 1083 ViewSize = 0; 1084 Snapshot = NULL; 1085 1086 Status = NtMapViewOfSection(hSnapshot, 1087 NtCurrentProcess(), 1088 (PVOID*)&Snapshot, 1089 0, 1090 0, 1091 &SOffset, 1092 &ViewSize, 1093 ViewShare, 1094 0, 1095 PAGE_READWRITE); 1096 if(NT_SUCCESS(Status)) 1097 { 1098 BOOL Ret; 1099 1100 if(Snapshot->ProcessListCount > 0 && 1101 Snapshot->ProcessListIndex < Snapshot->ProcessListCount) 1102 { 1103 LPPROCESSENTRY32W Entries = (LPPROCESSENTRY32W)OffsetToPtr(Snapshot, Snapshot->ProcessListOffset); 1104 RtlCopyMemory(lppe, &Entries[Snapshot->ProcessListIndex++], sizeof(PROCESSENTRY32W)); 1105 Ret = TRUE; 1106 } 1107 else 1108 { 1109 SetLastError(ERROR_NO_MORE_FILES); 1110 Ret = FALSE; 1111 } 1112 1113 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 1114 return Ret; 1115 } 1116 1117 BaseSetLastNTError(Status); 1118 return FALSE; 1119 } 1120 1121 1122 /* 1123 * @implemented 1124 */ 1125 BOOL 1126 WINAPI 1127 Thread32First(HANDLE hSnapshot, LPTHREADENTRY32 lpte) 1128 { 1129 PTH32SNAPSHOT Snapshot; 1130 LARGE_INTEGER SOffset; 1131 SIZE_T ViewSize; 1132 NTSTATUS Status; 1133 1134 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32)); 1135 1136 SOffset.QuadPart = 0; 1137 ViewSize = 0; 1138 Snapshot = NULL; 1139 1140 Status = NtMapViewOfSection(hSnapshot, 1141 NtCurrentProcess(), 1142 (PVOID*)&Snapshot, 1143 0, 1144 0, 1145 &SOffset, 1146 &ViewSize, 1147 ViewShare, 1148 0, 1149 PAGE_READWRITE); 1150 if(NT_SUCCESS(Status)) 1151 { 1152 BOOL Ret; 1153 1154 if(Snapshot->ThreadListCount > 0) 1155 { 1156 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset); 1157 Snapshot->ThreadListIndex = 1; 1158 RtlCopyMemory(lpte, &Entries[0], sizeof(THREADENTRY32)); 1159 Ret = TRUE; 1160 } 1161 else 1162 { 1163 SetLastError(ERROR_NO_MORE_FILES); 1164 Ret = FALSE; 1165 } 1166 1167 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 1168 return Ret; 1169 } 1170 1171 BaseSetLastNTError(Status); 1172 return FALSE; 1173 } 1174 1175 1176 /* 1177 * @implemented 1178 */ 1179 BOOL 1180 WINAPI 1181 Thread32Next(HANDLE hSnapshot, LPTHREADENTRY32 lpte) 1182 { 1183 PTH32SNAPSHOT Snapshot; 1184 LARGE_INTEGER SOffset; 1185 SIZE_T ViewSize; 1186 NTSTATUS Status; 1187 1188 CHECK_PARAM_SIZE(lpte, sizeof(THREADENTRY32)); 1189 1190 SOffset.QuadPart = 0; 1191 ViewSize = 0; 1192 Snapshot = NULL; 1193 1194 Status = NtMapViewOfSection(hSnapshot, 1195 NtCurrentProcess(), 1196 (PVOID*)&Snapshot, 1197 0, 1198 0, 1199 &SOffset, 1200 &ViewSize, 1201 ViewShare, 1202 0, 1203 PAGE_READWRITE); 1204 if(NT_SUCCESS(Status)) 1205 { 1206 BOOL Ret; 1207 1208 if(Snapshot->ThreadListCount > 0 && 1209 Snapshot->ThreadListIndex < Snapshot->ThreadListCount) 1210 { 1211 LPTHREADENTRY32 Entries = (LPTHREADENTRY32)OffsetToPtr(Snapshot, Snapshot->ThreadListOffset); 1212 RtlCopyMemory(lpte, &Entries[Snapshot->ThreadListIndex++], sizeof(THREADENTRY32)); 1213 Ret = TRUE; 1214 } 1215 else 1216 { 1217 SetLastError(ERROR_NO_MORE_FILES); 1218 Ret = FALSE; 1219 } 1220 1221 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)Snapshot); 1222 return Ret; 1223 } 1224 1225 BaseSetLastNTError(Status); 1226 return FALSE; 1227 } 1228 1229 1230 /* 1231 * @implemented 1232 */ 1233 BOOL 1234 WINAPI 1235 Toolhelp32ReadProcessMemory(DWORD th32ProcessID, LPCVOID lpBaseAddress, 1236 LPVOID lpBuffer, SIZE_T cbRead, SIZE_T* lpNumberOfBytesRead) 1237 { 1238 HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, th32ProcessID); 1239 if(hProcess != NULL) 1240 { 1241 BOOL Ret = ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, cbRead, lpNumberOfBytesRead); 1242 CloseHandle(hProcess); 1243 return Ret; 1244 } 1245 1246 return FALSE; 1247 } 1248 1249 1250 /* 1251 * @implemented 1252 */ 1253 HANDLE 1254 WINAPI 1255 CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID) 1256 { 1257 PRTL_DEBUG_INFORMATION HeapDebug, ModuleDebug; 1258 PVOID ProcThrdInfo; 1259 SIZE_T ProcThrdInfoSize; 1260 NTSTATUS Status; 1261 HANDLE hSnapShotSection = NULL; 1262 1263 if(th32ProcessID == 0) 1264 { 1265 th32ProcessID = GetCurrentProcessId(); 1266 } 1267 1268 /* 1269 * Get all information required for the snapshot 1270 */ 1271 Status = TH32CreateSnapshot(dwFlags, 1272 th32ProcessID, 1273 &HeapDebug, 1274 &ModuleDebug, 1275 &ProcThrdInfo, 1276 &ProcThrdInfoSize); 1277 if(!NT_SUCCESS(Status)) 1278 { 1279 BaseSetLastNTError(Status); 1280 return NULL; 1281 } 1282 1283 /* 1284 * Create a section handle and initialize the collected information 1285 */ 1286 Status = TH32CreateSnapshotSectionInitialize(dwFlags, 1287 th32ProcessID, 1288 HeapDebug, 1289 ModuleDebug, 1290 ProcThrdInfo, 1291 &hSnapShotSection); 1292 1293 /* 1294 * Free the temporarily allocated memory which is no longer needed 1295 */ 1296 TH32FreeAllocatedResources(HeapDebug, 1297 ModuleDebug, 1298 ProcThrdInfo, 1299 ProcThrdInfoSize); 1300 1301 if(!NT_SUCCESS(Status)) 1302 { 1303 BaseSetLastNTError(Status); 1304 return NULL; 1305 } 1306 1307 return hSnapShotSection; 1308 } 1309 1310 /* EOF */ 1311