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
28pub trait HasIDispatch<T = Self> {
30 fn get_idispatch(&self) -> &IDispatch;
32}
33
34pub trait IDispatchExt {
36 fn call<S>(&self, name: S, args: Vec<VARIANT>) -> Result<VARIANT>
38 where
39 S: AsRef<str>;
40
41 fn get<S>(&self, name: S) -> Result<VARIANT>
43 where
44 S: AsRef<str>;
45
46 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
118pub trait VariantExt {
120 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
136pub trait IsA<T> {
138 fn upcast(&self) -> T;
140}
141
142pub trait VariantTypeExt<'a, T> {
144 fn variant_into(&'a self) -> core::Result<T>;
146
147 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}