use std::ffi::*;
use windows_core::{IUnknown, Interface};
use crate::windows_bindings::*;
use super::*;
pub fn create_result<T>(ok_value: T, code: ErrorCode) -> Result<T> {
match code {
ErrorCode::OK |
ErrorCode::SUCCESS => Ok(ok_value),
bad_code => Err(Error(unsafe { NonZeroI32::new_unchecked(bad_code.0) }))
}
}
#[must_use]
pub fn cstring_from_bytes_until_nul(buffer: &[u8]) -> CString {
CStr
::from_bytes_until_nul(buffer)
.expect("buffer overflow")
.to_owned()
}
#[derive(Debug)]
pub struct COM(());
impl COM {
pub fn new(coinit: COINIT) -> windows_core::Result<Self> {
unsafe { CoInitializeEx(None, coinit) }.ok()?;
Ok(Self(()))
}
#[expect(clippy::unused_self, reason = "required as a guarantee that COM is initialized")]
pub fn create_driver_instance(&self, guid: *const GUID) -> WinResult<IIASIORedecl> {
let i_unknown: IUnknown =
unsafe { CoCreateInstance(guid, None, CLSCTX_SERVER) }?;
unsafe { cast_decoupled(&i_unknown, guid) }
}
}
pub unsafe fn cast_decoupled<Target: Interface>(interface: &impl Interface, target_iid: *const GUID) -> windows_core::Result<Target> {
let mut out = None;
unsafe { interface.query(target_iid, (&raw mut out).cast()) }.ok()?;
out.ok_or_else(|| E_POINTER.into())
}
impl Drop for COM {
fn drop(&mut self) {
unsafe { CoUninitialize(); }
}
}