From e16be6db53444977479b246c0dce9f2d00233bda Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Wed, 16 Jun 2021 15:05:54 -0700 Subject: [PATCH] Follow the same failure behavior for [ComImport] classes on Windows with built-in COM disabled as non-Windows. (#54298) --- src/coreclr/vm/ecall.cpp | 7 +++- src/coreclr/vm/methodtablebuilder.cpp | 23 ++++++----- .../COM/NETClients/ComDisabled/App.manifest | 18 ++++++++ .../ComDisabled/NETClientComDisabled.csproj | 19 +++++++++ .../COM/NETClients/ComDisabled/Program.cs | 41 +++++++++++++++++++ 5 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 src/tests/Interop/COM/NETClients/ComDisabled/App.manifest create mode 100644 src/tests/Interop/COM/NETClients/ComDisabled/NETClientComDisabled.csproj create mode 100644 src/tests/Interop/COM/NETClients/ComDisabled/Program.cs diff --git a/src/coreclr/vm/ecall.cpp b/src/coreclr/vm/ecall.cpp index b5a9e17e754..974556232f6 100644 --- a/src/coreclr/vm/ecall.cpp +++ b/src/coreclr/vm/ecall.cpp @@ -430,11 +430,16 @@ PCODE ECall::GetFCallImpl(MethodDesc * pMD, BOOL * pfSharedOrDynamicFCallImpl /* // COM imported classes have special constructors if (pMT->IsComObjectType() #ifdef FEATURE_COMINTEROP - && pMT != g_pBaseCOMObject + && (g_pBaseCOMObject == NULL || pMT != g_pBaseCOMObject) #endif // FEATURE_COMINTEROP ) { #ifdef FEATURE_COMINTEROP + if (g_pBaseCOMObject == NULL) + { + COMPlusThrow(kPlatformNotSupportedException, IDS_EE_ERROR_COM); + } + if (pfSharedOrDynamicFCallImpl) *pfSharedOrDynamicFCallImpl = TRUE; diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 3fff3b61a2d..24dfe4c1240 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1511,7 +1511,7 @@ MethodTableBuilder::BuildMethodTableThrowing( if (IsComImport() && !IsEnum() && !IsInterface() && !IsValueClass() && !IsDelegate()) { #ifdef FEATURE_COMINTEROP - // ComImport classes must either extend from Object + // ComImport classes must extend from Object MethodTable* pMTParent = GetParentMethodTable(); if ((pMTParent == NULL) || (pMTParent != g_pObjectClass)) { @@ -1524,12 +1524,15 @@ MethodTableBuilder::BuildMethodTableThrowing( BuildMethodTableThrowException(IDS_CLASSLOAD_COMIMPCANNOTHAVELAYOUT); } - // We could have had COM interop classes derive from System._ComObject, - // but instead we have them derive from System.Object, have them set the - // ComImport bit in the type attributes, and then we swap out the parent - // type under the covers. - bmtInternal->pType->SetParentType(CreateTypeChain(g_pBaseCOMObject, Substitution())); - bmtInternal->pParentMT = g_pBaseCOMObject; + if (g_pBaseCOMObject != NULL) + { + // We could have had COM interop classes derive from System._ComObject, + // but instead we have them derive from System.Object, have them set the + // ComImport bit in the type attributes, and then we swap out the parent + // type under the covers. + bmtInternal->pType->SetParentType(CreateTypeChain(g_pBaseCOMObject, Substitution())); + bmtInternal->pParentMT = g_pBaseCOMObject; + } #endif // if the current class is imported bmtProp->fIsComObjectType = true; @@ -6307,13 +6310,13 @@ MethodTableBuilder::PlaceMethodImpls() { // The declaration is on the type being built bmtMDMethod * pCurDeclMethod = hDeclMethod.AsMDMethod(); - + mdToken mdef = pCurDeclMethod->GetMethodSignature().GetToken(); if (bmtMethodImpl->IsBody(mdef)) { // A method declared on this class cannot be both a decl and an impl BuildMethodTableThrowException(IDS_CLASSLOAD_MI_MULTIPLEOVERRIDES, mdef); } - + if (IsInterface()) { // Throws @@ -6340,7 +6343,7 @@ MethodTableBuilder::PlaceMethodImpls() else { bmtRTMethod * pCurDeclMethod = hDeclMethod.AsRTMethod(); - + if (IsInterface()) { // Throws diff --git a/src/tests/Interop/COM/NETClients/ComDisabled/App.manifest b/src/tests/Interop/COM/NETClients/ComDisabled/App.manifest new file mode 100644 index 00000000000..6bd83fd63f7 --- /dev/null +++ b/src/tests/Interop/COM/NETClients/ComDisabled/App.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/src/tests/Interop/COM/NETClients/ComDisabled/NETClientComDisabled.csproj b/src/tests/Interop/COM/NETClients/ComDisabled/NETClientComDisabled.csproj new file mode 100644 index 00000000000..fc9a84c0109 --- /dev/null +++ b/src/tests/Interop/COM/NETClients/ComDisabled/NETClientComDisabled.csproj @@ -0,0 +1,19 @@ + + + Exe + App.manifest + + + + + + + + + + + + + + + diff --git a/src/tests/Interop/COM/NETClients/ComDisabled/Program.cs b/src/tests/Interop/COM/NETClients/ComDisabled/Program.cs new file mode 100644 index 00000000000..d7f6a83983a --- /dev/null +++ b/src/tests/Interop/COM/NETClients/ComDisabled/Program.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace NetClient +{ + using System; + using System.Threading; + using System.Runtime.InteropServices; + using System.Runtime.CompilerServices; + + class Program + { + static int Main(string[] doNotUse) + { + // RegFree COM is not supported on Windows Nano + if (TestLibrary.Utilities.IsWindowsNanoServer) + { + return 100; + } + + try + { + ActivateServer(); + } + catch (PlatformNotSupportedException ex) + { + return 100; + } + + return 101; + } + + // Mark as NoInlining to make sure the failure is observed while running Main, + // not while JITing Main and trying to resolve the target of the constructor call. + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ActivateServer() + { + var server = (Server.Contract.Servers.NumericTesting)new Server.Contract.Servers.NumericTestingClass(); + } + } +} -- GitLab