Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
use super::*;
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>(imp::IAgileReference, PhantomData<T>);
impl<T: Interface> AgileReference<T> {
/// Creates an agile reference to the object.
pub fn new(object: &T) -> Result<Self> {
// TODO: this assert is required until we can catch this at compile time using an "associated const equality" constraint.
// For example, <T: Interface<UNKNOWN = true>>
// https://github.com/rust-lang/rust/issues/92827
assert!(T::UNKNOWN);
unsafe {
imp::RoGetAgileReference(
imp::AGILEREFERENCE_DEFAULT,
&T::IID,
core::mem::transmute::<&T, &IUnknown>(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> {}
impl<T> core::fmt::Debug for AgileReference<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "AgileReference({:?})", &self.0)
}
}

165
vendor/windows-core/src/array.rs vendored Normal file
View File

@@ -0,0 +1,165 @@
use super::*;
/// A WinRT array stores elements contiguously in a heap-allocated buffer.
pub struct Array<T: Type<T>> {
pub(crate) data: *mut T::Default,
pub(crate) len: u32,
}
impl<T: Type<T>> Default for Array<T> {
fn default() -> Self {
Self {
data: core::ptr::null_mut(),
len: 0,
}
}
}
impl<T: Type<T>> Array<T> {
/// Creates an empty array.
pub fn new() -> Self {
Self::default()
}
/// Creates an array of the given length with default values.
pub fn with_len(len: usize) -> Self {
assert!(len < u32::MAX as usize);
let bytes_amount = len
.checked_mul(core::mem::size_of::<T>())
.expect("Attempted to allocate too large an Array");
// WinRT arrays must be allocated with CoTaskMemAlloc.
// SAFETY: the call to CoTaskMemAlloc is safe to perform
// if len is zero and overflow was checked above.
// We ensured we alloc enough space by multiplying len * size_of::<T>
let data = unsafe { imp::CoTaskMemAlloc(bytes_amount) as *mut T::Default };
assert!(!data.is_null(), "Could not successfully allocate for Array");
// SAFETY: It is by definition safe to zero-initialize WinRT types.
// `write_bytes` will write 0 to (len * size_of::<T>())
// bytes making the entire array zero initialized. We have assured
// above that the data ptr is not null.
unsafe {
core::ptr::write_bytes(data, 0, len);
}
let len = len as u32;
Self { data, len }
}
/// Creates an array by copying the elements from the slice.
pub fn from_slice(values: &[T::Default]) -> Self
where
T::Default: Clone,
{
let mut array = Self::with_len(values.len());
array.clone_from_slice(values);
array
}
/// Creates an array from a pointer and length. The `len` argument is the number of elements, not the number of bytes.
/// # Safety
/// The `data` argument must have been allocated with `CoTaskMemAlloc`.
pub unsafe fn from_raw_parts(data: *mut T::Default, len: u32) -> Self {
Self { data, len }
}
/// Returns a slice containing the entire array.
pub fn as_slice(&self) -> &[T::Default] {
self
}
/// Returns `true` if the array is empty.
pub fn is_empty(&self) -> bool {
self.len == 0
}
/// Returns the length of the array.
pub fn len(&self) -> usize {
self.len as usize
}
/// Clears the contents of the array.
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
let mut data = core::ptr::null_mut();
let mut len = 0;
core::mem::swap(&mut data, &mut self.data);
core::mem::swap(&mut len, &mut self.len);
// SAFETY: At this point, self has been reset to zero so any panics in T's destructor would
// only leak data not leave the array in bad state.
unsafe {
// Call the destructors of all the elements of the old array
// SAFETY: the slice cannot be used after the call to `drop_in_place`
core::ptr::drop_in_place(core::ptr::slice_from_raw_parts_mut(data, len as usize));
// Free the data memory where the elements were
// SAFETY: we have unique access to the data pointer at this point
// so freeing it is the right thing to do
imp::CoTaskMemFree(data as _);
}
}
#[doc(hidden)]
/// Get a mutable pointer to the array's length
///
/// # Safety
///
/// This function is safe but writing to the pointer is not. Calling this without
/// a subsequent call to `set_abi` is likely to either leak memory or cause UB
pub unsafe fn set_abi_len(&mut self) -> *mut u32 {
&mut self.len
}
#[doc(hidden)]
/// Turn the array into a pointer to its data and its length
pub fn into_abi(self) -> (*mut T::Abi, u32) {
let abi = (self.data as *mut _, self.len);
core::mem::forget(self);
abi
}
}
impl<T: Type<T>> core::ops::Deref for Array<T> {
type Target = [T::Default];
fn deref(&self) -> &[T::Default] {
if self.is_empty() {
return &[];
}
// SAFETY: data must not be null if the array is not empty
unsafe { core::slice::from_raw_parts(self.data, self.len as usize) }
}
}
impl<T: Type<T>> core::ops::DerefMut for Array<T> {
fn deref_mut(&mut self) -> &mut [T::Default] {
if self.is_empty() {
return &mut [];
}
// SAFETY: data must not be null if the array is not empty
unsafe { core::slice::from_raw_parts_mut(self.data, self.len as usize) }
}
}
impl<T: Type<T>> Drop for Array<T> {
fn drop(&mut self) {
self.clear();
}
}
impl<T: Type<T>> core::fmt::Debug for Array<T>
where
T::Default: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
core::ops::Deref::deref(self).fmt(f)
}
}

20
vendor/windows-core/src/as_impl.rs vendored Normal file
View File

@@ -0,0 +1,20 @@
/// A trait for retrieving the implementation behind a COM or WinRT interface.
///
/// This trait is automatically implemented when using the `implement` macro.
pub trait AsImpl<T> {
/// # Safety
///
/// The caller needs to ensure that `self` is actually implemented by the
/// implementation `T`.
unsafe fn as_impl(&self) -> &T {
unsafe { self.as_impl_ptr().as_ref() }
}
/// Returns a pointer to the implementation object.
///
/// # Safety
///
/// The caller needs to ensure that `self` is actually implemented by the
/// implementation `T`.
unsafe fn as_impl_ptr(&self) -> core::ptr::NonNull<T>;
}

394
vendor/windows-core/src/com_object.rs vendored Normal file
View File

@@ -0,0 +1,394 @@
use crate::imp::Box;
use crate::{IUnknown, IUnknownImpl, Interface, InterfaceRef};
use core::any::Any;
use core::borrow::Borrow;
use core::ops::Deref;
use core::ptr::NonNull;
/// Identifies types that can be placed in [`ComObject`].
///
/// This trait links types that can be placed in `ComObject` with the types generated by the
/// `#[implement]` macro. The `#[implement]` macro generates implementations of this trait.
/// The generated types contain the vtable layouts and refcount-related fields for the COM
/// object implementation.
///
/// This trait is an implementation detail of the Windows crates.
/// User code should not deal directly with this trait.
///
/// This trait is sort of the reverse of [`IUnknownImpl`]. This trait allows user code to use
/// [`ComObject<T>`] instead of `ComObject<T_Impl>`.
pub trait ComObjectInner: Sized {
/// The generated `<foo>_Impl` type (aka the "boxed" type or "outer" type).
type Outer: IUnknownImpl<Impl = Self>;
/// Moves an instance of this type into a new ComObject box and returns it.
///
/// # Safety
///
/// It is important that safe Rust code never be able to acquire an owned instance of a
/// generated "outer" COM object type, e.g. `<foo>_Impl`. This would be unsafe because the
/// `<foo>_Impl` object contains a reference count field and provides methods that adjust
/// the reference count, and destroy the object when the reference count reaches zero.
///
/// Safe Rust code must only be able to interact with these values by accessing them via a
/// `ComObject` reference. `ComObject` handles adjusting reference counts and associates the
/// lifetime of a `&<foo>_Impl` with the lifetime of the related `ComObject`.
///
/// The `#[implement]` macro generates the implementation of this `into_object` method.
/// The generated `into_object` method encapsulates the construction of the `<foo>_Impl`
/// object and immediately places it into the heap and returns a `ComObject` reference to it.
/// This ensures that our requirement -- that safe Rust code never own a `<foo>_Impl` value
/// directly -- is met.
fn into_object(self) -> ComObject<Self>;
}
/// Describes the COM interfaces implemented by a specific COM object.
///
/// The `#[implement]` macro generates implementations of this trait. Implementations are attached
/// to the "outer" types generated by `#[implement]`, e.g. the `MyApp_Impl` type. Each
/// implementation knows how to locate the interface-specific field within `MyApp_Impl`.
///
/// This trait is an implementation detail of the Windows crates.
/// User code should not deal directly with this trait.
pub trait ComObjectInterface<I: Interface> {
/// Gets a borrowed interface that is implemented by `T`.
fn as_interface_ref(&self) -> InterfaceRef<'_, I>;
}
/// A counted pointer to a type that implements COM interfaces, where the object has been
/// placed in the heap (boxed).
///
/// This type exists so that you can place an object into the heap and query for COM interfaces,
/// without losing the safe reference to the implementation object.
///
/// Because the pointer inside this type is known to be non-null, `Option<ComObject<T>>` should
/// always have the same size as a single pointer.
///
/// # Safety
///
/// The contained `ptr` field is an owned, reference-counted pointer to a _pinned_ `Pin<Box<T::Outer>>`.
/// Although this code does not currently use `Pin<T>`, it takes care not to expose any unsafe semantics
/// to safe code. However, code that calls unsafe functions on [`ComObject`] must, like all unsafe code,
/// understand and preserve invariants.
#[repr(transparent)]
pub struct ComObject<T: ComObjectInner> {
ptr: NonNull<T::Outer>,
}
impl<T: ComObjectInner> ComObject<T> {
/// Allocates a heap cell (box) and moves `value` into it. Returns a counted pointer to `value`.
pub fn new(value: T) -> Self {
T::into_object(value)
}
/// Creates a new `ComObject` that points to an existing boxed instance.
///
/// # Safety
///
/// The caller must ensure that `ptr` points to a valid, heap-allocated instance of `T::Outer`.
/// Normally, this pointer comes from using `Box::into_raw(Box::new(...))`.
///
/// The pointed-to box must have a reference count that is greater than zero.
///
/// This function takes ownership of the existing pointer; it does not call `AddRef`.
/// The reference count must accurately reflect all outstanding references to the box,
/// including `ptr` in the count.
pub unsafe fn from_raw(ptr: NonNull<T::Outer>) -> Self {
Self { ptr }
}
/// Gets a reference to the shared object stored in the box.
///
/// [`ComObject`] also implements [`Deref`], so you can often deref directly into the object.
/// For those situations where using the [`Deref`] impl is inconvenient, you can use
/// this method to explicitly get a reference to the contents.
#[inline(always)]
pub fn get(&self) -> &T {
self.get_box().get_impl()
}
/// Gets a reference to the shared object's heap box.
#[inline(always)]
fn get_box(&self) -> &T::Outer {
unsafe { self.ptr.as_ref() }
}
// Note that we _do not_ provide a way to get a mutable reference to the outer box.
// It's ok to return `&mut T`, but not `&mut T::Outer`. That would allow someone to replace the
// contents of the entire object (box and reference count), which could lead to UB.
// This could maybe be solved by returning `Pin<&mut T::Outer>`, but that requires some
// additional thinking.
/// Gets a mutable reference to the object stored in the box, if the reference count
/// is exactly 1. If there are multiple references to this object then this returns `None`.
#[inline(always)]
pub fn get_mut(&mut self) -> Option<&mut T> {
if self.is_reference_count_one() {
// SAFETY: We must only return &mut T, *NOT* &mut T::Outer.
// Returning T::Outer would allow swapping the contents of the object, which would
// allow (incorrectly) modifying the reference count.
unsafe { Some(self.ptr.as_mut().get_impl_mut()) }
} else {
None
}
}
/// If this object has only a single object reference (i.e. this [`ComObject`] is the only
/// reference to the heap allocation), then this method will extract the inner `T`
/// (and return it in an `Ok`) and then free the heap allocation.
///
/// If there is more than one reference to this object, then this returns `Err(self)`.
#[inline(always)]
pub fn take(self) -> Result<T, Self> {
if self.is_reference_count_one() {
let outer_box: Box<T::Outer> = unsafe { core::mem::transmute(self) };
Ok(outer_box.into_inner())
} else {
Err(self)
}
}
/// Casts to a given interface type.
///
/// This always performs a `QueryInterface`, even if `T` is known to implement `I`.
/// If you know that `T` implements `I`, then use [`Self::as_interface`] or [`Self::to_interface`] because
/// those functions do not require a dynamic `QueryInterface` call.
#[inline(always)]
pub fn cast<I: Interface>(&self) -> windows_core::Result<I>
where
T::Outer: ComObjectInterface<IUnknown>,
{
let unknown = self.as_interface::<IUnknown>();
unknown.cast()
}
/// Gets a borrowed reference to an interface that is implemented by `T`.
///
/// The returned reference does not have an additional reference count.
/// You can AddRef it by calling [`InterfaceRef::to_owned`].
#[inline(always)]
pub fn as_interface<I: Interface>(&self) -> InterfaceRef<'_, I>
where
T::Outer: ComObjectInterface<I>,
{
self.get_box().as_interface_ref()
}
/// Gets an owned (counted) reference to an interface that is implemented by this [`ComObject`].
#[inline(always)]
pub fn to_interface<I: Interface>(&self) -> I
where
T::Outer: ComObjectInterface<I>,
{
self.as_interface::<I>().to_owned()
}
/// Converts `self` into an interface that it implements.
///
/// This does not need to adjust reference counts because `self` is consumed.
#[inline(always)]
pub fn into_interface<I: Interface>(self) -> I
where
T::Outer: ComObjectInterface<I>,
{
unsafe {
let raw = self.get_box().as_interface_ref().as_raw();
core::mem::forget(self);
I::from_raw(raw)
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `MyApp_Impl`, not the inner `MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is an owned (counted) reference; this function calls `AddRef` on the
/// underlying COM object. If you do not need an owned reference, then you can use the
/// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`.
pub fn cast_from<I>(interface: &I) -> crate::Result<Self>
where
I: Interface,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
interface.cast_object()
}
}
impl<T: ComObjectInner + Default> Default for ComObject<T> {
fn default() -> Self {
Self::new(T::default())
}
}
impl<T: ComObjectInner> Drop for ComObject<T> {
fn drop(&mut self) {
unsafe {
T::Outer::Release(self.ptr.as_ptr());
}
}
}
impl<T: ComObjectInner> Clone for ComObject<T> {
#[inline(always)]
fn clone(&self) -> Self {
unsafe {
self.ptr.as_ref().AddRef();
Self { ptr: self.ptr }
}
}
}
impl<T: ComObjectInner> AsRef<T> for ComObject<T> {
#[inline(always)]
fn as_ref(&self) -> &T {
self.get()
}
}
impl<T: ComObjectInner> Deref for ComObject<T> {
type Target = T::Outer;
#[inline(always)]
fn deref(&self) -> &Self::Target {
self.get_box()
}
}
// There is no DerefMut implementation because we cannot statically guarantee
// that the reference count is 1, which is a requirement for getting exclusive
// access to the contents of the object. Use get_mut() for dynamically-checked
// exclusive access.
impl<T: ComObjectInner> From<T> for ComObject<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
// Delegate hashing, if implemented.
impl<T: ComObjectInner + core::hash::Hash> core::hash::Hash for ComObject<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.get().hash(state);
}
}
// If T is Send (or Sync) then the ComObject<T> is also Send (or Sync).
// Since the actual object storage is in the heap, the object is never moved.
unsafe impl<T: ComObjectInner + Send> Send for ComObject<T> {}
unsafe impl<T: ComObjectInner + Sync> Sync for ComObject<T> {}
impl<T: ComObjectInner + PartialEq> PartialEq for ComObject<T> {
fn eq(&self, other: &Self) -> bool {
let inner_self: &T = self.get();
let other_self: &T = other.get();
inner_self == other_self
}
}
impl<T: ComObjectInner + Eq> Eq for ComObject<T> {}
impl<T: ComObjectInner + PartialOrd> PartialOrd for ComObject<T> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
let inner_self: &T = self.get();
let other_self: &T = other.get();
<T as PartialOrd>::partial_cmp(inner_self, other_self)
}
}
impl<T: ComObjectInner + Ord> Ord for ComObject<T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
let inner_self: &T = self.get();
let other_self: &T = other.get();
<T as Ord>::cmp(inner_self, other_self)
}
}
impl<T: ComObjectInner + core::fmt::Debug> core::fmt::Debug for ComObject<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<T as core::fmt::Debug>::fmt(self.get(), f)
}
}
impl<T: ComObjectInner + core::fmt::Display> core::fmt::Display for ComObject<T> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<T as core::fmt::Display>::fmt(self.get(), f)
}
}
impl<T: ComObjectInner> Borrow<T> for ComObject<T> {
fn borrow(&self) -> &T {
self.get()
}
}
/// Enables applications to define COM objects using static storage. This is useful for factory
/// objects, stateless objects, or objects which use need to contain or use mutable global state.
///
/// COM objects that are defined using `StaticComObject` have their storage placed directly in
/// static storage; they are not stored in the heap.
///
/// COM objects defined using `StaticComObject` do have a reference count and this reference
/// count is adjusted when owned COM interface references (e.g. `IFoo` and `IUnknown`) are created
/// for the object. The reference count is initialized to 1.
///
/// # Example
///
/// ```rust,ignore
/// #[implement(IFoo)]
/// struct MyApp {
/// // ...
/// }
///
/// static MY_STATIC_APP: StaticComObject<MyApp> = MyApp { ... }.into_static();
///
/// fn get_my_static_ifoo() -> IFoo {
/// MY_STATIC_APP.to_interface()
/// }
/// ```
pub struct StaticComObject<T>
where
T: ComObjectInner,
{
outer: T::Outer,
}
// IMPORTANT: Do not expose any methods that return mutable access to the contents of StaticComObject.
// Doing so would violate our safety invariants. For example, we provide a Deref impl but it would
// be unsound to provide a DerefMut impl.
impl<T> StaticComObject<T>
where
T: ComObjectInner,
{
/// Wraps `outer` in a `StaticComObject`.
pub const fn from_outer(outer: T::Outer) -> Self {
Self { outer }
}
}
impl<T> StaticComObject<T>
where
T: ComObjectInner,
{
/// Gets access to the contained value.
pub const fn get(&'static self) -> &'static T::Outer {
&self.outer
}
}
impl<T> core::ops::Deref for StaticComObject<T>
where
T: ComObjectInner,
{
type Target = T::Outer;
fn deref(&self) -> &Self::Target {
&self.outer
}
}

144
vendor/windows-core/src/event.rs vendored Normal file
View File

@@ -0,0 +1,144 @@
use super::*;
use core::{iter::once, mem::transmute_copy};
use std::sync::{Arc, RwLock};
/// A type that you can use to declare and implement an event of a specified delegate type.
///
/// The implementation is thread-safe and designed to avoid contention between events being
/// raised and delegates being added or removed.
pub struct Event<T: Interface> {
delegates: RwLock<Option<Arc<[Delegate<T>]>>>,
}
unsafe impl<T: Interface> Send for Event<T> {}
unsafe impl<T: Interface> Sync for Event<T> {}
impl<T: Interface> Default for Event<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Interface> Event<T> {
/// Creates a new, empty `Event<T>`.
pub const fn new() -> Self {
Self {
delegates: RwLock::new(None),
}
}
/// Registers a delegate with the event object.
pub fn add(&self, delegate: &T) -> Result<i64> {
let new_delegate = Delegate::new(delegate)?;
let token = new_delegate.to_token();
let new_iter = once(new_delegate);
let mut guard = self.delegates.write().unwrap();
let new_list = if let Some(old_delegates) = guard.as_ref() {
Arc::from_iter(old_delegates.iter().cloned().chain(new_iter))
} else {
Arc::from_iter(new_iter)
};
let old_list = guard.replace(new_list);
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
Ok(token)
}
/// Revokes a delegate's registration from the event object.
pub fn remove(&self, token: i64) {
let mut guard = self.delegates.write().unwrap();
let mut old_list = None;
if let Some(old_delegates) = guard.as_ref() {
// `self.delegates` is only modified if the token is found.
if let Some(i) = old_delegates
.iter()
.position(|old_delegate| old_delegate.to_token() == token)
{
let new_list = Arc::from_iter(
old_delegates[..i]
.iter()
.chain(old_delegates[i + 1..].iter())
.cloned(),
);
old_list = guard.replace(new_list);
}
}
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Clears the event, removing all delegates.
pub fn clear(&self) {
let mut guard = self.delegates.write().unwrap();
let old_list = guard.take();
drop(guard);
drop(old_list); // drop the old delegates _after_ releasing lock
}
/// Invokes all of the event object's registered delegates with the provided callback.
pub fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) {
let delegates = {
let guard = self.delegates.read().unwrap();
if let Some(delegates) = guard.as_ref() {
delegates.clone()
} else {
// No delegates to call.
return;
}
// <-- lock is released here
};
for delegate in delegates.iter() {
if let Err(error) = delegate.call(&mut callback) {
const RPC_E_SERVER_UNAVAILABLE: HRESULT = HRESULT(-2147023174); // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE)
if matches!(
error.code(),
imp::RPC_E_DISCONNECTED | imp::JSCRIPT_E_CANTEXECUTE | RPC_E_SERVER_UNAVAILABLE
) {
self.remove(delegate.to_token());
}
}
}
}
}
/// Holds either a direct or indirect reference to a delegate. A direct reference is typically
/// agile while an indirect reference is an agile wrapper.
#[derive(Clone)]
enum Delegate<T> {
Direct(T),
Indirect(AgileReference<T>),
}
impl<T: Interface> Delegate<T> {
/// Creates a new `Delegate<T>`, containing a suitable reference to the specified delegate.
fn new(delegate: &T) -> Result<Self> {
if delegate.cast::<imp::IAgileObject>().is_ok() {
Ok(Self::Direct(delegate.clone()))
} else {
Ok(Self::Indirect(AgileReference::new(delegate)?))
}
}
/// Returns an encoded token to identify the delegate.
fn to_token(&self) -> i64 {
unsafe {
match self {
Self::Direct(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64,
Self::Indirect(delegate) => imp::EncodePointer(transmute_copy(delegate)) as i64,
}
}
}
/// Invokes the delegates with the provided callback.
fn call<F: FnMut(&T) -> Result<()>>(&self, mut callback: F) -> Result<()> {
match self {
Self::Direct(delegate) => callback(delegate),
Self::Indirect(delegate) => callback(&delegate.resolve()?),
}
}
}

206
vendor/windows-core/src/guid.rs vendored Normal file
View File

@@ -0,0 +1,206 @@
use super::*;
/// A globally unique identifier ([GUID](https://docs.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid))
/// used to identify COM and WinRT interfaces.
#[repr(C)]
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct GUID {
/// Specifies the first 8 hexadecimal digits.
pub data1: u32,
/// Specifies the first group of 4 hexadecimal digits.
pub data2: u16,
/// Specifies the second group of 4 hexadecimal digits.
pub data3: u16,
/// The first 2 bytes contain the third group of 4 hexadecimal digits. The remaining 6 bytes contain the final 12 hexadecimal digits.
pub data4: [u8; 8],
}
impl GUID {
/// Creates a unique `GUID` value.
pub fn new() -> Result<Self> {
let mut guid = Self::zeroed();
let result = unsafe { imp::UuidCreate(&mut guid as *mut _ as _) };
if matches!(result, 0 | imp::RPC_S_UUID_LOCAL_ONLY) {
Ok(guid)
} else {
Err(Error::from_hresult(HRESULT::from_win32(result as u32)))
}
}
/// Creates a `GUID` represented by the all-zero byte-pattern.
pub const fn zeroed() -> Self {
Self {
data1: 0,
data2: 0,
data3: 0,
data4: [0, 0, 0, 0, 0, 0, 0, 0],
}
}
/// Creates a `GUID` with the given constant values.
pub const fn from_values(data1: u32, data2: u16, data3: u16, data4: [u8; 8]) -> Self {
Self {
data1,
data2,
data3,
data4,
}
}
/// Creates a `GUID` from a `u128` value.
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: ((uuid >> 80) & 0xffff) as u16,
data3: ((uuid >> 64) & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes(),
}
}
/// Converts a `GUID` to a `u128` value.
pub const fn to_u128(&self) -> u128 {
((self.data1 as u128) << 96)
+ ((self.data2 as u128) << 80)
+ ((self.data3 as u128) << 64)
+ u64::from_be_bytes(self.data4) as u128
}
/// Creates a `GUID` for a "generic" WinRT type.
pub const fn from_signature(signature: imp::ConstBuffer) -> Self {
let data = imp::ConstBuffer::from_slice(&[
0x11, 0xf4, 0x7a, 0xd5, 0x7b, 0x73, 0x42, 0xc0, 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16,
0xad, 0xee,
]);
let data = data.push_other(signature);
let bytes = imp::sha1(&data).bytes();
let first = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
let second = u16::from_be_bytes([bytes[4], bytes[5]]);
let mut third = u16::from_be_bytes([bytes[6], bytes[7]]);
third = (third & 0x0fff) | (5 << 12);
let fourth = (bytes[8] & 0x3f) | 0x80;
Self::from_values(
first,
second,
third,
[
fourth, bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
],
)
}
}
impl RuntimeType for GUID {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"g16");
}
impl TypeKind for GUID {
type TypeKind = CopyType;
}
impl core::fmt::Debug for GUID {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"{:08X?}-{:04X?}-{:04X?}-{:02X?}{:02X?}-{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}{:02X?}",
self.data1,
self.data2,
self.data3,
self.data4[0],
self.data4[1],
self.data4[2],
self.data4[3],
self.data4[4],
self.data4[5],
self.data4[6],
self.data4[7]
)
}
}
impl TryFrom<&str> for GUID {
type Error = Error;
fn try_from(from: &str) -> Result<Self> {
if from.len() != 36 {
return Err(invalid_guid());
}
let bytes = &mut from.bytes();
let mut guid = Self::zeroed();
guid.data1 = try_u32(bytes, true)?;
guid.data2 = try_u16(bytes, true)?;
guid.data3 = try_u16(bytes, true)?;
guid.data4[0] = try_u8(bytes, false)?;
guid.data4[1] = try_u8(bytes, true)?;
guid.data4[2] = try_u8(bytes, false)?;
guid.data4[3] = try_u8(bytes, false)?;
guid.data4[4] = try_u8(bytes, false)?;
guid.data4[5] = try_u8(bytes, false)?;
guid.data4[6] = try_u8(bytes, false)?;
guid.data4[7] = try_u8(bytes, false)?;
Ok(guid)
}
}
impl From<u128> for GUID {
fn from(value: u128) -> Self {
Self::from_u128(value)
}
}
impl From<GUID> for u128 {
fn from(value: GUID) -> Self {
value.to_u128()
}
}
fn invalid_guid() -> Error {
Error::from_hresult(imp::E_INVALIDARG)
}
fn try_u32(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u32> {
next(bytes, 8, delimiter).ok_or_else(invalid_guid)
}
fn try_u16(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u16> {
next(bytes, 4, delimiter)
.map(|value| value as u16)
.ok_or_else(invalid_guid)
}
fn try_u8(bytes: &mut core::str::Bytes, delimiter: bool) -> Result<u8> {
next(bytes, 2, delimiter)
.map(|value| value as u8)
.ok_or_else(invalid_guid)
}
fn next(bytes: &mut core::str::Bytes, len: usize, delimiter: bool) -> Option<u32> {
let mut value: u32 = 0;
for _ in 0..len {
let digit = bytes.next()?;
match digit {
b'0'..=b'9' => value = (value << 4) + (digit - b'0') as u32,
b'A'..=b'F' => value = (value << 4) + (digit - b'A' + 10) as u32,
b'a'..=b'f' => value = (value << 4) + (digit - b'a' + 10) as u32,
_ => return None,
}
}
if delimiter && bytes.next() != Some(b'-') {
None
} else {
Some(value)
}
}

46
vendor/windows-core/src/handles.rs vendored Normal file
View File

@@ -0,0 +1,46 @@
/// Custom code to free a handle.
///
/// This is similar to the [`Drop`] trait, and may be used to implement [`Drop`], but allows handles
/// to be dropped depending on context.
pub trait Free {
/// Calls the handle's free function.
///
/// # Safety
/// The handle must be owned by the caller and safe to free.
unsafe fn free(&mut self);
}
/// A wrapper to provide ownership for handles to automatically drop via the handle's [`Free`] trait.
#[repr(transparent)]
#[derive(PartialEq, Eq, Default, Debug)]
pub struct Owned<T: Free>(T);
impl<T: Free> Owned<T> {
/// Takes ownership of the handle.
///
/// # Safety
///
/// The handle must be owned by the caller and safe to free.
pub unsafe fn new(x: T) -> Self {
Self(x)
}
}
impl<T: Free> Drop for Owned<T> {
fn drop(&mut self) {
unsafe { self.0.free() };
}
}
impl<T: Free> core::ops::Deref for Owned<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Free> core::ops::DerefMut for Owned<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

View File

@@ -0,0 +1,38 @@
use crate::{Array, Type};
pub struct ArrayProxy<T: Type<T>> {
data: *mut *mut T::Default,
len: *mut u32,
temp: core::mem::ManuallyDrop<Array<T>>,
}
pub unsafe fn array_proxy<T: Type<T>>(data: *mut *mut T::Default, len: *mut u32) -> ArrayProxy<T> {
ArrayProxy {
data,
len,
temp: core::mem::ManuallyDrop::new(Array::new()),
}
}
impl<T: Type<T>> Drop for ArrayProxy<T> {
fn drop(&mut self) {
unsafe {
*self.data = self.temp.data;
*self.len = self.temp.len;
}
}
}
impl<T: Type<T>> core::ops::Deref for ArrayProxy<T> {
type Target = Array<T>;
fn deref(&self) -> &Array<T> {
&self.temp
}
}
impl<T: Type<T>> core::ops::DerefMut for ArrayProxy<T> {
fn deref_mut(&mut self) -> &mut Array<T> {
&mut self.temp
}
}

40
vendor/windows-core/src/imp/bindings.rs vendored Normal file
View File

@@ -0,0 +1,40 @@
windows_link::link!("combase.dll" "system" fn CoIncrementMTAUsage(pcookie : *mut CO_MTA_USAGE_COOKIE) -> HRESULT);
windows_link::link!("combase.dll" "system" fn CoTaskMemAlloc(cb : usize) -> *mut core::ffi::c_void);
windows_link::link!("combase.dll" "system" fn CoTaskMemFree(pv : *const core::ffi::c_void));
windows_link::link!("kernel32.dll" "system" fn EncodePointer(ptr : *const core::ffi::c_void) -> *mut core::ffi::c_void);
windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> BOOL);
windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : HMODULE, lpprocname : PCSTR) -> FARPROC);
windows_link::link!("kernel32.dll" "system" fn LoadLibraryExA(lplibfilename : PCSTR, hfile : HANDLE, dwflags : LOAD_LIBRARY_FLAGS) -> HMODULE);
windows_link::link!("api-ms-win-core-winrt-l1-1-0.dll" "system" fn RoGetActivationFactory(activatableclassid : HSTRING, iid : *const GUID, factory : *mut *mut core::ffi::c_void) -> HRESULT);
windows_link::link!("rpcrt4.dll" "system" fn UuidCreate(uuid : *mut GUID) -> RPC_STATUS);
pub type BOOL = i32;
pub type CO_MTA_USAGE_COOKIE = *mut core::ffi::c_void;
pub type FARPROC = Option<unsafe extern "system" fn() -> isize>;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct GUID {
pub data1: u32,
pub data2: u16,
pub data3: u16,
pub data4: [u8; 8],
}
impl GUID {
pub const fn from_u128(uuid: u128) -> Self {
Self {
data1: (uuid >> 96) as u32,
data2: (uuid >> 80 & 0xffff) as u16,
data3: (uuid >> 64 & 0xffff) as u16,
data4: (uuid as u64).to_be_bytes(),
}
}
}
pub type HANDLE = *mut core::ffi::c_void;
pub type HINSTANCE = *mut core::ffi::c_void;
pub type HMODULE = *mut core::ffi::c_void;
pub type HRESULT = i32;
pub type LOAD_LIBRARY_FLAGS = u32;
pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 4096u32;
pub type PCSTR = *const u8;
pub type RPC_STATUS = i32;
pub const RPC_S_UUID_LOCAL_ONLY: RPC_STATUS = 1824i32;
pub type HSTRING = *mut core::ffi::c_void;

View File

@@ -0,0 +1,5 @@
pub trait CanInto<T>: Sized {
const QUERY: bool = false;
}
impl<T> CanInto<T> for T where T: Clone {}

View File

@@ -0,0 +1,246 @@
#[inline]
pub unsafe fn RoGetAgileReference<P2>(
options: AgileReferenceOptions,
riid: *const windows_core::GUID,
punk: P2,
) -> windows_core::Result<IAgileReference>
where
P2: windows_core::Param<windows_core::IUnknown>,
{
windows_core::link!("combase.dll" "system" fn RoGetAgileReference(options : AgileReferenceOptions, riid : *const windows_core::GUID, punk : * mut core::ffi::c_void, ppagilereference : *mut * mut core::ffi::c_void) -> windows_core::HRESULT);
unsafe {
let mut result__ = core::mem::zeroed();
RoGetAgileReference(options, riid, punk.param().abi(), &mut result__)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
pub const AGILEREFERENCE_DEFAULT: AgileReferenceOptions = AgileReferenceOptions(0i32);
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct AgileReferenceOptions(pub i32);
pub const CO_E_NOTINITIALIZED: windows_core::HRESULT = windows_core::HRESULT(0x800401F0_u32 as _);
pub const E_INVALIDARG: windows_core::HRESULT = windows_core::HRESULT(0x80070057_u32 as _);
pub const E_NOINTERFACE: windows_core::HRESULT = windows_core::HRESULT(0x80004002_u32 as _);
pub const E_POINTER: windows_core::HRESULT = windows_core::HRESULT(0x80004003_u32 as _);
windows_core::imp::define_interface!(
IAgileObject,
IAgileObject_Vtbl,
0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90
);
windows_core::imp::interface_hierarchy!(IAgileObject, windows_core::IUnknown);
#[repr(C)]
#[doc(hidden)]
pub struct IAgileObject_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
}
pub trait IAgileObject_Impl: windows_core::IUnknownImpl {}
impl IAgileObject_Vtbl {
pub const fn new<Identity: IAgileObject_Impl, const OFFSET: isize>() -> Self {
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IAgileObject as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IAgileObject {}
windows_core::imp::define_interface!(
IAgileReference,
IAgileReference_Vtbl,
0xc03f6a43_65a4_9818_987e_e0b810d2a6f2
);
windows_core::imp::interface_hierarchy!(IAgileReference, windows_core::IUnknown);
impl IAgileReference {
pub unsafe fn Resolve<T>(&self) -> windows_core::Result<T>
where
T: windows_core::Interface,
{
let mut result__ = core::ptr::null_mut();
unsafe {
(windows_core::Interface::vtable(self).Resolve)(
windows_core::Interface::as_raw(self),
&T::IID,
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IAgileReference_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub Resolve: unsafe extern "system" fn(
*mut core::ffi::c_void,
*const windows_core::GUID,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IAgileReference_Impl: windows_core::IUnknownImpl {
fn Resolve(
&self,
riid: *const windows_core::GUID,
ppvobjectreference: *mut *mut core::ffi::c_void,
) -> windows_core::Result<()>;
}
impl IAgileReference_Vtbl {
pub const fn new<Identity: IAgileReference_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn Resolve<Identity: IAgileReference_Impl, const OFFSET: isize>(
this: *mut core::ffi::c_void,
riid: *const windows_core::GUID,
ppvobjectreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
IAgileReference_Impl::Resolve(
this,
core::mem::transmute_copy(&riid),
core::mem::transmute_copy(&ppvobjectreference),
)
.into()
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
Resolve: Resolve::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IAgileReference as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IAgileReference {}
windows_core::imp::define_interface!(
IWeakReference,
IWeakReference_Vtbl,
0x00000037_0000_0000_c000_000000000046
);
windows_core::imp::interface_hierarchy!(IWeakReference, windows_core::IUnknown);
impl IWeakReference {
pub unsafe fn Resolve<T>(&self) -> windows_core::Result<T>
where
T: windows_core::Interface,
{
let mut result__ = core::ptr::null_mut();
unsafe {
(windows_core::Interface::vtable(self).Resolve)(
windows_core::Interface::as_raw(self),
&T::IID,
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IWeakReference_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub Resolve: unsafe extern "system" fn(
*mut core::ffi::c_void,
*const windows_core::GUID,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IWeakReference_Impl: windows_core::IUnknownImpl {
fn Resolve(
&self,
riid: *const windows_core::GUID,
objectreference: *mut *mut core::ffi::c_void,
) -> windows_core::Result<()>;
}
impl IWeakReference_Vtbl {
pub const fn new<Identity: IWeakReference_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn Resolve<Identity: IWeakReference_Impl, const OFFSET: isize>(
this: *mut core::ffi::c_void,
riid: *const windows_core::GUID,
objectreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
IWeakReference_Impl::Resolve(
this,
core::mem::transmute_copy(&riid),
core::mem::transmute_copy(&objectreference),
)
.into()
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
Resolve: Resolve::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IWeakReference as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IWeakReference {}
windows_core::imp::define_interface!(
IWeakReferenceSource,
IWeakReferenceSource_Vtbl,
0x00000038_0000_0000_c000_000000000046
);
windows_core::imp::interface_hierarchy!(IWeakReferenceSource, windows_core::IUnknown);
impl IWeakReferenceSource {
pub unsafe fn GetWeakReference(&self) -> windows_core::Result<IWeakReference> {
unsafe {
let mut result__ = core::mem::zeroed();
(windows_core::Interface::vtable(self).GetWeakReference)(
windows_core::Interface::as_raw(self),
&mut result__,
)
.and_then(|| windows_core::Type::from_abi(result__))
}
}
}
#[repr(C)]
#[doc(hidden)]
pub struct IWeakReferenceSource_Vtbl {
pub base__: windows_core::IUnknown_Vtbl,
pub GetWeakReference: unsafe extern "system" fn(
*mut core::ffi::c_void,
*mut *mut core::ffi::c_void,
) -> windows_core::HRESULT,
}
pub trait IWeakReferenceSource_Impl: windows_core::IUnknownImpl {
fn GetWeakReference(&self) -> windows_core::Result<IWeakReference>;
}
impl IWeakReferenceSource_Vtbl {
pub const fn new<Identity: IWeakReferenceSource_Impl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn GetWeakReference<
Identity: IWeakReferenceSource_Impl,
const OFFSET: isize,
>(
this: *mut core::ffi::c_void,
weakreference: *mut *mut core::ffi::c_void,
) -> windows_core::HRESULT {
unsafe {
let this: &Identity =
&*((this as *const *const ()).offset(OFFSET) as *const Identity);
match IWeakReferenceSource_Impl::GetWeakReference(this) {
Ok(ok__) => {
weakreference.write(core::mem::transmute(ok__));
windows_core::HRESULT(0)
}
Err(err) => err.into(),
}
}
}
Self {
base__: windows_core::IUnknown_Vtbl::new::<Identity, OFFSET>(),
GetWeakReference: GetWeakReference::<Identity, OFFSET>,
}
}
pub fn matches(iid: &windows_core::GUID) -> bool {
iid == &<IWeakReferenceSource as windows_core::Interface>::IID
}
}
impl windows_core::RuntimeName for IWeakReferenceSource {}
pub const JSCRIPT_E_CANTEXECUTE: windows_core::HRESULT = windows_core::HRESULT(0x89020001_u32 as _);
pub const REGDB_E_CLASSNOTREG: windows_core::HRESULT = windows_core::HRESULT(0x80040154_u32 as _);
pub const RPC_E_DISCONNECTED: windows_core::HRESULT = windows_core::HRESULT(0x80010108_u32 as _);
pub const S_OK: windows_core::HRESULT = windows_core::HRESULT(0x0_u32 as _);

View File

@@ -0,0 +1,214 @@
use super::*;
use crate::Interface;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::{forget, transmute, transmute_copy};
use core::ptr::null_mut;
use core::sync::atomic::{AtomicPtr, Ordering};
pub struct FactoryCache<C, I> {
shared: AtomicPtr<c_void>,
_c: PhantomData<C>,
_i: PhantomData<I>,
}
impl<C, I> FactoryCache<C, I> {
pub const fn new() -> Self {
Self {
shared: AtomicPtr::new(null_mut()),
_c: PhantomData,
_i: PhantomData,
}
}
}
impl<C, I> Default for FactoryCache<C, I> {
fn default() -> Self {
Self::new()
}
}
impl<C: crate::RuntimeName, I: Interface> FactoryCache<C, I> {
pub fn call<R, F: FnOnce(&I) -> crate::Result<R>>(&self, callback: F) -> crate::Result<R> {
loop {
// Attempt to load a previously cached factory pointer.
let ptr = self.shared.load(Ordering::Relaxed);
// If a pointer is found, the cache is primed and we're good to go.
if !ptr.is_null() {
return callback(unsafe { transmute::<&*mut c_void, &I>(&ptr) });
}
// Otherwise, we load the factory the usual way.
let factory = load_factory::<C, I>()?;
// If the factory is agile, we can safely cache it.
if factory.cast::<IAgileObject>().is_ok() {
if self
.shared
.compare_exchange_weak(
null_mut(),
factory.as_raw(),
Ordering::Relaxed,
Ordering::Relaxed,
)
.is_ok()
{
forget(factory);
}
} else {
// Otherwise, for non-agile factories we simply use the factory
// and discard after use as it is not safe to cache.
return callback(&factory);
}
}
}
}
// This is safe because `FactoryCache` only holds agile factory pointers, which are safe to cache and share between threads.
unsafe impl<C, I> Sync for FactoryCache<C, I> {}
/// Attempts to load the factory object for the given WinRT class.
/// This can be used to access COM interfaces implemented on a Windows Runtime class factory.
pub fn load_factory<C: crate::RuntimeName, I: Interface>() -> crate::Result<I> {
let mut factory: Option<I> = None;
let name = crate::HSTRING::from(C::NAME);
let code = unsafe {
let mut get_com_factory = || {
crate::HRESULT(RoGetActivationFactory(
transmute_copy(&name),
&I::IID as *const _ as _,
&mut factory as *mut _ as *mut _,
))
};
let mut code = get_com_factory();
// If RoGetActivationFactory fails because combase hasn't been loaded yet then load combase
// automatically so that it "just works" for apartment-agnostic code.
if code == CO_E_NOTINITIALIZED {
let mut cookie = core::ptr::null_mut();
CoIncrementMTAUsage(&mut cookie);
// Now try a second time to get the activation factory via the OS.
code = get_com_factory();
}
code
};
// If this succeeded then return the resulting factory interface.
if let Some(factory) = factory {
return Ok(factory);
}
// Reg-free activation should only be attempted if the class is not registered.
// It should not be attempted if the class is registered but fails to activate.
if code == REGDB_E_CLASSNOTREG {
// Now attempt to find the factory's implementation heuristically.
if let Some(i) = search_path(C::NAME, |library| unsafe {
get_activation_factory(library, &name)
}) {
return i.cast();
}
}
Err(crate::Error::from_hresult(code))
}
// Remove the suffix until a match is found appending `.dll\0` at the end
///
/// For example, if the class name is
/// "A.B.TypeName" then the attempted load order will be:
/// 1. A.B.dll
/// 2. A.dll
fn search_path<F, R>(mut path: &str, mut callback: F) -> Option<R>
where
F: FnMut(crate::PCSTR) -> crate::Result<R>,
{
let suffix = b".dll\0";
let mut library = alloc::vec![0; path.len() + suffix.len()];
while let Some(pos) = path.rfind('.') {
path = &path[..pos];
library.truncate(path.len() + suffix.len());
library[..path.len()].copy_from_slice(path.as_bytes());
library[path.len()..].copy_from_slice(suffix);
if let Ok(r) = callback(crate::PCSTR::from_raw(library.as_ptr())) {
return Some(r);
}
}
None
}
unsafe fn get_activation_factory(
library: crate::PCSTR,
name: &crate::HSTRING,
) -> crate::Result<IGenericFactory> {
unsafe {
let function =
delay_load::<DllGetActivationFactory>(library, crate::s!("DllGetActivationFactory"))
.ok_or_else(crate::Error::from_thread)?;
let mut abi = null_mut();
function(transmute_copy(name), &mut abi).and_then(|| crate::Type::from_abi(abi))
}
}
unsafe fn delay_load<T>(library: crate::PCSTR, function: crate::PCSTR) -> Option<T> {
unsafe {
let library = LoadLibraryExA(
library.0,
core::ptr::null_mut(),
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS,
);
if library.is_null() {
return None;
}
let address = GetProcAddress(library, function.0);
if address.is_some() {
return Some(core::mem::transmute_copy(&address));
}
FreeLibrary(library);
None
}
}
type DllGetActivationFactory =
extern "system" fn(name: *mut c_void, factory: *mut *mut c_void) -> crate::HRESULT;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dll_search() {
let path = "A.B.TypeName";
// Test library successfully found
let mut results = Vec::new();
let end_result = search_path(path, |library| {
results.push(unsafe { library.to_string().unwrap() });
if unsafe { library.as_bytes() } == &b"A.dll"[..] {
Ok(42)
} else {
Err(crate::Error::empty())
}
});
assert!(matches!(end_result, Some(42)));
assert_eq!(results, vec!["A.B.dll", "A.dll"]);
// Test library never successfully found
let mut results = Vec::new();
let end_result = search_path(path, |library| {
results.push(unsafe { library.to_string().unwrap() });
crate::Result::<()>::Err(crate::Error::empty())
});
assert!(end_result.is_none());
assert_eq!(results, vec!["A.B.dll", "A.dll"]);
}
}

View File

@@ -0,0 +1,33 @@
use crate::Interface;
use core::ffi::c_void;
use core::mem::{transmute_copy, zeroed};
// A streamlined version of the IActivationFactory interface used by WinRT class factories used internally by the windows crate
// to simplify code generation. Components should implement the `IActivationFactory` interface published by the windows crate.
super::define_interface!(
IGenericFactory,
IGenericFactory_Vtbl,
0x00000035_0000_0000_c000_000000000046
);
super::interface_hierarchy!(IGenericFactory, crate::IUnknown, crate::IInspectable);
impl IGenericFactory {
pub fn ActivateInstance<I: Interface>(&self) -> crate::Result<I> {
unsafe {
let mut result__ = zeroed();
(Interface::vtable(self).ActivateInstance)(
transmute_copy(self),
&mut result__ as *mut _ as *mut _,
)
.and_then(|| crate::Type::from_abi(result__))
.and_then(|interface: crate::IInspectable| interface.cast())
}
}
}
#[repr(C)]
pub struct IGenericFactory_Vtbl {
pub base__: crate::IInspectable_Vtbl,
pub ActivateInstance:
unsafe extern "system" fn(this: *mut c_void, instance: *mut *mut c_void) -> crate::HRESULT,
}

268
vendor/windows-core/src/imp/marshaler.rs vendored Normal file
View File

@@ -0,0 +1,268 @@
use super::*;
use crate::{IUnknown, IUnknown_Vtbl, Interface, GUID, HRESULT};
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
windows_link::link!("combase.dll" "system" fn CoCreateFreeThreadedMarshaler(punkouter: *mut c_void, ppunkmarshal: *mut *mut c_void) -> HRESULT);
pub unsafe fn marshaler(outer: IUnknown, result: *mut *mut c_void) -> HRESULT {
unsafe {
let mut marshaler_raw = null_mut();
_ = CoCreateFreeThreadedMarshaler(null_mut(), &mut marshaler_raw);
assert!(!marshaler_raw.is_null(), "allocation failed");
let marshaler: IUnknown = transmute(marshaler_raw);
_ = (marshaler.vtable().QueryInterface)(
transmute_copy(&marshaler),
&IMarshal::IID,
&mut marshaler_raw,
);
debug_assert!(!marshaler_raw.is_null());
let marshaler: IMarshal = transmute(marshaler_raw);
let marshaler = Marshaler {
vtable: &Marshaler::VTABLE,
outer,
marshaler,
count: RefCount::new(1),
};
debug_assert!(!result.is_null());
*result = transmute::<Box<_>, *mut c_void>(Box::new(marshaler));
S_OK
}
}
#[repr(C)]
struct Marshaler {
vtable: *const IMarshal_Vtbl,
outer: IUnknown,
marshaler: IMarshal,
count: RefCount,
}
impl Marshaler {
const VTABLE: IMarshal_Vtbl = IMarshal_Vtbl {
base__: IUnknown_Vtbl {
QueryInterface: Self::QueryInterface,
AddRef: Self::AddRef,
Release: Self::Release,
},
GetUnmarshalClass: Self::GetUnmarshalClass,
GetMarshalSizeMax: Self::GetMarshalSizeMax,
MarshalInterface: Self::MarshalInterface,
UnmarshalInterface: Self::UnmarshalInterface,
ReleaseMarshalData: Self::ReleaseMarshalData,
DisconnectObject: Self::DisconnectObject,
};
unsafe extern "system" fn QueryInterface(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
if *iid == IMarshal::IID {
*interface = &mut (*this).vtable as *mut _ as _;
(*this).count.add_ref();
return S_OK;
}
((*this).outer.vtable().QueryInterface)(transmute_copy(&(*this).outer), iid, interface)
}
}
unsafe extern "system" fn AddRef(this: *mut c_void) -> u32 {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
(*this).count.add_ref()
}
}
unsafe extern "system" fn Release(this: *mut c_void) -> u32 {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
let remaining = (*this).count.release();
if remaining == 0 {
let _ = Box::from_raw(this);
}
remaining
}
}
unsafe extern "system" fn GetUnmarshalClass(
this: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
pcid: *mut GUID,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().GetUnmarshalClass)(
transmute_copy(&(*this).marshaler),
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
pcid,
)
}
}
unsafe extern "system" fn GetMarshalSizeMax(
this: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
psize: *mut u32,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().GetMarshalSizeMax)(
transmute_copy(&(*this).marshaler),
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
psize,
)
}
}
unsafe extern "system" fn MarshalInterface(
this: *mut c_void,
pstm: *mut c_void,
riid: *const GUID,
pv: *const c_void,
dwdestcontext: u32,
pvdestcontext: *const c_void,
mshlflags: u32,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().MarshalInterface)(
transmute_copy(&(*this).marshaler),
pstm,
riid,
pv,
dwdestcontext,
pvdestcontext,
mshlflags,
)
}
}
unsafe extern "system" fn UnmarshalInterface(
this: *mut c_void,
pstm: *mut c_void,
riid: *const GUID,
ppv: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().UnmarshalInterface)(
transmute_copy(&(*this).marshaler),
pstm,
riid,
ppv,
)
}
}
unsafe extern "system" fn ReleaseMarshalData(this: *mut c_void, pstm: *mut c_void) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().ReleaseMarshalData)(
transmute_copy(&(*this).marshaler),
pstm,
)
}
}
unsafe extern "system" fn DisconnectObject(this: *mut c_void, dwreserved: u32) -> HRESULT {
unsafe {
let this = this as *mut *mut c_void as *mut Self;
((*this).marshaler.vtable().DisconnectObject)(
transmute_copy(&(*this).marshaler),
dwreserved,
)
}
}
}
#[repr(transparent)]
#[derive(Clone)]
pub struct IMarshal(IUnknown);
unsafe impl Interface for IMarshal {
type Vtable = IMarshal_Vtbl;
const IID: GUID = GUID::from_u128(0x00000003_0000_0000_c000_000000000046);
}
#[repr(C)]
pub struct IMarshal_Vtbl {
base__: IUnknown_Vtbl,
GetUnmarshalClass: unsafe extern "system" fn(
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
*mut GUID,
) -> HRESULT,
GetMarshalSizeMax: unsafe extern "system" fn(
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
*mut u32,
) -> HRESULT,
MarshalInterface: unsafe extern "system" fn(
*mut c_void,
*mut c_void,
*const GUID,
*const c_void,
u32,
*const c_void,
u32,
) -> HRESULT,
UnmarshalInterface: unsafe extern "system" fn(
*mut c_void,
*mut c_void,
*const GUID,
*mut *mut c_void,
) -> HRESULT,
ReleaseMarshalData: unsafe extern "system" fn(*mut c_void, *mut c_void) -> HRESULT,
DisconnectObject: unsafe extern "system" fn(*mut c_void, u32) -> HRESULT,
}

98
vendor/windows-core/src/imp/mod.rs vendored Normal file
View File

@@ -0,0 +1,98 @@
#[cfg(windows)]
include!("windows.rs");
mod bindings;
mod can_into;
mod com_bindings;
mod ref_count;
mod sha1;
mod weak_ref_count;
pub(crate) use bindings::*;
pub use can_into::*;
pub use com_bindings::*;
pub use ref_count::*;
pub use sha1::*;
pub use weak_ref_count::*;
#[doc(hidden)]
#[macro_export]
macro_rules! interface_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::imp::CanInto<$parent> for $child {}
impl ::core::convert::From<&$child> for &$parent {
fn from(value: &$child) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
impl ::core::convert::From<$child> for $parent {
fn from(value: $child) -> Self {
unsafe { ::core::mem::transmute(value) }
}
}
};
($child:ident, $first:ty, $($rest:ty),+) => {
$crate::imp::interface_hierarchy!($child, $first);
$crate::imp::interface_hierarchy!($child, $($rest),+);
};
}
#[doc(hidden)]
pub use interface_hierarchy;
#[doc(hidden)]
#[macro_export]
macro_rules! required_hierarchy {
($child:ident, $parent:ty) => {
impl ::windows_core::imp::CanInto<$parent> for $child { const QUERY: bool = true; }
};
($child:ident, $first:ty, $($rest:ty),+) => {
$crate::imp::required_hierarchy!($child, $first);
$crate::imp::required_hierarchy!($child, $($rest),+);
};
}
#[doc(hidden)]
pub use required_hierarchy;
#[doc(hidden)]
#[macro_export]
macro_rules! define_interface {
($name:ident, $vtbl:ident, $iid:literal) => {
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)]
pub struct $name(::windows_core::IUnknown);
unsafe impl ::windows_core::Interface for $name {
type Vtable = $vtbl;
const IID: ::windows_core::GUID = ::windows_core::GUID::from_u128($iid);
}
impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> core::fmt::Result {
f.debug_tuple(stringify!($name))
.field(&::windows_core::Interface::as_raw(self))
.finish()
}
}
};
($name:ident, $vtbl:ident) => {
#[repr(transparent)]
#[derive(::core::cmp::PartialEq, ::core::cmp::Eq, ::core::clone::Clone)]
pub struct $name(::core::ptr::NonNull<::core::ffi::c_void>);
unsafe impl ::windows_core::Interface for $name {
type Vtable = $vtbl;
const IID: ::windows_core::GUID = ::windows_core::GUID::zeroed();
const UNKNOWN: bool = false;
}
impl ::core::fmt::Debug for $name {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> core::fmt::Result {
f.debug_tuple(stringify!($name)).field(&self.0).finish()
}
}
};
}
#[doc(hidden)]
pub use define_interface;
#[doc(hidden)]
pub use alloc::boxed::Box;

View File

@@ -0,0 +1,33 @@
use core::sync::atomic::{fence, AtomicI32, Ordering};
#[repr(transparent)]
#[derive(Default)]
pub struct RefCount(pub(crate) AtomicI32);
impl RefCount {
/// Creates a new `RefCount` with an initial value of `1`.
pub const fn new(count: u32) -> Self {
Self(AtomicI32::new(count as i32))
}
/// Increments the reference count, returning the new value.
pub fn add_ref(&self) -> u32 {
(self.0.fetch_add(1, Ordering::Relaxed) + 1) as u32
}
/// Decrements the reference count, returning the new value.
///
/// This operation inserts an `Acquire` fence when the reference count reaches zero.
/// This prevents reordering before the object is destroyed.
pub fn release(&self) -> u32 {
let remaining = self.0.fetch_sub(1, Ordering::Release) - 1;
match remaining.cmp(&0) {
core::cmp::Ordering::Equal => fence(Ordering::Acquire),
core::cmp::Ordering::Less => panic!("Object has been over-released."),
core::cmp::Ordering::Greater => {}
}
remaining as u32
}
}

487
vendor/windows-core/src/imp/sha1.rs vendored Normal file
View File

@@ -0,0 +1,487 @@
pub const fn sha1(data: &ConstBuffer) -> Digest {
let state: [u32; 5] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];
let len: u64 = 0;
let blocks = Blocks {
len: 0,
data: [0; 64],
};
let (blocks, len, state) = process_blocks(blocks, data, len, state);
digest(state, len, blocks)
}
const BUFFER_SIZE: usize = 1024;
pub struct ConstBuffer {
data: [u8; BUFFER_SIZE],
head: usize,
}
impl Default for ConstBuffer {
fn default() -> Self {
Self::new()
}
}
impl ConstBuffer {
pub const fn for_class<C: crate::RuntimeName, I: crate::RuntimeType>() -> Self {
Self::new()
.push_slice(b"rc(")
.push_slice(C::NAME.as_bytes())
.push(b';')
.push_other(I::SIGNATURE)
.push(b')')
}
pub const fn for_interface<T: crate::Interface>() -> Self {
Self::new().push_guid(&T::IID)
}
pub const fn from_slice(slice: &[u8]) -> Self {
let s = Self::new();
s.push_slice(slice)
}
pub const fn new() -> Self {
Self {
data: [0; BUFFER_SIZE],
head: 0,
}
}
pub const fn push_slice(self, slice: &[u8]) -> Self {
self.push_amount(slice, slice.len())
}
const fn get(&self, index: usize) -> u8 {
self.data[index]
}
const fn len(&self) -> usize {
self.head
}
pub fn as_slice(&self) -> &[u8] {
&self.data[..self.head]
}
pub const fn push_other(self, other: Self) -> Self {
self.push_amount(&other.data, other.len())
}
const fn push(mut self, value: u8) -> Self {
self.data[self.head] = value;
self.head += 1;
self
}
const fn push_hex_u8(self, value: u8) -> Self {
const fn digit(mut value: u8) -> u8 {
value &= 0xF;
if value < 10 {
b'0' + value
} else {
b'a' + (value - 10)
}
}
self.push(digit(value >> 4)).push(digit(value))
}
const fn push_hex_u16(self, value: u16) -> Self {
self.push_hex_u8((value >> 8) as u8)
.push_hex_u8((value & 0xFF) as u8)
}
const fn push_hex_u32(self, value: u32) -> Self {
self.push_hex_u16((value >> 16) as u16)
.push_hex_u16((value & 0xFFFF) as u16)
}
const fn push_amount(mut self, slice: &[u8], amount: usize) -> Self {
let mut i = 0;
while i < amount {
self.data[self.head + i] = slice[i];
i += 1;
}
self.head += i;
self
}
const fn push_guid(self, guid: &crate::GUID) -> Self {
self.push(b'{')
.push_hex_u32(guid.data1)
.push(b'-')
.push_hex_u16(guid.data2)
.push(b'-')
.push_hex_u16(guid.data3)
.push(b'-')
.push_hex_u16(((guid.data4[0] as u16) << 8) | guid.data4[1] as u16)
.push(b'-')
.push_hex_u16(((guid.data4[2] as u16) << 8) | guid.data4[3] as u16)
.push_hex_u16(((guid.data4[4] as u16) << 8) | guid.data4[5] as u16)
.push_hex_u16(((guid.data4[6] as u16) << 8) | guid.data4[7] as u16)
.push(b'}')
}
}
struct Blocks {
len: u32,
data: [u8; 64],
}
const fn process_blocks(
mut blocks: Blocks,
data: &ConstBuffer,
mut len: u64,
mut state: [u32; 5],
) -> (Blocks, u64, [u32; 5]) {
const fn as_block(input: &ConstBuffer, offset: usize) -> [u32; 16] {
let mut result = [0u32; 16];
let mut i = 0;
while i != 16 {
let off = offset + (i * 4);
result[i] = (input.get(off + 3) as u32)
| ((input.get(off + 2) as u32) << 8)
| ((input.get(off + 1) as u32) << 16)
| ((input.get(off) as u32) << 24);
i += 1;
}
result
}
const fn clone_from_slice_64(
mut data: [u8; 64],
slice: &[u8],
offset: usize,
num_elems: usize,
) -> [u8; 64] {
let mut i = 0;
while i < num_elems {
data[i] = slice[offset + i];
i += 1;
}
data
}
let mut i = 0;
while i < data.len() {
if data.len() - i >= 64 {
let chunk_block = as_block(data, i);
len += 64;
state = process_state(state, chunk_block);
i += 64;
} else {
let num_elems = data.len() - i;
blocks.data = clone_from_slice_64(blocks.data, &data.data, i, num_elems);
blocks.len = num_elems as u32;
break;
}
}
(blocks, len, state)
}
const fn process_state(mut state: [u32; 5], block: [u32; 16]) -> [u32; 5] {
let a = state[0];
let b = state[1];
let c = state[2];
let d = state[3];
let e = state[4];
let (block, b, e) = r0(block, a, b, c, d, e, 0);
let (block, a, d) = r0(block, e, a, b, c, d, 1);
let (block, e, c) = r0(block, d, e, a, b, c, 2);
let (block, d, b) = r0(block, c, d, e, a, b, 3);
let (block, c, a) = r0(block, b, c, d, e, a, 4);
let (block, b, e) = r0(block, a, b, c, d, e, 5);
let (block, a, d) = r0(block, e, a, b, c, d, 6);
let (block, e, c) = r0(block, d, e, a, b, c, 7);
let (block, d, b) = r0(block, c, d, e, a, b, 8);
let (block, c, a) = r0(block, b, c, d, e, a, 9);
let (block, b, e) = r0(block, a, b, c, d, e, 10);
let (block, a, d) = r0(block, e, a, b, c, d, 11);
let (block, e, c) = r0(block, d, e, a, b, c, 12);
let (block, d, b) = r0(block, c, d, e, a, b, 13);
let (block, c, a) = r0(block, b, c, d, e, a, 14);
let (block, b, e) = r0(block, a, b, c, d, e, 15);
let (block, a, d) = r1(block, e, a, b, c, d, 0);
let (block, e, c) = r1(block, d, e, a, b, c, 1);
let (block, d, b) = r1(block, c, d, e, a, b, 2);
let (block, c, a) = r1(block, b, c, d, e, a, 3);
let (block, b, e) = r2(block, a, b, c, d, e, 4);
let (block, a, d) = r2(block, e, a, b, c, d, 5);
let (block, e, c) = r2(block, d, e, a, b, c, 6);
let (block, d, b) = r2(block, c, d, e, a, b, 7);
let (block, c, a) = r2(block, b, c, d, e, a, 8);
let (block, b, e) = r2(block, a, b, c, d, e, 9);
let (block, a, d) = r2(block, e, a, b, c, d, 10);
let (block, e, c) = r2(block, d, e, a, b, c, 11);
let (block, d, b) = r2(block, c, d, e, a, b, 12);
let (block, c, a) = r2(block, b, c, d, e, a, 13);
let (block, b, e) = r2(block, a, b, c, d, e, 14);
let (block, a, d) = r2(block, e, a, b, c, d, 15);
let (block, e, c) = r2(block, d, e, a, b, c, 0);
let (block, d, b) = r2(block, c, d, e, a, b, 1);
let (block, c, a) = r2(block, b, c, d, e, a, 2);
let (block, b, e) = r2(block, a, b, c, d, e, 3);
let (block, a, d) = r2(block, e, a, b, c, d, 4);
let (block, e, c) = r2(block, d, e, a, b, c, 5);
let (block, d, b) = r2(block, c, d, e, a, b, 6);
let (block, c, a) = r2(block, b, c, d, e, a, 7);
let (block, b, e) = r3(block, a, b, c, d, e, 8);
let (block, a, d) = r3(block, e, a, b, c, d, 9);
let (block, e, c) = r3(block, d, e, a, b, c, 10);
let (block, d, b) = r3(block, c, d, e, a, b, 11);
let (block, c, a) = r3(block, b, c, d, e, a, 12);
let (block, b, e) = r3(block, a, b, c, d, e, 13);
let (block, a, d) = r3(block, e, a, b, c, d, 14);
let (block, e, c) = r3(block, d, e, a, b, c, 15);
let (block, d, b) = r3(block, c, d, e, a, b, 0);
let (block, c, a) = r3(block, b, c, d, e, a, 1);
let (block, b, e) = r3(block, a, b, c, d, e, 2);
let (block, a, d) = r3(block, e, a, b, c, d, 3);
let (block, e, c) = r3(block, d, e, a, b, c, 4);
let (block, d, b) = r3(block, c, d, e, a, b, 5);
let (block, c, a) = r3(block, b, c, d, e, a, 6);
let (block, b, e) = r3(block, a, b, c, d, e, 7);
let (block, a, d) = r3(block, e, a, b, c, d, 8);
let (block, e, c) = r3(block, d, e, a, b, c, 9);
let (block, d, b) = r3(block, c, d, e, a, b, 10);
let (block, c, a) = r3(block, b, c, d, e, a, 11);
let (block, b, e) = r4(block, a, b, c, d, e, 12);
let (block, a, d) = r4(block, e, a, b, c, d, 13);
let (block, e, c) = r4(block, d, e, a, b, c, 14);
let (block, d, b) = r4(block, c, d, e, a, b, 15);
let (block, c, a) = r4(block, b, c, d, e, a, 0);
let (block, b, e) = r4(block, a, b, c, d, e, 1);
let (block, a, d) = r4(block, e, a, b, c, d, 2);
let (block, e, c) = r4(block, d, e, a, b, c, 3);
let (block, d, b) = r4(block, c, d, e, a, b, 4);
let (block, c, a) = r4(block, b, c, d, e, a, 5);
let (block, b, e) = r4(block, a, b, c, d, e, 6);
let (block, a, d) = r4(block, e, a, b, c, d, 7);
let (block, e, c) = r4(block, d, e, a, b, c, 8);
let (block, d, b) = r4(block, c, d, e, a, b, 9);
let (block, c, a) = r4(block, b, c, d, e, a, 10);
let (block, b, e) = r4(block, a, b, c, d, e, 11);
let (block, a, d) = r4(block, e, a, b, c, d, 12);
let (block, e, c) = r4(block, d, e, a, b, c, 13);
let (block, d, b) = r4(block, c, d, e, a, b, 14);
let (_, c, a) = r4(block, b, c, d, e, a, 15);
state[0] = state[0].wrapping_add(a);
state[1] = state[1].wrapping_add(b);
state[2] = state[2].wrapping_add(c);
state[3] = state[3].wrapping_add(d);
state[4] = state[4].wrapping_add(e);
state
}
const fn digest(mut state: [u32; 5], len: u64, blocks: Blocks) -> Digest {
const fn clone_from_slice_128(
mut data: [u8; 128],
slice: &[u8],
offset: usize,
num_elems: usize,
) -> [u8; 128] {
let mut i = 0;
while i < num_elems {
data[i] = slice[offset + i];
i += 1;
}
data
}
const fn clone_slice_128(mut data: [u8; 128], slice: &[u8], _offset: usize) -> [u8; 128] {
let mut i = 0;
while i < slice.len() {
data[_offset + i] = slice[i];
i += 1;
}
data
}
const fn as_block(input: &[u8], offset: usize) -> [u32; 16] {
let mut result = [0u32; 16];
let mut i = 0;
while i != 16 {
let off = offset + (i * 4);
result[i] = (input[off + 3] as u32)
| ((input[off + 2] as u32) << 8)
| ((input[off + 1] as u32) << 16)
| ((input[off] as u32) << 24);
i += 1;
}
result
}
let bits = (len + (blocks.len as u64)) * 8;
let extra = [
(bits >> 56) as u8,
(bits >> 48) as u8,
(bits >> 40) as u8,
(bits >> 32) as u8,
(bits >> 24) as u8,
(bits >> 16) as u8,
(bits >> 8) as u8,
bits as u8,
];
let mut last = [0; 128];
let blocklen = blocks.len as usize;
last = clone_from_slice_128(last, &blocks.data, 0, blocklen);
last[blocklen] = 0x80;
if blocklen < 56 {
last = clone_slice_128(last, &extra, 56);
state = process_state(state, as_block(&last, 0));
} else {
last = clone_slice_128(last, &extra, 120);
state = process_state(state, as_block(&last, 0));
state = process_state(state, as_block(&last, 64));
}
Digest { data: state }
}
const fn rol(value: u32, bits: usize) -> u32 {
(value << bits) | (value >> (32 - bits))
}
const fn blk(block: &[u32], i: usize) -> u32 {
let value = block[(i + 13) & 15] ^ block[(i + 8) & 15] ^ block[(i + 2) & 15] ^ block[i];
rol(value, 1)
}
const fn r0(
block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
let n = ((w & (x ^ y)) ^ y)
.wrapping_add(block[i])
.wrapping_add(0x5a82_7999)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r1(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = ((w & (x ^ y)) ^ y)
.wrapping_add(block[i])
.wrapping_add(0x5a82_7999)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r2(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (w ^ x ^ y)
.wrapping_add(block[i])
.wrapping_add(0x6ed9_eba1)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r3(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (((w | x) & y) | (w & x))
.wrapping_add(block[i])
.wrapping_add(0x8f1b_bcdc)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
const fn r4(
mut block: [u32; 16],
v: u32,
mut w: u32,
x: u32,
y: u32,
mut z: u32,
i: usize,
) -> ([u32; 16], u32, u32) {
block[i] = blk(&block, i);
let n = (w ^ x ^ y)
.wrapping_add(block[i])
.wrapping_add(0xca62_c1d6)
.wrapping_add(rol(v, 5));
z = z.wrapping_add(n);
w = rol(w, 30);
(block, w, z)
}
pub struct Digest {
data: [u32; 5],
}
impl Digest {
pub const fn bytes(&self) -> [u8; 20] {
[
(self.data[0] >> 24) as u8,
(self.data[0] >> 16) as u8,
(self.data[0] >> 8) as u8,
self.data[0] as u8,
(self.data[1] >> 24) as u8,
(self.data[1] >> 16) as u8,
(self.data[1] >> 8) as u8,
self.data[1] as u8,
(self.data[2] >> 24) as u8,
(self.data[2] >> 16) as u8,
(self.data[2] >> 8) as u8,
self.data[2] as u8,
(self.data[3] >> 24) as u8,
(self.data[3] >> 16) as u8,
(self.data[3] >> 8) as u8,
self.data[3] as u8,
(self.data[4] >> 24) as u8,
(self.data[4] >> 16) as u8,
(self.data[4] >> 8) as u8,
self.data[4] as u8,
]
}
}
impl core::fmt::Display for Digest {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
for i in self.data.iter() {
write!(f, "{i:08x}")?;
}
Ok(())
}
}

View File

@@ -0,0 +1,327 @@
use super::*;
use crate::{IUnknown, IUnknown_Vtbl, Interface, GUID, HRESULT};
use core::ffi::c_void;
use core::mem::{transmute, transmute_copy};
use core::ptr::null_mut;
use core::sync::atomic::{AtomicIsize, Ordering};
#[repr(transparent)]
#[derive(Default)]
pub struct WeakRefCount(AtomicIsize);
impl WeakRefCount {
pub const fn new() -> Self {
Self(AtomicIsize::new(1))
}
pub fn add_ref(&self) -> u32 {
self.0
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count_or_pointer| {
bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer + 1)
})
.map(|u| u as u32 + 1)
.unwrap_or_else(|pointer| unsafe { TearOff::decode(pointer).strong_count.add_ref() })
}
#[inline(always)]
pub fn is_one(&self) -> bool {
self.0.load(Ordering::Acquire) == 1
}
pub fn release(&self) -> u32 {
self.0
.fetch_update(Ordering::Release, Ordering::Relaxed, |count_or_pointer| {
bool::then_some(!is_weak_ref(count_or_pointer), count_or_pointer - 1)
})
.map(|u| u as u32 - 1)
.unwrap_or_else(|pointer| unsafe {
let tear_off = TearOff::decode(pointer);
let remaining = tear_off.strong_count.release();
// If this is the last strong reference, we can release the weak reference implied by the strong reference.
// There may still be weak references, so the WeakRelease is called to handle such possibilities.
if remaining == 0 {
TearOff::WeakRelease(&mut tear_off.weak_vtable as *mut _ as _);
}
remaining
})
}
/// # Safety
pub unsafe fn query(&self, iid: &GUID, object: *mut c_void) -> *mut c_void {
unsafe {
if iid != &IWeakReferenceSource::IID {
return null_mut();
}
let mut count_or_pointer = self.0.load(Ordering::Relaxed);
if is_weak_ref(count_or_pointer) {
return TearOff::from_encoding(count_or_pointer);
}
let tear_off = TearOff::new(object, count_or_pointer as u32);
let tear_off_ptr: *mut c_void = transmute_copy(&tear_off);
let encoding: usize = ((tear_off_ptr as usize) >> 1) | (1 << (usize::BITS - 1));
loop {
match self.0.compare_exchange_weak(
count_or_pointer,
encoding as isize,
Ordering::AcqRel,
Ordering::Relaxed,
) {
Ok(_) => {
let result: *mut c_void = transmute(tear_off);
TearOff::from_strong_ptr(result).strong_count.add_ref();
return result;
}
Err(pointer) => count_or_pointer = pointer,
}
if is_weak_ref(count_or_pointer) {
return TearOff::from_encoding(count_or_pointer);
}
TearOff::from_strong_ptr(tear_off_ptr)
.strong_count
.0
.store(count_or_pointer as i32, Ordering::SeqCst);
}
}
}
}
fn is_weak_ref(value: isize) -> bool {
value < 0
}
#[repr(C)]
struct TearOff {
strong_vtable: *const IWeakReferenceSource_Vtbl,
weak_vtable: *const IWeakReference_Vtbl,
object: *mut c_void,
strong_count: RefCount,
weak_count: RefCount,
}
impl TearOff {
#[expect(clippy::new_ret_no_self)]
unsafe fn new(object: *mut c_void, strong_count: u32) -> IWeakReferenceSource {
unsafe {
transmute(Box::new(Self {
strong_vtable: &Self::STRONG_VTABLE,
weak_vtable: &Self::WEAK_VTABLE,
object,
strong_count: RefCount::new(strong_count),
weak_count: RefCount::new(1),
}))
}
}
unsafe fn from_encoding(encoding: isize) -> *mut c_void {
unsafe {
let tear_off = Self::decode(encoding);
tear_off.strong_count.add_ref();
tear_off as *mut _ as *mut _
}
}
const STRONG_VTABLE: IWeakReferenceSource_Vtbl = IWeakReferenceSource_Vtbl {
base__: IUnknown_Vtbl {
QueryInterface: Self::StrongQueryInterface,
AddRef: Self::StrongAddRef,
Release: Self::StrongRelease,
},
GetWeakReference: Self::StrongDowngrade,
};
const WEAK_VTABLE: IWeakReference_Vtbl = IWeakReference_Vtbl {
base__: IUnknown_Vtbl {
QueryInterface: Self::WeakQueryInterface,
AddRef: Self::WeakAddRef,
Release: Self::WeakRelease,
},
Resolve: Self::WeakUpgrade,
};
unsafe fn from_strong_ptr<'a>(this: *mut c_void) -> &'a mut Self {
unsafe { &mut *(this as *mut *mut c_void as *mut Self) }
}
unsafe fn from_weak_ptr<'a>(this: *mut c_void) -> &'a mut Self {
unsafe { &mut *((this as *mut *mut c_void).sub(1) as *mut Self) }
}
unsafe fn decode<'a>(value: isize) -> &'a mut Self {
unsafe { &mut *((value << 1) as *mut Self) as &mut Self }
}
unsafe fn query_interface(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT {
unsafe {
((*(*(self.object as *mut *mut IUnknown_Vtbl))).QueryInterface)(
self.object,
iid,
interface,
)
}
}
unsafe extern "system" fn StrongQueryInterface(
ptr: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = Self::from_strong_ptr(ptr);
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
// Only directly respond to queries for the the tear-off's strong interface. This is
// effectively a self-query.
if *iid == IWeakReferenceSource::IID {
*interface = ptr;
this.strong_count.add_ref();
return HRESULT(0);
}
// As the tear-off is sharing the identity of the object, simply delegate any remaining
// queries to the object.
this.query_interface(iid, interface)
}
}
unsafe extern "system" fn WeakQueryInterface(
ptr: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = Self::from_weak_ptr(ptr);
if iid.is_null() || interface.is_null() {
return E_POINTER;
}
// While the weak vtable is packed into the same allocation as the strong vtable and
// tear-off, it represents a distinct COM identity and thus does not share or delegate to
// the object.
*interface = if *iid == IWeakReference::IID
|| *iid == IUnknown::IID
|| *iid == IAgileObject::IID
{
ptr
} else {
#[cfg(windows)]
if *iid == IMarshal::IID {
this.weak_count.add_ref();
return marshaler(transmute::<*mut c_void, IUnknown>(ptr), interface);
}
null_mut()
};
if (*interface).is_null() {
E_NOINTERFACE
} else {
this.weak_count.add_ref();
HRESULT(0)
}
}
}
unsafe extern "system" fn StrongAddRef(ptr: *mut c_void) -> u32 {
unsafe {
let this = Self::from_strong_ptr(ptr);
// Implement `AddRef` directly as we own the strong reference.
this.strong_count.add_ref()
}
}
unsafe extern "system" fn WeakAddRef(ptr: *mut c_void) -> u32 {
unsafe {
let this = Self::from_weak_ptr(ptr);
// Implement `AddRef` directly as we own the weak reference.
this.weak_count.add_ref()
}
}
unsafe extern "system" fn StrongRelease(ptr: *mut c_void) -> u32 {
unsafe {
let this = Self::from_strong_ptr(ptr);
// Forward strong `Release` to the object so that it can destroy itself. It will then
// decrement its weak reference and allow the tear-off to be released as needed.
((*(*(this.object as *mut *mut IUnknown_Vtbl))).Release)(this.object)
}
}
unsafe extern "system" fn WeakRelease(ptr: *mut c_void) -> u32 {
unsafe {
let this = Self::from_weak_ptr(ptr);
// Implement `Release` directly as we own the weak reference.
let remaining = this.weak_count.release();
// If there are no remaining references, it means that the object has already been
// destroyed. Go ahead and destroy the tear-off.
if remaining == 0 {
let _ = Box::from_raw(this);
}
remaining
}
}
unsafe extern "system" fn StrongDowngrade(
ptr: *mut c_void,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = Self::from_strong_ptr(ptr);
// The strong vtable hands out a reference to the weak vtable. This is always safe and
// straightforward since a strong reference guarantees there is at least one weak
// reference.
*interface = &mut this.weak_vtable as *mut _ as _;
this.weak_count.add_ref();
HRESULT(0)
}
}
unsafe extern "system" fn WeakUpgrade(
ptr: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = Self::from_weak_ptr(ptr);
this.strong_count
.0
.fetch_update(Ordering::Acquire, Ordering::Relaxed, |count| {
// Attempt to acquire a strong reference count to stabilize the object for the duration
// of the `QueryInterface` call.
bool::then_some(count != 0, count + 1)
})
.map(|_| {
// Let the object respond to the upgrade query.
let result = this.query_interface(iid, interface);
// Decrement the temporary reference account used to stabilize the object.
this.strong_count.0.fetch_sub(1, Ordering::Relaxed);
// Return the result of the query.
result
})
.unwrap_or_else(|_| {
*interface = null_mut();
HRESULT(0)
})
}
}
}

11
vendor/windows-core/src/imp/windows.rs vendored Normal file
View File

@@ -0,0 +1,11 @@
mod factory_cache;
pub use factory_cache::*;
mod generic_factory;
pub use generic_factory::*;
mod marshaler;
pub use marshaler::*;
mod array_proxy;
pub use array_proxy::*;

123
vendor/windows-core/src/inspectable.rs vendored Normal file
View File

@@ -0,0 +1,123 @@
use super::*;
use core::ffi::c_void;
use core::ptr::null_mut;
/// Parent interface for all WinRT interfaces.
///
/// A WinRT object that may be used as a polymorphic stand-in for any WinRT class, interface, or boxed value.
/// [`IInspectable`] represents the
/// [IInspectable](https://docs.microsoft.com/en-us/windows/win32/api/inspectable/nn-inspectable-iinspectable)
/// interface.
#[repr(transparent)]
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct IInspectable(pub IUnknown);
interface_hierarchy!(IInspectable, IUnknown);
impl IInspectable {
/// Returns the canonical type name for the underlying object.
#[cfg(windows)]
pub fn GetRuntimeClassName(&self) -> Result<HSTRING> {
unsafe {
let mut abi = null_mut();
(self.vtable().GetRuntimeClassName)(core::mem::transmute_copy(self), &mut abi).ok()?;
Ok(core::mem::transmute::<*mut c_void, HSTRING>(abi))
}
}
/// Gets the trust level of the current object.
pub fn GetTrustLevel(&self) -> Result<i32> {
unsafe {
let mut value = 0;
(self.vtable().GetTrustLevel)(core::mem::transmute_copy(self), &mut value).ok()?;
Ok(value)
}
}
}
#[doc(hidden)]
#[repr(C)]
pub struct IInspectable_Vtbl {
pub base: IUnknown_Vtbl,
pub GetIids: unsafe extern "system" fn(
this: *mut c_void,
count: *mut u32,
values: *mut *mut GUID,
) -> HRESULT,
pub GetRuntimeClassName:
unsafe extern "system" fn(this: *mut c_void, value: *mut *mut c_void) -> HRESULT,
pub GetTrustLevel: unsafe extern "system" fn(this: *mut c_void, value: *mut i32) -> HRESULT,
}
unsafe impl Interface for IInspectable {
type Vtable = IInspectable_Vtbl;
const IID: GUID = GUID::from_u128(0xaf86e2e0_b12d_4c6a_9c5a_d7aa65101e90);
}
impl RuntimeType for IInspectable {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"cinterface(IInspectable)");
}
impl RuntimeName for IInspectable {}
impl IInspectable_Vtbl {
pub const fn new<Identity: IUnknownImpl, Name: RuntimeName, const OFFSET: isize>() -> Self {
unsafe extern "system" fn GetIids(
_: *mut c_void,
count: *mut u32,
values: *mut *mut GUID,
) -> HRESULT {
unsafe {
if count.is_null() || values.is_null() {
return imp::E_POINTER;
}
// Note: even if we end up implementing this in future, it still doesn't need a this pointer
// since the data to be returned is type- not instance-specific so can be shared for all
// interfaces.
*count = 0;
*values = null_mut();
HRESULT(0)
}
}
unsafe extern "system" fn GetRuntimeClassName<T: RuntimeName>(
_: *mut c_void,
value: *mut *mut c_void,
) -> HRESULT {
unsafe {
if value.is_null() {
return imp::E_POINTER;
}
#[cfg(windows)]
{
*value = core::mem::transmute::<HSTRING, *mut c_void>(T::NAME.into());
}
#[cfg(not(windows))]
{
*value = core::ptr::null_mut();
}
HRESULT(0)
}
}
unsafe extern "system" fn GetTrustLevel<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
value: *mut i32,
) -> HRESULT {
unsafe {
if value.is_null() {
return imp::E_POINTER;
}
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).GetTrustLevel(value)
}
}
Self {
base: IUnknown_Vtbl::new::<Identity, OFFSET>(),
GetIids,
GetRuntimeClassName: GetRuntimeClassName::<Name>,
GetTrustLevel: GetTrustLevel::<Identity, OFFSET>,
}
}
}

339
vendor/windows-core/src/interface.rs vendored Normal file
View File

@@ -0,0 +1,339 @@
use super::*;
use core::any::Any;
use core::ffi::c_void;
use core::marker::PhantomData;
use core::mem::{forget, transmute_copy, MaybeUninit};
use core::ptr::NonNull;
/// Provides low-level access to an interface vtable.
///
/// This trait is automatically implemented by the generated bindings and should not be
/// implemented manually.
///
/// # Safety
pub unsafe trait Interface: Sized + Clone {
#[doc(hidden)]
type Vtable;
/// The `GUID` associated with the interface.
const IID: GUID;
#[doc(hidden)]
const UNKNOWN: bool = true;
/// A reference to the interface's vtable
#[doc(hidden)]
#[inline(always)]
fn vtable(&self) -> &Self::Vtable {
// SAFETY: the implementor of the trait guarantees that `Self` is castable to its vtable
unsafe { self.assume_vtable::<Self>() }
}
/// Cast this interface as a reference to the supplied interfaces `Vtable`
///
/// # Safety
///
/// This is safe if `T` is an equivalent interface to `Self` or a super interface.
/// In other words, `T::Vtable` must be equivalent to the beginning of `Self::Vtable`.
#[doc(hidden)]
#[inline(always)]
unsafe fn assume_vtable<T: Interface>(&self) -> &T::Vtable {
unsafe { &**(self.as_raw() as *mut *mut T::Vtable) }
}
/// Returns the raw COM interface pointer. The resulting pointer continues to be owned by the `Interface` implementation.
#[inline(always)]
fn as_raw(&self) -> *mut c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
unsafe { transmute_copy(self) }
}
/// Returns the raw COM interface pointer and releases ownership. It the caller's responsibility to release the COM interface pointer.
#[inline(always)]
fn into_raw(self) -> *mut c_void {
// SAFETY: implementors of this trait must guarantee that the implementing type has a pointer in-memory representation
let raw = self.as_raw();
forget(self);
raw
}
/// Creates an `Interface` by taking ownership of the `raw` COM interface pointer.
///
/// # Safety
///
/// The `raw` pointer must be owned by the caller and represent a valid COM interface pointer. In other words,
/// it must point to a vtable beginning with the `IUnknown` function pointers and match the vtable of `Interface`.
unsafe fn from_raw(raw: *mut c_void) -> Self {
unsafe { transmute_copy(&raw) }
}
/// Creates an `Interface` that is valid so long as the `raw` COM interface pointer is valid.
///
/// # Safety
///
/// The `raw` pointer must be a valid COM interface pointer. In other words, it must point to a vtable
/// beginning with the `IUnknown` function pointers and match the vtable of `Interface`.
#[inline(always)]
unsafe fn from_raw_borrowed(raw: &*mut c_void) -> Option<&Self> {
unsafe {
if raw.is_null() {
None
} else {
Some(transmute_copy(&raw))
}
}
}
/// Attempts to cast the current interface to another interface using `QueryInterface`.
///
/// The name `cast` is preferred to `query` because there is a WinRT method named query but not one
/// named cast.
#[inline(always)]
fn cast<T: Interface>(&self) -> Result<T> {
// SAFETY: `result` is valid for writing an interface pointer and it is safe
// to cast the `result` pointer as `T` on success because we are using the `IID` tied
// to `T` which the implementor of `Interface` has guaranteed is correct
unsafe {
// If query() returns a failure code then we propagate that failure code to the caller.
// In that case, we ignore the contents of 'result' (which will _not_ be dropped,
// because MaybeUninit intentionally does not drop its contents).
//
// This guards against implementations of COM interfaces which may store non-null values
// in 'result' but still return E_NOINTERFACE.
let mut result = MaybeUninit::<Option<T>>::zeroed();
self.query(&T::IID, result.as_mut_ptr() as _).ok()?;
// If we get here, then query() has succeeded, but we still need to double-check
// that the output pointer is non-null.
if let Some(obj) = result.assume_init() {
Ok(obj)
} else {
Err(imp::E_POINTER.into())
}
}
}
/// This casts the given COM interface to [`&dyn Any`].
///
/// Applications should generally _not_ call this method directly. Instead, use the
/// [`Interface::cast_object_ref`] or [`Interface::cast_object`] methods.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// # Safety
///
/// **IMPORTANT!!** This uses a non-standard protocol for QueryInterface! The `DYNAMIC_CAST_IID`
/// IID identifies this protocol, but there is no `IDynamicCast` interface. Instead, objects
/// that recognize `DYNAMIC_CAST_IID` simply store their `&dyn Any` directly at the interface
/// pointer that was passed to `QueryInterface. This means that the returned value has a
/// size that is twice as large (`size_of::<&dyn Any>() == 2 * size_of::<*const c_void>()`).
///
/// This means that callers that use this protocol cannot simply pass `&mut ptr` for
/// an ordinary single-pointer-sized pointer. Only this method understands this protocol.
///
/// Another part of this protocol is that the implementation of `QueryInterface` _does not_
/// AddRef the object. The caller must guarantee the liveness of the COM object. In Rust,
/// this means tying the lifetime of the IUnknown* that we used for the QueryInterface
/// call to the lifetime of the returned `&dyn Any` value.
///
/// This method preserves type safety and relies on these invariants:
///
/// * All `QueryInterface` implementations that recognize `DYNAMIC_CAST_IID` are generated by
/// the `#[implement]` macro and respect the rules described here.
#[inline(always)]
fn cast_to_any<T>(&self) -> Result<&dyn Any>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
unsafe {
let mut any_ref_arg: MaybeUninit<&dyn Any> = MaybeUninit::zeroed();
self.query(
&DYNAMIC_CAST_IID,
any_ref_arg.as_mut_ptr() as *mut *mut c_void,
)
.ok()?;
Ok(any_ref_arg.assume_init())
}
}
/// Returns `true` if the given COM interface refers to an implementation of `T`.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `false`.
#[inline(always)]
fn is_object<T>(&self) -> bool
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
if let Ok(any) = self.cast_to_any::<T>() {
any.is::<T::Outer>()
} else {
false
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `&MyApp_Impl`, not the inner `&MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is borrowed. If you need an owned (counted) reference, then use
/// [`Interface::cast_object`].
#[inline(always)]
fn cast_object_ref<T>(&self) -> Result<&T::Outer>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
let any: &dyn Any = self.cast_to_any::<T>()?;
if let Some(outer) = any.downcast_ref::<T::Outer>() {
Ok(outer)
} else {
Err(imp::E_NOINTERFACE.into())
}
}
/// This casts the given COM interface to [`&dyn Any`]. It returns a reference to the "outer"
/// object, e.g. `MyApp_Impl`, not the inner `MyApp` object.
///
/// `T` must be a type that has been annotated with `#[implement]`; this is checked at
/// compile-time by the generic constraints of this method. However, note that the
/// returned `&dyn Any` refers to the _outer_ implementation object that was generated by
/// `#[implement]`, i.e. the `MyApp_Impl` type, not the inner `MyApp` type.
///
/// If the given object is not a Rust object, or is a Rust object but not `T`, or is a Rust
/// object that contains non-static lifetimes, then this function will return `Err(E_NOINTERFACE)`.
///
/// The returned value is an owned (counted) reference; this function calls `AddRef` on the
/// underlying COM object. If you do not need an owned reference, then you can use the
/// [`Interface::cast_object_ref`] method instead, and avoid the cost of `AddRef` / `Release`.
#[inline(always)]
fn cast_object<T>(&self) -> Result<ComObject<T>>
where
T: ComObjectInner,
T::Outer: Any + 'static + IUnknownImpl<Impl = T>,
{
let object_ref = self.cast_object_ref::<T>()?;
Ok(object_ref.to_object())
}
/// Attempts to create a [`Weak`] reference to this object.
fn downgrade(&self) -> Result<Weak<Self>> {
self.cast::<imp::IWeakReferenceSource>()
.map(|source| Weak::downgrade(&source))
}
/// Call `QueryInterface` on this interface
///
/// # Safety
///
/// `interface` must be a non-null, valid pointer for writing an interface pointer.
#[inline(always)]
unsafe fn query(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT {
unsafe {
if Self::UNKNOWN {
(self.assume_vtable::<IUnknown>().QueryInterface)(self.as_raw(), iid, interface)
} else {
panic!("Non-COM interfaces cannot be queried.")
}
}
}
/// Creates an `InterfaceRef` for this reference. The `InterfaceRef` tracks lifetimes statically,
/// and eliminates the need for dynamic reference count adjustments (AddRef/Release).
fn to_ref(&self) -> InterfaceRef<'_, Self> {
InterfaceRef::from_interface(self)
}
}
/// This has the same memory representation as `IFoo`, but represents a borrowed interface pointer.
///
/// This type has no `Drop` impl; it does not AddRef/Release the given interface. However, because
/// it has a lifetime parameter, it always represents a non-null pointer to an interface.
#[repr(transparent)]
pub struct InterfaceRef<'a, I>(NonNull<c_void>, PhantomData<&'a I>);
impl<I> Copy for InterfaceRef<'_, I> {}
impl<I> Clone for InterfaceRef<'_, I> {
fn clone(&self) -> Self {
*self
}
}
impl<I: core::fmt::Debug + Interface> core::fmt::Debug for InterfaceRef<'_, I> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
<I as core::fmt::Debug>::fmt(&**self, f)
}
}
impl<I: Interface> InterfaceRef<'_, I> {
/// Creates an `InterfaceRef` from a raw pointer. _This is extremely dangerous, since there
/// is no lifetime tracking at all!_
///
/// # Safety
/// The caller must guarantee that the `'a` lifetime parameter is bound by context to a correct
/// lifetime.
#[inline(always)]
pub unsafe fn from_raw(ptr: NonNull<c_void>) -> Self {
Self(ptr, PhantomData)
}
/// Creates an `InterfaceRef` from an interface reference. This safely associates the lifetime
/// of the interface reference with the `'a` parameter of `InterfaceRef`. This allows for
/// lifetime checking _without_ calling AddRef/Release on the underlying lifetime, which can
/// improve efficiency.
#[inline(always)]
pub fn from_interface(interface: &I) -> Self {
unsafe {
// SAFETY: new_unchecked() should be valid because Interface::as_raw should always
// return a non-null pointer.
Self(NonNull::new_unchecked(interface.as_raw()), PhantomData)
}
}
/// Calls AddRef on the underlying COM interface and returns an "owned" (counted) reference.
#[inline(always)]
pub fn to_owned(self) -> I {
(*self).clone()
}
}
impl<'a, 'i: 'a, I: Interface> From<&'i I> for InterfaceRef<'a, I> {
#[inline(always)]
fn from(interface: &'a I) -> Self {
InterfaceRef::from_interface(interface)
}
}
impl<I: Interface> core::ops::Deref for InterfaceRef<'_, I> {
type Target = I;
#[inline(always)]
fn deref(&self) -> &I {
unsafe { core::mem::transmute(self) }
}
}
/// This IID identifies a special protocol, used by [`Interface::cast_to_any`]. This is _not_
/// an ordinary COM interface; it uses special lifetime rules and a larger interface pointer.
/// See the comments on [`Interface::cast_to_any`].
#[doc(hidden)]
pub const DYNAMIC_CAST_IID: GUID = GUID::from_u128(0xae49d5cb_143f_431c_874c_2729336e4eca);

61
vendor/windows-core/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,61 @@
#![doc = include_str!("../readme.md")]
#![doc(html_no_source)]
#![debugger_visualizer(natvis_file = "../windows-core.natvis")]
#![cfg_attr(all(not(feature = "std")), no_std)]
#![expect(
non_snake_case,
non_camel_case_types,
dead_code,
clippy::missing_transmute_annotations,
clippy::upper_case_acronyms
)]
#[cfg(windows)]
include!("windows.rs");
extern crate self as windows_core;
extern crate alloc;
use alloc::boxed::Box;
#[doc(hidden)]
pub mod imp;
mod as_impl;
mod com_object;
mod guid;
mod inspectable;
mod interface;
mod out_param;
mod out_ref;
mod param;
mod param_value;
mod r#ref;
mod runtime_name;
mod runtime_type;
mod scoped_interface;
mod r#type;
mod unknown;
mod weak;
pub use as_impl::*;
pub use com_object::*;
pub use guid::*;
pub use inspectable::*;
pub use interface::*;
pub use out_param::*;
pub use out_ref::*;
pub use param::*;
pub use param_value::*;
pub use r#ref::*;
pub use r#type::*;
pub use runtime_name::*;
pub use runtime_type::*;
pub use scoped_interface::*;
pub use unknown::*;
pub use weak::*;
pub use windows_implement::implement;
pub use windows_interface::interface;
pub use windows_link::link;
pub use windows_result::*;

63
vendor/windows-core/src/out_param.rs vendored Normal file
View File

@@ -0,0 +1,63 @@
use super::*;
use core::mem::{take, transmute_copy, zeroed};
/// Provides automatic parameter conversion in cases where the Windows API expects implicit conversion support.
///
/// This is a mutable version of [Param] meant to support out parameters.
/// There is no need to implement this trait. Blanket implementations are provided for all applicable Windows types.
pub trait OutParam<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
#[doc(hidden)]
unsafe fn borrow_mut(&self) -> OutRef<'_, T>;
}
impl<T> OutParam<T, CloneType> for &mut T
where
T: TypeKind<TypeKind = CloneType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
unsafe {
let this: &mut T = transmute_copy(self);
take(this);
transmute_copy(self)
}
}
}
impl<T> OutParam<T, CopyType> for &mut T
where
T: TypeKind<TypeKind = CopyType> + Clone + Default,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
unsafe { transmute_copy(self) }
}
}
impl<T> OutParam<T, InterfaceType> for &mut Option<T>
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
unsafe {
let this: &mut Option<T> = transmute_copy(self);
take(this);
transmute_copy(self)
}
}
}
impl<T> OutParam<T> for Option<&mut T>
where
T: Type<T>,
{
unsafe fn borrow_mut(&self) -> OutRef<'_, T> {
unsafe {
match self {
Some(this) => transmute_copy(this),
None => zeroed(),
}
}
}
}

37
vendor/windows-core/src/out_ref.rs vendored Normal file
View File

@@ -0,0 +1,37 @@
use super::*;
/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
///
/// This is a mutable version of [Ref] meant to support out parameters.
#[repr(transparent)]
pub struct OutRef<'a, T: Type<T>>(*mut T::Abi, core::marker::PhantomData<&'a T>);
impl<T: Type<T>> OutRef<'_, T> {
/// Returns `true` if the argument is null.
pub fn is_null(&self) -> bool {
self.0.is_null()
}
/// Overwrites a memory location with the given value without reading or dropping the old value.
pub fn write(self, value: T::Default) -> Result<()> {
if self.0.is_null() {
Err(Error::from_hresult(imp::E_POINTER))
} else {
unsafe { *self.0 = core::mem::transmute_copy(&value) }
core::mem::forget(value);
Ok(())
}
}
}
impl<'a, T: Type<T>> From<&'a mut T::Default> for OutRef<'a, T> {
fn from(from: &'a mut T::Default) -> Self {
unsafe { core::mem::transmute(from) }
}
}
impl<T: Type<T>> Default for OutRef<'_, T> {
fn default() -> Self {
unsafe { core::mem::zeroed() }
}
}

76
vendor/windows-core/src/param.rs vendored Normal file
View File

@@ -0,0 +1,76 @@
use super::*;
use core::mem::transmute_copy;
use core::mem::zeroed;
/// Provides automatic parameter conversion in cases where the Windows API expects implicit conversion support.
///
/// There is no need to implement this trait. Blanket implementations are provided for all applicable Windows types.
pub trait Param<T: TypeKind, C = <T as TypeKind>::TypeKind>: Sized
where
T: Type<T>,
{
#[doc(hidden)]
unsafe fn param(self) -> ParamValue<T>;
}
impl<T> Param<T> for Option<&T>
where
T: Type<T>,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe {
ParamValue::Borrowed(match self {
Some(item) => transmute_copy(item),
None => zeroed(),
})
}
}
}
impl<T> Param<T> for InterfaceRef<'_, T>
where
T: Type<T>,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe { ParamValue::Borrowed(transmute_copy(&self)) }
}
}
impl<T, U> Param<T, InterfaceType> for &U
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
T: Interface,
U: Interface,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe {
if U::QUERY {
self.cast()
.map_or(ParamValue::Borrowed(zeroed()), |ok| ParamValue::Owned(ok))
} else {
ParamValue::Borrowed(transmute_copy(self))
}
}
}
}
impl<T> Param<T, CloneType> for &T
where
T: TypeKind<TypeKind = CloneType> + Clone,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe { ParamValue::Borrowed(transmute_copy(self)) }
}
}
impl<T, U> Param<T, CopyType> for U
where
T: TypeKind<TypeKind = CopyType> + Clone,
U: TypeKind<TypeKind = CopyType> + Clone,
U: imp::CanInto<T>,
{
unsafe fn param(self) -> ParamValue<T> {
unsafe { ParamValue::Owned(transmute_copy(&self)) }
}
}

24
vendor/windows-core/src/param_value.rs vendored Normal file
View File

@@ -0,0 +1,24 @@
use super::*;
use core::mem::transmute_copy;
#[doc(hidden)]
pub enum ParamValue<T: Type<T>> {
Owned(T),
Borrowed(T::Abi),
}
impl<T: Type<T>> ParamValue<T> {
// TODO: replace with `borrow` in windows-bindgen
pub fn abi(&self) -> T::Abi {
unsafe {
match self {
Self::Owned(item) => transmute_copy(item),
Self::Borrowed(borrowed) => transmute_copy(borrowed),
}
}
}
pub fn borrow(&self) -> Ref<'_, T> {
unsafe { transmute_copy(&self.abi()) }
}
}

88
vendor/windows-core/src/ref.rs vendored Normal file
View File

@@ -0,0 +1,88 @@
use super::*;
use core::mem::transmute;
/// A borrowed type with the same memory layout as the type itself that can be used to construct ABI-compatible function signatures.
#[repr(transparent)]
pub struct Ref<'a, T: Type<T>>(T::Abi, core::marker::PhantomData<&'a T>);
impl<T: Type<T>> Ref<'_, T> {
/// Returns `true` if the argument is null.
pub fn is_null(&self) -> bool {
T::is_null(&self.0)
}
/// Converts the argument to a [`Result<&T>`] reference.
pub fn ok(&self) -> Result<&T> {
self.as_ref()
.ok_or_else(|| Error::from_hresult(imp::E_POINTER))
}
/// Converts the argument to a [`Option<&T>`] reference.
pub fn as_ref(&self) -> Option<&T> {
if self.is_null() {
None
} else {
unsafe { Some(self.assume_init_ref()) }
}
}
/// Converts the argument to a `&T` reference.
///
/// # Panics
///
/// Panics if the argument is null.
#[track_caller]
pub fn unwrap(&self) -> &T {
self.as_ref().expect("called `Ref::unwrap` on a null value")
}
/// Converts the argument to an [`Option<T>`] by cloning the reference.
pub fn cloned(&self) -> Option<T> {
self.as_ref().cloned()
}
unsafe fn assume_init_ref(&self) -> &T {
unsafe { T::assume_init_ref(&self.0) }
}
}
impl<T: Type<T>> Default for Ref<'_, T> {
fn default() -> Self {
unsafe { core::mem::zeroed() }
}
}
impl<T: Type<T>> core::ops::Deref for Ref<'_, T> {
type Target = T::Default;
fn deref(&self) -> &Self::Target {
unsafe { transmute(&self.0) }
}
}
impl<'a, T: Type<T, InterfaceType>> From<&'a Option<T>> for Ref<'a, T>
where
T: TypeKind<TypeKind = InterfaceType>,
{
fn from(from: &'a Option<T>) -> Self {
unsafe { core::mem::transmute_copy(from) }
}
}
impl<'a, T: Type<T, InterfaceType>> From<Option<&'a T>> for Ref<'a, T>
where
T: TypeKind<TypeKind = InterfaceType>,
{
fn from(from: Option<&'a T>) -> Self {
if let Some(from) = from {
unsafe { core::mem::transmute_copy(from) }
} else {
unsafe { core::mem::zeroed() }
}
}
}
impl<'a, T: Type<T>> From<&'a T> for Ref<'a, T> {
fn from(from: &'a T) -> Self {
unsafe { core::mem::transmute_copy(from) }
}
}

View File

@@ -0,0 +1,5 @@
#[doc(hidden)]
pub trait RuntimeName {
// TODO: needs to use ConstBuffer like RuntimeType to allow generic interfaces to have names for GetRuntimeClassName
const NAME: &'static str = "";
}

30
vendor/windows-core/src/runtime_type.rs vendored Normal file
View File

@@ -0,0 +1,30 @@
use super::*;
#[doc(hidden)]
pub trait RuntimeType: Type<Self> {
const SIGNATURE: imp::ConstBuffer;
}
macro_rules! primitives {
($(($t:ty, $s:literal)),+) => {
$(
impl RuntimeType for $t {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice($s);
}
)*
};
}
primitives! {
(bool, b"b1"),
(i8, b"i1"),
(u8, b"u1"),
(i16, b"i2"),
(u16, b"u2"),
(i32, b"i4"),
(u32, b"u4"),
(i64, b"i8"),
(u64, b"u8"),
(f32, b"f4"),
(f64, b"f8")
}

View File

@@ -0,0 +1,41 @@
use super::*;
use core::ffi::c_void;
use core::marker::PhantomData;
#[doc(hidden)]
#[repr(C)]
pub struct ScopedHeap {
pub vtable: *const c_void,
pub this: *const c_void,
}
#[doc(hidden)]
pub struct ScopedInterface<'a, T: Interface> {
interface: T,
lifetime: PhantomData<&'a T>,
}
impl<T: Interface> ScopedInterface<'_, T> {
pub fn new(interface: T) -> Self {
Self {
interface,
lifetime: PhantomData,
}
}
}
impl<T: Interface> core::ops::Deref for ScopedInterface<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.interface
}
}
impl<T: Interface> Drop for ScopedInterface<'_, T> {
fn drop(&mut self) {
unsafe {
let _ = Box::from_raw(self.interface.as_raw() as *const _ as *mut ScopedHeap);
}
}
}

127
vendor/windows-core/src/type.rs vendored Normal file
View File

@@ -0,0 +1,127 @@
use super::*;
#[doc(hidden)]
pub trait TypeKind {
type TypeKind;
}
#[doc(hidden)]
pub struct InterfaceType;
#[doc(hidden)]
pub struct CloneType;
#[doc(hidden)]
pub struct CopyType;
#[doc(hidden)]
pub trait Type<T: TypeKind, C = <T as TypeKind>::TypeKind>: TypeKind + Sized + Clone {
type Abi;
type Default;
fn is_null(abi: &Self::Abi) -> bool;
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self;
unsafe fn from_abi(abi: Self::Abi) -> Result<Self>;
fn from_default(default: &Self::Default) -> Result<Self>;
}
impl<T> Type<T, InterfaceType> for T
where
T: TypeKind<TypeKind = InterfaceType> + Clone,
{
type Abi = *mut core::ffi::c_void;
type Default = Option<Self>;
fn is_null(abi: &Self::Abi) -> bool {
abi.is_null()
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
unsafe { core::mem::transmute::<&*mut core::ffi::c_void, &T>(abi) }
}
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
unsafe {
if !abi.is_null() {
Ok(core::mem::transmute_copy(&abi))
} else {
Err(Error::empty())
}
}
}
fn from_default(default: &Self::Default) -> Result<Self> {
default.as_ref().cloned().ok_or(Error::empty())
}
}
impl<T> Type<T, CloneType> for T
where
T: TypeKind<TypeKind = CloneType> + Clone,
{
type Abi = core::mem::MaybeUninit<Self>;
type Default = Self;
fn is_null(_: &Self::Abi) -> bool {
false
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
unsafe { abi.assume_init_ref() }
}
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
unsafe { Ok(abi.assume_init()) }
}
fn from_default(default: &Self::Default) -> Result<Self> {
Ok(default.clone())
}
}
impl<T> Type<T, CopyType> for T
where
T: TypeKind<TypeKind = CopyType> + Clone,
{
type Abi = Self;
type Default = Self;
fn is_null(_: &Self::Abi) -> bool {
false
}
unsafe fn assume_init_ref(abi: &Self::Abi) -> &Self {
abi
}
unsafe fn from_abi(abi: Self::Abi) -> Result<Self> {
Ok(abi)
}
fn from_default(default: &Self) -> Result<Self> {
Ok(default.clone())
}
}
impl<T: Interface> TypeKind for T {
type TypeKind = InterfaceType;
}
impl<T> TypeKind for *mut T {
type TypeKind = CopyType;
}
macro_rules! primitives {
($($t:ty),+) => {
$(
impl TypeKind for $t {
type TypeKind = CopyType;
}
)*
};
}
primitives!(bool, i8, u8, i16, u16, i32, u32, i64, u64, f32, f64, usize, isize);
#[doc(hidden)]
pub type AbiType<T> = <T as Type<T>>::Abi;

186
vendor/windows-core/src/unknown.rs vendored Normal file
View File

@@ -0,0 +1,186 @@
use super::*;
use core::ffi::c_void;
use core::ptr::NonNull;
/// Base interface for all COM interfaces.
///
/// All COM interfaces (and thus WinRT classes and interfaces) implement
/// [IUnknown](https://docs.microsoft.com/en-us/windows/win32/api/unknwn/nn-unknwn-iunknown)
/// under the hood to provide reference-counted lifetime management as well as the ability
/// to query for additional interfaces that the object may implement.
#[repr(transparent)]
pub struct IUnknown(NonNull<c_void>);
#[doc(hidden)]
#[repr(C)]
pub struct IUnknown_Vtbl {
pub QueryInterface: unsafe extern "system" fn(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT,
pub AddRef: unsafe extern "system" fn(this: *mut c_void) -> u32,
pub Release: unsafe extern "system" fn(this: *mut c_void) -> u32,
}
unsafe impl Interface for IUnknown {
type Vtable = IUnknown_Vtbl;
const IID: GUID = GUID::from_u128(0x00000000_0000_0000_c000_000000000046);
}
impl Clone for IUnknown {
fn clone(&self) -> Self {
unsafe {
(self.vtable().AddRef)(core::mem::transmute_copy(self));
}
Self(self.0)
}
}
impl Drop for IUnknown {
fn drop(&mut self) {
unsafe {
(self.vtable().Release)(core::mem::transmute_copy(self));
}
}
}
impl PartialEq for IUnknown {
fn eq(&self, other: &Self) -> bool {
// First we test for ordinary pointer equality. If two COM interface pointers have the
// same pointer value, then they are the same object. This can save us a lot of time,
// since calling QueryInterface is much more expensive than a single pointer comparison.
//
// However, interface pointers may have different values and yet point to the same object.
// Since COM objects may implement multiple interfaces, COM identity can only
// be determined by querying for `IUnknown` explicitly and then comparing the
// pointer values. This works since `QueryInterface` is required to return
// the same pointer value for queries for `IUnknown`.
core::ptr::eq(self.as_raw(), other.as_raw())
|| self.cast::<Self>().unwrap().0 == other.cast::<Self>().unwrap().0
}
}
impl Eq for IUnknown {}
impl core::fmt::Debug for IUnknown {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_tuple("IUnknown").field(&self.as_raw()).finish()
}
}
/// The `#[implement]` macro generates implementations of this trait for the types
/// that it generates, e.g. `MyApp_Impl`,
///
/// `ComObject` uses this trait to interact with boxed COM objects.
#[doc(hidden)]
pub trait IUnknownImpl {
/// The contained user type, e.g. `MyApp`. Also known as the "inner" type.
type Impl;
/// Get a reference to the backing implementation.
fn get_impl(&self) -> &Self::Impl;
/// Get a mutable reference to the contained (inner) object.
fn get_impl_mut(&mut self) -> &mut Self::Impl;
/// Consumes the box and returns the contained (inner) object. This is the opposite of `new_box`.
fn into_inner(self) -> Self::Impl;
/// The classic `QueryInterface` method from COM.
///
/// # Safety
///
/// This function is safe to call as long as the interface pointer is non-null and valid for writes
/// of an interface pointer.
unsafe fn QueryInterface(&self, iid: *const GUID, interface: *mut *mut c_void) -> HRESULT;
/// Increments the reference count of the interface
fn AddRef(&self) -> u32;
/// Decrements the reference count causing the interface's memory to be freed when the count is 0
///
/// # Safety
///
/// This function should only be called when the interface pointer is no longer used as calling `Release`
/// on a non-aliased interface pointer and then using that interface pointer may result in use after free.
///
/// This function takes `*mut Self` because the object may be freed by the time this method returns.
/// Taking `&self` would violate Rust's rules on reference lifetime.
unsafe fn Release(self_: *mut Self) -> u32;
/// Returns `true` if the reference count of the box is equal to 1.
fn is_reference_count_one(&self) -> bool;
/// Gets the trust level of the current object.
unsafe fn GetTrustLevel(&self, value: *mut i32) -> HRESULT;
/// Gets a borrowed reference to an interface that is implemented by this ComObject.
///
/// The returned reference does not have an additional reference count.
/// You can AddRef it by calling to_owned().
#[inline(always)]
fn as_interface<I: Interface>(&self) -> InterfaceRef<'_, I>
where
Self: ComObjectInterface<I>,
{
<Self as ComObjectInterface<I>>::as_interface_ref(self)
}
/// Gets an owned (counted) reference to an interface that is implemented by this ComObject.
#[inline(always)]
fn to_interface<I: Interface>(&self) -> I
where
Self: ComObjectInterface<I>,
{
<Self as ComObjectInterface<I>>::as_interface_ref(self).to_owned()
}
/// Creates a new owned reference to this object.
///
/// # Safety
///
/// This function can only be safely called by `<Foo>_Impl` objects that are embedded in a
/// `ComObject`. Since we only allow safe Rust code to access these objects using a `ComObject`
/// or a `&<Foo>_Impl` that points within a `ComObject`, this is safe.
fn to_object(&self) -> ComObject<Self::Impl>
where
Self::Impl: ComObjectInner<Outer = Self>;
}
impl IUnknown_Vtbl {
pub const fn new<T: IUnknownImpl, const OFFSET: isize>() -> Self {
unsafe extern "system" fn QueryInterface<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
iid: *const GUID,
interface: *mut *mut c_void,
) -> HRESULT {
unsafe {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).QueryInterface(iid, interface)
}
}
unsafe extern "system" fn AddRef<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
) -> u32 {
unsafe {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
(*this).AddRef()
}
}
unsafe extern "system" fn Release<T: IUnknownImpl, const OFFSET: isize>(
this: *mut c_void,
) -> u32 {
unsafe {
let this = (this as *mut *mut c_void).offset(OFFSET) as *mut T;
T::Release(this)
}
}
Self {
QueryInterface: QueryInterface::<T, OFFSET>,
AddRef: AddRef::<T, OFFSET>,
Release: Release::<T, OFFSET>,
}
}
}

28
vendor/windows-core/src/weak.rs vendored Normal file
View File

@@ -0,0 +1,28 @@
use super::*;
use core::marker::PhantomData;
/// `Weak` holds a non-owning reference to an object.
#[derive(Clone, PartialEq, Eq, Default)]
pub struct Weak<I: Interface>(Option<imp::IWeakReference>, PhantomData<I>);
impl<I: Interface> Weak<I> {
/// Creates a new `Weak` object without any backing object.
pub const fn new() -> Self {
Self(None, PhantomData)
}
/// Attempts to upgrade the weak reference to a strong reference.
pub fn upgrade(&self) -> Option<I> {
self.0
.as_ref()
.and_then(|inner| unsafe { inner.Resolve().ok() })
}
pub(crate) fn downgrade(source: &imp::IWeakReferenceSource) -> Self {
let reference = unsafe { source.GetWeakReference().ok() };
Self(reference, PhantomData)
}
}
unsafe impl<I: Interface> Send for Weak<I> {}
unsafe impl<I: Interface> Sync for Weak<I> {}

73
vendor/windows-core/src/windows.rs vendored Normal file
View File

@@ -0,0 +1,73 @@
mod agile_reference;
pub use agile_reference::*;
mod array;
pub use array::*;
#[cfg(feature = "std")]
mod event;
#[cfg(feature = "std")]
pub use event::*;
mod handles;
pub use handles::*;
pub use windows_strings::*;
/// Attempts to load the factory object for the given WinRT class.
/// This can be used to access COM interfaces implemented on a Windows Runtime class factory.
pub fn factory<C: RuntimeName, I: Interface>() -> Result<I> {
imp::load_factory::<C, I>()
}
impl Param<PCWSTR> for &BSTR {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.as_ptr()))
}
}
impl Param<PCWSTR> for &HSTRING {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.as_ptr()))
}
}
impl Param<PCWSTR> for PWSTR {
unsafe fn param(self) -> ParamValue<PCWSTR> {
ParamValue::Owned(PCWSTR(self.0))
}
}
impl Param<PCSTR> for PSTR {
unsafe fn param(self) -> ParamValue<PCSTR> {
ParamValue::Owned(PCSTR(self.0))
}
}
impl RuntimeType for HSTRING {
const SIGNATURE: imp::ConstBuffer = imp::ConstBuffer::from_slice(b"string");
}
impl TypeKind for PWSTR {
type TypeKind = CopyType;
}
impl TypeKind for PSTR {
type TypeKind = CopyType;
}
impl TypeKind for PCWSTR {
type TypeKind = CopyType;
}
impl TypeKind for PCSTR {
type TypeKind = CopyType;
}
impl TypeKind for HSTRING {
type TypeKind = CloneType;
}
impl TypeKind for BSTR {
type TypeKind = CloneType;
}