Skip to content

Commit 785d711

Browse files
committed
Finish implementation
1 parent 009095d commit 785d711

File tree

3 files changed

+138
-41
lines changed

3 files changed

+138
-41
lines changed

CMakeSettings.json

Lines changed: 0 additions & 16 deletions
This file was deleted.

include/wil/toolhelp32.h

Lines changed: 116 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,133 @@
1+
#include "resource.h"
12
#ifndef __WIL_TOOLHELP32_INCLUDED
23
#define __WIL_TOOLHELP32_INCLUDED
34
#include <TlHelp32.h>
5+
#include <processthreadsapi.h>
46
namespace wil
57
{
6-
namespace details
7-
{
8+
namespace details
9+
{
10+
template <typename TEntry, typename TEnumApi, typename TCallback>
11+
void do_enum_snapshot(HANDLE handle, TEntry& entry, TEnumApi&& enumApiFirst, TEnumApi&& enumApiNext, TCallback&& callback)
12+
{
13+
using result_t = decltype(callback(TEntry{}));
14+
bool enumResult = enumApiFirst(handle, &entry);
15+
if (!enumResult)
16+
return;
817

9-
}
18+
do
19+
{
20+
if constexpr (wistd::is_void_v<result_t>)
21+
{
22+
callback(entry);
23+
}
24+
else if constexpr (wistd::is_same_v<result_t, bool>)
25+
{
26+
if (callback(entry))
27+
return;
28+
}
29+
else
30+
{
31+
static_assert(
32+
[] {
33+
return false;
34+
}(),
35+
"Callback must return void or bool");
36+
}
37+
enumResult = enumApiNext(handle, &entry);
38+
} while (enumResult);
39+
}
40+
} // namespace details
1041

11-
template<typename TCallback>
12-
void for_each_process(TCallback&& /*callback*/)
13-
{
42+
template <typename TCallback>
43+
void for_each_process(TCallback&& callback)
44+
{
45+
PROCESSENTRY32 entry{};
46+
entry.dwSize = sizeof(entry);
47+
details::do_enum_snapshot(
48+
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)}.get(),
49+
entry,
50+
&Process32First,
51+
&Process32Next,
52+
wistd::forward<TCallback>(callback));
53+
}
1454

15-
}
55+
template <typename TCallback>
56+
void for_each_thread(TCallback&& callback)
57+
{
58+
THREADENTRY32 entry{};
59+
entry.dwSize = sizeof(entry);
60+
details::do_enum_snapshot(
61+
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)}.get(),
62+
entry,
63+
&Thread32First,
64+
&Thread32Next,
65+
wistd::forward<TCallback>(callback));
66+
}
1667

17-
template<typename TCallback>
18-
void for_each_thread(TCallback&& /*callback*/)
19-
{
68+
template <typename TCallback>
69+
void for_each_module(TCallback&& callback, bool include32For64Bit = false)
70+
{
71+
MODULEENTRY32 entry{};
72+
entry.dwSize = sizeof(entry);
73+
details::do_enum_snapshot(
74+
unique_handle{CreateToolhelp32Snapshot(include32For64Bit ? TH32CS_SNAPMODULE32 : TH32CS_SNAPMODULE, 0)}.get(),
75+
entry,
76+
&Module32First,
77+
&Module32Next,
78+
wistd::forward<TCallback>(callback));
79+
}
2080

21-
}
81+
template <typename TCallback>
82+
void for_each_heap_list(TCallback&& callback)
83+
{
84+
HEAPLIST32 entry{};
85+
entry.dwSize = sizeof(entry);
86+
details::do_enum_snapshot(
87+
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, 0)}.get(),
88+
entry,
89+
&Heap32ListFirst,
90+
&Heap32ListNext,
91+
wistd::forward<TCallback>(callback));
92+
}
2293

23-
template<typename TCallback>
24-
void for_each_module(TCallback&& /*callback*/)
25-
{
94+
template <typename TCallback>
95+
void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurrentProcessId())
96+
{
97+
using result_t = decltype(callback(HEAPENTRY32{}));
2698

27-
}
99+
HEAPENTRY32 entry{};
100+
entry.dwSize = sizeof(entry);
28101

29-
template<typename TCallback>
30-
void for_each_heap(TCallback&& /*callback*/)
31-
{
102+
bool enumResult = Heap32First(&entry, pid, heapId);
103+
do
104+
{
105+
if constexpr (wistd::is_void_v<result_t>)
106+
{
107+
callback(entry);
108+
}
109+
else if constexpr (wistd::is_same_v<result_t, bool>)
110+
{
111+
if (callback(entry))
112+
return;
113+
}
114+
else
115+
{
116+
static_assert(
117+
[] {
118+
return false;
119+
}(),
120+
"Callback must return void or bool");
121+
}
122+
enumResult = Heap32Next(&entry);
123+
} while (enumResult);
124+
}
32125

33-
}
126+
template <typename TCallback>
127+
void for_each_heap(TCallback&& callback, HEAPLIST32 const& heapList, DWORD pid = GetCurrentProcessId())
128+
{
129+
for_each_heap(wistd::forward<TCallback>(callback), heapList.th32HeapID, pid);
34130
}
131+
} // namespace wil
35132

36133
#endif

tests/Toolhelp32Tests.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,44 @@
55

66
TEST_CASE("Toolhelp32", "[EnumProcesses]")
77
{
8-
wil::for_each_process([](PROCESSENTRY32 entry) {
8+
wil::for_each_process([](PROCESSENTRY32 const& entry) {
99
REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0);
1010
});
1111
}
1212

1313
TEST_CASE("Toolhelp32", "[EnumModules]")
1414
{
15-
wil::for_each_module([](MODULEENTRY32 entry) {
15+
wil::for_each_module([](MODULEENTRY32 const& entry) {
1616
REQUIRE_FALSE(std::strlen(entry.szExePath) == 0);
1717
});
1818
}
1919

2020
TEST_CASE("Toolhelp32", "[EnumThreads]")
2121
{
22-
wil::for_each_thread([](THREADENTRY32 entry) {
23-
REQUIRE_FALSE(entry.th32ThreadID == 0);
22+
wil::for_each_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) {
23+
if (entry.th32OwnerProcessID == pid)
24+
{
25+
REQUIRE_FALSE(entry.th32ThreadID == 0);
26+
}
2427
});
2528
}
2629

27-
TEST_CASE("Toolhelp32", "[EnumHeaps]")
30+
TEST_CASE("Toolhelp32", "[EnumHeapLists]")
2831
{
29-
wil::for_each_heap([](HEAPLIST32 entry) {
32+
wil::for_each_heap_list([](HEAPLIST32 const& entry) {
3033
REQUIRE_FALSE(entry.th32HeapID == 0);
3134
});
35+
}
36+
37+
TEST_CASE("Toolhelp32", "[EnumHeap]")
38+
{
39+
wil::for_each_heap_list([](HEAPLIST32 const& heapListEntry) {
40+
REQUIRE_FALSE(heapListEntry.th32HeapID == 0);
41+
wil::for_each_heap(
42+
[](HEAPENTRY32 const& heapEntry) {
43+
REQUIRE_FALSE(heapEntry.dwAddress == 0);
44+
},
45+
heapListEntry);
46+
return false;
47+
});
3248
}

0 commit comments

Comments
 (0)