1use log::trace;
2use std::ptr;
3use winapi::{
4 shared::{guiddef::GUID, minwindef::LPVOID, winerror::NOERROR, wtypesbase::CLSCTX},
5 um::{combaseapi::CoCreateInstance, oaidl::LPDISPATCH, unknwnbase::LPUNKNOWN},
6};
7
8use super::guids::{IID_IDISPATCH, IID_IUNKNOWN};
9use super::{dispatch::DispatchInterface, Error};
10
11pub struct UnknownInterface {
15 unknown: LPUNKNOWN,
16 released: bool,
17}
18
19impl UnknownInterface {
20 pub fn new(class_id: GUID, class_context: CLSCTX) -> Result<UnknownInterface, Error> {
23 let mut unknown: LPVOID = ptr::null_mut();
24 let result = unsafe {
25 CoCreateInstance(
26 &class_id,
27 ptr::null_mut(),
28 class_context,
29 &IID_IUNKNOWN,
30 &mut unknown,
31 )
32 };
33 if result != NOERROR {
34 Err(result.into())
35 } else {
36 Ok(UnknownInterface {
37 unknown: unknown as LPUNKNOWN,
38 released: false,
39 })
40 }
41 }
42 pub fn get_dispatch_interface(&self) -> Result<DispatchInterface, Error> {
45 let mut dispatch: LPVOID = ptr::null_mut();
46 let result = unsafe {
47 if let Some(r) = self.unknown.as_ref() {
48 r.QueryInterface(&IID_IDISPATCH, &mut dispatch)
49 } else {
50 return Err(Error::NullUnknownPointer);
51 }
52 };
53 if result != NOERROR {
54 Err(result.into())
55 } else {
56 Ok(DispatchInterface::new(dispatch as LPDISPATCH))
57 }
58 }
59
60 fn release(&mut self) {
61 if self.released {
62 return;
63 }
64 unsafe {
65 if let Some(r) = self.unknown.as_ref() {
66 r.Release();
67 self.released = true;
68 self.unknown = ptr::null_mut();
69 }
70 }
71 }
72}
73
74impl Drop for UnknownInterface {
75 fn drop(&mut self) {
76 trace!("dropping unknown interface");
77 self.release();
78 }
79}