#![allow(unused_macros)]
macro_rules! com_interface {
(
$name:ident : $guid:expr;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
#[repr(transparent)]
pub struct $name(crate::kernel::ffi_types::COMPTR);
unsafe impl Send for $name {}
impl Drop for $name {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe {
use crate::{prelude::ole_IUnknown, ole::vts::IUnknownVT};
(crate::ole::privs::vt::<IUnknownVT>(self).Release)(self.ptr());
}
}
}
}
impl Clone for $name {
fn clone(&self) -> Self {
use crate::{prelude::ole_IUnknown, ole::vts::IUnknownVT};
unsafe { (crate::ole::privs::vt::<IUnknownVT>(self).AddRef)(self.ptr()); }
Self(self.ptr())
}
}
impl crate::prelude::ole_IUnknown for $name {
const IID: crate::co::IID = unsafe { crate::co::IID::from_raw($guid) };
unsafe fn from_ptr(p: *mut std::ffi::c_void) -> Self {
Self(p)
}
unsafe fn as_mut(&mut self) -> &mut *mut std::ffi::c_void {
&mut self.0
}
fn ptr(&self) -> *mut std::ffi::c_void {
self.0
}
}
};
}
macro_rules! fn_com_noparm {
(
$method:ident : $vt:ty;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
fn $method(&self) -> crate::HrResult<()> {
crate::ole::privs::HrRet(
unsafe {
(crate::ole::privs::vt::<$vt>(self).$method)(self.ptr())
},
).to_hrresult()
}
};
}
macro_rules! fn_com_noparm_noret {
(
$method:ident : $vt:ty;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
fn $method(&self) {
unsafe { (crate::ole::privs::vt::<$vt>(self).$method)(self.ptr()); }
}
};
}
macro_rules! fn_com_interface_get {
(
$method:ident : $vt:ty => $iface:ty;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
#[must_use]
fn $method(&self) -> crate::HrResult<$iface> {
use crate::prelude::ole_IUnknown;
let mut queried = unsafe { <$iface>::null() };
crate::ole::privs::HrRet(
unsafe {
(crate::ole::privs::vt::<$vt>(self).$method)(self.ptr(), queried.as_mut())
},
).to_hrresult().map(|_| queried)
}
};
}
macro_rules! fn_com_bstr_get {
(
$method:ident : $vt:ty;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
#[must_use]
fn $method(&self) -> crate::HrResult<String> {
let mut pstr = std::ptr::null_mut::<u16>();
crate::ole::privs::HrRet(
unsafe {
(crate::ole::privs::vt::<$vt>(self).$method)(self.ptr(), &mut pstr)
},
).to_hrresult().map(|_| {
let bstr = unsafe { crate::BSTR::from_ptr(pstr) };
bstr.to_string()
})
}
};
}
macro_rules! fn_com_bstr_set {
(
$method:ident : $vt:ty, $arg:ident;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
fn $method(&self, $arg: &str) -> crate::HrResult<()> {
crate::ole::privs::HrRet(
unsafe {
(crate::ole::privs::vt::<$vt>(self).$method)(
self.ptr(),
crate::BSTR::SysAllocString($arg)?.as_ptr(),
)
},
).to_hrresult()
}
};
}
macro_rules! com_interface_userdef {
(
$name:ident : $impl:ident, $guid:expr;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
#[repr(transparent)]
pub struct $name(*mut $impl);
unsafe impl Send for $name {}
impl Drop for $name {
fn drop(&mut self) {
if !self.0.is_null() {
let ppvt = &self.0 as *const *mut $impl;
$impl::Release(ppvt as _); }
}
}
impl Clone for $name {
fn clone(&self) -> Self {
let ppvt = &self.0 as *const *mut $impl;
$impl::AddRef(ppvt as _);
Self(self.0)
}
}
impl crate::prelude::ole_IUnknown for $name {
const IID: crate::co::IID = unsafe { crate::co::IID::from_raw($guid) };
unsafe fn from_ptr(_p: *mut std::ffi::c_void) -> Self {
panic!("Cannot create a custom COM implementation from a pointer, use new_impl().");
}
unsafe fn as_mut(&mut self) -> &mut *mut std::ffi::c_void {
panic!("Cannot modify a custom COM implementation pointer.");
}
fn ptr(&self) -> *mut std::ffi::c_void {
let p = &self.0 as *const *mut $impl;
p as *mut _
}
}
impl $name {
#[must_use]
pub fn new_impl() -> Self {
let box_impl = Box::new($impl::new()); Self(Box::into_raw(box_impl))
}
}
};
}
macro_rules! fn_com_userdef_event {
(
$method:ident: $fun: path;
$( #[$doc:meta] )*
) => {
$( #[$doc] )*
pub fn $method<F>(&self, func: F) -> &Self
where F: $fun + 'static,
{
let mut box_impl = std::mem::ManuallyDrop::new(unsafe { Box::from_raw(self.0) });
box_impl.$method = Some(Box::new(func));
self
}
};
}
macro_rules! fn_com_userdef_iunknown_impls {
($impl:ident) => {
fn QueryInterface(
_p: crate::kernel::ffi_types::COMPTR,
_riid: crate::kernel::ffi_types::PCVOID,
ppv: *mut crate::kernel::ffi_types::COMPTR,
) -> crate::kernel::ffi_types::HRES {
unsafe {
*ppv = std::ptr::null_mut();
}
crate::co::HRESULT::E_NOTIMPL.raw()
}
fn AddRef(p: crate::kernel::ffi_types::COMPTR) -> u32 {
let box_impl = crate::ole::privs::box_impl_of::<Self>(p);
let cc = box_impl
.counter
.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
+ 1;
cc
}
fn Release(p: crate::kernel::ffi_types::COMPTR) -> u32 {
let mut box_impl = crate::ole::privs::box_impl_of::<Self>(p);
let count = box_impl
.counter
.fetch_sub(1, std::sync::atomic::Ordering::Relaxed)
- 1;
if count == 0 {
unsafe {
std::mem::ManuallyDrop::drop(&mut box_impl); }
}
count
}
};
}
macro_rules! fn_com_userdef_impl_noparm {
($name:ident) => {
fn $name(p: crate::kernel::ffi_types::COMPTR) -> crate::kernel::ffi_types::HRES {
let box_impl = crate::ole::privs::box_impl_of::<Self>(p);
crate::ole::privs::hrresult_to_hres(match &box_impl.$name {
Some(func) => crate::ole::privs::anyresult_to_hresult(func()),
None => Ok(()),
})
}
};
}
macro_rules! const_guid {
(
$name:ident;
$( #[$doc:meta] )*
=>
$( $pubname:ident $guid:expr )*
) => {
$( #[$doc] )*
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct $name(crate::GUID);
impl From<crate::GUID> for $name {
fn from(guid: crate::GUID) -> Self {
Self(guid)
}
}
impl AsRef<crate::GUID> for $name {
fn as_ref(&self) -> &crate::GUID {
&self.0
}
}
impl std::fmt::Debug for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.0, f)
}
}
impl $name {
#[must_use]
pub const unsafe fn from_raw(guid_str: &str) -> Self {
Self(crate::GUID::from_str(guid_str))
}
}
const_guid_values! {
$name;
$( $pubname $guid )*
}
};
}
macro_rules! const_guid_values {
(
$name:ident;
$( $pubname:ident $guid:expr )*
) => {
impl $name {
$(
pub const $pubname: $name = unsafe { $name::from_raw($guid) };
)*
}
};
}