clroxide 1.1.1

A library that allows you to host the CLR and execute dotnet binaries.
Documentation
use crate::primitives::{Interface, GUID, HRESULT};
use std::{ffi::c_void, mem::transmute_copy};

#[repr(C)]
pub struct IUnknown {
    pub vtable: *const IUnknownVtbl,
}

#[repr(C)]
pub struct IUnknownVtbl {
    pub QueryInterface: unsafe extern "system" fn(
        this: *mut c_void,
        iid: *const GUID,
        interface: *mut *mut c_void,
    ) -> HRESULT,
    pub AddRef: unsafe extern "system" fn(this: *mut c_void) -> u32,
    pub Release: unsafe extern "system" fn(this: *mut c_void) -> u32,
}

impl IUnknown {
    #[inline]
    pub unsafe fn QueryInterface(&self, riid: *const GUID, ppvObject: *mut *mut c_void) -> HRESULT {
        ((*self.vtable).QueryInterface)(self as *const _ as *mut _, riid, ppvObject)
    }

    #[inline]
    pub unsafe fn AddRef(&self) -> u32 {
        ((*self.vtable).AddRef)(self as *const _ as *mut _)
    }

    #[inline]
    pub unsafe fn Release(&self) -> u32 {
        ((*self.vtable).Release)(self as *const _ as *mut _)
    }
}

impl Interface for IUnknown {
    const IID: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046);

    fn vtable(&self) -> *const c_void {
        self.vtable as *const _ as *const c_void
    }
}

impl Clone for IUnknown {
    fn clone(&self) -> Self {
        unsafe {
            self.AddRef();
        }

        unsafe { transmute_copy(self) }
    }
}

impl Drop for IUnknown {
    fn drop(&mut self) {
        unsafe {
            self.Release();
        }
    }
}

impl std::fmt::Debug for IUnknown {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("IUnknown").field(&self).finish()
    }
}