From 8b3c55c36531689c337df37f15eb5a40530fa42f Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Thu, 7 Mar 2019 12:19:53 -0800 Subject: [PATCH] Update error message for when a parent is marked as COMVisible(false) (#23092) * Update message to include type and parent type marked as COMVisible(false) --- src/dlls/mscorrc/mscorrc.rc | 2 +- src/vm/comcallablewrapper.cpp | 39 ++++++++++++++++++++++++++++++++------- src/vm/comcallablewrapper.h | 3 ++- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc index 20612bb..517c548 100644 --- a/src/dlls/mscorrc/mscorrc.rc +++ b/src/dlls/mscorrc/mscorrc.rc @@ -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." diff --git a/src/vm/comcallablewrapper.cpp b/src/vm/comcallablewrapper.cpp index 415cfa8..ec05f00 100644 --- a/src/vm/comcallablewrapper.cpp +++ b/src/vm/comcallablewrapper.cpp @@ -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; } //-------------------------------------------------------------------------- diff --git a/src/vm/comcallablewrapper.h b/src/vm/comcallablewrapper.h index a8cce3d..11c0574 100644 --- a/src/vm/comcallablewrapper.h +++ b/src/vm/comcallablewrapper.h @@ -449,7 +449,8 @@ private: ComMethodTable* CreateComMethodTableForBasic(MethodTable* pClassMT); ComMethodTable* CreateComMethodTableForDelegate(MethodTable *pDelegateMT); - void DetermineComVisibility(); + void DetermineComVisibility(); + ComCallWrapperTemplate* FindInvisibleParent(); private: LONG m_cbRefCount; -- 2.7.4