1#![allow(dead_code)]
6
7use std::cell::Cell;
8use std::io;
9
10use windows::core::{
11 Interface,
12 GUID,
13};
14use windows::Win32::System::Com::{
15 CoCreateInstance,
16 CoInitializeEx,
17 CoTaskMemFree,
18 CLSCTX_INPROC_SERVER,
19 COINIT_APARTMENTTHREADED,
20};
21
22pub fn initialize_com() -> windows::core::Result<()> {
24 thread_local! {
25 static COM_INITIALIZED: Cell<bool> = const { Cell::new(false) };
26 }
27 COM_INITIALIZED.with(|initialized| {
28 if !initialized.get() {
29 let init_result = unsafe { CoInitializeEx(None, COINIT_APARTMENTTHREADED).ok() };
30 if let Ok(()) = init_result {
31 initialized.set(true);
32 }
33 init_result
34 } else {
35 Ok(())
36 }
37 })
38}
39
40pub(crate) trait ComInterfaceExt: Interface {
41 const CLASS_GUID: GUID;
42
43 fn new_instance() -> io::Result<Self> {
44 initialize_com()?;
45 let result = unsafe { CoCreateInstance(&Self::CLASS_GUID, None, CLSCTX_INPROC_SERVER) };
46 result.map_err(Into::into)
47 }
48}
49
50#[derive(Debug)]
52pub(crate) struct ComTaskMemory<T>(pub *mut T);
53
54impl<T> From<*mut T> for ComTaskMemory<T> {
55 fn from(value: *mut T) -> Self {
56 ComTaskMemory(value)
57 }
58}
59
60impl<T> Drop for ComTaskMemory<T> {
61 fn drop(&mut self) {
62 unsafe { CoTaskMemFree(Some(self.0 as *mut _)) }
63 }
64}