use crate::errors::MethodHResult;
use winapi::ctypes::c_void;
use winapi::shared::winerror::{S_OK, S_FALSE};
use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize, CoIncrementMTAUsage, CoDecrementMTAUsage, CO_MTA_USAGE_COOKIE};
use winapi::um::objbase::{COINIT, COINIT_APARTMENTTHREADED, COINIT_MULTITHREADED, COINIT_DISABLE_OLE1DDE, COINIT_SPEED_OVER_MEMORY};
use core::fmt::{self, Debug, Formatter};
use core::marker::PhantomData;
use core::ops::{BitOr, BitOrAssign};
use core::ptr::null_mut;
pub fn sta() -> Result<bool, MethodHResult> { co_initialize_ex((), CoInit::STA) }
pub fn mta() -> Result<bool, MethodHResult> { co_initialize_ex((), CoInit::MTA) }
pub fn co_initialize_ex<'r>(reserved: impl Into<CoInitializeExReserved<'r>>, coinit: impl Into<CoInit>) -> Result<bool, MethodHResult> {
let reserved = reserved.into().0;
let coinit = coinit.into().0;
let hr = unsafe { CoInitializeEx(reserved, coinit) };
MethodHResult::check("CoInitializeEx", hr)?;
match hr {
S_FALSE => Ok(false),
S_OK => Ok(true),
_unexpected => {
Ok(true)
},
}
}
pub unsafe fn uninitialize() {
CoUninitialize(); }
#[doc(hidden)]
pub struct CoInitializeExReserved<'p>(*mut c_void, PhantomData<&'p ()>);
impl<'p> Default for CoInitializeExReserved<'p> {
fn default() -> Self { Self(null_mut(), PhantomData) }
}
impl<'p> From<()> for CoInitializeExReserved<'p> {
fn from(_: ()) -> Self { Self(null_mut(), PhantomData) }
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CoInit(COINIT);
impl CoInit {
pub fn init(self) -> Result<bool, MethodHResult> { co_initialize_ex((), self) }
pub const APARTMENT_THREADED : CoInit = CoInit(COINIT_APARTMENTTHREADED);
pub const MULTI_THREADED : CoInit = CoInit(COINIT_MULTITHREADED);
pub const DISABLE_OLE1DDE : CoInitFlag = CoInitFlag::DISABLE_OLE1DDE;
pub const SPEED_OVER_MEMORY : CoInitFlag = CoInitFlag::SPEED_OVER_MEMORY;
#[doc(hidden)] pub const APARTMENTTHREADED : CoInit = Self::APARTMENT_THREADED;
#[doc(hidden)] pub const MULTITHREADED : CoInit = Self::MULTI_THREADED;
#[doc(hidden)] pub const STA : CoInit = Self::APARTMENT_THREADED;
#[doc(hidden)] pub const MTA : CoInit = Self::MULTI_THREADED;
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CoInitFlag(COINIT);
impl CoInitFlag {
pub const DISABLE_OLE1DDE : CoInitFlag = CoInitFlag(COINIT_DISABLE_OLE1DDE);
pub const SPEED_OVER_MEMORY : CoInitFlag = CoInitFlag(COINIT_SPEED_OVER_MEMORY);
}
impl BitOrAssign<CoInitFlag> for CoInit { fn bitor_assign(&mut self, rhs: CoInitFlag) { self.0 |= rhs.0; } }
impl BitOrAssign<CoInitFlag> for CoInitFlag { fn bitor_assign(&mut self, rhs: CoInitFlag) { self.0 |= rhs.0; } }
impl BitOr<CoInitFlag> for CoInit { fn bitor(self, rhs: CoInitFlag) -> Self::Output { CoInit(self.0 | rhs.0) } type Output = CoInit; }
impl BitOr<CoInit> for CoInitFlag { fn bitor(self, rhs: CoInit ) -> Self::Output { CoInit(self.0 | rhs.0) } type Output = CoInit; }
impl BitOr<CoInitFlag> for CoInitFlag { fn bitor(self, rhs: CoInitFlag) -> Self::Output { CoInitFlag(self.0 | rhs.0) } type Output = CoInitFlag; }
pub struct MTAUsageScope(CO_MTA_USAGE_COOKIE);
impl MTAUsageScope {
pub unsafe fn new() -> Result<Self, MethodHResult> {
let mut cookie = null_mut();
let hr = CoIncrementMTAUsage(&mut cookie);
MethodHResult::check("CoIncrementMTAUsage", hr)?;
Ok(Self(cookie))
}
}
impl Debug for MTAUsageScope {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "MTAUsageScope") }
}
impl Drop for MTAUsageScope {
fn drop(&mut self) {
let hr = unsafe { CoDecrementMTAUsage(self.0) };
MethodHResult::check("CoDecrementMTAUsage", hr).unwrap();
}
}