3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * KERNEL32.DLL toolhelp functions
23 * COPYRIGHT: See COPYING in the top level directory
24 * PROJECT: ReactOS system libraries
25 * FILE: lib/kernel32/misc/toolhelp.c
26 * PURPOSE: Toolhelp functions
27 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
28 * Robert Dickenson (robd@mok.lvcm.com)
30 * NOTES: Do NOT use the heap functions in here because they
31 * adulterate the heap statistics!
34 * 10/30/2004 Implemented some parts (w3)
35 * Inspired by the book "Windows NT Native API"
36 * Created 05 January 2003 (robd)
44 #include "../include/debug.h"
46 /* INTERNAL DEFINITIONS *******************************************************/
48 #define CHECK_PARAM_SIZE(ptr, siz) \
49 if((ptr) == NULL || (ptr)->dwSize != (siz)) \
51 SetLastError(ERROR_INVALID_PARAMETER); \
56 * Tests in win showed that the dwSize field can be greater than the actual size
57 * of the structure for the ansi functions. I found this out by accidently
58 * forgetting to set the dwSize field in a test application and it just didn't
59 * work in ros but in win.
62 #define CHECK_PARAM_SIZEA(ptr, siz) \
63 if((ptr) == NULL || (ptr)->dwSize < (siz)) \
65 SetLastError(ERROR_INVALID_PARAMETER); \
69 #define OffsetToPtr(Snapshot, Offset) \
70 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
72 typedef struct _TH32SNAPSHOT
77 ULONG_PTR HeapListOffset
;
79 ULONG ModuleListCount
;
80 ULONG ModuleListIndex
;
81 ULONG_PTR ModuleListOffset
;
83 ULONG ProcessListCount
;
84 ULONG ProcessListIndex
;
85 ULONG_PTR ProcessListOffset
;
87 ULONG ThreadListCount
;
88 ULONG ThreadListIndex
;
89 ULONG_PTR ThreadListOffset
;
90 } TH32SNAPSHOT
, *PTH32SNAPSHOT
;
92 /* INTERNAL FUNCTIONS *********************************************************/
95 TH32FreeAllocatedResources(PRTL_DEBUG_BUFFER HeapDebug
,
96 PRTL_DEBUG_BUFFER ModuleDebug
,
98 SIZE_T ProcThrdInfoSize
)
100 if(HeapDebug
!= NULL
)
102 RtlDestroyQueryDebugBuffer(HeapDebug
);
104 if(ModuleDebug
!= NULL
)
106 RtlDestroyQueryDebugBuffer(ModuleDebug
);
109 if(ProcThrdInfo
!= NULL
)
111 NtFreeVirtualMemory(NtCurrentProcess(),
119 TH32CreateSnapshot(DWORD dwFlags
,
121 PRTL_DEBUG_BUFFER
*HeapDebug
,
122 PRTL_DEBUG_BUFFER
*ModuleDebug
,
124 SIZE_T
*ProcThrdInfoSize
)
126 NTSTATUS Status
= STATUS_SUCCESS
;
130 *ProcThrdInfo
= NULL
;
131 *ProcThrdInfoSize
= 0;
134 * Allocate the debug information for a heap snapshot
136 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
138 *HeapDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
139 if(*HeapDebug
!= NULL
)
141 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
142 RTL_DEBUG_QUERY_HEAPS
,
146 Status
= STATUS_UNSUCCESSFUL
;
150 * Allocate the debug information for a module snapshot
152 if(dwFlags
& TH32CS_SNAPMODULE
&&
155 *ModuleDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
156 if(*ModuleDebug
!= NULL
)
158 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
159 RTL_DEBUG_QUERY_MODULES
,
163 Status
= STATUS_UNSUCCESSFUL
;
167 * Allocate enough memory for the system's process list
170 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
) &&
175 (*ProcThrdInfoSize
) += 0x10000;
176 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
182 if(!NT_SUCCESS(Status
))
187 Status
= NtQuerySystemInformation(SystemProcessInformation
,
191 if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
193 NtFreeVirtualMemory(NtCurrentProcess(),
197 *ProcThrdInfo
= NULL
;
207 * Free resources in case of failure!
210 if(!NT_SUCCESS(Status
))
212 TH32FreeAllocatedResources(*HeapDebug
,
222 TH32CreateSnapshotSectionInitialize(DWORD dwFlags
,
224 PRTL_DEBUG_BUFFER HeapDebug
,
225 PRTL_DEBUG_BUFFER ModuleDebug
,
227 HANDLE
*SectionHandle
)
229 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
230 LPHEAPLIST32 HeapListEntry
;
231 LPMODULEENTRY32W ModuleListEntry
;
232 LPPROCESSENTRY32W ProcessListEntry
;
233 LPTHREADENTRY32 ThreadListEntry
;
234 OBJECT_ATTRIBUTES ObjectAttributes
;
235 LARGE_INTEGER SSize
, SOffset
;
237 PTH32SNAPSHOT Snapshot
;
238 ULONG_PTR DataOffset
;
240 ULONG nProcesses
= 0, nThreads
= 0, nHeaps
= 0, nModules
= 0;
241 ULONG RequiredSnapshotSize
= sizeof(TH32SNAPSHOT
);
242 PRTL_PROCESS_HEAPS hi
= NULL
;
243 PRTL_PROCESS_MODULES mi
= NULL
;
244 NTSTATUS Status
= STATUS_SUCCESS
;
247 * Determine the required size for the heap snapshot
249 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
251 hi
= (PRTL_PROCESS_HEAPS
)HeapDebug
->HeapInformation
;
252 nHeaps
= hi
->HeapCount
;
253 RequiredSnapshotSize
+= nHeaps
* sizeof(HEAPLIST32
);
257 * Determine the required size for the module snapshot
259 if(dwFlags
& TH32CS_SNAPMODULE
)
261 mi
= (PRTL_PROCESS_MODULES
)ModuleDebug
->ModuleInformation
;
262 nModules
= mi
->ModuleCount
;
263 RequiredSnapshotSize
+= nModules
* sizeof(MODULEENTRY32W
);
267 * Determine the required size for the processes and threads snapshot
269 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
))
271 ULONG ProcOffset
= 0;
273 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
276 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
278 nThreads
+= ProcessInfo
->NumberOfThreads
;
279 ProcOffset
= ProcessInfo
->NextEntryOffset
;
280 } while(ProcOffset
!= 0);
282 if(dwFlags
& TH32CS_SNAPPROCESS
)
284 RequiredSnapshotSize
+= nProcesses
* sizeof(PROCESSENTRY32W
);
286 if(dwFlags
& TH32CS_SNAPTHREAD
)
288 RequiredSnapshotSize
+= nThreads
* sizeof(THREADENTRY32
);
293 * Create and map the section
296 SSize
.QuadPart
= RequiredSnapshotSize
;
298 InitializeObjectAttributes(&ObjectAttributes
,
300 ((dwFlags
& TH32CS_INHERIT
) ? OBJ_INHERIT
: 0),
304 Status
= NtCreateSection(&hSection
,
311 if(!NT_SUCCESS(Status
))
316 SOffset
.QuadPart
= 0;
320 Status
= NtMapViewOfSection(hSection
,
330 if(!NT_SUCCESS(Status
))
336 RtlZeroMemory(Snapshot
, sizeof(TH32SNAPSHOT
));
340 * Initialize the section data and fill it with all the data we collected
343 /* initialize the heap list */
344 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
346 Snapshot
->HeapListCount
= nHeaps
;
347 Snapshot
->HeapListOffset
= DataOffset
;
348 HeapListEntry
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, DataOffset
);
349 for(i
= 0; i
< nHeaps
; i
++)
351 HeapListEntry
->dwSize
= sizeof(HEAPLIST32
);
352 HeapListEntry
->th32ProcessID
= th32ProcessID
;
353 HeapListEntry
->th32HeapID
= (ULONG_PTR
)hi
->HeapEntry
[i
].Base
;
354 HeapListEntry
->dwFlags
= hi
->HeapEntry
[i
].Flags
;
359 DataOffset
+= hi
->HeapCount
* sizeof(HEAPLIST32
);
362 /* initialize the module list */
363 if(dwFlags
& TH32CS_SNAPMODULE
)
365 Snapshot
->ModuleListCount
= nModules
;
366 Snapshot
->ModuleListOffset
= DataOffset
;
367 ModuleListEntry
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
368 for(i
= 0; i
< nModules
; i
++)
370 ModuleListEntry
->dwSize
= sizeof(MODULEENTRY32W
);
371 ModuleListEntry
->th32ModuleID
= 1; /* no longer used, always set to one! */
372 ModuleListEntry
->th32ProcessID
= th32ProcessID
;
373 ModuleListEntry
->GlblcntUsage
= mi
->ModuleEntry
[i
].LoadCount
;
374 ModuleListEntry
->ProccntUsage
= mi
->ModuleEntry
[i
].LoadCount
;
375 ModuleListEntry
->modBaseAddr
= (BYTE
*)mi
->ModuleEntry
[i
].Base
;
376 ModuleListEntry
->modBaseSize
= mi
->ModuleEntry
[i
].Size
;
377 ModuleListEntry
->hModule
= (HMODULE
)mi
->ModuleEntry
[i
].Base
;
379 MultiByteToWideChar(CP_ACP
,
381 &mi
->ModuleEntry
[i
].ImageName
[mi
->ModuleEntry
[i
].ModuleNameOffset
],
383 ModuleListEntry
->szModule
,
384 sizeof(ModuleListEntry
->szModule
) / sizeof(ModuleListEntry
->szModule
[0]));
386 MultiByteToWideChar(CP_ACP
,
388 mi
->ModuleEntry
[i
].ImageName
,
390 ModuleListEntry
->szExePath
,
391 sizeof(ModuleListEntry
->szExePath
) / sizeof(ModuleListEntry
->szExePath
[0]));
396 DataOffset
+= mi
->ModuleCount
* sizeof(MODULEENTRY32W
);
399 /* initialize the process list */
400 if(dwFlags
& TH32CS_SNAPPROCESS
)
402 ULONG ProcOffset
= 0;
404 Snapshot
->ProcessListCount
= nProcesses
;
405 Snapshot
->ProcessListOffset
= DataOffset
;
406 ProcessListEntry
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
407 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
410 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
412 ProcessListEntry
->dwSize
= sizeof(PROCESSENTRY32W
);
413 ProcessListEntry
->cntUsage
= 0; /* no longer used */
414 ProcessListEntry
->th32ProcessID
= (ULONG
)ProcessInfo
->UniqueProcessId
;
415 ProcessListEntry
->th32DefaultHeapID
= 0; /* no longer used */
416 ProcessListEntry
->th32ModuleID
= 0; /* no longer used */
417 ProcessListEntry
->cntThreads
= ProcessInfo
->NumberOfThreads
;
418 ProcessListEntry
->th32ParentProcessID
= (ULONG
)ProcessInfo
->InheritedFromUniqueProcessId
;
419 ProcessListEntry
->pcPriClassBase
= ProcessInfo
->BasePriority
;
420 ProcessListEntry
->dwFlags
= 0; /* no longer used */
421 if(ProcessInfo
->ImageName
.Buffer
!= NULL
)
423 lstrcpynW(ProcessListEntry
->szExeFile
,
424 ProcessInfo
->ImageName
.Buffer
,
425 min(ProcessInfo
->ImageName
.Length
/ sizeof(WCHAR
), sizeof(ProcessListEntry
->szExeFile
) / sizeof(ProcessListEntry
->szExeFile
[0])));
429 lstrcpyW(ProcessListEntry
->szExeFile
, L
"[System Process]");
434 ProcOffset
= ProcessInfo
->NextEntryOffset
;
435 } while(ProcOffset
!= 0);
437 DataOffset
+= nProcesses
* sizeof(PROCESSENTRY32W
);
440 /* initialize the thread list */
441 if(dwFlags
& TH32CS_SNAPTHREAD
)
443 ULONG ProcOffset
= 0;
445 Snapshot
->ThreadListCount
= nThreads
;
446 Snapshot
->ThreadListOffset
= DataOffset
;
447 ThreadListEntry
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, DataOffset
);
448 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
451 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
454 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
455 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(ProcessInfo
+ 1);
457 for(n
= 0; n
< ProcessInfo
->NumberOfThreads
; n
++)
459 ThreadListEntry
->dwSize
= sizeof(THREADENTRY32
);
460 ThreadListEntry
->cntUsage
= 0; /* no longer used */
461 ThreadListEntry
->th32ThreadID
= (ULONG
)ThreadInfo
->ClientId
.UniqueThread
;
462 ThreadListEntry
->th32OwnerProcessID
= (ULONG
)ThreadInfo
->ClientId
.UniqueProcess
;
463 ThreadListEntry
->tpBasePri
= ThreadInfo
->BasePriority
;
464 ThreadListEntry
->tpDeltaPri
= 0; /* no longer used */
465 ThreadListEntry
->dwFlags
= 0; /* no longer used */
471 ProcOffset
= ProcessInfo
->NextEntryOffset
;
472 } while(ProcOffset
!= 0);
476 * We're done, unmap the view and return the section handle
479 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
481 if(NT_SUCCESS(Status
))
483 *SectionHandle
= hSection
;
493 /* PUBLIC FUNCTIONS ***********************************************************/
500 Heap32First(LPHEAPENTRY32 lphe
, DWORD th32ProcessID
, DWORD th32HeapID
)
502 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
504 SetLastError(ERROR_NO_MORE_FILES
);
514 Heap32Next(LPHEAPENTRY32 lphe
)
516 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
518 SetLastError(ERROR_NO_MORE_FILES
);
528 Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
530 PTH32SNAPSHOT Snapshot
;
531 LARGE_INTEGER SOffset
;
535 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
537 SOffset
.QuadPart
= 0;
541 Status
= NtMapViewOfSection(hSnapshot
,
551 if(NT_SUCCESS(Status
))
555 if(Snapshot
->HeapListCount
> 0)
557 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
558 Snapshot
->HeapListIndex
= 1;
559 RtlCopyMemory(lphl
, &Entries
[0], sizeof(HEAPLIST32
));
564 SetLastError(ERROR_NO_MORE_FILES
);
568 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
572 SetLastErrorByStatus(Status
);
582 Heap32ListNext(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
584 PTH32SNAPSHOT Snapshot
;
585 LARGE_INTEGER SOffset
;
589 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
591 SOffset
.QuadPart
= 0;
595 Status
= NtMapViewOfSection(hSnapshot
,
605 if(NT_SUCCESS(Status
))
609 if(Snapshot
->HeapListCount
> 0 &&
610 Snapshot
->HeapListIndex
< Snapshot
->HeapListCount
)
612 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
613 RtlCopyMemory(lphl
, &Entries
[Snapshot
->HeapListIndex
++], sizeof(HEAPLIST32
));
618 SetLastError(ERROR_NO_MORE_FILES
);
622 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
626 SetLastErrorByStatus(Status
);
636 Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
641 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
643 me
.dwSize
= sizeof(MODULEENTRY32W
);
645 Ret
= Module32FirstW(hSnapshot
, &me
);
648 lpme
->th32ModuleID
= me
.th32ModuleID
;
649 lpme
->th32ProcessID
= me
.th32ProcessID
;
650 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
651 lpme
->ProccntUsage
= me
.ProccntUsage
;
652 lpme
->modBaseAddr
= me
.modBaseAddr
;
653 lpme
->modBaseSize
= me
.modBaseSize
;
654 lpme
->hModule
= me
.hModule
;
656 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
657 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
669 Module32FirstW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
671 PTH32SNAPSHOT Snapshot
;
672 LARGE_INTEGER SOffset
;
676 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
678 SOffset
.QuadPart
= 0;
682 Status
= NtMapViewOfSection(hSnapshot
,
692 if(NT_SUCCESS(Status
))
696 if(Snapshot
->ModuleListCount
> 0)
698 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
699 Snapshot
->ModuleListIndex
= 1;
700 RtlCopyMemory(lpme
, &Entries
[0], sizeof(MODULEENTRY32W
));
705 SetLastError(ERROR_NO_MORE_FILES
);
709 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
713 SetLastErrorByStatus(Status
);
723 Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
728 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
730 me
.dwSize
= sizeof(MODULEENTRY32W
);
732 Ret
= Module32NextW(hSnapshot
, &me
);
735 lpme
->th32ModuleID
= me
.th32ModuleID
;
736 lpme
->th32ProcessID
= me
.th32ProcessID
;
737 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
738 lpme
->ProccntUsage
= me
.ProccntUsage
;
739 lpme
->modBaseAddr
= me
.modBaseAddr
;
740 lpme
->modBaseSize
= me
.modBaseSize
;
741 lpme
->hModule
= me
.hModule
;
743 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
744 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
756 Module32NextW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
758 PTH32SNAPSHOT Snapshot
;
759 LARGE_INTEGER SOffset
;
763 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
765 SOffset
.QuadPart
= 0;
769 Status
= NtMapViewOfSection(hSnapshot
,
779 if(NT_SUCCESS(Status
))
783 if(Snapshot
->ModuleListCount
> 0 &&
784 Snapshot
->ModuleListIndex
< Snapshot
->ModuleListCount
)
786 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
787 RtlCopyMemory(lpme
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(MODULEENTRY32W
));
792 SetLastError(ERROR_NO_MORE_FILES
);
796 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
800 SetLastErrorByStatus(Status
);
810 Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
815 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
817 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
819 Ret
= Process32FirstW(hSnapshot
, &pe
);
822 lppe
->cntUsage
= pe
.cntUsage
;
823 lppe
->th32ProcessID
= pe
.th32ProcessID
;
824 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
825 lppe
->th32ModuleID
= pe
.th32ModuleID
;
826 lppe
->cntThreads
= pe
.cntThreads
;
827 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
828 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
829 lppe
->dwFlags
= pe
.dwFlags
;
831 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
843 Process32FirstW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
845 PTH32SNAPSHOT Snapshot
;
846 LARGE_INTEGER SOffset
;
850 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
852 SOffset
.QuadPart
= 0;
856 Status
= NtMapViewOfSection(hSnapshot
,
866 if(NT_SUCCESS(Status
))
870 if(Snapshot
->ProcessListCount
> 0)
872 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
874 Snapshot
->ProcessListIndex
= 1;
875 RtlCopyMemory(lppe
, &Entries
[0], sizeof(PROCESSENTRY32W
));
881 SetLastError(ERROR_NO_MORE_FILES
);
885 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
889 SetLastErrorByStatus(Status
);
899 Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
904 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
906 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
908 Ret
= Process32NextW(hSnapshot
, &pe
);
911 lppe
->cntUsage
= pe
.cntUsage
;
912 lppe
->th32ProcessID
= pe
.th32ProcessID
;
913 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
914 lppe
->th32ModuleID
= pe
.th32ModuleID
;
915 lppe
->cntThreads
= pe
.cntThreads
;
916 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
917 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
918 lppe
->dwFlags
= pe
.dwFlags
;
920 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
932 Process32NextW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
934 PTH32SNAPSHOT Snapshot
;
935 LARGE_INTEGER SOffset
;
939 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
941 SOffset
.QuadPart
= 0;
945 Status
= NtMapViewOfSection(hSnapshot
,
955 if(NT_SUCCESS(Status
))
959 if(Snapshot
->ProcessListCount
> 0 &&
960 Snapshot
->ProcessListIndex
< Snapshot
->ProcessListCount
)
962 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
963 RtlCopyMemory(lppe
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(PROCESSENTRY32W
));
968 SetLastError(ERROR_NO_MORE_FILES
);
972 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
976 SetLastErrorByStatus(Status
);
986 Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
988 PTH32SNAPSHOT Snapshot
;
989 LARGE_INTEGER SOffset
;
993 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
995 SOffset
.QuadPart
= 0;
999 Status
= NtMapViewOfSection(hSnapshot
,
1009 if(NT_SUCCESS(Status
))
1013 if(Snapshot
->ThreadListCount
> 0)
1015 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1016 Snapshot
->ThreadListIndex
= 1;
1017 RtlCopyMemory(lpte
, &Entries
[0], sizeof(THREADENTRY32
));
1022 SetLastError(ERROR_NO_MORE_FILES
);
1026 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1030 SetLastErrorByStatus(Status
);
1040 Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1042 PTH32SNAPSHOT Snapshot
;
1043 LARGE_INTEGER SOffset
;
1047 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1049 SOffset
.QuadPart
= 0;
1053 Status
= NtMapViewOfSection(hSnapshot
,
1063 if(NT_SUCCESS(Status
))
1067 if(Snapshot
->ThreadListCount
> 0 &&
1068 Snapshot
->ThreadListIndex
< Snapshot
->ThreadListCount
)
1070 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1071 RtlCopyMemory(lpte
, &Entries
[Snapshot
->ThreadListIndex
++], sizeof(THREADENTRY32
));
1076 SetLastError(ERROR_NO_MORE_FILES
);
1080 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1084 SetLastErrorByStatus(Status
);
1094 Toolhelp32ReadProcessMemory(DWORD th32ProcessID
, LPCVOID lpBaseAddress
,
1095 LPVOID lpBuffer
, DWORD cbRead
, LPDWORD lpNumberOfBytesRead
)
1097 HANDLE hProcess
= OpenProcess(PROCESS_VM_READ
, FALSE
, th32ProcessID
);
1098 if(hProcess
!= NULL
)
1100 BOOL Ret
= ReadProcessMemory(hProcess
, lpBaseAddress
, lpBuffer
, cbRead
, lpNumberOfBytesRead
);
1101 CloseHandle(hProcess
);
1114 CreateToolhelp32Snapshot(DWORD dwFlags
, DWORD th32ProcessID
)
1116 PRTL_DEBUG_BUFFER HeapDebug
, ModuleDebug
;
1118 SIZE_T ProcThrdInfoSize
;
1120 HANDLE hSnapShotSection
= NULL
;
1122 if(th32ProcessID
== 0)
1124 th32ProcessID
= GetCurrentProcessId();
1128 * Get all information required for the snapshot
1130 Status
= TH32CreateSnapshot(dwFlags
,
1136 if(!NT_SUCCESS(Status
))
1138 SetLastErrorByStatus(Status
);
1143 * Create a section handle and initialize the collected information
1145 Status
= TH32CreateSnapshotSectionInitialize(dwFlags
,
1153 * Free the temporarily allocated memory which is no longer needed
1155 TH32FreeAllocatedResources(HeapDebug
,
1160 if(!NT_SUCCESS(Status
))
1162 SetLastErrorByStatus(Status
);
1166 return hSnapShotSection
;