Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,4 @@ ASALocalRun/

# CMake/Build output
build/
/CMakeSettings.json
133 changes: 133 additions & 0 deletions include/wil/toolhelp32.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#include "resource.h"
Comment thread
dunhor marked this conversation as resolved.
Outdated
#ifndef __WIL_TOOLHELP32_INCLUDED
#define __WIL_TOOLHELP32_INCLUDED
#include <TlHelp32.h>
#include <processthreadsapi.h>
namespace wil
Comment thread
HO-COOH marked this conversation as resolved.
Outdated
{
namespace details
{
template <typename TEntry, typename TEnumApi, typename TCallback>
void do_enum_snapshot(HANDLE handle, TEntry& entry, TEnumApi&& enumApiFirst, TEnumApi&& enumApiNext, TCallback&& callback)
{
using result_t = decltype(callback(TEntry{}));
bool enumResult = enumApiFirst(handle, &entry);
if (!enumResult)
return;

do
{
if constexpr (wistd::is_void_v<result_t>)
{
callback(entry);
}
else if constexpr (wistd::is_same_v<result_t, bool>)
{
if (callback(entry))
return;
}
else
{
static_assert(
[] {
return false;
}(),
"Callback must return void or bool");
}
enumResult = enumApiNext(handle, &entry);
} while (enumResult);
}
} // namespace details

template <typename TCallback>
void for_each_process(TCallback&& callback)
{
PROCESSENTRY32 entry{};
entry.dwSize = sizeof(entry);
details::do_enum_snapshot(
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)}.get(),
Comment thread
HO-COOH marked this conversation as resolved.
entry,
&Process32First,
&Process32Next,
wistd::forward<TCallback>(callback));
}

template <typename TCallback>
void for_each_thread(TCallback&& callback)
Comment thread
HO-COOH marked this conversation as resolved.
Outdated
{
THREADENTRY32 entry{};
entry.dwSize = sizeof(entry);
details::do_enum_snapshot(
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)}.get(),
entry,
&Thread32First,
&Thread32Next,
wistd::forward<TCallback>(callback));
}

template <typename TCallback>
void for_each_module(TCallback&& callback, bool include32For64Bit = false)
Comment thread
HO-COOH marked this conversation as resolved.
Outdated
{
MODULEENTRY32 entry{};
entry.dwSize = sizeof(entry);
details::do_enum_snapshot(
unique_handle{CreateToolhelp32Snapshot(include32For64Bit ? TH32CS_SNAPMODULE32 : TH32CS_SNAPMODULE, 0)}.get(),
entry,
&Module32First,
&Module32Next,
wistd::forward<TCallback>(callback));
}

template <typename TCallback>
void for_each_heap_list(TCallback&& callback)
{
HEAPLIST32 entry{};
entry.dwSize = sizeof(entry);
details::do_enum_snapshot(
unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, 0)}.get(),
entry,
&Heap32ListFirst,
&Heap32ListNext,
wistd::forward<TCallback>(callback));
}

template <typename TCallback>
void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurrentProcessId())
Comment thread
HO-COOH marked this conversation as resolved.
Outdated
{
using result_t = decltype(callback(HEAPENTRY32{}));

HEAPENTRY32 entry{};
entry.dwSize = sizeof(entry);

bool enumResult = Heap32First(&entry, pid, heapId);
do
{
if constexpr (wistd::is_void_v<result_t>)
{
callback(entry);
}
else if constexpr (wistd::is_same_v<result_t, bool>)
{
if (callback(entry))
return;
}
else
{
static_assert(
[] {
return false;
}(),
"Callback must return void or bool");
}
enumResult = Heap32Next(&entry);
} while (enumResult);
}

template <typename TCallback>
void for_each_heap(TCallback&& callback, HEAPLIST32 const& heapList, DWORD pid = GetCurrentProcessId())
Comment thread
HO-COOH marked this conversation as resolved.
Outdated
{
for_each_heap(wistd::forward<TCallback>(callback), heapList.th32HeapID, pid);
}
} // namespace wil

#endif
48 changes: 48 additions & 0 deletions tests/Toolhelp32Tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "common.h"
#include <WinUser.h>
#include <wil/toolhelp32.h>
#include <cstring>

TEST_CASE("Toolhelp32", "[EnumProcesses]")
{
wil::for_each_process([](PROCESSENTRY32 const& entry) {
REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0);
});
}

TEST_CASE("Toolhelp32", "[EnumModules]")
{
wil::for_each_module([](MODULEENTRY32 const& entry) {
REQUIRE_FALSE(std::strlen(entry.szExePath) == 0);
});
}

TEST_CASE("Toolhelp32", "[EnumThreads]")
{
wil::for_each_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) {
if (entry.th32OwnerProcessID == pid)
{
REQUIRE_FALSE(entry.th32ThreadID == 0);
}
});
}

TEST_CASE("Toolhelp32", "[EnumHeapLists]")
{
wil::for_each_heap_list([](HEAPLIST32 const& entry) {
REQUIRE_FALSE(entry.th32HeapID == 0);
});
}

TEST_CASE("Toolhelp32", "[EnumHeap]")
{
wil::for_each_heap_list([](HEAPLIST32 const& heapListEntry) {
REQUIRE_FALSE(heapListEntry.th32HeapID == 0);
wil::for_each_heap(
[](HEAPENTRY32 const& heapEntry) {
REQUIRE_FALSE(heapEntry.dwAddress == 0);
},
heapListEntry);
return false;
});
}
1 change: 1 addition & 0 deletions tests/cpplatest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ target_sources(witest.cpplatest PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../WatcherTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../WinRTTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../WinVerifyTrustTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../Toolhelp32Tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/app.manifest
)
1 change: 1 addition & 0 deletions tests/normal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ target_sources(witest PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../WatcherTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../WinRTTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../WinVerifyTrustTest.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../Toolhelp32Tests.cpp
)
1 change: 1 addition & 0 deletions tests/win7/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ target_sources(witest.win7 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../StlTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../TokenHelpersTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../WatcherTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../Toolhelp32Tests.cpp
)