binaryninja/
main_thread.rs1use crate::rc::{Ref, RefCountable};
2use binaryninjacore_sys::{
3 BNExecuteMainThreadAction, BNExecuteOnMainThread, BNExecuteOnMainThreadAndWait,
4 BNFreeMainThreadAction, BNIsMainThreadActionDone, BNMainThreadAction, BNMainThreadCallbacks,
5 BNNewMainThreadActionReference, BNRegisterMainThread, BNWaitForMainThreadAction,
6};
7use std::ffi::c_void;
8
9pub struct MainThreadActionExecutor {
10 func: Box<dyn Fn()>,
11}
12
13impl MainThreadActionExecutor {
14 unsafe extern "C" fn cb_execute(ctx: *mut c_void) {
15 let f: Box<Self> = Box::from_raw(ctx as *mut Self);
16 f.execute();
17 }
18
19 pub fn execute(&self) {
20 (self.func)();
21 }
22}
23
24pub fn execute_on_main_thread<F: Fn() + 'static>(f: F) -> Option<Ref<MainThreadAction>> {
28 let boxed_executor = Box::new(MainThreadActionExecutor { func: Box::new(f) });
29 let raw_executor = Box::into_raw(boxed_executor);
30 let raw_action = unsafe {
31 BNExecuteOnMainThread(
32 raw_executor as *mut c_void,
33 Some(MainThreadActionExecutor::cb_execute),
34 )
35 };
36 match raw_action.is_null() {
37 false => Some(MainThreadAction::ref_from_raw(raw_action)),
38 true => None,
39 }
40}
41
42pub fn execute_on_main_thread_and_wait<F: Fn() + 'static>(f: F) {
46 let boxed_executor = Box::new(MainThreadActionExecutor { func: Box::new(f) });
47 let raw_executor = Box::into_raw(boxed_executor);
48 unsafe {
49 BNExecuteOnMainThreadAndWait(
50 raw_executor as *mut c_void,
51 Some(MainThreadActionExecutor::cb_execute),
52 )
53 };
54}
55
56pub trait MainThreadHandler: Sized {
58 fn add_action(&self, _view: Ref<MainThreadAction>);
59
60 unsafe extern "C" fn cb_add_action(ctxt: *mut c_void, action: *mut BNMainThreadAction) {
61 ffi_wrap!("MainThread::add_action", {
62 let main_thread = &*(ctxt as *mut Self);
63 let action = MainThreadAction::ref_from_raw(action);
64 main_thread.add_action(action);
65 })
66 }
67
68 fn register(self) {
72 let raw = Box::into_raw(Box::new(self));
74 let mut callbacks = BNMainThreadCallbacks {
75 context: raw as *mut c_void,
76 addAction: Some(Self::cb_add_action),
77 };
78 unsafe { BNRegisterMainThread(&mut callbacks) };
79 }
80}
81
82pub struct MainThreadAction {
83 pub handle: *mut BNMainThreadAction,
84}
85
86impl MainThreadAction {
87 pub fn from_raw(handle: *mut BNMainThreadAction) -> Self {
88 assert!(!handle.is_null());
89 Self { handle }
90 }
91
92 pub fn ref_from_raw(handle: *mut BNMainThreadAction) -> Ref<Self> {
93 unsafe { Ref::new(Self::from_raw(handle)) }
94 }
95
96 pub fn execute(&self) {
97 unsafe { BNExecuteMainThreadAction(self.handle) }
98 }
99
100 pub fn is_done(&self) -> bool {
101 unsafe { BNIsMainThreadActionDone(self.handle) }
102 }
103
104 pub fn wait(&self) {
105 unsafe { BNWaitForMainThreadAction(self.handle) }
106 }
107}
108
109impl ToOwned for MainThreadAction {
110 type Owned = Ref<Self>;
111
112 fn to_owned(&self) -> Self::Owned {
113 unsafe { RefCountable::inc_ref(self) }
114 }
115}
116
117unsafe impl RefCountable for MainThreadAction {
118 unsafe fn inc_ref(action: &Self) -> Ref<Self> {
119 Ref::new(Self {
120 handle: BNNewMainThreadActionReference(action.handle),
121 })
122 }
123
124 unsafe fn dec_ref(action: &Self) {
125 BNFreeMainThreadAction(action.handle);
126 }
127}
128
129unsafe impl Send for MainThreadAction {}