diff options
| -rw-r--r-- | activity.cpp | 6 | ||||
| -rw-r--r-- | binaryninjaapi.h | 24 | ||||
| -rw-r--r-- | binaryninjacore.h | 22 | ||||
| -rw-r--r-- | binaryview.cpp | 4 | ||||
| -rw-r--r-- | function.cpp | 4 | ||||
| -rw-r--r-- | python/binaryview.py | 2 | ||||
| -rw-r--r-- | python/function.py | 2 | ||||
| -rw-r--r-- | python/workflow.py | 156 | ||||
| -rw-r--r-- | workflow.cpp | 106 |
9 files changed, 266 insertions, 60 deletions
diff --git a/activity.cpp b/activity.cpp index 4b2f933f..fcc7386a 100644 --- a/activity.cpp +++ b/activity.cpp @@ -5,8 +5,7 @@ using namespace BinaryNinja; using namespace std; -Activity::Activity(const string& configuration, const std::function<void(Ref<AnalysisContext> analysisContext)>& action) : - m_action(action) +Activity::Activity(const string& configuration, const std::function<void(Ref<AnalysisContext> analysisContext)>& action) : m_action(action) { // LogError("API-Side Activity Constructed!"); m_object = BNCreateActivity(configuration.c_str(), this, Run); @@ -15,6 +14,7 @@ Activity::Activity(const string& configuration, const std::function<void(Ref<Ana Activity::Activity(BNActivity* activity) { + // LogError("API-Side Activity Constructed!"); m_object = BNNewActivityReference(activity); } @@ -27,6 +27,7 @@ Activity::~Activity() void Activity::Run(void* ctxt, BNAnalysisContext* analysisContext) { + // LogError("API-Side Activity Run!"); Activity* activity = (Activity*)ctxt; Ref<AnalysisContext> ac = new AnalysisContext(BNNewAnalysisContextReference(analysisContext)); activity->m_action(ac); @@ -35,6 +36,7 @@ void Activity::Run(void* ctxt, BNAnalysisContext* analysisContext) string Activity::GetName() const { + // LogError("API-Side Activity GetName!"); char* name = BNActivityGetName(m_object); string result = name; BNFreeString(name); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index bcaf644e..e67a836e 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -6419,7 +6419,7 @@ namespace BinaryNinja { void Reanalyze(); - Ref<Workflow> GetWorkflow() const; + Ref<Workflow> GetWorkflow(); /*! Displays contents to the user in the UI or on the command-line @@ -9914,6 +9914,20 @@ namespace BinaryNinja { std::string GetName() const; }; + class WorkflowMachine + { + Ref<BinaryView> m_view; + Ref<Function> m_function; + + public: + WorkflowMachine(Ref<BinaryView> view); + WorkflowMachine(Ref<Function> function); + + std::optional<bool> QueryOverride(const std::string& activity); + bool SetOverride(const std::string& activity, bool enable); + bool ClearOverride(const std::string& activity); + }; + /*! A Binary Ninja Workflow is an abstraction of a computational binary analysis pipeline and it provides the extensibility mechanism needed for tailored binary analysis and decompilation. More specifically, a Workflow is a repository of activities along with a unique strategy to execute them. Binary Ninja provides two Workflows named ``core.module.defaultAnalysis`` and ``core.function.defaultAnalysis`` @@ -9927,9 +9941,13 @@ namespace BinaryNinja { */ class Workflow : public CoreRefCountObject<BNWorkflow, BNNewWorkflowReference, BNFreeWorkflow> { + std::unique_ptr<WorkflowMachine> m_machine; + public: Workflow(const std::string& name = ""); Workflow(BNWorkflow* workflow); + Workflow(BNWorkflow* workflow, Ref<BinaryView> view); + Workflow(BNWorkflow* workflow, Ref<Function> function); virtual ~Workflow() {} /*! Get a list of all workflows @@ -10095,6 +10113,8 @@ namespace BinaryNinja { void ShowReport(const std::string& name); std::vector<std::string> GetEligibilitySettings(); + + WorkflowMachine* GetWorkflowMachine() const { return m_machine.get(); } }; class DisassemblySettings : @@ -11012,7 +11032,7 @@ namespace BinaryNinja { void MarkUpdatesRequired(BNFunctionUpdateType type = UserFunctionUpdate); void MarkCallerUpdatesRequired(BNFunctionUpdateType type = UserFunctionUpdate); - Ref<Workflow> GetWorkflow() const; + Ref<Workflow> GetWorkflow(); void RequestAdvancedAnalysisData(); void ReleaseAdvancedAnalysisData(); diff --git a/binaryninjacore.h b/binaryninjacore.h index e1b08f5c..2fcf82c6 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 80 +#define BN_CURRENT_CORE_ABI_VERSION 81 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 80 +#define BN_MINIMUM_CORE_ABI_VERSION 81 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -5157,11 +5157,6 @@ extern "C" BINARYNINJACOREAPI void BNMarkUpdatesRequired(BNFunction* func, BNFunctionUpdateType type); BINARYNINJACOREAPI void BNMarkCallerUpdatesRequired(BNFunction* func, BNFunctionUpdateType type); - BINARYNINJACOREAPI BNWorkflow* BNGetWorkflowForBinaryView(BNBinaryView* view); - BINARYNINJACOREAPI BNWorkflow* BNGetWorkflowForFunction(BNFunction* func); - BINARYNINJACOREAPI char* BNPostWorkflowRequestForFunction(BNFunction* func, const char* request); - BINARYNINJACOREAPI char* BNGetProvenanceString(BNFunction* func); - BINARYNINJACOREAPI BNHighlightColor BNGetInstructionHighlight( BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNSetAutoInstructionHighlight( @@ -5433,6 +5428,19 @@ extern "C" BINARYNINJACOREAPI const char** BNWorkflowGetEligibilitySettings(BNWorkflow* workflow, size_t* inoutSize); + // BinaryView Workflow Machine + BINARYNINJACOREAPI BNWorkflow* BNGetWorkflowForBinaryView(BNBinaryView* view); + BINARYNINJACOREAPI char* BNPostWorkflowRequestForBinaryView(BNBinaryView* view, const char* request); + BINARYNINJACOREAPI void BNShowWorkflowReportForBinaryView(BNBinaryView* view, const char* name); + + // Function Workflow Machine + BINARYNINJACOREAPI BNWorkflow* BNGetWorkflowForFunction(BNFunction* func); + BINARYNINJACOREAPI char* BNPostWorkflowRequestForFunction(BNFunction* func, const char* request); + BINARYNINJACOREAPI void BNShowWorkflowReportForFunction(BNFunction* func, const char* name); + + // Provenance + BINARYNINJACOREAPI char* BNGetProvenanceString(BNFunction* func); + // Disassembly settings BINARYNINJACOREAPI BNDisassemblySettings* BNCreateDisassemblySettings(void); BINARYNINJACOREAPI BNDisassemblySettings* BNNewDisassemblySettingsReference(BNDisassemblySettings* settings); diff --git a/binaryview.cpp b/binaryview.cpp index 7bd9cec8..32aff542 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -4678,12 +4678,12 @@ void BinaryView::Reanalyze() } -Ref<Workflow> BinaryView::GetWorkflow() const +Ref<Workflow> BinaryView::GetWorkflow() { BNWorkflow* workflow = BNGetWorkflowForBinaryView(m_object); if (!workflow) return nullptr; - return new Workflow(workflow); + return new Workflow(workflow, this); } diff --git a/function.cpp b/function.cpp index ab441193..433bdea1 100644 --- a/function.cpp +++ b/function.cpp @@ -2483,12 +2483,12 @@ void Function::MarkCallerUpdatesRequired(BNFunctionUpdateType type) } -Ref<Workflow> Function::GetWorkflow() const +Ref<Workflow> Function::GetWorkflow() { BNWorkflow* workflow = BNGetWorkflowForFunction(m_object); if (!workflow) return nullptr; - return new Workflow(workflow); + return new Workflow(workflow, this); } diff --git a/python/binaryview.py b/python/binaryview.py index 3d5187d6..8c056db0 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -8945,7 +8945,7 @@ to a the type "tagRECT" found in the typelibrary "winX64common" handle = core.BNGetWorkflowForBinaryView(self.handle) if handle is None: return None - return _workflow.Workflow(handle=handle) + return _workflow.Workflow(handle=handle, object_handle=self.handle) def rebase(self, address: int, force: Optional[bool] = False, progress_func: Optional[ProgressFuncType] = None) -> Optional['BinaryView']: diff --git a/python/function.py b/python/function.py index 62a5dc0c..e43c11e2 100644 --- a/python/function.py +++ b/python/function.py @@ -3021,7 +3021,7 @@ class Function: handle = core.BNGetWorkflowForFunction(self.handle) if handle is None: return None - return workflow.Workflow(handle=handle, function_handle=self.handle) + return workflow.Workflow(handle=handle, object_handle=self.handle) @property def provenance(self): diff --git a/python/workflow.py b/python/workflow.py index 77227933..98e3118b 100644 --- a/python/workflow.py +++ b/python/workflow.py @@ -253,7 +253,7 @@ class Workflow(metaclass=_WorkflowMetaclass): .. note:: Binary Ninja Workflows is currently under development and available as an early feature preview. For additional documentation see Help / User Guide / Developer Guide / Workflows """ - def __init__(self, name: str = "", handle: core.BNWorkflowHandle = None, query_registry: bool = True, function_handle: core.BNFunctionHandle = None): + def __init__(self, name: str = "", handle: core.BNWorkflowHandle = None, query_registry: bool = True, object_handle: Union[core.BNFunctionHandle, core.BNBinaryViewHandle] = None): if handle is None: if query_registry: _handle = core.BNWorkflowInstance(str(name)) @@ -265,8 +265,8 @@ class Workflow(metaclass=_WorkflowMetaclass): self.handle = _handle self._name = core.BNGetWorkflowName(self.handle) self._machine = None - if function_handle is not None: - self._machine = WorkflowMachine(function_handle) + if object_handle is not None: + self._machine = WorkflowMachine(object_handle) def __del__(self): if core is not None: @@ -498,14 +498,6 @@ class Workflow(metaclass=_WorkflowMetaclass): core.BNShowGraphReport(None, f'{self.name} <{activity}>' if activity else self.name, graph.handle) return graph - def show_metrics(self) -> None: - """ - ``show_metrics`` Not yet implemented. - - :rtype: None - """ - core.BNWorkflowShowReport(self.handle, "metrics") - def show_topology(self) -> None: """ ``show_topology`` Show the Workflow topology in the UI. @@ -514,14 +506,6 @@ class Workflow(metaclass=_WorkflowMetaclass): """ core.BNWorkflowShowReport(self.handle, "topology") - def show_trace(self) -> None: - """ - ``show_trace`` Not yet implemented. - - :rtype: None - """ - core.BNWorkflowShowReport(self.handle, "trace") - def eligibility_settings(self) -> List[str]: """ ``eligibility_settings`` Retrieve the list of eligibility settings for the Workflow. @@ -548,28 +532,67 @@ class Workflow(metaclass=_WorkflowMetaclass): raise AttributeError("Machine does not exist.") class WorkflowMachine: - def __init__(self, handle: core.BNFunctionHandle = None): + def __init__(self, handle: Union[core.BNFunctionHandle, core.BNBinaryViewHandle] = None): + if isinstance(handle, core.BNFunctionHandle): + self.is_function_machine = True + elif isinstance(handle, core.BNBinaryViewHandle): + self.is_function_machine = False + else: + raise ValueError("WorkflowMachine requires a Function or BinaryView handle!") self.handle = handle + def show_metrics(self) -> None: + if self.is_function_machine: + core.BNShowWorkflowReportForFunction(self.handle, "metrics") + else: + core.BNShowWorkflowReportForBinaryView(self.handle, "metrics") + + def show_topology(self) -> None: + if self.is_function_machine: + core.BNShowWorkflowReportForFunction(self.handle, "topology") + else: + core.BNShowWorkflowReportForBinaryView(self.handle, "topology") + + def show_trace(self) -> None: + if self.is_function_machine: + core.BNShowWorkflowReportForFunction(self.handle, "trace") + else: + core.BNShowWorkflowReportForBinaryView(self.handle, "trace") + def log(self, enable: bool = True, is_global: bool = False): request = json.dumps({"command": "log", "enable": enable, "global": is_global}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def metrics(self, enable: bool = True, is_global: bool = False): request = json.dumps({"command": "metrics", "enable": enable, "global": is_global}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def dump(self): request = json.dumps({"command": "dump"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def configure(self, advanced: bool = True, incremental: bool = False): request = json.dumps({"command": "configure", "advanced": advanced, "incremental": incremental}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def resume(self): request = json.dumps({"command": "run"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def run(self): status = self.status() @@ -580,62 +603,109 @@ class WorkflowMachine: raise AttributeError("Unknown status response!") request = json.dumps({"command": "run"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def abort(self): request = json.dumps({"command": "abort"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def halt(self): request = json.dumps({"command": "halt"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def reset(self): request = json.dumps({"command": "reset"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def enable(self): request = json.dumps({"command": "enable"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def disable(self): request = json.dumps({"command": "disable"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def step(self): request = json.dumps({"command": "step"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def breakpoint_delete(self, activities): request = json.dumps({"command": "breakpoint", "action": "delete", "activities": activities}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def breakpoint_query(self): request = json.dumps({"command": "breakpoint", "action": "query"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def breakpoint_set(self, activities): request = json.dumps({"command": "breakpoint", "action": "set", "activities": activities}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def status(self): request = json.dumps({"command": "status"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def override_clear(self, activity): request = json.dumps({"command": "override", "action": "clear", "activity": activity}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) - def override_query(self): - request = json.dumps({"command": "override", "action": "query"}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + def override_query(self, activity = None): + if activity is None: + activity = "" + request = json.dumps({"command": "override", "action": "query", "activity": activity}) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def override_set(self, activity, enable): request = json.dumps({"command": "override", "action": "set", "activity": activity, "enable": enable}) - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def request(self, request): - return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + if self.is_function_machine: + return json.loads(core.BNPostWorkflowRequestForFunction(self.handle, request)) + else: + return json.loads(core.BNPostWorkflowRequestForBinaryView(self.handle, request)) def cli(self): WorkflowMachineCLI(self).cmdloop() @@ -811,7 +881,7 @@ class WorkflowMachineCLI(cmd.Cmd): status = self.machine.override_clear(args.activity) print(json.dumps(status, indent=4)) elif args.action == "query": - status = self.machine.override_query() + status = self.machine.override_query(args.activity) accepted = status.get('commandStatus', {}).get('accepted', False) if accepted: response = status.pop("response", None) diff --git a/workflow.cpp b/workflow.cpp index 0d02ab5b..90ddb024 100644 --- a/workflow.cpp +++ b/workflow.cpp @@ -1,5 +1,6 @@ #include "binaryninjaapi.h" #include "json/json.h" +#include "rapidjsonwrapper.h" #include <string> #include <variant> @@ -100,6 +101,97 @@ bool AnalysisContext::Inform(const string& request) } +WorkflowMachine::WorkflowMachine(Ref<BinaryView> view): m_view(view) +{ + +} + + +WorkflowMachine::WorkflowMachine(Ref<Function> function): m_function(function) +{ + +} + + +std::optional<bool> WorkflowMachine::QueryOverride(const string& activity) +{ + rapidjson::Document request(rapidjson::kObjectType); + rapidjson::Document::AllocatorType& allocator = request.GetAllocator(); + request.AddMember("command", "override", allocator); + request.AddMember("action", "query", allocator); + request.AddMember("activity", rapidjson::Value(activity.c_str(), allocator), allocator); + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + request.Accept(writer); + + string jsonResult; + if (m_function) + jsonResult = BNPostWorkflowRequestForFunction(m_function->GetObject(), buffer.GetString()); + else + jsonResult = BNPostWorkflowRequestForBinaryView(m_view->GetObject(), buffer.GetString()); + + rapidjson::Document response(rapidjson::kObjectType); + response.Parse(jsonResult.c_str()); + if (response.HasMember("response") && response["response"].HasMember("activity") && response["response"]["activity"].HasMember("override")) + return response["response"]["activity"]["override"].GetBool(); + + return std::nullopt; +} + + +bool WorkflowMachine::SetOverride(const string& activity, bool enable) +{ + rapidjson::Document request(rapidjson::kObjectType); + rapidjson::Document::AllocatorType& allocator = request.GetAllocator(); + request.AddMember("command", "override", allocator); + request.AddMember("action", "set", allocator); + request.AddMember("activity", rapidjson::Value(activity.c_str(), allocator), allocator); + request.AddMember("enable", enable, allocator); + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + request.Accept(writer); + + string jsonResult; + if (m_function) + jsonResult = BNPostWorkflowRequestForFunction(m_function->GetObject(), buffer.GetString()); + else + jsonResult = BNPostWorkflowRequestForBinaryView(m_view->GetObject(), buffer.GetString()); + + rapidjson::Document response(rapidjson::kObjectType); + response.Parse(jsonResult.c_str()); + if (response.HasMember("commandStatus") && response["commandStatus"].HasMember("accepted")) + return response["commandStatus"]["accepted"].GetBool(); + + return false; +} + + +bool WorkflowMachine::ClearOverride(const string& activity) +{ + rapidjson::Document request(rapidjson::kObjectType); + rapidjson::Document::AllocatorType& allocator = request.GetAllocator(); + request.AddMember("command", "override", allocator); + request.AddMember("action", "clear", allocator); + request.AddMember("activity", rapidjson::Value(activity.c_str(), allocator), allocator); + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + request.Accept(writer); + + string jsonResult; + if (m_function) + jsonResult = BNPostWorkflowRequestForFunction(m_function->GetObject(), buffer.GetString()); + else + jsonResult = BNPostWorkflowRequestForBinaryView(m_view->GetObject(), buffer.GetString()); + + rapidjson::Document response(rapidjson::kObjectType); + response.Parse(jsonResult.c_str()); + if (response.HasMember("commandStatus") && response["commandStatus"].HasMember("accepted")) + return response["commandStatus"]["accepted"].GetBool(); + + return false; +} + + Workflow::Workflow(const string& name) { m_object = BNCreateWorkflow(name.c_str()); @@ -112,6 +204,20 @@ Workflow::Workflow(BNWorkflow* workflow) } +Workflow::Workflow(BNWorkflow* workflow, Ref<BinaryView> view) +{ + m_object = BNNewWorkflowReference(workflow); + m_machine = make_unique<WorkflowMachine>(view); +} + + +Workflow::Workflow(BNWorkflow* workflow, Ref<Function> function) +{ + m_object = BNNewWorkflowReference(workflow); + m_machine = make_unique<WorkflowMachine>(function); +} + + vector<Ref<Workflow>> Workflow::GetList() { size_t count; |
