diff --git a/src/WinRT.Runtime/ApiCompatBaseline.txt b/src/WinRT.Runtime/ApiCompatBaseline.txt index 720baef0a..e73eb07dd 100644 --- a/src/WinRT.Runtime/ApiCompatBaseline.txt +++ b/src/WinRT.Runtime/ApiCompatBaseline.txt @@ -14,4 +14,5 @@ CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAc CannotMakeMemberNonVirtual : Member 'public System.Int32 WinRT.IObjectReference.TryAs(System.Guid, WinRT.ObjectReference)' is non-virtual in the implementation but is virtual in the contract. MembersMustExist : Member 'protected System.Boolean System.Boolean WinRT.IObjectReference.disposed' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'protected void WinRT.IObjectReference.Dispose(System.Boolean)' does not exist in the implementation but it does exist in the contract. -Total Issues: 15 +CannotChangeAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' on 'ABI.System.Type.FromAbi(ABI.System.Type)' changed from '[UnconditionalSuppressMessageAttribute("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification="Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")]' in the contract to '[UnconditionalSuppressMessageAttribute("ReflectionAnalysis", "IL2057", Justification="Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")]' in the implementation. +Total Issues: 16 diff --git a/src/WinRT.Runtime/ComWrappersSupport.cs b/src/WinRT.Runtime/ComWrappersSupport.cs index 6b8d7b44c..0e3293887 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.cs @@ -385,31 +385,37 @@ private static Func CreateKeyValuePairFactory(Type type) return createRcwFunc; } - internal static Func CreateDelegateFactory(Type type) + internal static Func GetOrCreateDelegateFactory(Type type) { - return DelegateFactoryCache.GetOrAdd(type, (type) => - { - var createRcwFunc = (Func)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static). - CreateDelegate(typeof(Func)); - var iid = GuidGenerator.GetIID(type); + return DelegateFactoryCache.GetOrAdd(type, CreateDelegateFactory); + } + +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067", + Justification = "The type is a delegate type, so 'GuidGenerator.GetIID' doesn't need to access public fields from it (it uses the helper type).")] +#endif + private static Func CreateDelegateFactory(Type type) + { + var createRcwFunc = (Func)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static). + CreateDelegate(typeof(Func)); + var iid = GuidGenerator.GetIID(type); - return (IntPtr externalComObject) => + return (IntPtr externalComObject) => + { + // The CreateRCW function for delegates expect the pointer to be the delegate interface in CsWinRT 1.5. + // But CreateObject is passed the IUnknown interface. This would typically be fine for delegates as delegates + // don't implement interfaces and implementations typically have both the IUnknown vtable and the delegate + // vtable point to the same vtable. But when the pointer is to a proxy, that can not be relied on. + Marshal.ThrowExceptionForHR(Marshal.QueryInterface(externalComObject, ref iid, out var ptr)); + try { - // The CreateRCW function for delegates expect the pointer to be the delegate interface in CsWinRT 1.5. - // But CreateObject is passed the IUnknown interface. This would typically be fine for delegates as delegates - // don't implement interfaces and implementations typically have both the IUnknown vtable and the delegate - // vtable point to the same vtable. But when the pointer is to a proxy, that can not be relied on. - Marshal.ThrowExceptionForHR(Marshal.QueryInterface(externalComObject, ref iid, out var ptr)); - try - { - return createRcwFunc(ptr); - } - finally - { - Marshal.Release(ptr); - } - }; - }); + return createRcwFunc(ptr); + } + finally + { + Marshal.Release(ptr); + } + }; } public static bool RegisterDelegateFactory(Type implementationType, Func delegateFactory) => DelegateFactoryCache.TryAdd(implementationType, delegateFactory); diff --git a/src/WinRT.Runtime/ComWrappersSupport.net5.cs b/src/WinRT.Runtime/ComWrappersSupport.net5.cs index 855be7593..c66a77d44 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.net5.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.net5.cs @@ -181,9 +181,6 @@ internal static IntPtr CreateCCWForObjectForABI(object obj, Guid iid) public static unsafe T FindObject(IntPtr ptr) where T : class => ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)ptr); - private static T FindDelegate(IntPtr thisPtr) - where T : class, System.Delegate => FindObject(thisPtr); - public static IUnknownVftbl IUnknownVftbl => DefaultComWrappers.IUnknownVftbl; public static IntPtr IUnknownVftblPtr => DefaultComWrappers.IUnknownVftblPtr; @@ -537,7 +534,7 @@ private static object CreateObject(IntPtr externalComObject) { if (ComWrappersSupport.CreateRCWType != null && ComWrappersSupport.CreateRCWType.IsDelegate()) { - return ComWrappersSupport.CreateDelegateFactory(ComWrappersSupport.CreateRCWType)(externalComObject); + return ComWrappersSupport.GetOrCreateDelegateFactory(ComWrappersSupport.CreateRCWType)(externalComObject); } else if (Marshal.QueryInterface(externalComObject, ref inspectableIID, out ptr) == 0) { diff --git a/src/WinRT.Runtime/ComWrappersSupport.netstandard2.0.cs b/src/WinRT.Runtime/ComWrappersSupport.netstandard2.0.cs index 92ec5f02f..e3c60195f 100644 --- a/src/WinRT.Runtime/ComWrappersSupport.netstandard2.0.cs +++ b/src/WinRT.Runtime/ComWrappersSupport.netstandard2.0.cs @@ -48,7 +48,7 @@ private static T CreateRcwForComObject(IntPtr ptr, bool tryUseCache) object runtimeWrapper = null; if (typeof(T).IsDelegate()) { - runtimeWrapper = CreateDelegateFactory(typeof(T))(ptr); + runtimeWrapper = GetOrCreateDelegateFactory(typeof(T))(ptr); } else if (identity.TryAs(out var inspectableRef) == 0) { diff --git a/src/WinRT.Runtime/Marshalers.cs b/src/WinRT.Runtime/Marshalers.cs index 9a1fdadc5..a3d930bbe 100644 --- a/src/WinRT.Runtime/Marshalers.cs +++ b/src/WinRT.Runtime/Marshalers.cs @@ -1499,14 +1499,16 @@ private static Func BindCreateMarshaler() public #endif static class MarshalInspectable< -#if NET6_0_OR_GREATER - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.NonPublicConstructors)] -#elif NET - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] #endif T> { - public static IObjectReference CreateMarshaler( + public static IObjectReference CreateMarshaler< +#if NET + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] +#endif + V>( T o, Guid iid, bool unwrapObject = true) @@ -1687,6 +1689,10 @@ public static ObjectReferenceValue CreateMarshaler2(object o, Guid delegateIID, return ComWrappersSupport.CreateCCWForObjectForMarshaling(o, delegateIID); } +#if NET + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2091", + Justification = "Preserving constructors is not necessary when creating RCWs for delegates, as they go through the factory methods in the helper types.")] +#endif public static T FromAbi(IntPtr nativeDelegate) where T : Delegate { @@ -1694,14 +1700,13 @@ public static T FromAbi(IntPtr nativeDelegate) { return null; } - else if (IUnknownVftbl.IsReferenceToManagedObject(nativeDelegate)) + + if (IUnknownVftbl.IsReferenceToManagedObject(nativeDelegate)) { return ComWrappersSupport.FindObject(nativeDelegate); } - else - { - return ComWrappersSupport.CreateRcwForComObject(nativeDelegate); - } + + return ComWrappersSupport.CreateRcwForComObject(nativeDelegate); } } diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt index ecaea5c28..025d85e37 100644 --- a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt +++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt @@ -137,4 +137,6 @@ MembersMustExist : Member 'public WinRT.ObjectReference WinRT.ObjectReference MembersMustExist : Member 'public WinRT.ObjectReference WinRT.ObjectReference.FromAbi(System.IntPtr, System.Guid)' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public WinRT.ObjectReference WinRT.ObjectReference.FromAbi(System.IntPtr, T, System.Guid)' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'WinRT.ActivationFactory' does not exist in the reference but it does exist in the implementation. -Total Issues: 138 +CannotChangeAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' on 'ABI.System.Type.FromAbi(ABI.System.Type)' changed from '[UnconditionalSuppressMessageAttribute("ReflectionAnalysis", "IL2057", Justification="Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")]' in the implementation to '[UnconditionalSuppressMessageAttribute("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification="Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")]' in the reference. +CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute' exists on 'WinRT.MarshalDelegate.FromAbi(System.IntPtr)' in the implementation but not the reference. +Total Issues: 140 diff --git a/src/WinRT.Runtime/Projections/Type.cs b/src/WinRT.Runtime/Projections/Type.cs index 7c4d39f8d..f324875cb 100644 --- a/src/WinRT.Runtime/Projections/Type.cs +++ b/src/WinRT.Runtime/Projections/Type.cs @@ -128,7 +128,7 @@ public static Type GetAbi(Marshaler m) } #if NET - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057", Justification = "Any types which are trimmed are not used by managed user code and there is fallback logic to handle that.")] #endif public static global::System.Type FromAbi(Type value)