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)
42 #include "../include/debug.h"
44 /* INTERNAL DEFINITIONS *******************************************************/
46 #define CHECK_PARAM_SIZE(ptr, siz) \
47 if((ptr) == NULL || (ptr)->dwSize != (siz)) \
49 SetLastError(ERROR_INVALID_PARAMETER); \
54 * Tests in win showed that the dwSize field can be greater than the actual size
55 * of the structure for the ansi functions. I found this out by accidently
56 * forgetting to set the dwSize field in a test application and it just didn't
57 * work in ros but in win.
60 #define CHECK_PARAM_SIZEA(ptr, siz) \
61 if((ptr) == NULL || (ptr)->dwSize < (siz)) \
63 SetLastError(ERROR_INVALID_PARAMETER); \
67 #define OffsetToPtr(Snapshot, Offset) \
68 ((ULONG_PTR)((Snapshot) + 1) + (ULONG_PTR)(Offset))
70 typedef struct _TH32SNAPSHOT
75 ULONG_PTR HeapListOffset
;
77 ULONG ModuleListCount
;
78 ULONG ModuleListIndex
;
79 ULONG_PTR ModuleListOffset
;
81 ULONG ProcessListCount
;
82 ULONG ProcessListIndex
;
83 ULONG_PTR ProcessListOffset
;
85 ULONG ThreadListCount
;
86 ULONG ThreadListIndex
;
87 ULONG_PTR ThreadListOffset
;
88 } TH32SNAPSHOT
, *PTH32SNAPSHOT
;
90 /* INTERNAL FUNCTIONS *********************************************************/
93 TH32FreeAllocatedResources(PDEBUG_BUFFER HeapDebug
,
94 PDEBUG_BUFFER ModuleDebug
,
96 ULONG ProcThrdInfoSize
)
100 RtlDestroyQueryDebugBuffer(HeapDebug
);
102 if(ModuleDebug
!= NULL
)
104 RtlDestroyQueryDebugBuffer(ModuleDebug
);
107 if(ProcThrdInfo
!= NULL
)
109 NtFreeVirtualMemory(NtCurrentProcess(),
117 TH32CreateSnapshot(DWORD dwFlags
,
119 PDEBUG_BUFFER
*HeapDebug
,
120 PDEBUG_BUFFER
*ModuleDebug
,
122 ULONG
*ProcThrdInfoSize
)
124 NTSTATUS Status
= STATUS_SUCCESS
;
128 *ProcThrdInfo
= NULL
;
129 *ProcThrdInfoSize
= 0;
132 * Allocate the debug information for a heap snapshot
134 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
136 *HeapDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
137 if(*HeapDebug
!= NULL
)
139 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
144 Status
= STATUS_UNSUCCESSFUL
;
148 * Allocate the debug information for a module snapshot
150 if(dwFlags
& TH32CS_SNAPMODULE
&&
153 *ModuleDebug
= RtlCreateQueryDebugBuffer(0, FALSE
);
154 if(*ModuleDebug
!= NULL
)
156 Status
= RtlQueryProcessDebugInformation(th32ProcessID
,
161 Status
= STATUS_UNSUCCESSFUL
;
165 * Allocate enough memory for the system's process list
168 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
) &&
173 (*ProcThrdInfoSize
) += 0x10000;
174 Status
= NtAllocateVirtualMemory(NtCurrentProcess(),
180 if(!NT_SUCCESS(Status
))
185 Status
= NtQuerySystemInformation(SystemProcessInformation
,
189 if(Status
== STATUS_INFO_LENGTH_MISMATCH
)
191 NtFreeVirtualMemory(NtCurrentProcess(),
195 *ProcThrdInfo
= NULL
;
205 * Free resources in case of failure!
208 if(!NT_SUCCESS(Status
))
210 TH32FreeAllocatedResources(*HeapDebug
,
220 TH32CreateSnapshotSectionInitialize(DWORD dwFlags
,
222 PDEBUG_BUFFER HeapDebug
,
223 PDEBUG_BUFFER ModuleDebug
,
225 HANDLE
*SectionHandle
)
227 PSYSTEM_PROCESS_INFORMATION ProcessInfo
;
228 LPHEAPLIST32 HeapListEntry
;
229 LPMODULEENTRY32W ModuleListEntry
;
230 LPPROCESSENTRY32W ProcessListEntry
;
231 LPTHREADENTRY32 ThreadListEntry
;
232 OBJECT_ATTRIBUTES ObjectAttributes
;
233 LARGE_INTEGER SSize
, SOffset
;
235 PTH32SNAPSHOT Snapshot
;
236 ULONG_PTR DataOffset
;
238 ULONG nProcesses
= 0, nThreads
= 0, nHeaps
= 0, nModules
= 0;
239 ULONG RequiredSnapshotSize
= sizeof(TH32SNAPSHOT
);
240 PHEAP_INFORMATION hi
= NULL
;
241 PMODULE_INFORMATION mi
= NULL
;
242 NTSTATUS Status
= STATUS_SUCCESS
;
245 * Determine the required size for the heap snapshot
247 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
249 hi
= (PHEAP_INFORMATION
)HeapDebug
->HeapInformation
;
250 nHeaps
= hi
->HeapCount
;
251 RequiredSnapshotSize
+= nHeaps
* sizeof(HEAPLIST32
);
255 * Determine the required size for the module snapshot
257 if(dwFlags
& TH32CS_SNAPMODULE
)
259 mi
= (PMODULE_INFORMATION
)ModuleDebug
->ModuleInformation
;
260 nModules
= mi
->ModuleCount
;
261 RequiredSnapshotSize
+= nModules
* sizeof(MODULEENTRY32W
);
265 * Determine the required size for the processes and threads snapshot
267 if(dwFlags
& (TH32CS_SNAPPROCESS
| TH32CS_SNAPTHREAD
))
269 ULONG ProcOffset
= 0;
271 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
274 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
276 nThreads
+= ProcessInfo
->NumberOfThreads
;
277 ProcOffset
= ProcessInfo
->NextEntryOffset
;
278 } while(ProcOffset
!= 0);
280 if(dwFlags
& TH32CS_SNAPPROCESS
)
282 RequiredSnapshotSize
+= nProcesses
* sizeof(PROCESSENTRY32W
);
284 if(dwFlags
& TH32CS_SNAPTHREAD
)
286 RequiredSnapshotSize
+= nThreads
* sizeof(THREADENTRY32
);
291 * Create and map the section
294 SSize
.QuadPart
= RequiredSnapshotSize
;
296 InitializeObjectAttributes(&ObjectAttributes
,
298 ((dwFlags
& TH32CS_INHERIT
) ? OBJ_INHERIT
: 0),
302 Status
= NtCreateSection(&hSection
,
309 if(!NT_SUCCESS(Status
))
314 SOffset
.QuadPart
= 0;
318 Status
= NtMapViewOfSection(hSection
,
328 if(!NT_SUCCESS(Status
))
334 RtlZeroMemory(Snapshot
, sizeof(TH32SNAPSHOT
));
338 * Initialize the section data and fill it with all the data we collected
341 /* initialize the heap list */
342 if(dwFlags
& TH32CS_SNAPHEAPLIST
)
344 Snapshot
->HeapListCount
= nHeaps
;
345 Snapshot
->HeapListOffset
= DataOffset
;
346 HeapListEntry
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, DataOffset
);
347 for(i
= 0; i
< nHeaps
; i
++)
349 HeapListEntry
->dwSize
= sizeof(HEAPLIST32
);
350 HeapListEntry
->th32ProcessID
= th32ProcessID
;
351 HeapListEntry
->th32HeapID
= (ULONG_PTR
)hi
->HeapEntry
[i
].Base
;
352 HeapListEntry
->dwFlags
= hi
->HeapEntry
[i
].Flags
;
357 DataOffset
+= hi
->HeapCount
* sizeof(HEAPLIST32
);
360 /* initialize the module list */
361 if(dwFlags
& TH32CS_SNAPMODULE
)
363 Snapshot
->ModuleListCount
= nModules
;
364 Snapshot
->ModuleListOffset
= DataOffset
;
365 ModuleListEntry
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
366 for(i
= 0; i
< nModules
; i
++)
368 ModuleListEntry
->dwSize
= sizeof(MODULEENTRY32W
);
369 ModuleListEntry
->th32ModuleID
= 1; /* no longer used, always set to one! */
370 ModuleListEntry
->th32ProcessID
= th32ProcessID
;
371 ModuleListEntry
->GlblcntUsage
= mi
->ModuleEntry
[i
].LoadCount
;
372 ModuleListEntry
->ProccntUsage
= mi
->ModuleEntry
[i
].LoadCount
;
373 ModuleListEntry
->modBaseAddr
= (BYTE
*)mi
->ModuleEntry
[i
].Base
;
374 ModuleListEntry
->modBaseSize
= mi
->ModuleEntry
[i
].Size
;
375 ModuleListEntry
->hModule
= (HMODULE
)mi
->ModuleEntry
[i
].Base
;
377 MultiByteToWideChar(CP_ACP
,
379 &mi
->ModuleEntry
[i
].ImageName
[mi
->ModuleEntry
[i
].ModuleNameOffset
],
381 ModuleListEntry
->szModule
,
382 sizeof(ModuleListEntry
->szModule
) / sizeof(ModuleListEntry
->szModule
[0]));
384 MultiByteToWideChar(CP_ACP
,
386 mi
->ModuleEntry
[i
].ImageName
,
388 ModuleListEntry
->szExePath
,
389 sizeof(ModuleListEntry
->szExePath
) / sizeof(ModuleListEntry
->szExePath
[0]));
394 DataOffset
+= mi
->ModuleCount
* sizeof(MODULEENTRY32W
);
397 /* initialize the process list */
398 if(dwFlags
& TH32CS_SNAPPROCESS
)
400 ULONG ProcOffset
= 0;
402 Snapshot
->ProcessListCount
= nProcesses
;
403 Snapshot
->ProcessListOffset
= DataOffset
;
404 ProcessListEntry
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
405 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
408 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
410 ProcessListEntry
->dwSize
= sizeof(PROCESSENTRY32W
);
411 ProcessListEntry
->cntUsage
= 0; /* no longer used */
412 ProcessListEntry
->th32ProcessID
= (ULONG
)ProcessInfo
->UniqueProcessId
;
413 ProcessListEntry
->th32DefaultHeapID
= 0; /* no longer used */
414 ProcessListEntry
->th32ModuleID
= 0; /* no longer used */
415 ProcessListEntry
->cntThreads
= ProcessInfo
->NumberOfThreads
;
416 ProcessListEntry
->th32ParentProcessID
= (ULONG
)ProcessInfo
->InheritedFromUniqueProcessId
;
417 ProcessListEntry
->pcPriClassBase
= ProcessInfo
->BasePriority
;
418 ProcessListEntry
->dwFlags
= 0; /* no longer used */
419 if(ProcessInfo
->ImageName
.Buffer
!= NULL
)
421 lstrcpynW(ProcessListEntry
->szExeFile
,
422 ProcessInfo
->ImageName
.Buffer
,
423 min(ProcessInfo
->ImageName
.Length
/ sizeof(WCHAR
), sizeof(ProcessListEntry
->szExeFile
) / sizeof(ProcessListEntry
->szExeFile
[0])));
427 lstrcpyW(ProcessListEntry
->szExeFile
, L
"[System Process]");
432 ProcOffset
= ProcessInfo
->NextEntryOffset
;
433 } while(ProcOffset
!= 0);
435 DataOffset
+= nProcesses
* sizeof(PROCESSENTRY32W
);
438 /* initialize the thread list */
439 if(dwFlags
& TH32CS_SNAPTHREAD
)
441 ULONG ProcOffset
= 0;
443 Snapshot
->ThreadListCount
= nThreads
;
444 Snapshot
->ThreadListOffset
= DataOffset
;
445 ThreadListEntry
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, DataOffset
);
446 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
449 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
452 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
453 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(ProcessInfo
+ 1);
455 for(n
= 0; n
< ProcessInfo
->NumberOfThreads
; n
++)
457 ThreadListEntry
->dwSize
= sizeof(THREADENTRY32
);
458 ThreadListEntry
->cntUsage
= 0; /* no longer used */
459 ThreadListEntry
->th32ThreadID
= (ULONG
)ThreadInfo
->ClientId
.UniqueThread
;
460 ThreadListEntry
->th32OwnerProcessID
= (ULONG
)ThreadInfo
->ClientId
.UniqueProcess
;
461 ThreadListEntry
->tpBasePri
= ThreadInfo
->BasePriority
;
462 ThreadListEntry
->tpDeltaPri
= 0; /* no longer used */
463 ThreadListEntry
->dwFlags
= 0; /* no longer used */
469 ProcOffset
= ProcessInfo
->NextEntryOffset
;
470 } while(ProcOffset
!= 0);
474 * We're done, unmap the view and return the section handle
477 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
479 if(NT_SUCCESS(Status
))
481 *SectionHandle
= hSection
;
491 /* PUBLIC FUNCTIONS ***********************************************************/
498 Heap32First(LPHEAPENTRY32 lphe
, DWORD th32ProcessID
, DWORD th32HeapID
)
500 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
502 SetLastError(ERROR_NO_MORE_FILES
);
512 Heap32Next(LPHEAPENTRY32 lphe
)
514 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
516 SetLastError(ERROR_NO_MORE_FILES
);
526 Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
528 PTH32SNAPSHOT Snapshot
;
529 LARGE_INTEGER SOffset
;
533 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
535 SOffset
.QuadPart
= 0;
539 Status
= NtMapViewOfSection(hSnapshot
,
549 if(NT_SUCCESS(Status
))
553 if(Snapshot
->ModuleListCount
> 0)
555 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
556 Snapshot
->HeapListIndex
= 1;
557 RtlCopyMemory(lphl
, &Entries
[0], sizeof(HEAPLIST32
));
562 SetLastError(ERROR_NO_MORE_FILES
);
566 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
570 SetLastErrorByStatus(Status
);
580 Heap32ListNext(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
582 PTH32SNAPSHOT Snapshot
;
583 LARGE_INTEGER SOffset
;
587 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
589 SOffset
.QuadPart
= 0;
593 Status
= NtMapViewOfSection(hSnapshot
,
603 if(NT_SUCCESS(Status
))
607 if(Snapshot
->HeapListCount
> 0 &&
608 Snapshot
->HeapListIndex
< Snapshot
->HeapListCount
)
610 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
611 RtlCopyMemory(lphl
, &Entries
[Snapshot
->HeapListIndex
++], sizeof(HEAPLIST32
));
616 SetLastError(ERROR_NO_MORE_FILES
);
620 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
624 SetLastErrorByStatus(Status
);
634 Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
639 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
641 me
.dwSize
= sizeof(MODULEENTRY32W
);
643 Ret
= Module32FirstW(hSnapshot
, &me
);
646 lpme
->th32ModuleID
= me
.th32ModuleID
;
647 lpme
->th32ProcessID
= me
.th32ProcessID
;
648 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
649 lpme
->ProccntUsage
= me
.ProccntUsage
;
650 lpme
->modBaseAddr
= me
.modBaseAddr
;
651 lpme
->modBaseSize
= me
.modBaseSize
;
652 lpme
->hModule
= me
.hModule
;
654 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
655 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
667 Module32FirstW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
669 PTH32SNAPSHOT Snapshot
;
670 LARGE_INTEGER SOffset
;
674 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
676 SOffset
.QuadPart
= 0;
680 Status
= NtMapViewOfSection(hSnapshot
,
690 if(NT_SUCCESS(Status
))
694 if(Snapshot
->ModuleListCount
> 0)
696 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
697 Snapshot
->ModuleListIndex
= 1;
698 RtlCopyMemory(lpme
, &Entries
[0], sizeof(MODULEENTRY32W
));
703 SetLastError(ERROR_NO_MORE_FILES
);
707 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
711 SetLastErrorByStatus(Status
);
721 Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
726 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
728 me
.dwSize
= sizeof(MODULEENTRY32W
);
730 Ret
= Module32NextW(hSnapshot
, &me
);
733 lpme
->th32ModuleID
= me
.th32ModuleID
;
734 lpme
->th32ProcessID
= me
.th32ProcessID
;
735 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
736 lpme
->ProccntUsage
= me
.ProccntUsage
;
737 lpme
->modBaseAddr
= me
.modBaseAddr
;
738 lpme
->modBaseSize
= me
.modBaseSize
;
739 lpme
->hModule
= me
.hModule
;
741 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
742 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
754 Module32NextW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
756 PTH32SNAPSHOT Snapshot
;
757 LARGE_INTEGER SOffset
;
761 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
763 SOffset
.QuadPart
= 0;
767 Status
= NtMapViewOfSection(hSnapshot
,
777 if(NT_SUCCESS(Status
))
781 if(Snapshot
->ModuleListCount
> 0 &&
782 Snapshot
->ModuleListIndex
< Snapshot
->ModuleListCount
)
784 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
785 RtlCopyMemory(lpme
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(MODULEENTRY32W
));
790 SetLastError(ERROR_NO_MORE_FILES
);
794 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
798 SetLastErrorByStatus(Status
);
808 Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
813 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
815 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
817 Ret
= Process32FirstW(hSnapshot
, &pe
);
820 lppe
->cntUsage
= pe
.cntUsage
;
821 lppe
->th32ProcessID
= pe
.th32ProcessID
;
822 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
823 lppe
->th32ModuleID
= pe
.th32ModuleID
;
824 lppe
->cntThreads
= pe
.cntThreads
;
825 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
826 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
827 lppe
->dwFlags
= pe
.dwFlags
;
829 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
841 Process32FirstW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
843 PTH32SNAPSHOT Snapshot
;
844 LARGE_INTEGER SOffset
;
848 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
850 SOffset
.QuadPart
= 0;
854 Status
= NtMapViewOfSection(hSnapshot
,
864 if(NT_SUCCESS(Status
))
868 if(Snapshot
->ProcessListCount
> 0)
870 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
872 Snapshot
->ProcessListIndex
= 1;
873 RtlCopyMemory(lppe
, &Entries
[0], sizeof(PROCESSENTRY32W
));
879 SetLastError(ERROR_NO_MORE_FILES
);
883 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
887 SetLastErrorByStatus(Status
);
897 Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
902 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
904 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
906 Ret
= Process32NextW(hSnapshot
, &pe
);
909 lppe
->cntUsage
= pe
.cntUsage
;
910 lppe
->th32ProcessID
= pe
.th32ProcessID
;
911 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
912 lppe
->th32ModuleID
= pe
.th32ModuleID
;
913 lppe
->cntThreads
= pe
.cntThreads
;
914 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
915 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
916 lppe
->dwFlags
= pe
.dwFlags
;
918 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
930 Process32NextW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
932 PTH32SNAPSHOT Snapshot
;
933 LARGE_INTEGER SOffset
;
937 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
939 SOffset
.QuadPart
= 0;
943 Status
= NtMapViewOfSection(hSnapshot
,
953 if(NT_SUCCESS(Status
))
957 if(Snapshot
->ProcessListCount
> 0 &&
958 Snapshot
->ProcessListIndex
< Snapshot
->ProcessListCount
)
960 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
961 RtlCopyMemory(lppe
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(PROCESSENTRY32W
));
966 SetLastError(ERROR_NO_MORE_FILES
);
970 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
974 SetLastErrorByStatus(Status
);
984 Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
986 PTH32SNAPSHOT Snapshot
;
987 LARGE_INTEGER SOffset
;
991 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
993 SOffset
.QuadPart
= 0;
997 Status
= NtMapViewOfSection(hSnapshot
,
1007 if(NT_SUCCESS(Status
))
1011 if(Snapshot
->ThreadListCount
> 0)
1013 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1014 Snapshot
->ThreadListIndex
= 1;
1015 RtlCopyMemory(lpte
, &Entries
[0], sizeof(THREADENTRY32
));
1020 SetLastError(ERROR_NO_MORE_FILES
);
1024 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1028 SetLastErrorByStatus(Status
);
1038 Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1040 PTH32SNAPSHOT Snapshot
;
1041 LARGE_INTEGER SOffset
;
1045 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1047 SOffset
.QuadPart
= 0;
1051 Status
= NtMapViewOfSection(hSnapshot
,
1061 if(NT_SUCCESS(Status
))
1065 if(Snapshot
->ThreadListCount
> 0 &&
1066 Snapshot
->ThreadListIndex
< Snapshot
->ThreadListCount
)
1068 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1069 RtlCopyMemory(lpte
, &Entries
[Snapshot
->ThreadListIndex
++], sizeof(THREADENTRY32
));
1074 SetLastError(ERROR_NO_MORE_FILES
);
1078 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1082 SetLastErrorByStatus(Status
);
1092 Toolhelp32ReadProcessMemory(DWORD th32ProcessID
, LPCVOID lpBaseAddress
,
1093 LPVOID lpBuffer
, DWORD cbRead
, LPDWORD lpNumberOfBytesRead
)
1095 HANDLE hProcess
= OpenProcess(PROCESS_VM_READ
, FALSE
, th32ProcessID
);
1096 if(hProcess
!= NULL
)
1098 BOOL Ret
= ReadProcessMemory(hProcess
, lpBaseAddress
, lpBuffer
, cbRead
, lpNumberOfBytesRead
);
1099 CloseHandle(hProcess
);
1112 CreateToolhelp32Snapshot(DWORD dwFlags
, DWORD th32ProcessID
)
1114 PDEBUG_BUFFER HeapDebug
, ModuleDebug
;
1116 ULONG ProcThrdInfoSize
;
1117 HANDLE hSnapShotSection
;
1120 if(th32ProcessID
== 0)
1122 th32ProcessID
= GetCurrentProcessId();
1126 * Get all information required for the snapshot
1128 Status
= TH32CreateSnapshot(dwFlags
,
1134 if(!NT_SUCCESS(Status
))
1136 SetLastErrorByStatus(Status
);
1141 * Create a section handle and initialize the collected information
1143 Status
= TH32CreateSnapshotSectionInitialize(dwFlags
,
1151 * Free the temporarily allocated memory which is no longer needed
1153 TH32FreeAllocatedResources(HeapDebug
,
1158 if(!NT_SUCCESS(Status
))
1160 SetLastErrorByStatus(Status
);
1164 return hSnapShotSection
;