intercom/
interfaces.rs

1use super::*;
2use crate::raw::HRESULT;
3use crate::type_system::{AutomationTypeSystem, RawTypeSystem};
4
5/// The `IUnknown` COM interface.
6///
7/// All COM interfaces must inherit from `IUnknown` interface directly or
8/// indirectly. The interface provides the basis of COM reference counting
9/// and interface discovery.
10///
11/// For Rust code, Intercom implements the interface automatically.
12#[com_interface(
13    com_iid = "00000000-0000-0000-C000-000000000046",
14    raw_iid = "11111111-0000-0000-C000-000000000046",
15    base = NO_BASE,
16    vtable_of = RawIUnknown )]
17pub trait IUnknown {}
18
19#[com_interface(
20    com_iid = "00000000-0000-0000-C000-000000000046",
21    raw_iid = "11111111-0000-0000-C000-000000000046",
22    base = NO_BASE )]
23pub trait RawIUnknown
24{
25    /// Tries to get a different COM interface for the current object.
26    ///
27    /// COM objects may (and do) implement multiple interfaces. COM defines
28    /// `QueryInterface` as the mechanism for acquiring an interface pointer
29    /// to a different interface the object implements.
30    ///
31    /// * `riid` - The `IID` of the interface to query.
32    ///
33    /// Returns `Ok( interface_ptr )` if the object supports the specified
34    /// interface or `Err( E_NOINTERFACE )` if it doesn't.
35    fn query_interface(&self, riid: crate::REFIID) -> crate::RawComResult<crate::raw::RawComPtr>;
36
37    /// Increments the reference count of the object.
38    ///
39    /// Returns the reference count after the incrementation.
40    fn add_ref(&self) -> u32;
41
42    /// Decreases the reference count of the object.
43    ///
44    /// Returns the reference count after the decrement.
45    ///
46    /// If the reference count reaches zero, the object will deallocate
47    /// itself. As the call might deallocate the object, the caller must
48    /// ensure that the released reference is not used afterwards.
49    fn release(&self) -> u32;
50}
51
52impl<I, S> crate::attributes::ComInterfaceVTableFor<I, S, RawTypeSystem> for dyn IUnknown
53where
54    I: ?Sized,
55    S: intercom::attributes::ComClassInterface<I, RawTypeSystem> + intercom::attributes::ComClass,
56{
57    const VTABLE: Self::VTable = Self::VTable {
58        query_interface: query_interface::<I, S, RawTypeSystem>,
59        add_ref: add_ref::<I, S, RawTypeSystem>,
60        release: release::<I, S, RawTypeSystem>,
61    };
62}
63impl<I, S> crate::attributes::ComInterfaceVTableFor<I, S, AutomationTypeSystem> for dyn IUnknown
64where
65    I: ?Sized,
66    S: intercom::attributes::ComClassInterface<I, AutomationTypeSystem>
67        + intercom::attributes::ComClass,
68{
69    const VTABLE: Self::VTable = Self::VTable {
70        query_interface: query_interface::<I, S, AutomationTypeSystem>,
71        add_ref: add_ref::<I, S, AutomationTypeSystem>,
72        release: release::<I, S, AutomationTypeSystem>,
73    };
74}
75
76#[doc(hidden)]
77pub unsafe extern "system" fn query_interface<I, S, TS>(
78    self_vtable: crate::raw::RawComPtr,
79    riid: *const crate::GUID,
80    out: *mut *mut std::ffi::c_void,
81) -> HRESULT
82where
83    I: ?Sized,
84    S: intercom::attributes::ComClassInterface<I, TS> + intercom::attributes::ComClass,
85    TS: crate::type_system::TypeSystem,
86{
87    let combox = S::get_box(self_vtable);
88    log::trace!(
89        "[{:p}, through {:p}] Serving {}::query_interface",
90        combox,
91        self_vtable,
92        std::any::type_name::<S>()
93    );
94    intercom::ComBoxData::<S>::query_interface(combox, riid, out)
95}
96
97#[doc(hidden)]
98pub unsafe extern "system" fn add_ref<I, S, TS>(self_vtable: crate::raw::RawComPtr) -> u32
99where
100    I: ?Sized,
101    S: intercom::attributes::ComClassInterface<I, TS> + intercom::attributes::ComClass,
102    TS: crate::type_system::TypeSystem,
103{
104    let combox = S::get_box(self_vtable);
105    log::trace!(
106        "[{:p}, through {:p}] Serving {}::add_ref",
107        combox,
108        self_vtable,
109        std::any::type_name::<S>()
110    );
111    intercom::ComBoxData::<S>::add_ref(combox)
112}
113
114#[doc(hidden)]
115pub unsafe extern "system" fn release<I, S, TS>(self_vtable: crate::raw::RawComPtr) -> u32
116where
117    I: ?Sized,
118    S: intercom::attributes::ComClassInterface<I, TS> + intercom::attributes::ComClass,
119    TS: crate::type_system::TypeSystem,
120{
121    let combox = S::get_box(self_vtable);
122    log::trace!(
123        "[{:p}, through {:p}] Serving {}::release",
124        combox,
125        self_vtable,
126        std::any::type_name::<S>()
127    );
128    intercom::ComBoxData::<S>::release(combox)
129}
130
131/// The `ISupportErrorInfo` COM interface.
132///
133/// The `ISupportErrorInfo` is part of COM error handling concept. As the
134/// methods are traditionally limited to `HRESULT` return values, they may
135/// make more detailed `IErrorInfo` data available through the error info
136/// APIs.
137///
138/// The `ISupportErrorInfo` interface communicates which interfaces that an
139/// object implements support detailed error info. When a COM client
140/// receives an error-HRESULT, it may query for error info support through
141/// this interface. If the interface returns an `S_OK` as opposed to
142/// `S_FALSE` return value, the client can then use separate error info
143/// APIs to retrieve a detailed `IErrorInfo` object that contains more
144/// details about the error, such as the error message.
145///
146/// Intercom COM classes support the detailed error info for all user
147/// specified interfaces automatically. Only methods that return a
148/// two-parameter `Result<S,E>` value will store the detailed `IErrorInfo`.
149/// Other methods will set a null `IErrorInfo` value.
150#[com_interface(
151    com_iid = "DF0B3D60-548F-101B-8E65-08002B2BD119",
152    raw_iid = "4C667A45-1C4F-4761-8EBF-34E7699BD06E",
153    implemented_by = isupporterrorinfo
154)]
155pub trait ISupportErrorInfo: IUnknown
156{
157    /// Informs the current COM class supports `IErrorInfo` for a specific
158    /// interface.
159    ///
160    /// * `riid` - The `IID` of the interface to query.
161    ///
162    /// Returns `S_OK` if the object supports `IErrorInfo` for the
163    /// interface specified by the `riid` parameter. Otherwise returns
164    /// `S_FALSE` - even in the case the object doesn't implement `riid`
165    /// at all.
166    ///
167    /// # Description
168    ///
169    /// If the object returns `S_OK` for an interface, then any methods
170    /// the object implements for that interface must store the
171    /// `IErrorInfo` on failure.
172    ///
173    /// Intercom will implement the support for `IErrorInfo` automatically
174    /// for all custom interfaces the user defines. This includes returning
175    /// `S_OK` from this method.
176    ///
177    fn interface_supports_error_info(&self, riid: crate::REFIID) -> crate::raw::HRESULT;
178}
179
180pub mod isupporterrorinfo
181{
182    use crate::{combox::ComBoxData, raw, REFIID};
183
184    /// Checks whether the given interface identified by the IID supports error
185    /// info through IErrorInfo.
186    pub fn interface_supports_error_info<S>(_this: &ComBoxData<S>, riid: REFIID) -> raw::HRESULT
187    where
188        S: intercom::attributes::ComClass,
189    {
190        match S::interface_supports_error_info(riid) {
191            true => raw::S_OK,
192            false => raw::S_FALSE,
193        }
194    }
195}