From 1c9e2009d9942a6df31daad8c912c68446856fa2 Mon Sep 17 00:00:00 2001 From: Lakshan Fernando Date: Tue, 27 Apr 2021 04:03:13 -0700 Subject: [PATCH] Feature switch to turn off COM support in Windows (#50662) * Incorporating FB * non-windows build break fix * FB * fb * test fixes + added new guards to missed ones * test fixed based on FB --- .../Runtime/InteropServices/ComActivator.cs | 36 ++++ .../InteropServices/Marshal.CoreCLR.cs | 115 ++++++++++- .../src/System/RuntimeType.CoreCLR.cs | 5 + src/coreclr/vm/ecalllist.h | 9 +- src/coreclr/vm/eeconfig.cpp | 2 + src/coreclr/vm/eeconfig.h | 3 + src/coreclr/vm/interopconverter.cpp | 9 + src/coreclr/vm/marshalnative.cpp | 29 ++- src/coreclr/vm/marshalnative.h | 9 +- .../src/Resources/Strings.resx | 3 + ...e.InteropServices.ComDisabled.Tests.csproj | 15 ++ .../Marshal/MarshalComDisabledTests.cs | 181 ++++++++++++++++++ 12 files changed, 400 insertions(+), 16 deletions(-) create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj create mode 100644 src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs 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 9f2c011efac3..598d7b809e89 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 @@ -91,10 +91,16 @@ public struct ComActivationContext public string AssemblyName; public string TypeName; + [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 FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + return new ComActivationContext() { ClassId = cxtInt.ClassId, @@ -122,9 +128,15 @@ public static class ComActivator /// Entry point for unmanaged COM activation API from managed code /// /// 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) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (cxt.InterfaceId != typeof(IClassFactory).GUID && cxt.InterfaceId != typeof(IClassFactory2).GUID) { @@ -154,9 +166,15 @@ public static object GetClassFactoryForType(ComActivationContext cxt) /// /// 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) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + // Retrieve the attribute type to use to determine if a function is the requested user defined // registration function. string attributeName = register ? "ComRegisterFunctionAttribute" : "ComUnregisterFunctionAttribute"; @@ -246,11 +264,17 @@ public static void ClassRegistrationScenarioForType(ComActivationContext cxt, bo /// Internal entry point for unmanaged COM activation API from native code /// /// 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) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + ref ComActivationContextInternal cxtInt = ref *pCxtInt; if (IsLoggingEnabled()) @@ -287,11 +311,17 @@ public static unsafe int GetClassFactoryForTypeInternal(ComActivationContextInte /// Internal entry point for registering a managed COM server API from native code /// /// 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) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + ref ComActivationContextInternal cxtInt = ref *pCxtInt; if (IsLoggingEnabled()) @@ -331,11 +361,17 @@ public static unsafe int RegisterClassForTypeInternal(ComActivationContextIntern /// /// 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) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + ref ComActivationContextInternal cxtInt = ref *pCxtInt; if (IsLoggingEnabled()) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index 823ddadc0431..46ea1bb35438 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -195,6 +195,9 @@ private static void PrelinkCore(MethodInfo m) [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void InternalPrelink(RuntimeMethodHandleInternal m); + [DllImport(RuntimeHelpers.QCall)] + private static extern bool IsComSupportedInternal(); + [MethodImpl(MethodImplOptions.InternalCall)] public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers(); @@ -233,6 +236,10 @@ private static object PtrToStructureHelper(IntPtr ptr, Type structureType) [MethodImpl(MethodImplOptions.InternalCall)] internal static extern bool IsPinnable(object? obj); + internal static bool IsComSupported { get; } = InitializeIsComSupported(); + + private static bool InitializeIsComSupported() => IsComSupportedInternal(); + #if TARGET_WINDOWS /// /// Returns the HInstance for this module. Returns -1 if the module doesn't have @@ -289,6 +296,11 @@ public static string GetTypeInfoName(ITypeInfo typeInfo) // on Marshal for more consistent API surface. internal static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + // Note: "throwOnError" is a vacuous parameter. Any errors due to the CLSID not being registered or the server not being found will happen // on the Activator.CreateInstance() call. GetTypeFromCLSID() merely wraps the data in a Type object without any validation. @@ -429,12 +441,27 @@ public static object GetUniqueObjectForIUnknown(IntPtr unknown) public static extern object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t); [SupportedOSPlatform("windows")] + public static IntPtr CreateAggregatedObject(IntPtr pOuter, object o) + { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + + return CreateAggregatedObjectNative(pOuter, o); + } + [MethodImpl(MethodImplOptions.InternalCall)] - public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, object o); + private static extern IntPtr CreateAggregatedObjectNative(IntPtr pOuter, object o); [SupportedOSPlatform("windows")] public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) where T : notnull { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + return CreateAggregatedObject(pOuter, (object)o); } @@ -457,6 +484,11 @@ public static object GetUniqueObjectForIUnknown(IntPtr unknown) [SupportedOSPlatform("windows")] public static int ReleaseComObject(object o) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (o is null) { // Match .NET Framework behaviour. @@ -480,6 +512,11 @@ public static int ReleaseComObject(object o) [SupportedOSPlatform("windows")] public static int FinalReleaseComObject(object o) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (o is null) { throw new ArgumentNullException(nameof(o)); @@ -499,6 +536,11 @@ public static int FinalReleaseComObject(object o) [SupportedOSPlatform("windows")] public static object? GetComObjectData(object obj, object key) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (obj is null) { throw new ArgumentNullException(nameof(obj)); @@ -525,6 +567,11 @@ public static int FinalReleaseComObject(object o) [SupportedOSPlatform("windows")] public static bool SetComObjectData(object obj, object key, object? data) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (obj is null) { throw new ArgumentNullException(nameof(obj)); @@ -550,6 +597,11 @@ public static bool SetComObjectData(object obj, object key, object? data) [return: NotNullIfNotNull("o")] public static object? CreateWrapperOfType(object? o, Type t) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + if (t is null) { throw new ArgumentNullException(nameof(t)); @@ -600,6 +652,11 @@ public static bool SetComObjectData(object obj, object key, object? data) [SupportedOSPlatform("windows")] public static TWrapper CreateWrapperOfType(T? o) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper))!; } @@ -613,32 +670,77 @@ public static bool SetComObjectData(object obj, object key, object? data) public static extern bool IsTypeVisibleFromCom(Type t); [SupportedOSPlatform("windows")] + public static void GetNativeVariantForObject(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant) + { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + + GetNativeVariantForObjectNative(obj, pDstNativeVariant); + } + [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void GetNativeVariantForObject(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant); + private static extern void GetNativeVariantForObjectNative(object? obj, /* VARIANT * */ IntPtr pDstNativeVariant); [SupportedOSPlatform("windows")] public static void GetNativeVariantForObject(T? obj, IntPtr pDstNativeVariant) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + GetNativeVariantForObject((object?)obj, pDstNativeVariant); } [SupportedOSPlatform("windows")] + public static object? GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant) + { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + + return GetObjectForNativeVariantNative(pSrcNativeVariant); + } + [MethodImpl(MethodImplOptions.InternalCall)] - public static extern object? GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant); + private static extern object? GetObjectForNativeVariantNative(/* VARIANT * */ IntPtr pSrcNativeVariant); [SupportedOSPlatform("windows")] public static T? GetObjectForNativeVariant(IntPtr pSrcNativeVariant) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + return (T?)GetObjectForNativeVariant(pSrcNativeVariant); } [SupportedOSPlatform("windows")] + public static object?[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars) + { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + + return GetObjectsForNativeVariantsNative(aSrcNativeVariant, cVars); + } + [MethodImpl(MethodImplOptions.InternalCall)] - public static extern object?[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars); + private static extern object?[] GetObjectsForNativeVariantsNative(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars); [SupportedOSPlatform("windows")] public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int cVars) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + object?[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars); T[] result = new T[objects.Length]; @@ -665,6 +767,11 @@ public static T[] GetObjectsForNativeVariants(IntPtr aSrcNativeVariant, int c [SupportedOSPlatform("windows")] public static object BindToMoniker(string monikerName) { + if (!IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + CreateBindCtx(0, out IBindCtx bindctx); MkParseDisplayName(bindctx, monikerName, out _, out IMoniker pmoniker); diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index 78bb08345933..f645ad15a407 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3680,6 +3680,11 @@ internal static object CreateEnum(RuntimeType enumType, long value) Type[] aArgsTypes, Type retType) { + if (!Marshal.IsComSupported) + { + throw new NotSupportedException(SR.NotSupported_COM); + } + Debug.Assert( aArgs.Length == aArgsIsByRef.Length && aArgs.Length == aArgsTypes.Length diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index ccb784484ab1..d309500d50f9 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -758,6 +758,7 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper) QCFuncElement("InternalPrelink", MarshalNative::Prelink) + QCFuncElement("IsComSupportedInternal", MarshalNative::IsComSupported) FCFuncElement("GetExceptionForHRInternal", MarshalNative::GetExceptionForHR) FCFuncElement("GetDelegateForFunctionPointerInternal", MarshalNative::GetDelegateForFunctionPointerInternal) FCFuncElement("GetFunctionPointerForDelegateInternal", MarshalNative::GetFunctionPointerForDelegateInternal) @@ -767,14 +768,14 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("IsComObject", MarshalNative::IsComObject) FCFuncElement("GetObjectForIUnknownNative", MarshalNative::GetObjectForIUnknownNative) FCFuncElement("GetUniqueObjectForIUnknownNative", MarshalNative::GetUniqueObjectForIUnknownNative) - FCFuncElement("GetNativeVariantForObject", MarshalNative::GetNativeVariantForObject) - FCFuncElement("GetObjectForNativeVariant", MarshalNative::GetObjectForNativeVariant) + FCFuncElement("GetNativeVariantForObjectNative", MarshalNative::GetNativeVariantForObjectNative) + FCFuncElement("GetObjectForNativeVariantNative", MarshalNative::GetObjectForNativeVariantNative) FCFuncElement("InternalFinalReleaseComObject", MarshalNative::FinalReleaseComObject) FCFuncElement("IsTypeVisibleFromCom", MarshalNative::IsTypeVisibleFromCom) - FCFuncElement("CreateAggregatedObject", MarshalNative::CreateAggregatedObject) + FCFuncElement("CreateAggregatedObjectNative", MarshalNative::CreateAggregatedObjectNative) FCFuncElement("AreComObjectsAvailableForCleanup", MarshalNative::AreComObjectsAvailableForCleanup) FCFuncElement("InternalCreateWrapperOfType", MarshalNative::InternalCreateWrapperOfType) - FCFuncElement("GetObjectsForNativeVariants", MarshalNative::GetObjectsForNativeVariants) + FCFuncElement("GetObjectsForNativeVariantsNative", MarshalNative::GetObjectsForNativeVariantsNative) FCFuncElement("GetStartComSlot", MarshalNative::GetStartComSlot) FCFuncElement("GetEndComSlot", MarshalNative::GetEndComSlot) FCFuncElement("GetIUnknownForObjectNative", MarshalNative::GetIUnknownForObjectNative) diff --git a/src/coreclr/vm/eeconfig.cpp b/src/coreclr/vm/eeconfig.cpp index 5dd61484cd48..778edeadae63 100644 --- a/src/coreclr/vm/eeconfig.cpp +++ b/src/coreclr/vm/eeconfig.cpp @@ -170,6 +170,7 @@ HRESULT EEConfig::Init() #ifdef FEATURE_COMINTEROP bLogCCWRefCountChange = false; pszLogCCWRefCountChange = NULL; + m_fBuiltInCOMInteropSupported = true; #endif // FEATURE_COMINTEROP #ifdef _DEBUG @@ -682,6 +683,7 @@ HRESULT EEConfig::sync() bLogCCWRefCountChange = true; fEnableRCWCleanupOnSTAShutdown = (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_EnableRCWCleanupOnSTAShutdown) != 0); + m_fBuiltInCOMInteropSupported = Configuration::GetKnobBooleanValue(W("System.Runtime.InteropServices.Marshal.IsComSupported"), true); #endif // FEATURE_COMINTEROP #ifdef _DEBUG diff --git a/src/coreclr/vm/eeconfig.h b/src/coreclr/vm/eeconfig.h index d995d25007d7..bfb9ba167561 100644 --- a/src/coreclr/vm/eeconfig.h +++ b/src/coreclr/vm/eeconfig.h @@ -287,6 +287,8 @@ class EEConfig LIMITED_METHOD_CONTRACT; return fEnableRCWCleanupOnSTAShutdown; } + + bool IsBuiltInCOMSupported() const { LIMITED_METHOD_CONTRACT; return m_fBuiltInCOMInteropSupported; } #endif // FEATURE_COMINTEROP #ifdef _DEBUG @@ -546,6 +548,7 @@ class EEConfig LPCUTF8 pszLogCCWRefCountChange; // OutputDebugString when AddRef/Release is called on a CCW // for the specified type(s) bool fEnableRCWCleanupOnSTAShutdown; // Register our IInitializeSpy even in classic processes + bool m_fBuiltInCOMInteropSupported; // COM built-in support #endif // FEATURE_COMINTEROP #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT diff --git a/src/coreclr/vm/interopconverter.cpp b/src/coreclr/vm/interopconverter.cpp index 30604d630f03..d74eb6c780fb 100644 --- a/src/coreclr/vm/interopconverter.cpp +++ b/src/coreclr/vm/interopconverter.cpp @@ -113,6 +113,9 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, MethodTable *pMT, BOOL bEnable RETURN pvObj; } + if (!g_pConfig->IsBuiltInCOMSupported()) + COMPlusThrow(kNotSupportedException, W("NotSupported_COM")); + SyncBlock* pBlock = (*poref)->GetSyncBlock(); InteropSyncBlockInfo* pInteropInfo = pBlock->GetInteropInfo(); @@ -201,6 +204,9 @@ IUnknown *GetComIPFromObjectRef(OBJECTREF *poref, ComIpType ReqIpType, ComIpType RETURN pvObj; } + if (!g_pConfig->IsBuiltInCOMSupported()) + COMPlusThrow(kNotSupportedException, W("NotSupported_COM")); + MethodTable *pMT = (*poref)->GetMethodTable(); SyncBlock* pBlock = (*poref)->GetSyncBlock(); @@ -387,6 +393,9 @@ void GetObjectRefFromComIP(OBJECTREF* pObjOut, IUnknown **ppUnk, MethodTable *pM return; } + if (!g_pConfig->IsBuiltInCOMSupported()) + COMPlusThrow(kNotSupportedException, W("NotSupported_COM")); + Thread * pThread = GetThread(); IUnknown* pOuter = pUnk; diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index 7100fe37d8b3..86046fccdcec 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -69,6 +69,27 @@ VOID QCALLTYPE MarshalNative::Prelink(MethodDesc * pMD) END_QCALL; } +// IsComSupported +// Built-in COM support is only checked from the native side to ensure the runtime +// is in a consistent state +BOOL QCALLTYPE MarshalNative::IsComSupported() +{ + QCALL_CONTRACT; + + BOOL ret = TRUE; + + BEGIN_QCALL; + +#ifdef FEATURE_COMINTEROP + ret = g_pConfig->IsBuiltInCOMSupported(); +#else // FEATURE_COMINTEROP + ret = FALSE; +#endif // FEATURE_COMINTEROP + + END_QCALL; + + return ret; +} FCIMPL3(VOID, MarshalNative::StructureToPtr, Object* pObjUNSAFE, LPVOID ptr, CLR_BOOL fDeleteOld) { @@ -821,7 +842,7 @@ FCIMPL2(Object*, MarshalNative::GetTypedObjectForIUnknown, IUnknown* pUnk, Refle } FCIMPLEND -FCIMPL2(IUnknown*, MarshalNative::CreateAggregatedObject, IUnknown* pOuter, Object* refObjUNSAFE) +FCIMPL2(IUnknown*, MarshalNative::CreateAggregatedObjectNative, IUnknown* pOuter, Object* refObjUNSAFE) { CONTRACTL { @@ -1094,7 +1115,7 @@ FCIMPL1(FC_BOOL_RET, MarshalNative::IsTypeVisibleFromCom, ReflectClassBaseObject } FCIMPLEND -FCIMPL2(void, MarshalNative::GetNativeVariantForObject, Object* ObjUNSAFE, LPVOID pDestNativeVariant) +FCIMPL2(void, MarshalNative::GetNativeVariantForObjectNative, Object* ObjUNSAFE, LPVOID pDestNativeVariant) { CONTRACTL { @@ -1126,7 +1147,7 @@ FCIMPL2(void, MarshalNative::GetNativeVariantForObject, Object* ObjUNSAFE, LPVOI } FCIMPLEND -FCIMPL1(Object*, MarshalNative::GetObjectForNativeVariant, LPVOID pSrcNativeVariant) +FCIMPL1(Object*, MarshalNative::GetObjectForNativeVariantNative, LPVOID pSrcNativeVariant) { CONTRACTL { @@ -1148,7 +1169,7 @@ FCIMPL1(Object*, MarshalNative::GetObjectForNativeVariant, LPVOID pSrcNativeVari } FCIMPLEND -FCIMPL2(Object*, MarshalNative::GetObjectsForNativeVariants, VARIANT* aSrcNativeVariant, int cVars) +FCIMPL2(Object*, MarshalNative::GetObjectsForNativeVariantsNative, VARIANT* aSrcNativeVariant, int cVars) { CONTRACTL { diff --git a/src/coreclr/vm/marshalnative.h b/src/coreclr/vm/marshalnative.h index fea67622219c..5971225d22d5 100644 --- a/src/coreclr/vm/marshalnative.h +++ b/src/coreclr/vm/marshalnative.h @@ -20,6 +20,7 @@ class MarshalNative { public: static VOID QCALLTYPE Prelink(MethodDesc * pMD); + static BOOL QCALLTYPE IsComSupported(); //==================================================================== // These methods convert between an HR and and a managed exception. @@ -95,7 +96,7 @@ class MarshalNative //==================================================================== // Create an object and aggregate it, then return the inner unknown. //==================================================================== - static FCDECL2(IUnknown*, CreateAggregatedObject, IUnknown* pOuter, Object* refObjUNSAFE); + static FCDECL2(IUnknown*, CreateAggregatedObjectNative, IUnknown* pOuter, Object* refObjUNSAFE); //==================================================================== // check if the object is classic COM component @@ -123,9 +124,9 @@ class MarshalNative //==================================================================== // These methods convert OLE variants to and from objects. //==================================================================== - static FCDECL2(void, GetNativeVariantForObject, Object* ObjUNSAFE, LPVOID pDestNativeVariant); - static FCDECL1(Object*, GetObjectForNativeVariant, LPVOID pSrcNativeVariant); - static FCDECL2(Object*, GetObjectsForNativeVariants, VARIANT* aSrcNativeVariant, int cVars); + static FCDECL2(void, GetNativeVariantForObjectNative, Object* ObjUNSAFE, LPVOID pDestNativeVariant); + static FCDECL1(Object*, GetObjectForNativeVariantNative, LPVOID pSrcNativeVariant); + static FCDECL2(Object*, GetObjectsForNativeVariantsNative, VARIANT* aSrcNativeVariant, int cVars); //==================================================================== // These methods are used to map COM slots to method info's. diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index ab45140cc875..ebf8f105fe94 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -3721,4 +3721,7 @@ Method body replacement not supported in this runtime. + + Built-in COM has been disabled via a feature switch. See https://aka.ms/dotnet-illink/com for more information. + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj new file mode 100644 index 000000000000..28c2c77dacc2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj @@ -0,0 +1,15 @@ + + + true + $(NetCoreAppCurrent) + true + + true + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs new file mode 100644 index 000000000000..4a927df56cdf --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs @@ -0,0 +1,181 @@ +//using System.Runtime.InteropServices.Tests.Common; +using Xunit; + +namespace System.Runtime.InteropServices.Tests +{ + [PlatformSpecific(TestPlatforms.Windows)] + public partial class MarshalComDisabledTests + { + [Fact] + public void GetTypeFromCLSID_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetTypeFromCLSID(Guid.Empty)); + } + + [Fact] + public void CreateAggregatedObject_ThrowsNotSupportedException() + { + object value = new object(); + Assert.Throws(() => Marshal.CreateAggregatedObject(IntPtr.Zero, value)); + } + + [Fact] + public void CreateAggregatedObject_T_ThrowsNotSupportedException() + { + object value = new object(); + Assert.Throws(() => Marshal.CreateAggregatedObject(IntPtr.Zero, value)); + } + + + [Fact] + public void ReleaseComObject_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.ReleaseComObject(new object())); + } + + [Fact] + public void FinalReleaseComObject_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.FinalReleaseComObject(new object())); + } + + [Fact] + public void GetComObjectData_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetComObjectData("key", "value")); + } + + [Fact] + public void SetComObjectData_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.SetComObjectData(new object(), "key", "value")); + } + + [Fact] + public void CreateWrapperOfType_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.CreateWrapperOfType(new object(), typeof(object))); + } + + [Fact] + public void CreateWrapperOfType_T_TWrapper_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.CreateWrapperOfType(new object())); + } + + [Fact] + public void GetNativeVariantForObject_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetNativeVariantForObject(99, IntPtr.Zero)); + } + + [Fact] + public void GetNativeVariantForObject_T_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetNativeVariantForObject(99, IntPtr.Zero)); + } + + public struct NativeVariant{} + + [Fact] + public void GetObjectForNativeVariant_ThrowsNotSupportedException() + { + NativeVariant variant = new NativeVariant(); + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); + try + { + Marshal.StructureToPtr(variant, ptr, fDeleteOld: false); + Assert.Throws(() => Marshal.GetObjectForNativeVariant(ptr)); + } + finally + { + Marshal.DestroyStructure(ptr); + Marshal.FreeHGlobal(ptr); + } + } + + public struct NativeVariant_T{} + + [Fact] + public void GetObjectForNativeVariant_T_ThrowsNotSupportedException() + { + NativeVariant_T variant = new NativeVariant_T(); + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); + try + { + Marshal.StructureToPtr(variant, ptr, fDeleteOld: false); + Assert.Throws(() => Marshal.GetObjectForNativeVariant(ptr)); + } + finally + { + Marshal.DestroyStructure(ptr); + Marshal.FreeHGlobal(ptr); + } + } + + [Fact] + public void GetObjectsForNativeVariants_ThrowsNotSupportedException() + { + IntPtr ptr = Marshal.AllocHGlobal(2 * Marshal.SizeOf()); + try + { + Assert.Throws(() => Marshal.GetObjectsForNativeVariants(ptr, 2)); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + } + + [Fact] + public void GetObjectsForNativeVariants_T_ThrowsNotSupportedException() + { + IntPtr ptr = Marshal.AllocHGlobal(2 * Marshal.SizeOf()); + try + { + Assert.Throws(() => Marshal.GetObjectsForNativeVariants(ptr, 2)); + } + finally + { + Marshal.FreeHGlobal(ptr); + } + } + + [Fact] + public void BindToMoniker_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.BindToMoniker("test")); + } + + [Fact] + public void GetIUnknownForObject_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetIUnknownForObject(new object())); + } + + [Fact] + public void GetIDispatchForObject_ThrowsNotSupportedException() + { + Assert.Throws(() => Marshal.GetIDispatchForObject(new object())); + } + + public struct StructForIUnknown{} + + [Fact] + public void GetObjectForIUnknown_ThrowsNotSupportedException() + { + StructForIUnknown test = new StructForIUnknown(); + IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf()); + try + { + Marshal.StructureToPtr(test, ptr, fDeleteOld: false); + Assert.Throws(() => Marshal.GetObjectForIUnknown(ptr)); + } + finally + { + Marshal.DestroyStructure(ptr); + Marshal.FreeHGlobal(ptr); + } + } + } +}