Skip to main content

mssf_core/runtime/
self_reconfiguring_bridge.rs

1// ------------------------------------------------------------
2// Copyright (c) Microsoft Corporation.  All rights reserved.
3// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
4// ------------------------------------------------------------
5
6// windows::core::implement macro generates snake case types.
7#![allow(non_camel_case_types)]
8
9use std::sync::Arc;
10
11use crate::{
12    ErrorCode, runtime::SelfReconfiguringServicePartition, strings::StringResult,
13    sync::BridgeContext, types::Uri,
14};
15use mssf_com::{
16    FabricCommon::IFabricStringResult,
17    FabricRuntime::{
18        IFabricSelfReconfiguringConfigurationChangeRequest, IFabricSelfReconfiguringServiceFactory,
19        IFabricSelfReconfiguringServiceFactory_Impl, IFabricSelfReconfiguringServiceInstance,
20        IFabricSelfReconfiguringServiceInstance_Impl, IFabricSelfReconfiguringServicePartition,
21    },
22    FabricTypes::{
23        FABRIC_SELF_RECONFIGURING_CONFIGURATION_REQUEST,
24        FABRIC_SELF_RECONFIGURING_INSTANCE_OPEN_MODE, FABRIC_URI,
25    },
26};
27use windows_core::{WString, implement};
28
29use crate::runtime::{
30    executor::Executor,
31    {ISelfReconfiguringServiceFactory, ISelfReconfiguringServiceInstance},
32};
33use crate::types::{
34    SelfReconfiguringConfigurationChangeRequest, SelfReconfiguringConfigurationRequest,
35    SelfReconfiguringOpenMode,
36};
37
38#[implement(IFabricSelfReconfiguringServiceFactory)]
39pub struct SelfReconfiguringServiceFactoryBridge<E>
40where
41    E: Executor + 'static,
42{
43    inner: Box<dyn ISelfReconfiguringServiceFactory>,
44    rt: E,
45}
46
47impl<E> SelfReconfiguringServiceFactoryBridge<E>
48where
49    E: Executor,
50{
51    pub fn create(
52        factory: Box<dyn ISelfReconfiguringServiceFactory>,
53        rt: E,
54    ) -> SelfReconfiguringServiceFactoryBridge<E> {
55        SelfReconfiguringServiceFactoryBridge { inner: factory, rt }
56    }
57}
58
59impl<E> IFabricSelfReconfiguringServiceFactory_Impl
60    for SelfReconfiguringServiceFactoryBridge_Impl<E>
61where
62    E: Executor,
63{
64    #[allow(clippy::not_unsafe_ptr_arg_deref)]
65    #[cfg_attr(
66        feature = "tracing",
67        tracing::instrument(skip_all, ret(level = "debug"), err)
68    )]
69    fn CreateInstance(
70        &self,
71        servicetypename: &crate::PCWSTR,
72        servicename: FABRIC_URI,
73        initializationdatalength: u32,
74        initializationdata: *const u8,
75        partitionid: &crate::GUID,
76        instanceid: i64,
77    ) -> crate::WinResult<IFabricSelfReconfiguringServiceInstance> {
78        let h_servicename = Uri::from(servicename);
79        let h_servicetypename = WString::from(*servicetypename);
80        let data = unsafe {
81            if !initializationdata.is_null() {
82                std::slice::from_raw_parts(initializationdata, initializationdatalength as usize)
83            } else {
84                &[]
85            }
86        };
87
88        let instance = self.inner.create_instance(
89            h_servicetypename,
90            h_servicename,
91            data,
92            *partitionid,
93            instanceid,
94        )?;
95        let rt = self.rt.clone();
96        let instance_bridge = IFabricSelfReconfiguringServiceInstanceBridge::create(instance, rt);
97
98        Ok(instance_bridge.into())
99    }
100}
101
102// bridge from safe service instance to com
103#[implement(IFabricSelfReconfiguringServiceInstance)]
104pub(crate) struct IFabricSelfReconfiguringServiceInstanceBridge<E>
105where
106    E: Executor,
107{
108    inner: Arc<Box<dyn ISelfReconfiguringServiceInstance>>,
109    rt: E,
110}
111
112impl<E> IFabricSelfReconfiguringServiceInstanceBridge<E>
113where
114    E: Executor,
115{
116    pub fn create(
117        instance: Box<dyn ISelfReconfiguringServiceInstance>,
118        rt: E,
119    ) -> IFabricSelfReconfiguringServiceInstanceBridge<E> {
120        IFabricSelfReconfiguringServiceInstanceBridge {
121            inner: Arc::new(instance),
122            rt,
123        }
124    }
125}
126
127impl<E> IFabricSelfReconfiguringServiceInstance_Impl
128    for IFabricSelfReconfiguringServiceInstanceBridge_Impl<E>
129where
130    E: Executor,
131{
132    #[cfg_attr(
133        feature = "tracing",
134        tracing::instrument(skip_all, ret(level = "debug"), err)
135    )]
136    fn BeginOpen(
137        &self,
138        openmode: FABRIC_SELF_RECONFIGURING_INSTANCE_OPEN_MODE,
139        partition: windows_core::Ref<IFabricSelfReconfiguringServicePartition>,
140        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
141    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
142        let partition_cp = partition.unwrap().clone();
143        let partition_bridge = SelfReconfiguringServicePartition::new(partition_cp);
144        let open_mode = SelfReconfiguringOpenMode::from(openmode);
145        let inner = self.inner.clone();
146        let (ctx, token) = BridgeContext::make(callback);
147        ctx.spawn(&self.rt, async move {
148            inner
149                .open(Arc::new(partition_bridge), open_mode, token)
150                .await
151                .map(|s| IFabricStringResult::from(StringResult::new(s)))
152                .map_err(crate::WinError::from)
153        })
154    }
155
156    #[cfg_attr(
157        feature = "tracing",
158        tracing::instrument(skip_all, ret(level = "debug"), err)
159    )]
160    fn EndOpen(
161        &self,
162        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
163    ) -> crate::WinResult<IFabricStringResult> {
164        BridgeContext::result(context)?
165    }
166
167    #[allow(clippy::not_unsafe_ptr_arg_deref)]
168    #[cfg_attr(
169        feature = "tracing",
170        tracing::instrument(skip_all, ret(level = "debug"), err)
171    )]
172    fn RequestConfiguration(
173        &self,
174        configurationrequest: *const FABRIC_SELF_RECONFIGURING_CONFIGURATION_REQUEST,
175    ) -> crate::WinResult<()> {
176        if configurationrequest.is_null() {
177            return Err(ErrorCode::E_POINTER.into());
178        }
179        let request =
180            SelfReconfiguringConfigurationRequest::from(unsafe { &*configurationrequest });
181        self.inner
182            .request_configuration(request)
183            .map_err(crate::WinError::from)
184    }
185
186    #[cfg_attr(
187        feature = "tracing",
188        tracing::instrument(skip_all, ret(level = "debug"), err)
189    )]
190    fn RequestConfigurationChange(
191        &self,
192        configurationchangerequest: windows_core::Ref<
193            IFabricSelfReconfiguringConfigurationChangeRequest,
194        >,
195    ) -> crate::WinResult<()> {
196        let com = configurationchangerequest.ok()?;
197        let raw = unsafe { com.get_ConfigurationChangeRequest() };
198        if raw.is_null() {
199            return Err(ErrorCode::E_POINTER.into());
200        }
201        let change = SelfReconfiguringConfigurationChangeRequest::from(unsafe { &*raw });
202        self.inner
203            .request_configuration_change(change)
204            .map_err(crate::WinError::from)
205    }
206
207    #[cfg_attr(
208        feature = "tracing",
209        tracing::instrument(skip_all, ret(level = "debug"), err)
210    )]
211    fn BeginClose(
212        &self,
213        callback: windows_core::Ref<super::IFabricAsyncOperationCallback>,
214    ) -> crate::WinResult<super::IFabricAsyncOperationContext> {
215        let inner = self.inner.clone();
216        let (ctx, token) = BridgeContext::make(callback);
217        ctx.spawn(&self.rt, async move {
218            inner.close(token).await.map_err(crate::WinError::from)
219        })
220    }
221
222    #[cfg_attr(
223        feature = "tracing",
224        tracing::instrument(skip_all, ret(level = "debug"), err)
225    )]
226    fn EndClose(
227        &self,
228        context: windows_core::Ref<super::IFabricAsyncOperationContext>,
229    ) -> crate::WinResult<()> {
230        BridgeContext::result(context)?
231    }
232
233    #[cfg_attr(
234        feature = "tracing",
235        tracing::instrument(skip_all, ret(level = "debug"))
236    )]
237    fn Abort(&self) {
238        self.inner.abort()
239    }
240}