#com #com-interface #winapi #windows #reference-counting

com-impl

Automatically implement Win32 COM interfaces from Rust, along with some useful helper types for getting it done

5 releases

0.2.0 Jul 25, 2023
0.1.1 Mar 1, 2019
0.1.0 Mar 1, 2019
0.1.0-alpha2 Nov 11, 2018

#87 in Windows APIs

Download history 15/week @ 2024-01-08 23/week @ 2024-01-15 4/week @ 2024-01-22 3/week @ 2024-01-29 5/week @ 2024-02-05 22/week @ 2024-02-12 24/week @ 2024-02-19 79/week @ 2024-02-26 25/week @ 2024-03-04 30/week @ 2024-03-11 31/week @ 2024-03-18 36/week @ 2024-03-25 49/week @ 2024-04-01 15/week @ 2024-04-08 25/week @ 2024-04-15

128 downloads per month
Used in 3 crates (2 directly)

MIT license

10KB
64 lines

com-impl

Automatically implement Win32 COM interfaces from Rust, along with some useful helper types for getting it done.

Provides automatic implementation of IUnknown, and an atomic refcount type which will be used automatically when you #[derive(ComImpl)] your type.

#[repr(C)]
#[derive(com_impl::ComImpl)]
#[interfaces(IDWriteFontFileStream)] // IUnknown is implicit in this list
pub struct FileStream {
    vtbl: com_impl::VTable<IDWriteFontFileStreamVtbl>,
    refcount: com_impl::Refcount,
    write_time: u64,
    file_data: Vec<u8>,
}

impl FileStream {
    pub fn new(write_time: u64, data: Vec<u8>) -> ComPtr<IDWriteFontFileStream> {
        let ptr = FileStream::create_raw(write_time, data);
        let ptr = ptr as *mut IDWriteFontFileStream;
        unsafe { ComPtr::from_raw(ptr) }
    }
}

#[com_impl::com_impl]
unsafe impl IDWriteFontFileStream for FileStream {
    unsafe fn get_file_size(&self, size: *mut u64) -> HRESULT {
        *size = self.file_data.len() as u64;
        S_OK
    }

    unsafe fn get_last_write_time(&self, write_time: *mut u64) -> HRESULT {
        *write_time = self.write_time;
        S_OK
    }

    unsafe fn read_file_fragment(
        &self,
        start: *mut *const c_void,
        offset: u64,
        size: u64,
        ctx: *mut *mut c_void,
    ) -> HRESULT {
        if offset > std::isize::MAX as u64 || size > std::isize::MAX as u64 {
            return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
        }

        let offset = offset as usize;
        let size = size as usize;

        if offset + size > self.file_data.len() {
            return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
        }

        *start = self.file_data.as_ptr().offset(offset as isize) as *const c_void;
        *ctx = std::ptr::null_mut();

        S_OK
    }

    unsafe fn release_file_fragment(&self, _ctx: *mut c_void) {
        // Nothing to do
    }
}

fn main() {
    let ptr = FileStream::new(100, vec![0xDE, 0xAF, 0x00, 0xF0, 0x01]);

    // Do things with ptr
}

Dependencies

~0–460KB