1 | use super::*; |
2 | use core::ffi::c_void; |
3 | use core::ptr::NonNull; |
4 | |
5 | /// Base interface for all COM interfaces. |
6 | /// |
7 | /// All COM interfaces (and thus WinRT classes and interfaces) implement |
8 | /// [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown) |
9 | /// under the hood to provide reference-counted lifetime management as well as the ability |
10 | /// to query for additional interfaces that the object may implement. |
11 | #[repr (transparent)] |
12 | pub struct IUnknown(NonNull<c_void>); |
13 | |
14 | #[doc (hidden)] |
15 | #[repr (C)] |
16 | #[allow (non_camel_case_types)] |
17 | pub struct IUnknown_Vtbl { |
18 | pub QueryInterface: unsafe extern "system" fn( |
19 | this: *mut c_void, |
20 | iid: *const GUID, |
21 | interface: *mut *mut c_void, |
22 | ) -> HRESULT, |
23 | pub AddRef: unsafe extern "system" fn(this: *mut c_void) -> u32, |
24 | pub Release: unsafe extern "system" fn(this: *mut c_void) -> u32, |
25 | } |
26 | |
27 | unsafe impl Interface for IUnknown { |
28 | type Vtable = IUnknown_Vtbl; |
29 | const IID: GUID = GUID::from_u128(uuid:0x00000000_0000_0000_c000_000000000046); |
30 | } |
31 | |
32 | impl Clone for IUnknown { |
33 | fn clone(&self) -> Self { |
34 | unsafe { |
35 | (self.vtable().AddRef)(core::mem::transmute_copy(self)); |
36 | } |
37 | |
38 | Self(self.0) |
39 | } |
40 | } |
41 | |
42 | impl Drop for IUnknown { |
43 | fn drop(&mut self) { |
44 | unsafe { |
45 | (self.vtable().Release)(core::mem::transmute_copy(self)); |
46 | } |
47 | } |
48 | } |
49 | |
50 | impl PartialEq for IUnknown { |
51 | fn eq(&self, other: &Self) -> bool { |
52 | // First we test for ordinary pointer equality. If two COM interface pointers have the |
53 | // same pointer value, then they are the same object. This can save us a lot of time, |
54 | // since calling QueryInterface is much more expensive than a single pointer comparison. |
55 | // |
56 | // However, interface pointers may have different values and yet point to the same object. |
57 | // Since COM objects may implement multiple interfaces, COM identity can only |
58 | // be determined by querying for `IUnknown` explicitly and then comparing the |
59 | // pointer values. This works since `QueryInterface` is required to return |
60 | // the same pointer value for queries for `IUnknown`. |
61 | self.as_raw() == other.as_raw() |
62 | || self.cast::<IUnknown>().unwrap().0 == other.cast::<IUnknown>().unwrap().0 |
63 | } |
64 | } |
65 | |
66 | impl Eq for IUnknown {} |
67 | |
68 | impl core::fmt::Debug for IUnknown { |
69 | fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
70 | f.debug_tuple(name:"IUnknown" ).field(&self.as_raw()).finish() |
71 | } |
72 | } |
73 | |
74 | /// The `#[implement]` macro generates implementations of this trait for the types |
75 | /// that it generates, e.g. `MyApp_Impl`, |
76 | /// |
77 | /// `ComObject` uses this trait to interact with boxed COM objects. |
78 | #[doc (hidden)] |
79 | pub trait IUnknownImpl { |
80 | /// The contained user type, e.g. `MyApp`. Also known as the "inner" type. |
81 | type Impl; |
82 | |
83 | /// Get a reference to the backing implementation. |
84 | fn get_impl(&self) -> &Self::Impl; |
85 | |
86 | /// Get a mutable reference to the contained (inner) object. |
87 | fn get_impl_mut(&mut self) -> &mut Self::Impl; |
88 | |
89 | /// Consumes the box and returns the contained (inner) object. This is the opposite of `new_box`. |
90 | fn into_inner(self) -> Self::Impl; |
91 | |
92 | /// The classic `QueryInterface` method from COM. |
93 | /// |
94 | /// # Safety |
95 | /// |
96 | /// This function is safe to call as long as the interface pointer is non-null and valid for writes |
97 | /// of an interface pointer. |
98 | unsafe fn QueryInterface(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT; |
99 | |
100 | /// Increments the reference count of the interface |
101 | fn AddRef(&self) -> u32; |
102 | |
103 | /// Decrements the reference count causing the interface's memory to be freed when the count is 0 |
104 | /// |
105 | /// # Safety |
106 | /// |
107 | /// This function should only be called when the interface pointer is no longer used as calling `Release` |
108 | /// on a non-aliased interface pointer and then using that interface pointer may result in use after free. |
109 | /// |
110 | /// This function takes `*mut Self` because the object may be freed by the time this method returns. |
111 | /// Taking `&self` would violate Rust's rules on reference lifetime. |
112 | unsafe fn Release(self_: *mut Self) -> u32; |
113 | |
114 | /// Returns `true` if the reference count of the box is equal to 1. |
115 | fn is_reference_count_one(&self) -> bool; |
116 | |
117 | /// Gets the trust level of the current object. |
118 | unsafe fn GetTrustLevel(&self, value: *mut i32) -> HRESULT; |
119 | |
120 | /// Gets a borrowed reference to an interface that is implemented by this ComObject. |
121 | /// |
122 | /// The returned reference does not have an additional reference count. |
123 | /// You can AddRef it by calling to_owned(). |
124 | #[inline (always)] |
125 | fn as_interface<I: Interface>(&self) -> InterfaceRef<'_, I> |
126 | where |
127 | Self: ComObjectInterface<I>, |
128 | { |
129 | <Self as ComObjectInterface<I>>::as_interface_ref(self) |
130 | } |
131 | |
132 | /// Gets an owned (counted) reference to an interface that is implemented by this ComObject. |
133 | #[inline (always)] |
134 | fn to_interface<I: Interface>(&self) -> I |
135 | where |
136 | Self: ComObjectInterface<I>, |
137 | { |
138 | <Self as ComObjectInterface<I>>::as_interface_ref(self).to_owned() |
139 | } |
140 | |
141 | /// Creates a new owned reference to this object. |
142 | /// |
143 | /// # Safety |
144 | /// |
145 | /// This function can only be safely called by `<Foo>_Impl` objects that are embedded in a |
146 | /// `ComObject`. Since we only allow safe Rust code to access these objects using a `ComObject` |
147 | /// or a `&<Foo>_Impl` that points within a `ComObject`, this is safe. |
148 | fn to_object(&self) -> ComObject<Self::Impl> |
149 | where |
150 | Self::Impl: ComObjectInner<Outer = Self>; |
151 | } |
152 | |
153 | impl IUnknown_Vtbl { |
154 | pub const fn new<T: IUnknownImpl, const OFFSET: isize>() -> Self { |
155 | unsafe extern "system" fn QueryInterface<T: IUnknownImpl, const OFFSET: isize>( |
156 | this: *mut c_void, |
157 | iid: *const GUID, |
158 | interface: *mut *mut c_void, |
159 | ) -> HRESULT { |
160 | unsafe { |
161 | let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; |
162 | (*this).QueryInterface(iid, interface) |
163 | } |
164 | } |
165 | unsafe extern "system" fn AddRef<T: IUnknownImpl, const OFFSET: isize>( |
166 | this: *mut c_void, |
167 | ) -> u32 { |
168 | unsafe { |
169 | let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; |
170 | (*this).AddRef() |
171 | } |
172 | } |
173 | unsafe extern "system" fn Release<T: IUnknownImpl, const OFFSET: isize>( |
174 | this: *mut c_void, |
175 | ) -> u32 { |
176 | unsafe { |
177 | let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T; |
178 | T::Release(this) |
179 | } |
180 | } |
181 | Self { |
182 | QueryInterface: QueryInterface::<T, OFFSET>, |
183 | AddRef: AddRef::<T, OFFSET>, |
184 | Release: Release::<T, OFFSET>, |
185 | } |
186 | } |
187 | } |
188 | |