Skip to content

Commit

Permalink
Added ComInterface trait to tie IID to interface type (requires night…
Browse files Browse the repository at this point in the history
…ly).
  • Loading branch information
Boddlnagg committed May 28, 2016
1 parent 370b65e commit 7c06074
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 32 deletions.
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,4 @@ authors = ["Patrick Reisert"]

[dependencies]
winapi = "0.2.7"
runtimeobject-sys = "0.0.1"

[features]
nightly = []
runtimeobject-sys = "0.0.1"
6 changes: 4 additions & 2 deletions src/comptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use winapi as w;
use std::ops::{Deref, DerefMut};
use std::fmt;
use std::{ptr, mem};
use super::ComInterface;

#[derive(Debug)]
pub struct ComPtr<T>(*mut T);
pub struct ComPtr<T>(*mut T); // TODO: use NonZero?

impl<T> fmt::Pointer for ComPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down Expand Up @@ -33,7 +34,8 @@ impl<T> ComPtr<T> {
&mut self.0
}

pub fn query_interface<Target>(&self, iid: ::winapi::REFIID) -> Option<ComPtr<Target>> {
pub fn query_interface<Target>(&self) -> Option<ComPtr<Target>> where Target: ComInterface {
let iid: ::winapi::REFIID = Target::IID;
let mut result: ComPtr<Target> = unsafe { ComPtr::new(ptr::null_mut()) };
match unsafe { self.as_unknown().QueryInterface(iid, result.get_address() as *mut _ as *mut *mut ::winapi::VOID) } {
::winapi::S_OK => Some(result),
Expand Down
71 changes: 45 additions & 26 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![cfg_attr(test,feature(test))]

#![cfg_attr(feature="nightly", feature(specialization))]
#![feature(specialization, associated_consts)]

#![allow(dead_code,non_upper_case_globals,non_snake_case)]

Expand All @@ -27,10 +27,13 @@ use hstring::HString;

pub mod comptr;
use comptr::ComPtr;


pub trait ComInterface {
const IID: REFIID;
}

macro_rules! RIDL {
(interface $interface:ident ($vtbl:ident)
(interface $interface:ident ($vtbl:ident) [$iid:ident]
{$(
fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
),+}
Expand All @@ -52,8 +55,11 @@ macro_rules! RIDL {
((*self.lpVtbl).$method)(self $(,$p)*)
})+
}
impl ComInterface for $interface {
const IID: REFIID = &$iid;
}
};
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) {
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) [$iid:ident] {
}) => {
#[repr(C)] #[allow(missing_copy_implementations)]
pub struct $vtbl {
Expand All @@ -63,6 +69,9 @@ macro_rules! RIDL {
pub struct $interface {
pub lpVtbl: *const $vtbl
}
impl ComInterface for $interface {
const IID: REFIID = &$iid;
}
impl ::std::ops::Deref for $interface {
type Target = $crate::$pinterface;
#[inline]
Expand All @@ -77,7 +86,7 @@ macro_rules! RIDL {
}
}
};
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident)
(interface $interface:ident ($vtbl:ident) : $pinterface:ident ($pvtbl:ident) [$iid:ident]
{$(
fn $method:ident(&mut self $(,$p:ident : $t:ty)*) -> $rtr:ty
),+}
Expand All @@ -100,6 +109,9 @@ macro_rules! RIDL {
((*self.lpVtbl).$method)(self $(,$p)*)
})+
}
impl ComInterface for $interface {
const IID: REFIID = &$iid;
}
impl ::std::ops::Deref for $interface {
type Target = $crate::$pinterface;
#[inline]
Expand All @@ -116,11 +128,19 @@ macro_rules! RIDL {
};
}

// redefine some things from winapi
pub type IUnknown = ::winapi::IUnknown;
pub type IUnknownVtbl = ::winapi::IUnknownVtbl;
pub type IInspectable = ::winapi::IInspectable;
pub type IInspectableVtbl = ::winapi::IInspectableVtbl;

DEFINE_GUID!(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
DEFINE_GUID!(IID_IInspectable, 0xAF86E2E0, 0xB12D, 0x4c6a, 0x9C, 0x5A, 0xD7, 0xAA, 0x65, 0x10, 0x1E, 0x90);

impl ComInterface for IUnknown { const IID: REFIID = &IID_IUnknown; }
impl ComInterface for IInspectable { const IID: REFIID = &IID_IInspectable; }


fn main() {
unsafe {
let hres = RoInitialize(RO_INIT_MULTITHREADED);
Expand All @@ -134,7 +154,7 @@ unsafe fn run() {
let Windows_Devices_Midi_MidiOutPort: HString = "Windows.Devices.Midi.MidiOutPort".into();
let mut outPortStatics: ComPtr<IMidiOutPortStatics> = ComPtr::new(ptr::null_mut());
let hres = RoGetActivationFactory(Windows_Devices_Midi_MidiOutPort.get(), &IID_IMidiOutPortStatics, outPortStatics.get_address() as *mut *mut _ as *mut *mut VOID);
println!("HRESULT (RoGetActivationFactory) = {}", hres);
assert_eq!(hres, S_OK);
println!("outPortStatics: {:p}", outPortStatics);

//let mut hstring: HSTRING = ptr::null_mut();
Expand All @@ -156,13 +176,13 @@ unsafe fn run() {
println!("HRESULT (GetRuntimeClassName) = {:x}", hres);
println!("CLS: {}", className.to_string());

let mut asi = asyncOp.query_interface::<IAsyncInfo>(&IID_IAsyncInfo).unwrap();
let mut asi = asyncOp.query_interface::<IAsyncInfo>().unwrap();
println!("IAsyncInfo: {:p}, IAsyncOperation: {:p}", asi, asyncOp);

let unknown = asyncOp.query_interface::<IUnknown>(&IID_IUnknown).unwrap();
let unknown = asyncOp.query_interface::<IUnknown>().unwrap();
println!("IAsyncInfo: {:p}, IAsyncOperation: {:p}, IUnknown: {:p}", asi, asyncOp, unknown);

let unknown = asi.query_interface::<IUnknown>(&IID_IUnknown).unwrap();
let unknown = asi.query_interface::<IUnknown>().unwrap();
println!("IAsyncInfo: {:p}, IAsyncOperation: {:p}, IUnknown: {:p}", asi, asyncOp, unknown);

let mut id = 0;
Expand Down Expand Up @@ -194,7 +214,7 @@ unsafe fn run() {
assert!(deviceInformationCollection.get_Size(&mut count) == S_OK);
println!("Device Count: {}", count);

assert!(deviceInformationCollection.query_interface::<IIterable>(&IID_IIterable) == None);
assert!(deviceInformationCollection.query_interface::<IIterable>() == None);

let mut deviceInformation: ComPtr<IDeviceInformation> = ComPtr::new(ptr::null_mut());
let hres = deviceInformationCollection.GetAt(0, deviceInformation.get_address() as *mut _ as *mut *mut IInspectable);
Expand All @@ -219,11 +239,6 @@ unsafe fn run() {
use std::{ptr, mem};
use std::sync::atomic::Ordering;

DEFINE_GUID!(IID_IInspectable, 0xAF86E2E0, 0xB12D, 0x4c6a, 0x9C, 0x5A, 0xD7, 0xAA, 0x65, 0x10, 0x1E, 0x90);
DEFINE_GUID!(IID_IUnknown, 0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
DEFINE_GUID!(IID_IAgileObject, 0x94EA2B94, 0xE9CC, 0x49E0, 0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90);
DEFINE_GUID!(KEINE_AHNUNG, 0x4A458732, 0x527E, 0x5C73, 0x9A, 0x68, 0xA7, 0x3D, 0xA3, 0x70, 0xF7, 0x82);

// Custom COM component
struct MyIAsyncActionCompletedHandler {
pub lpVtbl: *const IAsyncActionCompletedHandlerVtbl,
Expand All @@ -246,6 +261,10 @@ unsafe extern "system" fn My_Invoke(this: *mut IAsyncActionCompletedHandler, _as

unsafe extern "system" fn My_QueryInterface(this: *mut IUnknown, vTableGuid: REFIID, ppv: *mut *mut VOID) -> HRESULT
{
// these are only needed here:
DEFINE_GUID!(IID_IAgileObject, 0x94EA2B94, 0xE9CC, 0x49E0, 0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90);
DEFINE_GUID!(KEINE_AHNUNG, 0x4A458732, 0x527E, 0x5C73, 0x9A, 0x68, 0xA7, 0x3D, 0xA3, 0x70, 0xF7, 0x82);

fn print_guid(guid: &::winapi::GUID) {
println!("{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
guid.Data1, guid.Data2, guid.Data3,
Expand Down Expand Up @@ -315,12 +334,12 @@ unsafe extern "system" fn My_Release(this: *mut IUnknown) -> ULONG
}

DEFINE_GUID!(IID_IStringable, 2520162132, 36534, 18672, 171, 206, 193, 178, 17, 230, 39, 195);
RIDL!{interface IStringable(IStringableVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IStringable(IStringableVtbl): IInspectable(IInspectableVtbl) [IID_IStringable] {
fn ToString(&mut self, value: *mut HSTRING) -> HRESULT
}}

DEFINE_GUID!(IID_IAsyncInfo, 0x00000036,0x0000,0x0000,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
RIDL!{interface IAsyncInfo(IAsyncInfoVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IAsyncInfo(IAsyncInfoVtbl): IInspectable(IInspectableVtbl) [IID_IAsyncInfo] {
fn get_Id(&mut self, id: *mut u32) -> HRESULT,
fn get_Status(&mut self, status: *mut AsyncStatus) -> HRESULT,
fn get_ErrorCode(&mut self, errorCode: *mut HRESULT) -> HRESULT,
Expand All @@ -329,21 +348,21 @@ RIDL!{interface IAsyncInfo(IAsyncInfoVtbl): IInspectable(IInspectableVtbl) {
}}

DEFINE_GUID!(IID_IAsyncAction, 0x5A648006,0x843A,0x4DA9,0x86,0x5B,0x9D,0x26,0xE5,0xDF,0xAD,0x7B);
RIDL!{interface IAsyncAction(IAsyncActionVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IAsyncAction(IAsyncActionVtbl): IInspectable(IInspectableVtbl) [IID_IAsyncAction] {
fn put_Completed(&mut self, handler: *mut IAsyncActionCompletedHandler) -> HRESULT,
fn get_Completed(&mut self, handler: *mut *mut IAsyncActionCompletedHandler) -> HRESULT,
fn GetResults(&mut self) -> HRESULT
}}

// see winrt/windows.foundation.h
DEFINE_GUID!(IID_IAsyncActionCompletedHandler, 0xA4ED5C81,0x76C9,0x40BD,0x8B,0xE6,0xB1,0xD9,0x0F,0xB2,0x0A,0xE7);
RIDL!{interface IAsyncActionCompletedHandler(IAsyncActionCompletedHandlerVtbl): IUnknown(IUnknownVtbl) {
RIDL!{interface IAsyncActionCompletedHandler(IAsyncActionCompletedHandlerVtbl): IUnknown(IUnknownVtbl) [IID_IAsyncActionCompletedHandler] {
fn Invoke(&mut self, asyncAction: *mut IAsyncAction, status: AsyncStatus) -> HRESULT
}}

// TODO: this should be generic in the result type
DEFINE_GUID!(IID_IAsyncOperation, 0x9fc2b0bb, 0xe446, 0x44e2, 0xaa,0x61,0x9c,0xab,0x8f,0x63,0x6a,0xf2);
RIDL!{interface IAsyncOperation(IAsyncOperationVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IAsyncOperation(IAsyncOperationVtbl): IInspectable(IInspectableVtbl) [IID_IAsyncOperation] {
fn put_Completed(&mut self, handler: *mut IAsyncActionCompletedHandler/*<TResult>*/) -> HRESULT,
fn get_Completed(&mut self, handler: *mut *mut IAsyncActionCompletedHandler/*<TResult>*/) -> HRESULT,
fn GetResults(&mut self, results: *mut *mut /*TResult*/IInspectable) -> HRESULT
Expand All @@ -360,13 +379,13 @@ pub enum AsyncStatus {
}

DEFINE_GUID!(IID_IMidiOutPortStatics, 106742761, 3976, 17547, 155, 100, 169, 88, 38, 198, 91, 143);
RIDL!{interface IMidiOutPortStatics(IMidiOutPortStaticsVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IMidiOutPortStatics(IMidiOutPortStaticsVtbl): IInspectable(IInspectableVtbl) [IID_IMidiOutPortStatics] {
fn FromIdAsync(&mut self, deviceId: HSTRING, asyncOp: *mut *mut IAsyncOperation/*<IMidiOutPort>*/) -> HRESULT,
fn GetDeviceSelector(&mut self, value: *const HSTRING) -> HRESULT
}}

DEFINE_GUID!(IID_IDeviceInformationStatics, 3246329870, 14918, 19064, 128, 19, 118, 157, 201, 185, 115, 144);
RIDL!{interface IDeviceInformationStatics(IDeviceInformationStaticsVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IDeviceInformationStatics(IDeviceInformationStaticsVtbl): IInspectable(IInspectableVtbl) [IID_IDeviceInformationStatics] {
fn __CreateFromIdAsync(&mut self) -> HRESULT,
fn __CreateFromIdAsyncAdditionalProperties(&mut self) -> HRESULT,
fn __FindAllAsync(&mut self) -> HRESULT,
Expand All @@ -380,12 +399,12 @@ RIDL!{interface IDeviceInformationStatics(IDeviceInformationStaticsVtbl): IInspe
}}

DEFINE_GUID!(IID_IIterable, 4205151722, 25108, 16919, 175, 218, 127, 70, 222, 88, 105, 179);
RIDL!{interface IIterable(IIterableVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IIterable(IIterableVtbl): IInspectable(IInspectableVtbl) [IID_IIterable] {
fn First(&mut self, first: *mut *mut IIterator/*<T>*/) -> HRESULT
}}

DEFINE_GUID!(IID_IIterator, 1786374243, 17152, 17818, 153, 102, 203, 182, 96, 150, 62, 225);
RIDL!{interface IIterator(IIteratorVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IIterator(IIteratorVtbl): IInspectable(IInspectableVtbl) [IID_IIterator] {
fn get_Current(&mut self, current: *mut VOID /*T*/) -> HRESULT,
fn get_HasCurrent(&mut self, hasCurrent: *mut BOOL) -> HRESULT,
fn MoveNext(&mut self, hasCurrent: *mut BOOL) -> HRESULT
Expand All @@ -394,15 +413,15 @@ RIDL!{interface IIterator(IIteratorVtbl): IInspectable(IInspectableVtbl) {

DEFINE_GUID!(IID_IVectorView, 3152149068, 45283, 17795, 186, 239, 31, 27, 46, 72, 62, 86);
// NOTE: For some reason this does NOT actually inherit from IIterable as the metadata would suggest
RIDL!{interface IVectorView(IVectorViewVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IVectorView(IVectorViewVtbl): IInspectable(IInspectableVtbl) [IID_IVectorView] {
fn GetAt(&mut self, index: UINT, item: *mut *mut IInspectable /*T*/) -> HRESULT,
fn get_Size(&mut self, size: *mut UINT) -> HRESULT,
fn IndexOf(&mut self, value: VOID /*T*/, index: *mut UINT, found: *mut BOOL) -> HRESULT
// fn GetMany...
}}

DEFINE_GUID!(IID_IDeviceInformation, 2879454101, 17304, 18589, 142, 68, 230, 19, 9, 39, 1, 31);
RIDL!{interface IDeviceInformation(IDeviceInformationVtbl): IInspectable(IInspectableVtbl) {
RIDL!{interface IDeviceInformation(IDeviceInformationVtbl): IInspectable(IInspectableVtbl) [IID_IDeviceInformation] {
fn get_Id(&mut self, value: *mut HSTRING) -> HRESULT,
fn get_Name(&mut self, value: *mut HSTRING) -> HRESULT
// ...
Expand Down

0 comments on commit 7c06074

Please sign in to comment.