1use 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 pub static ref API_TABLE: ApiTable = ApiTable::create(&LIB_TABLE);
21}
22
23pub 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#[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}