]>
Commit | Line | Data |
---|---|---|
353b0b11 FG |
1 | use super::*; |
2 | use imp::IWeakReferenceSource; | |
3 | ||
4 | /// Provides low-level access to a COM interface. | |
5 | /// | |
6 | /// This trait is automatically implemented by the generated bindings and should not be | |
7 | /// implemented manually. | |
8 | /// | |
9 | /// # Safety | |
10 | /// | |
11 | /// It is only safe to implement this trait if the implementing type is a valid COM interface pointer meaning | |
12 | /// the following criteria are met: | |
13 | /// * its in-memory representation is equal to `NonNull<NonNull<Self::VTable>>` | |
14 | /// * the vtable is correctly structured beginning with the `IUnknown` function pointers | |
15 | /// * the vtable must be the correct vtable for the supplied IID | |
16 | pub unsafe trait ComInterface: Interface + Clone { | |
17 | /// A unique identifier representing this interface. | |
18 | const IID: GUID; | |
19 | ||
20 | /// Attempts to cast the current interface to another interface using `QueryInterface`. | |
21 | /// | |
22 | /// The name `cast` is preferred to `query` because there is a WinRT method named query but not one | |
23 | /// named cast. | |
24 | fn cast<T: ComInterface>(&self) -> Result<T> { | |
25 | let mut result = None; | |
26 | // SAFETY: `result` is valid for writing an interface pointer and it is safe | |
27 | // to cast the `result` pointer as `T` on success because we are using the `IID` tied | |
28 | // to `T` which the implementor of `ComInterface` has guaranteed is correct | |
29 | unsafe { self.query(&T::IID, &mut result as *mut _ as _).and_some(result) } | |
30 | } | |
31 | ||
32 | /// Attempts to create a [`Weak`] reference to this object. | |
33 | fn downgrade(&self) -> Result<Weak<Self>> { | |
34 | self.cast::<IWeakReferenceSource>().and_then(|source| Weak::downgrade(&source)) | |
35 | } | |
36 | ||
37 | /// Call `QueryInterface` on this interface | |
38 | /// | |
39 | /// # SAFETY | |
40 | /// | |
41 | /// `interface` must be a non-null, valid pointer for writing an interface pointer | |
42 | #[doc(hidden)] | |
43 | unsafe fn query(&self, iid: &GUID, interface: *mut *const std::ffi::c_void) -> HRESULT { | |
44 | (self.assume_vtable::<IUnknown>().QueryInterface)(self.as_raw(), iid, interface) | |
45 | } | |
46 | } |