com/interfaces/
iunknown.rs

1//! Everything related to the [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown) COM interface
2
3use crate::sys::{E_NOINTERFACE, E_POINTER, FAILED};
4use crate::sys::{GUID, HRESULT};
5use crate::{interfaces, Interface, IID};
6
7use core::ffi::c_void;
8
9interfaces! {
10    /// [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown) COM interface
11    #[uuid("00000000-0000-0000-C000-000000000046")]
12    pub unsafe interface IUnknown {
13        /// The COM [`QueryInterface` Method]
14        ///
15        /// This method normally should not be called directly. Interfaces that implement
16        /// `IUnknown` also implement [`IUnknown::query_interface`] which is a safe wrapper around
17        /// `IUnknown::QueryInterface`.
18        ///
19        /// [`QueryInterface` Method]: https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(refiid_void)
20        /// [`IUnknown::query_interface`]: trait.IUnknown.html#method.query_interface
21        pub unsafe fn QueryInterface(&self, riid: *const GUID, ppv: *mut *mut c_void) -> HRESULT;
22
23        /// The COM [`AddRef` Method]
24        ///
25        /// This method normally should not be called directly. This method is used by
26        /// the `Clone` implementation of interfaces to implement the reference counting mechanism.
27        ///
28        /// [`AddRef` Method]: https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-addref
29        pub unsafe fn AddRef(&self) -> u32;
30
31        /// The COM [`Release` Method]
32        ///
33        /// This method normally should not be called directly. This method is used by
34        /// the `Drop` implementation of interfaces to implement the reference counting mechanism.
35        ///
36        /// [`Release` Method]: https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nf-unknwn-iunknown-release
37        /// [`ComPtr`]: struct.ComPtr.html
38        pub unsafe fn Release(&self) -> u32;
39    }
40
41}
42
43impl IUnknown {
44    /// A safe version of `QueryInterface`.
45    ///
46    /// If the backing class implements the interface `I` then a `Some`
47    /// containing an `ComPtr` pointing to that interface will be returned
48    /// otherwise `None` will be returned.
49    pub fn query_interface<I: Interface>(&self) -> Option<I> {
50        let mut ppv = None;
51        let hr = unsafe {
52            self.QueryInterface(
53                &I::IID as *const IID,
54                &mut ppv as *mut _ as *mut *mut c_void,
55            )
56        };
57        if FAILED(hr) {
58            assert!(
59                hr == E_NOINTERFACE || hr == E_POINTER,
60                "QueryInterface returned non-standard error"
61            );
62            return None;
63        }
64        debug_assert!(ppv.is_some());
65        ppv
66    }
67}