diff options
| author | Mason Reed <mason@vector35.com> | 2025-06-18 00:14:48 -0400 |
|---|---|---|
| committer | Mason Reed <mason@vector35.com> | 2025-07-02 01:56:54 -0400 |
| commit | ba6d08199b0067adf3222559363a819f4b11c502 (patch) | |
| tree | 7cf917dfbc757d757a9bc4b48c0a5aa6d80b6d3e /rust/src/command.rs | |
| parent | 00686dfc68ee40b9b7378febadf3c27eb657dff9 (diff) | |
Add PluginCommand for projects and hide non-contextual commands in linear/graph view
Diffstat (limited to 'rust/src/command.rs')
| -rw-r--r-- | rust/src/command.rs | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/rust/src/command.rs b/rust/src/command.rs index 46f43bbd..eecdf4a8 100644 --- a/rust/src/command.rs +++ b/rust/src/command.rs @@ -33,16 +33,18 @@ //! The return value of these functions should indicate whether they successfully initialized themselves. use binaryninjacore_sys::{ - BNBinaryView, BNFunction, BNRegisterPluginCommand, BNRegisterPluginCommandForAddress, - BNRegisterPluginCommandForFunction, BNRegisterPluginCommandForRange, + BNBinaryView, BNFunction, BNProject, BNRegisterPluginCommand, + BNRegisterPluginCommandForAddress, BNRegisterPluginCommandForFunction, + BNRegisterPluginCommandForProject, BNRegisterPluginCommandForRange, }; -use std::ops::Range; -use std::os::raw::c_void; - use crate::binary_view::BinaryView; use crate::function::Function; +use crate::project::Project; use crate::string::IntoCStr; +use std::ops::Range; +use std::os::raw::c_void; +use std::ptr::NonNull; /// The trait required for generic commands. See [register_command] for example usage. pub trait Command: 'static + Sync { @@ -451,3 +453,56 @@ pub fn register_command_for_function<C: FunctionCommand>(name: &str, desc: &str, ); } } + +pub trait ProjectCommand: 'static + Sync { + fn action(&self, project: &Project); + fn valid(&self, project: &Project) -> bool; +} + +pub fn register_command_for_project<C: ProjectCommand>(name: &str, desc: &str, command: C) { + extern "C" fn cb_action<C>(ctxt: *mut c_void, project: *mut BNProject) + where + C: ProjectCommand, + { + ffi_wrap!("Command::action", unsafe { + let cmd = &*(ctxt as *const C); + + let handle = NonNull::new(project).expect("project handle is null"); + let project = Project { handle }; + + cmd.action(&project); + }) + } + + extern "C" fn cb_valid<C>(ctxt: *mut c_void, project: *mut BNProject) -> bool + where + C: ProjectCommand, + { + ffi_wrap!("Command::valid", unsafe { + let cmd = &*(ctxt as *const C); + + let handle = NonNull::new(project).expect("project handle is null"); + let project = Project { handle }; + + cmd.valid(&project) + }) + } + + let name = name.to_cstr(); + let desc = desc.to_cstr(); + + let name_ptr = name.as_ptr(); + let desc_ptr = desc.as_ptr(); + + let ctxt = Box::into_raw(Box::new(command)); + + unsafe { + BNRegisterPluginCommandForProject( + name_ptr, + desc_ptr, + Some(cb_action::<C>), + Some(cb_valid::<C>), + ctxt as *mut _, + ); + } +} |
