3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: dll/win32/kernel32/misc/toolhelp.c
6 * PURPOSE: Toolhelp functions
7 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
8 * Robert Dickenson (robd@mok.lvcm.com)
10 * NOTES: Do NOT use the heap functions in here because they
11 * adulterate the heap statistics!
14 * 10/30/2004 Implemented some parts (w3)
15 * Inspired by the book "Windows NT Native API"
16 * Created 05 January 2003 (robd)
26 /* INTERNAL DEFINITIONS *******************************************************/
28 typedef struct _RTLP_HEAP_ENTRY
32 USHORT Unknown1
; /* FIXME */
33 ULONG Unknown2
; /* FIXME */
35 } RTLP_HEAP_ENTRY
, *PRTLP_HEAP_ENTRY
;
37 #define CHECK_PARAM_SIZE(ptr, siz) \
38 if((ptr) == NULL || (ptr)->dwSize != (siz)) \
40 SetLastError(ERROR_INVALID_PARAMETER); \
45 * Tests in win showed that the dwSize field can be greater than the actual size
46 * of the structure for the ansi functions. I found this out by accidently
47 * forgetting to set the dwSize field in a test application and it just didn't
48 * work in ros but in win.
51 #define CHECK_PARAM_SIZEA(ptr, siz) \
52 if((ptr) == NULL || (ptr)->dwSize < (siz)) \
54 SetLastError(ERROR_INVALID_PARAMETER); \
58 #define OffsetToPtr(Snapshot, Offset) \
59 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
61 typedef struct _TH32SNAPSHOT
66 ULONG_PTR HeapListOffset
;
68 ULONG ModuleListCount
;
69 ULONG ModuleListIndex
;
70 ULONG_PTR ModuleListOffset
;
72 ULONG ProcessListCount
;
73 ULONG ProcessListIndex
;
74 ULONG_PTR ProcessListOffset
;
76 ULONG ThreadListCount
;
77 ULONG ThreadListIndex
;
78 ULONG_PTR ThreadListOffset
;
79 } TH32SNAPSHOT
, *PTH32SNAPSHOT
;
81 /* INTERNAL FUNCTIONS *********************************************************/
84 TH32FreeAllocatedResources(PRTL_DEBUG_INFORMATION HeapDebug
,
85 PRTL_DEBUG_INFORMATION ModuleDebug
,
87 SIZE_T ProcThrdInfoSize
)
91 RtlDestroyQueryDebugBuffer(HeapDebug
);
93 if(ModuleDebug
!= NULL
)
95 RtlDestroyQueryDebugBuffer(ModuleDebug
);
98 if(ProcThrdInfo
!= NULL
)
100 NtFreeVirtualMemory(NtCurrentProcess(),
108 TH32CreateSnapshot(DWORD dwFlags
,
110 PRTL_DEBUG_INFORMATION
*HeapDebug
,
111 PRTL_DEBUG_INFORMATION
*ModuleDebug
,
113 SIZE_T
*ProcThrdInfoSize
)
115 NTSTATUS Status
= STATUS_SUCCESS
;
119 *ProcThrdInfo
= NULL
;
120 *ProcThrdInfoSize
= 0;
123 * Allocate the debug information for a heap snapshot
125 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
127 *HeapDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
128 if(*HeapDebug
!= NULL
)
130 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
131 RTL_DEBUG_QUERY_HEAPS
,
135 Status
= STATUS_UNSUCCESSFUL
;
139 * Allocate the debug information for a module snapshot
141 if(dwFlags
& TH32CS_SNAPMODULE
&&
144 *ModuleDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
145 if(*ModuleDebug
!= NULL
)
147 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
148 RTL_DEBUG_QUERY_MODULES
,
152 Status
= STATUS_UNSUCCESSFUL
;
156 * Allocate enough memory for the system's process list
159 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
) &&
164 (*ProcThrdInfoSize
) += 0x10000;
165 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
171 if(!NT_SUCCESS(Status
))
176 Status
= NtQuerySystemInformation(SystemProcessInformation
,
180 if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
182 NtFreeVirtualMemory(NtCurrentProcess(),
186 *ProcThrdInfo
= NULL
;
196 * Free resources in case of failure!
199 if(!NT_SUCCESS(Status
))
201 TH32FreeAllocatedResources(*HeapDebug
,
211 TH32CreateSnapshotSectionInitialize(DWORD dwFlags
,
213 PRTL_DEBUG_INFORMATION HeapDebug
,
214 PRTL_DEBUG_INFORMATION ModuleDebug
,
216 HANDLE
*SectionHandle
)
218 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
219 LPHEAPLIST32 HeapListEntry
;
220 LPMODULEENTRY32W ModuleListEntry
;
221 LPPROCESSENTRY32W ProcessListEntry
;
222 LPTHREADENTRY32 ThreadListEntry
;
223 OBJECT_ATTRIBUTES ObjectAttributes
;
224 LARGE_INTEGER SSize
, SOffset
;
226 PTH32SNAPSHOT Snapshot
;
227 ULONG_PTR DataOffset
;
229 ULONG i
, nProcesses
= 0, nThreads
= 0, nHeaps
= 0, nModules
= 0;
230 ULONG RequiredSnapshotSize
= sizeof(TH32SNAPSHOT
);
231 PRTL_PROCESS_HEAPS hi
= NULL
;
232 PRTL_PROCESS_MODULES mi
= NULL
;
233 NTSTATUS Status
= STATUS_SUCCESS
;
236 * Determine the required size for the heap snapshot
238 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
240 hi
= (PRTL_PROCESS_HEAPS
)HeapDebug
->Heaps
;
241 nHeaps
= hi
->NumberOfHeaps
;
242 RequiredSnapshotSize
+= nHeaps
* sizeof(HEAPLIST32
);
246 * Determine the required size for the module snapshot
248 if(dwFlags
& TH32CS_SNAPMODULE
)
250 mi
= (PRTL_PROCESS_MODULES
)ModuleDebug
->Modules
;
251 nModules
= mi
->NumberOfModules
;
252 RequiredSnapshotSize
+= nModules
* sizeof(MODULEENTRY32W
);
256 * Determine the required size for the processes and threads snapshot
258 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
))
260 ULONG ProcOffset
= 0;
262 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
265 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
267 nThreads
+= ProcessInfo
->NumberOfThreads
;
268 ProcOffset
= ProcessInfo
->NextEntryOffset
;
269 } while(ProcOffset
!= 0);
271 if(dwFlags
& TH32CS_SNAPPROCESS
)
273 RequiredSnapshotSize
+= nProcesses
* sizeof(PROCESSENTRY32W
);
275 if(dwFlags
& TH32CS_SNAPTHREAD
)
277 RequiredSnapshotSize
+= nThreads
* sizeof(THREADENTRY32
);
282 * Create and map the section
285 SSize
.QuadPart
= RequiredSnapshotSize
;
287 InitializeObjectAttributes(&ObjectAttributes
,
289 ((dwFlags
& TH32CS_INHERIT
) ? OBJ_INHERIT
: 0),
293 Status
= NtCreateSection(&hSection
,
300 if(!NT_SUCCESS(Status
))
305 SOffset
.QuadPart
= 0;
309 Status
= NtMapViewOfSection(hSection
,
319 if(!NT_SUCCESS(Status
))
325 RtlZeroMemory(Snapshot
, sizeof(TH32SNAPSHOT
));
329 * Initialize the section data and fill it with all the data we collected
332 /* initialize the heap list */
333 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
335 Snapshot
->HeapListCount
= nHeaps
;
336 Snapshot
->HeapListOffset
= DataOffset
;
337 HeapListEntry
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, DataOffset
);
338 for(i
= 0; i
< nHeaps
; i
++)
340 HeapListEntry
->dwSize
= sizeof(HEAPLIST32
);
341 HeapListEntry
->th32ProcessID
= th32ProcessID
;
342 HeapListEntry
->th32HeapID
= (ULONG_PTR
)hi
->Heaps
[i
].BaseAddress
;
343 HeapListEntry
->dwFlags
= hi
->Heaps
[i
].Flags
;
348 DataOffset
+= hi
->NumberOfHeaps
* sizeof(HEAPLIST32
);
351 /* initialize the module list */
352 if(dwFlags
& TH32CS_SNAPMODULE
)
354 Snapshot
->ModuleListCount
= nModules
;
355 Snapshot
->ModuleListOffset
= DataOffset
;
356 ModuleListEntry
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
357 for(i
= 0; i
< nModules
; i
++)
359 ModuleListEntry
->dwSize
= sizeof(MODULEENTRY32W
);
360 ModuleListEntry
->th32ModuleID
= 1; /* no longer used, always set to one! */
361 ModuleListEntry
->th32ProcessID
= th32ProcessID
;
362 ModuleListEntry
->GlblcntUsage
= mi
->Modules
[i
].LoadCount
;
363 ModuleListEntry
->ProccntUsage
= mi
->Modules
[i
].LoadCount
;
364 ModuleListEntry
->modBaseAddr
= (BYTE
*)mi
->Modules
[i
].ImageBase
;
365 ModuleListEntry
->modBaseSize
= mi
->Modules
[i
].ImageSize
;
366 ModuleListEntry
->hModule
= (HMODULE
)mi
->Modules
[i
].ImageBase
;
368 MultiByteToWideChar(CP_ACP
,
370 &mi
->Modules
[i
].FullPathName
[mi
->Modules
[i
].OffsetToFileName
],
372 ModuleListEntry
->szModule
,
373 sizeof(ModuleListEntry
->szModule
) / sizeof(ModuleListEntry
->szModule
[0]));
375 MultiByteToWideChar(CP_ACP
,
377 mi
->Modules
[i
].FullPathName
,
379 ModuleListEntry
->szExePath
,
380 sizeof(ModuleListEntry
->szExePath
) / sizeof(ModuleListEntry
->szExePath
[0]));
385 DataOffset
+= mi
->NumberOfModules
* sizeof(MODULEENTRY32W
);
388 /* initialize the process list */
389 if(dwFlags
& TH32CS_SNAPPROCESS
)
391 ULONG ProcOffset
= 0;
393 Snapshot
->ProcessListCount
= nProcesses
;
394 Snapshot
->ProcessListOffset
= DataOffset
;
395 ProcessListEntry
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
396 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
399 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
401 ProcessListEntry
->dwSize
= sizeof(PROCESSENTRY32W
);
402 ProcessListEntry
->cntUsage
= 0; /* no longer used */
403 ProcessListEntry
->th32ProcessID
= (ULONG_PTR
)ProcessInfo
->UniqueProcessId
;
404 ProcessListEntry
->th32DefaultHeapID
= 0; /* no longer used */
405 ProcessListEntry
->th32ModuleID
= 0; /* no longer used */
406 ProcessListEntry
->cntThreads
= ProcessInfo
->NumberOfThreads
;
407 ProcessListEntry
->th32ParentProcessID
= (ULONG_PTR
)ProcessInfo
->InheritedFromUniqueProcessId
;
408 ProcessListEntry
->pcPriClassBase
= ProcessInfo
->BasePriority
;
409 ProcessListEntry
->dwFlags
= 0; /* no longer used */
410 if(ProcessInfo
->ImageName
.Buffer
!= NULL
)
412 lstrcpynW(ProcessListEntry
->szExeFile
,
413 ProcessInfo
->ImageName
.Buffer
,
414 min(ProcessInfo
->ImageName
.Length
/ sizeof(WCHAR
), sizeof(ProcessListEntry
->szExeFile
) / sizeof(ProcessListEntry
->szExeFile
[0])));
418 lstrcpyW(ProcessListEntry
->szExeFile
, L
"[System Process]");
423 ProcOffset
= ProcessInfo
->NextEntryOffset
;
424 } while(ProcOffset
!= 0);
426 DataOffset
+= nProcesses
* sizeof(PROCESSENTRY32W
);
429 /* initialize the thread list */
430 if(dwFlags
& TH32CS_SNAPTHREAD
)
432 ULONG ProcOffset
= 0;
434 Snapshot
->ThreadListCount
= nThreads
;
435 Snapshot
->ThreadListOffset
= DataOffset
;
436 ThreadListEntry
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, DataOffset
);
437 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
440 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
443 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
444 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(ProcessInfo
+ 1);
446 for(n
= 0; n
< ProcessInfo
->NumberOfThreads
; n
++)
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 */
460 ProcOffset
= ProcessInfo
->NextEntryOffset
;
461 } while(ProcOffset
!= 0);
465 * We're done, unmap the view and return the section handle
468 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
470 if(NT_SUCCESS(Status
))
472 *SectionHandle
= hSection
;
482 /* PUBLIC FUNCTIONS ***********************************************************/
489 Heap32First(LPHEAPENTRY32 lphe
, DWORD th32ProcessID
, DWORD th32HeapID
)
491 PRTL_DEBUG_INFORMATION DebugInfo
;
492 PRTL_HEAP_INFORMATION Heap
;
493 PRTLP_HEAP_ENTRY Block
, LastBlock
;
497 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
499 DebugInfo
= RtlCreateQueryDebugBuffer(0,
501 if (DebugInfo
== NULL
)
503 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
507 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
508 RTL_DEBUG_QUERY_HEAPS
| RTL_DEBUG_QUERY_HEAP_BLOCKS
,
511 if (NT_SUCCESS(Status
))
513 Status
= STATUS_NO_MORE_FILES
;
516 i
!= DebugInfo
->Heaps
->NumberOfHeaps
;
519 Heap
= &DebugInfo
->Heaps
->Heaps
[i
];
521 if ((ULONG_PTR
)Heap
->BaseAddress
== th32HeapID
)
523 lphe
->hHandle
= (HANDLE
)Heap
->BaseAddress
;
525 lphe
->dwBlockSize
= 0;
527 lphe
->dwLockCount
= 0;
529 lphe
->th32ProcessID
= th32ProcessID
;
530 lphe
->th32HeapID
= (ULONG_PTR
)Heap
->BaseAddress
;
532 Block
= (PRTLP_HEAP_ENTRY
)Heap
->Entries
;
533 LastBlock
= Block
+ Heap
->NumberOfEntries
;
535 while (Block
!= LastBlock
&& (Block
->Flags
& PROCESS_HEAP_UNCOMMITTED_RANGE
))
538 lphe
->dwAddress
= (ULONG_PTR
)((ULONG_PTR
)Block
->Address
+ Heap
->EntryOverhead
);
542 if (Block
!= LastBlock
&& lphe
->dwResvd
!= 0)
544 lphe
->dwBlockSize
= Block
->Size
;
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
;
553 Status
= STATUS_SUCCESS
;
561 RtlDestroyQueryDebugBuffer(DebugInfo
);
563 if (!NT_SUCCESS(Status
))
565 BaseSetLastNTError(Status
);
578 Heap32Next(LPHEAPENTRY32 lphe
)
580 PRTL_DEBUG_INFORMATION DebugInfo
;
581 PRTL_HEAP_INFORMATION Heap
;
582 PRTLP_HEAP_ENTRY Block
, LastBlock
;
583 BOOLEAN FoundUncommitted
= FALSE
;
587 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
589 DebugInfo
= RtlCreateQueryDebugBuffer(0,
591 if (DebugInfo
== NULL
)
593 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
597 Status
= RtlQueryProcessDebugInformation(lphe
->th32ProcessID
,
598 RTL_DEBUG_QUERY_HEAPS
| RTL_DEBUG_QUERY_HEAP_BLOCKS
,
601 if (NT_SUCCESS(Status
))
603 Status
= STATUS_NO_MORE_FILES
;
606 i
!= DebugInfo
->Heaps
->NumberOfHeaps
;
609 Heap
= &DebugInfo
->Heaps
->Heaps
[i
];
611 if ((ULONG_PTR
)Heap
->BaseAddress
== lphe
->th32HeapID
)
613 if (++lphe
->dwResvd
< Heap
->NumberOfEntries
)
617 Block
= (PRTLP_HEAP_ENTRY
)Heap
->Entries
+ lphe
->dwResvd
;
618 LastBlock
= (PRTLP_HEAP_ENTRY
)Heap
->Entries
+ Heap
->NumberOfEntries
;
620 while (Block
< LastBlock
&& (Block
->Flags
& PROCESS_HEAP_UNCOMMITTED_RANGE
))
623 lphe
->dwAddress
= (ULONG_PTR
)((ULONG_PTR
)Block
->Address
+ Heap
->EntryOverhead
);
624 FoundUncommitted
= TRUE
;
628 if (Block
< LastBlock
)
630 if (!FoundUncommitted
)
631 lphe
->dwAddress
+= lphe
->dwBlockSize
;
633 lphe
->dwBlockSize
= Block
->Size
;
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
;
642 Status
= STATUS_SUCCESS
;
651 RtlDestroyQueryDebugBuffer(DebugInfo
);
653 if (!NT_SUCCESS(Status
))
655 BaseSetLastNTError(Status
);
669 Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
671 PTH32SNAPSHOT Snapshot
;
672 LARGE_INTEGER SOffset
;
676 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
678 SOffset
.QuadPart
= 0;
682 Status
= NtMapViewOfSection(hSnapshot
,
692 if(NT_SUCCESS(Status
))
696 if(Snapshot
->HeapListCount
> 0)
698 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
699 Snapshot
->HeapListIndex
= 1;
700 RtlCopyMemory(lphl
, &Entries
[0], sizeof(HEAPLIST32
));
705 SetLastError(ERROR_NO_MORE_FILES
);
709 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
713 BaseSetLastNTError(Status
);
723 Heap32ListNext(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
725 PTH32SNAPSHOT Snapshot
;
726 LARGE_INTEGER SOffset
;
730 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
732 SOffset
.QuadPart
= 0;
736 Status
= NtMapViewOfSection(hSnapshot
,
746 if(NT_SUCCESS(Status
))
750 if(Snapshot
->HeapListCount
> 0 &&
751 Snapshot
->HeapListIndex
< Snapshot
->HeapListCount
)
753 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
754 RtlCopyMemory(lphl
, &Entries
[Snapshot
->HeapListIndex
++], sizeof(HEAPLIST32
));
759 SetLastError(ERROR_NO_MORE_FILES
);
763 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
767 BaseSetLastNTError(Status
);
777 Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
782 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
784 me
.dwSize
= sizeof(MODULEENTRY32W
);
786 Ret
= Module32FirstW(hSnapshot
, &me
);
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
;
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);
810 Module32FirstW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
812 PTH32SNAPSHOT Snapshot
;
813 LARGE_INTEGER SOffset
;
817 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
819 SOffset
.QuadPart
= 0;
823 Status
= NtMapViewOfSection(hSnapshot
,
833 if(NT_SUCCESS(Status
))
837 if(Snapshot
->ModuleListCount
> 0)
839 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
840 Snapshot
->ModuleListIndex
= 1;
841 RtlCopyMemory(lpme
, &Entries
[0], sizeof(MODULEENTRY32W
));
846 SetLastError(ERROR_NO_MORE_FILES
);
850 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
854 BaseSetLastNTError(Status
);
864 Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
869 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
871 me
.dwSize
= sizeof(MODULEENTRY32W
);
873 Ret
= Module32NextW(hSnapshot
, &me
);
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
;
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);
897 Module32NextW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
899 PTH32SNAPSHOT Snapshot
;
900 LARGE_INTEGER SOffset
;
904 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
906 SOffset
.QuadPart
= 0;
910 Status
= NtMapViewOfSection(hSnapshot
,
920 if(NT_SUCCESS(Status
))
924 if((Snapshot
->ModuleListCount
> 0) &&
925 (Snapshot
->ModuleListIndex
< Snapshot
->ModuleListCount
))
927 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
928 RtlCopyMemory(lpme
, &Entries
[Snapshot
->ModuleListIndex
++], sizeof(MODULEENTRY32W
));
933 SetLastError(ERROR_NO_MORE_FILES
);
937 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
941 BaseSetLastNTError(Status
);
951 Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
956 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
958 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
960 Ret
= Process32FirstW(hSnapshot
, &pe
);
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
;
972 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
984 Process32FirstW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
986 PTH32SNAPSHOT Snapshot
;
987 LARGE_INTEGER SOffset
;
991 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
993 SOffset
.QuadPart
= 0;
997 Status
= NtMapViewOfSection(hSnapshot
,
1007 if(NT_SUCCESS(Status
))
1011 if(Snapshot
->ProcessListCount
> 0)
1013 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
1015 Snapshot
->ProcessListIndex
= 1;
1016 RtlCopyMemory(lppe
, &Entries
[0], sizeof(PROCESSENTRY32W
));
1022 SetLastError(ERROR_NO_MORE_FILES
);
1026 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1030 BaseSetLastNTError(Status
);
1040 Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
1045 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
1047 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
1049 Ret
= Process32NextW(hSnapshot
, &pe
);
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
;
1061 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
1073 Process32NextW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
1075 PTH32SNAPSHOT Snapshot
;
1076 LARGE_INTEGER SOffset
;
1080 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
1082 SOffset
.QuadPart
= 0;
1086 Status
= NtMapViewOfSection(hSnapshot
,
1096 if(NT_SUCCESS(Status
))
1100 if(Snapshot
->ProcessListCount
> 0 &&
1101 Snapshot
->ProcessListIndex
< Snapshot
->ProcessListCount
)
1103 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
1104 RtlCopyMemory(lppe
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(PROCESSENTRY32W
));
1109 SetLastError(ERROR_NO_MORE_FILES
);
1113 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1117 BaseSetLastNTError(Status
);
1127 Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1129 PTH32SNAPSHOT Snapshot
;
1130 LARGE_INTEGER SOffset
;
1134 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1136 SOffset
.QuadPart
= 0;
1140 Status
= NtMapViewOfSection(hSnapshot
,
1150 if(NT_SUCCESS(Status
))
1154 if(Snapshot
->ThreadListCount
> 0)
1156 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1157 Snapshot
->ThreadListIndex
= 1;
1158 RtlCopyMemory(lpte
, &Entries
[0], sizeof(THREADENTRY32
));
1163 SetLastError(ERROR_NO_MORE_FILES
);
1167 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1171 BaseSetLastNTError(Status
);
1181 Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1183 PTH32SNAPSHOT Snapshot
;
1184 LARGE_INTEGER SOffset
;
1188 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1190 SOffset
.QuadPart
= 0;
1194 Status
= NtMapViewOfSection(hSnapshot
,
1204 if(NT_SUCCESS(Status
))
1208 if(Snapshot
->ThreadListCount
> 0 &&
1209 Snapshot
->ThreadListIndex
< Snapshot
->ThreadListCount
)
1211 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1212 RtlCopyMemory(lpte
, &Entries
[Snapshot
->ThreadListIndex
++], sizeof(THREADENTRY32
));
1217 SetLastError(ERROR_NO_MORE_FILES
);
1221 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1225 BaseSetLastNTError(Status
);
1235 Toolhelp32ReadProcessMemory(DWORD th32ProcessID
, LPCVOID lpBaseAddress
,
1236 LPVOID lpBuffer
, SIZE_T cbRead
, SIZE_T
* lpNumberOfBytesRead
)
1238 HANDLE hProcess
= OpenProcess(PROCESS_VM_READ
, FALSE
, th32ProcessID
);
1239 if(hProcess
!= NULL
)
1241 BOOL Ret
= ReadProcessMemory(hProcess
, lpBaseAddress
, lpBuffer
, cbRead
, lpNumberOfBytesRead
);
1242 CloseHandle(hProcess
);
1255 CreateToolhelp32Snapshot(DWORD dwFlags
, DWORD th32ProcessID
)
1257 PRTL_DEBUG_INFORMATION HeapDebug
, ModuleDebug
;
1259 SIZE_T ProcThrdInfoSize
;
1261 HANDLE hSnapShotSection
= NULL
;
1263 if(th32ProcessID
== 0)
1265 th32ProcessID
= GetCurrentProcessId();
1269 * Get all information required for the snapshot
1271 Status
= TH32CreateSnapshot(dwFlags
,
1277 if(!NT_SUCCESS(Status
))
1279 BaseSetLastNTError(Status
);
1284 * Create a section handle and initialize the collected information
1286 Status
= TH32CreateSnapshotSectionInitialize(dwFlags
,
1294 * Free the temporarily allocated memory which is no longer needed
1296 TH32FreeAllocatedResources(HeapDebug
,
1301 if(!NT_SUCCESS(Status
))
1303 BaseSetLastNTError(Status
);
1307 return hSnapShotSection
;