How do I query for a specific COM interface?

COM and WinRT interfaces in the windows crate implement the ComInterface trait. This trait provides the cast method that will use QueryInterface under the hood to cast the current interface to another interface supported by the object. The cast method returns a Result<T> so that failure can be handled in a natural way in Rust.

For example, it is often necesary to get the IDXGIDevice interface for a given Direct3D device to interop with other rendering APIs. This is how you might create a swap chain for drawing and presenting to a Direct3D device. Let's imagine a simple function that accepts a Direct3D device and returns the underlying DXGI factory:

#![allow(unused)]
fn main() {
fn get_dxgi_factory(device: &ID3D11Device) -> Result<IDXGIFactory2> {
}
}

The first thing you need to do is query or cast the Direct3D device for its DXGI interface as follows:

#![allow(unused)]
fn main() {
let device = device.cast::<IDXGIDevice>()?;
}

If its more convenient, you can also make use of type inference as follows:

#![allow(unused)]
fn main() {
let device: IDXGIDevice = device.cast()?;
}

With the COM interface in hand, we need an unsafe block to call its methods:

#![allow(unused)]
fn main() {
unsafe {
}
}

Within the unsafe block, we can retrieve the device's physical adapter:

#![allow(unused)]
fn main() {
let adapter = device.GetAdapter()?;
}

And just for fun (or debugging), we might print out the adapter's name:

#![allow(unused)]
fn main() {
if cfg!(debug_assertions) {
    let mut desc = Default::default();
    adapter.GetDesc(&mut desc)?;
    println!("{}", String::from_utf16_lossy(&desc.Description));
}
}

Finally, we can return the adapter's parent and also the DXGI factory object for the device:

#![allow(unused)]
fn main() {
adapter.GetParent()
}

Running the sample I get the following impressive results:

AMD FirePro W4100

Here's a more comprehensive DirectX example.

The cast method works equally well for WinRT classes and interfaces. It is particularly useful for interop with WinRT APIs.