From: Jeremy Koritzinsky Date: Sat, 20 Nov 2021 03:28:42 +0000 (-0800) Subject: Use reflection or a compile-time only shim assembly to reference unexposed corelib... X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~12157 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7099f4b12a9335690eae6b9b6170bc7431e88621;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Use reflection or a compile-time only shim assembly to reference unexposed corelib types. (#61802) Co-authored-by: Aaron Robinson --- diff --git a/docs/workflow/testing/coreclr/test-configuration.md b/docs/workflow/testing/coreclr/test-configuration.md index 3e0f0d2..a2342d3 100644 --- a/docs/workflow/testing/coreclr/test-configuration.md +++ b/docs/workflow/testing/coreclr/test-configuration.md @@ -52,8 +52,6 @@ Therefore the managed portion of each test **must not contain**: * Exclude test from JIT stress runs runs by adding the following to the csproj: * `true` * Add NuGet references by updating the following [test project](https://github.com/dotnet/runtime/blob/main/src/tests/Common/test_dependencies/test_dependencies.csproj). -* Get access to System.Private.CoreLib types and methods that are not exposed via public surface by adding the following to the csproj: - * `true` * Any System.Private.CoreLib types and methods used by tests must be available for building on all platforms. This means there must be enough implementation for the C# compiler to find the referenced types and methods. Unsupported target platforms should simply `throw new PlatformNotSupportedException()` in its dummy method implementations. diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivationContextInternal.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivationContextInternal.cs index 1db025e..c16a56e 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivationContextInternal.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivationContextInternal.cs @@ -25,7 +25,7 @@ namespace Internal.Runtime.InteropServices // [StructLayout(LayoutKind.Sequential)] - public partial struct ComActivationContext + internal partial struct ComActivationContext { public Guid ClassId; public Guid InterfaceId; @@ -38,7 +38,7 @@ namespace Internal.Runtime.InteropServices [ComVisible(false)] [Guid("00000001-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IClassFactory + internal interface IClassFactory { [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] void CreateInstance( diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs index 6d4ddfa..1bb64cf 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs @@ -12,35 +12,24 @@ namespace Internal.Runtime.InteropServices /// Internal entry point for unmanaged COM activation API from native code /// /// Pointer to a instance - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int GetClassFactoryForTypeInternal(ComActivationContextInternal* pCxtInt) + private static unsafe int GetClassFactoryForTypeInternal(ComActivationContextInternal* pCxtInt) => throw new PlatformNotSupportedException(); /// /// Internal entry point for registering a managed COM server API from native code /// /// Pointer to a instance - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int RegisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) + private static unsafe int RegisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) => throw new PlatformNotSupportedException(); /// /// Internal entry point for unregistering a managed COM server API from native code /// /// Pointer to a instance - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int UnregisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) - => throw new PlatformNotSupportedException(); - - // Exists here to allow tests to build on any platform. - public static object GetClassFactoryForType(ComActivationContext cxt) - => throw new PlatformNotSupportedException(); - - // Exists here to allow tests to build on any platform. - public static void ClassRegistrationScenarioForType(ComActivationContext cxt, bool register) + private static unsafe int UnregisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) => throw new PlatformNotSupportedException(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs index a00ecd1..a78bb67 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs @@ -57,10 +57,9 @@ namespace Internal.Runtime.InteropServices out IntPtr ppvObject); } - public partial struct ComActivationContext + internal partial struct ComActivationContext { [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - [CLSCompliant(false)] public static unsafe ComActivationContext Create(ref ComActivationContextInternal cxtInt) { if (!Marshal.IsBuiltInComSupported) @@ -91,7 +90,7 @@ namespace Internal.Runtime.InteropServices /// /// Reference to a instance [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - public static object GetClassFactoryForType(ComActivationContext cxt) + private static object GetClassFactoryForType(ComActivationContext cxt) { if (!Marshal.IsBuiltInComSupported) { @@ -125,7 +124,7 @@ namespace Internal.Runtime.InteropServices /// Reference to a instance /// true if called for register or false to indicate unregister [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - public static void ClassRegistrationScenarioForType(ComActivationContext cxt, bool register) + private static void ClassRegistrationScenarioForType(ComActivationContext cxt, bool register) { if (!Marshal.IsBuiltInComSupported) { @@ -219,9 +218,8 @@ namespace Internal.Runtime.InteropServices /// /// Pointer to a instance [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int GetClassFactoryForTypeInternal(ComActivationContextInternal* pCxtInt) + private static unsafe int GetClassFactoryForTypeInternal(ComActivationContextInternal* pCxtInt) { if (!Marshal.IsBuiltInComSupported) { @@ -262,9 +260,8 @@ $@"{nameof(GetClassFactoryForTypeInternal)} arguments: /// /// Pointer to a instance [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int RegisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) + private static unsafe int RegisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) { if (!Marshal.IsBuiltInComSupported) { @@ -308,9 +305,8 @@ $@"{nameof(RegisterClassForTypeInternal)} arguments: /// Internal entry point for unregistering a managed COM server API from native code /// [RequiresUnreferencedCode("Built-in COM support is not trim compatible", Url = "https://aka.ms/dotnet-illink/com")] - [CLSCompliant(false)] [UnmanagedCallersOnly] - public static unsafe int UnregisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) + private static unsafe int UnregisterClassForTypeInternal(ComActivationContextInternal* pCxtInt) { if (!Marshal.IsBuiltInComSupported) { diff --git a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props index cf35f35..b05866e 100644 --- a/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props +++ b/src/tests/Common/XUnitWrapperGenerator/XUnitWrapperGenerator.props @@ -6,7 +6,6 @@ - diff --git a/src/tests/Common/override.targets b/src/tests/Common/override.targets deleted file mode 100644 index 0586ffe..0000000 --- a/src/tests/Common/override.targets +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index 0c52df3..84bb4bd 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -80,7 +80,6 @@ <_WillCLRTestProjectBuild Condition="'$(BuildAllProjects)' != 'true'">true <_WillCLRTestProjectBuild Condition="'$(BuildAllProjects)' == 'true' And '$(CLRTestPriority)' <= '$(CLRTestPriorityToBuild)'">true <_WillCLRTestProjectBuild Condition="'$(CLRTestBuildAllTargets)' != 'allTargets' And '$(CLRTestTargetUnsupported)' == 'true'">false - <_WillCLRTestProjectBuild Condition="'$(ReferenceSystemPrivateCoreLib)' == 'true' and '$(RuntimeFlavor)' == 'mono'">false <_WillCLRTestProjectBuild Condition="'$(DisableProjectBuild)' == 'true'">false @@ -95,8 +94,6 @@ - - @@ -225,12 +222,11 @@ BeforeTargets="BeforeResolveReferences" > + Targets="GetLiveRefAssemblies"> - + false @@ -255,10 +251,6 @@ $(BaseOutputPath)\packages\Common\test_dependencies\test_dependencies\project.assets.json - - - - true diff --git a/src/tests/Interop/COM/Activator/Activator.csproj b/src/tests/Interop/COM/Activator/Activator.csproj index 87b0633..6090e01d 100644 --- a/src/tests/Interop/COM/Activator/Activator.csproj +++ b/src/tests/Interop/COM/Activator/Activator.csproj @@ -1,14 +1,15 @@ Exe - - true true true + true + true + diff --git a/src/tests/Interop/COM/Activator/ActivatorBuiltInComDisabled.csproj b/src/tests/Interop/COM/Activator/ActivatorBuiltInComDisabled.csproj index b119bcc..5414a40 100644 --- a/src/tests/Interop/COM/Activator/ActivatorBuiltInComDisabled.csproj +++ b/src/tests/Interop/COM/Activator/ActivatorBuiltInComDisabled.csproj @@ -1,14 +1,15 @@ Exe - - true true true + true + true + diff --git a/src/tests/Interop/COM/Activator/ComActivationContext.cs b/src/tests/Interop/COM/Activator/ComActivationContext.cs new file mode 100644 index 0000000..9864107 --- /dev/null +++ b/src/tests/Interop/COM/Activator/ComActivationContext.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Activator +{ + [StructLayout(LayoutKind.Sequential)] + public partial struct ComActivationContext + { + public Guid ClassId; + public Guid InterfaceId; + public string AssemblyPath; + public string AssemblyName; + public string TypeName; + } +} diff --git a/src/tests/Interop/COM/Activator/Program.cs b/src/tests/Interop/COM/Activator/Program.cs index b16802d..48bd0d5 100644 --- a/src/tests/Interop/COM/Activator/Program.cs +++ b/src/tests/Interop/COM/Activator/Program.cs @@ -1,21 +1,65 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; -namespace Activator +using Internal.Runtime.InteropServices; +using TestLibrary; +using Xunit; + +namespace Internal.Runtime.InteropServices { - using Internal.Runtime.InteropServices; + [ComImport] + [ComVisible(false)] + [Guid("00000001-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IClassFactory + { + void CreateInstance( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + ref Guid riid, + out IntPtr ppvObject); - using System; - using System.IO; - using System.Runtime.InteropServices; + void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); + } +} - using TestLibrary; - using Xunit; +sealed class ClassFactoryWrapper +{ + private static readonly MethodInfo IClassFactory_Create = typeof(object).Assembly.GetType("Internal.Runtime.InteropServices.IClassFactory").GetMethod("CreateInstance"); + private readonly object _obj; + + public ClassFactoryWrapper(object obj) + { + _obj = obj; + } - using Console = Internal.Console; + public void CreateInstance( + object pUnkOuter, + ref Guid riid, + out IntPtr ppvObject) + { + object[] args = new object[] { pUnkOuter, riid, null }; + IClassFactory_Create.Invoke(_obj, BindingFlags.DoNotWrapExceptions, binder: null, args, culture: null); + riid = (Guid)args[1]; + ppvObject = (IntPtr)args[2]; + } +} - class Program +namespace Activator +{ + unsafe class Program { + private static delegate* GetClassFactoryForTypeMethod = (delegate*)typeof(object).Assembly.GetType("Internal.Runtime.InteropServices.ComActivator", throwOnError: true).GetMethod("GetClassFactoryForType", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer(); + private static delegate* ClassRegistrationScenarioForType = (delegate*)typeof(object).Assembly.GetType("Internal.Runtime.InteropServices.ComActivator", throwOnError: true).GetMethod("ClassRegistrationScenarioForType", BindingFlags.NonPublic | BindingFlags.Static).MethodHandle.GetFunctionPointer(); + + private static ClassFactoryWrapper GetClassFactoryForType(ComActivationContext context) + { + return new ClassFactoryWrapper(GetClassFactoryForTypeMethod(context)); + } + static void InvalidInterfaceRequest() { Console.WriteLine($"Running {nameof(InvalidInterfaceRequest)}..."); @@ -28,7 +72,7 @@ namespace Activator { InterfaceId = notIClassFactory }; - ComActivator.GetClassFactoryForType(cxt); + GetClassFactoryForType(cxt); }); } @@ -43,7 +87,7 @@ namespace Activator InterfaceId = typeof(IClassFactory).GUID, AssemblyPath = "foo.dll" }; - ComActivator.GetClassFactoryForType(cxt); + GetClassFactoryForType(cxt); }; if (!builtInComDisabled) @@ -69,7 +113,7 @@ namespace Activator InterfaceId = typeof(IClassFactory).GUID, AssemblyPath = @"C:\foo.dll" }; - ComActivator.GetClassFactoryForType(cxt); + GetClassFactoryForType(cxt); }; if (!builtInComDisabled) @@ -119,11 +163,11 @@ namespace Activator if (builtInComDisabled) { Assert.Throws( - () => ComActivator.GetClassFactoryForType(cxt)); + () => GetClassFactoryForType(cxt)); return; } - var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt); + var factory = GetClassFactoryForType(cxt); IntPtr svrRaw; factory.CreateInstance(null, ref iid, out svrRaw); @@ -147,7 +191,7 @@ namespace Activator TypeName = "ClassFromB" }; - var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt); + var factory = GetClassFactoryForType(cxt); IntPtr svrRaw; factory.CreateInstance(null, ref iid, out svrRaw); @@ -200,7 +244,7 @@ namespace Activator TypeName = typeName }; - var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt); + var factory = GetClassFactoryForType(cxt); IntPtr svrRaw; factory.CreateInstance(null, ref iid, out svrRaw); @@ -212,8 +256,8 @@ namespace Activator Assert.False(inst.DidUnregister()); cxt.InterfaceId = Guid.Empty; - ComActivator.ClassRegistrationScenarioForType(cxt, register: true); - ComActivator.ClassRegistrationScenarioForType(cxt, register: false); + ClassRegistrationScenarioForType(cxt, true); + ClassRegistrationScenarioForType(cxt, false); Assert.True(inst.DidRegister(), $"User-defined register function should have been called."); Assert.True(inst.DidUnregister(), $"User-defined unregister function should have been called."); @@ -239,7 +283,7 @@ namespace Activator TypeName = typename }; - var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt); + var factory = GetClassFactoryForType(cxt); IntPtr svrRaw; factory.CreateInstance(null, ref iid, out svrRaw); @@ -251,7 +295,7 @@ namespace Activator bool exceptionThrown = false; try { - ComActivator.ClassRegistrationScenarioForType(cxt, register: true); + ClassRegistrationScenarioForType(cxt, true); } catch { @@ -263,7 +307,7 @@ namespace Activator exceptionThrown = false; try { - ComActivator.ClassRegistrationScenarioForType(cxt, register: false); + ClassRegistrationScenarioForType(cxt, false); } catch { diff --git a/src/tests/Interop/Directory.Build.targets b/src/tests/Interop/Directory.Build.targets index 0d5ce0b..12c68c9 100644 --- a/src/tests/Interop/Directory.Build.targets +++ b/src/tests/Interop/Directory.Build.targets @@ -3,20 +3,11 @@ - + - - - - - - - diff --git a/src/tests/Interop/ICastable/Castable.cs b/src/tests/Interop/ICastable/Castable.cs index 3a20177..5493d16 100644 --- a/src/tests/Interop/ICastable/Castable.cs +++ b/src/tests/Interop/ICastable/Castable.cs @@ -6,18 +6,6 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using Xunit; -using Console = Internal.Console; - -namespace Xunit -{ - // Include an inline definition of the SkipOnMonoAttribute type as tests that reference CoreLib - // only reference CoreLib and don't reference any other assemblies. - public class SkipOnMonoAttribute : Attribute - { - public SkipOnMonoAttribute(string reason, int testPlatforms = ~0) { } - } -} - public interface IRetArg { T ReturnArg(T t); diff --git a/src/tests/Interop/ICastable/Castable.csproj b/src/tests/Interop/ICastable/Castable.csproj index 7007b69..76fc602 100644 --- a/src/tests/Interop/ICastable/Castable.csproj +++ b/src/tests/Interop/ICastable/Castable.csproj @@ -1,9 +1,9 @@ - - true + true + diff --git a/src/tests/Interop/ICastable/ICastable.CoreLib.csproj b/src/tests/Interop/ICastable/ICastable.CoreLib.csproj new file mode 100644 index 0000000..482a08e --- /dev/null +++ b/src/tests/Interop/ICastable/ICastable.CoreLib.csproj @@ -0,0 +1,17 @@ + + + + Library + SharedLibrary + System.Private.CoreLib + annotations + + + + + diff --git a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs index e7df50e..66232d4 100644 --- a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs +++ b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.cs @@ -5,12 +5,9 @@ using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; -using Internal.Runtime.InteropServices; using TestLibrary; using Xunit; -using Console = Internal.Console; - namespace LoadIjwFromModuleHandle { class LoadIjwFromModuleHandle @@ -38,7 +35,15 @@ namespace LoadIjwFromModuleHandle string.Empty)) fixed (char* path = ijwModulePath) { - InMemoryAssemblyLoader.LoadInMemoryAssembly(ijwNativeHandle, (IntPtr)path); + typeof(object).Assembly + .GetType("Internal.Runtime.InteropServices.InMemoryAssemblyLoader") + .GetMethod("LoadInMemoryAssembly") + .Invoke( + null, + BindingFlags.DoNotWrapExceptions, + binder: null, + new object[] { ijwNativeHandle, (IntPtr)path }, + culture: null); } NativeEntryPointDelegate nativeEntryPoint = Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(ijwNativeHandle, "NativeEntryPoint")); diff --git a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.csproj b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.csproj index a42c985..f5f12e8 100644 --- a/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.csproj +++ b/src/tests/Interop/IJW/LoadIjwFromModuleHandle/LoadIjwFromModuleHandle.csproj @@ -1,8 +1,6 @@ Exe - - true true true @@ -12,6 +10,7 @@ true true + true true