mssf_core/api/
mod.rs

1//! Dynamically load SF libs and c functions.
2//! SF shared lib provides these functions, and we dynamically load them here so that user of this crate
3//! does not need to worry about installing SF lib and linking, which can be complex.
4//!
5
6use mssf_com::{
7    FabricClient::{IFabricClientConnectionEventHandler, IFabricServiceNotificationEventHandler},
8    FabricCommon::{
9        IFabricAsyncOperationCallback, IFabricAsyncOperationContext, IFabricStringResult,
10    },
11    FabricRuntime::IFabricStoreEventHandler,
12    FabricTypes::{FABRIC_CLIENT_ROLE, FABRIC_LOCAL_STORE_KIND, FABRIC_REPLICATOR_SETTINGS},
13};
14use windows_core::{Interface, Param};
15
16lazy_static::lazy_static! {
17    static ref LIB_TABLE: LibTable = LibTable::create();
18    /// All SF APIs entrypoints needed for mssf.
19    /// These APIs are lazy loaded at the first time use after app starts.
20    pub static ref API_TABLE: ApiTable = ApiTable::create(&LIB_TABLE);
21}
22
23/// Contains all the SF shared libs needs to be loaded for mssf.
24pub struct LibTable {
25    fabric_runtime: libloading::Library,
26    fabric_common: libloading::Library,
27    fabric_client: libloading::Library,
28}
29
30impl LibTable {
31    fn create() -> Self {
32        Self {
33            fabric_runtime: load_lib("FabricRuntime"),
34            fabric_common: load_lib("FabricCommon"),
35            fabric_client: load_lib("FabricClient"),
36        }
37    }
38}
39
40fn load_lib(name: &str) -> libloading::Library {
41    unsafe { libloading::Library::new(libloading::library_filename(name)) }
42        .unwrap_or_else(|e| panic!("cannot load lib {name} :{e}"))
43}
44
45fn load_fn<T>(lib: &'static libloading::Library, name: &str) -> libloading::Symbol<'static, T> {
46    unsafe { lib.get(name.as_bytes()) }.unwrap_or_else(|e| panic!("cannot load fn {name} :{e}"))
47}
48
49/// Contains all SF APIs loaded from SF libs needed for mssf.
50/// More APIs can be added here when mssf needs them.
51pub struct ApiTable {
52    fabric_get_last_error_message_fn: libloading::Symbol<
53        'static,
54        unsafe extern "system" fn(message: *mut *mut core::ffi::c_void) -> crate::HRESULT,
55    >,
56    fabric_create_client3_fn: libloading::Symbol<
57        'static,
58        unsafe extern "system" fn(
59            connectionstringssize: u16,
60            connectionstrings: *const windows_core::PCWSTR,
61            __midl__fabricclientmodule0002: *mut core::ffi::c_void,
62            __midl__fabricclientmodule0003: *mut core::ffi::c_void,
63            iid: *const windows_core::GUID,
64            fabricclient: *mut *mut core::ffi::c_void,
65        ) -> crate::HRESULT,
66    >,
67    fabric_create_local_client3_fn: libloading::Symbol<
68        'static,
69        unsafe extern "system" fn(
70            __midl__fabricclientmodule0004: *mut core::ffi::c_void,
71            __midl__fabricclientmodule0005: *mut core::ffi::c_void,
72            iid: *const windows_core::GUID,
73            fabricclient: *mut *mut core::ffi::c_void,
74        ) -> crate::HRESULT,
75    >,
76
77    fabric_create_local_client4_fn: libloading::Symbol<
78        'static,
79        unsafe extern "system" fn(
80            __midl__fabricclientmodule0006: *mut core::ffi::c_void,
81            __midl__fabricclientmodule0007: *mut core::ffi::c_void,
82            clientrole: FABRIC_CLIENT_ROLE,
83            iid: *const windows_core::GUID,
84            fabricclient: *mut *mut core::ffi::c_void,
85        ) -> crate::HRESULT,
86    >,
87
88    fabric_create_runtime_fn: libloading::Symbol<
89        'static,
90        unsafe extern "system" fn(
91            riid: *const windows_core::GUID,
92            fabricruntime: *mut *mut core::ffi::c_void,
93        ) -> crate::HRESULT,
94    >,
95
96    fabric_get_activation_context_fn: libloading::Symbol<
97        'static,
98        unsafe extern "system" fn(
99            riid: *const windows_core::GUID,
100            activationcontext: *mut *mut core::ffi::c_void,
101        ) -> crate::HRESULT,
102    >,
103
104    fabric_begin_get_node_context_fn: libloading::Symbol<
105        'static,
106        unsafe extern "system" fn(
107            timeoutmilliseconds: u32,
108            callback: *mut core::ffi::c_void,
109            context: *mut *mut core::ffi::c_void,
110        ) -> crate::HRESULT,
111    >,
112
113    fabric_end_get_node_context_fn: libloading::Symbol<
114        'static,
115        unsafe extern "system" fn(
116            context: *mut core::ffi::c_void,
117            nodecontext: *mut *mut core::ffi::c_void,
118        ) -> crate::HRESULT,
119    >,
120    fabric_get_node_context_fn: libloading::Symbol<
121        'static,
122        unsafe extern "system" fn(nodecontext: *mut *mut core::ffi::c_void) -> crate::HRESULT,
123    >,
124    fabric_create_key_value_store_replica_fn: libloading::Symbol<
125        'static,
126        unsafe extern "system" fn(
127            riid: *const windows_core::GUID,
128            storename: windows_core::PCWSTR,
129            partitionid: windows_core::GUID,
130            replicaid: i64,
131            replicatorsettings: *const FABRIC_REPLICATOR_SETTINGS,
132            localstorekind: FABRIC_LOCAL_STORE_KIND,
133            localstoresettings: *const core::ffi::c_void,
134            storeeventhandler: *mut core::ffi::c_void,
135            keyvaluestore: *mut *mut core::ffi::c_void,
136        ) -> crate::HRESULT,
137    >,
138}
139
140impl ApiTable {
141    fn create(lib_table: &'static LibTable) -> Self {
142        Self {
143            fabric_get_last_error_message_fn: load_fn(
144                &lib_table.fabric_common,
145                "FabricGetLastErrorMessage",
146            ),
147            fabric_create_client3_fn: load_fn(&lib_table.fabric_client, "FabricCreateClient3"),
148            fabric_create_local_client3_fn: load_fn(
149                &lib_table.fabric_client,
150                "FabricCreateLocalClient3",
151            ),
152            fabric_create_local_client4_fn: load_fn(
153                &lib_table.fabric_client,
154                "FabricCreateLocalClient4",
155            ),
156            fabric_create_runtime_fn: load_fn(&lib_table.fabric_runtime, "FabricCreateRuntime"),
157            fabric_get_activation_context_fn: load_fn(
158                &lib_table.fabric_runtime,
159                "FabricGetActivationContext",
160            ),
161            fabric_begin_get_node_context_fn: load_fn(
162                &lib_table.fabric_runtime,
163                "FabricBeginGetNodeContext",
164            ),
165            fabric_end_get_node_context_fn: load_fn(
166                &lib_table.fabric_runtime,
167                "FabricEndGetNodeContext",
168            ),
169            fabric_get_node_context_fn: load_fn(&lib_table.fabric_runtime, "FabricGetNodeContext"),
170            fabric_create_key_value_store_replica_fn: load_fn(
171                &lib_table.fabric_runtime,
172                "FabricCreateKeyValueStoreReplica",
173            ),
174        }
175    }
176
177    pub fn fabric_get_last_error_message(&self) -> crate::WinResult<IFabricStringResult> {
178        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
179        unsafe { (self.fabric_get_last_error_message_fn)(std::ptr::addr_of_mut!(result)) }.ok()?;
180        assert!(!result.is_null());
181        Ok(unsafe { IFabricStringResult::from_raw(result) })
182    }
183
184    pub fn fabric_create_client3<T: Interface>(
185        &self,
186        connectionstrings: &[windows_core::PCWSTR],
187        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
188        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
189    ) -> crate::WinResult<T> {
190        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
191        unsafe {
192            (self.fabric_create_client3_fn)(
193                connectionstrings.len().try_into().unwrap(),
194                connectionstrings.as_ptr(),
195                service_notification_handler.param().abi(),
196                client_connection_handler.param().abi(),
197                &T::IID,
198                std::ptr::addr_of_mut!(result),
199            )
200        }
201        .ok()?;
202        Ok(unsafe { T::from_raw(result) })
203    }
204
205    pub fn fabric_create_local_client3<T: Interface>(
206        &self,
207        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
208        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
209    ) -> crate::WinResult<T> {
210        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
211        unsafe {
212            (self.fabric_create_local_client3_fn)(
213                service_notification_handler.param().abi(),
214                client_connection_handler.param().abi(),
215                &T::IID,
216                std::ptr::addr_of_mut!(result),
217            )
218        }
219        .ok()?;
220        Ok(unsafe { T::from_raw(result) })
221    }
222
223    pub fn fabric_create_local_client4<T: Interface>(
224        &self,
225        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
226        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
227        clientrole: FABRIC_CLIENT_ROLE,
228    ) -> crate::WinResult<T> {
229        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
230        unsafe {
231            (self.fabric_create_local_client4_fn)(
232                service_notification_handler.param().abi(),
233                client_connection_handler.param().abi(),
234                clientrole,
235                &T::IID,
236                std::ptr::addr_of_mut!(result),
237            )
238        }
239        .ok()?;
240        Ok(unsafe { T::from_raw(result) })
241    }
242
243    pub fn fabric_create_runtime<T: Interface>(&self) -> crate::WinResult<T> {
244        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
245        unsafe { (self.fabric_create_runtime_fn)(&T::IID, std::ptr::addr_of_mut!(result)) }.ok()?;
246        Ok(unsafe { T::from_raw(result) })
247    }
248
249    pub fn fabric_get_activation_context<T: Interface>(&self) -> crate::WinResult<T> {
250        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
251        unsafe { (self.fabric_get_activation_context_fn)(&T::IID, std::ptr::addr_of_mut!(result)) }
252            .ok()?;
253        Ok(unsafe { T::from_raw(result) })
254    }
255
256    pub fn fabric_begin_get_node_context(
257        &self,
258        timeoutmilliseconds: u32,
259        callback: Option<&IFabricAsyncOperationCallback>,
260    ) -> crate::WinResult<IFabricAsyncOperationContext> {
261        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
262        unsafe {
263            (self.fabric_begin_get_node_context_fn)(
264                timeoutmilliseconds,
265                callback.param().abi(),
266                std::ptr::addr_of_mut!(result),
267            )
268        }
269        .ok()?;
270        Ok(unsafe { IFabricAsyncOperationContext::from_raw(result) })
271    }
272
273    pub fn fabric_end_get_node_context<T: Interface>(
274        &self,
275        context: Option<&IFabricAsyncOperationContext>,
276    ) -> crate::WinResult<T> {
277        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
278        unsafe {
279            (self.fabric_end_get_node_context_fn)(
280                context.param().abi(),
281                std::ptr::addr_of_mut!(result),
282            )
283        }
284        .ok()?;
285        Ok(unsafe { T::from_raw(result) })
286    }
287
288    pub fn fabric_get_node_context<T: Interface>(&self) -> crate::WinResult<T> {
289        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
290        unsafe { (self.fabric_get_node_context_fn)(std::ptr::addr_of_mut!(result)) }.ok()?;
291        Ok(unsafe { T::from_raw(result) })
292    }
293
294    #[allow(clippy::too_many_arguments)]
295    pub fn fabric_create_key_value_store_replica<T: Interface>(
296        &self,
297        storename: windows_core::PCWSTR,
298        partitionid: windows_core::GUID,
299        replicaid: i64,
300        replicatorsettings: *const FABRIC_REPLICATOR_SETTINGS,
301        localstorekind: FABRIC_LOCAL_STORE_KIND,
302        localstoresettings: *const core::ffi::c_void,
303        storeeventhandler: Option<&IFabricStoreEventHandler>,
304    ) -> crate::WinResult<T> {
305        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
306        unsafe {
307            (self.fabric_create_key_value_store_replica_fn)(
308                &T::IID,
309                storename,
310                partitionid,
311                replicaid,
312                replicatorsettings,
313                localstorekind,
314                localstoresettings,
315                storeeventhandler.param().abi(),
316                std::ptr::addr_of_mut!(result),
317            )
318        }
319        .ok()?;
320        Ok(unsafe { T::from_raw(result) })
321    }
322}