From 009095d9af5f48e4bf67da5ae7f39068a9af3e37 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 9 Feb 2024 00:33:57 +0800 Subject: [PATCH 1/8] Create stub for toolhelp32 --- CMakeSettings.json | 16 ++++++++++++++++ include/wil/toolhelp32.h | 36 ++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/Toolhelp32Tests.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 CMakeSettings.json create mode 100644 include/wil/toolhelp32.h create mode 100644 tests/Toolhelp32Tests.cpp diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 000000000..1dad0e113 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "cmakeToolchain": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/vcpkg/scripts/buildsystems/vcpkg.cmake" + } + ] +} \ No newline at end of file diff --git a/include/wil/toolhelp32.h b/include/wil/toolhelp32.h new file mode 100644 index 000000000..051d935f8 --- /dev/null +++ b/include/wil/toolhelp32.h @@ -0,0 +1,36 @@ +#ifndef __WIL_TOOLHELP32_INCLUDED +#define __WIL_TOOLHELP32_INCLUDED +#include +namespace wil +{ + namespace details + { + + } + + template + void for_each_process(TCallback&& /*callback*/) + { + + } + + template + void for_each_thread(TCallback&& /*callback*/) + { + + } + + template + void for_each_module(TCallback&& /*callback*/) + { + + } + + template + void for_each_heap(TCallback&& /*callback*/) + { + + } +} + +#endif \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d5f7c7436..99434393f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -75,6 +75,7 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WistdTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wiTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../natvis/wil.natvis + ${CMAKE_CURRENT_SOURCE_DIR}/Toolhelp32Tests.cpp ) if (MSVC) diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp new file mode 100644 index 000000000..b0167b272 --- /dev/null +++ b/tests/Toolhelp32Tests.cpp @@ -0,0 +1,32 @@ +#include "common.h" +#include +#include +#include + +TEST_CASE("Toolhelp32", "[EnumProcesses]") +{ + wil::for_each_process([](PROCESSENTRY32 entry) { + REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumModules]") +{ + wil::for_each_module([](MODULEENTRY32 entry) { + REQUIRE_FALSE(std::strlen(entry.szExePath) == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumThreads]") +{ + wil::for_each_thread([](THREADENTRY32 entry) { + REQUIRE_FALSE(entry.th32ThreadID == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumHeaps]") +{ + wil::for_each_heap([](HEAPLIST32 entry) { + REQUIRE_FALSE(entry.th32HeapID == 0); + }); +} \ No newline at end of file From 785d711e62209efb5d089bc30bc16554db18989a Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 20 Feb 2024 22:57:37 +0800 Subject: [PATCH 2/8] Finish implementation --- CMakeSettings.json | 16 ----- include/wil/toolhelp32.h | 135 ++++++++++++++++++++++++++++++++------ tests/Toolhelp32Tests.cpp | 28 ++++++-- 3 files changed, 138 insertions(+), 41 deletions(-) delete mode 100644 CMakeSettings.json diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 1dad0e113..000000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "cmakeToolchain": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/vcpkg/scripts/buildsystems/vcpkg.cmake" - } - ] -} \ No newline at end of file diff --git a/include/wil/toolhelp32.h b/include/wil/toolhelp32.h index 051d935f8..587212d87 100644 --- a/include/wil/toolhelp32.h +++ b/include/wil/toolhelp32.h @@ -1,36 +1,133 @@ +#include "resource.h" #ifndef __WIL_TOOLHELP32_INCLUDED #define __WIL_TOOLHELP32_INCLUDED #include +#include namespace wil { - namespace details - { +namespace details +{ + template + 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) + { + callback(entry); + } + else if constexpr (wistd::is_same_v) + { + if (callback(entry)) + return; + } + else + { + static_assert( + [] { + return false; + }(), + "Callback must return void or bool"); + } + enumResult = enumApiNext(handle, &entry); + } while (enumResult); + } +} // namespace details - template - void for_each_process(TCallback&& /*callback*/) - { +template +void for_each_process(TCallback&& callback) +{ + PROCESSENTRY32 entry{}; + entry.dwSize = sizeof(entry); + details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)}.get(), + entry, + &Process32First, + &Process32Next, + wistd::forward(callback)); +} - } +template +void for_each_thread(TCallback&& callback) +{ + THREADENTRY32 entry{}; + entry.dwSize = sizeof(entry); + details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)}.get(), + entry, + &Thread32First, + &Thread32Next, + wistd::forward(callback)); +} - template - void for_each_thread(TCallback&& /*callback*/) - { +template +void for_each_module(TCallback&& callback, bool include32For64Bit = false) +{ + 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(callback)); +} - } +template +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(callback)); +} - template - void for_each_module(TCallback&& /*callback*/) - { +template +void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurrentProcessId()) +{ + using result_t = decltype(callback(HEAPENTRY32{})); - } + HEAPENTRY32 entry{}; + entry.dwSize = sizeof(entry); - template - void for_each_heap(TCallback&& /*callback*/) - { + bool enumResult = Heap32First(&entry, pid, heapId); + do + { + if constexpr (wistd::is_void_v) + { + callback(entry); + } + else if constexpr (wistd::is_same_v) + { + if (callback(entry)) + return; + } + else + { + static_assert( + [] { + return false; + }(), + "Callback must return void or bool"); + } + enumResult = Heap32Next(&entry); + } while (enumResult); +} - } +template +void for_each_heap(TCallback&& callback, HEAPLIST32 const& heapList, DWORD pid = GetCurrentProcessId()) +{ + for_each_heap(wistd::forward(callback), heapList.th32HeapID, pid); } +} // namespace wil #endif \ No newline at end of file diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp index b0167b272..a47218a32 100644 --- a/tests/Toolhelp32Tests.cpp +++ b/tests/Toolhelp32Tests.cpp @@ -5,28 +5,44 @@ TEST_CASE("Toolhelp32", "[EnumProcesses]") { - wil::for_each_process([](PROCESSENTRY32 entry) { + wil::for_each_process([](PROCESSENTRY32 const& entry) { REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0); }); } TEST_CASE("Toolhelp32", "[EnumModules]") { - wil::for_each_module([](MODULEENTRY32 entry) { + wil::for_each_module([](MODULEENTRY32 const& entry) { REQUIRE_FALSE(std::strlen(entry.szExePath) == 0); }); } TEST_CASE("Toolhelp32", "[EnumThreads]") { - wil::for_each_thread([](THREADENTRY32 entry) { - REQUIRE_FALSE(entry.th32ThreadID == 0); + wil::for_each_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) { + if (entry.th32OwnerProcessID == pid) + { + REQUIRE_FALSE(entry.th32ThreadID == 0); + } }); } -TEST_CASE("Toolhelp32", "[EnumHeaps]") +TEST_CASE("Toolhelp32", "[EnumHeapLists]") { - wil::for_each_heap([](HEAPLIST32 entry) { + 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; + }); } \ No newline at end of file From c982bbee74d74ace16af68ca14febdd7fadb035b Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 9 Feb 2024 00:33:57 +0800 Subject: [PATCH 3/8] Create stub for toolhelp32 --- CMakeSettings.json | 16 ++++++++++++++++ include/wil/toolhelp32.h | 36 ++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/Toolhelp32Tests.cpp | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 CMakeSettings.json create mode 100644 include/wil/toolhelp32.h create mode 100644 tests/Toolhelp32Tests.cpp diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 000000000..1dad0e113 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "cmakeToolchain": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/vcpkg/scripts/buildsystems/vcpkg.cmake" + } + ] +} \ No newline at end of file diff --git a/include/wil/toolhelp32.h b/include/wil/toolhelp32.h new file mode 100644 index 000000000..051d935f8 --- /dev/null +++ b/include/wil/toolhelp32.h @@ -0,0 +1,36 @@ +#ifndef __WIL_TOOLHELP32_INCLUDED +#define __WIL_TOOLHELP32_INCLUDED +#include +namespace wil +{ + namespace details + { + + } + + template + void for_each_process(TCallback&& /*callback*/) + { + + } + + template + void for_each_thread(TCallback&& /*callback*/) + { + + } + + template + void for_each_module(TCallback&& /*callback*/) + { + + } + + template + void for_each_heap(TCallback&& /*callback*/) + { + + } +} + +#endif \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d5f7c7436..99434393f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -75,6 +75,7 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WistdTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wiTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../natvis/wil.natvis + ${CMAKE_CURRENT_SOURCE_DIR}/Toolhelp32Tests.cpp ) if (MSVC) diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp new file mode 100644 index 000000000..b0167b272 --- /dev/null +++ b/tests/Toolhelp32Tests.cpp @@ -0,0 +1,32 @@ +#include "common.h" +#include +#include +#include + +TEST_CASE("Toolhelp32", "[EnumProcesses]") +{ + wil::for_each_process([](PROCESSENTRY32 entry) { + REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumModules]") +{ + wil::for_each_module([](MODULEENTRY32 entry) { + REQUIRE_FALSE(std::strlen(entry.szExePath) == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumThreads]") +{ + wil::for_each_thread([](THREADENTRY32 entry) { + REQUIRE_FALSE(entry.th32ThreadID == 0); + }); +} + +TEST_CASE("Toolhelp32", "[EnumHeaps]") +{ + wil::for_each_heap([](HEAPLIST32 entry) { + REQUIRE_FALSE(entry.th32HeapID == 0); + }); +} \ No newline at end of file From 6ccd95b4934beffed57562ba129773c12715460b Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 20 Feb 2024 22:57:37 +0800 Subject: [PATCH 4/8] Finish implementation --- CMakeSettings.json | 16 ----- include/wil/toolhelp32.h | 135 ++++++++++++++++++++++++++++++++------ tests/Toolhelp32Tests.cpp | 28 ++++++-- 3 files changed, 138 insertions(+), 41 deletions(-) delete mode 100644 CMakeSettings.json diff --git a/CMakeSettings.json b/CMakeSettings.json deleted file mode 100644 index 1dad0e113..000000000 --- a/CMakeSettings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "", - "cmakeToolchain": "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/vcpkg/scripts/buildsystems/vcpkg.cmake" - } - ] -} \ No newline at end of file diff --git a/include/wil/toolhelp32.h b/include/wil/toolhelp32.h index 051d935f8..587212d87 100644 --- a/include/wil/toolhelp32.h +++ b/include/wil/toolhelp32.h @@ -1,36 +1,133 @@ +#include "resource.h" #ifndef __WIL_TOOLHELP32_INCLUDED #define __WIL_TOOLHELP32_INCLUDED #include +#include namespace wil { - namespace details - { +namespace details +{ + template + 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) + { + callback(entry); + } + else if constexpr (wistd::is_same_v) + { + if (callback(entry)) + return; + } + else + { + static_assert( + [] { + return false; + }(), + "Callback must return void or bool"); + } + enumResult = enumApiNext(handle, &entry); + } while (enumResult); + } +} // namespace details - template - void for_each_process(TCallback&& /*callback*/) - { +template +void for_each_process(TCallback&& callback) +{ + PROCESSENTRY32 entry{}; + entry.dwSize = sizeof(entry); + details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)}.get(), + entry, + &Process32First, + &Process32Next, + wistd::forward(callback)); +} - } +template +void for_each_thread(TCallback&& callback) +{ + THREADENTRY32 entry{}; + entry.dwSize = sizeof(entry); + details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)}.get(), + entry, + &Thread32First, + &Thread32Next, + wistd::forward(callback)); +} - template - void for_each_thread(TCallback&& /*callback*/) - { +template +void for_each_module(TCallback&& callback, bool include32For64Bit = false) +{ + 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(callback)); +} - } +template +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(callback)); +} - template - void for_each_module(TCallback&& /*callback*/) - { +template +void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurrentProcessId()) +{ + using result_t = decltype(callback(HEAPENTRY32{})); - } + HEAPENTRY32 entry{}; + entry.dwSize = sizeof(entry); - template - void for_each_heap(TCallback&& /*callback*/) - { + bool enumResult = Heap32First(&entry, pid, heapId); + do + { + if constexpr (wistd::is_void_v) + { + callback(entry); + } + else if constexpr (wistd::is_same_v) + { + if (callback(entry)) + return; + } + else + { + static_assert( + [] { + return false; + }(), + "Callback must return void or bool"); + } + enumResult = Heap32Next(&entry); + } while (enumResult); +} - } +template +void for_each_heap(TCallback&& callback, HEAPLIST32 const& heapList, DWORD pid = GetCurrentProcessId()) +{ + for_each_heap(wistd::forward(callback), heapList.th32HeapID, pid); } +} // namespace wil #endif \ No newline at end of file diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp index b0167b272..a47218a32 100644 --- a/tests/Toolhelp32Tests.cpp +++ b/tests/Toolhelp32Tests.cpp @@ -5,28 +5,44 @@ TEST_CASE("Toolhelp32", "[EnumProcesses]") { - wil::for_each_process([](PROCESSENTRY32 entry) { + wil::for_each_process([](PROCESSENTRY32 const& entry) { REQUIRE_FALSE(std::strlen(entry.szExeFile) == 0); }); } TEST_CASE("Toolhelp32", "[EnumModules]") { - wil::for_each_module([](MODULEENTRY32 entry) { + wil::for_each_module([](MODULEENTRY32 const& entry) { REQUIRE_FALSE(std::strlen(entry.szExePath) == 0); }); } TEST_CASE("Toolhelp32", "[EnumThreads]") { - wil::for_each_thread([](THREADENTRY32 entry) { - REQUIRE_FALSE(entry.th32ThreadID == 0); + wil::for_each_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) { + if (entry.th32OwnerProcessID == pid) + { + REQUIRE_FALSE(entry.th32ThreadID == 0); + } }); } -TEST_CASE("Toolhelp32", "[EnumHeaps]") +TEST_CASE("Toolhelp32", "[EnumHeapLists]") { - wil::for_each_heap([](HEAPLIST32 entry) { + 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; + }); } \ No newline at end of file From 76eb9f85be33af69a59141711ce984ff8a0729c4 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 20 Feb 2024 23:25:01 +0800 Subject: [PATCH 5/8] Remove from common_source --- .gitignore | 1 + tests/CMakeLists.txt | 1 - tests/cpplatest/CMakeLists.txt | 1 + tests/normal/CMakeLists.txt | 1 + tests/win7/CMakeLists.txt | 1 + 5 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3973a16bf..f2c941991 100644 --- a/.gitignore +++ b/.gitignore @@ -334,3 +334,4 @@ ASALocalRun/ # CMake/Build output build/ +/CMakeSettings.json diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 99434393f..d5f7c7436 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -75,7 +75,6 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WistdTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wiTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../natvis/wil.natvis - ${CMAKE_CURRENT_SOURCE_DIR}/Toolhelp32Tests.cpp ) if (MSVC) diff --git a/tests/cpplatest/CMakeLists.txt b/tests/cpplatest/CMakeLists.txt index ae22fc9f5..7ae95556f 100644 --- a/tests/cpplatest/CMakeLists.txt +++ b/tests/cpplatest/CMakeLists.txt @@ -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 ) diff --git a/tests/normal/CMakeLists.txt b/tests/normal/CMakeLists.txt index 7b651c2f4..637b52287 100644 --- a/tests/normal/CMakeLists.txt +++ b/tests/normal/CMakeLists.txt @@ -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 ) diff --git a/tests/win7/CMakeLists.txt b/tests/win7/CMakeLists.txt index 15445f9f7..48fcc684b 100644 --- a/tests/win7/CMakeLists.txt +++ b/tests/win7/CMakeLists.txt @@ -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 ) From b946d295369e9dfe0504c7cc101affdf0ac5ab45 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 21 Feb 2024 00:53:19 +0800 Subject: [PATCH 6/8] Remove Toolhelp32Test from COMMON_SOURCES --- tests/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 99434393f..d5f7c7436 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -75,7 +75,6 @@ set(COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/WistdTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wiTest.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../natvis/wil.natvis - ${CMAKE_CURRENT_SOURCE_DIR}/Toolhelp32Tests.cpp ) if (MSVC) From 091494e68da046f8f83796a383b0dc19240d47f5 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 20 Apr 2024 01:10:44 +0800 Subject: [PATCH 7/8] Fix: Suggested fixes from PR #438 --- include/wil/toolhelp32.h | 242 +++++++++++++++++++++++++++++++++++--- tests/Toolhelp32Tests.cpp | 7 +- 2 files changed, 227 insertions(+), 22 deletions(-) diff --git a/include/wil/toolhelp32.h b/include/wil/toolhelp32.h index 587212d87..e5b0db9fd 100644 --- a/include/wil/toolhelp32.h +++ b/include/wil/toolhelp32.h @@ -1,19 +1,32 @@ -#include "resource.h" +//********************************************************* +// +// Copyright (c) Microsoft. All rights reserved. +// This code is licensed under the MIT License. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. +// +//********************************************************* #ifndef __WIL_TOOLHELP32_INCLUDED #define __WIL_TOOLHELP32_INCLUDED #include #include +#include "resource.h" namespace wil { namespace details { template - void do_enum_snapshot(HANDLE handle, TEntry& entry, TEnumApi&& enumApiFirst, TEnumApi&& enumApiNext, TCallback&& callback) + auto do_enum_snapshot(HANDLE handle, TEntry& entry, TEnumApi&& enumApiFirst, TEnumApi&& enumApiNext, TCallback&& callback) { + if (handle == INVALID_HANDLE_VALUE) + return E_HANDLE; + using result_t = decltype(callback(TEntry{})); bool enumResult = enumApiFirst(handle, &entry); if (!enumResult) - return; + return E_ABORT; do { @@ -24,7 +37,7 @@ namespace details else if constexpr (wistd::is_same_v) { if (callback(entry)) - return; + return S_OK; } else { @@ -36,15 +49,17 @@ namespace details } enumResult = enumApiNext(handle, &entry); } while (enumResult); + return S_OK; } } // namespace details +#pragma region Process template -void for_each_process(TCallback&& callback) +auto for_each_process_nothrow(TCallback&& callback) { PROCESSENTRY32 entry{}; entry.dwSize = sizeof(entry); - details::do_enum_snapshot( + return details::do_enum_snapshot( unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)}.get(), entry, &Process32First, @@ -53,11 +68,27 @@ void for_each_process(TCallback&& callback) } template -void for_each_thread(TCallback&& callback) +void for_each_process_failfast(TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_process_nothrow(callback)); +} + +#ifdef WIL_ENABLE_EXCEPTIONS +template +void for_each_process(TCallback&& callback) +{ + THROW_IF_FAILED(for_each_process_nothrow(callback)); +} +#endif +#pragma endregion + +#pragma region Thread +template +auto for_each_system_thread_nothrow(TCallback&& callback) { THREADENTRY32 entry{}; entry.dwSize = sizeof(entry); - details::do_enum_snapshot( + return details::do_enum_snapshot( unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0)}.get(), entry, &Thread32First, @@ -66,12 +97,68 @@ void for_each_thread(TCallback&& callback) } template -void for_each_module(TCallback&& callback, bool include32For64Bit = false) +void for_each_system_thread_failfast(TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_system_thread_nothrow(callback)); +} + +template +auto for_each_process_thread_nothrow(DWORD pid, TCallback&& callback) +{ + return for_each_system_thread_nothrow([&](THREADENTRY32 const& entry) { + if (entry.th32OwnerProcessID == pid) + callback(entry); + }); +} + +template +auto for_each_process_thread_nothrow(TCallback&& callback) +{ + return for_each_process_thread_nothrow(GetCurrentProcessId(), callback); +} + +template +void for_each_process_thread_failfast(DWORD pid, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_process_thread_nothrow(pid, callback)); +} + +template +void for_each_process_thread_failfast(TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_process_thread_nothrow(callback)); +} + +#ifdef WIL_ENABLE_EXCEPTIONS +template +void for_each_system_thread(TCallback&& callback) +{ + THROW_IF_FAILED(for_each_system_thread_nothrow(callback)); +} + +template +void for_each_process_thread(DWORD pid, TCallback&& callback) +{ + THROW_IF_FAILED(for_each_process_thread_nothrow(pid, callback)); +} + +template +void for_each_process_thread(TCallback&& callback) +{ + THROW_IF_FAILED(for_each_process_thread_nothrow(callback)); +} + +#endif +#pragma endregion + +#pragma region Module +template +auto for_each_module_nothrow(DWORD pid, bool include32BitModule, TCallback&& callback) { MODULEENTRY32 entry{}; entry.dwSize = sizeof(entry); - details::do_enum_snapshot( - unique_handle{CreateToolhelp32Snapshot(include32For64Bit ? TH32CS_SNAPMODULE32 : TH32CS_SNAPMODULE, 0)}.get(), + return details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | (include32BitModule ? TH32CS_SNAPMODULE32 : 0), pid)}.get(), entry, &Module32First, &Module32Next, @@ -79,12 +166,64 @@ void for_each_module(TCallback&& callback, bool include32For64Bit = false) } template -void for_each_heap_list(TCallback&& callback) +auto for_each_module_nothrow(bool include32BitModule, TCallback&& callback) +{ + return for_each_module_nothrow(0, include32BitModule, callback); +} + +template +auto for_each_module_nothrow(TCallback&& callback) +{ + return for_each_module_nothrow(true, callback); +} + +template +void for_each_module_failfast(DWORD pid, bool include32BitModule, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_module_nothrow(pid, include32BitModule, callback)); +} + +template +void for_each_module_failfast(bool include32BitModule, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_module_nothrow(0, include32BitModule, callback)); +} + +template +void for_each_module_failfast(TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_module_nothrow(callback)); +} + +#ifdef WIL_ENABLE_EXCEPTIONS +template +void for_each_module(DWORD pid, bool include32BitModule, TCallback&& callback) +{ + THROW_IF_FAILED(for_each_module_nothrow(pid, include32BitModule, callback)); +} + +template +void for_each_module(bool include32BitModule, TCallback&& callback) +{ + THROW_IF_FAILED(for_each_module_nothrow(0, include32BitModule, callback)); +} + +template +void for_each_module(TCallback&& callback) +{ + THROW_IF_FAILED(for_each_module_nothrow(callback)); +} +#endif +#pragma endregion + +#pragma region HeapList +template +auto for_each_heap_list_nothrow(DWORD pid, TCallback&& callback) { HEAPLIST32 entry{}; entry.dwSize = sizeof(entry); - details::do_enum_snapshot( - unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, 0)}.get(), + return details::do_enum_snapshot( + unique_handle{CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST, pid)}.get(), entry, &Heap32ListFirst, &Heap32ListNext, @@ -92,14 +231,51 @@ void for_each_heap_list(TCallback&& callback) } template -void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurrentProcessId()) +auto for_each_heap_list_nothrow(TCallback&& callback) +{ + return for_each_heap_list_nothrow(0, callback); +} + +template +void for_each_heap_list_failfast(DWORD pid, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_heap_list_nothrow(pid, callback)); +} + +template +void for_each_heap_list_failfast(TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_heap_list_nothrow(callback)); +} + +#ifdef WIL_ENABLE_EXCEPTIONS +template +void for_each_heap_list(DWORD pid, TCallback&& callback) +{ + THROW_IF_FAILED(for_each_heap_list_nothrow(pid, callback)); +} + +template +void for_each_heap_list(TCallback&& callback) +{ + THROW_IF_FAILED(for_each_heap_list_nothrow(callback)); +} +#endif +#pragma endregion + +#pragma region Heap +template +auto for_each_heap_nothrow(DWORD pid, ULONG_PTR heapId, TCallback&& callback) { using result_t = decltype(callback(HEAPENTRY32{})); HEAPENTRY32 entry{}; entry.dwSize = sizeof(entry); - bool enumResult = Heap32First(&entry, pid, heapId); + if (!Heap32First(&entry, pid, heapId)) + return E_ABORT; + + bool enumResult = true; do { if constexpr (wistd::is_void_v) @@ -109,7 +285,7 @@ void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurren else if constexpr (wistd::is_same_v) { if (callback(entry)) - return; + return S_OK; } else { @@ -121,13 +297,41 @@ void for_each_heap(TCallback&& callback, ULONG_PTR heapId, DWORD pid = GetCurren } enumResult = Heap32Next(&entry); } while (enumResult); + return S_OK; +} + +template +auto for_each_heap_nothrow(ULONG_PTR heapId, TCallback&& callback) +{ + return for_each_heap_nothrow(GetCurrentProcessId(), heapId, callback); +} + +template +void for_each_heap_failfast(DWORD pid, ULONG_PTR heapId, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_heap_nothrow(pid, heapId, callback)); +} + +template +void for_each_heap_failfast(ULONG_PTR heapId, TCallback&& callback) +{ + FAIL_FAST_IF_FAILED(for_each_heap_nothrow(heapId, callback)); +} + +#ifdef WIL_ENABLE_EXCEPTIONS +template +void for_each_heap(DWORD pid, ULONG_PTR heapId, TCallback&& callback) +{ + THROW_IF_FAILED(for_each_heap_nothrow(pid, heapId, callback)); } template -void for_each_heap(TCallback&& callback, HEAPLIST32 const& heapList, DWORD pid = GetCurrentProcessId()) +void for_each_heap(ULONG_PTR heapId, TCallback&& callback) { - for_each_heap(wistd::forward(callback), heapList.th32HeapID, pid); + THROW_IF_FAILED(for_each_heap_nothrow(heapId, callback)); } +#endif +#pragma endregion } // namespace wil #endif \ No newline at end of file diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp index a47218a32..0d1d98efb 100644 --- a/tests/Toolhelp32Tests.cpp +++ b/tests/Toolhelp32Tests.cpp @@ -19,7 +19,7 @@ TEST_CASE("Toolhelp32", "[EnumModules]") TEST_CASE("Toolhelp32", "[EnumThreads]") { - wil::for_each_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) { + wil::for_each_system_thread([pid = GetCurrentProcessId()](THREADENTRY32 const& entry) { if (entry.th32OwnerProcessID == pid) { REQUIRE_FALSE(entry.th32ThreadID == 0); @@ -39,10 +39,11 @@ TEST_CASE("Toolhelp32", "[EnumHeap]") wil::for_each_heap_list([](HEAPLIST32 const& heapListEntry) { REQUIRE_FALSE(heapListEntry.th32HeapID == 0); wil::for_each_heap( + heapListEntry.th32HeapID, [](HEAPENTRY32 const& heapEntry) { REQUIRE_FALSE(heapEntry.dwAddress == 0); - }, - heapListEntry); + } + ); return false; }); } \ No newline at end of file From b78d3c8a1bfead403d6d8297089d83ecf93a72c2 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 20 Apr 2024 01:20:00 +0800 Subject: [PATCH 8/8] Fix test not formated --- tests/Toolhelp32Tests.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/Toolhelp32Tests.cpp b/tests/Toolhelp32Tests.cpp index 0d1d98efb..2a56545d2 100644 --- a/tests/Toolhelp32Tests.cpp +++ b/tests/Toolhelp32Tests.cpp @@ -38,12 +38,9 @@ TEST_CASE("Toolhelp32", "[EnumHeap]") { wil::for_each_heap_list([](HEAPLIST32 const& heapListEntry) { REQUIRE_FALSE(heapListEntry.th32HeapID == 0); - wil::for_each_heap( - heapListEntry.th32HeapID, - [](HEAPENTRY32 const& heapEntry) { - REQUIRE_FALSE(heapEntry.dwAddress == 0); - } - ); + wil::for_each_heap(heapListEntry.th32HeapID, [](HEAPENTRY32 const& heapEntry) { + REQUIRE_FALSE(heapEntry.dwAddress == 0); + }); return false; }); } \ No newline at end of file