From 3e736b36b6aa603eefe6e5b399162d4b9db1331e Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sun, 12 Dec 2021 00:41:44 +0100 Subject: [PATCH] api: Refactored providers to allow for loading interfaces and config views --- plugins/builtin/CMakeLists.txt | 2 +- .../content/providers/file_provider.hpp | 20 +++--- .../content/providers/gdb_provider.hpp | 30 ++++---- .../content/views/view_information.hpp | 2 + ...iew_gdb.hpp => view_provider_settings.hpp} | 10 ++- .../content/providers/file_provider.cpp | 28 +++++--- .../source/content/providers/gdb_provider.cpp | 72 +++++++++++++++---- plugins/builtin/source/content/views.cpp | 4 +- .../builtin/source/content/views/view_gdb.cpp | 51 ------------- .../source/content/views/view_hexeditor.cpp | 9 ++- .../source/content/views/view_information.cpp | 47 ++++++------ .../content/views/view_provider_settings.cpp | 65 +++++++++++++++++ plugins/builtin/source/lang/de_DE.cpp | 1 + plugins/builtin/source/lang/en_US.cpp | 1 + plugins/builtin/source/lang/it_IT.cpp | 1 + plugins/builtin/source/lang/zh_CN.cpp | 1 + plugins/libimhex/include/hex/api/event.hpp | 1 + .../include/hex/providers/provider.hpp | 40 ++++++----- plugins/libimhex/source/api/imhex_api.cpp | 2 + .../libimhex/source/providers/provider.cpp | 21 ++++++ source/window/window.cpp | 3 + tests/algorithms/include/test_provider.hpp | 3 + .../include/test_provider.hpp | 3 + 23 files changed, 272 insertions(+), 145 deletions(-) rename plugins/builtin/include/content/views/{view_gdb.hpp => view_provider_settings.hpp} (64%) delete mode 100644 plugins/builtin/source/content/views/view_gdb.cpp create mode 100644 plugins/builtin/source/content/views/view_provider_settings.cpp diff --git a/plugins/builtin/CMakeLists.txt b/plugins/builtin/CMakeLists.txt index b2599766d..91fa5e900 100644 --- a/plugins/builtin/CMakeLists.txt +++ b/plugins/builtin/CMakeLists.txt @@ -38,7 +38,7 @@ add_library(${PROJECT_NAME} SHARED source/content/views/view_constants.cpp source/content/views/view_store.cpp source/content/views/view_diff.cpp - source/content/views/view_gdb.cpp + source/content/views/view_provider_settings.cpp source/math_evaluator.cpp diff --git a/plugins/builtin/include/content/providers/file_provider.hpp b/plugins/builtin/include/content/providers/file_provider.hpp index 9bd70de69..efd74ff70 100644 --- a/plugins/builtin/include/content/providers/file_provider.hpp +++ b/plugins/builtin/include/content/providers/file_provider.hpp @@ -21,11 +21,11 @@ namespace hex::plugin::builtin::prv { explicit FileProvider(); ~FileProvider() override; - bool isAvailable() const override; - bool isReadable() const override; - bool isWritable() const override; - bool isResizable() const override; - bool isSavable() const override; + [[nodiscard]] bool isAvailable() const override; + [[nodiscard]] bool isReadable() const override; + [[nodiscard]] bool isWritable() const override; + [[nodiscard]] bool isResizable() const override; + [[nodiscard]] bool isSavable() const override; void read(u64 offset, void *buffer, size_t size, bool overlays) override; void write(u64 offset, const void *buffer, size_t size) override; @@ -33,7 +33,7 @@ namespace hex::plugin::builtin::prv { void readRaw(u64 offset, void *buffer, size_t size) override; void writeRaw(u64 offset, const void *buffer, size_t size) override; - size_t getActualSize() const override; + [[nodiscard]] size_t getActualSize() const override; void save() override; void saveAs(const std::string &path) override; @@ -41,10 +41,12 @@ namespace hex::plugin::builtin::prv { [[nodiscard]] std::string getName() const override; [[nodiscard]] std::vector> getDataInformation() const override; - void open(const std::string &path); - void close(); + void setPath(const std::string &path); - private: + [[nodiscard]] bool open() override; + void close() override; + + protected: #if defined(OS_WINDOWS) HANDLE m_file = INVALID_HANDLE_VALUE; HANDLE m_mapping = INVALID_HANDLE_VALUE; diff --git a/plugins/builtin/include/content/providers/gdb_provider.hpp b/plugins/builtin/include/content/providers/gdb_provider.hpp index 65dae1e18..0940c02ea 100644 --- a/plugins/builtin/include/content/providers/gdb_provider.hpp +++ b/plugins/builtin/include/content/providers/gdb_provider.hpp @@ -14,11 +14,11 @@ class GDBProvider : public hex::prv::Provider { explicit GDBProvider(); ~GDBProvider() override; - bool isAvailable() const override; - bool isReadable() const override; - bool isWritable() const override; - bool isResizable() const override; - bool isSavable() const override; + [[nodiscard]] bool isAvailable() const override; + [[nodiscard]] bool isReadable() const override; + [[nodiscard]] bool isWritable() const override; + [[nodiscard]] bool isResizable() const override; + [[nodiscard]] bool isSavable() const override; void read(u64 offset, void *buffer, size_t size, bool overlays) override; void write(u64 offset, const void *buffer, size_t size) override; @@ -26,7 +26,7 @@ class GDBProvider : public hex::prv::Provider { void readRaw(u64 offset, void *buffer, size_t size) override; void writeRaw(u64 offset, const void *buffer, size_t size) override; - size_t getActualSize() const override; + [[nodiscard]] size_t getActualSize() const override; void save() override; void saveAs(const std::string &path) override; @@ -34,20 +34,26 @@ class GDBProvider : public hex::prv::Provider { [[nodiscard]] std::string getName() const override; [[nodiscard]] std::vector> getDataInformation() const override; - void connect(const std::string &address, u16 port); - void disconnect(); - bool isConnected(); + [[nodiscard]] bool open() override; + void close() override; - private: + [[nodiscard]] bool isConnected() const; + + [[nodiscard]] bool hasLoadInterface() const override { return true; } + void drawLoadInterface() override; + + protected: hex::Socket m_socket; std::string m_ipAddress; - u16 m_port; + int m_port; + + constexpr static size_t CacheLineSize = 0x1000; struct CacheLine { u64 address; - std::array data; + std::array data; }; std::list m_cache; diff --git a/plugins/builtin/include/content/views/view_information.hpp b/plugins/builtin/include/content/views/view_information.hpp index 95a9dbdb5..0122295a8 100644 --- a/plugins/builtin/include/content/views/view_information.hpp +++ b/plugins/builtin/include/content/views/view_information.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -30,6 +31,7 @@ namespace hex::plugin::builtin { std::array m_valueCounts = { 0 }; bool m_analyzing = false; + std::atomic m_bytesAnalyzed; std::pair m_analyzedRegion = { 0, 0 }; diff --git a/plugins/builtin/include/content/views/view_gdb.hpp b/plugins/builtin/include/content/views/view_provider_settings.hpp similarity index 64% rename from plugins/builtin/include/content/views/view_gdb.hpp rename to plugins/builtin/include/content/views/view_provider_settings.hpp index 42447eaba..87b927319 100644 --- a/plugins/builtin/include/content/views/view_gdb.hpp +++ b/plugins/builtin/include/content/views/view_provider_settings.hpp @@ -10,19 +10,17 @@ namespace hex::plugin::builtin { - class ViewGDB : public hex::View { + class ViewProviderSettings : public hex::View { public: - ViewGDB(); + ViewProviderSettings(); + ~ViewProviderSettings(); void drawContent() override; + void drawAlwaysVisible() override; bool hasViewMenuItemEntry() override; bool isAvailable(); - - private: - std::string m_address; - int m_port = 0; }; } \ No newline at end of file diff --git a/plugins/builtin/source/content/providers/file_provider.cpp b/plugins/builtin/source/content/providers/file_provider.cpp index b293c0a59..c9e3e2247 100644 --- a/plugins/builtin/source/content/providers/file_provider.cpp +++ b/plugins/builtin/source/content/providers/file_provider.cpp @@ -130,7 +130,7 @@ namespace hex::plugin::builtin::prv { ::close(handle); #endif - this->open(this->m_path); + this->open(); } size_t FileProvider::getActualSize() const { @@ -156,8 +156,11 @@ namespace hex::plugin::builtin::prv { return result; } - void FileProvider::open(const std::string &path) { + void FileProvider::setPath(const std::string &path) { this->m_path = path; + } + + bool FileProvider::open() { this->m_fileStatsValid = stat(this->m_path.data(), &this->m_fileStats) == 0; this->m_readable = true; @@ -194,12 +197,12 @@ namespace hex::plugin::builtin::prv { }; if (this->m_file == nullptr || this->m_file == INVALID_HANDLE_VALUE) { - return; + return false; } this->m_mapping = CreateFileMapping(this->m_file, nullptr, PAGE_READWRITE, fileSize.HighPart, fileSize.LowPart, nullptr); if (this->m_mapping == nullptr || this->m_mapping == INVALID_HANDLE_VALUE) { - return; + return false; } auto mappingCleanup = SCOPE_GUARD { @@ -211,7 +214,7 @@ namespace hex::plugin::builtin::prv { this->m_mappedFile = MapViewOfFile(this->m_mapping, FILE_MAP_ALL_ACCESS, 0, 0, this->m_fileSize); if (this->m_mappedFile == nullptr) { this->m_readable = false; - return; + return false; } fileCleanup.release(); @@ -220,7 +223,7 @@ namespace hex::plugin::builtin::prv { ProjectFile::setFilePath(this->m_path); #else - this->m_file = ::open(this->m_path.data(), O_RDWR); + this->m_file = ::open(this->m_path.data(), O_RDWR); if (this->m_file == -1) { this->m_file = ::open(this->m_path.data(), O_RDONLY); this->m_writable = false; @@ -228,14 +231,21 @@ namespace hex::plugin::builtin::prv { if (this->m_file == -1) { this->m_readable = false; - return; + return false; } this->m_fileSize = this->m_fileStats.st_size; - this->m_mappedFile = mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0); + this->m_mappedFile = ::mmap(nullptr, this->m_fileSize, PROT_READ | PROT_WRITE, MAP_PRIVATE, this->m_file, 0); + if (this->m_mappedFile == nullptr) { + ::close(this->m_file); + this->m_file = -1; - #endif + return false; + } + #endif + + return true; } void FileProvider::close() { diff --git a/plugins/builtin/source/content/providers/gdb_provider.cpp b/plugins/builtin/source/content/providers/gdb_provider.cpp index e6d43e67b..3f4fd97cc 100644 --- a/plugins/builtin/source/content/providers/gdb_provider.cpp +++ b/plugins/builtin/source/content/providers/gdb_provider.cpp @@ -77,6 +77,19 @@ namespace hex::plugin::builtin::prv { return data; } + void writeMemory(Socket &socket, u64 address, const void *buffer, size_t size) { + std::vector bytes(size); + std::memcpy(bytes.data(), buffer, size); + + std::string byteString = crypt::encode16(bytes); + + std::string packet = createPacket(hex::format("M{:X},{:X}:{}", address, size, byteString)); + + socket.writeString(packet); + + auto receivedPacket = socket.readString(3); + } + bool enableNoAckMode(Socket &socket) { socket.writeString(createPacket("QStartNoAckMode")); @@ -104,7 +117,7 @@ namespace hex::plugin::builtin::prv { } GDBProvider::~GDBProvider() { - this->disconnect(); + this->close(); } @@ -135,9 +148,9 @@ namespace hex::plugin::builtin::prv { offset -= this->getBaseAddress(); - u64 alignedOffset = offset - (offset & 0xFFF); + u64 alignedOffset = offset - (offset % CacheLineSize); - { + if (size <= CacheLineSize) { std::scoped_lock lock(this->m_cacheLock); const auto &cacheLine = std::find_if(this->m_cache.begin(), this->m_cache.end(), [&](auto &line){ @@ -154,7 +167,15 @@ namespace hex::plugin::builtin::prv { } if (cacheLine != this->m_cache.end()) - std::memcpy(buffer, &cacheLine->data[0] + (offset & 0xFFF), size); + std::memcpy(buffer, &cacheLine->data[0] + (offset % CacheLineSize), size); + } else { + while (size > 0) { + size_t readSize = std::min(size, CacheLineSize); + this->readRaw(offset, buffer, readSize); + + size -= readSize; + offset += readSize; + } } for (u64 i = 0; i < size; i++) @@ -166,7 +187,12 @@ namespace hex::plugin::builtin::prv { } void GDBProvider::write(u64 offset, const void *buffer, size_t size) { + if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0) + return; + offset -= this->getBaseAddress(); + + gdb::writeMemory(this->m_socket, offset, buffer, size); } void GDBProvider::readRaw(u64 offset, void *buffer, size_t size) { @@ -178,7 +204,10 @@ namespace hex::plugin::builtin::prv { } void GDBProvider::writeRaw(u64 offset, const void *buffer, size_t size) { + if ((offset - this->getBaseAddress()) > (this->getActualSize() - size) || buffer == nullptr || size == 0) + return; + gdb::writeMemory(this->m_socket, offset, buffer, size); } void GDBProvider::save() { @@ -200,7 +229,7 @@ namespace hex::plugin::builtin::prv { std::string GDBProvider::getName() const { std::string address, port; - if (this->m_ipAddress.empty()) { + if (!this->isConnected()) { address = "-"; port = "-"; } else { @@ -212,19 +241,18 @@ namespace hex::plugin::builtin::prv { } std::vector> GDBProvider::getDataInformation() const { - return { }; + return { + { "hex.builtin.provider.gdb.server"_lang, hex::format("{}:{}", this->m_ipAddress, this->m_port) }, + }; } - void GDBProvider::connect(const std::string &address, u16 port) { - this->m_socket.connect(address, port); + bool GDBProvider::open() { + this->m_socket.connect(this->m_ipAddress, this->m_port); if (!gdb::enableNoAckMode(this->m_socket)) { this->m_socket.disconnect(); - return; + return false; } - this->m_ipAddress = address; - this->m_port = port; - if (this->m_socket.isConnected()) { this->m_cacheUpdateThread = std::thread([this]() { auto cacheLine = this->m_cache.begin(); @@ -250,10 +278,14 @@ namespace hex::plugin::builtin::prv { std::this_thread::sleep_for(100ms); } }); + + return true; + } else { + return false; } } - void GDBProvider::disconnect() { + void GDBProvider::close() { this->m_socket.disconnect(); if (this->m_cacheUpdateThread.joinable()) { @@ -261,8 +293,20 @@ namespace hex::plugin::builtin::prv { } } - bool GDBProvider::isConnected() { + bool GDBProvider::isConnected() const { return this->m_socket.isConnected(); } + + + void GDBProvider::drawLoadInterface() { + ImGui::InputText("hex.builtin.view.gdb.ip"_lang, this->m_ipAddress.data(), this->m_ipAddress.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &this->m_ipAddress); + ImGui::InputInt("hex.builtin.view.gdb.port"_lang, &this->m_port, 0, 0); + + if (this->m_port < 0) + this->m_port = 0; + else if (this->m_port > 0xFFFF) + this->m_port = 0xFFFF; + } + } \ No newline at end of file diff --git a/plugins/builtin/source/content/views.cpp b/plugins/builtin/source/content/views.cpp index 843a40ae5..43dd81162 100644 --- a/plugins/builtin/source/content/views.cpp +++ b/plugins/builtin/source/content/views.cpp @@ -17,7 +17,7 @@ #include "content/views/view_constants.hpp" #include "content/views/view_store.hpp" #include "content/views/view_diff.hpp" -#include "content/views/view_gdb.hpp" +#include "content/views/view_provider_settings.hpp" namespace hex::plugin::builtin { @@ -41,7 +41,7 @@ namespace hex::plugin::builtin { ContentRegistry::Views::add(); ContentRegistry::Views::add(); ContentRegistry::Views::add(); - ContentRegistry::Views::add(); + ContentRegistry::Views::add(); } } \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_gdb.cpp b/plugins/builtin/source/content/views/view_gdb.cpp deleted file mode 100644 index c5c23b39c..000000000 --- a/plugins/builtin/source/content/views/view_gdb.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "content/views/view_gdb.hpp" - -#include "content/providers/gdb_provider.hpp" - -namespace hex::plugin::builtin { - - ViewGDB::ViewGDB() : hex::View("hex.builtin.view.gdb.name") { - this->m_address.reserve(3 * 4 + 4); - this->m_port = 0; - } - - void ViewGDB::drawContent() { - if (ImGui::Begin(View::toWindowName("hex.builtin.view.gdb.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { - ImGui::Header("hex.builtin.view.gdb.settings"_lang); - ImGui::InputText("hex.builtin.view.gdb.ip"_lang, this->m_address.data(), this->m_address.capacity(), ImGuiInputTextFlags_CallbackEdit, ImGui::UpdateStringSizeCallback, &this->m_address); - ImGui::InputInt("hex.builtin.view.gdb.port"_lang, &this->m_port, 0, 0); - - if (this->m_port < 0) - this->m_port = 0; - else if (this->m_port > 0xFFFF) - this->m_port = 0xFFFF; - - ImGui::NewLine(); - - auto provider = dynamic_cast(hex::ImHexApi::Provider::get()); - if (provider != nullptr) { - if (!provider->isConnected()) { - if (ImGui::Button("hex.builtin.view.gdb.connect"_lang)) { - provider->connect(this->m_address, this->m_port); - } - } else { - if (ImGui::Button("hex.builtin.view.gdb.disconnect"_lang)) { - provider->disconnect(); - } - } - } - } - ImGui::End(); - } - - bool ViewGDB::hasViewMenuItemEntry() { - return this->isAvailable(); - } - - bool ViewGDB::isAvailable() { - auto provider = hex::ImHexApi::Provider::get(); - - return provider != nullptr && dynamic_cast(provider) != nullptr; - } - -} \ No newline at end of file diff --git a/plugins/builtin/source/content/views/view_hexeditor.cpp b/plugins/builtin/source/content/views/view_hexeditor.cpp index 986c90644..5fa481c87 100644 --- a/plugins/builtin/source/content/views/view_hexeditor.cpp +++ b/plugins/builtin/source/content/views/view_hexeditor.cpp @@ -713,8 +713,13 @@ namespace hex::plugin::builtin { hex::prv::Provider *provider = nullptr; EventManager::post("hex.builtin.provider.file", &provider); - if (auto fileProvider = dynamic_cast(provider)) - fileProvider->open(path); + if (auto fileProvider = dynamic_cast(provider)) { + fileProvider->setPath(path); + if (!fileProvider->open()) { + View::showErrorPopup("hex.builtin.view.hexeditor.error.open"_lang); + return; + } + } if (!provider->isWritable()) { this->m_memoryEditor.ReadOnly = true; diff --git a/plugins/builtin/source/content/views/view_information.cpp b/plugins/builtin/source/content/views/view_information.cpp index cc78766c1..0a1d90852 100644 --- a/plugins/builtin/source/content/views/view_information.cpp +++ b/plugins/builtin/source/content/views/view_information.cpp @@ -51,23 +51,18 @@ namespace hex::plugin::builtin { EventManager::unsubscribe(this); } - static float calculateEntropy(std::array &valueCounts, size_t numBytes) { + static float calculateEntropy(std::array &valueCounts, size_t blockSize) { float entropy = 0; - if (numBytes == 0) - return 0.0F; + for (auto count : valueCounts) { + if (count == 0) continue; - std::array floatValueCounts{ 0 }; - std::copy(valueCounts.begin(), valueCounts.end(), floatValueCounts.begin()); + float probability = static_cast(count) / blockSize; - for (u16 i = 0; i < 256; i++) { - floatValueCounts[i] /= float(numBytes); - - if (floatValueCounts[i] > 0) - entropy -= (floatValueCounts[i] * std::log2(floatValueCounts[i])); + entropy += probability * std::log2(probability); } - return entropy / 8; + return (-entropy) / 8; // log2(256) = 8 } void ViewInformation::analyze() { @@ -93,7 +88,10 @@ namespace hex::plugin::builtin { blockValueCounts[buffer[j]]++; this->m_valueCounts[buffer[j]]++; } + this->m_blockEntropy.push_back(calculateEntropy(blockValueCounts, this->m_blockSize)); + + this->m_bytesAnalyzed = i; } this->m_averageEntropy = calculateEntropy(this->m_valueCounts, provider->getSize()); @@ -128,20 +126,23 @@ namespace hex::plugin::builtin { }, this->m_analyzing); if (this->m_analyzing) { - ImGui::SameLine(); ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang); + ImGui::ProgressBar(this->m_bytesAnalyzed / static_cast(provider->getSize())); + } else { + ImGui::NewLine(); + ImGui::NewLine(); + } + + ImGui::NewLine(); + ImGui::TextUnformatted("hex.builtin.view.information.region"_lang); + ImGui::Separator(); + + for (auto &[name, value] : provider->getDataInformation()) { + ImGui::LabelText(name.c_str(), "%s", value.c_str()); } if (this->m_dataValid) { - ImGui::NewLine(); - ImGui::TextUnformatted("hex.builtin.view.information.region"_lang); - ImGui::Separator(); - - for (auto &[name, value] : provider->getDataInformation()) { - ImGui::LabelText(name.c_str(), "%s", value.c_str()); - } - ImGui::LabelText("hex.builtin.view.information.region"_lang, "0x%llx - 0x%llx", this->m_analyzedRegion.first, this->m_analyzedRegion.second); ImGui::NewLine(); @@ -169,8 +170,8 @@ namespace hex::plugin::builtin { ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_WindowBg)); ImGui::TextUnformatted("hex.builtin.view.information.distribution"_lang); - ImPlot::SetNextPlotLimits(0, 256, 0, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always); - if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock)) { + ImPlot::SetNextPlotLimits(0, 256, 0.5, float(*std::max_element(this->m_valueCounts.begin(), this->m_valueCounts.end())) * 1.1F, ImGuiCond_Always); + if (ImPlot::BeginPlot("##distribution", "Address", "Count", ImVec2(-1,0), ImPlotFlags_NoLegend | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect, ImPlotAxisFlags_Lock, ImPlotAxisFlags_Lock | ImPlotAxisFlags_LogScale)) { static auto x = []{ std::array result{ 0 }; std::iota(result.begin(), result.end(), 0); @@ -188,7 +189,7 @@ namespace hex::plugin::builtin { ImGui::TextUnformatted("hex.builtin.view.information.entropy"_lang); ImPlot::SetNextPlotLimits(0, this->m_blockEntropy.size(), -0.1, 1.1, ImGuiCond_Always); - if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) { + if (ImPlot::BeginPlot("##entropy", "Address", "Entropy", ImVec2(-1,0), ImPlotFlags_CanvasOnly | ImPlotFlags_AntiAliased, ImPlotAxisFlags_Lock | ImPlotAxisFlags_NoTickLabels, ImPlotAxisFlags_Lock)) { ImPlot::PlotLine("##entropy_line", this->m_blockEntropy.data(), this->m_blockEntropy.size()); if (ImPlot::DragLineX("Position", &this->m_entropyHandlePosition, false)) { diff --git a/plugins/builtin/source/content/views/view_provider_settings.cpp b/plugins/builtin/source/content/views/view_provider_settings.cpp new file mode 100644 index 000000000..a5cc0de99 --- /dev/null +++ b/plugins/builtin/source/content/views/view_provider_settings.cpp @@ -0,0 +1,65 @@ +#include "content/views/view_provider_settings.hpp" + +namespace hex::plugin::builtin { + + ViewProviderSettings::ViewProviderSettings() : hex::View("hex.builtin.view.provider_settings.name") { + EventManager::subscribe(this, [](hex::prv::Provider *provider){ + if (provider->hasLoadInterface()) + EventManager::post(View::toWindowName("hex.builtin.view.provider_settings.load_popup")); + }); + } + + ViewProviderSettings::~ViewProviderSettings() { + EventManager::unsubscribe(this); + } + + void ViewProviderSettings::drawContent() { + if (ImGui::Begin(View::toWindowName("hex.builtin.view.provider_settings.name").c_str(), &this->getWindowOpenState(), ImGuiWindowFlags_NoCollapse)) { + auto provider = hex::ImHexApi::Provider::get(); + + if (provider != nullptr) + provider->drawInterface(); + } + ImGui::End(); + } + + void ViewProviderSettings::drawAlwaysVisible() { + ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Appearing, ImVec2(0.5F, 0.5F)); + if (ImGui::BeginPopupModal(View::toWindowName("hex.builtin.view.provider_settings.load_popup").c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + + auto provider = hex::ImHexApi::Provider::get(); + + if (provider != nullptr) { + provider->drawLoadInterface(); + + ImGui::NewLine(); + ImGui::Separator(); + + if (ImGui::Button("hex.common.open"_lang)) { + if (provider->open()) + ImGui::CloseCurrentPopup(); + } + + ImGui::SameLine(); + + if (ImGui::Button("hex.common.cancel"_lang)) { + ImHexApi::Provider::remove(provider); + ImGui::CloseCurrentPopup(); + } + } + + ImGui::EndPopup(); + } + } + + bool ViewProviderSettings::hasViewMenuItemEntry() { + return this->isAvailable(); + } + + bool ViewProviderSettings::isAvailable() { + auto provider = hex::ImHexApi::Provider::get(); + + return provider != nullptr && provider->hasInterface(); + } + +} \ No newline at end of file diff --git a/plugins/builtin/source/lang/de_DE.cpp b/plugins/builtin/source/lang/de_DE.cpp index cf971f8b7..d813b4220 100644 --- a/plugins/builtin/source/lang/de_DE.cpp +++ b/plugins/builtin/source/lang/de_DE.cpp @@ -678,6 +678,7 @@ namespace hex::plugin::builtin { { "hex.builtin.provider.file", "Datei Provider" }, { "hex.builtin.provider.gdb", "GDB Server Provider" }, { "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" }, + { "hex.builtin.provider.gdb.server", "Server" }, }); } diff --git a/plugins/builtin/source/lang/en_US.cpp b/plugins/builtin/source/lang/en_US.cpp index 322ab7dfe..629753566 100644 --- a/plugins/builtin/source/lang/en_US.cpp +++ b/plugins/builtin/source/lang/en_US.cpp @@ -681,6 +681,7 @@ namespace hex::plugin::builtin { { "hex.builtin.provider.file", "File Provider" }, { "hex.builtin.provider.gdb", "GDB Server Provider" }, { "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" }, + { "hex.builtin.provider.gdb.server", "Server" }, }); } diff --git a/plugins/builtin/source/lang/it_IT.cpp b/plugins/builtin/source/lang/it_IT.cpp index 6c0735818..b370cd7ca 100644 --- a/plugins/builtin/source/lang/it_IT.cpp +++ b/plugins/builtin/source/lang/it_IT.cpp @@ -675,6 +675,7 @@ namespace hex::plugin::builtin { //{ "hex.builtin.provider.file", "File Provider" }, //{ "hex.builtin.provider.gdb", "GDB Server Provider" }, //{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" }, + //{ "hex.builtin.provider.gdb.server", "Server" }, }); } diff --git a/plugins/builtin/source/lang/zh_CN.cpp b/plugins/builtin/source/lang/zh_CN.cpp index 64c9333f1..94d1a2ab7 100644 --- a/plugins/builtin/source/lang/zh_CN.cpp +++ b/plugins/builtin/source/lang/zh_CN.cpp @@ -677,6 +677,7 @@ namespace hex::plugin::builtin { //{ "hex.builtin.provider.file", "File Provider" }, //{ "hex.builtin.provider.gdb", "GDB Server Provider" }, //{ "hex.builtin.provider.gdb.name", "GDB Server <{0}:{1}>" }, + //{ "hex.builtin.provider.gdb.server", "Server" }, }); } diff --git a/plugins/libimhex/include/hex/api/event.hpp b/plugins/libimhex/include/hex/api/event.hpp index 1a7251f55..316151145 100644 --- a/plugins/libimhex/include/hex/api/event.hpp +++ b/plugins/libimhex/include/hex/api/event.hpp @@ -107,6 +107,7 @@ namespace hex { EVENT_DEF(EventSettingsChanged); EVENT_DEF(EventAbnormalTermination, int); EVENT_DEF(EventOSThemeChanged); + EVENT_DEF(EventProviderCreated, prv::Provider*); EVENT_DEF(RequestOpenWindow, std::string); EVENT_DEF(RequestSelectionChange, Region); diff --git a/plugins/libimhex/include/hex/providers/provider.hpp b/plugins/libimhex/include/hex/providers/provider.hpp index 6051d9611..eaa805af2 100644 --- a/plugins/libimhex/include/hex/providers/provider.hpp +++ b/plugins/libimhex/include/hex/providers/provider.hpp @@ -19,11 +19,11 @@ namespace hex::prv { Provider(); virtual ~Provider(); - virtual bool isAvailable() const = 0; - virtual bool isReadable() const = 0; - virtual bool isWritable() const = 0; - virtual bool isResizable() const = 0; - virtual bool isSavable() const = 0; + [[nodiscard]] virtual bool isAvailable() const = 0; + [[nodiscard]] virtual bool isReadable() const = 0; + [[nodiscard]] virtual bool isWritable() const = 0; + [[nodiscard]] virtual bool isResizable() const = 0; + [[nodiscard]] virtual bool isSavable() const = 0; virtual void read(u64 offset, void *buffer, size_t size, bool overlays = true); virtual void write(u64 offset, const void *buffer, size_t size); @@ -35,38 +35,46 @@ namespace hex::prv { virtual void readRaw(u64 offset, void *buffer, size_t size) = 0; virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0; - virtual size_t getActualSize() const = 0; + [[nodiscard]] virtual size_t getActualSize() const = 0; void applyOverlays(u64 offset, void *buffer, size_t size); - std::map& getPatches(); - const std::map& getPatches() const; + [[nodiscard]] std::map& getPatches(); + [[nodiscard]] const std::map& getPatches() const; void applyPatches(); [[nodiscard]] Overlay* newOverlay(); void deleteOverlay(Overlay *overlay); [[nodiscard]] const std::list& getOverlays(); - u32 getPageCount() const; - u32 getCurrentPage() const; + [[nodiscard]] u32 getPageCount() const; + [[nodiscard]] u32 getCurrentPage() const; void setCurrentPage(u32 page); virtual void setBaseAddress(u64 address); - virtual u64 getBaseAddress() const; - virtual u64 getCurrentPageAddress() const; - virtual size_t getSize() const; - virtual std::optional getPageOfAddress(u64 address) const; + [[nodiscard]] virtual u64 getBaseAddress() const; + [[nodiscard]] virtual u64 getCurrentPageAddress() const; + [[nodiscard]] virtual size_t getSize() const; + [[nodiscard]] virtual std::optional getPageOfAddress(u64 address) const; [[nodiscard]] virtual std::string getName() const = 0; [[nodiscard]] virtual std::vector> getDataInformation() const = 0; + [[nodiscard]] virtual bool open() = 0; + virtual void close() = 0; + void addPatch(u64 offset, const void *buffer, size_t size); void undo(); void redo(); - bool canUndo() const; - bool canRedo() const; + [[nodiscard]] bool canUndo() const; + [[nodiscard]] bool canRedo() const; + + [[nodiscard]] virtual bool hasLoadInterface() const; + [[nodiscard]] virtual bool hasInterface() const; + virtual void drawLoadInterface(); + virtual void drawInterface(); protected: u32 m_currPage = 0; diff --git a/plugins/libimhex/source/api/imhex_api.cpp b/plugins/libimhex/source/api/imhex_api.cpp index 5ea78d376..798c16433 100644 --- a/plugins/libimhex/source/api/imhex_api.cpp +++ b/plugins/libimhex/source/api/imhex_api.cpp @@ -68,6 +68,8 @@ namespace hex { void ImHexApi::Provider::add(prv::Provider *provider) { SharedData::providers.push_back(provider); SharedData::currentProvider = SharedData::providers.size() - 1; + + EventManager::post(provider); } void ImHexApi::Provider::remove(prv::Provider *provider) { diff --git a/plugins/libimhex/source/providers/provider.cpp b/plugins/libimhex/source/providers/provider.cpp index 233228c82..95953411f 100644 --- a/plugins/libimhex/source/providers/provider.cpp +++ b/plugins/libimhex/source/providers/provider.cpp @@ -1,6 +1,7 @@ #include #include +#include #include #include @@ -12,6 +13,9 @@ namespace hex::prv { Provider::Provider() { this->m_patches.emplace_back(); + + if (this->hasLoadInterface()) + EventManager::post(View::toWindowName("hex.builtin.view.provider_settings.load_popup")); } Provider::~Provider() { @@ -142,4 +146,21 @@ namespace hex::prv { return this->m_patchTreeOffset > 0; } + + bool Provider::hasLoadInterface() const { + return false; + } + + bool Provider::hasInterface() const { + return false; + } + + void Provider::drawLoadInterface() { + + } + + void Provider::drawInterface() { + + } + } \ No newline at end of file diff --git a/source/window/window.cpp b/source/window/window.cpp index bb2c209d3..5f7cf2b94 100644 --- a/source/window/window.cpp +++ b/source/window/window.cpp @@ -485,6 +485,7 @@ namespace hex { View::getDeferedCalls().clear(); for (auto &view : ContentRegistry::Views::getEntries()) { + GImGui->NextWindowData.ClearFlags(); view->drawAlwaysVisible(); if (!view->shouldProcess()) @@ -496,6 +497,8 @@ namespace hex { ImGui::SetNextWindowSizeConstraints(minSize, view->getMaxSize()); view->drawContent(); + GImGui->NextWindowData.ClearFlags(); + view->handleShortcut(pressedKeys, ImGui::GetIO().KeyCtrl, ImGui::GetIO().KeyShift, ImGui::GetIO().KeyAlt); } diff --git a/tests/algorithms/include/test_provider.hpp b/tests/algorithms/include/test_provider.hpp index 31a20ada4..c2510e631 100644 --- a/tests/algorithms/include/test_provider.hpp +++ b/tests/algorithms/include/test_provider.hpp @@ -48,6 +48,9 @@ namespace hex::test { return this->m_data->size(); } + bool open() override { return true; } + void close() override { } + private: std::vector* m_data; }; diff --git a/tests/pattern_language/include/test_provider.hpp b/tests/pattern_language/include/test_provider.hpp index 7b6fb2cd3..9e8ed2b6b 100644 --- a/tests/pattern_language/include/test_provider.hpp +++ b/tests/pattern_language/include/test_provider.hpp @@ -45,6 +45,9 @@ namespace hex::test { return this->m_testFile.getSize(); } + bool open() override { return true; } + void close() override { } + private: File m_testFile; };