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
49pub 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}