rs_dispatch/com/
com_module.rs1#![allow(dead_code)]
2
3use anyhow::{anyhow, Context};
4use std::env;
5use windows::core::*;
6use windows::Win32::System::Com::*;
7use windows::Win32::System::Ole::*;
8
9const LOCALE_USER_DEFAULT: u32 = 0x0400;
10const LOCALE_SYSTEM_DEFAULT: u32 = 0x0800;
11
12pub struct Variant(VARIANT);
13
14impl From<bool> for Variant {
15 fn from(value: bool) -> Self {
16 Self(value.into())
17 }
18}
19
20impl From<i32> for Variant {
21 fn from(value: i32) -> Self {
22 Self(value.into())
23 }
24}
25
26impl From<i64> for Variant {
27 fn from(value: i64) -> Self {
28 Self(value.into())
29 }
30}
31
32impl From<f64> for Variant {
33 fn from(value: f64) -> Self {
34 Self(value.into())
35 }
36}
37
38impl From<&str> for Variant {
39 fn from(value: &str) -> Self {
40 Self(BSTR::from(value).into())
41 }
42}
43
44impl From<&String> for Variant {
45 fn from(value: &String) -> Self {
46 Self(BSTR::from(value).into())
47 }
48}
49
50impl Variant {
51 pub fn bool(&self) -> anyhow::Result<bool> {
52 Ok(bool::try_from(&self.0)?)
53 }
54
55 pub fn int(&self) -> anyhow::Result<i32> {
56 Ok(i32::try_from(&self.0)?)
57 }
58 pub fn long(&self) -> anyhow::Result<i64> {
59 Ok(i64::try_from(&self.0)?)
60 }
61 pub fn float(&self) -> anyhow::Result<f64> {
62 Ok(f64::try_from(&self.0)?)
63 }
64
65 pub fn string(&self) -> anyhow::Result<String> {
66 Ok(BSTR::try_from(&self.0)?.to_string())
67 }
68
69 pub fn idispatch(&self) -> anyhow::Result<IDispatchW> {
70 Ok(IDispatchW(IDispatch::try_from(&self.0)?))
71 }
72
73 pub fn vt(&self) -> u16 {
74 unsafe { self.0.as_raw().Anonymous.Anonymous.vt }
75 }
76}
77pub struct IDispatchW(pub IDispatch);
81impl IDispatchW {
82 pub fn invoke(
87 &self,
88 flags: DISPATCH_FLAGS,
89 name: &str,
90 mut args: Vec<Variant>,
91 ) -> anyhow::Result<Variant> {
92 unsafe {
93 let mut dispatch_id = 0;
94 self.0
95 .GetIDsOfNames(
96 &GUID::default(),
97 &PCWSTR::from_raw(HSTRING::from(name).as_ptr()),
98 1,
99 LOCALE_USER_DEFAULT,
100 &mut dispatch_id,
101 ).with_context(|| "GetIDsOfNames Failiure!")?;
102 let mut dispatch_param = DISPPARAMS::default();
103 let mut dispatch_named = DISPID_PROPERTYPUT;
104 if !args.is_empty() {
105 args.reverse();
106 dispatch_param.cArgs = args.len() as u32;
107 dispatch_param.rgvarg = args.as_mut_ptr() as *mut VARIANT;
108 if (flags & DISPATCH_PROPERTYPUT) != DISPATCH_FLAGS(0) {
109 dispatch_param.cNamedArgs = 1;
110 dispatch_param.rgdispidNamedArgs = &mut dispatch_named;
111 }
112 }
113 let mut result = VARIANT::default();
114 self.0
115 .Invoke(
116 dispatch_id,
117 &GUID::default(),
118 LOCALE_SYSTEM_DEFAULT,
119 flags,
120 &dispatch_param,
121 Some(&mut result),
122 None,
123 None,
124 ).with_context(|| "Invokation Failure!")?;
125 Ok(Variant(result))
126 }
127 }
128
129 pub fn get(&self, name: &str,args:Vec<Variant>) -> anyhow::Result<Variant> {
130 self.invoke(DISPATCH_PROPERTYGET, name, args)
131 }
132
133 pub fn int(&self, name: &str,args:Vec<Variant>) -> anyhow::Result<i32> {
134 let result = self.get(name,args)?;
135 result.int()
136 }
137
138 pub fn bool(&self, name: &str,args:Vec<Variant>) -> anyhow::Result<bool> {
139 let result = self.get(name,args)?;
140 result.bool()
141 }
142 pub fn float(&self, name: &str,args:Vec<Variant>) -> anyhow::Result<f64> {
143 let result = self.get(name,args)?;
144 result.float()
145 }
146
147 pub fn string(&self, name: &str,args:Vec<Variant>) -> anyhow::Result<String> {
148 let result = self.get(name,args)?;
149 result.string()
150 }
151
152 pub fn put(&self, name: &str, args: Vec<Variant>) -> anyhow::Result<Variant> {
153 self.invoke(DISPATCH_PROPERTYPUT, name, args)
154 }
155
156 pub fn call(&self, name: &str, args: Vec<Variant>) -> anyhow::Result<Variant> {
157 self.invoke(DISPATCH_METHOD, name, args)
158 }
159}
160
161pub struct DeferCoUninitialize;
164impl Drop for DeferCoUninitialize {
165 fn drop(&mut self) {
166 unsafe {
167 CoUninitialize();
168 }
169 }
170}
171pub struct RSCom {
175 pub api: IDispatchW,
176}
177
178impl RSCom {
179 pub fn init(com_name:&str) -> anyhow::Result<RSCom> {
182 let mut args = env::args();
183 let _ = args.next();
184 unsafe {
185 let res = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
188 if res.is_err() {
189 return Err(anyhow!("error: {}", res.message()));
190 }
191 let clsid = CLSIDFromProgID(PCWSTR::from_raw(
194 HSTRING::from(com_name).as_ptr(),
195 ))
196 .with_context(|| "wrong clsid of api")?;
197 println!("printing api id {:?}", clsid);
198 let _api_dispatch = CoCreateInstance(&clsid, None, CLSCTX_LOCAL_SERVER)
200 .with_context(|| "CoCreateInstance of api")?;
201 let api_dispatch = IDispatchW(_api_dispatch);
203 Ok(RSCom { api: api_dispatch })
204 }
205 }
206 pub fn close_api(&self) -> () {
208 unsafe { CoUninitialize() }
209 }
210}
211unsafe impl Send for RSCom {}