Update error message for when a parent is marked as COMVisible(false) (dotnet/coreclr...
authorAaron Robinson <arobins@microsoft.com>
Thu, 7 Mar 2019 20:19:53 +0000 (12:19 -0800)
committerGitHub <noreply@github.com>
Thu, 7 Mar 2019 20:19:53 +0000 (12:19 -0800)
* Update message to include type and parent type marked as COMVisible(false)

Commit migrated from https://github.com/dotnet/coreclr/commit/8b3c55c36531689c337df37f15eb5a40530fa42f

src/coreclr/src/dlls/mscorrc/mscorrc.rc
src/coreclr/src/vm/comcallablewrapper.cpp
src/coreclr/src/vm/comcallablewrapper.h

index 20612bb..517c548 100644 (file)
@@ -907,7 +907,7 @@ BEGIN
     IDS_CLASSLOAD_CONSTRAINT_MISMATCH_ON_INTERFACE_METHOD_IMPL "Method '%3' on type '%1' from assembly '%2' tried to explicitly implement an interface method with weaker type parameter constraints."
     IDS_CLASSLOAD_EXPLICIT_GENERIC "Could not load type '%1' from assembly '%2' because generic types cannot have explicit layout."
     
-    IDS_EE_COM_INVISIBLE_PARENT "This type has a ComVisible(false) parent in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed."
+    IDS_EE_COM_INVISIBLE_PARENT "Type '%1' has a ComVisible(false) parent '%2' in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed."
 
     IDS_EE_COMIMPORT_METHOD_NO_INTERFACE    "Method '%1' in ComImport class '%2' must implement an interface method."
     IDS_EE_ATTEMPT_TO_CREATE_GENERIC_CCW    "Generic types cannot be marshaled to COM interface pointers."
index 415cfa8..ec05f00 100644 (file)
@@ -5305,7 +5305,16 @@ void ComCallWrapperTemplate::CheckParentComVisibility(BOOL fForIDispatch)
 
     // Throw an exception to report the error.
     if (!CheckParentComVisibilityNoThrow(fForIDispatch))
-        COMPlusThrow(kInvalidOperationException, IDS_EE_COM_INVISIBLE_PARENT);    
+    {
+        ComCallWrapperTemplate *invisParent = FindInvisibleParent();
+        _ASSERTE(invisParent != NULL);
+
+        SString thisType;
+        SString invisParentType;
+        TypeString::AppendType(thisType, m_thClass);
+        TypeString::AppendType(invisParentType, invisParent->m_thClass);
+        COMPlusThrow(kInvalidOperationException, IDS_EE_COM_INVISIBLE_PARENT, thisType.GetUnicode(), invisParentType.GetUnicode());
+    }
 }
 
 BOOL ComCallWrapperTemplate::CheckParentComVisibilityNoThrow(BOOL fForIDispatch)
@@ -6173,20 +6182,36 @@ void ComCallWrapperTemplate::DetermineComVisibility()
 
     m_flags &= (~enum_InvisibleParent);
 
-    // If there are no parents...leave it as false.
     if (m_pParent == NULL)
         return;
 
-    // If our parent has an invisible parent
-    if (m_pParent->HasInvisibleParent())
+    // Check if the parent has an invisible parent
+    // or if the parent itself is invisible.
+    if (m_pParent->HasInvisibleParent()
+        || !IsTypeVisibleFromCom(m_pParent->m_thClass))
     {
+        _ASSERTE(NULL != FindInvisibleParent());
         m_flags |= enum_InvisibleParent;
     }
-    // If our parent is invisible
-    else if (!IsTypeVisibleFromCom(m_pParent->m_thClass))
+}
+
+ComCallWrapperTemplate* ComCallWrapperTemplate::FindInvisibleParent()
+{
+    ComCallWrapperTemplate* invisParentMaybe = m_pParent;
+
+    // Walk up the CCW parent classes and try to find
+    // if one is invisible to COM.
+    while (invisParentMaybe != NULL)
     {
-        m_flags |= enum_InvisibleParent;
+        // If our parent is invisible, return it.
+        if (!IsTypeVisibleFromCom(invisParentMaybe->m_thClass))
+            return invisParentMaybe;
+
+        invisParentMaybe = invisParentMaybe->m_pParent;
     }
+
+    // All classes in hierarchy are COM visible
+    return NULL;
 }
 
 //--------------------------------------------------------------------------
index a8cce3d..11c0574 100644 (file)
@@ -449,7 +449,8 @@ private:
     ComMethodTable* CreateComMethodTableForBasic(MethodTable* pClassMT);
     ComMethodTable* CreateComMethodTableForDelegate(MethodTable *pDelegateMT);
 
-    void            DetermineComVisibility();
+    void DetermineComVisibility();
+    ComCallWrapperTemplate* FindInvisibleParent();
 
 private:
     LONG                                    m_cbRefCount;