| File: MS\Internal\WindowsRuntime\Generated\WinRT.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection; using System.Runtime.InteropServices; using WinRT.Interop; #pragma warning disable 0169 // The field 'xxx' is never used #pragma warning disable 0649 // Field 'xxx' is never assigned to, and will always have its default value namespace WinRT { internal static class DelegateExtensions { public static void DynamicInvokeAbi(this System.Delegate del, object[] invoke_params) { Marshal.ThrowExceptionForHR((int)del.DynamicInvoke(invoke_params)); } public static T AsDelegate<T>(this MulticastDelegate del) { return Marshal.GetDelegateForFunctionPointer<T>( Marshal.GetFunctionPointerForDelegate(del)); } } internal class Platform { [DllImport("api-ms-win-core-com-l1-1-0.dll")] public static extern int CoDecrementMTAUsage(IntPtr cookie); [DllImport("api-ms-win-core-com-l1-1-0.dll")] public static extern unsafe int CoIncrementMTAUsage(IntPtr* cookie); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FreeLibrary(IntPtr moduleHandle); [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr GetProcAddress(IntPtr moduleHandle, [MarshalAs(UnmanagedType.LPStr)] string functionName); public static T GetProcAddress<T>(IntPtr moduleHandle) { IntPtr functionPtr = Platform.GetProcAddress(moduleHandle, typeof(T).Name); if (functionPtr == IntPtr.Zero) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } return Marshal.GetDelegateForFunctionPointer<T>(functionPtr); } [DllImport("kernel32.dll", SetLastError = true)] public static extern IntPtr LoadLibraryExW([MarshalAs(UnmanagedType.LPWStr)] string fileName, IntPtr fileHandle, uint flags); [DllImport("api-ms-win-core-winrt-l1-1-0.dll")] public static extern unsafe int RoGetActivationFactory(IntPtr runtimeClassId, ref Guid iid, IntPtr* factory); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] public static extern unsafe int WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString, int length, IntPtr* hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] public static extern unsafe int WindowsCreateStringReference(char* sourceString, int length, IntPtr* hstring_header, IntPtr* hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] public static extern int WindowsDeleteString(IntPtr hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] public static extern unsafe int WindowsDuplicateString(IntPtr sourceString, IntPtr* hstring); [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] public static extern unsafe char* WindowsGetStringRawBuffer(IntPtr hstring, uint* length); } internal struct VftblPtr { public IntPtr Vftbl; } internal class DllModule { [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate int DllGetActivationFactory( IntPtr activatableClassId, out IntPtr activationFactory); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate int DllCanUnloadNow(); private readonly string _fileName; private readonly IntPtr _moduleHandle; private readonly DllGetActivationFactory _GetActivationFactory; private readonly DllCanUnloadNow _CanUnloadNow; // TODO: Eventually periodically call private static readonly string _currentModuleDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); private static Dictionary<string, DllModule> _cache = new System.Collections.Generic.Dictionary<string, DllModule>(); public static DllModule Load(string fileName) { lock (_cache) { DllModule module; if (!_cache.TryGetValue(fileName, out module)) { module = new DllModule(fileName); _cache[fileName] = module; } return module; } } private DllModule(string fileName) { _fileName = fileName; // Explicitly look for module in the same directory as this one, and // use altered search path to ensure any dependencies in the same directory are found. _moduleHandle = Platform.LoadLibraryExW(System.IO.Path.Combine(_currentModuleDirectory, fileName), IntPtr.Zero, /* LOAD_WITH_ALTERED_SEARCH_PATH */ 8); #if !NETSTANDARD2_0 && !NETCOREAPP2_0 if (_moduleHandle == IntPtr.Zero) { try { // Allow runtime to find module in RID-specific relative subfolder _moduleHandle = NativeLibrary.Load(fileName, Assembly.GetExecutingAssembly(), null); } catch (Exception) { } } #endif if (_moduleHandle == IntPtr.Zero) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } _GetActivationFactory = Platform.GetProcAddress<DllGetActivationFactory>(_moduleHandle); var canUnloadNow = Platform.GetProcAddress(_moduleHandle, "DllCanUnloadNow"); if (canUnloadNow != IntPtr.Zero) { _CanUnloadNow = Marshal.GetDelegateForFunctionPointer<DllCanUnloadNow>(canUnloadNow); } } public unsafe (ObjectReference<IActivationFactoryVftbl> obj, int hr) GetActivationFactory(string runtimeClassId) { IntPtr instancePtr; var hstrRuntimeClassId = MarshalString.CreateMarshaler(runtimeClassId); int hr = _GetActivationFactory(MarshalString.GetAbi(hstrRuntimeClassId), out instancePtr); return (hr == 0 ? ObjectReference<IActivationFactoryVftbl>.Attach(ref instancePtr) : null, hr); } ~DllModule() { System.Diagnostics.Debug.Assert(_CanUnloadNow == null || _CanUnloadNow() == 0); // S_OK lock (_cache) { _cache.Remove(_fileName); } if ((_moduleHandle != IntPtr.Zero) && !Platform.FreeLibrary(_moduleHandle)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } } } internal class WeakLazy<T> where T : class, new() { private WeakReference<T> _instance = new WeakReference<T>(null); public T Value { get { lock (_instance) { T value; if (!_instance.TryGetTarget(out value)) { value = new T(); _instance.SetTarget(value); } return value; } } } } internal class WinrtModule { private readonly IntPtr _mtaCookie; private static Lazy<WinrtModule> _instance = new Lazy<WinrtModule>(); public static WinrtModule Instance => _instance.Value; public unsafe WinrtModule() { IntPtr mtaCookie; Marshal.ThrowExceptionForHR(Platform.CoIncrementMTAUsage(&mtaCookie)); _mtaCookie = mtaCookie; } public static unsafe (ObjectReference<IActivationFactoryVftbl> obj, int hr) GetActivationFactory(string runtimeClassId) { var module = Instance; // Ensure COM is initialized Guid iid = typeof(IActivationFactoryVftbl).GUID; IntPtr instancePtr; var hstrRuntimeClassId = MarshalString.CreateMarshaler(runtimeClassId); int hr = Platform.RoGetActivationFactory(MarshalString.GetAbi(hstrRuntimeClassId), ref iid, &instancePtr); return (hr == 0 ? ObjectReference<IActivationFactoryVftbl>.Attach(ref instancePtr) : null, hr); } ~WinrtModule() { Marshal.ThrowExceptionForHR(Platform.CoDecrementMTAUsage(_mtaCookie)); } } internal class BaseActivationFactory { private ObjectReference<IActivationFactoryVftbl> _IActivationFactory; public BaseActivationFactory(string typeNamespace, string typeFullName) { var runtimeClassId = TypeExtensions.RemoveNamespacePrefix(typeFullName); // Prefer the RoGetActivationFactory HRESULT failure over the LoadLibrary/etc. failure int hr; (_IActivationFactory, hr) = WinrtModule.GetActivationFactory(runtimeClassId); if (_IActivationFactory != null) { return; } var moduleName = typeNamespace; while (true) { try { (_IActivationFactory, _) = DllModule.Load($"{moduleName}.dll").GetActivationFactory(runtimeClassId); if (_IActivationFactory != null) { return; } } catch (Exception) { } var lastSegment = moduleName.LastIndexOf('.'); if (lastSegment <= 0) { Marshal.ThrowExceptionForHR(hr); } moduleName = moduleName.Remove(lastSegment); } } public unsafe ObjectReference<I> _ActivateInstance<I>() { Marshal.ThrowExceptionForHR(_IActivationFactory.Vftbl.ActivateInstance(_IActivationFactory.ThisPtr, out IntPtr instancePtr)); try { return ComWrappersSupport.GetObjectReferenceForInterface(instancePtr).As<I>(); } finally { MarshalInspectable.DisposeAbi(instancePtr); } } public ObjectReference<I> _As<I>() => _IActivationFactory.As<I>(); } internal class ActivationFactory<T> : BaseActivationFactory { public ActivationFactory() : base(typeof(T).Namespace, typeof(T).FullName) { } private static WeakLazy<ActivationFactory<T>> _factory = new WeakLazy<ActivationFactory<T>>(); public static ObjectReference<I> As<I>() => _factory.Value._As<I>(); public static ObjectReference<I> ActivateInstance<I>() => _factory.Value._ActivateInstance<I>(); } }