Skip to content

Commit

Permalink
Add AgileReference (#1474)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nerixyz committed Feb 2, 2022
1 parent faaf25b commit 4fc9e3b
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Expand Up @@ -101,6 +101,7 @@ jobs:
cargo clippy -p windows_x86_64_gnu &&
cargo clippy -p windows_x86_64_msvc &&
cargo clippy -p test_agile &&
cargo clippy -p test_agile_reference &&
cargo clippy -p test_alternate_success_code &&
cargo clippy -p test_arch &&
cargo clippy -p test_arch_feature &&
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Expand Up @@ -70,6 +70,7 @@ jobs:
cargo test --target ${{ matrix.target }} -p windows_x86_64_gnu &&
cargo test --target ${{ matrix.target }} -p windows_x86_64_msvc &&
cargo test --target ${{ matrix.target }} -p test_agile &&
cargo test --target ${{ matrix.target }} -p test_agile_reference &&
cargo test --target ${{ matrix.target }} -p test_alternate_success_code &&
cargo test --target ${{ matrix.target }} -p test_arch &&
cargo test --target ${{ matrix.target }} -p test_arch_feature &&
Expand Down
26 changes: 26 additions & 0 deletions crates/libs/windows/src/core/agile_reference.rs
@@ -0,0 +1,26 @@
use super::*;
use bindings::*;
use core::marker::PhantomData;

/// A type representing an agile reference to a COM/WinRT object.
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq)]
pub struct AgileReference<T>(IAgileReference, PhantomData<T>);

impl<T: Interface> AgileReference<T> {
/// Creates an agile reference to the object.
pub fn new<'a>(object: &'a T) -> Result<Self>
where
&'a T: IntoParam<'a, IUnknown>,
{
unsafe { RoGetAgileReference(AGILEREFERENCE_DEFAULT, &T::IID, object).map(|reference| Self(reference, Default::default())) }
}

/// Retrieves a proxy to the target of the `AgileReference` object that may safely be used within any thread context in which get is called.
pub fn resolve(&self) -> Result<T> {
unsafe { self.0.Resolve() }
}
}

unsafe impl<T: Interface> Send for AgileReference<T> {}
unsafe impl<T: Interface> Sync for AgileReference<T> {}
92 changes: 92 additions & 0 deletions crates/libs/windows/src/core/bindings.rs
Expand Up @@ -2098,6 +2098,98 @@ pub unsafe fn WaitForSingleObject<'a, Param0: ::windows::core::IntoParam<'a, HAN
unimplemented!("Unsupported target OS");
}
#[repr(transparent)]
pub struct IAgileReference(::windows::core::IUnknown);
impl IAgileReference {
pub unsafe fn Resolve<T: ::windows::core::Interface>(&self) -> ::windows::core::Result<T> {
let mut result__ = ::core::option::Option::None;
(::windows::core::Interface::vtable(self).Resolve)(::core::mem::transmute_copy(self), &<T as ::windows::core::Interface>::IID, &mut result__ as *mut _ as *mut _).and_some(result__)
}
}
impl ::core::convert::From<IAgileReference> for ::windows::core::IUnknown {
fn from(value: IAgileReference) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
impl ::core::convert::From<&IAgileReference> for ::windows::core::IUnknown {
fn from(value: &IAgileReference) -> Self {
::core::convert::From::from(::core::clone::Clone::clone(value))
}
}
impl<'a> ::windows::core::IntoParam<'a, ::windows::core::IUnknown> for IAgileReference {
fn into_param(self) -> ::windows::core::Param<'a, ::windows::core::IUnknown> {
::windows::core::Param::Owned(unsafe { ::core::mem::transmute(self) })
}
}
impl<'a> ::windows::core::IntoParam<'a, ::windows::core::IUnknown> for &IAgileReference {
fn into_param(self) -> ::windows::core::Param<'a, ::windows::core::IUnknown> {
::windows::core::Param::Borrowed(unsafe { ::core::mem::transmute(self) })
}
}
impl ::core::clone::Clone for IAgileReference {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl ::core::cmp::PartialEq for IAgileReference {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl ::core::cmp::Eq for IAgileReference {}
impl ::core::fmt::Debug for IAgileReference {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_tuple("IAgileReference").field(&self.0).finish()
}
}
unsafe impl ::windows::core::Interface for IAgileReference {
type Vtable = IAgileReference_Vtbl;
const IID: ::windows::core::GUID = ::windows::core::GUID::from_u128(0xc03f6a43_65a4_9818_987e_e0b810d2a6f2);
}
#[repr(C)]
#[doc(hidden)]
pub struct IAgileReference_Vtbl {
pub base: ::windows::core::IUnknownVtbl,
pub Resolve: unsafe extern "system" fn(this: *mut ::core::ffi::c_void, riid: *const ::windows::core::GUID, ppvobjectreference: *mut *mut ::core::ffi::c_void) -> ::windows::core::HRESULT,
}
#[repr(transparent)]
#[derive(:: core :: cmp :: PartialEq, :: core :: cmp :: Eq)]
pub struct AgileReferenceOptions(pub i32);
pub const AGILEREFERENCE_DEFAULT: AgileReferenceOptions = AgileReferenceOptions(0i32);
pub const AGILEREFERENCE_DELAYEDMARSHAL: AgileReferenceOptions = AgileReferenceOptions(1i32);
impl ::core::marker::Copy for AgileReferenceOptions {}
impl ::core::clone::Clone for AgileReferenceOptions {
fn clone(&self) -> Self {
*self
}
}
impl ::core::default::Default for AgileReferenceOptions {
fn default() -> Self {
Self(0)
}
}
unsafe impl ::windows::core::Abi for AgileReferenceOptions {
type Abi = Self;
}
impl ::core::fmt::Debug for AgileReferenceOptions {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
f.debug_tuple("AgileReferenceOptions").field(&self.0).finish()
}
}
#[inline]
pub unsafe fn RoGetAgileReference<'a, Param2: ::windows::core::IntoParam<'a, ::windows::core::IUnknown>>(options: AgileReferenceOptions, riid: *const ::windows::core::GUID, punk: Param2) -> ::windows::core::Result<IAgileReference> {
#[cfg(windows)]
{
#[link(name = "windows")]
extern "system" {
fn RoGetAgileReference(options: AgileReferenceOptions, riid: *const ::windows::core::GUID, punk: *mut ::core::ffi::c_void, ppagilereference: *mut ::windows::core::RawPtr) -> ::windows::core::HRESULT;
}
let mut result__: ::windows::core::RawPtr = ::core::mem::zeroed();
RoGetAgileReference(::core::mem::transmute(options), ::core::mem::transmute(riid), punk.into_param().abi(), ::core::mem::transmute(&mut result__)).from_abi::<IAgileReference>(result__)
}
#[cfg(not(windows))]
unimplemented!("Unsupported target OS");
}
#[repr(transparent)]
pub struct ILanguageExceptionErrorInfo(::windows::core::IUnknown);
impl ILanguageExceptionErrorInfo {
pub unsafe fn GetLanguageException(&self) -> ::windows::core::Result<::windows::core::IUnknown> {
Expand Down
2 changes: 2 additions & 0 deletions crates/libs/windows/src/core/mod.rs
@@ -1,5 +1,6 @@
mod abi;
mod activation_factory;
mod agile_reference;
mod array;
pub(crate) mod bindings;
mod compose;
Expand Down Expand Up @@ -28,6 +29,7 @@ mod weak_ref_count;
pub use abi::*;
#[doc(hidden)]
pub use activation_factory::*;
pub use agile_reference::*;
pub use array::*;
#[doc(hidden)]
pub use compose::*;
Expand Down
13 changes: 13 additions & 0 deletions crates/tests/agile_reference/Cargo.toml
@@ -0,0 +1,13 @@
[package]
name = "test_agile_reference"
version = "0.0.0"
authors = ["Microsoft"]
edition = "2018"

[dependencies.windows]
path = "../../libs/windows"
features = [
"Foundation",
"Media_Control",
"Foundation_Collections"
]
1 change: 1 addition & 0 deletions crates/tests/agile_reference/src/lib.rs
@@ -0,0 +1 @@

16 changes: 16 additions & 0 deletions crates/tests/agile_reference/tests/tests.rs
@@ -0,0 +1,16 @@
use windows::core::{AgileReference, Result};
use windows::Media::Control::GlobalSystemMediaTransportControlsSessionManager;

#[test]
fn test() -> Result<()> {
let manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync()?.get()?;
let reference = AgileReference::new(&manager)?;

let handle = std::thread::spawn(move || {
let manager = reference.resolve()?;

manager.GetSessions()?;
Ok(())
});
handle.join().unwrap()
}
3 changes: 3 additions & 0 deletions crates/tools/bindings/src/main.rs
Expand Up @@ -50,6 +50,9 @@ fn main() -> std::io::Result<()> {
"Windows.Win32.System.Threading.CreateEventA",
"Windows.Win32.System.Threading.SetEvent",
"Windows.Win32.System.Threading.WaitForSingleObject",
"Windows.Win32.System.WinRT.IAgileReference",
"Windows.Win32.System.WinRT.AgileReferenceOptions",
"Windows.Win32.System.WinRT.RoGetAgileReference",
"Windows.Win32.System.WinRT.ILanguageExceptionErrorInfo",
"Windows.Win32.System.WinRT.ILanguageExceptionErrorInfo2",
"Windows.Win32.System.WinRT.IRestrictedErrorInfo",
Expand Down

0 comments on commit 4fc9e3b

Please sign in to comment.