diff options
Diffstat (limited to 'vendor/windows-core/src/imp')
| -rw-r--r-- | vendor/windows-core/src/imp/bindings.rs | 45 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/can_into.rs | 5 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/com_bindings.rs | 262 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/factory_cache.rs | 218 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/generic_factory.rs | 33 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/marshaler.rs | 268 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/mod.rs | 96 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/ref_count.rs | 33 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/sha1.rs | 481 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/weak_ref_count.rs | 327 | ||||
| -rw-r--r-- | vendor/windows-core/src/imp/windows.rs | 11 |
11 files changed, 1779 insertions, 0 deletions
diff --git a/vendor/windows-core/src/imp/bindings.rs b/vendor/windows-core/src/imp/bindings.rs new file mode 100644 index 00000000..caf8507e --- /dev/null +++ b/vendor/windows-core/src/imp/bindings.rs @@ -0,0 +1,45 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] + +windows_link::link!("ole32.dll" "system" fn CoIncrementMTAUsage(pcookie : *mut CO_MTA_USAGE_COOKIE) -> HRESULT); +windows_link::link!("ole32.dll" "system" fn CoTaskMemAlloc(cb : usize) -> *mut core::ffi::c_void); +windows_link::link!("ole32.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); +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 HSTRING = *mut core::ffi::c_void; diff --git a/vendor/windows-core/src/imp/can_into.rs b/vendor/windows-core/src/imp/can_into.rs new file mode 100644 index 00000000..47ee7838 --- /dev/null +++ b/vendor/windows-core/src/imp/can_into.rs @@ -0,0 +1,5 @@ +pub trait CanInto<T>: Sized { + const QUERY: bool = false; +} + +impl<T> CanInto<T> for T where T: Clone {} diff --git a/vendor/windows-core/src/imp/com_bindings.rs b/vendor/windows-core/src/imp/com_bindings.rs new file mode 100644 index 00000000..2c16fbff --- /dev/null +++ b/vendor/windows-core/src/imp/com_bindings.rs @@ -0,0 +1,262 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] + +#[inline] +pub unsafe fn CoCreateGuid() -> windows_core::Result<windows_core::GUID> { + windows_link::link!("ole32.dll" "system" fn CoCreateGuid(pguid : *mut windows_core::GUID) -> windows_core::HRESULT); + unsafe { + let mut result__ = core::mem::zeroed(); + CoCreateGuid(&mut result__).map(|| result__) + } +} +#[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_link::link!("ole32.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 _); diff --git a/vendor/windows-core/src/imp/factory_cache.rs b/vendor/windows-core/src/imp/factory_cache.rs new file mode 100644 index 00000000..e60abb3a --- /dev/null +++ b/vendor/windows-core/src/imp/factory_cache.rs @@ -0,0 +1,218 @@ +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); + } + + // If not, first capture the error information from the failure above so that we + // can ultimately return this error information if all else fails. + let original: crate::Error = code.into(); + + // 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(original) +} + +// 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_win32)?; + 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"]); + } +} diff --git a/vendor/windows-core/src/imp/generic_factory.rs b/vendor/windows-core/src/imp/generic_factory.rs new file mode 100644 index 00000000..1f9ddcee --- /dev/null +++ b/vendor/windows-core/src/imp/generic_factory.rs @@ -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, +} diff --git a/vendor/windows-core/src/imp/marshaler.rs b/vendor/windows-core/src/imp/marshaler.rs new file mode 100644 index 00000000..2ef9d847 --- /dev/null +++ b/vendor/windows-core/src/imp/marshaler.rs @@ -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!("ole32.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, +} diff --git a/vendor/windows-core/src/imp/mod.rs b/vendor/windows-core/src/imp/mod.rs new file mode 100644 index 00000000..036b540b --- /dev/null +++ b/vendor/windows-core/src/imp/mod.rs @@ -0,0 +1,96 @@ +#[cfg(windows)] +include!("windows.rs"); + +mod can_into; +mod com_bindings; +mod ref_count; +mod sha1; +mod weak_ref_count; + +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; diff --git a/vendor/windows-core/src/imp/ref_count.rs b/vendor/windows-core/src/imp/ref_count.rs new file mode 100644 index 00000000..97e1f2a6 --- /dev/null +++ b/vendor/windows-core/src/imp/ref_count.rs @@ -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 + } +} diff --git a/vendor/windows-core/src/imp/sha1.rs b/vendor/windows-core/src/imp/sha1.rs new file mode 100644 index 00000000..deab3ae5 --- /dev/null +++ b/vendor/windows-core/src/imp/sha1.rs @@ -0,0 +1,481 @@ +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 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(()) + } +} diff --git a/vendor/windows-core/src/imp/weak_ref_count.rs b/vendor/windows-core/src/imp/weak_ref_count.rs new file mode 100644 index 00000000..6ea23635 --- /dev/null +++ b/vendor/windows-core/src/imp/weak_ref_count.rs @@ -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 { + #[allow(clippy::new_ret_no_self)] + unsafe fn new(object: *mut c_void, strong_count: u32) -> IWeakReferenceSource { + unsafe { + transmute(Box::new(TearOff { + 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 = TearOff::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 { transmute(value << 1) } + } + + 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) + }) + } + } +} diff --git a/vendor/windows-core/src/imp/windows.rs b/vendor/windows-core/src/imp/windows.rs new file mode 100644 index 00000000..d8dd81f0 --- /dev/null +++ b/vendor/windows-core/src/imp/windows.rs @@ -0,0 +1,11 @@ +mod factory_cache; +pub use factory_cache::*; + +mod generic_factory; +pub use generic_factory::*; + +mod bindings; +pub use bindings::*; + +mod marshaler; +pub use marshaler::*; |
