Skip to content

Commit

Permalink
Stop preserving interfaces from MarshalInspectable<T> (#1452)
Browse files Browse the repository at this point in the history
* Fix trim warnings in MarshalInspectable<T>

* Fix trimming warnings in Type

* Update ApiCompatBaseline.txt

* Update MatchingRefApiCompatBaseline.txt

* Remove more warnings, and a leftover method
  • Loading branch information
Sergio0694 authored Jan 26, 2024
1 parent c989f44 commit ed303ba
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 40 deletions.
3 changes: 2 additions & 1 deletion src/WinRT.Runtime/ApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.DynamicallyAc
CannotMakeMemberNonVirtual : Member 'public System.Int32 WinRT.IObjectReference.TryAs<T>(System.Guid, WinRT.ObjectReference<T>)' 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
50 changes: 28 additions & 22 deletions src/WinRT.Runtime/ComWrappersSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,31 +385,37 @@ private static Func<IInspectable, object> CreateKeyValuePairFactory(Type type)
return createRcwFunc;
}

internal static Func<IntPtr, object> CreateDelegateFactory(Type type)
internal static Func<IntPtr, object> GetOrCreateDelegateFactory(Type type)
{
return DelegateFactoryCache.GetOrAdd(type, (type) =>
{
var createRcwFunc = (Func<IntPtr, object>)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static).
CreateDelegate(typeof(Func<IntPtr, object>));
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<IntPtr, object> CreateDelegateFactory(Type type)
{
var createRcwFunc = (Func<IntPtr, object>)type.GetHelperType().GetMethod("CreateRcw", BindingFlags.Public | BindingFlags.Static).
CreateDelegate(typeof(Func<IntPtr, object>));
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<IntPtr, object> delegateFactory) => DelegateFactoryCache.TryAdd(implementationType, delegateFactory);
Expand Down
5 changes: 1 addition & 4 deletions src/WinRT.Runtime/ComWrappersSupport.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,6 @@ internal static IntPtr CreateCCWForObjectForABI(object obj, Guid iid)
public static unsafe T FindObject<T>(IntPtr ptr)
where T : class => ComInterfaceDispatch.GetInstance<T>((ComInterfaceDispatch*)ptr);

private static T FindDelegate<T>(IntPtr thisPtr)
where T : class, System.Delegate => FindObject<T>(thisPtr);

public static IUnknownVftbl IUnknownVftbl => DefaultComWrappers.IUnknownVftbl;
public static IntPtr IUnknownVftblPtr => DefaultComWrappers.IUnknownVftblPtr;

Expand Down Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/ComWrappersSupport.netstandard2.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private static T CreateRcwForComObject<T>(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<IInspectable.Vftbl>(out var inspectableRef) == 0)
{
Expand Down
25 changes: 15 additions & 10 deletions src/WinRT.Runtime/Marshalers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1499,14 +1499,16 @@ private static Func<T, IObjectReference> 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<V>(
public static IObjectReference CreateMarshaler<
#if NET
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)]
#endif
V>(
T o,
Guid iid,
bool unwrapObject = true)
Expand Down Expand Up @@ -1687,21 +1689,24 @@ 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<T>(IntPtr nativeDelegate)
where T : Delegate
{
if (nativeDelegate == IntPtr.Zero)
{
return null;
}
else if (IUnknownVftbl.IsReferenceToManagedObject(nativeDelegate))

if (IUnknownVftbl.IsReferenceToManagedObject(nativeDelegate))
{
return ComWrappersSupport.FindObject<T>(nativeDelegate);
}
else
{
return ComWrappersSupport.CreateRcwForComObject<T>(nativeDelegate);
}

return ComWrappersSupport.CreateRcwForComObject<T>(nativeDelegate);
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,6 @@ MembersMustExist : Member 'public WinRT.ObjectReference<T> WinRT.ObjectReference
MembersMustExist : Member 'public WinRT.ObjectReference<T> WinRT.ObjectReference<T>.FromAbi(System.IntPtr, System.Guid)' does not exist in the reference but it does exist in the implementation.
MembersMustExist : Member 'public WinRT.ObjectReference<T> WinRT.ObjectReference<T>.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<T>(System.IntPtr)' in the implementation but not the reference.
Total Issues: 140
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/Projections/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit ed303ba

Please sign in to comment.