Fail COM CoClass creation during construction instead of during jitting (#54508)
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Tue, 22 Jun 2021 16:32:53 +0000 (09:32 -0700)
committerGitHub <noreply@github.com>
Tue, 22 Jun 2021 16:32:53 +0000 (09:32 -0700)
src/coreclr/vm/ecall.cpp
src/coreclr/vm/ecall.h
src/coreclr/vm/gchelpers.cpp
src/tests/Interop/COM/NETClients/ComDisabled/Program.cs
src/tests/issues.targets

index 9745562..c6d1b6d 100644 (file)
@@ -434,12 +434,6 @@ PCODE ECall::GetFCallImpl(MethodDesc * pMD, BOOL * pfSharedOrDynamicFCallImpl /*
 #endif // FEATURE_COMINTEROP
     )
     {
-#ifdef FEATURE_COMINTEROP
-        if (g_pBaseCOMObject == NULL)
-        {
-            COMPlusThrow(kPlatformNotSupportedException, IDS_EE_ERROR_COM);
-        }
-
         if (pfSharedOrDynamicFCallImpl)
             *pfSharedOrDynamicFCallImpl = TRUE;
 
@@ -448,9 +442,6 @@ PCODE ECall::GetFCallImpl(MethodDesc * pMD, BOOL * pfSharedOrDynamicFCallImpl /*
 
         // FCComCtor does not need to be in the fcall hashtable since it does not erect frame.
         return GetEEFuncEntryPoint(FCComCtor);
-#else
-        COMPlusThrow(kPlatformNotSupportedException, IDS_EE_ERROR_COM);
-#endif // FEATURE_COMINTEROP
     }
 
     if (!pMD->GetModule()->IsSystem())
@@ -571,9 +562,7 @@ BOOL ECall::IsSharedFCallImpl(PCODE pImpl)
     PCODE pNativeCode = pImpl;
 
     return
-#ifdef FEATURE_COMINTEROP
         (pNativeCode == GetEEFuncEntryPoint(FCComCtor)) ||
-#endif
         (pNativeCode == GetEEFuncEntryPoint(COMDelegate::DelegateConstruct));
 }
 
@@ -619,7 +608,12 @@ BOOL ECall::CheckUnusedECalls(SetSHash<DWORD>& usedIDs)
 }
 
 
-#if defined(FEATURE_COMINTEROP) && !defined(CROSSGEN_COMPILE)
+#if !defined(CROSSGEN_COMPILE)
+// This function is a stub implementation for the constructor of a ComImport class.
+// The actual work to implement COM Activation (and built-in COM support checks) is done as part
+// of the implementation of object allocation. As a result, the constructor itself has no extra
+// work to do once the object has been allocated. As a result, we just provide a dummy implementation
+// here since a constructor has to have an implementation.
 FCIMPL1(VOID, FCComCtor, LPVOID pV)
 {
     FCALL_CONTRACT;
@@ -627,7 +621,7 @@ FCIMPL1(VOID, FCComCtor, LPVOID pV)
     FCUnique(0x34);
 }
 FCIMPLEND
-#endif // FEATURE_COMINTEROP && !CROSSGEN_COMPILE
+#endif // !CROSSGEN_COMPILE
 
 
 
index 387bbc2..9b946ad 100644 (file)
@@ -134,8 +134,6 @@ class ECall
         static LPVOID GetQCallImpl(MethodDesc * pMD);
 };
 
-#ifdef FEATURE_COMINTEROP
 extern "C" FCDECL1(VOID, FCComCtor, LPVOID pV);
-#endif
 
 #endif // _ECALL_H_
index 74412a9..0cecfc6 100644 (file)
@@ -930,15 +930,25 @@ OBJECTREF AllocateObject(MethodTable *pMT
 #ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
     if (fHandleCom && pMT->IsComObjectType())
     {
+        if (!g_pConfig->IsBuiltInCOMSupported())
+        {
+            COMPlusThrow(kNotSupportedException, W("NotSupported_COM"));
+        }
+
         // Create a instance of __ComObject here is not allowed as we don't know what COM object to create
         if (pMT == g_pBaseCOMObject)
             COMPlusThrow(kInvalidComObjectException, IDS_EE_NO_BACKING_CLASS_FACTORY);
 
         oref = OBJECTREF_TO_UNCHECKED_OBJECTREF(AllocateComObject_ForManaged(pMT));
     }
-    else
 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+#else  // FEATURE_COMINTEROP
+    if (pMT->IsComObjectType())
+    {
+        COMPlusThrow(kPlatformNotSupportedException, IDS_EE_ERROR_COM);
+    }
 #endif // FEATURE_COMINTEROP
+    else
     {
         GC_ALLOC_FLAGS flags = GC_ALLOC_NO_FLAGS;
         if (pMT->ContainsPointers())
index d7f6a83..8f25b3d 100644 (file)
@@ -20,22 +20,18 @@ namespace NetClient
 
             try
             {
-                ActivateServer();
+                var server = (Server.Contract.Servers.NumericTesting)new Server.Contract.Servers.NumericTestingClass();
             }
-            catch (PlatformNotSupportedException ex)
+            catch (NotSupportedException) when (OperatingSystem.IsWindows())
+            {
+                return 100;
+            }
+            catch (PlatformNotSupportedException) when (!OperatingSystem.IsWindows())
             {
                 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();
-        }
     }
 }
index 25b94c7..1daa9fd 100644 (file)
         <ExcludeList Include="$(XunitTestBinBase)/tracing/eventpipe/eventsvalidation/ThreadPool/*">
             <Issue>https://github.com/dotnet/runtime/issues/48727</Issue>
         </ExcludeList>
-        <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/ComDisabled/NETClientComDisabled/*">
-            <Issue>https://github.com/dotnet/runtime/issues/54379</Issue>
-        </ExcludeList>
         <ExcludeList Include="$(XunitTestBinBase)/Interop/LayoutClass/LayoutClassTest/*">
             <Issue>https://github.com/dotnet/runtime/issues/54316</Issue>
         </ExcludeList>