rustcomwindows-rs

consume COM library from C# to rust


Question

I want to rewrite my project from C# to rust. But I stuck in Segmentation Fault situation. I think I misunderstood something, or meet crate limitation, hope for some help.

Rust Code

use windows::core::{GUID, HRESULT, IUnknown, IUnknown_Vtbl, interface};
use windows::Win32::System::Com::{
    COINIT_APARTMENTTHREADED, 
    CLSCTX_ALL,
    CoInitializeEx,
    CoCreateInstance};

// define interface
#[interface("288EFDEC-3CF0-4F6C-8473-4E4CD47A93C7")]
unsafe trait Inhicshisx: IUnknown {
    fn VPNGetRandomX(&self) -> HRESULT;
}

fn run() -> Result<(), anyhow::Error> {
    unsafe {
        // 2F5AECD5-B5CD-41E1-8265-E2F6AA4548CB
        const CLSID: GUID = GUID {
            data1: 0x2F5AECD5,
            data2: 0xB5CD,
            data3: 0x41E1,
            data4: [0x82, 0x65, 0xE2, 0xF6, 0xAA, 0x45, 0x48, 0xCB],
        };
        
        // initialize runtime
        CoInitializeEx(Some(ptr::null_mut() as *mut c_void), COINIT_APARTMENTTHREADED)?;
        
        // create COM object
        let hisx: Inhicshisx = CoCreateInstance(&CLSID, None, CLSCTX_ALL)?;
        
        // call object function
        let value = hisx.VPNGetRandomX();
    }
    
    Ok(())
}

C# Part

using CSHISXLib;
string MyStr0;
CSHISXLib.Inhicshisx CSHISXLibObj = new CSHISXLib.nhicshisx();
MyStr0 = CSHISXLibObj.VPNGetRandomX();
Console.WriteLine(MyStr0);

Update information

According to @IInspectable help, I can generate interface by oleview.exe tool.

[
  odl,
  uuid(288EFDEC-3CF0-4F6C-8473-4E4CD47A93C7),
  helpstring("Inhicshisx Interface"),
  dual,
  oleautomation
]
interface Inhicshisx : IDispatch {
    [id(0x00000001), helpstring("method VPNGetRandomX")]
    HRESULT VPNGetRandomX([out, retval] BSTR* strRandom);
    [id(0x00000002), helpstring("method VPNH_SignX")]
    HRESULT VPNH_SignX(
                    [in] BSTR strRandom, 
                    [in, optional, defaultvalue("")] BSTR strCardType, 
                    [in, optional, defaultvalue("")] BSTR strServiceType, 
                    [out, retval] BSTR* strRet);
}
use windows::core::BSTR;

#[interface("288EFDEC-3CF0-4F6C-8473-4E4CD47A93C7")]
unsafe trait Inhicshisx: IDispatch {
    fn VPNGetRandomX(&self) -> BSTR;
    fn VPNH_SignX(&self, *mut BSTR, *mut BSTR, *mut BSTR) -> BSTR;
}

But it still cause Segmentation Fault, hope some advice 🙏


Solution

  • Thank for @IInspectable advice.

    Segmentation Fault caused by wrong interface.

    Find the COM interface

    you can use oleview to display for COM library interface. In my case, the interface like this.

    interface Inhicshisx : IDispatch {
        [id(0x00000001), helpstring("method VPNGetRandomX")]
        HRESULT VPNGetRandomX([out, retval] BSTR* strRandom);
        [id(0x00000002), helpstring("method VPNH_SignX")]
        HRESULT VPNH_SignX(
                        [in] BSTR strRandom, 
                        [in, optional, defaultvalue("")] BSTR strCardType, 
                        [in, optional, defaultvalue("")] BSTR strServiceType, 
                        [out, retval] BSTR* strRet);
    }
    

    Declare interface in Rust

    #[interface("288EFDEC-3CF0-4F6C-8473-4E4CD47A93C7")]
    unsafe trait Inhicshisx: IDispatch {
        fn VPNGetRandomX(&self, random: *mut BSTR) -> HRESULT;
        fn VPNH_SignX(&self, random: BSTR, card_type: BSTR, service_type: BSTR, sign: *mut BSTR) -> HRESULT;
    }