summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2022-09-26 23:12:20 -0400
committerGlenn Smith <glenn@vector35.com>2022-09-29 21:02:20 -0400
commit207925956bb8ca0174d40523fda70bfb5bc7bd38 (patch)
tree4d5c8cba9ee2ad2b061f1e420c681a793ad397b8
parent5c8aa2ad6c2c03b37cacad4021f81310be12f375 (diff)
Interaction::RunProgressDialog
-rw-r--r--binaryninjaapi.cpp9
-rw-r--r--binaryninjaapi.h12
-rw-r--r--binaryninjacore.h4
-rw-r--r--binaryview.cpp49
-rw-r--r--filemetadata.cpp61
-rw-r--r--interaction.cpp36
-rw-r--r--python/interaction.py43
-rw-r--r--python/plugin.py40
-rw-r--r--rust/src/interaction.rs49
9 files changed, 214 insertions, 89 deletions
diff --git a/binaryninjaapi.cpp b/binaryninjaapi.cpp
index 610cb494..3c7f5e83 100644
--- a/binaryninjaapi.cpp
+++ b/binaryninjaapi.cpp
@@ -422,3 +422,12 @@ std::function<bool(size_t, size_t)> BinaryNinja::SplitProgress(
return originalFn(subpartStarts[subpart] * steps + subpartProgress, steps);
};
}
+
+
+bool BinaryNinja::ProgressCallback(void* ctxt, size_t current, size_t total)
+{
+ ProgressContext* pctxt = reinterpret_cast<ProgressContext*>(ctxt);
+ if (!pctxt->callback)
+ return true;
+ return pctxt->callback(current, total);
+}
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 964e0636..bf00f6f2 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1063,6 +1063,17 @@ namespace BinaryNinja {
*/
bool OpenUrl(const std::string& url);
+ /*! Run a given task in a background thread, and show an updating progress bar which the user can cancel
+
+ \param title Dialog title
+ \param canCancel If the task can be cancelled
+ \param task Function to perform the task, taking as a parameter a function which should be called to report progress
+ updates and check for cancellation. If the progress function returns false, the user has requested
+ to cancel, and the task should handle this appropriately.
+ \return True if not cancelled
+ */
+ bool RunProgressDialog(const std::string& title, bool canCancel, std::function<void(std::function<bool(size_t, size_t)> progress)> task);
+
/*!
Split a single progress function into equally sized subparts.
This function takes the original progress function and returns a new function whose signature
@@ -11286,6 +11297,7 @@ namespace BinaryNinja {
virtual BNMessageBoxButtonResult ShowMessageBox(const std::string& title, const std::string& text,
BNMessageBoxButtonSet buttons = OKButtonSet, BNMessageBoxIcon icon = InformationIcon) = 0;
virtual bool OpenUrl(const std::string& url) = 0;
+ virtual bool RunProgressDialog(const std::string& title, bool canCancel, std::function<void(std::function<bool(size_t, size_t)> progress)> task) = 0;
};
typedef BNPluginOrigin PluginOrigin;
diff --git a/binaryninjacore.h b/binaryninjacore.h
index fcd7deb4..f2211a45 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -2638,6 +2638,8 @@ extern "C"
BNMessageBoxButtonResult (*showMessageBox)(
void* ctxt, const char* title, const char* text, BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon);
bool (*openUrl)(void* ctxt, const char* url);
+ bool (*runProgressDialog)(void* ctxt, const char* title, bool canCancel,
+ void (*task)(void* taskCtxt, bool(*progress)(void* progressCtxt, size_t cur, size_t max), void* progressCtxt), void* taskCtxt);
};
struct BNObjectDestructionCallbacks
@@ -5870,6 +5872,8 @@ extern "C"
BINARYNINJACOREAPI BNMessageBoxButtonResult BNShowMessageBox(
const char* title, const char* text, BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon);
BINARYNINJACOREAPI bool BNOpenUrl(const char* url);
+ BINARYNINJACOREAPI bool BNRunProgressDialog(const char* title, bool canCancel,
+ void (*task)(void* taskCtxt, bool(*progress)(void* progressCtxt, size_t cur, size_t max), void* progressCtxt), void* taskCtxt);
BINARYNINJACOREAPI BNReportCollection* BNCreateReportCollection(void);
BINARYNINJACOREAPI BNReportCollection* BNNewReportCollectionReference(BNReportCollection* reports);
diff --git a/binaryview.cpp b/binaryview.cpp
index fa00b4e9..8c6080d0 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -3602,19 +3602,6 @@ bool BinaryView::FindNextConstant(
}
-struct FindProgressCallbackContext
-{
- std::function<bool(size_t, size_t)> func;
-};
-
-
-static bool FindProgressCallback(void* ctxt, size_t progress, size_t total)
-{
- FindProgressCallbackContext* cb = (FindProgressCallbackContext*)ctxt;
- return cb->func(progress, total);
-}
-
-
struct MatchCallbackContextForDataBuffer
{
std::function<bool(uint64_t, const DataBuffer&)> func;
@@ -3665,10 +3652,10 @@ static bool MatchCallbackForConstant(void* ctxt, uint64_t addr, BNLinearDisassem
bool BinaryView::FindNextData(uint64_t start, uint64_t end, const DataBuffer& data, uint64_t& addr, BNFindFlag flags,
const std::function<bool(size_t current, size_t total)>& progress)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
return BNFindNextDataWithProgress(
- m_object, start, end, data.GetBufferObject(), &addr, flags, &fp, FindProgressCallback);
+ m_object, start, end, data.GetBufferObject(), &addr, flags, &fp, ProgressCallback);
}
@@ -3676,10 +3663,10 @@ bool BinaryView::FindNextText(uint64_t start, uint64_t end, const std::string& d
Ref<DisassemblySettings> settings, BNFindFlag flags, BNFunctionGraphType graph,
const std::function<bool(size_t current, size_t total)>& progress)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
return BNFindNextTextWithProgress(
- m_object, start, end, data.c_str(), &addr, settings->GetObject(), flags, graph, &fp, FindProgressCallback);
+ m_object, start, end, data.c_str(), &addr, settings->GetObject(), flags, graph, &fp, ProgressCallback);
}
@@ -3687,10 +3674,10 @@ bool BinaryView::FindNextConstant(uint64_t start, uint64_t end, uint64_t constan
Ref<DisassemblySettings> settings, BNFunctionGraphType graph,
const std::function<bool(size_t current, size_t total)>& progress)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
return BNFindNextConstantWithProgress(
- m_object, start, end, constant, &addr, settings->GetObject(), graph, &fp, FindProgressCallback);
+ m_object, start, end, constant, &addr, settings->GetObject(), graph, &fp, ProgressCallback);
}
@@ -3698,11 +3685,11 @@ bool BinaryView::FindAllData(uint64_t start, uint64_t end, const DataBuffer& dat
const std::function<bool(size_t current, size_t total)>& progress,
const std::function<bool(uint64_t addr, const DataBuffer& match)>& matchCallback)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
MatchCallbackContextForDataBuffer mc;
mc.func = matchCallback;
- return BNFindAllDataWithProgress(m_object, start, end, data.GetBufferObject(), flags, &fp, FindProgressCallback,
+ return BNFindAllDataWithProgress(m_object, start, end, data.GetBufferObject(), flags, &fp, ProgressCallback,
&mc, MatchCallbackForDataBuffer);
}
@@ -3712,12 +3699,12 @@ bool BinaryView::FindAllText(uint64_t start, uint64_t end, const std::string& da
const std::function<bool(uint64_t addr, const std::string& match, const LinearDisassemblyLine& line)>&
matchCallback)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
MatchCallbackContextForText mc;
mc.func = matchCallback;
return BNFindAllTextWithProgress(m_object, start, end, data.c_str(), settings->GetObject(), flags, graph, &fp,
- FindProgressCallback, &mc, MatchCallbackForText);
+ ProgressCallback, &mc, MatchCallbackForText);
}
@@ -3725,12 +3712,12 @@ bool BinaryView::FindAllConstant(uint64_t start, uint64_t end, uint64_t constant
BNFunctionGraphType graph, const std::function<bool(size_t current, size_t total)>& progress,
const std::function<bool(uint64_t addr, const LinearDisassemblyLine& line)>& matchCallback)
{
- FindProgressCallbackContext fp;
- fp.func = progress;
+ ProgressContext fp;
+ fp.callback = progress;
MatchCallbackContextForConstant mc;
mc.func = matchCallback;
return BNFindAllConstantWithProgress(m_object, start, end, constant, settings->GetObject(), graph, &fp,
- FindProgressCallback, &mc, MatchCallbackForConstant);
+ ProgressCallback, &mc, MatchCallbackForConstant);
}
diff --git a/filemetadata.cpp b/filemetadata.cpp
index 9b1dfee3..84c25e62 100644
--- a/filemetadata.cpp
+++ b/filemetadata.cpp
@@ -25,19 +25,6 @@ using namespace Json;
using namespace std;
-struct DatabaseProgressCallbackContext
-{
- std::function<bool(size_t, size_t)> func;
-};
-
-
-static bool DatabaseProgressCallback(void* ctxt, size_t progress, size_t total)
-{
- DatabaseProgressCallbackContext* cb = (DatabaseProgressCallbackContext*)ctxt;
- return cb->func(progress, total);
-}
-
-
char* NavigationHandler::GetCurrentViewCallback(void* ctxt)
{
NavigationHandler* handler = (NavigationHandler*)ctxt;
@@ -172,10 +159,10 @@ bool FileMetadata::CreateDatabase(const string& name, BinaryView* data, Ref<Save
bool FileMetadata::CreateDatabase(const string& name, BinaryView* data,
const function<bool(size_t progress, size_t total)>& progressCallback, Ref<SaveSettings> settings)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progressCallback;
+ ProgressContext cb;
+ cb.callback = progressCallback;
return BNCreateDatabaseWithProgress(
- data->GetObject(), name.c_str(), &cb, DatabaseProgressCallback, settings ? settings->GetObject() : nullptr);
+ data->GetObject(), name.c_str(), &cb, ProgressCallback, settings ? settings->GetObject() : nullptr);
}
@@ -191,9 +178,9 @@ Ref<BinaryView> FileMetadata::OpenExistingDatabase(const string& path)
Ref<BinaryView> FileMetadata::OpenExistingDatabase(
const string& path, const function<bool(size_t progress, size_t total)>& progressCallback)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progressCallback;
- BNBinaryView* data = BNOpenExistingDatabaseWithProgress(m_object, path.c_str(), &cb, DatabaseProgressCallback);
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ BNBinaryView* data = BNOpenExistingDatabaseWithProgress(m_object, path.c_str(), &cb, ProgressCallback);
if (!data)
return nullptr;
return new BinaryView(data);
@@ -218,29 +205,29 @@ bool FileMetadata::SaveAutoSnapshot(BinaryView* data, Ref<SaveSettings> settings
bool FileMetadata::SaveAutoSnapshot(
BinaryView* data, const function<bool(size_t progress, size_t total)>& progressCallback, Ref<SaveSettings> settings)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progressCallback;
+ ProgressContext cb;
+ cb.callback = progressCallback;
return BNSaveAutoSnapshotWithProgress(
- data->GetObject(), &cb, DatabaseProgressCallback, settings ? settings->GetObject() : nullptr);
+ data->GetObject(), &cb, ProgressCallback, settings ? settings->GetObject() : nullptr);
}
void FileMetadata::GetSnapshotData(
Ref<KeyValueStore> data, Ref<KeyValueStore> cache, const std::function<bool(size_t, size_t)>& progress)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progress;
- BNGetSnapshotData(GetObject(), data->GetObject(), cache->GetObject(), &cb, DatabaseProgressCallback);
+ ProgressContext cb;
+ cb.callback = progress;
+ BNGetSnapshotData(GetObject(), data->GetObject(), cache->GetObject(), &cb, ProgressCallback);
}
void FileMetadata::ApplySnapshotData(BinaryView* file, Ref<KeyValueStore> data, Ref<KeyValueStore> cache,
const std::function<bool(size_t, size_t)>& progress, bool openForConfiguration, bool restoreRawView)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progress;
+ ProgressContext cb;
+ cb.callback = progress;
BNApplySnapshotData(GetObject(), file->GetObject(), data->GetObject(), cache->GetObject(), &cb,
- DatabaseProgressCallback, openForConfiguration, restoreRawView);
+ ProgressCallback, openForConfiguration, restoreRawView);
}
@@ -262,9 +249,9 @@ bool FileMetadata::Rebase(BinaryView* data, uint64_t address)
bool FileMetadata::Rebase(
BinaryView* data, uint64_t address, const function<bool(size_t progress, size_t total)>& progressCallback)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progressCallback;
- return BNRebaseWithProgress(data->GetObject(), address, &cb, DatabaseProgressCallback);
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ return BNRebaseWithProgress(data->GetObject(), address, &cb, ProgressCallback);
}
@@ -277,9 +264,9 @@ bool FileMetadata::CreateSnapshotedView(BinaryView *data, const std::string &vie
bool FileMetadata::CreateSnapshotedView(BinaryView* data, const std::string& viewName,
const function<bool(size_t progress, size_t total)>& progressCallback)
{
- DatabaseProgressCallbackContext cb;
- cb.func = progressCallback;
- return BNCreateSnapshotedViewWithProgress(data->GetObject(), viewName.c_str(), &cb, DatabaseProgressCallback);
+ ProgressContext cb;
+ cb.callback = progressCallback;
+ return BNCreateSnapshotedViewWithProgress(data->GetObject(), viewName.c_str(), &cb, ProgressCallback);
}
@@ -291,11 +278,11 @@ MergeResult FileMetadata::MergeUserAnalysis(
for (size_t i = 0; i < numHashes; i++)
tempList[i] = BNAllocString(excludedHashes[i].c_str());
- DatabaseProgressCallbackContext cb;
- cb.func = progress;
+ ProgressContext cb;
+ cb.callback = progress;
BNMergeResult bnResult =
- BNMergeUserAnalysis(m_object, name.c_str(), &cb, DatabaseProgressCallback, tempList, numHashes);
+ BNMergeUserAnalysis(m_object, name.c_str(), &cb, ProgressCallback, tempList, numHashes);
MergeResult result(bnResult);
for (size_t i = 0; i < numHashes; i++)
diff --git a/interaction.cpp b/interaction.cpp
index 580e2a39..8bfe4495 100644
--- a/interaction.cpp
+++ b/interaction.cpp
@@ -420,6 +420,18 @@ static bool OpenUrlCallback(void* ctxt, const char* url)
}
+static bool RunProgressDialogCallback(void* ctxt, const char* title, bool canCancel,
+ void (*task)(void*, bool (*)(void*, size_t, size_t), void*), void* taskCtxt)
+{
+ InteractionHandler* handler = (InteractionHandler*)ctxt;
+ return handler->RunProgressDialog(title, canCancel, [=](std::function<bool(size_t, size_t)> progress) {
+ ProgressContext context;
+ context.callback = progress;
+ task(taskCtxt, ProgressCallback, &context);
+ });
+}
+
+
void BinaryNinja::RegisterInteractionHandler(InteractionHandler* handler)
{
BNInteractionHandlerCallbacks cb;
@@ -439,6 +451,7 @@ void BinaryNinja::RegisterInteractionHandler(InteractionHandler* handler)
cb.getFormInput = GetFormInputCallback;
cb.showMessageBox = ShowMessageBoxCallback;
cb.openUrl = OpenUrlCallback;
+ cb.runProgressDialog = RunProgressDialogCallback;
BNRegisterInteractionHandler(&cb);
}
@@ -671,6 +684,29 @@ bool BinaryNinja::OpenUrl(const std::string& url)
}
+struct TaskContext
+{
+ std::function<void(std::function<bool(size_t, size_t)> progress)> callback;
+};
+
+
+static void TaskCallback(void* taskCtxt, bool (*progress)(void*, size_t, size_t), void* progressCtxt)
+{
+ TaskContext* context = (TaskContext*)taskCtxt;
+ context->callback([=](size_t cur, size_t max) {
+ return progress(progressCtxt, cur, max);
+ });
+}
+
+
+bool BinaryNinja::RunProgressDialog(const std::string& title, bool canCancel, std::function<void(std::function<bool(size_t, size_t)> progress)> task)
+{
+ TaskContext context;
+ context.callback = task;
+ return BNRunProgressDialog(title.c_str(), canCancel, TaskCallback, &context);
+}
+
+
ReportCollection::ReportCollection()
{
m_object = BNCreateReportCollection();
diff --git a/python/interaction.py b/python/interaction.py
index 2331b586..9fb5d9c7 100644
--- a/python/interaction.py
+++ b/python/interaction.py
@@ -21,7 +21,7 @@
import ctypes
import traceback
import webbrowser
-from typing import Optional
+from typing import Optional, Callable
# Binary Ninja components
from . import _binaryninjacore as core
@@ -29,6 +29,7 @@ from .enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, Mess
from . import binaryview
from .log import log_error
from . import flowgraph
+from . import mainthread
class LabelField:
@@ -493,6 +494,7 @@ class InteractionHandler:
self._cb.getFormInput = self._cb.getFormInput.__class__(self._get_form_input)
self._cb.showMessageBox = self._cb.showMessageBox.__class__(self._show_message_box)
self._cb.openUrl = self._cb.openUrl.__class__(self._open_url)
+ self._cb.runProgressDialog = self._cb.runProgressDialog.__class__(self._run_progress_dialog)
def register(self):
self.__class__._interaction_handler = self
@@ -708,6 +710,17 @@ class InteractionHandler:
log_error(traceback.format_exc())
return False
+ def _run_progress_dialog(self, title, can_cancel, task, task_ctxt):
+ try:
+ def py_task(progress: Callable[[int, int], bool]):
+ progress_c = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t, lambda ctxt, cur, max: progress(cur, max))
+ task(task_ctxt, progress_c, None)
+
+ return self.run_progress_dialog(title, can_cancel, py_task)
+ except:
+ log_error(traceback.format_exc())
+ return False
+
def show_plain_text_report(self, view, title, contents):
pass
@@ -762,6 +775,10 @@ class InteractionHandler:
webbrowser.open(url)
return True
+ def run_progress_dialog(self, task: Callable[[Callable[[int, int], bool]], None]) -> bool:
+ mainthread.execute_on_main_thread_and_wait(lambda: task(lambda cur, max: True))
+ return True
+
class PlainTextReport:
def __init__(self, title, contents, view=None):
@@ -1359,3 +1376,27 @@ def open_url(url):
:rtype: bool
"""
return core.BNOpenUrl(url)
+
+
+def run_progress_dialog(title: str, can_cancel: bool, task: Callable[[Callable[[int, int], bool]], None]) -> bool:
+ """
+ ``run_progress_dialog`` runs a given task in a background thread, showing an updating
+ progress bar which the user can cancel.
+
+ :param title: Dialog title
+ :param can_cancel: If the task can be cancelled
+ :param task: Function to perform the task, taking as a parameter a function which should
+ be called to report progress updates and check for cancellation. If the progress function
+ returns false, the user has requested to cancel, and the task should handle this appropriately.
+ :return: True if not cancelled
+ """
+
+ progress_type = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_size_t)
+ task_type = ctypes.CFUNCTYPE(None, ctypes.c_void_p, progress_type, ctypes.c_void_p)
+
+ def do_task(ctxt: ctypes.c_void_p, progress: progress_type, progress_ctxt: ctypes.c_void_p):
+ def py_progress(cur: int, max: int) -> bool:
+ return progress(progress_ctxt, cur, max)
+ task(py_progress)
+
+ return core.BNRunProgressDialog(title, can_cancel, task_type(do_task), None)
diff --git a/python/plugin.py b/python/plugin.py
index f1720ccd..eec25683 100644
--- a/python/plugin.py
+++ b/python/plugin.py
@@ -358,8 +358,8 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView], None],
- is_valid: Optional[Callable[[binaryview.BinaryView], bool]] = None
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView'], None],
+ is_valid: Optional[Callable[['binaryview.BinaryView'], bool]] = None
):
r"""
``register`` Register a plugin
@@ -384,8 +384,8 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_address(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, int], None],
- is_valid: Optional[Callable[[binaryview.BinaryView, int], bool]] = None
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', int], None],
+ is_valid: Optional[Callable[['binaryview.BinaryView', int], bool]] = None
):
r"""
``register_for_address`` Register a plugin to be called with an address argument
@@ -410,8 +410,8 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_range(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, int, int], None],
- is_valid: Optional[Callable[[binaryview.BinaryView, int, int], bool]] = None
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', int, int], None],
+ is_valid: Optional[Callable[['binaryview.BinaryView', int, int], bool]] = None
):
r"""
``register_for_range`` Register a plugin to be called with a range argument
@@ -436,8 +436,8 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_function(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, function.Function], None],
- is_valid: Optional[Callable[[binaryview.BinaryView, function.Function], bool]] = None
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'function.Function'], None],
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'function.Function'], bool]] = None
):
r"""
``register_for_function`` Register a plugin to be called with a function argument
@@ -462,9 +462,9 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_low_level_il_function(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, lowlevelil.LowLevelILFunction],
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'lowlevelil.LowLevelILFunction'],
None],
- is_valid: Optional[Callable[[binaryview.BinaryView, lowlevelil.LowLevelILFunction], bool]] = None
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'lowlevelil.LowLevelILFunction'], bool]] = None
):
r"""
``register_for_low_level_il_function`` Register a plugin to be called with a low level IL function argument
@@ -490,9 +490,9 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_low_level_il_instruction(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, lowlevelil.LowLevelILInstruction],
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'lowlevelil.LowLevelILInstruction'],
None],
- is_valid: Optional[Callable[[binaryview.BinaryView, lowlevelil.LowLevelILInstruction], bool]] = None
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'lowlevelil.LowLevelILInstruction'], bool]] = None
):
r"""
``register_for_low_level_il_instruction`` Register a plugin to be called with a low level IL instruction argument
@@ -519,9 +519,9 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_medium_level_il_function(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, mediumlevelil.MediumLevelILFunction],
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'mediumlevelil.MediumLevelILFunction'],
None],
- is_valid: Optional[Callable[[binaryview.BinaryView, mediumlevelil.MediumLevelILFunction], bool]] = None
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'mediumlevelil.MediumLevelILFunction'], bool]] = None
):
r"""
``register_for_medium_level_il_function`` Register a plugin to be called with a medium level IL function argument
@@ -548,8 +548,8 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_medium_level_il_instruction(
cls, name: str, description: str,
- action: Callable[[binaryview.BinaryView, mediumlevelil.MediumLevelILInstruction], None],
- is_valid: Optional[Callable[[binaryview.BinaryView, mediumlevelil.MediumLevelILInstruction], bool]] = None
+ action: Callable[['binaryview.BinaryView', 'mediumlevelil.MediumLevelILInstruction'], None],
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'mediumlevelil.MediumLevelILInstruction'], bool]] = None
):
r"""
``register_for_medium_level_il_instruction`` Register a plugin to be called with a medium level IL instruction argument
@@ -576,9 +576,9 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_high_level_il_function(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, highlevelil.HighLevelILFunction],
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'highlevelil.HighLevelILFunction'],
None],
- is_valid: Optional[Callable[[binaryview.BinaryView, highlevelil.HighLevelILFunction], bool]] = None
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'highlevelil.HighLevelILFunction'], bool]] = None
):
r"""
``register_for_high_level_il_function`` Register a plugin to be called with a high level IL function argument
@@ -604,9 +604,9 @@ class PluginCommand(metaclass=_PluginCommandMetaClass):
@classmethod
def register_for_high_level_il_instruction(
- cls, name: str, description: str, action: Callable[[binaryview.BinaryView, highlevelil.HighLevelILInstruction],
+ cls, name: str, description: str, action: Callable[['binaryview.BinaryView', 'highlevelil.HighLevelILInstruction'],
None],
- is_valid: Optional[Callable[[binaryview.BinaryView, highlevelil.HighLevelILInstruction], bool]] = None
+ is_valid: Optional[Callable[['binaryview.BinaryView', 'highlevelil.HighLevelILInstruction'], bool]] = None
):
r"""
``register_for_high_level_il_instruction`` Register a plugin to be called with a high level IL instruction argument
diff --git a/rust/src/interaction.rs b/rust/src/interaction.rs
index 96af3daa..41289a14 100644
--- a/rust/src/interaction.rs
+++ b/rust/src/interaction.rs
@@ -17,6 +17,7 @@
use binaryninjacore_sys::*;
use std::ffi::CString;
+use std::os::raw::c_void;
use std::path::PathBuf;
use crate::string::BnString;
@@ -121,3 +122,51 @@ pub fn get_directory_name_input(prompt: &str, default_name: &str) -> Option<Path
let string = unsafe { BnString::from_raw(value) };
Some(PathBuf::from(string.as_str()))
}
+
+struct TaskContext<F: Fn(Box<dyn Fn(usize, usize) -> Result<(), ()>>)>(F);
+
+pub fn run_progress_dialog<F: Fn(Box<dyn Fn(usize, usize) -> Result<(), ()>>)>(
+ title: &str,
+ can_cancel: bool,
+ task: F,
+) -> Result<(), ()> {
+ let title = CString::new(title).unwrap();
+
+ let mut ctxt = TaskContext::<F>(task);
+
+ unsafe extern "C" fn cb_task<F: Fn(Box<dyn Fn(usize, usize) -> Result<(), ()>>)>(
+ ctxt: *mut c_void,
+ progress: Option<unsafe extern "C" fn(*mut c_void, usize, usize) -> bool>,
+ progress_ctxt: *mut c_void,
+ ) {
+ ffi_wrap!("run_progress_dialog", unsafe {
+ let context = ctxt as *mut TaskContext<F>;
+ let progress_fn = Box::new(move |cur: usize, max: usize| -> Result<(), ()> {
+ match progress {
+ Some(func) => {
+ if (func)(progress_ctxt, cur, max) {
+ Ok(())
+ } else {
+ Err(())
+ }
+ }
+ None => Ok(()),
+ }
+ });
+ ((*context).0)(progress_fn);
+ })
+ }
+
+ if unsafe {
+ BNRunProgressDialog(
+ title.as_ptr(),
+ can_cancel,
+ Some(cb_task::<F>),
+ &mut ctxt as *mut _ as *mut c_void,
+ )
+ } {
+ Ok(())
+ } else {
+ Err(())
+ }
+}