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.5 2004/10/31 00:04:19 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 DbgPrint("proc: %ws\n", ProcessInfo
->ImageName
.Buffer
);
404 lstrcpynW(ProcessListEntry
->szExeFile
,
405 ProcessInfo
->ImageName
.Buffer
,
406 min(ProcessInfo
->ImageName
.Length
, sizeof(ProcessListEntry
->szExeFile
) / sizeof(ProcessListEntry
->szExeFile
[0])));
410 lstrcpyW(ProcessListEntry
->szExeFile
, L
"[System Process]");
415 ProcOffset
= ProcessInfo
->NextEntryOffset
;
416 } while(ProcOffset
!= 0);
418 DataOffset
+= nProcesses
* sizeof(PROCESSENTRY32W
);
421 /* initialize the thread list */
422 if(dwFlags
& TH32CS_SNAPTHREAD
)
424 ULONG ProcOffset
= 0;
426 Snapshot
->ThreadListCount
= nThreads
;
427 Snapshot
->ThreadListOffset
= DataOffset
;
428 ThreadListEntry
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, DataOffset
);
429 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)ProcThrdInfo
;
432 PSYSTEM_THREAD_INFORMATION ThreadInfo
;
435 ProcessInfo
= (PSYSTEM_PROCESS_INFORMATION
)((ULONG_PTR
)ProcessInfo
+ ProcOffset
);
436 ThreadInfo
= (PSYSTEM_THREAD_INFORMATION
)(ProcessInfo
+ 1);
438 for(n
= 0; n
< ProcessInfo
->NumberOfThreads
; n
++)
440 ThreadListEntry
->dwSize
= sizeof(THREADENTRY32
);
441 ThreadListEntry
->cntUsage
= 0; /* no longer used */
442 ThreadListEntry
->th32ThreadID
= (ULONG
)ThreadInfo
->ClientId
.UniqueThread
;
443 ThreadListEntry
->th32OwnerProcessID
= (ULONG
)ThreadInfo
->ClientId
.UniqueProcess
;
444 ThreadListEntry
->tpBasePri
= ThreadInfo
->BasePriority
;
445 ThreadListEntry
->tpDeltaPri
= 0; /* no longer used */
446 ThreadListEntry
->dwFlags
= 0; /* no longer used */
452 ProcOffset
= ProcessInfo
->NextEntryOffset
;
453 } while(ProcOffset
!= 0);
457 * We're done, unmap the view and return the section handle
460 Status
= NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
462 if(NT_SUCCESS(Status
))
464 *SectionHandle
= hSection
;
474 /* PUBLIC FUNCTIONS ***********************************************************/
481 Heap32First(LPHEAPENTRY32 lphe
, DWORD th32ProcessID
, DWORD th32HeapID
)
483 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
485 SetLastError(ERROR_NO_MORE_FILES
);
495 Heap32Next(LPHEAPENTRY32 lphe
)
497 CHECK_PARAM_SIZE(lphe
, sizeof(HEAPENTRY32
));
499 SetLastError(ERROR_NO_MORE_FILES
);
509 Heap32ListFirst(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
511 PTH32SNAPSHOT Snapshot
;
512 LARGE_INTEGER SOffset
;
516 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
518 SOffset
.QuadPart
= 0;
522 Status
= NtMapViewOfSection(hSnapshot
,
532 if(NT_SUCCESS(Status
))
536 if(Snapshot
->ModuleListCount
> 0)
538 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
539 Snapshot
->HeapListIndex
= 1;
540 RtlCopyMemory(lphl
, &Entries
[0], sizeof(HEAPLIST32
));
545 SetLastError(ERROR_NO_MORE_FILES
);
549 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
553 SetLastErrorByStatus(Status
);
563 Heap32ListNext(HANDLE hSnapshot
, LPHEAPLIST32 lphl
)
565 PTH32SNAPSHOT Snapshot
;
566 LARGE_INTEGER SOffset
;
570 CHECK_PARAM_SIZE(lphl
, sizeof(HEAPLIST32
));
572 SOffset
.QuadPart
= 0;
576 Status
= NtMapViewOfSection(hSnapshot
,
586 if(NT_SUCCESS(Status
))
590 if(Snapshot
->HeapListCount
> 0 &&
591 Snapshot
->HeapListIndex
< Snapshot
->HeapListCount
)
593 LPHEAPLIST32 Entries
= (LPHEAPLIST32
)OffsetToPtr(Snapshot
, Snapshot
->HeapListOffset
);
594 RtlCopyMemory(lphl
, &Entries
[Snapshot
->HeapListIndex
++], sizeof(HEAPLIST32
));
599 SetLastError(ERROR_NO_MORE_FILES
);
603 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
607 SetLastErrorByStatus(Status
);
617 Module32First(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
622 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
624 me
.dwSize
= sizeof(MODULEENTRY32W
);
626 Ret
= Module32FirstW(hSnapshot
, &me
);
629 lpme
->th32ModuleID
= me
.th32ModuleID
;
630 lpme
->th32ProcessID
= me
.th32ProcessID
;
631 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
632 lpme
->ProccntUsage
= me
.ProccntUsage
;
633 lpme
->modBaseAddr
= me
.modBaseAddr
;
634 lpme
->modBaseSize
= me
.modBaseSize
;
635 lpme
->hModule
= me
.hModule
;
637 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
638 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
650 Module32FirstW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
652 PTH32SNAPSHOT Snapshot
;
653 LARGE_INTEGER SOffset
;
657 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
659 SOffset
.QuadPart
= 0;
663 Status
= NtMapViewOfSection(hSnapshot
,
673 if(NT_SUCCESS(Status
))
677 if(Snapshot
->ModuleListCount
> 0)
679 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
680 Snapshot
->ModuleListIndex
= 1;
681 RtlCopyMemory(lpme
, &Entries
[0], sizeof(MODULEENTRY32W
));
686 SetLastError(ERROR_NO_MORE_FILES
);
690 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
694 SetLastErrorByStatus(Status
);
704 Module32Next(HANDLE hSnapshot
, LPMODULEENTRY32 lpme
)
709 CHECK_PARAM_SIZEA(lpme
, sizeof(MODULEENTRY32
));
711 me
.dwSize
= sizeof(MODULEENTRY32W
);
713 Ret
= Module32NextW(hSnapshot
, &me
);
716 lpme
->th32ModuleID
= me
.th32ModuleID
;
717 lpme
->th32ProcessID
= me
.th32ProcessID
;
718 lpme
->GlblcntUsage
= me
.GlblcntUsage
;
719 lpme
->ProccntUsage
= me
.ProccntUsage
;
720 lpme
->modBaseAddr
= me
.modBaseAddr
;
721 lpme
->modBaseSize
= me
.modBaseSize
;
722 lpme
->hModule
= me
.hModule
;
724 WideCharToMultiByte(CP_ACP
, 0, me
.szModule
, -1, lpme
->szModule
, sizeof(lpme
->szModule
), 0, 0);
725 WideCharToMultiByte(CP_ACP
, 0, me
.szExePath
, -1, lpme
->szExePath
, sizeof(lpme
->szExePath
), 0, 0);
734 Module32NextW(HANDLE hSnapshot
, LPMODULEENTRY32W lpme
)
736 PTH32SNAPSHOT Snapshot
;
737 LARGE_INTEGER SOffset
;
741 CHECK_PARAM_SIZE(lpme
, sizeof(MODULEENTRY32W
));
743 SOffset
.QuadPart
= 0;
747 Status
= NtMapViewOfSection(hSnapshot
,
757 if(NT_SUCCESS(Status
))
761 if(Snapshot
->ModuleListCount
> 0 &&
762 Snapshot
->ModuleListIndex
< Snapshot
->ModuleListCount
)
764 LPMODULEENTRY32W Entries
= (LPMODULEENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ModuleListOffset
);
765 RtlCopyMemory(lpme
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(MODULEENTRY32W
));
770 SetLastError(ERROR_NO_MORE_FILES
);
774 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
778 SetLastErrorByStatus(Status
);
788 Process32First(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
793 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
795 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
797 Ret
= Process32FirstW(hSnapshot
, &pe
);
800 lppe
->cntUsage
= pe
.cntUsage
;
801 lppe
->th32ProcessID
= pe
.th32ProcessID
;
802 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
803 lppe
->th32ModuleID
= pe
.th32ModuleID
;
804 lppe
->cntThreads
= pe
.cntThreads
;
805 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
806 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
807 lppe
->dwFlags
= pe
.dwFlags
;
809 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
821 Process32FirstW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
823 PTH32SNAPSHOT Snapshot
;
824 LARGE_INTEGER SOffset
;
828 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
830 SOffset
.QuadPart
= 0;
834 Status
= NtMapViewOfSection(hSnapshot
,
844 if(NT_SUCCESS(Status
))
848 if(Snapshot
->ProcessListCount
> 0)
850 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
852 Snapshot
->ProcessListIndex
= 1;
853 RtlCopyMemory(lppe
, &Entries
[0], sizeof(PROCESSENTRY32W
));
859 SetLastError(ERROR_NO_MORE_FILES
);
863 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
867 SetLastErrorByStatus(Status
);
877 Process32Next(HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
882 CHECK_PARAM_SIZEA(lppe
, sizeof(PROCESSENTRY32
));
884 pe
.dwSize
= sizeof(PROCESSENTRY32W
);
886 Ret
= Process32NextW(hSnapshot
, &pe
);
889 lppe
->cntUsage
= pe
.cntUsage
;
890 lppe
->th32ProcessID
= pe
.th32ProcessID
;
891 lppe
->th32DefaultHeapID
= pe
.th32DefaultHeapID
;
892 lppe
->th32ModuleID
= pe
.th32ModuleID
;
893 lppe
->cntThreads
= pe
.cntThreads
;
894 lppe
->th32ParentProcessID
= pe
.th32ParentProcessID
;
895 lppe
->pcPriClassBase
= pe
.pcPriClassBase
;
896 lppe
->dwFlags
= pe
.dwFlags
;
898 WideCharToMultiByte(CP_ACP
, 0, pe
.szExeFile
, -1, lppe
->szExeFile
, sizeof(lppe
->szExeFile
), 0, 0);
910 Process32NextW(HANDLE hSnapshot
, LPPROCESSENTRY32W lppe
)
912 PTH32SNAPSHOT Snapshot
;
913 LARGE_INTEGER SOffset
;
917 CHECK_PARAM_SIZE(lppe
, sizeof(PROCESSENTRY32W
));
919 SOffset
.QuadPart
= 0;
923 Status
= NtMapViewOfSection(hSnapshot
,
933 if(NT_SUCCESS(Status
))
937 if(Snapshot
->ProcessListCount
> 0 &&
938 Snapshot
->ProcessListIndex
< Snapshot
->ProcessListCount
)
940 LPPROCESSENTRY32W Entries
= (LPPROCESSENTRY32W
)OffsetToPtr(Snapshot
, Snapshot
->ProcessListOffset
);
941 RtlCopyMemory(lppe
, &Entries
[Snapshot
->ProcessListIndex
++], sizeof(PROCESSENTRY32W
));
946 SetLastError(ERROR_NO_MORE_FILES
);
950 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
954 SetLastErrorByStatus(Status
);
964 Thread32First(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
966 PTH32SNAPSHOT Snapshot
;
967 LARGE_INTEGER SOffset
;
971 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
973 SOffset
.QuadPart
= 0;
977 Status
= NtMapViewOfSection(hSnapshot
,
987 if(NT_SUCCESS(Status
))
991 if(Snapshot
->ThreadListCount
> 0)
993 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
994 Snapshot
->ThreadListIndex
= 1;
995 RtlCopyMemory(lpte
, &Entries
[0], sizeof(THREADENTRY32
));
1000 SetLastError(ERROR_NO_MORE_FILES
);
1004 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1008 SetLastErrorByStatus(Status
);
1018 Thread32Next(HANDLE hSnapshot
, LPTHREADENTRY32 lpte
)
1020 PTH32SNAPSHOT Snapshot
;
1021 LARGE_INTEGER SOffset
;
1025 CHECK_PARAM_SIZE(lpte
, sizeof(THREADENTRY32
));
1027 SOffset
.QuadPart
= 0;
1031 Status
= NtMapViewOfSection(hSnapshot
,
1041 if(NT_SUCCESS(Status
))
1045 if(Snapshot
->ThreadListCount
> 0 &&
1046 Snapshot
->ThreadListIndex
< Snapshot
->ThreadListCount
)
1048 LPTHREADENTRY32 Entries
= (LPTHREADENTRY32
)OffsetToPtr(Snapshot
, Snapshot
->ThreadListOffset
);
1049 RtlCopyMemory(lpte
, &Entries
[Snapshot
->ThreadListIndex
++], sizeof(THREADENTRY32
));
1054 SetLastError(ERROR_NO_MORE_FILES
);
1058 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID
)Snapshot
);
1062 SetLastErrorByStatus(Status
);
1072 Toolhelp32ReadProcessMemory(DWORD th32ProcessID
, LPCVOID lpBaseAddress
,
1073 LPVOID lpBuffer
, DWORD cbRead
, LPDWORD lpNumberOfBytesRead
)
1075 HANDLE hProcess
= OpenProcess(PROCESS_VM_READ
, FALSE
, th32ProcessID
);
1076 if(hProcess
!= NULL
)
1078 BOOL Ret
= ReadProcessMemory(hProcess
, lpBaseAddress
, lpBuffer
, cbRead
, lpNumberOfBytesRead
);
1079 CloseHandle(hProcess
);
1092 CreateToolhelp32Snapshot(DWORD dwFlags
, DWORD th32ProcessID
)
1094 PDEBUG_BUFFER HeapDebug
, ModuleDebug
;
1096 ULONG ProcThrdInfoSize
;
1097 HANDLE hSnapShotSection
;
1100 if(th32ProcessID
== 0)
1102 th32ProcessID
= GetCurrentProcessId();
1106 * Get all information required for the snapshot
1108 Status
= TH32CreateSnapshot(dwFlags
,
1114 if(!NT_SUCCESS(Status
))
1116 SetLastErrorByStatus(Status
);
1121 * Create a section handle and initialize the collected information
1123 Status
= TH32CreateSnapshotSectionInitialize(dwFlags
,
1131 * Free the temporarily allocated memory to collect all information
1133 TH32FreeAllocatedResources(HeapDebug
,
1138 if(!NT_SUCCESS(Status
))
1140 SetLastErrorByStatus(Status
);
1144 return hSnapShotSection
;