usesuper::*; usecrate::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};
// 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 = factory::<C, I>()?;
// If the factory is agile, we can safely cache it. if factory.cast::<IAgileObject>().is_ok() { ifself
.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. unsafeimpl<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. pubfn factory<C: crate::RuntimeName, I: Interface>() -> crate::Result<I> { letmut factory: Option<I> = None; let name = crate::HSTRING::from(C::NAME);
let code = unsafe { letmut get_com_factory = || { crate::HRESULT(RoGetActivationFactory(
transmute_copy(&name),
&I::IID as *const _ as _,
&mut factory as *mut _ as *mut _,
))
}; letmut 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 { letmut 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. iflet 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();
// Now attempt to find the factory's implementation heuristically. iflet 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(crate::PCSTR) -> crate::Result<R>,
{ let suffix = b".dll\0"; letmut library = alloc::vec![0; path.len() + suffix.len()]; whilelet 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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.