diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:41:41 +0000 |
commit | 10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch) | |
tree | bdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/windows/src/imp | |
parent | Releasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff) | |
download | rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip |
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/windows/src/imp')
-rw-r--r-- | vendor/windows/src/imp/bindings.rs | 305 | ||||
-rw-r--r-- | vendor/windows/src/imp/delay_load.rs | 25 | ||||
-rw-r--r-- | vendor/windows/src/imp/factory_cache.rs | 161 | ||||
-rw-r--r-- | vendor/windows/src/imp/generic_factory.rs | 31 | ||||
-rw-r--r-- | vendor/windows/src/imp/heap.rs | 35 | ||||
-rw-r--r-- | vendor/windows/src/imp/mod.rs | 114 | ||||
-rw-r--r-- | vendor/windows/src/imp/ref_count.rs | 34 | ||||
-rw-r--r-- | vendor/windows/src/imp/sha1.rs | 333 | ||||
-rw-r--r-- | vendor/windows/src/imp/waiter.rs | 39 | ||||
-rw-r--r-- | vendor/windows/src/imp/weak_ref_count.rs | 232 |
10 files changed, 0 insertions, 1309 deletions
diff --git a/vendor/windows/src/imp/bindings.rs b/vendor/windows/src/imp/bindings.rs deleted file mode 100644 index 289592f10..000000000 --- a/vendor/windows/src/imp/bindings.rs +++ /dev/null @@ -1,305 +0,0 @@ -use super::*; -use std::ffi::c_void; - -link!("kernel32.dll" "system" fn CreateEventW(attributes: *const c_void, manual_reset: i32, initial_state: i32, name: *const c_void) -> isize); -link!("kernel32.dll" "system" fn EncodePointer(ptr: *const c_void) -> *mut c_void); -link!("kernel32.dll" "system" fn FormatMessageW(flags: u32, source: *const c_void, code: u32, lang: u32, buffer: core::PWSTR, len: u32, args: *const *const i8) -> u32); -link!("kernel32.dll" "system" fn FreeLibrary(library: isize) -> i32); -link!("kernel32.dll" "system" fn GetLastError() -> u32); -link!("kernel32.dll" "system" fn GetProcAddress(library: isize, name: core::PCSTR) -> *const c_void); -link!("kernel32.dll" "system" fn GetProcessHeap() -> isize); -link!("kernel32.dll" "system" fn HeapAlloc(heap: isize, flags: u32, len: usize) -> *mut c_void); -link!("kernel32.dll" "system" fn HeapFree(heap: isize, flags: u32, ptr: *const c_void) -> i32); -link!("kernel32.dll" "system" fn LoadLibraryA(name: core::PCSTR) -> isize); -link!("kernel32.dll" "system" fn SetEvent(handle: isize) -> i32); -link!("kernel32.dll" "system" fn WaitForSingleObject(handle: isize, milliseconds: u32) -> u32); -link!("kernel32.dll""system" fn CloseHandle(handle: isize) -> i32); -link!("ole32.dll" "system" fn CoCreateGuid(guid: *mut core::GUID) -> core::HRESULT); -link!("ole32.dll" "system" fn CoTaskMemAlloc(len: usize) -> *mut c_void); -link!("ole32.dll" "system" fn CoTaskMemFree(ptr: *const c_void) -> ()); -link!("ole32.dll" "system" fn RoGetAgileReference(options: i32, iid: &core::GUID, object: *const c_void, reference: *mut *mut c_void) -> core::HRESULT); -link!("oleaut32.dll" "system" fn GetErrorInfo(reserved: u32, info: *mut *mut c_void) -> core::HRESULT); -link!("oleaut32.dll" "system" fn SetErrorInfo(reserved: u32, info: *const c_void) -> core::HRESULT); -link!("oleaut32.dll" "system" fn SysAllocStringLen(input: *const u16, len: u32) -> *const u16); -link!("oleaut32.dll" "system" fn SysFreeString(bstr: *const u16) -> ()); -link!("oleaut32.dll" "system" fn SysStringLen(bstr: *const u16) -> u32); - -pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: u32 = 256; -pub const FORMAT_MESSAGE_FROM_SYSTEM: u32 = 4096; -pub const FORMAT_MESSAGE_IGNORE_INSERTS: u32 = 512; -pub const AGILEREFERENCE_DEFAULT: i32 = 0; - -pub const ERROR_NO_UNICODE_TRANSLATION: u32 = 1113u32; -pub const CLASS_E_CLASSNOTAVAILABLE: core::HRESULT = core::HRESULT(-2147221231i32); -pub const CO_E_NOTINITIALIZED: core::HRESULT = core::HRESULT(-2147221008i32); -pub const E_NOINTERFACE: core::HRESULT = core::HRESULT(-2147467262i32); -pub const E_OUTOFMEMORY: core::HRESULT = core::HRESULT(-2147024882i32); -pub const RPC_E_DISCONNECTED: core::HRESULT = core::HRESULT(-2147417848i32); -pub const JSCRIPT_E_CANTEXECUTE: core::HRESULT = core::HRESULT(-1996357631i32); -pub const S_OK: core::HRESULT = core::HRESULT(0i32); -pub const E_BOUNDS: core::HRESULT = core::HRESULT(-2147483637i32); - -#[repr(transparent)] -pub struct IAgileObject(core::IUnknown); -impl std::clone::Clone for IAgileObject { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IAgileObject { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IAgileObject {} -unsafe impl core::Interface for IAgileObject { - type Vtable = IAgileObject_Vtbl; -} -unsafe impl core::ComInterface for IAgileObject { - const IID: core::GUID = core::GUID::from_u128(0x94ea2b94_e9cc_49e0_c0ff_ee64ca8f5b90); -} -#[repr(C)] -#[doc(hidden)] -pub struct IAgileObject_Vtbl { - pub base__: core::IUnknown_Vtbl, -} - -#[repr(transparent)] -pub struct IErrorInfo(core::IUnknown); -impl IErrorInfo { - pub unsafe fn GetDescription(&self) -> core::Result<core::BSTR> { - let mut result__ = core::zeroed::<core::BSTR>(); - (core::Interface::vtable(self).GetDescription)(core::Interface::as_raw(self), result__.as_mut_ptr()).from_abi(result__) - } -} - -impl std::clone::Clone for IErrorInfo { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IErrorInfo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IErrorInfo {} -unsafe impl core::Interface for IErrorInfo { - type Vtable = IErrorInfo_Vtbl; -} -unsafe impl core::ComInterface for IErrorInfo { - const IID: core::GUID = core::GUID::from_u128(0x1cf2b120_547d_101b_8e65_08002b2bd119); -} -#[repr(C)] -#[doc(hidden)] -pub struct IErrorInfo_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub GetGUID: unsafe extern "system" fn(this: *mut c_void, pguid: *mut core::GUID) -> core::HRESULT, - pub GetSource: unsafe extern "system" fn(this: *mut c_void, pbstrsource: *mut core::BSTR) -> core::HRESULT, - pub GetDescription: unsafe extern "system" fn(this: *mut c_void, pbstrdescription: *mut core::BSTR) -> core::HRESULT, - pub GetHelpFile: unsafe extern "system" fn(this: *mut c_void, pbstrhelpfile: *mut core::BSTR) -> core::HRESULT, - pub GetHelpContext: unsafe extern "system" fn(this: *mut c_void, pdwhelpcontext: *mut u32) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct IAgileReference(pub(crate) core::IUnknown); -impl IAgileReference { - pub unsafe fn Resolve<T>(&self) -> core::Result<T> - where - T: core::ComInterface, - { - let mut result__ = std::ptr::null_mut(); - (core::Interface::vtable(self).Resolve)(core::Interface::as_raw(self), &<T as core::ComInterface>::IID, &mut result__).from_abi(result__) - } -} - -impl std::clone::Clone for IAgileReference { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IAgileReference { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IAgileReference {} -unsafe impl core::Interface for IAgileReference { - type Vtable = IAgileReference_Vtbl; -} -unsafe impl core::ComInterface for IAgileReference { - const IID: core::GUID = core::GUID::from_u128(0xc03f6a43_65a4_9818_987e_e0b810d2a6f2); -} -#[repr(C)] -#[doc(hidden)] -pub struct IAgileReference_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub Resolve: unsafe extern "system" fn(this: *mut c_void, riid: *const core::GUID, ppvobjectreference: *mut *mut c_void) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct ILanguageExceptionErrorInfo(core::IUnknown); -impl std::clone::Clone for ILanguageExceptionErrorInfo { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for ILanguageExceptionErrorInfo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for ILanguageExceptionErrorInfo {} -unsafe impl core::Interface for ILanguageExceptionErrorInfo { - type Vtable = ILanguageExceptionErrorInfo_Vtbl; -} -unsafe impl core::ComInterface for ILanguageExceptionErrorInfo { - const IID: core::GUID = core::GUID::from_u128(0x04a2dbf3_df83_116c_0946_0812abf6e07d); -} -#[repr(C)] -#[doc(hidden)] -pub struct ILanguageExceptionErrorInfo_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub GetLanguageException: unsafe extern "system" fn(this: *mut c_void, languageexception: *mut *mut c_void) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct ILanguageExceptionErrorInfo2(core::IUnknown); -impl ILanguageExceptionErrorInfo2 { - pub unsafe fn CapturePropagationContext<P0>(&self, languageexception: P0) -> core::Result<()> - where - P0: core::IntoParam<core::IUnknown>, - { - (core::Interface::vtable(self).CapturePropagationContext)(core::Interface::as_raw(self), languageexception.into_param().abi()).ok() - } -} -impl std::clone::Clone for ILanguageExceptionErrorInfo2 { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for ILanguageExceptionErrorInfo2 { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for ILanguageExceptionErrorInfo2 {} -unsafe impl core::Interface for ILanguageExceptionErrorInfo2 { - type Vtable = ILanguageExceptionErrorInfo2_Vtbl; -} -unsafe impl core::ComInterface for ILanguageExceptionErrorInfo2 { - const IID: core::GUID = core::GUID::from_u128(0x5746e5c4_5b97_424c_b620_2822915734dd); -} -#[repr(C)] -#[doc(hidden)] -pub struct ILanguageExceptionErrorInfo2_Vtbl { - pub base__: ILanguageExceptionErrorInfo_Vtbl, - pub GetPreviousLanguageExceptionErrorInfo: unsafe extern "system" fn(this: *mut c_void, previouslanguageexceptionerrorinfo: *mut *mut c_void) -> core::HRESULT, - pub CapturePropagationContext: unsafe extern "system" fn(this: *mut c_void, languageexception: *mut c_void) -> core::HRESULT, - pub GetPropagationContextHead: unsafe extern "system" fn(this: *mut c_void, propagatedlanguageexceptionerrorinfohead: *mut *mut c_void) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct IRestrictedErrorInfo(core::IUnknown); -impl IRestrictedErrorInfo { - pub unsafe fn GetErrorDetails(&self, description: &mut core::BSTR, error: &mut core::HRESULT, restricteddescription: &mut core::BSTR, capabilitysid: &mut core::BSTR) -> core::Result<()> { - (core::Interface::vtable(self).GetErrorDetails)(core::Interface::as_raw(self), description as *mut _, error as *mut _, restricteddescription as *mut _, capabilitysid as *mut _).ok() - } - pub unsafe fn GetReference(&self) -> core::Result<core::BSTR> { - let mut result__ = core::zeroed::<core::BSTR>(); - (core::Interface::vtable(self).GetReference)(core::Interface::as_raw(self), &mut result__).from_abi(result__) - } -} -impl std::clone::Clone for IRestrictedErrorInfo { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IRestrictedErrorInfo { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IRestrictedErrorInfo {} -unsafe impl std::marker::Send for IRestrictedErrorInfo {} -unsafe impl std::marker::Sync for IRestrictedErrorInfo {} -unsafe impl core::Interface for IRestrictedErrorInfo { - type Vtable = IRestrictedErrorInfo_Vtbl; -} -unsafe impl core::ComInterface for IRestrictedErrorInfo { - const IID: core::GUID = core::GUID::from_u128(0x82ba7092_4c88_427d_a7bc_16dd93feb67e); -} -#[repr(C)] -#[doc(hidden)] -pub struct IRestrictedErrorInfo_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub GetErrorDetails: unsafe extern "system" fn(this: *mut c_void, description: *mut core::BSTR, error: *mut core::HRESULT, restricteddescription: *mut core::BSTR, capabilitysid: *mut core::BSTR) -> core::HRESULT, - pub GetReference: unsafe extern "system" fn(this: *mut c_void, reference: *mut std::mem::MaybeUninit<core::BSTR>) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct IWeakReference(core::IUnknown); -impl IWeakReference { - pub unsafe fn Resolve<T>(&self) -> core::Result<T> - where - T: core::ComInterface, - { - let mut result__ = std::ptr::null_mut(); - (core::Interface::vtable(self).Resolve)(core::Interface::as_raw(self), &<T as core::ComInterface>::IID, &mut result__).from_abi(result__) - } -} -impl std::clone::Clone for IWeakReference { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IWeakReference { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IWeakReference {} -unsafe impl core::Interface for IWeakReference { - type Vtable = IWeakReference_Vtbl; -} -unsafe impl core::ComInterface for IWeakReference { - const IID: core::GUID = core::GUID::from_u128(0x00000037_0000_0000_c000_000000000046); -} -#[repr(C)] -#[doc(hidden)] -pub struct IWeakReference_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub Resolve: unsafe extern "system" fn(this: *mut c_void, riid: *const core::GUID, objectreference: *mut *mut c_void) -> core::HRESULT, -} - -#[repr(transparent)] -pub struct IWeakReferenceSource(core::IUnknown); -impl IWeakReferenceSource { - pub unsafe fn GetWeakReference(&self) -> core::Result<IWeakReference> { - let mut result__ = std::ptr::null_mut(); - (core::Interface::vtable(self).GetWeakReference)(core::Interface::as_raw(self), &mut result__).from_abi(result__) - } -} -impl std::clone::Clone for IWeakReferenceSource { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} -impl std::cmp::PartialEq for IWeakReferenceSource { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } -} -impl std::cmp::Eq for IWeakReferenceSource {} -unsafe impl core::Interface for IWeakReferenceSource { - type Vtable = IWeakReferenceSource_Vtbl; -} -unsafe impl core::ComInterface for IWeakReferenceSource { - const IID: core::GUID = core::GUID::from_u128(0x00000038_0000_0000_c000_000000000046); -} -#[repr(C)] -#[doc(hidden)] -pub struct IWeakReferenceSource_Vtbl { - pub base__: core::IUnknown_Vtbl, - pub GetWeakReference: unsafe extern "system" fn(this: *mut c_void, weakreference: *mut *mut c_void) -> core::HRESULT, -} diff --git a/vendor/windows/src/imp/delay_load.rs b/vendor/windows/src/imp/delay_load.rs deleted file mode 100644 index 055c38b8b..000000000 --- a/vendor/windows/src/imp/delay_load.rs +++ /dev/null @@ -1,25 +0,0 @@ -use super::*; - -/// Attempts to load a function from a given library. -/// -/// This is a small wrapper around `LoadLibrary` and `GetProcAddress`. -/// -/// # Safety -/// -/// * Both the library and function names must be valid null-terminated strings. -pub unsafe fn delay_load<T>(library: core::PCSTR, function: core::PCSTR) -> Option<T> { - let library = LoadLibraryA(library); - - if library == 0 { - return None; - } - - let address = GetProcAddress(library, function); - - if !address.is_null() { - return Some(std::mem::transmute_copy(&address)); - } - - FreeLibrary(library); - None -} diff --git a/vendor/windows/src/imp/factory_cache.rs b/vendor/windows/src/imp/factory_cache.rs deleted file mode 100644 index 685dfe401..000000000 --- a/vendor/windows/src/imp/factory_cache.rs +++ /dev/null @@ -1,161 +0,0 @@ -use super::*; -use std::marker::PhantomData; -use std::sync::atomic::{AtomicPtr, Ordering}; -use windows::core::*; - -#[doc(hidden)] -pub struct FactoryCache<C, I> { - shared: AtomicPtr<std::ffi::c_void>, - _c: PhantomData<C>, - _i: PhantomData<I>, -} - -impl<C, I> FactoryCache<C, I> { - pub const fn new() -> Self { - Self { shared: AtomicPtr::new(std::ptr::null_mut()), _c: PhantomData, _i: PhantomData } - } -} - -impl<C: core::RuntimeName, I: core::ComInterface> FactoryCache<C, I> { - pub fn call<R, F: FnOnce(&I) -> core::Result<R>>(&self, callback: F) -> core::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 { std::mem::transmute(&ptr) }); - } - - // Otherwise, we load the factory the usual way. - let factory = 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(std::ptr::null_mut(), factory.as_raw(), Ordering::Relaxed, Ordering::Relaxed).is_ok() { - std::mem::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> std::marker::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 factory<C: core::RuntimeName, I: core::ComInterface>() -> core::Result<I> { - let mut factory: Option<I> = None; - let name = core::HSTRING::from(C::NAME); - - let code = if let Some(function) = unsafe { delay_load::<RoGetActivationFactory>(s!("combase.dll"), s!("RoGetActivationFactory")) } { - unsafe { - let mut code = function(std::mem::transmute_copy(&name), &I::IID, &mut factory as *mut _ as *mut _); - - // 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 { - if let Some(mta) = delay_load::<CoIncrementMTAUsage>(s!("ole32.dll"), s!("CoIncrementMTAUsage")) { - let mut cookie = std::ptr::null_mut(); - let _ = mta(&mut cookie); - } - - // Now try a second time to get the activation factory via the OS. - code = function(std::mem::transmute_copy(&name), &I::IID, &mut factory as *mut _ as *mut _); - } - - code - } - } else { - CLASS_E_CLASSNOTAVAILABLE - }; - - // If this succeeded then return the resulting factory interface. - if code.is_ok() { - return code.and_some(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: core::Error = code.into(); - - // Now attempt to find the factory's implementation heuristically. - if let Some(i) = search_path(C::NAME, |library| unsafe { get_activation_factory(library, &name) }) { - i.cast() - } else { - 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(core::PCSTR) -> core::Result<R>, -{ - let suffix = b".dll\0"; - let mut library = 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(core::PCSTR::from_raw(library.as_ptr())) { - return Some(r); - } - } - - None -} - -unsafe fn get_activation_factory(library: core::PCSTR, name: &core::HSTRING) -> core::Result<IGenericFactory> { - let function = delay_load::<DllGetActivationFactory>(library, s!("DllGetActivationFactory")).ok_or_else(core::Error::from_win32)?; - let mut abi = std::ptr::null_mut(); - function(std::mem::transmute_copy(name), &mut abi).from_abi(abi) -} - -type CoIncrementMTAUsage = extern "system" fn(cookie: *mut *mut std::ffi::c_void) -> core::HRESULT; -type RoGetActivationFactory = extern "system" fn(hstring: *mut std::ffi::c_void, interface: &core::GUID, result: *mut *mut std::ffi::c_void) -> core::HRESULT; -type DllGetActivationFactory = extern "system" fn(name: *mut std::ffi::c_void, factory: *mut *mut std::ffi::c_void) -> core::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(core::Error::OK) - } - }); - 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() }); - core::Result::<()>::Err(core::Error::OK) - }); - assert!(matches!(end_result, None)); - assert_eq!(results, vec!["A.B.dll", "A.dll"]); - } -} diff --git a/vendor/windows/src/imp/generic_factory.rs b/vendor/windows/src/imp/generic_factory.rs deleted file mode 100644 index 706160b09..000000000 --- a/vendor/windows/src/imp/generic_factory.rs +++ /dev/null @@ -1,31 +0,0 @@ -use super::*; -use windows::core::ComInterface; - -// 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. -#[repr(transparent)] -#[derive(Clone, PartialEq, Eq)] -pub struct IGenericFactory(core::IUnknown); - -impl IGenericFactory { - pub fn ActivateInstance<I: core::ComInterface>(&self) -> core::Result<I> { - unsafe { - let mut result__ = core::zeroed::<I>(); - (core::Interface::vtable(self).ActivateInstance)(std::mem::transmute_copy(self), &mut result__ as *mut _ as *mut _).from_abi::<core::IInspectable>(result__)?.cast() - } - } -} - -#[repr(C)] -pub struct IGenericFactory_Vtbl { - pub base__: core::IInspectable_Vtbl, - pub ActivateInstance: unsafe extern "system" fn(this: *mut std::ffi::c_void, instance: *mut *mut std::ffi::c_void) -> core::HRESULT, -} - -unsafe impl core::Interface for IGenericFactory { - type Vtable = IGenericFactory_Vtbl; -} - -unsafe impl core::ComInterface for IGenericFactory { - const IID: core::GUID = core::GUID::from_u128(0x00000035_0000_0000_c000_000000000046); -} diff --git a/vendor/windows/src/imp/heap.rs b/vendor/windows/src/imp/heap.rs deleted file mode 100644 index fe7980d7d..000000000 --- a/vendor/windows/src/imp/heap.rs +++ /dev/null @@ -1,35 +0,0 @@ -use super::*; - -/// Allocate memory of size `bytes` using `HeapAlloc`. -/// -/// The memory allocated by this function is uninitialized. -/// -/// This function will fail in OOM situations, if the heap is otherwise corrupt, -/// or if getting a handle to the process heap fails. -pub fn heap_alloc(bytes: usize) -> core::Result<*mut std::ffi::c_void> { - let ptr = unsafe { HeapAlloc(GetProcessHeap(), 0, bytes) }; - - if ptr.is_null() { - Err(E_OUTOFMEMORY.into()) - } else { - // HeapAlloc is not guaranteed to return zero memory but usually does. This just ensures that - // it predictably returns non-zero memory for testing purposes. This is similar to what MSVC's - // debug allocator does for the same reason. - #[cfg(debug_assertions)] - unsafe { - std::ptr::write_bytes(ptr, 0xCC, bytes); - } - Ok(ptr) - } -} - -/// Free memory allocated by `HeapAlloc` or `HeapReAlloc`. -/// -/// The pointer is allowed to be null. -/// -/// # Safety -/// -/// `ptr` must be a valid pointer to memory allocated by `HeapAlloc` or `HeapReAlloc` -pub unsafe fn heap_free(ptr: *mut std::ffi::c_void) { - HeapFree(GetProcessHeap(), 0, ptr); -} diff --git a/vendor/windows/src/imp/mod.rs b/vendor/windows/src/imp/mod.rs deleted file mode 100644 index d29b0b9a5..000000000 --- a/vendor/windows/src/imp/mod.rs +++ /dev/null @@ -1,114 +0,0 @@ -use super::*; - -mod bindings; -mod delay_load; -mod factory_cache; -mod generic_factory; -mod heap; -mod ref_count; -mod sha1; -mod waiter; -mod weak_ref_count; - -pub use bindings::*; -pub use delay_load::*; -pub use factory_cache::*; -pub use generic_factory::*; -pub use heap::*; -pub use ref_count::*; -pub use sha1::*; -pub use waiter::*; -pub use weak_ref_count::*; - -// This is a workaround since 1.48 does not include `bool::then_some`. -pub fn then_some<T>(value: bool, t: T) -> Option<T> { - if value { - Some(t) - } else { - None - } -} - -// This is a workaround since 1.48 does not include `bool::then`. -pub fn then<T, F: FnOnce() -> T>(value: bool, f: F) -> Option<T> { - if value { - Some(f()) - } else { - None - } -} - -pub fn wide_trim_end(mut wide: &[u16]) -> &[u16] { - while let Some(last) = wide.last() { - match last { - 32 | 9..=13 => wide = &wide[..wide.len() - 1], - _ => break, - } - } - wide -} - -#[doc(hidden)] -#[macro_export] -macro_rules! interface_hierarchy { - ($child:ty, $parent:ty) => { - impl ::windows::core::CanInto<$parent> for $child {} - }; - ($child:ty, $first:ty, $($rest:ty),+) => { - $crate::imp::interface_hierarchy!($child, $first); - $crate::imp::interface_hierarchy!($child, $($rest),+); - }; -} - -#[doc(hidden)] -pub use interface_hierarchy; - -#[cfg(all(windows_raw_dylib, target_arch = "x86"))] -#[macro_export] -#[doc(hidden)] -macro_rules! link { - ($library:literal $abi:literal fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( - #[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim", import_name_type = "undecorated")] - extern $abi { - pub fn $name($($arg: $argty),*) -> $ret; - } - ) -} - -#[cfg(all(windows_raw_dylib, not(target_arch = "x86")))] -#[macro_export] -#[doc(hidden)] -macro_rules! link { - ($library:literal $abi:literal fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( - #[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim")] - extern "system" { - pub fn $name($($arg: $argty),*) -> $ret; - } - ) -} - -#[cfg(all(windows, not(windows_raw_dylib)))] -#[macro_export] -#[doc(hidden)] -macro_rules! link { - ($library:literal $abi:literal fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( - #[link(name = "windows")] - extern $abi { - pub fn $name($($arg: $argty),*) -> $ret; - } - ) -} - -#[cfg(all(not(windows), not(windows_raw_dylib)))] -#[macro_export] -#[doc(hidden)] -macro_rules! link { - ($library:literal $abi:literal fn $name:ident($($arg:ident: $argty:ty),*)->$ret:ty) => ( - extern $abi { - pub fn $name($($arg: $argty),*) -> $ret; - } - ) -} - -#[doc(hidden)] -pub use crate::link; diff --git a/vendor/windows/src/imp/ref_count.rs b/vendor/windows/src/imp/ref_count.rs deleted file mode 100644 index 4b894626c..000000000 --- a/vendor/windows/src/imp/ref_count.rs +++ /dev/null @@ -1,34 +0,0 @@ -use std::sync::atomic::{fence, AtomicI32, Ordering}; - -#[doc(hidden)] -#[repr(transparent)] -#[derive(Default)] -pub struct RefCount(pub(crate) AtomicI32); - -impl RefCount { - /// Creates a new `RefCount` with an initial value of `1`. - pub fn new(count: u32) -> Self { - Self(AtomicI32::new(count as _)) - } - - /// 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) { - std::cmp::Ordering::Equal => fence(Ordering::Acquire), - std::cmp::Ordering::Less => panic!("Object has been over-released."), - std::cmp::Ordering::Greater => {} - } - - remaining as u32 - } -} diff --git a/vendor/windows/src/imp/sha1.rs b/vendor/windows/src/imp/sha1.rs deleted file mode 100644 index 5962a3d02..000000000 --- a/vendor/windows/src/imp/sha1.rs +++ /dev/null @@ -1,333 +0,0 @@ -#![allow(clippy::many_single_char_names)] - -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 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 - } - - const fn as_slice(&self) -> &[u8] { - &self.data - } - - pub const fn push_other(self, other: Self) -> Self { - self.push_amount(other.as_slice(), other.len()) - } - - 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 - } -} - -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.as_slice(), 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 std::fmt::Display for Digest { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - for i in self.data.iter() { - write!(f, "{:08x}", i)?; - } - Ok(()) - } -} diff --git a/vendor/windows/src/imp/waiter.rs b/vendor/windows/src/imp/waiter.rs deleted file mode 100644 index bcd23ef86..000000000 --- a/vendor/windows/src/imp/waiter.rs +++ /dev/null @@ -1,39 +0,0 @@ -use super::*; - -#[doc(hidden)] -pub struct Waiter(isize); -pub struct WaiterSignaler(isize); - -impl Waiter { - pub fn new() -> core::Result<(Waiter, WaiterSignaler)> { - unsafe { - let handle = CreateEventW(std::ptr::null(), 1, 0, std::ptr::null()); - if handle == 0 { - Err(core::Error::from_win32()) - } else { - Ok((Waiter(handle), WaiterSignaler(handle))) - } - } - } -} - -impl WaiterSignaler { - /// # Safety - /// Signals the `Waiter`. This is unsafe because the lifetime of `WaiterSignaler` is not tied - /// to the lifetime of the `Waiter`. This is not possible in this case because the `Waiter` - /// is used to signal a WinRT async completion and the compiler doesn't know that the lifetime - /// of the delegate is bounded by the calling function. - pub unsafe fn signal(&self) { - // https://github.com/microsoft/windows-rs/pull/374#discussion_r535313344 - SetEvent(self.0); - } -} - -impl Drop for Waiter { - fn drop(&mut self) { - unsafe { - WaitForSingleObject(self.0, 0xFFFFFFFF); - CloseHandle(self.0); - } - } -} diff --git a/vendor/windows/src/imp/weak_ref_count.rs b/vendor/windows/src/imp/weak_ref_count.rs deleted file mode 100644 index 364c8b2a7..000000000 --- a/vendor/windows/src/imp/weak_ref_count.rs +++ /dev/null @@ -1,232 +0,0 @@ -use super::*; -use std::sync::atomic::{AtomicIsize, Ordering}; -use windows::core::ComInterface; - -#[doc(hidden)] -#[repr(transparent)] -#[derive(Default)] -pub struct WeakRefCount(AtomicIsize); - -impl WeakRefCount { - pub fn new() -> Self { - Self(AtomicIsize::new(1)) - } - - pub fn add_ref(&self) -> u32 { - self.0.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |count_or_pointer| 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() }) - } - - pub fn release(&self) -> u32 { - self.0.fetch_update(Ordering::Release, Ordering::Relaxed, |count_or_pointer| 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: &windows::core::GUID, object: *mut std::ffi::c_void) -> *mut std::ffi::c_void { - if iid != &IWeakReferenceSource::IID { - return std::ptr::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 _); - let tear_off_ptr: *mut std::ffi::c_void = std::mem::transmute_copy(&tear_off); - let encoding: usize = ((tear_off_ptr as usize) >> 1) | (1 << (std::mem::size_of::<usize>() * 8 - 1)); - - loop { - match self.0.compare_exchange_weak(count_or_pointer, encoding as _, Ordering::AcqRel, Ordering::Relaxed) { - Ok(_) => { - let result: *mut std::ffi::c_void = std::mem::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 _, 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 std::ffi::c_void, - strong_count: RefCount, - weak_count: RefCount, -} - -impl TearOff { - #[allow(clippy::new_ret_no_self)] - unsafe fn new(object: *mut std::ffi::c_void, strong_count: u32) -> IWeakReferenceSource { - std::mem::transmute(std::boxed::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 std::ffi::c_void { - 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__: core::IUnknown_Vtbl { QueryInterface: Self::StrongQueryInterface, AddRef: Self::StrongAddRef, Release: Self::StrongRelease }, - GetWeakReference: Self::StrongDowngrade, - }; - - const WEAK_VTABLE: IWeakReference_Vtbl = IWeakReference_Vtbl { - base__: core::IUnknown_Vtbl { QueryInterface: Self::WeakQueryInterface, AddRef: Self::WeakAddRef, Release: Self::WeakRelease }, - Resolve: Self::WeakUpgrade, - }; - - unsafe fn from_strong_ptr<'a>(this: *mut std::ffi::c_void) -> &'a mut Self { - &mut *(this as *mut *mut std::ffi::c_void as *mut Self) - } - - unsafe fn from_weak_ptr<'a>(this: *mut std::ffi::c_void) -> &'a mut Self { - &mut *((this as *mut *mut std::ffi::c_void).sub(1) as *mut Self) - } - - unsafe fn decode<'a>(value: isize) -> &'a mut Self { - std::mem::transmute(value << 1) - } - - unsafe fn query_interface(&self, iid: &core::GUID, interface: *mut *const std::ffi::c_void) -> core::HRESULT { - ((*(*(self.object as *mut *mut _) as *mut core::IUnknown_Vtbl)).QueryInterface)(self.object, iid, interface) - } - - unsafe extern "system" fn StrongQueryInterface(ptr: *mut std::ffi::c_void, iid: &core::GUID, interface: *mut *const std::ffi::c_void) -> core::HRESULT { - let this = Self::from_strong_ptr(ptr); - - // 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 core::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 std::ffi::c_void, iid: &core::GUID, interface: *mut *const std::ffi::c_void) -> core::HRESULT { - let this = Self::from_weak_ptr(ptr); - - // 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 == &core::IUnknown::IID || iid == &IAgileObject::IID { ptr } else { std::ptr::null_mut() }; - - // TODO: implement IMarshal - - if (*interface).is_null() { - E_NOINTERFACE - } else { - this.weak_count.add_ref(); - core::HRESULT(0) - } - } - - unsafe extern "system" fn StrongAddRef(ptr: *mut std::ffi::c_void) -> u32 { - 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 std::ffi::c_void) -> u32 { - 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 std::ffi::c_void) -> u32 { - 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 _) as *mut core::IUnknown_Vtbl)).Release)(this.object) - } - - unsafe extern "system" fn WeakRelease(ptr: *mut std::ffi::c_void) -> u32 { - 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 _ = std::boxed::Box::from_raw(this); - } - - remaining - } - - unsafe extern "system" fn StrongDowngrade(ptr: *mut std::ffi::c_void, interface: *mut *mut std::ffi::c_void) -> core::HRESULT { - 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(); - core::HRESULT(0) - } - - unsafe extern "system" fn WeakUpgrade(ptr: *mut std::ffi::c_void, iid: *const core::GUID, interface: *mut *mut std::ffi::c_void) -> core::HRESULT { - 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. - then_some(count != 0, count + 1) - }) - .map(|_| { - // Let the object respond to the upgrade query. - let result = this.query_interface(&*iid, interface as *mut _); - // 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 = std::ptr::null_mut(); - core::HRESULT(0) - }) - } -} |