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, mut 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(&mut 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        let mut args = vec![value];
103        unsafe {
104            self.Invoke(
105                utils::get_method_dispid(self, name)?,
106                &iid_null,
107                0,
108                DISPATCH_PROPERTYPUT,
109                &utils::assemble_dispparams_put(&mut args),
110                Some(&mut result),
111                None,
112                None,
113            )?;
114        }
115        Ok(result)
116    }
117}
118
119/// Extension functions for a [`VARIANT`].
120pub trait VariantExt {
121    /// Generate a null [`VARIANT`].
122    fn null() -> VARIANT;
123}
124
125impl VariantExt for VARIANT {
126    fn null() -> VARIANT {
127        let mut variant = VARIANT::default();
128        let v00 = VARIANT_0_0 {
129            vt: VT_NULL,
130            ..Default::default()
131        };
132        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
133        variant
134    }
135}
136
137/// Indicates that this type is also a parent type and can be upcast to it.
138pub trait IsA<T> {
139    /// Upcast this value to it's parent type.
140    fn upcast(&self) -> T;
141}
142
143/// Functions to convert to and from a type that can be stored in a [`VARIANT`].
144pub trait VariantTypeExt<'a, T> {
145    /// Convert from a [`VARIANT`] into a type, T.
146    fn variant_into(&'a self) -> core::Result<T>;
147
148    /// Convert from a type T into a [`VARIANT`].
149    fn variant_from(value: T) -> VARIANT;
150}
151
152impl VariantTypeExt<'_, ()> for VARIANT {
153    fn variant_from(_value: ()) -> VARIANT {
154        VARIANT::null()
155    }
156
157    fn variant_into(&'_ self) -> core::Result<()> {
158        Ok(())
159    }
160}
161
162impl VariantTypeExt<'_, i16> for VARIANT {
163    fn variant_from(value: i16) -> VARIANT {
164        let mut variant = VARIANT::default();
165        let mut v00 = VARIANT_0_0 {
166            vt: VT_I2,
167            ..Default::default()
168        };
169        v00.Anonymous.iVal = value;
170        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
171        variant
172    }
173
174    fn variant_into(&self) -> core::Result<i16> {
175        unsafe {
176            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
177            let mut new = VARIANT::default();
178            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I2)?;
179            let v00 = &new.Anonymous.Anonymous;
180            let n = v00.Anonymous.iVal;
181            VariantClear(&mut new)?;
182            Ok(n)
183        }
184    }
185}
186
187impl VariantTypeExt<'_, i32> for VARIANT {
188    fn variant_from(value: i32) -> VARIANT {
189        let mut variant = VARIANT::default();
190        let mut v00 = VARIANT_0_0 {
191            vt: VT_I4,
192            ..Default::default()
193        };
194        v00.Anonymous.lVal = value;
195        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
196        variant
197    }
198
199    fn variant_into(&self) -> core::Result<i32> {
200        unsafe {
201            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
202            let mut new = VARIANT::default();
203            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I4)?;
204            let v00 = &new.Anonymous.Anonymous;
205            let n = v00.Anonymous.lVal;
206            VariantClear(&mut new)?;
207            Ok(n)
208        }
209    }
210}
211
212impl VariantTypeExt<'_, i64> for VARIANT {
213    fn variant_from(value: i64) -> VARIANT {
214        let mut variant = VARIANT::default();
215        let mut v00 = VARIANT_0_0 {
216            vt: VT_I8,
217            ..Default::default()
218        };
219        v00.Anonymous.llVal = value;
220        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
221        variant
222    }
223
224    fn variant_into(&self) -> core::Result<i64> {
225        unsafe {
226            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
227            let mut new = VARIANT::default();
228            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_I8)?;
229            let v00 = &new.Anonymous.Anonymous;
230            let n = v00.Anonymous.llVal;
231            VariantClear(&mut new)?;
232            Ok(n)
233        }
234    }
235}
236
237impl VariantTypeExt<'_, u8> for VARIANT {
238    fn variant_from(value: u8) -> VARIANT {
239        let mut variant = VARIANT::default();
240        let mut v00 = VARIANT_0_0 {
241            vt: VT_UI1,
242            ..Default::default()
243        };
244        v00.Anonymous.bVal = value;
245        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
246        variant
247    }
248
249    fn variant_into(&self) -> core::Result<u8> {
250        unsafe {
251            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
252            let mut new = VARIANT::default();
253            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI1)?;
254            let v00 = &new.Anonymous.Anonymous;
255            let n = v00.Anonymous.bVal;
256            VariantClear(&mut new)?;
257            Ok(n)
258        }
259    }
260}
261
262impl VariantTypeExt<'_, u16> for VARIANT {
263    fn variant_from(value: u16) -> VARIANT {
264        let mut variant = VARIANT::default();
265        let mut v00 = VARIANT_0_0 {
266            vt: VT_UI2,
267            ..Default::default()
268        };
269        v00.Anonymous.uiVal = value;
270        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
271        variant
272    }
273
274    fn variant_into(&self) -> core::Result<u16> {
275        unsafe {
276            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
277            let mut new = VARIANT::default();
278            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI2)?;
279            let v00 = &new.Anonymous.Anonymous;
280            let n = v00.Anonymous.uiVal;
281            VariantClear(&mut new)?;
282            Ok(n)
283        }
284    }
285}
286
287impl VariantTypeExt<'_, u32> for VARIANT {
288    fn variant_from(value: u32) -> VARIANT {
289        let mut variant = VARIANT::default();
290        let mut v00 = VARIANT_0_0 {
291            vt: VT_UI4,
292            ..Default::default()
293        };
294        v00.Anonymous.ulVal = value;
295        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
296        variant
297    }
298
299    fn variant_into(&self) -> core::Result<u32> {
300        unsafe {
301            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
302            let mut new = VARIANT::default();
303            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI4)?;
304            let v00 = &new.Anonymous.Anonymous;
305            let n = v00.Anonymous.ulVal;
306            VariantClear(&mut new)?;
307            Ok(n)
308        }
309    }
310}
311
312impl VariantTypeExt<'_, u64> for VARIANT {
313    fn variant_from(value: u64) -> VARIANT {
314        let mut variant = VARIANT::default();
315        let mut v00 = VARIANT_0_0 {
316            vt: VT_UI8,
317            ..Default::default()
318        };
319        v00.Anonymous.ullVal = value;
320        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
321        variant
322    }
323
324    fn variant_into(&self) -> core::Result<u64> {
325        unsafe {
326            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
327            let mut new = VARIANT::default();
328            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_UI8)?;
329            let v00 = &new.Anonymous.Anonymous;
330            let n = v00.Anonymous.ullVal;
331            VariantClear(&mut new)?;
332            Ok(n)
333        }
334    }
335}
336
337impl VariantTypeExt<'_, String> for VARIANT {
338    fn variant_from(value: String) -> VARIANT {
339        let mut variant = VARIANT::default();
340        let mut v00 = VARIANT_0_0 {
341            vt: VT_BSTR,
342            ..Default::default()
343        };
344        let bstr = BSTR::from(&value);
345        v00.Anonymous.bstrVal = ManuallyDrop::new(bstr);
346        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
347        variant
348    }
349
350    fn variant_into(&self) -> core::Result<String> {
351        unsafe {
352            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
353            let mut new = VARIANT::default();
354            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_BSTR)?;
355            let v00 = &new.Anonymous.Anonymous;
356            let str = v00.Anonymous.bstrVal.to_string();
357            VariantClear(&mut new)?;
358            Ok(str)
359        }
360    }
361}
362
363impl VariantTypeExt<'_, bool> for VARIANT {
364    fn variant_from(value: bool) -> VARIANT {
365        let mut variant = VARIANT::default();
366        let mut v00 = VARIANT_0_0 {
367            vt: VT_BOOL,
368            ..Default::default()
369        };
370        v00.Anonymous.boolVal = VARIANT_BOOL::from(value);
371        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
372        variant
373    }
374
375    fn variant_into(&self) -> core::Result<bool> {
376        unsafe {
377            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
378            let mut new = VARIANT::default();
379            VariantChangeType(&mut new, self, VAR_CHANGE_FLAGS(0), VT_BOOL)?;
380            let v00 = &new.Anonymous.Anonymous;
381            let b = v00.Anonymous.boolVal.as_bool();
382            VariantClear(&mut new)?;
383            Ok(b)
384        }
385    }
386}
387
388impl<'a> VariantTypeExt<'a, &'a IDispatch> for VARIANT {
389    fn variant_from(value: &'a IDispatch) -> VARIANT {
390        let mut variant = VARIANT::default();
391        let mut v00 = VARIANT_0_0 {
392            vt: VT_DISPATCH,
393            ..Default::default()
394        };
395        v00.Anonymous.pdispVal = ManuallyDrop::new(Some(value.clone()));
396        variant.Anonymous.Anonymous = ManuallyDrop::new(v00);
397        variant
398    }
399
400    fn variant_into(&'a self) -> core::Result<&'a IDispatch> {
401        unsafe {
402            tracing::debug!("Own type: {:?}", self.Anonymous.Anonymous.vt);
403            let v00 = &self.Anonymous.Anonymous;
404            let idisp = v00.Anonymous.pdispVal.as_ref().ok_or(core::Error::new(
405                core::HRESULT(0x00123456),
406                core::HSTRING::from("com-shim: Cannot read IDispatch"),
407            ))?;
408            Ok(idisp)
409        }
410    }
411}