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.
19 /* $Id: toolhelp.c,v 1.8 2004/10/31 19:24:31 weiden Exp $
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
= 0; /* FIXME - use the base address of the heap we're iterating */
352 HeapListEntry
->dwFlags
= 0; /* FIXME - use the flags of the heap we're iterating */
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
->th32ProcessID
= th32ProcessID
;
371 /* FIXME - fill the MODULEENTRY32W structure */
376 DataOffset
+= mi
->ModuleCount
* sizeof(MODULEENTRY32W
);
379 /* initialize the process list */
380 if(dwFlags
& TH32CS_SNAPPROCESS
)
382 ULONG ProcOffset
= 0;
384 Snapshot
->ProcessListCount
= nProcesses
;
385 Snapshot
->ProcessListOffset
= DataOffset
;
386 ProcessListEntry
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, DataOffset
);
387 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
390 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
392 ProcessListEntry
->dwSize
= sizeof(PROCESSENTRY32W
);
393 ProcessListEntry
->cntUsage
= 0; /* no longer used */
394 ProcessListEntry
->th32ProcessID
= (ULONG
)ProcessInfo
->UniqueProcessId
;
395 ProcessListEntry
->th32DefaultHeapID
= 0; /* no longer used */
396 ProcessListEntry
->th32ModuleID
= 0; /* no longer used */
397 ProcessListEntry
->cntThreads
= ProcessInfo
->NumberOfThreads
;
398 ProcessListEntry
->th32ParentProcessID
= (ULONG
)ProcessInfo
->InheritedFromUniqueProcessId
;
399 ProcessListEntry
->pcPriClassBase
= ProcessInfo
->BasePriority
;
400 ProcessListEntry
->dwFlags
= 0; /* no longer used */
401 if(ProcessInfo
->ImageName
.Buffer
!= NULL
)
403 lstrcpynW(ProcessListEntry
->szExeFile
,
404 ProcessInfo
->ImageName
.Buffer
,
405 min(ProcessInfo
->ImageName
.Length
, sizeof(ProcessListEntry
->szExeFile
) / sizeof(ProcessListEntry
->szExeFile
[0])));
409 lstrcpyW(ProcessListEntry
->szExeFile
, L
"[System Process]");
414 ProcOffset
= ProcessInfo
->NextEntryOffset
;
415 } while(ProcOffset
!= 0);
417 DataOffset
+= nProcesses
* sizeof(PROCESSENTRY32W
);
420 /* initialize the thread list */
421 if(dwFlags
& TH32CS_SNAPTHREAD
)
423 ULONG ProcOffset
= 0;
425 Snapshot
->ThreadListCount
= nThreads
;
426 Snapshot
->ThreadListOffset
= DataOffset
;
427 ThreadListEntry
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, DataOffset
);
428 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
431 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
434 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
435 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(ProcessInfo
+ 1);
437 for(n
= 0; n
< ProcessInfo
->NumberOfThreads
; n
++)
439 ThreadListEntry
->dwSize
= sizeof(THREADENTRY32
);
440 ThreadListEntry
->cntUsage
= 0; /* no longer used */
441 ThreadListEntry
->th32ThreadID
= (ULONG
)ThreadInfo
->ClientId
.UniqueThread
;
442 ThreadListEntry
->th32OwnerProcessID
= (ULONG
)ThreadInfo
->ClientId
.UniqueProcess
;
443 ThreadListEntry
->tpBasePri
= ThreadInfo
->BasePriority
;
444 ThreadListEntry
->tpDeltaPri
= 0; /* no longer used */
445 ThreadListEntry
->dwFlags
= 0; /* no longer used */
451 ProcOffset
= ProcessInfo
->NextEntryOffset
;
452 } while(ProcOffset
!= 0);
456 * We're done, unmap the view and return the section handle
459 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
461 if(NT_SUCCESS(Status
))
463 *SectionHandle
= hSection
;
473 /* PUBLIC FUNCTIONS ***********************************************************/
480 Heap32First(LPHEAPENTRY32 lphe
, DWORD th32ProcessID
, DWORD th32HeapID
)
482 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
484 SetLastError(ERROR_NO_MORE_FILES
);
494 Heap32Next(LPHEAPENTRY32 lphe
)
496 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
498 SetLastError(ERROR_NO_MORE_FILES
);
508 Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
510 PTH32SNAPSHOT Snapshot
;
511 LARGE_INTEGER SOffset
;
515 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
517 SOffset
.QuadPart
= 0;
521 Status
= NtMapViewOfSection(hSnapshot
,
531 if(NT_SUCCESS(Status
))
535 if(Snapshot
->ModuleListCount
> 0)
537 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
538 Snapshot
->HeapListIndex
= 1;
539 RtlCopyMemory(lphl
, &Entries
[0], sizeof(HEAPLIST32
));
544 SetLastError(ERROR_NO_MORE_FILES
);
548 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
552 SetLastErrorByStatus(Status
);
562 Heap32ListNext(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
564 PTH32SNAPSHOT Snapshot
;
565 LARGE_INTEGER SOffset
;
569 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
571 SOffset
.QuadPart
= 0;
575 Status
= NtMapViewOfSection(hSnapshot
,
585 if(NT_SUCCESS(Status
))
589 if(Snapshot
->HeapListCount
> 0 &&
590 Snapshot
->HeapListIndex
< Snapshot
->HeapListCount
)
592 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
593 RtlCopyMemory(lphl
, &Entries
[Snapshot
->HeapListIndex
++], sizeof(HEAPLIST32
));
598 SetLastError(ERROR_NO_MORE_FILES
);
602 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
606 SetLastErrorByStatus(Status
);
616 Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
621 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
623 me
.dwSize
= sizeof(MODULEENTRY32W
);
625 Ret
= Module32FirstW(hSnapshot
, &me
);
628 lpme
->th32ModuleID
= me
.th32ModuleID
;
629 lpme
->th32ProcessID
= me
.th32ProcessID
;
630 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
631 lpme
->ProccntUsage
= me
.ProccntUsage
;
632 lpme
->modBaseAddr
= me
.modBaseAddr
;
633 lpme
->modBaseSize
= me
.modBaseSize
;
634 lpme
->hModule
= me
.hModule
;
636 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
637 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
649 Module32FirstW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
651 PTH32SNAPSHOT Snapshot
;
652 LARGE_INTEGER SOffset
;
656 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
658 SOffset
.QuadPart
= 0;
662 Status
= NtMapViewOfSection(hSnapshot
,
672 if(NT_SUCCESS(Status
))
676 if(Snapshot
->ModuleListCount
> 0)
678 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
679 Snapshot
->ModuleListIndex
= 1;
680 RtlCopyMemory(lpme
, &Entries
[0], sizeof(MODULEENTRY32W
));
685 SetLastError(ERROR_NO_MORE_FILES
);
689 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
693 SetLastErrorByStatus(Status
);
703 Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
708 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
710 me
.dwSize
= sizeof(MODULEENTRY32W
);
712 Ret
= Module32NextW(hSnapshot
, &me
);
715 lpme
->th32ModuleID
= me
.th32ModuleID
;
716 lpme
->th32ProcessID
= me
.th32ProcessID
;
717 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
718 lpme
->ProccntUsage
= me
.ProccntUsage
;
719 lpme
->modBaseAddr
= me
.modBaseAddr
;
720 lpme
->modBaseSize
= me
.modBaseSize
;
721 lpme
->hModule
= me
.hModule
;
723 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
724 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
733 Module32NextW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
735 PTH32SNAPSHOT Snapshot
;
736 LARGE_INTEGER SOffset
;
740 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
742 SOffset
.QuadPart
= 0;
746 Status
= NtMapViewOfSection(hSnapshot
,
756 if(NT_SUCCESS(Status
))
760 if(Snapshot
->ModuleListCount
> 0 &&
761 Snapshot
->ModuleListIndex
< Snapshot
->ModuleListCount
)
763 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
764 RtlCopyMemory(lpme
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(MODULEENTRY32W
));
769 SetLastError(ERROR_NO_MORE_FILES
);
773 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
777 SetLastErrorByStatus(Status
);
787 Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
792 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
794 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
796 Ret
= Process32FirstW(hSnapshot
, &pe
);
799 lppe
->cntUsage
= pe
.cntUsage
;
800 lppe
->th32ProcessID
= pe
.th32ProcessID
;
801 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
802 lppe
->th32ModuleID
= pe
.th32ModuleID
;
803 lppe
->cntThreads
= pe
.cntThreads
;
804 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
805 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
806 lppe
->dwFlags
= pe
.dwFlags
;
808 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
820 Process32FirstW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
822 PTH32SNAPSHOT Snapshot
;
823 LARGE_INTEGER SOffset
;
827 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
829 SOffset
.QuadPart
= 0;
833 Status
= NtMapViewOfSection(hSnapshot
,
843 if(NT_SUCCESS(Status
))
847 if(Snapshot
->ProcessListCount
> 0)
849 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
851 Snapshot
->ProcessListIndex
= 1;
852 RtlCopyMemory(lppe
, &Entries
[0], sizeof(PROCESSENTRY32W
));
858 SetLastError(ERROR_NO_MORE_FILES
);
862 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
866 SetLastErrorByStatus(Status
);
876 Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
881 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
883 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
885 Ret
= Process32NextW(hSnapshot
, &pe
);
888 lppe
->cntUsage
= pe
.cntUsage
;
889 lppe
->th32ProcessID
= pe
.th32ProcessID
;
890 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
891 lppe
->th32ModuleID
= pe
.th32ModuleID
;
892 lppe
->cntThreads
= pe
.cntThreads
;
893 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
894 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
895 lppe
->dwFlags
= pe
.dwFlags
;
897 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
909 Process32NextW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
911 PTH32SNAPSHOT Snapshot
;
912 LARGE_INTEGER SOffset
;
916 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
918 SOffset
.QuadPart
= 0;
922 Status
= NtMapViewOfSection(hSnapshot
,
932 if(NT_SUCCESS(Status
))
936 if(Snapshot
->ProcessListCount
> 0 &&
937 Snapshot
->ProcessListIndex
< Snapshot
->ProcessListCount
)
939 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
940 RtlCopyMemory(lppe
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(PROCESSENTRY32W
));
945 SetLastError(ERROR_NO_MORE_FILES
);
949 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
953 SetLastErrorByStatus(Status
);
963 Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
965 PTH32SNAPSHOT Snapshot
;
966 LARGE_INTEGER SOffset
;
970 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
972 SOffset
.QuadPart
= 0;
976 Status
= NtMapViewOfSection(hSnapshot
,
986 if(NT_SUCCESS(Status
))
990 if(Snapshot
->ThreadListCount
> 0)
992 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
993 Snapshot
->ThreadListIndex
= 1;
994 RtlCopyMemory(lpte
, &Entries
[0], sizeof(THREADENTRY32
));
999 SetLastError(ERROR_NO_MORE_FILES
);
1003 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1007 SetLastErrorByStatus(Status
);
1017 Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1019 PTH32SNAPSHOT Snapshot
;
1020 LARGE_INTEGER SOffset
;
1024 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1026 SOffset
.QuadPart
= 0;
1030 Status
= NtMapViewOfSection(hSnapshot
,
1040 if(NT_SUCCESS(Status
))
1044 if(Snapshot
->ThreadListCount
> 0 &&
1045 Snapshot
->ThreadListIndex
< Snapshot
->ThreadListCount
)
1047 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1048 RtlCopyMemory(lpte
, &Entries
[Snapshot
->ThreadListIndex
++], sizeof(THREADENTRY32
));
1053 SetLastError(ERROR_NO_MORE_FILES
);
1057 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1061 SetLastErrorByStatus(Status
);
1071 Toolhelp32ReadProcessMemory(DWORD th32ProcessID
, LPCVOID lpBaseAddress
,
1072 LPVOID lpBuffer
, DWORD cbRead
, LPDWORD lpNumberOfBytesRead
)
1074 HANDLE hProcess
= OpenProcess(PROCESS_VM_READ
, FALSE
, th32ProcessID
);
1075 if(hProcess
!= NULL
)
1077 BOOL Ret
= ReadProcessMemory(hProcess
, lpBaseAddress
, lpBuffer
, cbRead
, lpNumberOfBytesRead
);
1078 CloseHandle(hProcess
);
1091 CreateToolhelp32Snapshot(DWORD dwFlags
, DWORD th32ProcessID
)
1093 PDEBUG_BUFFER HeapDebug
, ModuleDebug
;
1095 ULONG ProcThrdInfoSize
;
1096 HANDLE hSnapShotSection
;
1099 if(th32ProcessID
== 0)
1101 th32ProcessID
= GetCurrentProcessId();
1105 * Get all information required for the snapshot
1107 Status
= TH32CreateSnapshot(dwFlags
,
1113 if(!NT_SUCCESS(Status
))
1115 SetLastErrorByStatus(Status
);
1120 * Create a section handle and initialize the collected information
1122 Status
= TH32CreateSnapshotSectionInitialize(dwFlags
,
1130 * Free the temporarily allocated memory which is no longer needed
1132 TH32FreeAllocatedResources(HeapDebug
,
1137 if(!NT_SUCCESS(Status
))
1139 SetLastErrorByStatus(Status
);
1143 return hSnapShotSection
;