Fix RuntimeTypeHandle.IsComObject check for __ComObject type (#57171)
authorElinor Fung <elfung@microsoft.com>
Wed, 11 Aug 2021 16:25:18 +0000 (09:25 -0700)
committerGitHub <noreply@github.com>
Wed, 11 Aug 2021 16:25:18 +0000 (09:25 -0700)
src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs
src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs

index dd17a2f..2fbfd1c 100644 (file)
@@ -463,8 +463,9 @@ namespace System
         internal static bool IsComObject(RuntimeType type, bool isGenericCOM)
         {
 #if FEATURE_COMINTEROP
+            // We need to check the type handle values - not the instances - to determine if the runtime type is a ComObject.
             if (isGenericCOM)
-                return type == typeof(__ComObject);
+                return type.TypeHandle.Value == typeof(__ComObject).TypeHandle.Value;
 
             return RuntimeTypeHandle.CanCastTo(type, (RuntimeType)typeof(__ComObject));
 #else
index 1bade41..76de709 100644 (file)
@@ -29,6 +29,28 @@ namespace NetClient
             Assert.IsTrue(Marshal.IsComObject(test));
         }
 
+        static void Validate_Activation_CreateInstance()
+        {
+            Console.WriteLine($"{nameof(Validate_Activation_CreateInstance)}...");
+
+            Type t = Type.GetTypeFromCLSID(Guid.Parse(Guids.ConsumeNETServerTesting));
+            Assert.IsTrue(t.IsCOMObject);
+
+            object obj = Activator.CreateInstance(t);
+            var test = (CoClass.ConsumeNETServerTesting)obj;
+            test.ReleaseResources();
+            
+            Assert.IsTrue(Marshal.IsComObject(test));
+
+            // Use the overload that takes constructor arguments. This tests the path where the runtime searches for the
+            // constructor to use (which has some special-casing for COM) instead of just always using the default.
+            obj = Activator.CreateInstance(t, Array.Empty<object>());
+            test = (CoClass.ConsumeNETServerTesting)obj;
+            test.ReleaseResources();
+
+            Assert.IsTrue(Marshal.IsComObject(test));
+        }
+
         static void Validate_CCW_Wasnt_Unwrapped()
         {
             Console.WriteLine($"{nameof(Validate_CCW_Wasnt_Unwrapped)}...");
@@ -102,6 +124,7 @@ namespace NetClient
                     string.Empty))
                 {
                     Validate_Activation();
+                    Validate_Activation_CreateInstance();
                     Validate_CCW_Wasnt_Unwrapped();
                     Validate_Client_CCW_RCW();
                     Validate_Server_CCW_RCW();