feat: Display process icons in process memory provider

This commit is contained in:
WerWolv 2023-01-03 16:34:22 +01:00
parent ff91335011
commit 3a117b3bed
4 changed files with 66 additions and 7 deletions

View File

@ -13,6 +13,15 @@
namespace hex::plugin::builtin { namespace hex::plugin::builtin {
namespace {
[[maybe_unused]] void printThemeData(const auto &colorMap, const auto &colors) {
for (const auto &[name, id] : colorMap)
fmt::print("\"{}\": \"#{:08X}\",\n", name, hex::changeEndianess(colors[id], std::endian::big));
}
}
void registerThemeHandlers() { void registerThemeHandlers() {
api::ThemeManager::addThemeHandler("imgui", [](const std::string &key, const std::string &value) { api::ThemeManager::addThemeHandler("imgui", [](const std::string &key, const std::string &value) {
const static std::map<std::string, ImGuiCol> ColorMap = { const static std::map<std::string, ImGuiCol> ColorMap = {

View File

@ -41,15 +41,15 @@ namespace hex::plugin::builtin {
} }
else { else {
View::showErrorPopup("hex.builtin.view.provider_settings.load_error"_lang); View::showErrorPopup("hex.builtin.view.provider_settings.load_error"_lang);
ImHexApi::Provider::remove(provider); TaskManager::doLater([=] { ImHexApi::Provider::remove(provider); });
} }
} }
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Button("hex.builtin.common.cancel"_lang)) { if (ImGui::Button("hex.builtin.common.cancel"_lang)) {
ImHexApi::Provider::remove(provider);
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
TaskManager::doLater([=] { ImHexApi::Provider::remove(provider); });
} }
} }

View File

@ -5,6 +5,9 @@
#include <windows.h> #include <windows.h>
#include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h>
#include <array> #include <array>
#include <mutex> #include <mutex>
#include <string_view> #include <string_view>
@ -62,6 +65,7 @@ namespace hex::plugin::windows {
struct Process { struct Process {
u32 id; u32 id;
std::string name; std::string name;
ImGui::Texture icon;
}; };
struct MemoryRegion { struct MemoryRegion {
@ -74,7 +78,7 @@ namespace hex::plugin::windows {
}; };
std::vector<Process> m_processes; std::vector<Process> m_processes;
std::optional<Process> m_selectedProcess; Process *m_selectedProcess = nullptr;
std::set<MemoryRegion> m_memoryRegions; std::set<MemoryRegion> m_memoryRegions;

View File

@ -2,6 +2,7 @@
#include <windows.h> #include <windows.h>
#include <psapi.h> #include <psapi.h>
#include <shellapi.h>
#include <imgui.h> #include <imgui.h>
#include <hex/ui/imgui_imhex_extensions.h> #include <hex/ui/imgui_imhex_extensions.h>
@ -105,6 +106,8 @@ namespace hex::plugin::windows {
processIds.resize(numProcesses / sizeof(DWORD)); processIds.resize(numProcesses / sizeof(DWORD));
auto dc = GetDC(nullptr);
ON_SCOPE_EXIT { ReleaseDC(nullptr, dc); };
for (auto processId : processIds) { for (auto processId : processIds) {
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
if (processHandle == nullptr) if (processHandle == nullptr)
@ -116,14 +119,54 @@ namespace hex::plugin::windows {
if (GetModuleBaseNameA(processHandle, nullptr, processName, MAX_PATH) == 0) if (GetModuleBaseNameA(processHandle, nullptr, processName, MAX_PATH) == 0)
continue; continue;
this->m_processes.push_back({ processId, processName }); ImGui::Texture texture;
{
HMODULE moduleHandle = nullptr;
DWORD numModules = 0;
if (EnumProcessModules(processHandle, &moduleHandle, sizeof(HMODULE), &numModules) != FALSE) {
char modulePath[MAX_PATH];
if (GetModuleFileNameExA(processHandle, moduleHandle, modulePath, MAX_PATH) != FALSE) {
SHFILEINFOA fileInfo;
if (SHGetFileInfoA(modulePath, 0, &fileInfo, sizeof(SHFILEINFOA), SHGFI_ICON | SHGFI_SMALLICON) > 0) {
ON_SCOPE_EXIT { DestroyIcon(fileInfo.hIcon); };
ICONINFO iconInfo;
if (GetIconInfo(fileInfo.hIcon, &iconInfo) != FALSE) {
ON_SCOPE_EXIT { DeleteObject(iconInfo.hbmColor); DeleteObject(iconInfo.hbmMask); };
BITMAP bitmap;
if (GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bitmap) > 0) {
BITMAPINFO bitmapInfo = { };
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = bitmap.bmWidth;
bitmapInfo.bmiHeader.biHeight = -bitmap.bmHeight;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 32;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
std::vector<u32> pixels(bitmap.bmWidth * bitmap.bmHeight * 4);
if (GetDIBits(dc, iconInfo.hbmColor, 0, bitmap.bmHeight, pixels.data(), &bitmapInfo, DIB_RGB_COLORS) > 0) {
for (auto &pixel : pixels)
pixel = (pixel & 0xFF00FF00) | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16);
texture = ImGui::Texture((u8*)pixels.data(), pixels.size(), bitmap.bmWidth, bitmap.bmHeight);
}
}
}
}
}
}
}
this->m_processes.push_back({ processId, processName, std::move(texture) });
} }
} }
if (this->m_enumerationFailed) { if (this->m_enumerationFailed) {
ImGui::TextUnformatted("hex.windows.provider.process_memory.enumeration_failed"_lang); ImGui::TextUnformatted("hex.windows.provider.process_memory.enumeration_failed"_lang);
} else { } else {
if (ImGui::BeginTable("##process_table", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 500_scaled))) { if (ImGui::BeginTable("##process_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 500_scaled))) {
ImGui::TableSetupColumn("##icon");
ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_id"_lang); ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_id"_lang);
ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_name"_lang); ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_name"_lang);
ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupScrollFreeze(0, 1);
@ -134,12 +177,15 @@ namespace hex::plugin::windows {
ImGui::PushID(process.id); ImGui::PushID(process.id);
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Image(process.icon, process.icon.getSize());
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%d", process.id); ImGui::Text("%d", process.id);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (ImGui::Selectable(process.name.c_str(), this->m_selectedProcess.has_value() && process.id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns)) if (ImGui::Selectable(process.name.c_str(), this->m_selectedProcess != nullptr && process.id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process.icon.getSize().y)))
this->m_selectedProcess = process; this->m_selectedProcess = &process;
ImGui::PopID(); ImGui::PopID();
} }