use std::{io::Error as IoError, marker::PhantomData};
use windows::Win32::{
Foundation::RPC_E_CHANGED_MODE,
System::Com::{CoInitializeEx, CoTaskMemFree, CoUninitialize, COINIT_APARTMENTTHREADED},
};
thread_local!(static COM_INITIALIZED: ComInitialized = {
unsafe {
let result = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
if result.is_ok() || result == RPC_E_CHANGED_MODE {
ComInitialized {
result,
_ptr: PhantomData,
}
} else {
panic!(
"Failed to initialize COM: {}",
IoError::from_raw_os_error(result.0)
);
}
}
});
struct ComInitialized {
result: windows::core::HRESULT,
_ptr: PhantomData<*mut ()>,
}
impl Drop for ComInitialized {
fn drop(&mut self) {
if self.result.is_ok() {
unsafe { CoUninitialize() };
}
}
}
pub(super) struct ComString(pub windows::core::PWSTR);
impl Drop for ComString {
fn drop(&mut self) {
unsafe { CoTaskMemFree(Some(self.0.as_ptr() as *mut _)) }
}
}
pub fn com_initialized() {
COM_INITIALIZED.with(|_| {});
}