diff options
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | binaryninjaapi.h | 16 | ||||
| -rw-r--r-- | examples/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | examples/background_task/CMakeLists.txt | 36 | ||||
| -rw-r--r-- | examples/background_task/src/backgroundtask.cpp | 80 |
5 files changed, 132 insertions, 2 deletions
@@ -53,6 +53,7 @@ In addition to the default build setup, you may want to: There are many examples available. The [Python examples folder](https://github.com/Vector35/binaryninja-api/tree/dev/python/examples) demonstrates many different applications of the Python API, while C++ examples include: +- [background_task](https://github.com/Vector35/binaryninja-api/tree/dev/examples/background_task) is a plugin that demonstrates managing a background task.\* - [bin-info](https://github.com/Vector35/binaryninja-api/tree/dev/examples/bin-info) is a standalone executable that prints some information about a given binary to the terminal.\* - [breakpoint](https://github.com/Vector35/binaryninja-api/tree/dev/examples/breakpoint) is a plugin that allows you to select a region within an x86 binary and use the context menu to fill it with breakpoint bytes. - [command-line disassm](https://github.com/Vector35/binaryninja-api/tree/dev/examples/cmdline_disasm) demonstrates how to dump disassembly to the command line.\* diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 364eb564..d2cf74d2 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -15513,8 +15513,20 @@ namespace BinaryNinja { public CoreRefCountObject<BNBackgroundTask, BNNewBackgroundTaskReference, BNFreeBackgroundTask> { public: - BackgroundTask(BNBackgroundTask* task); - BackgroundTask(const std::string& initialText, bool canCancel); + BackgroundTask(BNBackgroundTask *task); + + /*! + Provides a mechanism for reporting progress of + an optionally cancelable task to the user via the status bar in the UI. + If canCancel is is `True`, then the task can be cancelled either + programmatically or by the user via the UI. + + \note This API does not provide a means to execute a task. The caller is responsible to execute (and possibly cancel) the task. + + \param initialText Text description of the progress of the background task (displayed in status bar of the UI) + \param canCancel Whether the task can be cancelled + */ + BackgroundTask(const std::string &initialText, bool canCancel); bool CanCancel() const; bool IsCancelled() const; diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 8a831b46..790815c3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(background_task) add_subdirectory(bin-info) add_subdirectory(breakpoint) add_subdirectory(cmdline_disasm) diff --git a/examples/background_task/CMakeLists.txt b/examples/background_task/CMakeLists.txt new file mode 100644 index 00000000..36e012b0 --- /dev/null +++ b/examples/background_task/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + +project(background_task CXX C) + +file(GLOB SOURCES + src/*.cpp + src/*.h) + +add_library(background_task SHARED ${SOURCES}) + +if(NOT BN_API_BUILD_EXAMPLES AND NOT BN_INTERNAL_BUILD) + # Out-of-tree build + find_path( + BN_API_PATH + NAMES binaryninjaapi.h + HINTS ../.. binaryninjaapi $ENV{BN_API_PATH} + REQUIRED + ) + add_subdirectory(${BN_API_PATH} api) +endif() + +target_link_libraries(background_task binaryninjaui) + +set_target_properties(background_task PROPERTIES + CXX_STANDARD 17 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out/bin) + +if(BN_INTERNAL_BUILD) + ui_plugin_rpath(background_task) +endif() + +bn_install_plugin(${PROJECT_NAME}) diff --git a/examples/background_task/src/backgroundtask.cpp b/examples/background_task/src/backgroundtask.cpp new file mode 100644 index 00000000..8a307080 --- /dev/null +++ b/examples/background_task/src/backgroundtask.cpp @@ -0,0 +1,80 @@ +#include <thread> +#include <random> + +#include "binaryninjaapi.h" + +using namespace BinaryNinja; + +static Ref<BackgroundTask> inspireBackgroundTask = nullptr; + +uint64_t InspireWriteCallback(uint8_t *data, uint64_t len, void *ctxt) +{ + try + { + Json::Value json; + std::unique_ptr<Json::CharReader> reader(Json::CharReaderBuilder().newCharReader()); + std::string errors; + if (!reader->parse((char *) data, (char *) data + len, &json, &errors)) + { + LogError("Failed to parse! %s", errors.c_str()); + } + else + { + std::random_device rd; + std::map<int, int> hist; + std::uniform_int_distribution<Json::ArrayIndex> dist(0, json.size()); + auto randQuoteObj = json.get(dist(rd), 0); + if (randQuoteObj.isObject() && randQuoteObj.size() == 2) + { + std::string quote = randQuoteObj.get("text", Json::Value("INVALID")).asString(); + LogInfo("%s", quote.c_str()); + // Display quote in progress text for 3 seconds. + inspireBackgroundTask->SetProgressText(quote); + std::this_thread::sleep_for(std::chrono::seconds(3)); + } + } + } catch (Json::Exception e) + { + LogError("JSON exception! %s", e.m_message.c_str()); + inspireBackgroundTask->Cancel(); + } + return len; +} + +bool InspireProgressCallback(void *ctxt, uint64_t progress, uint64_t total) +{ + // Close connection on cancellation + return !inspireBackgroundTask->IsCancelled(); +} + +void Inspire(BinaryView *bv) +{ + inspireBackgroundTask = new BackgroundTask("Getting inspired!", true); + std::thread inspireThread([]() { + LogInfo("Getting inspired!"); + BNDownloadInstanceOutputCallbacks outputCallbacks; + memset(&outputCallbacks, 0, sizeof(outputCallbacks)); + outputCallbacks.writeCallback = InspireWriteCallback; + outputCallbacks.progressCallback = InspireProgressCallback; + + auto downloadProvider = DownloadProvider::GetByName("CoreDownloadProvider"); + auto downloadInstance = downloadProvider->CreateNewInstance(); + inspireBackgroundTask->SetProgressText("Waiting for inspiration..."); + if (downloadInstance->PerformRequest("https://type.fit/api/quotes", &outputCallbacks)) + LogError("Inspiration failed!"); + + inspireBackgroundTask->Finish(); + }); + inspireThread.detach(); +} + +extern "C" { + BN_DECLARE_CORE_ABI_VERSION + + BINARYNINJAPLUGIN bool CorePluginInit() + { + PluginCommand::Register("Inspire me!", "Print an inspirational quote to the log", Inspire); + + return true; + } +} |
