<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.1.25080.3" />

ComHelpers

static class ComHelpers
using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Windows.Win32.Foundation; using Windows.Win32.System.Com; namespace Windows.Win32 { internal static class ComHelpers { private static readonly HRESULT COR_E_OBJECTDISPOSED = (HRESULT)(-2146232798); private static readonly HRESULT S_OK = (HRESULT)0; internal static bool BuiltInComSupported { get; } = !AppContext.TryGetSwitch("System.Runtime.InteropServices.BuiltInComInterop.IsSupported", out bool isEnabled) | isEnabled; internal unsafe static ComScope<T> GetComScope<[IsUnmanaged] T>([Nullable(2)] object object) where T : struct, IComIID { return new ComScope<T>(GetComPointer<T>(object)); } internal static ComScope<T> TryGetComScope<[IsUnmanaged] T>([Nullable(2)] object object) where T : struct, IComIID { HRESULT hr; return TryGetComScope<T>(object, out hr); } internal unsafe static ComScope<T> TryGetComScope<[IsUnmanaged] T>([Nullable(2)] object object, out HRESULT hr) where T : struct, IComIID { return new ComScope<T>(TryGetComPointer<T>(object, out hr)); } internal unsafe static T* GetComPointer<[IsUnmanaged] T>([Nullable(2)] object object) where T : struct, IComIID { HRESULT result; T* result2 = TryGetComPointer<T>(object, out result); result.ThrowOnFailure((IntPtr)0); return result2; } internal unsafe static T* TryGetComPointer<[IsUnmanaged] T>([Nullable(2)] object object) where T : struct, IComIID { HRESULT result; return TryGetComPointer<T>(object, out result); } internal static bool SupportsInterface<[IsUnmanaged] T>([Nullable(2)] object object) where T : struct, IComIID { HRESULT hr; ComScope<T> comScope = TryGetComScope<T>(object, out hr); try { return hr.Succeeded; } finally { comScope.Dispose(); } } internal unsafe static T* TryGetComPointer<[IsUnmanaged] T>([Nullable(2)] object object, out HRESULT result) where T : struct, IComIID { if (object == null) { result = HRESULT.E_POINTER; return null; } IUnknown* ptr = null; IntPtr unknown; if (object is IManagedWrapper) ptr = (IUnknown*)(long)WinFormsComWrappers.Instance.GetOrCreateComInterfaceForObject(object, CreateComInterfaceFlags.None); else if (!ComWrappers.TryGetComInstance(object, out unknown)) { try { ptr = (IUnknown*)(long)Marshal.GetIUnknownForObject(object); } catch (Exception) { } } else { ptr = (IUnknown*)(long)unknown; } if (ptr == null) { result = HRESULT.E_NOINTERFACE; return null; } if (typeof(T) == typeof(IUnknown)) { result = HRESULT.S_OK; return (T*)ptr; } result = ptr->QueryInterface(ref IID.GetRef<T>(), out void* ppvObject); ptr->Release(); return (T*)ppvObject; } public unsafe static bool TryUnwrapComWrapperCCW<[Nullable(1)] TWrapper>(IUnknown* unknown, [Nullable(2)] [NotNullWhen(true)] out TWrapper interface) where TWrapper : class { if (ComWrappers.TryGetObject((IntPtr)unknown, out object obj)) { TWrapper val = obj as TWrapper; if (val != null) { interface = val; return true; } } interface = null; return false; } internal unsafe static bool TryGetObjectForIUnknown<[Nullable(1)] TObject, [IsUnmanaged] TInterface>(ComScope<TInterface> comScope, [Nullable(2)] [NotNullWhen(true)] out TObject object) where TObject : class where TInterface : struct, IComIID { return TryGetObjectForIUnknown<TObject, TInterface>(comScope.Value, out object); } internal unsafe static bool TryGetObjectForIUnknown<[Nullable(1)] TObject, [IsUnmanaged] TInterface>(TInterface* comPointer, [Nullable(2)] [NotNullWhen(true)] out TObject object) where TObject : class where TInterface : struct, IComIID { if (comPointer == null) { object = null; return false; } IUnknown* ptr = (IUnknown*)comPointer; if (typeof(TInterface) == typeof(IUnknown)) return TryGetObjectForIUnknown(ptr, out object); if (ptr->QueryInterface(IID.Get<IUnknown>(), (void**)(&ptr)).Failed) { object = null; return false; } return TryGetObjectForIUnknown(ptr, out object); } internal unsafe static bool TryGetObjectForIUnknown<[Nullable(1)] TObject>(IUnknown* unknown, [Nullable(2)] [NotNullWhen(true)] out TObject object) where TObject : class { return TryGetObjectForIUnknown(unknown, false, out object); } internal unsafe static bool TryGetObjectForIUnknown<[Nullable(1)] TObject>(IUnknown* unknown, bool takeOwnership, [Nullable(2)] [NotNullWhen(true)] out TObject object) where TObject : class { object = null; if (unknown != null) try { object = (TObject)GetObjectForIUnknown(unknown); return true; } catch (Exception) { return false; } finally { if (takeOwnership) unknown->Release(); } return false; } internal unsafe static bool WrapsManagedObject<[IsUnmanaged] T>([Nullable(1)] object object, T* comPointer) where T : struct, IComIID { if (comPointer != null) { ComScope<IUnknown> scope = new ComScope<IUnknown>(null); try { ((IUnknown*)comPointer)->QueryInterface(IID.Get<IUnknown>(), (void**)ref scope).ThrowOnFailure((IntPtr)0); if (!ComWrappers.TryGetObject((IntPtr)ref scope, out object obj)) { ComScope<IUnknown> comScope = new ComScope<IUnknown>((IUnknown*)(long)Marshal.GetIUnknownForObject(object)); try { return comScope.Value == (void*)ref scope; } finally { comScope.Dispose(); } } return object == obj; } finally { scope.Dispose(); } } return false; } [return: Nullable(1)] internal unsafe static object GetObjectForIUnknown<[IsUnmanaged] TInterface>(TInterface* comPointer) where TInterface : struct, IComIID { if (comPointer == null) throw new ArgumentNullException("comPointer"); IUnknown* ptr = (IUnknown*)comPointer; if (typeof(TInterface) == typeof(IUnknown)) return GetObjectForIUnknown(ptr); ptr->QueryInterface(IID.Get<IUnknown>(), (void**)(&ptr)).ThrowOnFailure((IntPtr)0); return GetObjectForIUnknown(ptr); } [return: Nullable(1)] internal unsafe static object GetObjectForIUnknown<[IsUnmanaged] TInterface>(ComScope<TInterface> comScope) where TInterface : struct, IComIID { return GetObjectForIUnknown<TInterface>(comScope.Value); } [return: Nullable(1)] internal unsafe static object GetObjectForIUnknown(IUnknown* unknown) { if (unknown == null) throw new ArgumentNullException("unknown"); if (ComWrappers.TryGetObject((IntPtr)unknown, out object obj)) return obj; if (BuiltInComSupported) return Marshal.GetObjectForIUnknown((IntPtr)unknown); return WinFormsComStrategy.Instance.GetOrCreateObjectForComInstance((IntPtr)unknown, CreateObjectFlags.Unwrap); } public unsafe static ComScope<ITypeInfo> GetRegisteredTypeInfo(Guid typeLibrary, ushort majorVersion, ushort minorVersion, Guid interfaceId) { ComScope<ITypeLib> scope = new ComScope<ITypeLib>(null); try { PInvokeCore.LoadRegTypeLib(ref typeLibrary, majorVersion, minorVersion, 0, (ITypeLib**)ref scope).ThrowOnFailure((IntPtr)0); ComScope<ITypeInfo> scope2 = new ComScope<ITypeInfo>(null); scope.Value->GetTypeInfoOfGuid(ref interfaceId, (ITypeInfo**)ref scope2).ThrowOnFailure((IntPtr)0); return scope2; } finally { scope.Dispose(); } } internal unsafe static HRESULT UnwrapCCW<[IsUnmanaged] TThis, TInterface>(TThis* this, out TInterface object) where TThis : struct where TInterface : class { object = ComWrappers.ComInterfaceDispatch.GetInstance<TInterface>((ComWrappers.ComInterfaceDispatch*)this); if (object != null) return S_OK; return COR_E_OBJECTDISPOSED; } internal unsafe static void PopulateIUnknown<[IsUnmanaged] TComInterface>(IUnknown.Vtbl* vtable) where TComInterface : struct { PopulateIUnknownImpl<TComInterface>(vtable); if (vtable->QueryInterface_1 == (IntPtr)(void*)null) throw new NotImplementedException("v-tables cannot be accessed unless the Windows.Win32.ComHelpers.PopulateIUnknownImpl partial method is implemented."); } private unsafe static void PopulateIUnknownImpl<[IsUnmanaged] TComInterface>(IUnknown.Vtbl* vtable) where TComInterface : struct { WinFormsComWrappers.PopulateIUnknownVTable(vtable); } } }