diff --git a/crates/samples/windows/bits/src/main.rs b/crates/samples/windows/bits/src/main.rs index 601f845951..6f11b745d7 100644 --- a/crates/samples/windows/bits/src/main.rs +++ b/crates/samples/windows/bits/src/main.rs @@ -39,7 +39,7 @@ fn main() -> Result<()> { struct Callback; impl IBackgroundCopyCallback_Impl for Callback_Impl { - fn JobTransferred(&self, job: Option<&IBackgroundCopyJob>) -> Result<()> { + fn JobTransferred(&self, job: Ref) -> Result<()> { let job = job.unwrap(); unsafe { job.Complete()? }; println!("done"); @@ -48,8 +48,8 @@ impl IBackgroundCopyCallback_Impl for Callback_Impl { fn JobError( &self, - job: Option<&IBackgroundCopyJob>, - error: Option<&IBackgroundCopyError>, + job: Ref, + error: Ref, ) -> Result<()> { let job = job.unwrap(); let error = error.unwrap(); @@ -60,7 +60,7 @@ impl IBackgroundCopyCallback_Impl for Callback_Impl { std::process::exit(0); } - fn JobModification(&self, _: Option<&IBackgroundCopyJob>, _: u32) -> Result<()> { + fn JobModification(&self, _: Ref, _: u32) -> Result<()> { Ok(()) } } diff --git a/crates/samples/windows/core_app/src/main.rs b/crates/samples/windows/core_app/src/main.rs index d8c6bf58d5..ebab819b24 100644 --- a/crates/samples/windows/core_app/src/main.rs +++ b/crates/samples/windows/core_app/src/main.rs @@ -25,7 +25,7 @@ struct CoreAppView(); #[allow(non_snake_case)] impl IFrameworkView_Impl for CoreAppView_Impl { - fn Initialize(&self, _: Option<&CoreApplicationView>) -> Result<()> { + fn Initialize(&self, _: Ref) -> Result<()> { Ok(()) } @@ -47,7 +47,7 @@ impl IFrameworkView_Impl for CoreAppView_Impl { Ok(()) } - fn SetWindow(&self, _: Option<&CoreWindow>) -> Result<()> { + fn SetWindow(&self, _: Ref) -> Result<()> { Ok(()) } } diff --git a/crates/tests/bindgen/src/delegate_generic.rs b/crates/tests/bindgen/src/delegate_generic.rs index 0b64d43f2f..8b336dadb6 100644 --- a/crates/tests/bindgen/src/delegate_generic.rs +++ b/crates/tests/bindgen/src/delegate_generic.rs @@ -26,7 +26,7 @@ impl windows_core::RuntimeType for Event impl EventHandler { pub fn new< F: FnMut( - Option<&windows_core::IInspectable>, + windows_core::Ref<'_, windows_core::IInspectable>, &>::Default, ) -> windows_core::Result<()> + Send @@ -74,7 +74,7 @@ where struct EventHandlerBox< T, F: FnMut( - Option<&windows_core::IInspectable>, + windows_core::Ref<'_, windows_core::IInspectable>, &>::Default, ) -> windows_core::Result<()> + Send @@ -89,7 +89,7 @@ struct EventHandlerBox< impl< T: windows_core::RuntimeType + 'static, F: FnMut( - Option<&windows_core::IInspectable>, + windows_core::Ref<'_, windows_core::IInspectable>, &>::Default, ) -> windows_core::Result<()> + Send @@ -148,7 +148,7 @@ impl< ) -> windows_core::HRESULT { let this = &mut *(this as *mut *mut core::ffi::c_void as *mut Self); (this.invoke)( - windows_core::from_raw_borrowed(&sender), + core::mem::transmute_copy(&sender), core::mem::transmute(&args), ) .into() diff --git a/crates/tests/bindgen/src/lib.rs b/crates/tests/bindgen/src/lib.rs index f91fef82e1..6850e70cf6 100644 --- a/crates/tests/bindgen/src/lib.rs +++ b/crates/tests/bindgen/src/lib.rs @@ -61,6 +61,7 @@ pub mod interface_sys; pub mod interface_sys_no_core; pub mod multi; pub mod multi_sys; +pub mod ref_params; pub mod reference_async_action; pub mod reference_async_action_reference_namespace; pub mod reference_async_action_reference_type; diff --git a/crates/tests/bindgen/src/ref_params.rs b/crates/tests/bindgen/src/ref_params.rs new file mode 100644 index 0000000000..71015816b2 --- /dev/null +++ b/crates/tests/bindgen/src/ref_params.rs @@ -0,0 +1,1203 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] + +windows_core::imp::define_interface!( + IDynamicConceptProviderConcept, + IDynamicConceptProviderConcept_Vtbl, + 0x95a7f7dd_602e_483f_9d06_a15c0ee13174 +); +windows_core::imp::interface_hierarchy!(IDynamicConceptProviderConcept, windows_core::IUnknown); +impl IDynamicConceptProviderConcept { + pub unsafe fn GetConcept( + &self, + contextobject: P0, + conceptid: *const windows_core::GUID, + conceptinterface: *mut Option, + conceptmetadata: Option<*mut Option>, + hasconcept: *mut bool, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetConcept)( + windows_core::Interface::as_raw(self), + contextobject.param().abi(), + conceptid, + core::mem::transmute(conceptinterface), + core::mem::transmute(conceptmetadata.unwrap_or(core::mem::zeroed())), + core::mem::transmute(hasconcept), + ) + .ok() + } + pub unsafe fn SetConcept( + &self, + contextobject: P0, + conceptid: *const windows_core::GUID, + conceptinterface: P2, + conceptmetadata: P3, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + P2: windows_core::Param, + P3: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetConcept)( + windows_core::Interface::as_raw(self), + contextobject.param().abi(), + conceptid, + conceptinterface.param().abi(), + conceptmetadata.param().abi(), + ) + .ok() + } + pub unsafe fn NotifyParent(&self, parentmodel: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).NotifyParent)( + windows_core::Interface::as_raw(self), + parentmodel.param().abi(), + ) + .ok() + } + pub unsafe fn NotifyParentChange(&self, parentmodel: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).NotifyParentChange)( + windows_core::Interface::as_raw(self), + parentmodel.param().abi(), + ) + .ok() + } + pub unsafe fn NotifyDestruct(&self) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).NotifyDestruct)(windows_core::Interface::as_raw( + self, + )) + .ok() + } +} +#[repr(C)] +pub struct IDynamicConceptProviderConcept_Vtbl { + pub base__: windows_core::IUnknown_Vtbl, + pub GetConcept: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + *mut bool, + ) -> windows_core::HRESULT, + pub SetConcept: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub NotifyParent: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub NotifyParentChange: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub NotifyDestruct: unsafe extern "system" fn(*mut core::ffi::c_void) -> windows_core::HRESULT, +} +pub trait IDynamicConceptProviderConcept_Impl: windows_core::IUnknownImpl { + fn GetConcept( + &self, + contextobject: windows_core::Ref<'_, IModelObject>, + conceptid: *const windows_core::GUID, + conceptinterface: windows_core::OutRef<'_, windows_core::IUnknown>, + conceptmetadata: windows_core::OutRef<'_, IKeyStore>, + hasconcept: *mut bool, + ) -> windows_core::Result<()>; + fn SetConcept( + &self, + contextobject: windows_core::Ref<'_, IModelObject>, + conceptid: *const windows_core::GUID, + conceptinterface: windows_core::Ref<'_, windows_core::IUnknown>, + conceptmetadata: windows_core::Ref<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn NotifyParent( + &self, + parentmodel: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn NotifyParentChange( + &self, + parentmodel: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn NotifyDestruct(&self) -> windows_core::Result<()>; +} +impl IDynamicConceptProviderConcept_Vtbl { + pub const fn new() -> Self { + unsafe extern "system" fn GetConcept< + Identity: IDynamicConceptProviderConcept_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + contextobject: *mut core::ffi::c_void, + conceptid: *const windows_core::GUID, + conceptinterface: *mut *mut core::ffi::c_void, + conceptmetadata: *mut *mut core::ffi::c_void, + hasconcept: *mut bool, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IDynamicConceptProviderConcept_Impl::GetConcept( + this, + core::mem::transmute_copy(&contextobject), + core::mem::transmute_copy(&conceptid), + core::mem::transmute_copy(&conceptinterface), + core::mem::transmute_copy(&conceptmetadata), + core::mem::transmute_copy(&hasconcept), + ) + .into() + } + unsafe extern "system" fn SetConcept< + Identity: IDynamicConceptProviderConcept_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + contextobject: *mut core::ffi::c_void, + conceptid: *const windows_core::GUID, + conceptinterface: *mut core::ffi::c_void, + conceptmetadata: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IDynamicConceptProviderConcept_Impl::SetConcept( + this, + core::mem::transmute_copy(&contextobject), + core::mem::transmute_copy(&conceptid), + core::mem::transmute_copy(&conceptinterface), + core::mem::transmute_copy(&conceptmetadata), + ) + .into() + } + unsafe extern "system" fn NotifyParent< + Identity: IDynamicConceptProviderConcept_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + parentmodel: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IDynamicConceptProviderConcept_Impl::NotifyParent( + this, + core::mem::transmute_copy(&parentmodel), + ) + .into() + } + unsafe extern "system" fn NotifyParentChange< + Identity: IDynamicConceptProviderConcept_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + parentmodel: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IDynamicConceptProviderConcept_Impl::NotifyParentChange( + this, + core::mem::transmute_copy(&parentmodel), + ) + .into() + } + unsafe extern "system" fn NotifyDestruct< + Identity: IDynamicConceptProviderConcept_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IDynamicConceptProviderConcept_Impl::NotifyDestruct(this).into() + } + Self { + base__: windows_core::IUnknown_Vtbl::new::(), + GetConcept: GetConcept::, + SetConcept: SetConcept::, + NotifyParent: NotifyParent::, + NotifyParentChange: NotifyParentChange::, + NotifyDestruct: NotifyDestruct::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +impl windows_core::RuntimeName for IDynamicConceptProviderConcept {} +windows_core::imp::define_interface!( + IKeyStore, + IKeyStore_Vtbl, + 0x0fc7557d_401d_4fca_9365_da1e9850697c +); +windows_core::imp::interface_hierarchy!(IKeyStore, windows_core::IUnknown); +impl IKeyStore { + pub unsafe fn GetKey( + &self, + key: P0, + object: Option<*mut Option>, + metadata: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetKey)( + windows_core::Interface::as_raw(self), + key.param().abi(), + core::mem::transmute(object.unwrap_or(core::mem::zeroed())), + core::mem::transmute(metadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn SetKey( + &self, + key: P0, + object: P1, + metadata: P2, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + P2: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetKey)( + windows_core::Interface::as_raw(self), + key.param().abi(), + object.param().abi(), + metadata.param().abi(), + ) + .ok() + } + pub unsafe fn GetKeyValue( + &self, + key: P0, + object: Option<*mut Option>, + metadata: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetKeyValue)( + windows_core::Interface::as_raw(self), + key.param().abi(), + core::mem::transmute(object.unwrap_or(core::mem::zeroed())), + core::mem::transmute(metadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn SetKeyValue(&self, key: P0, object: P1) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetKeyValue)( + windows_core::Interface::as_raw(self), + key.param().abi(), + object.param().abi(), + ) + .ok() + } + pub unsafe fn ClearKeys(&self) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).ClearKeys)(windows_core::Interface::as_raw(self)) + .ok() + } +} +#[repr(C)] +pub struct IKeyStore_Vtbl { + pub base__: windows_core::IUnknown_Vtbl, + pub GetKey: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetKey: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetKeyValue: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetKeyValue: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub ClearKeys: unsafe extern "system" fn(*mut core::ffi::c_void) -> windows_core::HRESULT, +} +pub trait IKeyStore_Impl: windows_core::IUnknownImpl { + fn GetKey( + &self, + key: &windows_core::PCWSTR, + object: windows_core::OutRef<'_, IModelObject>, + metadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn SetKey( + &self, + key: &windows_core::PCWSTR, + object: windows_core::Ref<'_, IModelObject>, + metadata: windows_core::Ref<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn GetKeyValue( + &self, + key: &windows_core::PCWSTR, + object: windows_core::OutRef<'_, IModelObject>, + metadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn SetKeyValue( + &self, + key: &windows_core::PCWSTR, + object: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn ClearKeys(&self) -> windows_core::Result<()>; +} +impl IKeyStore_Vtbl { + pub const fn new() -> Self { + unsafe extern "system" fn GetKey( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut *mut core::ffi::c_void, + metadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IKeyStore_Impl::GetKey( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn SetKey( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut core::ffi::c_void, + metadata: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IKeyStore_Impl::SetKey( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn GetKeyValue( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut *mut core::ffi::c_void, + metadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IKeyStore_Impl::GetKeyValue( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn SetKeyValue( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IKeyStore_Impl::SetKeyValue( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + ) + .into() + } + unsafe extern "system" fn ClearKeys( + this: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IKeyStore_Impl::ClearKeys(this).into() + } + Self { + base__: windows_core::IUnknown_Vtbl::new::(), + GetKey: GetKey::, + SetKey: SetKey::, + GetKeyValue: GetKeyValue::, + SetKeyValue: SetKeyValue::, + ClearKeys: ClearKeys::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +impl windows_core::RuntimeName for IKeyStore {} +windows_core::imp::define_interface!( + IModelObject, + IModelObject_Vtbl, + 0xe28c7893_3f4b_4b96_baca_293cdc55f45d +); +windows_core::imp::interface_hierarchy!(IModelObject, windows_core::IUnknown); +impl IModelObject { + pub unsafe fn GetKeyValue( + &self, + key: P0, + object: Option<*mut Option>, + metadata: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetKeyValue)( + windows_core::Interface::as_raw(self), + key.param().abi(), + core::mem::transmute(object.unwrap_or(core::mem::zeroed())), + core::mem::transmute(metadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn SetKeyValue(&self, key: P0, object: P1) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetKeyValue)( + windows_core::Interface::as_raw(self), + key.param().abi(), + object.param().abi(), + ) + .ok() + } + pub unsafe fn Dereference(&self) -> windows_core::Result { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(self).Dereference)( + windows_core::Interface::as_raw(self), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + pub unsafe fn TryCastToRuntimeType(&self) -> windows_core::Result { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(self).TryCastToRuntimeType)( + windows_core::Interface::as_raw(self), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + pub unsafe fn GetConcept( + &self, + conceptid: *const windows_core::GUID, + conceptinterface: *mut Option, + conceptmetadata: Option<*mut Option>, + ) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).GetConcept)( + windows_core::Interface::as_raw(self), + conceptid, + core::mem::transmute(conceptinterface), + core::mem::transmute(conceptmetadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn GetNumberOfParentModels(&self) -> windows_core::Result { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(self).GetNumberOfParentModels)( + windows_core::Interface::as_raw(self), + &mut result__, + ) + .map(|| result__) + } + pub unsafe fn GetParentModel( + &self, + i: u64, + model: *mut Option, + contextobject: *mut Option, + ) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).GetParentModel)( + windows_core::Interface::as_raw(self), + i, + core::mem::transmute(model), + core::mem::transmute(contextobject), + ) + .ok() + } + pub unsafe fn AddParentModel( + &self, + model: P0, + contextobject: P1, + r#override: u8, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + { + (windows_core::Interface::vtable(self).AddParentModel)( + windows_core::Interface::as_raw(self), + model.param().abi(), + contextobject.param().abi(), + r#override, + ) + .ok() + } + pub unsafe fn RemoveParentModel(&self, model: P0) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).RemoveParentModel)( + windows_core::Interface::as_raw(self), + model.param().abi(), + ) + .ok() + } + pub unsafe fn GetKey( + &self, + key: P0, + object: Option<*mut Option>, + metadata: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetKey)( + windows_core::Interface::as_raw(self), + key.param().abi(), + core::mem::transmute(object.unwrap_or(core::mem::zeroed())), + core::mem::transmute(metadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn GetKeyReference( + &self, + key: P0, + objectreference: Option<*mut Option>, + metadata: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).GetKeyReference)( + windows_core::Interface::as_raw(self), + key.param().abi(), + core::mem::transmute(objectreference.unwrap_or(core::mem::zeroed())), + core::mem::transmute(metadata.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn SetKey( + &self, + key: P0, + object: P1, + metadata: P2, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + P2: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetKey)( + windows_core::Interface::as_raw(self), + key.param().abi(), + object.param().abi(), + metadata.param().abi(), + ) + .ok() + } + pub unsafe fn ClearKeys(&self) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).ClearKeys)(windows_core::Interface::as_raw(self)) + .ok() + } + pub unsafe fn SetConcept( + &self, + conceptid: *const windows_core::GUID, + conceptinterface: P1, + conceptmetadata: P2, + ) -> windows_core::Result<()> + where + P1: windows_core::Param, + P2: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetConcept)( + windows_core::Interface::as_raw(self), + conceptid, + conceptinterface.param().abi(), + conceptmetadata.param().abi(), + ) + .ok() + } + pub unsafe fn ClearConcepts(&self) -> windows_core::Result<()> { + (windows_core::Interface::vtable(self).ClearConcepts)(windows_core::Interface::as_raw(self)) + .ok() + } + pub unsafe fn SetContextForDataModel( + &self, + datamodelobject: P0, + context: P1, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + P1: windows_core::Param, + { + (windows_core::Interface::vtable(self).SetContextForDataModel)( + windows_core::Interface::as_raw(self), + datamodelobject.param().abi(), + context.param().abi(), + ) + .ok() + } + pub unsafe fn GetContextForDataModel( + &self, + datamodelobject: P0, + ) -> windows_core::Result + where + P0: windows_core::Param, + { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(self).GetContextForDataModel)( + windows_core::Interface::as_raw(self), + datamodelobject.param().abi(), + &mut result__, + ) + .and_then(|| windows_core::Type::from_abi(result__)) + } + pub unsafe fn Compare( + &self, + other: P0, + ppresult: Option<*mut Option>, + ) -> windows_core::Result<()> + where + P0: windows_core::Param, + { + (windows_core::Interface::vtable(self).Compare)( + windows_core::Interface::as_raw(self), + other.param().abi(), + core::mem::transmute(ppresult.unwrap_or(core::mem::zeroed())), + ) + .ok() + } + pub unsafe fn IsEqualTo(&self, other: P0) -> windows_core::Result + where + P0: windows_core::Param, + { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(self).IsEqualTo)( + windows_core::Interface::as_raw(self), + other.param().abi(), + &mut result__, + ) + .map(|| result__) + } +} +#[repr(C)] +pub struct IModelObject_Vtbl { + pub base__: windows_core::IUnknown_Vtbl, + GetContext: usize, + GetKind: usize, + GetIntrinsicValue: usize, + GetIntrinsicValueAs: usize, + pub GetKeyValue: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetKeyValue: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + EnumerateKeyValues: usize, + GetRawValue: usize, + EnumerateRawValues: usize, + pub Dereference: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub TryCastToRuntimeType: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetConcept: unsafe extern "system" fn( + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + GetLocation: usize, + GetTypeInfo: usize, + GetTargetInfo: usize, + pub GetNumberOfParentModels: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut u64) -> windows_core::HRESULT, + pub GetParentModel: unsafe extern "system" fn( + *mut core::ffi::c_void, + u64, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub AddParentModel: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + u8, + ) -> windows_core::HRESULT, + pub RemoveParentModel: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetKey: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetKeyReference: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub SetKey: unsafe extern "system" fn( + *mut core::ffi::c_void, + windows_core::PCWSTR, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub ClearKeys: unsafe extern "system" fn(*mut core::ffi::c_void) -> windows_core::HRESULT, + EnumerateKeys: usize, + EnumerateKeyReferences: usize, + pub SetConcept: unsafe extern "system" fn( + *mut core::ffi::c_void, + *const windows_core::GUID, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub ClearConcepts: unsafe extern "system" fn(*mut core::ffi::c_void) -> windows_core::HRESULT, + GetRawReference: usize, + EnumerateRawReferences: usize, + pub SetContextForDataModel: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub GetContextForDataModel: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub Compare: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub IsEqualTo: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut bool, + ) -> windows_core::HRESULT, +} +pub trait IModelObject_Impl: windows_core::IUnknownImpl { + fn GetKeyValue( + &self, + key: &windows_core::PCWSTR, + object: windows_core::OutRef<'_, IModelObject>, + metadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn SetKeyValue( + &self, + key: &windows_core::PCWSTR, + object: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn Dereference(&self) -> windows_core::Result; + fn TryCastToRuntimeType(&self) -> windows_core::Result; + fn GetConcept( + &self, + conceptid: *const windows_core::GUID, + conceptinterface: windows_core::OutRef<'_, windows_core::IUnknown>, + conceptmetadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn GetNumberOfParentModels(&self) -> windows_core::Result; + fn GetParentModel( + &self, + i: u64, + model: windows_core::OutRef<'_, IModelObject>, + contextobject: windows_core::OutRef<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn AddParentModel( + &self, + model: windows_core::Ref<'_, IModelObject>, + contextobject: windows_core::Ref<'_, IModelObject>, + r#override: u8, + ) -> windows_core::Result<()>; + fn RemoveParentModel( + &self, + model: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn GetKey( + &self, + key: &windows_core::PCWSTR, + object: windows_core::OutRef<'_, IModelObject>, + metadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn GetKeyReference( + &self, + key: &windows_core::PCWSTR, + objectreference: windows_core::OutRef<'_, IModelObject>, + metadata: windows_core::OutRef<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn SetKey( + &self, + key: &windows_core::PCWSTR, + object: windows_core::Ref<'_, IModelObject>, + metadata: windows_core::Ref<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn ClearKeys(&self) -> windows_core::Result<()>; + fn SetConcept( + &self, + conceptid: *const windows_core::GUID, + conceptinterface: windows_core::Ref<'_, windows_core::IUnknown>, + conceptmetadata: windows_core::Ref<'_, IKeyStore>, + ) -> windows_core::Result<()>; + fn ClearConcepts(&self) -> windows_core::Result<()>; + fn SetContextForDataModel( + &self, + datamodelobject: windows_core::Ref<'_, IModelObject>, + context: windows_core::Ref<'_, windows_core::IUnknown>, + ) -> windows_core::Result<()>; + fn GetContextForDataModel( + &self, + datamodelobject: windows_core::Ref<'_, IModelObject>, + ) -> windows_core::Result; + fn Compare( + &self, + other: windows_core::Ref<'_, IModelObject>, + ppresult: windows_core::OutRef<'_, IModelObject>, + ) -> windows_core::Result<()>; + fn IsEqualTo(&self, other: windows_core::Ref<'_, IModelObject>) -> windows_core::Result; +} +impl IModelObject_Vtbl { + pub const fn new() -> Self { + unsafe extern "system" fn GetKeyValue( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut *mut core::ffi::c_void, + metadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::GetKeyValue( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn SetKeyValue( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::SetKeyValue( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + ) + .into() + } + unsafe extern "system" fn Dereference( + this: *mut core::ffi::c_void, + object: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IModelObject_Impl::Dereference(this) { + Ok(ok__) => { + object.write(core::mem::transmute(ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn TryCastToRuntimeType< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + runtimetypedobject: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IModelObject_Impl::TryCastToRuntimeType(this) { + Ok(ok__) => { + runtimetypedobject.write(core::mem::transmute(ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn GetConcept( + this: *mut core::ffi::c_void, + conceptid: *const windows_core::GUID, + conceptinterface: *mut *mut core::ffi::c_void, + conceptmetadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::GetConcept( + this, + core::mem::transmute_copy(&conceptid), + core::mem::transmute_copy(&conceptinterface), + core::mem::transmute_copy(&conceptmetadata), + ) + .into() + } + unsafe extern "system" fn GetNumberOfParentModels< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + nummodels: *mut u64, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IModelObject_Impl::GetNumberOfParentModels(this) { + Ok(ok__) => { + nummodels.write(core::mem::transmute(ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn GetParentModel< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + i: u64, + model: *mut *mut core::ffi::c_void, + contextobject: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::GetParentModel( + this, + core::mem::transmute_copy(&i), + core::mem::transmute_copy(&model), + core::mem::transmute_copy(&contextobject), + ) + .into() + } + unsafe extern "system" fn AddParentModel< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + model: *mut core::ffi::c_void, + contextobject: *mut core::ffi::c_void, + r#override: u8, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::AddParentModel( + this, + core::mem::transmute_copy(&model), + core::mem::transmute_copy(&contextobject), + core::mem::transmute_copy(&r#override), + ) + .into() + } + unsafe extern "system" fn RemoveParentModel< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + model: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::RemoveParentModel(this, core::mem::transmute_copy(&model)).into() + } + unsafe extern "system" fn GetKey( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut *mut core::ffi::c_void, + metadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::GetKey( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn GetKeyReference< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + objectreference: *mut *mut core::ffi::c_void, + metadata: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::GetKeyReference( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&objectreference), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn SetKey( + this: *mut core::ffi::c_void, + key: windows_core::PCWSTR, + object: *mut core::ffi::c_void, + metadata: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::SetKey( + this, + core::mem::transmute(&key), + core::mem::transmute_copy(&object), + core::mem::transmute_copy(&metadata), + ) + .into() + } + unsafe extern "system" fn ClearKeys( + this: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::ClearKeys(this).into() + } + unsafe extern "system" fn SetConcept( + this: *mut core::ffi::c_void, + conceptid: *const windows_core::GUID, + conceptinterface: *mut core::ffi::c_void, + conceptmetadata: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::SetConcept( + this, + core::mem::transmute_copy(&conceptid), + core::mem::transmute_copy(&conceptinterface), + core::mem::transmute_copy(&conceptmetadata), + ) + .into() + } + unsafe extern "system" fn ClearConcepts< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::ClearConcepts(this).into() + } + unsafe extern "system" fn SetContextForDataModel< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + datamodelobject: *mut core::ffi::c_void, + context: *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::SetContextForDataModel( + this, + core::mem::transmute_copy(&datamodelobject), + core::mem::transmute_copy(&context), + ) + .into() + } + unsafe extern "system" fn GetContextForDataModel< + Identity: IModelObject_Impl, + const OFFSET: isize, + >( + this: *mut core::ffi::c_void, + datamodelobject: *mut core::ffi::c_void, + context: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IModelObject_Impl::GetContextForDataModel( + this, + core::mem::transmute_copy(&datamodelobject), + ) { + Ok(ok__) => { + context.write(core::mem::transmute(ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn Compare( + this: *mut core::ffi::c_void, + other: *mut core::ffi::c_void, + ppresult: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + IModelObject_Impl::Compare( + this, + core::mem::transmute_copy(&other), + core::mem::transmute_copy(&ppresult), + ) + .into() + } + unsafe extern "system" fn IsEqualTo( + this: *mut core::ffi::c_void, + other: *mut core::ffi::c_void, + equal: *mut bool, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match IModelObject_Impl::IsEqualTo(this, core::mem::transmute_copy(&other)) { + Ok(ok__) => { + equal.write(core::mem::transmute(ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + Self { + base__: windows_core::IUnknown_Vtbl::new::(), + GetContext: 0, + GetKind: 0, + GetIntrinsicValue: 0, + GetIntrinsicValueAs: 0, + GetKeyValue: GetKeyValue::, + SetKeyValue: SetKeyValue::, + EnumerateKeyValues: 0, + GetRawValue: 0, + EnumerateRawValues: 0, + Dereference: Dereference::, + TryCastToRuntimeType: TryCastToRuntimeType::, + GetConcept: GetConcept::, + GetLocation: 0, + GetTypeInfo: 0, + GetTargetInfo: 0, + GetNumberOfParentModels: GetNumberOfParentModels::, + GetParentModel: GetParentModel::, + AddParentModel: AddParentModel::, + RemoveParentModel: RemoveParentModel::, + GetKey: GetKey::, + GetKeyReference: GetKeyReference::, + SetKey: SetKey::, + ClearKeys: ClearKeys::, + EnumerateKeys: 0, + EnumerateKeyReferences: 0, + SetConcept: SetConcept::, + ClearConcepts: ClearConcepts::, + GetRawReference: 0, + EnumerateRawReferences: 0, + SetContextForDataModel: SetContextForDataModel::, + GetContextForDataModel: GetContextForDataModel::, + Compare: Compare::, + IsEqualTo: IsEqualTo::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +impl windows_core::RuntimeName for IModelObject {} diff --git a/crates/tests/bindgen/src/reference_async_action_reference_namespace.rs b/crates/tests/bindgen/src/reference_async_action_reference_namespace.rs index 7ca8c8eae3..57fcf12956 100644 --- a/crates/tests/bindgen/src/reference_async_action_reference_namespace.rs +++ b/crates/tests/bindgen/src/reference_async_action_reference_namespace.rs @@ -113,7 +113,7 @@ impl windows_core::RuntimeName for IAsyncAction { pub trait IAsyncAction_Impl: windows::Foundation::IAsyncInfo_Impl { fn SetCompleted( &self, - handler: Option<&windows::Foundation::AsyncActionCompletedHandler>, + handler: windows_core::Ref<'_, windows::Foundation::AsyncActionCompletedHandler>, ) -> windows_core::Result<()>; fn Completed(&self) -> windows_core::Result; fn GetResults(&self) -> windows_core::Result<()>; @@ -125,7 +125,7 @@ impl IAsyncAction_Vtbl { handler: *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - IAsyncAction_Impl::SetCompleted(this, windows_core::from_raw_borrowed(&handler)).into() + IAsyncAction_Impl::SetCompleted(this, core::mem::transmute_copy(&handler)).into() } unsafe extern "system" fn Completed( this: *mut core::ffi::c_void, diff --git a/crates/tests/bindgen/src/struct_with_cpp_interface.rs b/crates/tests/bindgen/src/struct_with_cpp_interface.rs index abd128100e..c8849d475b 100644 --- a/crates/tests/bindgen/src/struct_with_cpp_interface.rs +++ b/crates/tests/bindgen/src/struct_with_cpp_interface.rs @@ -190,7 +190,7 @@ pub trait ID3D12Object_Impl: windows_core::IUnknownImpl { fn SetPrivateDataInterface( &self, guid: *const windows_core::GUID, - pdata: Option<&windows_core::IUnknown>, + pdata: windows_core::Ref<'_, windows_core::IUnknown>, ) -> windows_core::Result<()>; fn SetName(&self, name: &windows_core::PCWSTR) -> windows_core::Result<()>; } @@ -244,7 +244,7 @@ impl ID3D12Object_Vtbl { ID3D12Object_Impl::SetPrivateDataInterface( this, core::mem::transmute_copy(&guid), - windows_core::from_raw_borrowed(&pdata), + core::mem::transmute_copy(&pdata), ) .into() } diff --git a/crates/tests/bindgen/tests/ref_params.rs b/crates/tests/bindgen/tests/ref_params.rs new file mode 100644 index 0000000000..c77013869f --- /dev/null +++ b/crates/tests/bindgen/tests/ref_params.rs @@ -0,0 +1,65 @@ +use test_bindgen::ref_params::*; +use windows::core::*; + +#[implement(IDynamicConceptProviderConcept)] +#[derive(Default)] +struct Test(std::sync::RwLock>); + +impl IDynamicConceptProviderConcept_Impl for Test_Impl { + fn GetConcept( + &self, + _: Ref, + _: *const GUID, + concept: OutRef, + _: OutRef, + _: *mut bool, + ) -> Result<()> { + let this = self.0.read().unwrap(); + concept.write(this.clone())?; + Ok(()) + } + fn SetConcept( + &self, + _: Ref, + _: *const GUID, + concept: Ref, + _: Ref, + ) -> Result<()> { + let mut this = self.0.write().unwrap(); + *this = concept.cloned(); + Ok(()) + } + fn NotifyParent(&self, _: Ref) -> Result<()> { + todo!() + } + fn NotifyParentChange(&self, _: Ref) -> Result<()> { + todo!() + } + fn NotifyDestruct(&self) -> Result<()> { + todo!() + } +} + +#[test] +fn test() { + unsafe { + let identity: IUnknown = Test::default().into(); + + let test: IDynamicConceptProviderConcept = Test::default().into(); + + test.SetConcept(None, std::ptr::null(), &identity, None) + .unwrap(); + + let mut concept = None; + test.GetConcept( + None, + std::ptr::null(), + &mut concept, + None, + std::ptr::null_mut(), + ) + .unwrap(); + + assert_eq!(identity, concept.unwrap()); + } +} diff --git a/crates/tests/misc/component/src/bindings.rs b/crates/tests/misc/component/src/bindings.rs index bc3b8e3138..e9668035da 100644 --- a/crates/tests/misc/component/src/bindings.rs +++ b/crates/tests/misc/component/src/bindings.rs @@ -315,10 +315,10 @@ pub trait IClass_Impl: windows_core::IUnknownImpl { ) -> windows_core::Result>; fn Input( &self, - a: Option<&windows_core::IInspectable>, - b: Option<&Class>, - c: Option<&windows::Foundation::IStringable>, - d: Option<&Callback>, + a: windows_core::Ref<'_, windows_core::IInspectable>, + b: windows_core::Ref<'_, Class>, + c: windows_core::Ref<'_, windows::Foundation::IStringable>, + d: windows_core::Ref<'_, Callback>, ) -> windows_core::Result<()>; } impl IClass_Vtbl { @@ -434,10 +434,10 @@ impl IClass_Vtbl { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); IClass_Impl::Input( this, - windows_core::from_raw_borrowed(&a), - windows_core::from_raw_borrowed(&b), - windows_core::from_raw_borrowed(&c), - windows_core::from_raw_borrowed(&d), + core::mem::transmute_copy(&a), + core::mem::transmute_copy(&b), + core::mem::transmute_copy(&c), + core::mem::transmute_copy(&d), ) .into() } diff --git a/crates/tests/misc/component/src/lib.rs b/crates/tests/misc/component/src/lib.rs index 84f7dbf676..e59606af91 100644 --- a/crates/tests/misc/component/src/lib.rs +++ b/crates/tests/misc/component/src/lib.rs @@ -39,15 +39,15 @@ impl bindings::IClass_Impl for Class_Impl { } fn Input( &self, - a: Option<&IInspectable>, - b: Option<&bindings::Class>, - c: Option<&IStringable>, - d: Option<&bindings::Callback>, + a: Ref, + b: Ref, + c: Ref, + d: Ref, ) -> Result<()> { - let a = a.ok_or_else(|| Error::from(E_INVALIDARG))?; - let b = b.ok_or_else(|| Error::from(E_INVALIDARG))?; - let c = c.ok_or_else(|| Error::from(E_INVALIDARG))?; - let d = d.ok_or_else(|| Error::from(E_INVALIDARG))?; + let a = a.ok()?; + let b = b.ok()?; + let c = c.ok()?; + let d = d.ok()?; let a: IUnknown = a.cast()?; let b: IUnknown = b.cast()?; diff --git a/crates/tests/misc/implement/tests/as_interface_param.rs b/crates/tests/misc/implement/tests/as_interface_param.rs index a68a7d1bd3..6c5784adda 100644 --- a/crates/tests/misc/implement/tests/as_interface_param.rs +++ b/crates/tests/misc/implement/tests/as_interface_param.rs @@ -4,7 +4,7 @@ use windows::{core::*, Foundation::*}; struct Async; impl IAsyncAction_Impl for Async_Impl { - fn SetCompleted(&self, handler: Option<&AsyncActionCompletedHandler>) -> Result<()> { + fn SetCompleted(&self, handler: Ref) -> Result<()> { // This validates that `as_interface` may be used to call a bindgen-produced method expecting a `Param` argument. handler .unwrap() diff --git a/crates/tests/misc/implement/tests/class_factory.rs b/crates/tests/misc/implement/tests/class_factory.rs index 26839ecbd6..786c4c3fe5 100644 --- a/crates/tests/misc/implement/tests/class_factory.rs +++ b/crates/tests/misc/implement/tests/class_factory.rs @@ -26,11 +26,11 @@ struct Factory(); impl IClassFactory_Impl for Factory_Impl { fn CreateInstance( &self, - outer: Option<&IUnknown>, + outer: Ref, iid: *const GUID, object: *mut *mut core::ffi::c_void, ) -> Result<()> { - assert!(outer.is_none()); + assert!(outer.is_null()); let unknown: IInspectable = Object().into(); unsafe { unknown.query(iid, object).ok() } } diff --git a/crates/tests/misc/implement/tests/com_chain.rs b/crates/tests/misc/implement/tests/com_chain.rs index 035adc7d57..7b9f783b70 100644 --- a/crates/tests/misc/implement/tests/com_chain.rs +++ b/crates/tests/misc/implement/tests/com_chain.rs @@ -18,11 +18,11 @@ impl IPersistStream_Impl for Test_Impl { S_OK } - fn Load(&self, _: Option<&IStream>) -> Result<()> { + fn Load(&self, _: Ref) -> Result<()> { Ok(()) } - fn Save(&self, _: Option<&IStream>, _: BOOL) -> Result<()> { + fn Save(&self, _: Ref, _: BOOL) -> Result<()> { Ok(()) } diff --git a/crates/tests/misc/implement/tests/data_object.rs b/crates/tests/misc/implement/tests/data_object.rs index a53787e290..d19096351e 100644 --- a/crates/tests/misc/implement/tests/data_object.rs +++ b/crates/tests/misc/implement/tests/data_object.rs @@ -62,7 +62,7 @@ impl IDataObject_Impl for Test_Impl { } } - fn DAdvise(&self, _: *const FORMATETC, _: u32, _: Option<&IAdviseSink>) -> Result { + fn DAdvise(&self, _: *const FORMATETC, _: u32, _: Ref) -> Result { unsafe { (*self.0.get()).DAdvise = true; Ok(0) diff --git a/crates/tests/misc/implement/tests/drop_target.rs b/crates/tests/misc/implement/tests/drop_target.rs index 940c3fdf0e..85a9863796 100644 --- a/crates/tests/misc/implement/tests/drop_target.rs +++ b/crates/tests/misc/implement/tests/drop_target.rs @@ -25,15 +25,10 @@ impl IDataObject_Impl for DataObject_Impl { fn EnumFormatEtc(&self, _: u32) -> Result { unimplemented!() } - fn DAdvise( - &self, - format: *const FORMATETC, - value: u32, - sink: Option<&IAdviseSink>, - ) -> Result { + fn DAdvise(&self, format: *const FORMATETC, value: u32, sink: Ref) -> Result { assert!(!format.is_null()); assert_eq!(value, 789); - assert!(sink.is_none()); + assert!(sink.is_null()); Ok(123) } fn DUnadvise(&self, _: u32) -> Result<()> { @@ -50,7 +45,7 @@ struct DropTarget(); impl IDropTarget_Impl for DropTarget_Impl { fn DragEnter( &self, - object: Option<&IDataObject>, + object: Ref, state: MODIFIERKEYS_FLAGS, point: &POINTL, effect: *mut DROPEFFECT, @@ -75,7 +70,7 @@ impl IDropTarget_Impl for DropTarget_Impl { } fn Drop( &self, - _: Option<&IDataObject>, + _: Ref, _: MODIFIERKEYS_FLAGS, _: &POINTL, _: *mut DROPEFFECT, diff --git a/crates/tests/misc/implement/tests/from_raw_borrowed.rs b/crates/tests/misc/implement/tests/from_raw_borrowed.rs index 99adf59846..b619c72c7f 100644 --- a/crates/tests/misc/implement/tests/from_raw_borrowed.rs +++ b/crates/tests/misc/implement/tests/from_raw_borrowed.rs @@ -31,9 +31,9 @@ impl IServiceProvider_Impl for Borrowed_Impl { } impl IProfferService_Impl for Borrowed_Impl { - fn ProfferService(&self, _: *const GUID, provider: Option<&IServiceProvider>) -> Result { + fn ProfferService(&self, _: *const GUID, provider: Ref) -> Result { unsafe { - if let Some(provider) = provider { + if let Ok(provider) = provider.ok() { Ok(provider.cast::()?.Call()) } else { Ok(0) diff --git a/crates/tests/misc/implement/tests/from_raw_borrowed_winrt.rs b/crates/tests/misc/implement/tests/from_raw_borrowed_winrt.rs index 98133c0a2f..1bb3540f6e 100644 --- a/crates/tests/misc/implement/tests/from_raw_borrowed_winrt.rs +++ b/crates/tests/misc/implement/tests/from_raw_borrowed_winrt.rs @@ -18,13 +18,9 @@ impl IBorrowed_Impl for Borrowed_Impl { } impl IBackgroundTask_Impl for Borrowed_Impl { - fn Run(&self, instance: Option<&IBackgroundTaskInstance>) -> Result<()> { - if let Some(instance) = instance { - assert_eq!(instance.SuspendedCount()?, *self.0.read().unwrap()); - Ok(()) - } else { - Err(E_INVALIDARG.into()) - } + fn Run(&self, instance: Ref) -> Result<()> { + assert_eq!(instance.ok()?.SuspendedCount()?, *self.0.read().unwrap()); + Ok(()) } } @@ -44,7 +40,7 @@ impl IBackgroundTaskInstance_Impl for Borrowed_Impl { fn TriggerDetails(&self) -> Result { unimplemented!() } - fn Canceled(&self, _cancelhandler: Option<&BackgroundTaskCanceledEventHandler>) -> Result { + fn Canceled(&self, _cancelhandler: Ref) -> Result { unimplemented!() } fn RemoveCanceled(&self, _cookie: i64) -> Result<()> { @@ -67,11 +63,11 @@ fn test() -> Result<()> { let task = one_two_three.cast::()?; let instance = one_two_three.cast::()?; - assert_eq!(task.Run(None).unwrap_err().code(), E_INVALIDARG); + assert_eq!(task.Run(None).unwrap_err().code(), E_POINTER); task.Run(&instance)?; let handler = BackgroundTaskCanceledEventHandler::new(|instance, reason| { - if let Some(instance) = instance { + if let Some(instance) = &*instance { assert_eq!( instance.SuspendedCount()?, instance.cast::()?.Call() diff --git a/crates/tests/misc/implement/tests/map.rs b/crates/tests/misc/implement/tests/map.rs index c86978495b..dfbac2971a 100644 --- a/crates/tests/misc/implement/tests/map.rs +++ b/crates/tests/misc/implement/tests/map.rs @@ -54,8 +54,8 @@ impl IMapView_Impl for MapView_Impl { } fn Split( &self, - _first: &mut Option>, - _second: &mut Option>, + _first: OutRef>, + _second: OutRef>, ) -> Result<()> { Ok(()) } diff --git a/crates/tests/misc/implement/tests/properties.rs b/crates/tests/misc/implement/tests/properties.rs index 0e50f60f0b..b16a305386 100644 --- a/crates/tests/misc/implement/tests/properties.rs +++ b/crates/tests/misc/implement/tests/properties.rs @@ -13,7 +13,7 @@ use windows::{ struct Object(std::sync::RwLock); impl IInitializeWithStream_Impl for Object_Impl { - fn Initialize(&self, _: Option<&IStream>, _: u32) -> Result<()> { + fn Initialize(&self, _: Ref, _: u32) -> Result<()> { Ok(()) } } diff --git a/crates/tests/winrt/constructors/src/bindings.rs b/crates/tests/winrt/constructors/src/bindings.rs index 9a559df2bb..1d0a15d5a2 100644 --- a/crates/tests/winrt/constructors/src/bindings.rs +++ b/crates/tests/winrt/constructors/src/bindings.rs @@ -297,14 +297,14 @@ impl windows_core::RuntimeName for IComposableFactory { pub trait IComposableFactory_Impl: windows_core::IUnknownImpl { fn CreateInstance( &self, - baseInterface: Option<&windows_core::IInspectable>, - innerInterface: &mut Option, + baseInterface: windows_core::Ref<'_, windows_core::IInspectable>, + innerInterface: windows_core::OutRef<'_, windows_core::IInspectable>, ) -> windows_core::Result; fn WithValue( &self, arg: i32, - baseInterface: Option<&windows_core::IInspectable>, - innerInterface: &mut Option, + baseInterface: windows_core::Ref<'_, windows_core::IInspectable>, + innerInterface: windows_core::OutRef<'_, windows_core::IInspectable>, ) -> windows_core::Result; } impl IComposableFactory_Vtbl { @@ -321,7 +321,7 @@ impl IComposableFactory_Vtbl { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); match IComposableFactory_Impl::CreateInstance( this, - windows_core::from_raw_borrowed(&baseinterface), + core::mem::transmute_copy(&baseinterface), core::mem::transmute_copy(&innerinterface), ) { Ok(ok__) => { @@ -346,7 +346,7 @@ impl IComposableFactory_Vtbl { match IComposableFactory_Impl::WithValue( this, arg, - windows_core::from_raw_borrowed(&baseinterface), + core::mem::transmute_copy(&baseinterface), core::mem::transmute_copy(&innerinterface), ) { Ok(ok__) => { diff --git a/crates/tests/winrt/constructors/src/lib.rs b/crates/tests/winrt/constructors/src/lib.rs index 49daa30a76..f55ae9fc74 100644 --- a/crates/tests/winrt/constructors/src/lib.rs +++ b/crates/tests/winrt/constructors/src/lib.rs @@ -62,11 +62,12 @@ impl IActivationFactory_Impl for ComposableFactory_Impl { impl bindings::IComposableFactory_Impl for ComposableFactory_Impl { fn CreateInstance( &self, - base: Option<&windows_core::IInspectable>, - inner: &mut Option, + base: Ref, + inner: OutRef, ) -> Result { // windows-rs doesn't support binary composition - if base.is_some() || inner.is_some() { + _ = inner.write(None); + if base.is_some() { Err(CLASS_E_NOAGGREGATION.into()) } else { Ok(Composable::new(0).into()) @@ -76,11 +77,12 @@ impl bindings::IComposableFactory_Impl for ComposableFactory_Impl { fn WithValue( &self, arg: i32, - base: Option<&windows_core::IInspectable>, - inner: &mut Option, + base: Ref, + inner: OutRef, ) -> Result { // windows-rs doesn't support binary composition - if base.is_some() || inner.is_some() { + _ = inner.write(None); + if base.is_some() { Err(CLASS_E_NOAGGREGATION.into()) } else { Ok(Composable::new(arg).into()) diff --git a/crates/tests/winrt/events/src/bindings.rs b/crates/tests/winrt/events/src/bindings.rs index e53a67590e..fe1d50de91 100644 --- a/crates/tests/winrt/events/src/bindings.rs +++ b/crates/tests/winrt/events/src/bindings.rs @@ -87,7 +87,7 @@ pub trait IClass_Impl: windows_core::IUnknownImpl { fn Signal(&self, value: i32) -> windows_core::Result; fn Event( &self, - handler: Option<&windows::Foundation::TypedEventHandler>, + handler: windows_core::Ref<'_, windows::Foundation::TypedEventHandler>, ) -> windows_core::Result; fn RemoveEvent(&self, token: i64) -> windows_core::Result<()>; } @@ -113,7 +113,7 @@ impl IClass_Vtbl { result__: *mut i64, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - match IClass_Impl::Event(this, windows_core::from_raw_borrowed(&handler)) { + match IClass_Impl::Event(this, core::mem::transmute_copy(&handler)) { Ok(ok__) => { result__.write(core::mem::transmute_copy(&ok__)); windows_core::HRESULT(0) diff --git a/crates/tests/winrt/events/src/lib.rs b/crates/tests/winrt/events/src/lib.rs index 0addeb2aa1..87b051964c 100644 --- a/crates/tests/winrt/events/src/lib.rs +++ b/crates/tests/winrt/events/src/lib.rs @@ -39,7 +39,7 @@ impl bindings::IClass_Impl for Class_Impl { fn Event( &self, - handler: Option<&windows::Foundation::TypedEventHandler>, + handler: Ref>, ) -> windows_core::Result { self.0.add(handler.unwrap()) } diff --git a/crates/tests/winrt/noexcept/src/bindings.rs b/crates/tests/winrt/noexcept/src/bindings.rs index 3943e94de5..7373e4c9a5 100644 --- a/crates/tests/winrt/noexcept/src/bindings.rs +++ b/crates/tests/winrt/noexcept/src/bindings.rs @@ -223,22 +223,22 @@ impl windows_core::RuntimeName for ITest { pub trait ITest_Impl: windows_core::IUnknownImpl { fn MethodString(&self, test: &windows_core::HSTRING) -> windows_core::Result<()>; fn MethodInt32(&self, test: i32) -> windows_core::Result<()>; - fn MethodTest(&self, test: Option<&ITest>) -> windows_core::Result<()>; + fn MethodTest(&self, test: windows_core::Ref<'_, ITest>) -> windows_core::Result<()>; fn String(&self) -> windows_core::Result; fn SetString(&self, value: &windows_core::HSTRING) -> windows_core::Result<()>; fn Int32(&self) -> windows_core::Result; fn SetInt32(&self, value: i32) -> windows_core::Result<()>; fn Test(&self) -> windows_core::Result; - fn SetTest(&self, value: Option<&ITest>) -> windows_core::Result<()>; + fn SetTest(&self, value: windows_core::Ref<'_, ITest>) -> windows_core::Result<()>; fn MethodStringN(&self, test: &windows_core::HSTRING); fn MethodInt32N(&self, test: i32); - fn MethodTestN(&self, test: Option<&ITest>); + fn MethodTestN(&self, test: windows_core::Ref<'_, ITest>); fn StringN(&self) -> windows_core::HSTRING; fn SetStringN(&self, value: &windows_core::HSTRING); fn Int32N(&self) -> i32; fn SetInt32N(&self, value: i32); fn TestN(&self) -> Option; - fn SetTestN(&self, value: Option<&ITest>); + fn SetTestN(&self, value: windows_core::Ref<'_, ITest>); } impl ITest_Vtbl { pub const fn new() -> Self { @@ -261,7 +261,7 @@ impl ITest_Vtbl { test: *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - ITest_Impl::MethodTest(this, windows_core::from_raw_borrowed(&test)).into() + ITest_Impl::MethodTest(this, core::mem::transmute_copy(&test)).into() } unsafe extern "system" fn String( this: *mut core::ffi::c_void, @@ -323,7 +323,7 @@ impl ITest_Vtbl { value: *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - ITest_Impl::SetTest(this, windows_core::from_raw_borrowed(&value)).into() + ITest_Impl::SetTest(this, core::mem::transmute_copy(&value)).into() } unsafe extern "system" fn MethodStringN( this: *mut core::ffi::c_void, @@ -346,7 +346,7 @@ impl ITest_Vtbl { test: *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - ITest_Impl::MethodTestN(this, windows_core::from_raw_borrowed(&test)); + ITest_Impl::MethodTestN(this, core::mem::transmute_copy(&test)); windows_core::HRESULT(0) } unsafe extern "system" fn StringN( @@ -399,7 +399,7 @@ impl ITest_Vtbl { value: *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - ITest_Impl::SetTestN(this, windows_core::from_raw_borrowed(&value)); + ITest_Impl::SetTestN(this, core::mem::transmute_copy(&value)); windows_core::HRESULT(0) } Self { diff --git a/crates/tests/winrt/noexcept/tests/test.rs b/crates/tests/winrt/noexcept/tests/test.rs index 5e6e6f54d5..43219ed06b 100644 --- a/crates/tests/winrt/noexcept/tests/test.rs +++ b/crates/tests/winrt/noexcept/tests/test.rs @@ -17,7 +17,7 @@ impl ITest_Impl for Test_Impl { this.1 = test; Ok(()) } - fn MethodTest(&self, test: Option<&ITest>) -> Result<()> { + fn MethodTest(&self, test: Ref) -> Result<()> { let mut this = self.0.write().unwrap(); this.2 = test.cloned(); Ok(()) @@ -44,7 +44,7 @@ impl ITest_Impl for Test_Impl { let this = self.0.read().unwrap(); this.2.clone().ok_or_else(Error::empty) } - fn SetTest(&self, value: Option<&ITest>) -> Result<()> { + fn SetTest(&self, value: Ref) -> Result<()> { let mut this = self.0.write().unwrap(); this.2 = value.cloned(); Ok(()) @@ -58,7 +58,7 @@ impl ITest_Impl for Test_Impl { let mut this = self.0.write().unwrap(); this.1 = test; } - fn MethodTestN(&self, test: Option<&ITest>) { + fn MethodTestN(&self, test: Ref) { let mut this = self.0.write().unwrap(); this.2 = test.cloned(); } @@ -82,7 +82,7 @@ impl ITest_Impl for Test_Impl { let this = self.0.read().unwrap(); this.2.clone() } - fn SetTestN(&self, value: Option<&ITest>) { + fn SetTestN(&self, value: Ref) { let mut this = self.0.write().unwrap(); this.2 = value.cloned(); } diff --git a/crates/tests/winrt/ref_params/Cargo.toml b/crates/tests/winrt/ref_params/Cargo.toml new file mode 100644 index 0000000000..0f93c2184d --- /dev/null +++ b/crates/tests/winrt/ref_params/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "test_ref_params" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +doc = false +doctest = false + +[dependencies.windows-core] +workspace = true + +[build-dependencies.windows-bindgen] +workspace = true + +[build-dependencies] +cc = "1.0" + +[build-dependencies.cppwinrt] +workspace = true diff --git a/crates/tests/winrt/ref_params/build.rs b/crates/tests/winrt/ref_params/build.rs new file mode 100644 index 0000000000..0a464c84d6 --- /dev/null +++ b/crates/tests/winrt/ref_params/build.rs @@ -0,0 +1,60 @@ +fn main() { + if !cfg!(target_env = "msvc") { + return; + } + + println!("cargo:rerun-if-changed=src/test.idl"); + let metadata_dir = format!("{}\\System32\\WinMetadata", env!("windir")); + let mut command = std::process::Command::new("midlrt.exe"); + println!("cargo:rerun-if-changed=src/interop.cpp"); + println!("cargo:rustc-link-lib=onecoreuap"); + + command.args([ + "/winrt", + "/nomidl", + "/h", + "nul", + "/metadata_dir", + &metadata_dir, + "/reference", + &format!("{metadata_dir}\\Windows.Foundation.winmd"), + "/winmd", + "test.winmd", + "src/test.idl", + ]); + + if !command.status().unwrap().success() { + panic!("Failed to run midlrt"); + } + + windows_bindgen::bindgen([ + "--in", + "test.winmd", + &metadata_dir, + "--out", + "src/bindings.rs", + "--filter", + "Test", + "--implement", + "--flat", + ]); + + let include = std::env::var("OUT_DIR").unwrap(); + + cppwinrt::cppwinrt([ + "-in", + "test.winmd", + &format!("{}\\System32\\WinMetadata", env!("windir")), + "-out", + &include, + ]) + .unwrap(); + + cc::Build::new() + .cpp(true) + .std("c++20") + .flag("/EHsc") + .file("src/interop.cpp") + .include(include) + .compile("interop"); +} diff --git a/crates/tests/winrt/ref_params/src/bindings.rs b/crates/tests/winrt/ref_params/src/bindings.rs new file mode 100644 index 0000000000..bcc95f60c7 --- /dev/null +++ b/crates/tests/winrt/ref_params/src/bindings.rs @@ -0,0 +1,151 @@ +// Bindings generated by `windows-bindgen` 0.58.0 + +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] + +windows_core::imp::define_interface!(ITest, ITest_Vtbl, 0xaa1cc4e9_4780_5808_b172_2ef6449e2ba4); +impl windows_core::RuntimeType for ITest { + const SIGNATURE: windows_core::imp::ConstBuffer = + windows_core::imp::ConstBuffer::for_interface::(); +} +windows_core::imp::interface_hierarchy!(ITest, windows_core::IUnknown, windows_core::IInspectable); +impl ITest { + pub fn Input(&self, input: P0) -> windows_core::Result + where + P0: windows_core::Param, + { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Input)( + windows_core::Interface::as_raw(this), + input.param().abi(), + &mut result__, + ) + .map(|| result__) + } + } + pub fn Output(&self, value: i32, output: &mut Option) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).Output)( + windows_core::Interface::as_raw(this), + value, + output as *mut _ as _, + ) + .ok() + } + } + pub fn Current(&self) -> windows_core::Result { + let this = self; + unsafe { + let mut result__ = core::mem::zeroed(); + (windows_core::Interface::vtable(this).Current)( + windows_core::Interface::as_raw(this), + &mut result__, + ) + .map(|| result__) + } + } + pub fn SetCurrent(&self, value: i32) -> windows_core::Result<()> { + let this = self; + unsafe { + (windows_core::Interface::vtable(this).SetCurrent)( + windows_core::Interface::as_raw(this), + value, + ) + .ok() + } + } +} +impl windows_core::RuntimeName for ITest { + const NAME: &'static str = "Test.ITest"; +} +pub trait ITest_Impl: windows_core::IUnknownImpl { + fn Input(&self, input: windows_core::Ref<'_, ITest>) -> windows_core::Result; + fn Output( + &self, + value: i32, + output: windows_core::OutRef<'_, ITest>, + ) -> windows_core::Result<()>; + fn Current(&self) -> windows_core::Result; + fn SetCurrent(&self, value: i32) -> windows_core::Result<()>; +} +impl ITest_Vtbl { + pub const fn new() -> Self { + unsafe extern "system" fn Input( + this: *mut core::ffi::c_void, + input: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match ITest_Impl::Input(this, core::mem::transmute_copy(&input)) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn Output( + this: *mut core::ffi::c_void, + value: i32, + output: *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + ITest_Impl::Output(this, value, core::mem::transmute_copy(&output)).into() + } + unsafe extern "system" fn Current( + this: *mut core::ffi::c_void, + result__: *mut i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + match ITest_Impl::Current(this) { + Ok(ok__) => { + result__.write(core::mem::transmute_copy(&ok__)); + windows_core::HRESULT(0) + } + Err(err) => err.into(), + } + } + unsafe extern "system" fn SetCurrent( + this: *mut core::ffi::c_void, + value: i32, + ) -> windows_core::HRESULT { + let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); + ITest_Impl::SetCurrent(this, value).into() + } + Self { + base__: windows_core::IInspectable_Vtbl::new::(), + Input: Input::, + Output: Output::, + Current: Current::, + SetCurrent: SetCurrent::, + } + } + pub fn matches(iid: &windows_core::GUID) -> bool { + iid == &::IID + } +} +#[repr(C)] +pub struct ITest_Vtbl { + pub base__: windows_core::IInspectable_Vtbl, + pub Input: unsafe extern "system" fn( + *mut core::ffi::c_void, + *mut core::ffi::c_void, + *mut i32, + ) -> windows_core::HRESULT, + pub Output: unsafe extern "system" fn( + *mut core::ffi::c_void, + i32, + *mut *mut core::ffi::c_void, + ) -> windows_core::HRESULT, + pub Current: + unsafe extern "system" fn(*mut core::ffi::c_void, *mut i32) -> windows_core::HRESULT, + pub SetCurrent: unsafe extern "system" fn(*mut core::ffi::c_void, i32) -> windows_core::HRESULT, +} diff --git a/crates/tests/winrt/ref_params/src/interop.cpp b/crates/tests/winrt/ref_params/src/interop.cpp new file mode 100644 index 0000000000..c1f9236592 --- /dev/null +++ b/crates/tests/winrt/ref_params/src/interop.cpp @@ -0,0 +1,78 @@ +#include +#include +#include "winrt/Test.h" + +using namespace winrt; +using namespace winrt::Test; + +struct Test : implements +{ + std::atomic_int32_t m_int32; + + Test(int32_t value) : m_int32(value) + { + } + + int32_t Input(ITest const& input) + { + return input.Current(); + } + + void Output(int32_t value, ITest& output) + { + output = make(value); + } + + int32_t Current() + { + return m_int32; + } + + void Current(int32_t value) + { + m_int32 = value; + } +}; + +void test_interface(ITest const& test) +{ + assert(test.Current() == 0); + test.Current(-321); + assert(test.Current() == -321); + + ITest one_two_three = make(123); + ITest four_five_six = make(456); + + assert(test.Input(one_two_three) == 123); + assert(test.Input(four_five_six) == 456); + + ITest seven_eight_nine; + test.Output(789, seven_eight_nine); + assert(seven_eight_nine.Current() == 789); +} + +extern "C" +{ + HRESULT __stdcall consume(void *abi) noexcept + try + { + ITest const &test = *reinterpret_cast(&abi); + test_interface(test); + return S_OK; + } + catch (...) + { + return to_hresult(); + } + + HRESULT __stdcall produce(void **abi) noexcept + try + { + *abi = detach_abi(make(0)); + return S_OK; + } + catch (...) + { + return to_hresult(); + } +} diff --git a/crates/tests/winrt/ref_params/src/lib.rs b/crates/tests/winrt/ref_params/src/lib.rs new file mode 100644 index 0000000000..6bff33433c --- /dev/null +++ b/crates/tests/winrt/ref_params/src/lib.rs @@ -0,0 +1,25 @@ +#![cfg(target_env = "msvc")] + +mod bindings; +pub use bindings::*; +pub use windows_core::*; + +pub fn consume(test: &ITest) -> Result<()> { + extern "system" { + fn consume(test: Ref) -> HRESULT; + } + + unsafe { consume(std::mem::transmute_copy(test)).ok() } +} + +pub fn produce() -> Result { + extern "system" { + fn produce(test: *mut *mut std::ffi::c_void) -> HRESULT; + } + + unsafe { + let mut test = None; + produce(&mut test as *mut _ as *mut _).ok()?; + Type::from_default(&test) + } +} diff --git a/crates/tests/winrt/ref_params/src/test.idl b/crates/tests/winrt/ref_params/src/test.idl new file mode 100644 index 0000000000..9204e6d2e4 --- /dev/null +++ b/crates/tests/winrt/ref_params/src/test.idl @@ -0,0 +1,10 @@ +namespace Test +{ + interface ITest + { + Int32 Input(ITest input); + void Output(Int32 value, out ITest output); + + Int32 Current { get; set; }; + } +} diff --git a/crates/tests/winrt/ref_params/tests/test.rs b/crates/tests/winrt/ref_params/tests/test.rs new file mode 100644 index 0000000000..6cd60f6f6e --- /dev/null +++ b/crates/tests/winrt/ref_params/tests/test.rs @@ -0,0 +1,56 @@ +#![cfg(target_env = "msvc")] + +use std::sync::atomic::*; +use test_ref_params::*; + +#[implement(ITest)] +struct Test(AtomicI32); + +impl ITest_Impl for Test_Impl { + fn Input(&self, input: Ref) -> Result { + input.ok()?.Current() + } + fn Output(&self, value: i32, output: OutRef) -> Result<()> { + output.write(Some(Test(value.into()).into())) + } + fn Current(&self) -> Result { + Ok(self.0.load(Ordering::Relaxed)) + } + fn SetCurrent(&self, value: i32) -> Result<()> { + self.0.store(value, Ordering::Relaxed); + Ok(()) + } +} + +fn test_interface(test: &ITest) -> Result<()> { + assert_eq!(test.Current()?, 0); + test.SetCurrent(-321)?; + assert_eq!(test.Current()?, -321); + + let one_two_three: ITest = Test(123.into()).into(); + let four_five_six: ITest = Test(456.into()).into(); + + assert_eq!(test.Input(&one_two_three)?, 123); + assert_eq!(test.Input(&four_five_six)?, 456); + + let mut seven_eight_nine = None; + test.Output(789, &mut seven_eight_nine)?; + assert_eq!(seven_eight_nine.unwrap().Current()?, 789); + + Ok(()) +} + +#[test] +fn test_rust() -> Result<()> { + let test: ITest = Test(0.into()).into(); + test_interface(&test) +} + +#[test] +fn test_cpp() -> Result<()> { + let test: ITest = Test(0.into()).into(); + consume(&test)?; + + let test: ITest = produce()?; + test_interface(&test) +} diff --git a/crates/tests/winrt/reference/src/bindings.rs b/crates/tests/winrt/reference/src/bindings.rs index 56e2a81bfc..01df725bf2 100644 --- a/crates/tests/winrt/reference/src/bindings.rs +++ b/crates/tests/winrt/reference/src/bindings.rs @@ -21,7 +21,7 @@ impl windows_core::RuntimeName for IReference { pub trait IReference_Impl: windows_core::IUnknownImpl { fn Method( &self, - stringable: Option<&windows::Foundation::IStringable>, + stringable: windows_core::Ref<'_, windows::Foundation::IStringable>, ) -> windows_core::Result; } impl IReference_Vtbl { @@ -32,7 +32,7 @@ impl IReference_Vtbl { result__: *mut *mut core::ffi::c_void, ) -> windows_core::HRESULT { let this: &Identity = &*((this as *const *const ()).offset(OFFSET) as *const Identity); - match IReference_Impl::Method(this, windows_core::from_raw_borrowed(&stringable)) { + match IReference_Impl::Method(this, core::mem::transmute_copy(&stringable)) { Ok(ok__) => { result__.write(core::mem::transmute_copy(&ok__)); core::mem::forget(ok__); diff --git a/crates/tests/winrt/reference/src/lib.rs b/crates/tests/winrt/reference/src/lib.rs index b02e0b65e6..5aed6f4004 100644 --- a/crates/tests/winrt/reference/src/lib.rs +++ b/crates/tests/winrt/reference/src/lib.rs @@ -34,7 +34,7 @@ impl IStringable_Impl for Reference_Impl { } impl bindings::IReference_Impl for Reference_Impl { - fn Method(&self, stringable: Option<&IStringable>) -> Result { + fn Method(&self, stringable: Ref) -> Result { stringable.unwrap().ToString() } } diff --git a/crates/tools/bindgen/src/main.rs b/crates/tools/bindgen/src/main.rs index 0fc7031f2e..cf878bb4bd 100644 --- a/crates/tools/bindgen/src/main.rs +++ b/crates/tools/bindgen/src/main.rs @@ -140,6 +140,9 @@ fn main() { test("--out bool.rs --filter EnableMouseInPointer --reference windows,skip-root,Windows"); test("--out bool_event.rs --filter CreateEventW SetEvent NtWaitForSingleObject WaitForSingleObjectEx --reference windows,skip-root,Windows"); + // Tests Ref and OutRef for COM interfaces since we can't use MIDLRT for that. + test("--out ref_params.rs --filter IDynamicConceptProviderConcept IModelObject IKeyStore"); + // Tests simulating reference dependency and dependent test_raw( "--no-comment --out reference_dependency_flat.rs --filter IMemoryBufferReference --flat",