1
0
mirror of synced 2025-02-17 18:59:21 +01:00

feat: Added basic ability to interrupt long running tasks

This commit is contained in:
WerWolv 2022-08-17 16:15:36 +02:00
parent cf6ae52889
commit e779285be4
26 changed files with 422 additions and 310 deletions

View File

@ -150,15 +150,6 @@ namespace hex {
}
namespace Tasks {
Task createTask(const std::string &unlocalizedName, u64 maxValue);
void doLater(const std::function<void()> &function);
std::vector<std::function<void()>> &getDeferredCalls();
}
namespace System {
namespace impl {

View File

@ -2,40 +2,100 @@
#include <hex.hpp>
#include <list>
#include <cstdio>
#include <thread>
#include <functional>
#include <cstdint>
#include <mutex>
#include <string>
#include <chrono>
#include <memory>
#include <list>
namespace hex {
class TaskHolder;
class TaskManager;
class Task {
public:
Task() = default;
Task(const std::string &unlocalizedName, u64 maxValue);
Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function);
Task(const Task&) = delete;
Task(Task &&other) noexcept;
~Task();
Task(Task &&other) noexcept;
void update(u64 value = 0);
void setMaxValue(u64 value);
void setMaxValue(u64 maxValue);
void update(u64 currValue);
void finish();
[[nodiscard]] bool isFinished() const;
[[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const;
void clearException();
[[nodiscard]] double getProgress() const;
[[nodiscard]] const std::string &getUnlocalizedName();
[[nodiscard]] u64 getValue() const;
[[nodiscard]] u64 getMaxValue() const;
[[nodiscard]] const std::string &getName() const;
[[nodiscard]] bool isPending() const;
static size_t getRunningTaskCount();
static std::list<Task *> &getRunningTasks() { return Task::s_runningTasks; }
static std::mutex &getTaskMutex() { return Task::s_taskMutex; }
void interrupt();
private:
std::string m_name;
u64 m_maxValue = 0, m_currValue = 0;
void finish();
void interruption();
void exception();
static std::list<Task *> s_runningTasks;
static std::mutex s_taskMutex;
private:
mutable std::mutex m_mutex;
std::string m_unlocalizedName;
u64 m_currValue, m_maxValue;
std::thread m_thread;
bool m_shouldInterrupt = false;
bool m_interrupted = false;
bool m_finished = false;
bool m_hadException = false;
struct TaskInterruptor { virtual ~TaskInterruptor() = default; };
friend class TaskHolder;
friend class TaskManager;
};
class TaskHolder {
public:
TaskHolder() = default;
explicit TaskHolder(std::weak_ptr<Task> task) : m_task(std::move(task)) { }
[[nodiscard]] bool isRunning() const;
[[nodiscard]] bool hadException() const;
[[nodiscard]] bool wasInterrupted() const;
void interrupt();
private:
std::weak_ptr<Task> m_task;
};
class TaskManager {
public:
TaskManager() = delete;
constexpr static auto NoProgress = 0;
static TaskHolder createTask(std::string name, u64 maxValue, std::function<void(Task &)> function);
static void collectGarbage();
static size_t getRunningTaskCount();
static std::list<std::shared_ptr<Task>> &getRunningTasks();
static void doLater(const std::function<void()> &function);
static void runDeferredCalls();
private:
static std::mutex s_deferredCallsMutex;
static std::list<std::shared_ptr<Task>> s_tasks;
static std::list<std::function<void()>> s_deferredCalls;
};
}

View File

@ -236,7 +236,7 @@ namespace hex {
}
void setCurrentProvider(u32 index) {
if (Task::getRunningTaskCount() > 0)
if (TaskManager::getRunningTaskCount() > 0)
return;
if (index < s_providers.size() && s_currentProvider != index) {
@ -266,7 +266,7 @@ namespace hex {
}
void add(prv::Provider *provider, bool skipLoadInterface) {
if (Task::getRunningTaskCount() > 0)
if (TaskManager::getRunningTaskCount() > 0)
return;
if (skipLoadInterface)
@ -282,7 +282,7 @@ namespace hex {
if (provider == nullptr)
return;
if (Task::getRunningTaskCount() > 0)
if (TaskManager::getRunningTaskCount() > 0)
return;
if (!noQuestions) {
@ -319,29 +319,6 @@ namespace hex {
}
namespace ImHexApi::Tasks {
Task createTask(const std::string &unlocalizedName, u64 maxValue) {
return { unlocalizedName, maxValue };
}
void doLater(const std::function<void()> &function) {
static std::mutex tasksMutex;
std::scoped_lock lock(tasksMutex);
getDeferredCalls().push_back(function);
}
std::vector<std::function<void()>> &getDeferredCalls() {
static std::vector<std::function<void()>> deferredCalls;
return deferredCalls;
}
}
namespace ImHexApi::System {
namespace impl {

View File

@ -6,66 +6,174 @@
namespace hex {
std::list<Task *> Task::s_runningTasks;
std::mutex Task::s_taskMutex;
std::mutex TaskManager::s_deferredCallsMutex;
Task::Task(const std::string &unlocalizedName, u64 maxValue) : m_name(LangEntry(unlocalizedName)), m_maxValue(maxValue), m_currValue(0) {
std::scoped_lock lock(Task::s_taskMutex);
std::list<std::shared_ptr<Task>> TaskManager::s_tasks;
std::list<std::function<void()>> TaskManager::s_deferredCalls;
Task::s_runningTasks.push_back(this);
}
Task::Task(std::string unlocalizedName, u64 maxValue, std::function<void(Task &)> function)
: m_unlocalizedName(std::move(unlocalizedName)), m_currValue(0), m_maxValue(maxValue) {
this->m_thread = std::thread([this, func = std::move(function)] {
try {
func(*this);
} catch (const TaskInterruptor &) {
this->interruption();
} catch (...) {
this->exception();
}
Task::~Task() {
this->finish();
this->finish();
});
}
Task::Task(hex::Task &&other) noexcept {
std::scoped_lock lock(Task::s_taskMutex);
std::scoped_lock thisLock(this->m_mutex);
std::scoped_lock otherLock(other.m_mutex);
this->m_thread = std::move(other.m_thread);
this->m_unlocalizedName = std::move(other.m_unlocalizedName);
this->m_name = other.m_name;
this->m_maxValue = other.m_maxValue;
this->m_currValue = other.m_currValue;
auto it = std::find(Task::s_runningTasks.begin(), Task::s_runningTasks.end(), &other);
if (it != Task::s_runningTasks.end()) {
*it = this;
}
this->m_finished = other.m_finished;
this->m_hadException = other.m_hadException;
this->m_interrupted = other.m_interrupted;
this->m_shouldInterrupt = other.m_shouldInterrupt;
}
Task::~Task() {
this->interrupt();
this->m_thread.join();
}
void Task::update(u64 value) {
std::scoped_lock lock(this->m_mutex);
this->m_currValue = value;
if (this->m_shouldInterrupt)
throw TaskInterruptor();
}
void Task::setMaxValue(u64 value) {
std::scoped_lock lock(this->m_mutex);
this->m_maxValue = value;
}
void Task::interrupt() {
std::scoped_lock lock(this->m_mutex);
this->m_shouldInterrupt = true;
}
bool Task::isFinished() const {
std::scoped_lock lock(this->m_mutex);
return this->m_finished;
}
bool Task::hadException() const {
std::scoped_lock lock(this->m_mutex);
return this->m_hadException;
}
bool Task::wasInterrupted() const {
std::scoped_lock lock(this->m_mutex);
return this->m_interrupted;
}
void Task::clearException() {
std::scoped_lock lock(this->m_mutex);
this->m_hadException = false;
}
const std::string &Task::getUnlocalizedName() {
return this->m_unlocalizedName;
}
u64 Task::getValue() const {
return this->m_currValue;
}
u64 Task::getMaxValue() const {
return this->m_maxValue;
}
void Task::finish() {
std::scoped_lock lock(Task::s_taskMutex);
std::scoped_lock lock(this->m_mutex);
Task::s_runningTasks.remove(this);
this->m_finished = true;
}
void Task::setMaxValue(u64 maxValue) {
this->m_maxValue = maxValue;
void Task::interruption() {
std::scoped_lock lock(this->m_mutex);
this->m_interrupted = true;
}
void Task::update(u64 currValue) {
if (this->m_currValue < this->m_maxValue)
this->m_currValue = currValue;
void Task::exception() {
std::scoped_lock lock(this->m_mutex);
this->m_hadException = true;
}
double Task::getProgress() const {
if (this->m_maxValue == 0)
return 100;
return static_cast<double>(this->m_currValue) / static_cast<double>(this->m_maxValue);
bool TaskHolder::isRunning() const {
return !m_task.expired() && !m_task.lock()->isFinished();
}
bool Task::isPending() const {
return this->m_maxValue == 0;
bool TaskHolder::hadException() const {
return m_task.expired() || m_task.lock()->hadException();
}
const std::string &Task::getName() const {
return this->m_name;
bool TaskHolder::wasInterrupted() const {
return m_task.expired() || m_task.lock()->wasInterrupted();
}
size_t Task::getRunningTaskCount() {
std::scoped_lock lock(Task::s_taskMutex);
void TaskHolder::interrupt() {
if (!this->m_task.expired())
this->m_task.lock()->interrupt();
}
return Task::s_runningTasks.size();
TaskHolder TaskManager::createTask(std::string name, u64 maxValue, std::function<void(Task &)> function) {
s_tasks.emplace_back(std::make_shared<Task>(std::move(name), maxValue, std::move(function)));
return TaskHolder(s_tasks.back());
}
void TaskManager::collectGarbage() {
std::erase_if(s_tasks, [](const auto &task) { return task->isFinished() && !task->hadException(); });
}
std::list<std::shared_ptr<Task>> &TaskManager::getRunningTasks() {
return s_tasks;
}
size_t TaskManager::getRunningTaskCount() {
return s_tasks.size();
}
void TaskManager::doLater(const std::function<void()> &function) {
std::scoped_lock lock(s_deferredCallsMutex);
s_deferredCalls.push_back(function);
}
void TaskManager::runDeferredCalls() {
std::scoped_lock lock(s_deferredCallsMutex);
for (const auto &call : s_deferredCalls)
call();
s_deferredCalls.clear();
}
}

View File

@ -13,6 +13,8 @@
#include <imgui_impl_opengl3_loader.h>
#include <hex/api/imhex_api.hpp>
namespace ImGui {
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
@ -536,7 +538,7 @@ namespace ImGui {
const ImGuiStyle &style = g.Style;
ImVec2 pos = window->DC.CursorPos + ImVec2(0, yOffset);
ImVec2 size = CalcItemSize(ImVec2(100, 5), 100, g.FontSize + style.FramePadding.y * 2.0f);
ImVec2 size = CalcItemSize(ImVec2(100, 5) * hex::ImHexApi::System::getGlobalScale(), 100, g.FontSize + style.FramePadding.y * 2.0f);
ImRect bb(pos, pos + size);
ItemSize(size, 0);
if (!ItemAdd(bb, 0))

View File

@ -49,7 +49,7 @@ namespace hex {
}
ImVec2 View::getMinSize() const {
return scaled(ImVec2(480, 720));
return scaled(ImVec2(10, 10));
}
ImVec2 View::getMaxSize() const {

View File

@ -173,7 +173,6 @@ namespace hex::init {
ContentRegistry::Provider::getEntries().clear();
ImHexApi::System::getInitArguments().clear();
ImHexApi::Tasks::getDeferredCalls().clear();
ImHexApi::HexEditor::impl::getBackgroundHighlights().clear();
ImHexApi::HexEditor::impl::getForegroundHighlights().clear();
ImHexApi::HexEditor::impl::getBackgroundHighlightingFunctions().clear();
@ -215,7 +214,7 @@ namespace hex::init {
ShortcutManager::clearShortcuts();
hex::Task::getRunningTasks().clear();
TaskManager::getRunningTasks().clear();
ContentRegistry::DataProcessorNode::getEntries().clear();

View File

@ -86,11 +86,11 @@ namespace hex {
{
for (const auto &[argument, value] : ImHexApi::System::getInitArguments()) {
if (argument == "no-plugins") {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("No Plugins"); });
TaskManager::doLater([] { ImGui::OpenPopup("No Plugins"); });
} else if (argument == "no-builtin-plugin") {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("No Builtin Plugin"); });
TaskManager::doLater([] { ImGui::OpenPopup("No Builtin Plugin"); });
} else if (argument == "multiple-builtin-plugins") {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("Multiple Builtin Plugins"); });
TaskManager::doLater([] { ImGui::OpenPopup("Multiple Builtin Plugins"); });
}
}
}
@ -179,7 +179,7 @@ namespace hex {
} else {
glfwPollEvents();
bool frameRateUnlocked = ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || Task::getRunningTaskCount() > 0 || this->m_mouseButtonDown || this->m_hadEvent || !this->m_pressedKeys.empty();
bool frameRateUnlocked = ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId) || TaskManager::getRunningTaskCount() > 0 || this->m_mouseButtonDown || this->m_hadEvent || !this->m_pressedKeys.empty();
const double timeout = std::max(0.0, (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime));
if ((this->m_lastFrameTime - this->m_frameRateUnlockTime) > 5 && this->m_frameRateTemporarilyUnlocked && !frameRateUnlocked) {
@ -424,7 +424,6 @@ namespace hex {
}
}
this->m_popupsToOpen.remove_if([](const auto &name) {
if (ImGui::IsPopupOpen(name.c_str()))
return true;
@ -434,17 +433,12 @@ namespace hex {
return false;
});
TaskManager::runDeferredCalls();
EventManager::post<EventFrameBegin>();
}
void Window::frame() {
{
auto &calls = ImHexApi::Tasks::getDeferredCalls();
for (const auto &callback : calls)
callback();
calls.clear();
}
auto &io = ImGui::GetIO();
for (auto &[name, view] : ContentRegistry::Views::getEntries()) {
ImGui::GetCurrentContext()->NextWindowData.ClearFlags();
@ -489,6 +483,8 @@ namespace hex {
void Window::frameEnd() {
EventManager::post<EventFrameEnd>();
TaskManager::collectGarbage();
this->endNativeWindowFrame();
ImGui::Render();

View File

@ -28,7 +28,7 @@ namespace hex::plugin::builtin {
void drawContent() override;
private:
bool m_disassembling = false;
TaskHolder m_disassemblerTask;
u64 m_baseAddress = 0;
ui::SelectedRegion m_range = ui::SelectedRegion::EntireData;

View File

@ -74,7 +74,7 @@ namespace hex::plugin::builtin {
std::map<prv::Provider*, std::vector<Occurrence>> m_foundOccurrences, m_sortedOccurrences;
std::map<prv::Provider*, OccurrenceTree> m_occurrenceTree;
std::atomic<bool> m_searchRunning;
TaskHolder m_searchTask;
bool m_settingsValid = false;
std::string m_currFilter;

View File

@ -1,6 +1,7 @@
#pragma once
#include <hex/ui/view.hpp>
#include <hex/api/task.hpp>
#include <array>
#include <atomic>
@ -27,7 +28,7 @@ namespace hex::plugin::builtin {
double m_entropyHandlePosition;
std::array<ImU64, 256> m_valueCounts = { 0 };
bool m_analyzing = false;
TaskHolder m_analyzerTask;
Region m_analyzedRegion = { 0, 0 };

View File

@ -5,6 +5,8 @@
#include <imgui.h>
#include <hex/ui/view.hpp>
#include <hex/api/task.hpp>
namespace hex::plugin::builtin {
class ViewYara : public View {
@ -29,7 +31,7 @@ namespace hex::plugin::builtin {
std::vector<std::pair<std::fs::path, std::fs::path>> m_rules;
std::vector<YaraMatch> m_matches;
u32 m_selectedRule = 0;
bool m_matching = false;
TaskHolder m_matcherTask;
std::vector<std::string> m_consoleMessages;

View File

@ -30,14 +30,14 @@ namespace hex::plugin::builtin {
EventManager::subscribe<EventWindowClosing>([](GLFWwindow *window) {
if (ImHexApi::Provider::isDirty()) {
glfwSetWindowShouldClose(window, GLFW_FALSE);
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.popup.exit_application.title"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.exit_application.title"_lang); });
}
});
EventManager::subscribe<EventProviderClosing>([](hex::prv::Provider *provider, bool *shouldClose) {
if (provider->isDirty()) {
*shouldClose = false;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.popup.close_provider.title"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.popup.close_provider.title"_lang); });
}
});
@ -87,12 +87,12 @@ namespace hex::plugin::builtin {
if (provider->hasFilePicker()) {
if (!provider->handleFilePicker()) {
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
if (!provider->open()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
}
@ -101,7 +101,7 @@ namespace hex::plugin::builtin {
else {
if (!provider->open() || !provider->isAvailable()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
}
}
});

View File

@ -9,8 +9,6 @@
#include <hex/helpers/crypto.hpp>
#include <hex/helpers/patches.hpp>
#include <thread>
namespace hex::plugin::builtin {
static bool g_demoWindowOpen = false;
@ -20,7 +18,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::registerMainMenuItem("hex.builtin.menu.file", 1000);
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1050, [&] {
bool taskRunning = Task::getRunningTaskCount() > 0;
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
if (ImGui::MenuItem("hex.builtin.menu.file.open_file"_lang, "CTRL + O", false, !taskRunning)) {
@ -44,7 +42,7 @@ namespace hex::plugin::builtin {
/* File open, quit imhex */
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1150, [&] {
bool providerValid = ImHexApi::Provider::isValid();
bool taskRunning = Task::getRunningTaskCount() > 0;
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
if (ImGui::MenuItem("hex.builtin.menu.file.close"_lang, "CTRL + W", false, providerValid && !taskRunning)) {
ImHexApi::Provider::remove(ImHexApi::Provider::get());
@ -59,7 +57,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1250, [&] {
auto provider = ImHexApi::Provider::get();
bool providerValid = ImHexApi::Provider::isValid();
bool taskRunning = Task::getRunningTaskCount() > 0;
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
if (ImGui::MenuItem("hex.builtin.menu.file.open_project"_lang, "", false, !taskRunning)) {
fs::openFileBrowser(fs::DialogMode::Open, { {"Project File", "hexproj"}
@ -85,7 +83,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.file", 1300, [&] {
auto provider = ImHexApi::Provider::get();
bool providerValid = ImHexApi::Provider::isValid();
bool taskRunning = Task::getRunningTaskCount() > 0;
bool taskRunning = TaskManager::getRunningTaskCount() > 0;
/* Import */
if (ImGui::BeginMenu("hex.builtin.menu.file.import"_lang, !taskRunning)) {
@ -126,9 +124,7 @@ namespace hex::plugin::builtin {
if (ImGui::MenuItem("hex.builtin.menu.file.import.ips"_lang, nullptr, false)) {
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
std::thread([path] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
auto patch = hex::loadIPSPatch(patchData);
@ -144,15 +140,13 @@ namespace hex::plugin::builtin {
}
provider->createUndoPoint();
}).detach();
});
});
}
if (ImGui::MenuItem("hex.builtin.menu.file.import.ips32"_lang, nullptr, false)) {
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
std::thread([path] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [path](auto &task) {
auto patchData = fs::File(path, fs::File::Mode::Read).readBytes();
auto patch = hex::loadIPS32Patch(patchData);
@ -168,7 +162,7 @@ namespace hex::plugin::builtin {
}
provider->createUndoPoint();
}).detach();
});
});
}
@ -186,12 +180,10 @@ namespace hex::plugin::builtin {
patches[0x00454F45] = value;
}
std::thread([patches] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [patches](auto &) {
auto data = generateIPSPatch(patches);
ImHexApi::Tasks::doLater([data] {
TaskManager::doLater([data] {
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
auto file = fs::File(path, fs::File::Mode::Create);
if (!file.isValid()) {
@ -202,7 +194,7 @@ namespace hex::plugin::builtin {
file.write(data);
});
});
}).detach();
});
}
if (ImGui::MenuItem("hex.builtin.menu.file.export.ips32"_lang, nullptr, false)) {
@ -213,23 +205,21 @@ namespace hex::plugin::builtin {
patches[0x45454F45] = value;
}
std::thread([patches] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.common.processing", 0);
TaskManager::createTask("hex.builtin.common.processing", TaskManager::NoProgress, [patches](auto &) {
auto data = generateIPS32Patch(patches);
ImHexApi::Tasks::doLater([data] {
TaskManager::doLater([data] {
fs::openFileBrowser(fs::DialogMode::Save, {}, [&data](const auto &path) {
auto file = fs::File(path, fs::File::Mode::Create);
if (!file.isValid()) {
View::showErrorPopup("hex.builtin.menu.file.export.popup.create"_lang);
View::showErrorPopup("hex.builtin.menu.file.export.base64.popup.export_error"_lang);
return;
}
file.write(data);
});
});
}).detach();
});
}
ImGui::EndMenu();

View File

@ -745,15 +745,15 @@ namespace hex::plugin::builtin {
void drawFileToolShredder() {
static bool shredding = false;
static std::u8string selectedFile;
static bool fastMode = false;
static TaskHolder shredderTask;
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.warning"_lang);
ImGui::NewLine();
if (ImGui::BeginChild("settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 4 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
ImGui::BeginDisabled(shredding);
ImGui::BeginDisabled(shredderTask.isRunning());
{
ImGui::TextUnformatted("hex.builtin.tools.file_tools.shredder.input"_lang);
ImGui::SameLine();
@ -771,17 +771,14 @@ namespace hex::plugin::builtin {
}
ImGui::EndChild();
if (shredding)
if (shredderTask.isRunning())
ImGui::TextSpinner("hex.builtin.tools.file_tools.shredder.shredding"_lang);
else {
ImGui::BeginDisabled(selectedFile.empty());
{
if (ImGui::Button("hex.builtin.tools.file_tools.shredder.shred"_lang)) {
shredding = true;
std::thread([] {
shredderTask = TaskManager::createTask("hex.builtin.tools.file_tools.shredder.shredding", 0, [](auto &task) {
ON_SCOPE_EXIT {
shredding = false;
selectedFile.clear();
};
fs::File file(selectedFile, fs::File::Mode::Write);
@ -791,6 +788,8 @@ namespace hex::plugin::builtin {
return;
}
task.setMaxValue(file.getSize());
std::vector<std::array<u8, 3>> overwritePattern;
if (fastMode) {
/* Should be sufficient for modern disks */
@ -803,40 +802,40 @@ namespace hex::plugin::builtin {
/* Fill fixed patterns */
overwritePattern = {
{ },
{ },
{},
{},
{ 0x55, 0x55, 0x55 },
{ 0xAA, 0xAA, 0xAA },
{ 0x92, 0x49, 0x24 },
{ 0x49, 0x24, 0x92 },
{ 0x24, 0x92, 0x49 },
{ 0x00, 0x00, 0x00 },
{ 0x11, 0x11, 0x11 },
{ 0x22, 0x22, 0x22 },
{ 0x33, 0x33, 0x44 },
{ 0x55, 0x55, 0x55 },
{ 0x66, 0x66, 0x66 },
{ 0x77, 0x77, 0x77 },
{ 0x88, 0x88, 0x88 },
{ 0x99, 0x99, 0x99 },
{ 0xAA, 0xAA, 0xAA },
{ 0xBB, 0xBB, 0xBB },
{ 0xCC, 0xCC, 0xCC },
{ 0xDD, 0xDD, 0xDD },
{ 0xEE, 0xEE, 0xEE },
{ 0xFF, 0xFF, 0xFF },
{ 0x92, 0x49, 0x24 },
{ 0x49, 0x24, 0x92 },
{ 0x24, 0x92, 0x49 },
{ 0x6D, 0xB6, 0xDB },
{ 0xB6, 0xDB, 0x6D },
{ 0xBD, 0x6D, 0xB6 },
{},
{},
{},
{}
{ },
{ },
{},
{},
{ 0x55, 0x55, 0x55 },
{ 0xAA, 0xAA, 0xAA },
{ 0x92, 0x49, 0x24 },
{ 0x49, 0x24, 0x92 },
{ 0x24, 0x92, 0x49 },
{ 0x00, 0x00, 0x00 },
{ 0x11, 0x11, 0x11 },
{ 0x22, 0x22, 0x22 },
{ 0x33, 0x33, 0x44 },
{ 0x55, 0x55, 0x55 },
{ 0x66, 0x66, 0x66 },
{ 0x77, 0x77, 0x77 },
{ 0x88, 0x88, 0x88 },
{ 0x99, 0x99, 0x99 },
{ 0xAA, 0xAA, 0xAA },
{ 0xBB, 0xBB, 0xBB },
{ 0xCC, 0xCC, 0xCC },
{ 0xDD, 0xDD, 0xDD },
{ 0xEE, 0xEE, 0xEE },
{ 0xFF, 0xFF, 0xFF },
{ 0x92, 0x49, 0x24 },
{ 0x49, 0x24, 0x92 },
{ 0x24, 0x92, 0x49 },
{ 0x6D, 0xB6, 0xDB },
{ 0xB6, 0xDB, 0x6D },
{ 0xBD, 0x6D, 0xB6 },
{},
{},
{},
{}
};
/* Fill random patterns */
@ -848,7 +847,6 @@ namespace hex::plugin::builtin {
size_t fileSize = file.getSize();
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.shredder.shredding", fileSize);
for (const auto &pattern : overwritePattern) {
for (u64 offset = 0; offset < fileSize; offset += 3) {
file.write(pattern.data(), std::min<u64>(pattern.size(), fileSize - offset));
@ -861,7 +859,7 @@ namespace hex::plugin::builtin {
file.remove();
View::showInfoPopup("hex.builtin.tools.file_tools.shredder.success"_lang);
}).detach();
});
}
}
ImGui::EndDisabled();
@ -890,14 +888,14 @@ namespace hex::plugin::builtin {
1
};
static bool splitting = false;
static std::u8string selectedFile;
static std::u8string baseOutputPath;
static u64 splitSize = sizes[0];
static int selectedItem = 0;
static TaskHolder splitterTask;
if (ImGui::BeginChild("split_settings", { 0, ImGui::GetTextLineHeightWithSpacing() * 7 }, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
ImGui::BeginDisabled(splitting);
ImGui::BeginDisabled(splitterTask.isRunning());
{
ImGui::InputText("##path", selectedFile);
ImGui::SameLine();
@ -926,7 +924,7 @@ namespace hex::plugin::builtin {
}
}
ImGui::EndDisabled();
ImGui::BeginDisabled(splitting || selectedItem != sizes.size() - 1);
ImGui::BeginDisabled(splitterTask.isRunning() || selectedItem != sizes.size() - 1);
{
ImGui::InputScalar("###custom_size", ImGuiDataType_U64, &splitSize);
ImGui::SameLine();
@ -938,15 +936,13 @@ namespace hex::plugin::builtin {
ImGui::BeginDisabled(selectedFile.empty() || baseOutputPath.empty() || splitSize == 0);
{
if (splitting)
if (splitterTask.isRunning())
ImGui::TextSpinner("hex.builtin.tools.file_tools.splitter.splitting"_lang);
else {
if (ImGui::Button("hex.builtin.tools.file_tools.splitter.split"_lang)) {
splitting = true;
std::thread([] {
splitterTask = TaskManager::createTask("hex.builtin.tools.file_tools.splitter.splitting", 0, [](auto &task) {
ON_SCOPE_EXIT {
splitting = false;
selectedFile.clear();
baseOutputPath.clear();
};
@ -962,7 +958,8 @@ namespace hex::plugin::builtin {
return;
}
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.splitter.splitting", file.getSize());
task.setMaxValue(file.getSize());
u32 index = 1;
for (u64 offset = 0; offset < file.getSize(); offset += splitSize) {
task.update(offset);
@ -987,7 +984,7 @@ namespace hex::plugin::builtin {
}
View::showInfoPopup("hex.builtin.tools.file_tools.splitter.success"_lang);
}).detach();
});
}
}
}
@ -995,10 +992,10 @@ namespace hex::plugin::builtin {
}
void drawFileToolCombiner() {
static bool combining = false;
static std::vector<std::fs::path> files;
static std::u8string outputPath;
static u32 selectedIndex;
static TaskHolder combinerTask;
if (ImGui::BeginTable("files_table", 2, ImGuiTableFlags_SizingStretchProp)) {
ImGui::TableSetupColumn("file list", ImGuiTableColumnFlags_NoHeaderLabel, 10);
@ -1041,7 +1038,7 @@ namespace hex::plugin::builtin {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::BeginDisabled(combining);
ImGui::BeginDisabled(combinerTask.isRunning());
{
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.add"_lang)) {
fs::openFileBrowser(fs::DialogMode::Open, {}, [](const auto &path) {
@ -1063,7 +1060,7 @@ namespace hex::plugin::builtin {
ImGui::EndTable();
}
ImGui::BeginDisabled(combining);
ImGui::BeginDisabled(combinerTask.isRunning());
{
ImGui::InputText("##output_path", outputPath);
ImGui::SameLine();
@ -1079,14 +1076,12 @@ namespace hex::plugin::builtin {
ImGui::BeginDisabled(files.empty() || outputPath.empty());
{
if (combining)
if (combinerTask.isRunning())
ImGui::TextSpinner("hex.builtin.tools.file_tools.combiner.combining"_lang);
else {
if (ImGui::Button("hex.builtin.tools.file_tools.combiner.combine"_lang)) {
combining = true;
std::thread([] {
ON_SCOPE_EXIT { combining = false; };
combinerTask = TaskManager::createTask("hex.builtin.tools.file_tools.combiner.combining", 0, [](auto &task) {
fs::File output(outputPath, fs::File::Mode::Create);
@ -1095,7 +1090,7 @@ namespace hex::plugin::builtin {
return;
}
auto task = ImHexApi::Tasks::createTask("hex.builtin.tools.file_tools.combiner.combining", files.size());
task.setMaxValue(files.size());
u64 fileIndex = 0;
for (const auto &file : files) {
@ -1121,7 +1116,7 @@ namespace hex::plugin::builtin {
outputPath.clear();
View::showInfoPopup("hex.builtin.tools.file_tools.combiner.success"_lang);
}).detach();
});
}
}
}

View File

@ -161,19 +161,19 @@ namespace hex::plugin::builtin {
EventManager::subscribe<RequestShowInfoPopup>([](const std::string &message) {
s_popupMessage = message;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.info"_lang); });
});
EventManager::subscribe<RequestShowErrorPopup>([](const std::string &message) {
s_popupMessage = message;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.error"_lang); });
});
EventManager::subscribe<RequestShowFatalErrorPopup>([](const std::string &message) {
s_popupMessage = message;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.fatal"_lang); });
});
EventManager::subscribe<RequestShowYesNoQuestionPopup>([](const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback) {
@ -182,7 +182,7 @@ namespace hex::plugin::builtin {
s_yesCallback = yesCallback;
s_noCallback = noCallback;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
});
EventManager::subscribe<RequestShowFileChooserPopup>([](const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
@ -191,7 +191,7 @@ namespace hex::plugin::builtin {
s_selectableFilesValidExtensions = validExtensions;
s_selectableFileOpenCallback = callback;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.common.choose_file"_lang); });
});
}
@ -213,28 +213,51 @@ namespace hex::plugin::builtin {
});
ContentRegistry::Interface::addFooterItem([] {
size_t taskCount = 0;
double taskProgress = 0.0;
std::string taskName;
{
std::scoped_lock lock(Task::getTaskMutex());
taskCount = Task::getRunningTasks().size();
if (taskCount > 0) {
auto frontTask = Task::getRunningTasks().front();
taskProgress = frontTask->getProgress();
taskName = frontTask->getName();
}
}
auto taskCount = TaskManager::getRunningTaskCount();
if (taskCount > 0) {
auto &tasks = TaskManager::getRunningTasks();
auto frontTask = tasks.front();
auto widgetStart = ImGui::GetCursorPos();
ImGui::TextSpinner(hex::format("({})", taskCount).c_str());
ImGui::SameLine();
ImGui::SmallProgressBar(frontTask->getMaxValue() == 0 ? 1 : (float(frontTask->getValue()) / frontTask->getMaxValue()), (ImGui::GetCurrentWindow()->MenuBarHeight() - 10_scaled) / 2.0);
ImGui::SameLine();
auto widgetEnd = ImGui::GetCursorPos();
ImGui::SetCursorPos(widgetStart);
ImGui::InvisibleButton("FrontTask", ImVec2(widgetEnd.x - widgetStart.x, ImGui::GetCurrentWindow()->MenuBarHeight()));
ImGui::SetCursorPos(widgetEnd);
ImGui::InfoTooltip(LangEntry(frontTask->getUnlocalizedName()).get().c_str());
if (ImGui::BeginPopupContextItem("FrontTask", ImGuiPopupFlags_MouseButtonLeft)) {
for (const auto &task : tasks) {
ImGui::PushID(&task);
ImGui::TextFormatted("{}", LangEntry(task->getUnlocalizedName()));
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
ImGui::SmallProgressBar(frontTask->getMaxValue() == 0 ? 1 : (float(frontTask->getValue()) / frontTask->getMaxValue()), (ImGui::GetTextLineHeightWithSpacing() - 5_scaled) / 2);
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
if (ImGui::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
task->interrupt();
ImGui::PopStyleVar();
ImGui::PopID();
}
ImGui::EndPopup();
}
ImGui::SameLine();
ImGui::SmallProgressBar(taskProgress, (ImGui::GetCurrentWindow()->MenuBarHeight() - 10_scaled) / 2.0);
ImGui::InfoTooltip(taskName.c_str());
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, scaled(ImVec2(1, 2)));
if (ImGui::ToolBarButton(ICON_VS_DEBUG_STOP, ImGui::GetStyleColorVec4(ImGuiCol_Text)))
frontTask->interrupt();
ImGui::PopStyleVar();
}
});
}
@ -243,7 +266,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addToolbarItem([] {
auto provider = ImHexApi::Provider::get();
bool providerValid = provider != nullptr;
bool tasksRunning = Task::getRunningTaskCount() > 0;
bool tasksRunning = TaskManager::getRunningTaskCount() > 0;
// Undo
ImGui::BeginDisabled(!providerValid || !provider->canUndo());

View File

@ -14,7 +14,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 1000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.help.about.name"_lang, "")) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.help.about.name").c_str()); });
this->m_aboutWindowOpen = true;
this->getWindowOpenState() = true;
}

View File

@ -24,9 +24,8 @@ namespace hex::plugin::builtin {
void ViewDisassembler::disassemble() {
this->m_disassembly.clear();
this->m_disassembling = true;
std::thread([this] {
this->m_disassemblerTask = TaskManager::createTask("hex.builtin.view.disassembler.disassembling", this->m_codeRegion.getSize(), [this](auto &task) {
csh capstoneHandle;
cs_insn *instructions = nullptr;
@ -40,7 +39,6 @@ namespace hex::plugin::builtin {
std::vector<u8> buffer(2048, 0x00);
size_t size = this->m_codeRegion.getSize();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.disassembler.disassembling", size);
for (u64 address = 0; address < size; address += 2048) {
task.update(address);
@ -80,9 +78,7 @@ namespace hex::plugin::builtin {
cs_close(&capstoneHandle);
}
this->m_disassembling = false;
}).detach();
});
}
void ViewDisassembler::drawContent() {
@ -321,14 +317,14 @@ namespace hex::plugin::builtin {
}
ImGui::EndChild();
ImGui::BeginDisabled(this->m_disassembling);
ImGui::BeginDisabled(this->m_disassemblerTask.isRunning());
{
if (ImGui::Button("hex.builtin.view.disassembler.disassemble"_lang))
this->disassemble();
}
ImGui::EndDisabled();
if (this->m_disassembling) {
if (this->m_disassemblerTask.isRunning()) {
ImGui::SameLine();
ImGui::TextSpinner("hex.builtin.view.disassembler.disassembling"_lang);
}
@ -345,7 +341,7 @@ namespace hex::plugin::builtin {
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.bytes"_lang);
ImGui::TableSetupColumn("hex.builtin.view.disassembler.disassembly.title"_lang);
if (!this->m_disassembling) {
if (!this->m_disassemblerTask.isRunning()) {
ImGuiListClipper clipper;
clipper.Begin(this->m_disassembly.size());

View File

@ -6,7 +6,6 @@
#include <array>
#include <regex>
#include <string>
#include <thread>
#include <utility>
#include <llvm/Demangle/Demangle.h>
@ -319,9 +318,7 @@ namespace hex::plugin::builtin {
}
}();
this->m_searchRunning = true;
std::thread([this, settings = this->m_searchSettings, searchRegion]{
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.find.searching", searchRegion.getSize());
this->m_searchTask = TaskManager::createTask("hex.builtin.view.find.searching", searchRegion.getSize(), [this, settings = this->m_searchSettings, searchRegion](auto &task) {
auto provider = ImHexApi::Provider::get();
switch (settings.mode) {
@ -338,7 +335,7 @@ namespace hex::plugin::builtin {
case BinaryPattern:
this->m_foundOccurrences[provider] = searchBinaryPattern(task, provider, searchRegion, settings.binaryPattern);
break;
}
}
this->m_sortedOccurrences[provider] = this->m_foundOccurrences[provider];
@ -346,9 +343,7 @@ namespace hex::plugin::builtin {
for (const auto &occurrence : this->m_foundOccurrences[provider])
intervals.push_back(OccurrenceTree::interval(occurrence.region.getStartAddress(), occurrence.region.getEndAddress(), occurrence));
this->m_occurrenceTree[provider] = std::move(intervals);
this->m_searchRunning = false;
}).detach();
});
}
std::string ViewFind::decodeValue(prv::Provider *provider, Occurrence occurrence) const {
@ -408,7 +403,7 @@ namespace hex::plugin::builtin {
if (ImGui::Begin(View::toWindowName("hex.builtin.view.find.name").c_str(), &this->getWindowOpenState())) {
auto provider = ImHexApi::Provider::get();
ImGui::BeginDisabled(this->m_searchRunning);
ImGui::BeginDisabled(this->m_searchTask.isRunning());
{
ui::regionSelectionPicker(&this->m_searchSettings.range, true, true);

View File

@ -189,13 +189,10 @@ namespace hex::plugin::builtin {
ImGui::EndTabBar();
}
if (!this->m_searchRunning && !searchSequence.empty() && this->m_shouldSearch) {
this->m_searchRunning = true;
std::thread([this, searchSequence, editor]{
auto task = ImHexApi::Tasks::createTask("Searching", ImHexApi::Provider::get()->getSize());
if (!this->m_searchTask.isRunning() && !searchSequence.empty() && this->m_shouldSearch) {
this->m_searchTask = TaskManager::createTask("hex.builtin.common.processing", ImHexApi::Provider::get()->getActualSize(), [this, editor, searchSequence](auto &) {
if (auto region = this->findSequence(editor, searchSequence, this->m_backwards); region.has_value()) {
ImHexApi::Tasks::doLater([editor, region]{
TaskManager::doLater([editor, region]{
editor->setSelection(region->getStartAddress(), region->getEndAddress());
editor->jumpToSelection();
});
@ -203,8 +200,7 @@ namespace hex::plugin::builtin {
this->m_shouldSearch = false;
this->m_requestFocus = true;
this->m_searchRunning = false;
}).detach();
});
}
}
@ -218,7 +214,7 @@ namespace hex::plugin::builtin {
this->m_requestFocus = false;
}
ImGui::BeginDisabled(this->m_searchRunning);
ImGui::BeginDisabled(this->m_searchTask.isRunning());
{
ImGui::SameLine();
if (ImGui::IconButton(ICON_VS_SEARCH "##search", ButtonColor, ButtonSize)) {
@ -285,7 +281,7 @@ namespace hex::plugin::builtin {
std::atomic<bool> m_shouldSearch = false;
std::atomic<bool> m_backwards = false;
std::atomic<bool> m_searchRunning = false;
TaskHolder m_searchTask;
};
class PopupBaseAddress : public ViewHexEditor::Popup {

View File

@ -4,20 +4,15 @@
#include <hex/providers/provider.hpp>
#include <hex/providers/buffered_reader.hpp>
#include <hex/helpers/fs.hpp>
#include <hex/helpers/fmt.hpp>
#include <hex/helpers/literals.hpp>
#include <hex/helpers/magic.hpp>
#include <cstring>
#include <cmath>
#include <cinttypes>
#include <filesystem>
#include <numeric>
#include <span>
#include <thread>
#include <vector>
#include <hex/helpers/magic.hpp>
#include <implot.h>
@ -80,12 +75,10 @@ namespace hex::plugin::builtin {
}
void ViewInformation::analyze() {
this->m_analyzing = true;
std::thread([this] {
this->m_analyzerTask = TaskManager::createTask("hex.builtin.view.information.analyzing", 0, [this](auto &task) {
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.information.analyzing", provider->getActualSize());
task.setMaxValue(provider->getActualSize());
this->m_analyzedRegion = { provider->getBaseAddress(), provider->getBaseAddress() + provider->getSize() };
@ -127,9 +120,7 @@ namespace hex::plugin::builtin {
else
this->m_highestBlockEntropy = 0;
}
this->m_analyzing = false;
}).detach();
});
}
void ViewInformation::drawContent() {
@ -138,14 +129,14 @@ namespace hex::plugin::builtin {
auto provider = ImHexApi::Provider::get();
if (ImHexApi::Provider::isValid() && provider->isReadable()) {
ImGui::BeginDisabled(this->m_analyzing);
ImGui::BeginDisabled(this->m_analyzerTask.isRunning());
{
if (ImGui::Button("hex.builtin.view.information.analyze"_lang, ImVec2(ImGui::GetContentRegionAvail().x, 0)))
this->analyze();
}
ImGui::EndDisabled();
if (this->m_analyzing) {
if (this->m_analyzerTask.isRunning()) {
ImGui::TextSpinner("hex.builtin.view.information.analyzing"_lang);
} else {
ImGui::NewLine();

View File

@ -815,10 +815,7 @@ namespace hex::plugin::builtin {
EventManager::post<EventHighlightingChanged>();
std::thread([this, code, &runtime] {
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.pattern_editor.evaluating", 1);
TaskManager::createTask("hex.builtin.view.pattern_editor.evaluating", TaskManager::NoProgress, [this, &runtime, code](auto &) {
std::map<std::string, pl::core::Token::Literal> envVars;
for (const auto &[id, name, value, type] : this->m_envVarEntries)
envVars.insert({ name, value });
@ -851,7 +848,7 @@ namespace hex::plugin::builtin {
this->m_runningEvaluators--;
this->m_lastEvaluationProcessed = false;
}).detach();
});
}
}

View File

@ -11,14 +11,14 @@ namespace hex::plugin::builtin {
ViewSettings::ViewSettings() : View("hex.builtin.view.settings.name") {
EventManager::subscribe<RequestOpenWindow>(this, [this](const std::string &name) {
if (name == "Settings") {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
this->getWindowOpenState() = true;
}
});
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 2000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.settings.name"_lang)) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.settings.name").c_str()); });
this->getWindowOpenState() = true;
}
});

View File

@ -29,7 +29,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Interface::addMenuItem("hex.builtin.menu.help", 3000, [&, this] {
if (ImGui::MenuItem("hex.builtin.view.store.name"_lang)) {
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
TaskManager::doLater([] { ImGui::OpenPopup(View::toWindowName("hex.builtin.view.store.name").c_str()); });
this->getWindowOpenState() = true;
}
});

View File

@ -44,7 +44,7 @@ namespace hex::plugin::builtin {
if (ImGui::Button("hex.builtin.view.yara.reload"_lang)) this->reloadRules();
} else {
ImGui::BeginDisabled(this->m_matching);
ImGui::BeginDisabled(this->m_matcherTask.isRunning());
{
if (ImGui::BeginCombo("hex.builtin.view.yara.header.rules"_lang, this->m_rules[this->m_selectedRule].first.string().c_str())) {
for (u32 i = 0; i < this->m_rules.size(); i++) {
@ -63,7 +63,7 @@ namespace hex::plugin::builtin {
}
ImGui::EndDisabled();
if (this->m_matching) {
if (this->m_matcherTask.isRunning()) {
ImGui::SameLine();
ImGui::TextSpinner("hex.builtin.view.yara.matching"_lang);
}
@ -86,7 +86,7 @@ namespace hex::plugin::builtin {
ImGui::TableHeadersRow();
if (!this->m_matching) {
if (!this->m_matcherTask.isRunning()) {
ImGuiListClipper clipper;
clipper.Begin(this->m_matches.size());
@ -173,19 +173,13 @@ namespace hex::plugin::builtin {
void ViewYara::applyRules() {
this->clearResult();
this->m_matching = true;
std::thread([this] {
this->m_matcherTask = TaskManager::createTask("hex.builtin.view.yara.matching", 0, [this](auto &task) {
if (!ImHexApi::Provider::isValid()) return;
auto provider = ImHexApi::Provider::get();
auto task = ImHexApi::Tasks::createTask("hex.builtin.view.yara.matching", provider->getActualSize());
YR_COMPILER *compiler = nullptr;
yr_compiler_create(&compiler);
ON_SCOPE_EXIT {
yr_compiler_destroy(compiler);
this->m_matching = false;
};
yr_compiler_set_include_callback(
@ -209,8 +203,8 @@ namespace hex::plugin::builtin {
delete[] ptr;
},
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data());
fs::toShortPath(this->m_rules[this->m_selectedRule].second).string().data()
);
fs::File file(this->m_rules[this->m_selectedRule].second, fs::File::Mode::Read);
if (!file.isValid()) return;
@ -220,7 +214,7 @@ namespace hex::plugin::builtin {
yr_compiler_get_error_message(compiler, errorMessage.data(), errorMessage.size());
hex::trim(errorMessage);
ImHexApi::Tasks::doLater([this, errorMessage] {
TaskManager::doLater([this, errorMessage] {
this->clearResult();
this->m_consoleMessages.push_back("Error: " + errorMessage);
@ -246,15 +240,14 @@ namespace hex::plugin::builtin {
context.currBlock.base = 0;
context.currBlock.fetch_data = [](auto *block) -> const u8 * {
auto &context = *static_cast<ScanContext *>(block->context);
auto provider = ImHexApi::Provider::get();
context.buffer.resize(context.currBlock.size);
if (context.buffer.empty()) return nullptr;
if (context.buffer.empty())
return nullptr;
block->size = context.currBlock.size;
provider->read(context.currBlock.base + provider->getBaseAddress(), context.buffer.data(), context.buffer.size());
return context.buffer.data();
@ -301,11 +294,11 @@ namespace hex::plugin::builtin {
ResultContext resultContext;
yr_rules_scan_mem_blocks(
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
auto &results = *static_cast<ResultContext *>(userData);
rules, &iterator, 0, [](YR_SCAN_CONTEXT *context, int message, void *data, void *userData) -> int {
auto &results = *static_cast<ResultContext *>(userData);
switch (message) {
case CALLBACK_MSG_RULE_MATCHING:
switch (message) {
case CALLBACK_MSG_RULE_MATCHING:
{
auto rule = static_cast<YR_RULE *>(data);
@ -315,30 +308,30 @@ namespace hex::plugin::builtin {
if (rule->strings != nullptr) {
yr_rule_strings_foreach(rule, string) {
yr_string_matches_foreach(context, string, match) {
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
}
results.newMatches.push_back({ rule->identifier, string->identifier, u64(match->offset), size_t(match->match_length), false, 0, 0 });
}
}
} else {
results.newMatches.push_back({ rule->identifier, "", 0, 0, true, 0, 0 });
}
}
break;
case CALLBACK_MSG_CONSOLE_LOG:
break;
case CALLBACK_MSG_CONSOLE_LOG:
{
results.consoleMessages.emplace_back(static_cast<const char *>(data));
}
break;
default:
break;
}
break;
default:
break;
}
return CALLBACK_CONTINUE;
},
&resultContext,
0);
return CALLBACK_CONTINUE;
},
&resultContext,
0);
ImHexApi::Tasks::doLater([this, resultContext] {
TaskManager::doLater([this, resultContext] {
this->m_matches = resultContext.newMatches;
this->m_consoleMessages = resultContext.consoleMessages;
@ -348,7 +341,7 @@ namespace hex::plugin::builtin {
match.tooltipId = ImHexApi::HexEditor::addTooltip({ match. address, match.size }, hex::format("{0} [{1}]", match.identifier, match.variable), YaraColor);
}
});
}).detach();
});
}
}

View File

@ -83,7 +83,7 @@ namespace hex::plugin::builtin {
if (!provider->open() || !provider->isAvailable()) {
View::showErrorPopup("hex.builtin.popup.error.open"_lang);
ImHexApi::Tasks::doLater([provider] { ImHexApi::Provider::remove(provider); });
TaskManager::doLater([provider] { ImHexApi::Provider::remove(provider); });
return;
}
@ -517,7 +517,7 @@ namespace hex::plugin::builtin {
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) {
if (auto filePath = std::fs::path(path) / CrashBackupFileName; fs::exists(filePath)) {
s_safetyBackupPath = filePath;
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.safety_backup.title"_lang); });
}
}
@ -526,7 +526,7 @@ namespace hex::plugin::builtin {
bool showTipOfTheDay = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.show_tips", 1);
if (showTipOfTheDay)
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
TaskManager::doLater([] { ImGui::OpenPopup("hex.builtin.welcome.tip_of_the_day"_lang); });
}
}