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.
51#[allow(non_snake_case)]
52pub struct ApiTable {
53    fabric_get_last_error_message_fn: libloading::Symbol<
54        'static,
55        unsafe extern "system" fn(message: *mut *mut core::ffi::c_void) -> crate::HRESULT,
56    >,
57    fabric_create_client3_fn: libloading::Symbol<
58        'static,
59        unsafe extern "system" fn(
60            connectionstringssize: u16,
61            connectionstrings: *const windows_core::PCWSTR,
62            __midl__fabricclientmodule0002: *mut core::ffi::c_void,
63            __midl__fabricclientmodule0003: *mut core::ffi::c_void,
64            iid: *const windows_core::GUID,
65            fabricclient: *mut *mut core::ffi::c_void,
66        ) -> crate::HRESULT,
67    >,
68    fabric_create_local_client3_fn: libloading::Symbol<
69        'static,
70        unsafe extern "system" fn(
71            __midl__fabricclientmodule0004: *mut core::ffi::c_void,
72            __midl__fabricclientmodule0005: *mut core::ffi::c_void,
73            iid: *const windows_core::GUID,
74            fabricclient: *mut *mut core::ffi::c_void,
75        ) -> crate::HRESULT,
76    >,
77
78    fabric_create_local_client4_fn: libloading::Symbol<
79        'static,
80        unsafe extern "system" fn(
81            __midl__fabricclientmodule0006: *mut core::ffi::c_void,
82            __midl__fabricclientmodule0007: *mut core::ffi::c_void,
83            clientrole: FABRIC_CLIENT_ROLE,
84            iid: *const windows_core::GUID,
85            fabricclient: *mut *mut core::ffi::c_void,
86        ) -> crate::HRESULT,
87    >,
88
89    fabric_create_runtime_fn: libloading::Symbol<
90        'static,
91        unsafe extern "system" fn(
92            riid: *const windows_core::GUID,
93            fabricruntime: *mut *mut core::ffi::c_void,
94        ) -> crate::HRESULT,
95    >,
96
97    fabric_get_activation_context_fn: libloading::Symbol<
98        'static,
99        unsafe extern "system" fn(
100            riid: *const windows_core::GUID,
101            activationcontext: *mut *mut core::ffi::c_void,
102        ) -> crate::HRESULT,
103    >,
104
105    fabric_begin_get_node_context_fn: libloading::Symbol<
106        'static,
107        unsafe extern "system" fn(
108            timeoutmilliseconds: u32,
109            callback: *mut core::ffi::c_void,
110            context: *mut *mut core::ffi::c_void,
111        ) -> crate::HRESULT,
112    >,
113
114    fabric_end_get_node_context_fn: libloading::Symbol<
115        'static,
116        unsafe extern "system" fn(
117            context: *mut core::ffi::c_void,
118            nodecontext: *mut *mut core::ffi::c_void,
119        ) -> crate::HRESULT,
120    >,
121    fabric_get_node_context_fn: libloading::Symbol<
122        'static,
123        unsafe extern "system" fn(nodecontext: *mut *mut core::ffi::c_void) -> crate::HRESULT,
124    >,
125    fabric_create_key_value_store_replica_fn: libloading::Symbol<
126        'static,
127        unsafe extern "system" fn(
128            riid: *const windows_core::GUID,
129            storename: windows_core::PCWSTR,
130            partitionid: windows_core::GUID,
131            replicaid: i64,
132            replicatorsettings: *const FABRIC_REPLICATOR_SETTINGS,
133            localstorekind: FABRIC_LOCAL_STORE_KIND,
134            localstoresettings: *const core::ffi::c_void,
135            storeeventhandler: *mut core::ffi::c_void,
136            keyvaluestore: *mut *mut core::ffi::c_void,
137        ) -> crate::HRESULT,
138    >,
139}
140
141impl ApiTable {
142    fn create(lib_table: &'static LibTable) -> Self {
143        Self {
144            fabric_get_last_error_message_fn: load_fn(
145                &lib_table.fabric_common,
146                "FabricGetLastErrorMessage",
147            ),
148            fabric_create_client3_fn: load_fn(&lib_table.fabric_client, "FabricCreateClient3"),
149            fabric_create_local_client3_fn: load_fn(
150                &lib_table.fabric_client,
151                "FabricCreateLocalClient3",
152            ),
153            fabric_create_local_client4_fn: load_fn(
154                &lib_table.fabric_client,
155                "FabricCreateLocalClient4",
156            ),
157            fabric_create_runtime_fn: load_fn(&lib_table.fabric_runtime, "FabricCreateRuntime"),
158            fabric_get_activation_context_fn: load_fn(
159                &lib_table.fabric_runtime,
160                "FabricGetActivationContext",
161            ),
162            fabric_begin_get_node_context_fn: load_fn(
163                &lib_table.fabric_runtime,
164                "FabricBeginGetNodeContext",
165            ),
166            fabric_end_get_node_context_fn: load_fn(
167                &lib_table.fabric_runtime,
168                "FabricEndGetNodeContext",
169            ),
170            fabric_get_node_context_fn: load_fn(&lib_table.fabric_runtime, "FabricGetNodeContext"),
171            fabric_create_key_value_store_replica_fn: load_fn(
172                &lib_table.fabric_runtime,
173                "FabricCreateKeyValueStoreReplica",
174            ),
175        }
176    }
177
178    pub fn fabric_get_last_error_message(&self) -> crate::WinResult<IFabricStringResult> {
179        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
180        unsafe { (self.fabric_get_last_error_message_fn)(std::ptr::addr_of_mut!(result)) }.ok()?;
181        assert!(!result.is_null());
182        Ok(unsafe { IFabricStringResult::from_raw(result) })
183    }
184
185    pub fn fabric_create_client3<T: Interface>(
186        &self,
187        connectionstrings: &[windows_core::PCWSTR],
188        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
189        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
190    ) -> crate::WinResult<T> {
191        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
192        unsafe {
193            (self.fabric_create_client3_fn)(
194                connectionstrings.len().try_into().unwrap(),
195                connectionstrings.as_ptr(),
196                service_notification_handler.param().abi(),
197                client_connection_handler.param().abi(),
198                &T::IID,
199                std::ptr::addr_of_mut!(result),
200            )
201        }
202        .ok()?;
203        Ok(unsafe { T::from_raw(result) })
204    }
205
206    pub fn fabric_create_local_client3<T: Interface>(
207        &self,
208        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
209        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
210    ) -> crate::WinResult<T> {
211        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
212        unsafe {
213            (self.fabric_create_local_client3_fn)(
214                service_notification_handler.param().abi(),
215                client_connection_handler.param().abi(),
216                &T::IID,
217                std::ptr::addr_of_mut!(result),
218            )
219        }
220        .ok()?;
221        Ok(unsafe { T::from_raw(result) })
222    }
223
224    pub fn fabric_create_local_client4<T: Interface>(
225        &self,
226        service_notification_handler: Option<&IFabricServiceNotificationEventHandler>,
227        client_connection_handler: Option<&IFabricClientConnectionEventHandler>,
228        clientrole: FABRIC_CLIENT_ROLE,
229    ) -> crate::WinResult<T> {
230        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
231        unsafe {
232            (self.fabric_create_local_client4_fn)(
233                service_notification_handler.param().abi(),
234                client_connection_handler.param().abi(),
235                clientrole,
236                &T::IID,
237                std::ptr::addr_of_mut!(result),
238            )
239        }
240        .ok()?;
241        Ok(unsafe { T::from_raw(result) })
242    }
243
244    pub fn fabric_create_runtime<T: Interface>(&self) -> crate::WinResult<T> {
245        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
246        unsafe { (self.fabric_create_runtime_fn)(&T::IID, std::ptr::addr_of_mut!(result)) }.ok()?;
247        Ok(unsafe { T::from_raw(result) })
248    }
249
250    pub fn fabric_get_activation_context<T: Interface>(&self) -> crate::WinResult<T> {
251        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
252        unsafe { (self.fabric_get_activation_context_fn)(&T::IID, std::ptr::addr_of_mut!(result)) }
253            .ok()?;
254        Ok(unsafe { T::from_raw(result) })
255    }
256
257    pub fn fabric_begin_get_node_context(
258        &self,
259        timeoutmilliseconds: u32,
260        callback: Option<&IFabricAsyncOperationCallback>,
261    ) -> crate::WinResult<IFabricAsyncOperationContext> {
262        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
263        unsafe {
264            (self.fabric_begin_get_node_context_fn)(
265                timeoutmilliseconds,
266                callback.param().abi(),
267                std::ptr::addr_of_mut!(result),
268            )
269        }
270        .ok()?;
271        Ok(unsafe { IFabricAsyncOperationContext::from_raw(result) })
272    }
273
274    pub fn fabric_end_get_node_context<T: Interface>(
275        &self,
276        context: Option<&IFabricAsyncOperationContext>,
277    ) -> crate::WinResult<T> {
278        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
279        unsafe {
280            (self.fabric_end_get_node_context_fn)(
281                context.param().abi(),
282                std::ptr::addr_of_mut!(result),
283            )
284        }
285        .ok()?;
286        Ok(unsafe { T::from_raw(result) })
287    }
288
289    pub fn fabric_get_node_context<T: Interface>(&self) -> crate::WinResult<T> {
290        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
291        unsafe { (self.fabric_get_node_context_fn)(std::ptr::addr_of_mut!(result)) }.ok()?;
292        Ok(unsafe { T::from_raw(result) })
293    }
294
295    #[allow(clippy::too_many_arguments)]
296    pub fn fabric_create_key_value_store_replica<T: Interface>(
297        &self,
298        storename: windows_core::PCWSTR,
299        partitionid: windows_core::GUID,
300        replicaid: i64,
301        replicatorsettings: *const FABRIC_REPLICATOR_SETTINGS,
302        localstorekind: FABRIC_LOCAL_STORE_KIND,
303        localstoresettings: *const core::ffi::c_void,
304        storeeventhandler: Option<&IFabricStoreEventHandler>,
305    ) -> crate::WinResult<T> {
306        let mut result = std::ptr::null_mut::<core::ffi::c_void>();
307        unsafe {
308            (self.fabric_create_key_value_store_replica_fn)(
309                &T::IID,
310                storename,
311                partitionid,
312                replicaid,
313                replicatorsettings,
314                localstorekind,
315                localstoresettings,
316                storeeventhandler.param().abi(),
317                std::ptr::addr_of_mut!(result),
318            )
319        }
320        .ok()?;
321        Ok(unsafe { T::from_raw(result) })
322    }
323}