Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AgileReference #1474

Merged
merged 10 commits into from Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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> {
Nerixyz marked this conversation as resolved.
Show resolved Hide resolved
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