1 use crate::*;
2 
3 /// All COM interfaces (and thus WinRT classes and interfaces) implement
4 /// [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown)
5 /// under the hood to provide reference-counted lifetime management as well as the ability
6 /// to query for additional interfaces that the object may implement.
7 #[repr(transparent)]
8 pub struct IUnknown(std::ptr::NonNull<std::ffi::c_void>);
9 
10 #[repr(C)]
11 pub struct IUnknown_vtable(
12     pub unsafe extern "system" fn(this: RawPtr, iid: &Guid, interface: *mut RawPtr) -> HRESULT,
13     pub unsafe extern "system" fn(this: RawPtr) -> u32,
14     pub unsafe extern "system" fn(this: RawPtr) -> u32,
15 );
16 
17 unsafe impl Interface for IUnknown {
18     type Vtable = IUnknown_vtable;
19 
20     const IID: Guid = Guid::from_values(
21         0x0000_0000,
22         0x0000,
23         0x0000,
24         [0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46],
25     );
26 }
27 
28 impl Clone for IUnknown {
clone(&self) -> Self29     fn clone(&self) -> Self {
30         unsafe {
31             (self.vtable().1)(self.abi()); // AddRef
32         }
33 
34         Self(self.0)
35     }
36 }
37 
38 impl Drop for IUnknown {
drop(&mut self)39     fn drop(&mut self) {
40         unsafe {
41             (self.vtable().2)(self.abi()); // Release
42         }
43     }
44 }
45 
46 impl PartialEq for IUnknown {
eq(&self, other: &Self) -> bool47     fn eq(&self, other: &Self) -> bool {
48         // Since COM objects may implement multiple intefaces, COM identity can only
49         // be determined by querying for `IUnknown` explicitly and then comparing the
50         // pointer values. This works since `QueryInterface` is required to return
51         // the same pointer value for queries for `IUnknown`.
52         self.cast::<IUnknown>().unwrap().0 == other.cast::<IUnknown>().unwrap().0
53     }
54 }
55 
56 impl Eq for IUnknown {}
57 
58 impl std::fmt::Debug for IUnknown {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result59     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60         write!(f, "{:?}", self.0)
61     }
62 }
63