com_shim/
lib.rs

1#![warn(missing_docs)]
2#![warn(clippy::pedantic)]
3#![doc = include_str!("../README.md")]
4
5use std::mem::ManuallyDrop;
6
7use windows::{
8    Win32::{
9        Foundation::VARIANT_BOOL,
10        System::{
11            Com::{DISPATCH_METHOD, DISPATCH_PROPERTYGET, DISPATCH_PROPERTYPUT, DISPPARAMS},
12            Variant::{
13                VAR_CHANGE_FLAGS, VARIANT_0_0, VT_BOOL, VT_BSTR, VT_DISPATCH, VT_I2, VT_I4, VT_I8,
14                VT_NULL, VT_UI1, VT_UI2, VT_UI4, VT_UI8, VariantChangeType, VariantClear,
15            },
16        },
17    },
18    core::{self, BSTR},
19};
20
21pub use com_shim_macro::com_shim;
22
23pub use windows::Win32::System::{Com::IDispatch, Variant::VARIANT};
24pub use windows::core::{GUID, Result};
25
26mod utils;
27
28/// A component that has an IDispatch value. Every component needs this, and this trait guarantees that.
29pub trait HasIDispatch<T = Self> {
30    /// Get the IDispatch object for low-level access to this component.
31    fn get_idispatch(&self) -> &IDispatch;
32}
33
34/// Additional functions for working with an [`IDispatch`].
35pub trait IDispatchExt {
36    /// Call a function on this IDispatch
37    fn call<S>(&self, name: S, args: Vec<VARIANT>) -> Result<VARIANT>
38    where
39        S: AsRef<str>;
40
41    /// Get the value of a variable on this IDispatch
42    fn get<S>(&self, name: S) -> Result<VARIANT>
43    where
44        S: AsRef<str>;
45
46    /// Set a value of a variable on this IDispatch
47    fn set<S>(&self, name: S, value: VARIANT) -> Result<VARIANT>
48    where
49        S: AsRef<str>;
50}
51
52impl IDispatchExt for IDispatch {
53    fn call<S>(&self, name: S, args: Vec<VARIANT>) -> Result<VARIANT>
54    where
55        S: AsRef<str>,
56    {
57        let iid_null = GUID::zeroed();
58        let mut result = VARIANT::null();
59        unsafe {
60            tracing::debug!("Invoking method: {}", name.as_ref());
61            self.Invoke(
62                utils::get_method_dispid(self, name)?,
63                &iid_null,
64                0,
65                DISPATCH_METHOD,
66                &utils::assemble_dispparams_get(args),
67                Some(&mut result),
68                None,
69                None,
70            )?;
71        }
72        Ok(result)
73    }
74
75    fn get<S>(&self, name: S) -> Result<VARIANT>
76    where
77        S: AsRef<str>,
78    {
79        let iid_null = GUID::zeroed();
80        let mut result = VARIANT::null();
81        unsafe {
82            self.Invoke(
83                utils::get_method_dispid(self, name)?,
84                &iid_null,
85                0,
86                DISPATCH_PROPERTYGET,
87                &DISPPARAMS::default(),
88                Some(&mut result),
89                None,
90                None,
91            )?;
92        }
93        Ok(result)
94    }
95
96    fn set<S>(&self, name: S, value: VARIANT) -> Result<VARIANT>
97    where
98        S: AsRef<str>,
99    {
100        let iid_null = GUID::zeroed();
101        let mut result = VARIANT::null();
102        unsafe {
103            self.Invoke(
104                utils::get_method_dispid(self, name)?,
105                &iid_null,
106                0,
107                DISPATCH_PROPERTYPUT,
108                &utils::assemble_dispparams_put(vec![value]),
109                Some(&mut result),
110                None,
111                None,
112            )?;
113        }
114        Ok(result)
115    }
116}
117
118/// Extension functions for a [`VARIANT`].
119pub trait VariantExt {
120    /// Generate a null [`VARIANT`].
121    fn null() -> VARIANT;
122}
123
124impl VariantExt for VARIANT {
125    fn null() -> VARIANT {
126        let mut variant = VARIANT::default();
127        let v00 = VARIANT_0_0 {
128            vt: VT_NULL,
129            ..Default::default()
130        };
131        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
132        variant
133    }
134}
135
136/// Indicates that this type is also a parent type and can be upcast to it.
137pub trait IsA<T> {
138    /// Upcast this value to it's parent type.
139    fn upcast(&self) -> T;
140}
141
142/// Functions to convert to and from a type that can be stored in a [`VARIANT`].
143pub trait VariantTypeExt<'a, T> {
144    /// Convert from a [`VARIANT`] into a type, T.
145    fn variant_into(&'a self) -> core::Result<T>;
146
147    /// Convert from a type T into a [`VARIANT`].
148    fn variant_from(value: T) -> VARIANT;
149}
150
151impl VariantTypeExt<'_, ()> for VARIANT {
152    fn variant_from(_value: ()) -> VARIANT {
153        VARIANT::null()
154    }
155
156    fn variant_into(&'_ self) -> core::Result<()> {
157        Ok(())
158    }
159}
160
161impl VariantTypeExt<'_, i16> for VARIANT {
162    fn variant_from(value: i16) -> VARIANT {
163        let mut variant = VARIANT::default();
164        let mut v00 = VARIANT_0_0 {
165            vt: VT_I2,
166            ..Default::default()
167        };
168        v00.Anonymous.iVal = value;
169        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
170        variant
171    }
172
173    fn variant_into(&self) -> core::Result<i16> {
174        unsafe {
175            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
176            let mut new = VARIANT::default();
177            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I2)?;
178            let v00 = &new.Anonymous.Anonymous;
179            let n = v00.Anonymous.iVal;
180            VariantClear(&mut new)?;
181            Ok(n)
182        }
183    }
184}
185
186impl VariantTypeExt<'_, i32> for VARIANT {
187    fn variant_from(value: i32) -> VARIANT {
188        let mut variant = VARIANT::default();
189        let mut v00 = VARIANT_0_0 {
190            vt: VT_I4,
191            ..Default::default()
192        };
193        v00.Anonymous.lVal = value;
194        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
195        variant
196    }
197
198    fn variant_into(&self) -> core::Result<i32> {
199        unsafe {
200            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
201            let mut new = VARIANT::default();
202            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I4)?;
203            let v00 = &new.Anonymous.Anonymous;
204            let n = v00.Anonymous.lVal;
205            VariantClear(&mut new)?;
206            Ok(n)
207        }
208    }
209}
210
211impl VariantTypeExt<'_, i64> for VARIANT {
212    fn variant_from(value: i64) -> VARIANT {
213        let mut variant = VARIANT::default();
214        let mut v00 = VARIANT_0_0 {
215            vt: VT_I8,
216            ..Default::default()
217        };
218        v00.Anonymous.llVal = value;
219        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
220        variant
221    }
222
223    fn variant_into(&self) -> core::Result<i64> {
224        unsafe {
225            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
226            let mut new = VARIANT::default();
227            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I8)?;
228            let v00 = &new.Anonymous.Anonymous;
229            let n = v00.Anonymous.llVal;
230            VariantClear(&mut new)?;
231            Ok(n)
232        }
233    }
234}
235
236impl VariantTypeExt<'_, u8> for VARIANT {
237    fn variant_from(value: u8) -> VARIANT {
238        let mut variant = VARIANT::default();
239        let mut v00 = VARIANT_0_0 {
240            vt: VT_UI1,
241            ..Default::default()
242        };
243        v00.Anonymous.bVal = value;
244        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
245        variant
246    }
247
248    fn variant_into(&self) -> core::Result<u8> {
249        unsafe {
250            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
251            let mut new = VARIANT::default();
252            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI1)?;
253            let v00 = &new.Anonymous.Anonymous;
254            let n = v00.Anonymous.bVal;
255            VariantClear(&mut new)?;
256            Ok(n)
257        }
258    }
259}
260
261impl VariantTypeExt<'_, u16> for VARIANT {
262    fn variant_from(value: u16) -> VARIANT {
263        let mut variant = VARIANT::default();
264        let mut v00 = VARIANT_0_0 {
265            vt: VT_UI2,
266            ..Default::default()
267        };
268        v00.Anonymous.uiVal = value;
269        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
270        variant
271    }
272
273    fn variant_into(&self) -> core::Result<u16> {
274        unsafe {
275            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
276            let mut new = VARIANT::default();
277            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI2)?;
278            let v00 = &new.Anonymous.Anonymous;
279            let n = v00.Anonymous.uiVal;
280            VariantClear(&mut new)?;
281            Ok(n)
282        }
283    }
284}
285
286impl VariantTypeExt<'_, u32> for VARIANT {
287    fn variant_from(value: u32) -> VARIANT {
288        let mut variant = VARIANT::default();
289        let mut v00 = VARIANT_0_0 {
290            vt: VT_UI4,
291            ..Default::default()
292        };
293        v00.Anonymous.ulVal = value;
294        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
295        variant
296    }
297
298    fn variant_into(&self) -> core::Result<u32> {
299        unsafe {
300            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
301            let mut new = VARIANT::default();
302            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI4)?;
303            let v00 = &new.Anonymous.Anonymous;
304            let n = v00.Anonymous.ulVal;
305            VariantClear(&mut new)?;
306            Ok(n)
307        }
308    }
309}
310
311impl VariantTypeExt<'_, u64> for VARIANT {
312    fn variant_from(value: u64) -> VARIANT {
313        let mut variant = VARIANT::default();
314        let mut v00 = VARIANT_0_0 {
315            vt: VT_UI8,
316            ..Default::default()
317        };
318        v00.Anonymous.ullVal = value;
319        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
320        variant
321    }
322
323    fn variant_into(&self) -> core::Result<u64> {
324        unsafe {
325            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
326            let mut new = VARIANT::default();
327            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI8)?;
328            let v00 = &new.Anonymous.Anonymous;
329            let n = v00.Anonymous.ullVal;
330            VariantClear(&mut new)?;
331            Ok(n)
332        }
333    }
334}
335
336impl VariantTypeExt<'_, String> for VARIANT {
337    fn variant_from(value: String) -> VARIANT {
338        let mut variant = VARIANT::default();
339        let mut v00 = VARIANT_0_0 {
340            vt: VT_BSTR,
341            ..Default::default()
342        };
343        let bstr = BSTR::from(&value);
344        v00.Anonymous.bstrVal = ManuallyDrop::new(bstr);
345        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
346        variant
347    }
348
349    fn variant_into(&self) -> core::Result<String> {
350        unsafe {
351            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
352            let mut new = VARIANT::default();
353            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_BSTR)?;
354            let v00 = &new.Anonymous.Anonymous;
355            let str = v00.Anonymous.bstrVal.to_string();
356            VariantClear(&mut new)?;
357            Ok(str)
358        }
359    }
360}
361
362impl VariantTypeExt<'_, bool> for VARIANT {
363    fn variant_from(value: bool) -> VARIANT {
364        let mut variant = VARIANT::default();
365        let mut v00 = VARIANT_0_0 {
366            vt: VT_BOOL,
367            ..Default::default()
368        };
369        v00.Anonymous.boolVal = VARIANT_BOOL::from(value);
370        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
371        variant
372    }
373
374    fn variant_into(&self) -> core::Result<bool> {
375        unsafe {
376            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
377            let mut new = VARIANT::default();
378            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_BOOL)?;
379            let v00 = &new.Anonymous.Anonymous;
380            let b = v00.Anonymous.boolVal.as_bool();
381            VariantClear(&mut new)?;
382            Ok(b)
383        }
384    }
385}
386
387impl<'a> VariantTypeExt<'a, &'a IDispatch> for VARIANT {
388    fn variant_from(value: &'a IDispatch) -> VARIANT {
389        let mut variant = VARIANT::default();
390        let mut v00 = VARIANT_0_0 {
391            vt: VT_DISPATCH,
392            ..Default::default()
393        };
394        v00.Anonymous.pdispVal = ManuallyDrop::new(Some(value.clone()));
395        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
396        variant
397    }
398
399    fn variant_into(&'a self) -> core::Result<&'a IDispatch> {
400        unsafe {
401            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
402            let v00 = &self.Anonymous.Anonymous;
403            let idisp = v00.Anonymous.pdispVal.as_ref().ok_or(core::Error::new(
404                core::HRESULT(0x00123456),
405                core::HSTRING::from("com-shim: Cannot read IDispatch"),
406            ))?;
407            Ok(idisp)
408        }
409    }
410}