-
Notifications
You must be signed in to change notification settings - Fork 465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use ICLRMetaHost
#1998
Comments
Try this:
#![allow(non_snake_case, non_upper_case_globals)]
use std::ffi::*;
use std::mem::*;
use windows::{core::*, Win32::System::LibraryLoader::*};
const CLSID_CLRMetaHost: GUID = GUID::from_u128(0x9280188d_0e8e_4867_b30c_7fa83884e8de);
type CLRCreateInstance = extern "system" fn(*const GUID, *const GUID, *mut *mut c_void) -> HRESULT;
#[interface("D332DB9E-B9B3-4125-8207-A14884F53216")]
unsafe trait ICLRMetaHost: IUnknown {
unsafe fn GetRuntime(
&self,
pwzVersion: PCWSTR,
riid: *const GUID,
ppRuntime: *mut *mut c_void,
) -> HRESULT;
}
#[interface("BD39D1D2-BA2F-486a-89B0-B4B0CB466891")]
unsafe trait ICLRRuntimeInfo: IUnknown {
unsafe fn GetVersionString(&self, pwzBuffer: PWSTR, pcchBuffer: *mut u32) -> HRESULT;
}
fn main() -> Result<()> {
unsafe {
let mscoree = LoadLibraryA(s!("mscoree"))?;
let create: CLRCreateInstance =
std::mem::transmute(GetProcAddress(mscoree, s!("CLRCreateInstance")));
let mut host = MaybeUninit::zeroed();
let host: ICLRMetaHost =
create(&CLSID_CLRMetaHost, &ICLRMetaHost::IID, host.as_mut_ptr()).from_abi(host)?;
let mut info = MaybeUninit::zeroed();
let info: ICLRRuntimeInfo = host
.GetRuntime(
w!("v4.0.30319").into(),
&ICLRRuntimeInfo::IID,
info.as_mut_ptr(),
)
.from_abi(info)?;
let mut version = [0; 20];
let mut len = version.len() as u32;
info.GetVersionString(PWSTR(version.as_mut_ptr()), &mut len)
.ok()?;
println!(
"Version: {}",
String::from_utf16(&version).expect("Invalid string")
);
println!("Rust is now controlling the CLR 😜");
Ok(())
}
} |
ICLRMetaHost
Wow, thanks! That example is very helpful (TIL about the Abi trait and those string macros). I'm still unpacking it a bit, but it looks like my raw pointer cast for metahost was bad? And I actually had a pointer to the inner IUnknown? |
Yep, you need a pretty good understanding of both COM and how COM interface pointers are represented in Rust. We're working on making it as safe and simple as possible so if you find yourself doing a lot of contrived casting there's a good chance you're doing something wrong. |
Which crate is this about?
windows
Crate version
0.39.0
Summary
Hi, I am trying to declare and use the ICLRMetaHost interface from
mscoree.dll
with thewindows::core::interface
macro per the FAQ (https://github.com/microsoft/windows-rs/blob/master/docs/FAQ.md#how-do-i-declare-a-new-com-interface). As far as I can tell I have a valid metahost value, but when I attempt to call the interface methods, I am getting memory access violations (call rax
goes to a very high very wrong address). I'm not sure if this is a bug with the vtable generation or (more likely) if I'm just doing something wrong. The included example code is calling the GetRuntime method but I have tried some of the other methods with similar results. Thanks!Toolchain version/configuration
Reproducible example
Crate manifest
Expected behavior
I expected to receive a pointer to a CLRRuntimeInfo object
Actual behavior
stdout
windbg
Additional comments
No response
The text was updated successfully, but these errors were encountered: