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, 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
119pub trait VariantExt {
121 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
137pub trait IsA<T> {
139 fn upcast(&self) -> T;
141}
142
143pub trait VariantTypeExt<'a, T> {
145 fn variant_into(&'a self) -> core::Result<T>;
147
148 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}