intercom/
classfactory.rs

1//! The class factory is an infrastructure type used by the COM clients to
2//! create instances of the `#[com_class(..)]`es provided by the intercom
3//! library.
4//!
5//! Intercom implements the class factory infrastructure automatically when the
6//! user specifies the `#[com_library(..)]` -attribute.
7
8use super::*;
9use crate::attributes;
10use crate::raw::RawComPtr;
11
12#[com_interface(
13    com_iid = "00000001-0000-0000-C000-000000000046",
14    raw_iid = "11111112-0000-0000-C000-000000000046"
15)]
16pub trait IClassFactory
17{
18    /// # Safety
19    ///
20    /// The REFIID must be a valid IID pointer.
21    unsafe fn create_instance(&self, outer: RawComPtr, riid: REFIID) -> ComResult<RawComPtr>;
22
23    fn lock_server(&self, lock: bool) -> ComResult<()>;
24}
25
26#[doc(hidden)]
27#[com_class(IClassFactory)]
28pub struct ClassFactory<T: Default + intercom::attributes::ComClass>
29{
30    phantom: std::marker::PhantomData<T>,
31}
32
33impl<T: Default + attributes::ComClass> IClassFactory for ClassFactory<T>
34{
35    unsafe fn create_instance(&self, _outer: RawComPtr, riid: REFIID) -> ComResult<RawComPtr>
36    {
37        let instance = ComBox::new(T::default());
38        let mut out = std::ptr::null_mut();
39        let hr = ComBoxData::query_interface(instance.as_ref(), riid, &mut out);
40        if hr == raw::S_OK {
41            Ok(out)
42        } else {
43            Err(ComError::from(hr))
44        }
45    }
46
47    fn lock_server(&self, lock: bool) -> ComResult<()>
48    {
49        unsafe {
50            if lock {
51                ComBoxData::add_ref(ComBoxData::of(self));
52            } else {
53                ComBoxData::release(
54                    ComBoxData::of(self) as *const ComBoxData<Self> as *mut ComBoxData<Self>
55                );
56            }
57        }
58        Ok(())
59    }
60}
61
62impl<T: Default + attributes::ComClass> ClassFactory<T>
63{
64    /// # Safety
65    ///
66    /// The `out` pointer must be valid for receiving the requested interface.
67    pub unsafe fn create(riid: intercom::REFIID, out: *mut RawComPtr)
68        -> crate::error::raw::HRESULT
69    {
70        let factory = Self {
71            phantom: std::marker::PhantomData,
72        };
73
74        intercom::ComBoxData::query_interface(intercom::ComBox::new(factory).as_mut(), riid, out)
75    }
76}