use crate::error::WslcError;
use std::marker::PhantomData;
use windows_sys::Win32::System::Com::{COINIT_MULTITHREADED, CoInitializeEx, CoUninitialize};
use windows_sys::core::HRESULT;
const RPC_E_CHANGED_MODE: HRESULT = 0x8001_0106_u32 as HRESULT;
#[derive(Debug)]
pub struct ComGuard {
should_uninitialize: bool,
_not_send: PhantomData<*const ()>,
}
impl Drop for ComGuard {
fn drop(&mut self) {
if self.should_uninitialize {
unsafe {
CoUninitialize();
}
}
}
}
pub fn try_initialize_mta() -> Result<Option<ComGuard>, WslcError> {
let hr = unsafe { CoInitializeEx(std::ptr::null_mut(), COINIT_MULTITHREADED as u32) };
match hr {
0 | 1 => Ok(Some(ComGuard {
should_uninitialize: true,
_not_send: PhantomData,
})),
RPC_E_CHANGED_MODE => Ok(None),
code => Err(WslcError::Win32(
code as u32,
"CoInitializeEx 初始化失败".to_string(),
)),
}
}
pub fn with_mta<F, R>(f: F) -> Result<R, WslcError>
where
F: FnOnce() -> Result<R, WslcError>,
{
let _guard = try_initialize_mta()?;
f()
}