Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions src/coreclr/vm/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2865,11 +2865,6 @@ CorClassIfaceAttr MethodTable::GetComClassInterfaceType()
if (HasGenericClassInstantiationInHierarchy())
return clsIfNone;

// If the class does not support IClassX,
// then it is considered ClassInterfaceType.None unless explicitly overridden by the CA
if (!ClassSupportsIClassX(this))
return clsIfNone;

return ReadClassInterfaceTypeCustomAttribute(TypeHandle(this));
}
#endif // FEATURE_COMINTEROP
Expand Down
124 changes: 35 additions & 89 deletions src/coreclr/vm/comcallablewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2048,48 +2048,8 @@ IUnknown* ComCallWrapper::GetBasicIP(bool inspectionOnly)
}
CONTRACTL_END;

// If the legacy switch is set, we'll always return the IClassX IP
// when QIing for IUnknown or IDispatch.
// Whidbey Tactics has decided to make this opt-in rather than
// opt-out for now. Remove the check for the legacy switch.
if (GetComCallWrapperTemplate()->SupportsIClassX())
return GetIClassXIP(inspectionOnly);

ComCallWrapper *pWrap = this;
IUnknown *pIntf = NULL;

// The IClassX VTable pointer is in the start wrapper.
if (pWrap->IsLinked())
pWrap = ComCallWrapper::GetStartWrapper(pWrap);

ComMethodTable* pIBasicComMT = (ComMethodTable*)pWrap->m_rgpIPtr[Slot_Basic] - 1;
_ASSERTE(pIBasicComMT);

// Lay out the basic COM method table if it has not yet been laid out.
if (!pIBasicComMT->IsLayoutComplete())
{
if (inspectionOnly)
return NULL;
else
pIBasicComMT->LayOutBasicMethodTable();
}

// Return the basic vtable pointer.
pIntf = (IUnknown*)&pWrap->m_rgpIPtr[Slot_Basic];

// If we are not addref'ing the IUnknown (for passive inspection like ETW), return it now.
if (inspectionOnly)
{
return pIntf;
}

// AddRef the wrapper.
// Note that we don't do SafeAddRef(pIntf) because it's overkill to
// go via IUnknown when we already have the wrapper in-hand.
ULONG cbRef = pWrap->AddRefWithAggregationCheck();

// 0xbadF00d implies the AddRef didn't go through
return (cbRef != 0xbadf00d) ? pIntf : NULL;
// We always return the IClassX IP when QIing for IUnknown or IDispatch.
return GetIClassXIP(inspectionOnly);
}

//--------------------------------------------------------------------------
Expand Down Expand Up @@ -2280,23 +2240,20 @@ static IUnknown *GetComIPFromCCW_ForIntfMT_Worker(ComCallWrapper *pWrap, MethodT

// Retrieve the COM method table for the requested interface.
ComCallWrapperTemplate *pIntfCCWTemplate = ComCallWrapperTemplate::GetTemplate(TypeHandle(pIntfMT));
if (pIntfCCWTemplate->SupportsIClassX())
{
ComMethodTable * pIntfComMT = pIntfCCWTemplate->GetClassComMT();
ComMethodTable * pIntfComMT = pIntfCCWTemplate->GetClassComMT();

// If the class that this IClassX's was generated for is marked
// as ClassInterfaceType.AutoDual or AutoDisp,
// then give out the IClassX IP.
if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp)
{
// Make sure the all the base classes of the class this IClassX corresponds to
// are visible to COM.
pIntfComMT->CheckParentComVisibility();
// If the class that this IClassX's was generated for is marked
// as ClassInterfaceType.AutoDual or AutoDisp,
// then give out the IClassX IP.
if (pIntfComMT->GetClassInterfaceType() == clsIfAutoDual || pIntfComMT->GetClassInterfaceType() == clsIfAutoDisp)
{
// Make sure the all the base classes of the class this IClassX corresponds to
// are visible to COM.
pIntfComMT->CheckParentComVisibility();

// Giveout IClassX
IUnknown * pIntf = pWrap->GetIClassXIP();
return GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags);
}
// Giveout IClassX
IUnknown * pIntf = pWrap->GetIClassXIP();
return GetComIPFromCCW_VisibilityCheck(pIntf, pIntfMT, pIntfComMT, flags);
}
}
return NULL;
Expand Down Expand Up @@ -3648,7 +3605,6 @@ ComMethodTable* ComCallWrapperTemplate::GetClassComMT()
THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(SupportsIClassX());
}
CONTRACTL_END;

Expand Down Expand Up @@ -3851,7 +3807,6 @@ ComMethodTable* ComCallWrapperTemplate::CreateComMethodTableForClass(MethodTable
PRECONDITION(CheckPointer(pClassMT));
PRECONDITION(!pClassMT->IsInterface());
PRECONDITION(!pClassMT->GetComPlusParentMethodTable() || pClassMT->GetComPlusParentMethodTable()->GetComCallWrapperTemplate());
PRECONDITION(SupportsIClassX());
}
CONTRACTL_END;

Expand Down Expand Up @@ -4385,12 +4340,6 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas
pTemplate->m_pBasicComMT = pTemplate->CreateComMethodTableForBasic(pMT);
pTemplate->m_pBasicComMT->AddRef();

if (ClassSupportsIClassX(pMT))
{
// we will allow building IClassX for the class
pTemplate->m_flags |= enum_SupportsIClassX;
}

// Eagerly create the interface CMTs.
// when iterate the interfaces implemented by the methodtable, we can check whether
// the interface supports ICustomQueryInterface.
Expand All @@ -4417,36 +4366,33 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas

#ifdef PROFILING_SUPPORTED
// Notify profiler of the CCW, so it can avoid double-counting.
if (pRetTemplate->SupportsIClassX())
{
BEGIN_PROFILER_CALLBACK(CORProfilerTrackCCW());
// When under the profiler, we'll eagerly generate the IClassX CMT.
pRetTemplate->GetClassComMT();
BEGIN_PROFILER_CALLBACK(CORProfilerTrackCCW());
// When under the profiler, we'll eagerly generate the IClassX CMT.
pRetTemplate->GetClassComMT();

IID IClassXIID = GUID_NULL;
SLOT *pComVtable = (SLOT *)(pRetTemplate->m_pClassComMT + 1);
IID IClassXIID = GUID_NULL;
SLOT *pComVtable = (SLOT *)(pRetTemplate->m_pClassComMT + 1);

// If the class is visible from COM, then give out the IClassX IID.
if (pRetTemplate->m_pClassComMT->IsComVisible())
GenerateClassItfGuid(thClass, &IClassXIID);
// If the class is visible from COM, then give out the IClassX IID.
if (pRetTemplate->m_pClassComMT->IsComVisible())
GenerateClassItfGuid(thClass, &IClassXIID);

#if defined(_DEBUG)
CHAR rIID[MINIPAL_GUID_BUFFER_LEN];
minipal_guid_as_string(IClassXIID, rIID, MINIPAL_GUID_BUFFER_LEN);
SString ssName;
thClass.GetName(ssName);
LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated Class:%s, IID:%s, vTbl:%#08x\n",
ssName.GetUTF8(), rIID, pComVtable));
CHAR rIID[MINIPAL_GUID_BUFFER_LEN];
minipal_guid_as_string(IClassXIID, rIID, MINIPAL_GUID_BUFFER_LEN);
SString ssName;
thClass.GetName(ssName);
LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated Class:%s, IID:%s, vTbl:%#08x\n",
ssName.GetUTF8(), rIID, pComVtable));
#else
LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated TypeHandle:%#x, IID:{%08x-...}, vTbl:%#08x\n",
thClass.AsPtr(), IClassXIID.Data1, pComVtable));
LOG((LF_CORPROF, LL_INFO100, "COMClassicVTableCreated TypeHandle:%#x, IID:{%08x-...}, vTbl:%#08x\n",
thClass.AsPtr(), IClassXIID.Data1, pComVtable));
#endif
(&g_profControlBlock)->COMClassicVTableCreated(
(ClassID) thClass.AsPtr(), IClassXIID, pComVtable,
pRetTemplate->m_pClassComMT->m_cbSlots +
ComMethodTable::GetNumExtraSlots(pRetTemplate->m_pClassComMT->GetInterfaceType()));
END_PROFILER_CALLBACK();
}
(&g_profControlBlock)->COMClassicVTableCreated(
(ClassID) thClass.AsPtr(), IClassXIID, pComVtable,
pRetTemplate->m_pClassComMT->m_cbSlots +
ComMethodTable::GetNumExtraSlots(pRetTemplate->m_pClassComMT->GetInterfaceType()));
END_PROFILER_CALLBACK();
#endif // PROFILING_SUPPORTED
return pRetTemplate;
}
Expand Down
8 changes: 1 addition & 7 deletions src/coreclr/vm/comcallablewrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,6 @@ class ComCallWrapperTemplate
return m_flags & enum_ImplementsIMarshal;
}

BOOL SupportsIClassX()
{
LIMITED_METHOD_CONTRACT;
return m_flags & enum_SupportsIClassX;
}

TypeHandle GetClassType()
{
LIMITED_METHOD_CONTRACT;
Expand Down Expand Up @@ -312,7 +306,7 @@ class ComCallWrapperTemplate
enum_InvisibleParent = 0x20,
enum_ImplementsICustomQueryInterface = 0x40,
// enum_Unused = 0x80,
enum_SupportsIClassX = 0x100,
// enum_Unused = 0x100,

enum_RepresentsVariantInterface = 0x400, // this is a template for an interface with variance

Expand Down
35 changes: 7 additions & 28 deletions src/coreclr/vm/interoputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1679,18 +1679,14 @@ BOOL IsIClassX(MethodTable *pMT, REFIID riid, ComMethodTable **ppComMT)
// the IID's of the IClassX's against the specified IID.
while (pMT != NULL)
{
ComCallWrapperTemplate *pTemplate = ComCallWrapperTemplate::GetTemplate(pMT);
if (pTemplate->SupportsIClassX())
{
ComMethodTable *pComMT =
ComCallWrapperTemplate::SetupComMethodTableForClass(pMT, FALSE);
_ASSERTE(pComMT);
ComMethodTable *pComMT =
ComCallWrapperTemplate::SetupComMethodTableForClass(pMT, FALSE);
_ASSERTE(pComMT);

if (IsEqualIID(riid, pComMT->GetIID()))
{
*ppComMT = pComMT;
return TRUE;
}
if (IsEqualIID(riid, pComMT->GetIID()))
{
*ppComMT = pComMT;
return TRUE;
}

pMT = pMT->GetComPlusParentMethodTable();
Expand All @@ -1701,23 +1697,6 @@ BOOL IsIClassX(MethodTable *pMT, REFIID riid, ComMethodTable **ppComMT)



//---------------------------------------------------------------------------
// Returns TRUE if we support IClassX (the auto-generated class interface)
// for the given class.
BOOL ClassSupportsIClassX(MethodTable *pMT)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
MODE_ANY;
}
CONTRACTL_END;

return TRUE;
}



#ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
//---------------------------------------------------------------------------
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/interoputil.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,6 @@ BOOL IsStandardTearOff(IUnknown* pUnk);
// is the iid represent an IClassX for this class
BOOL IsIClassX(MethodTable *pMT, REFIID riid, ComMethodTable **ppComMT);

// Returns TRUE if we support IClassX for the given class.
BOOL ClassSupportsIClassX(MethodTable *pMT);

#ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
//---------------------------------------------------------------------------
// Calls COM class factory and instantiates a new RCW.
Expand Down
18 changes: 6 additions & 12 deletions src/coreclr/vm/stdinterfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,7 @@ ClassInfo_GetClassInfo(IUnknown* pUnk, ITypeInfo** ppTI)
// Find the first COM visible IClassX starting at ComMethodTable passed in and
// walking up the hierarchy.
ComMethodTable *pComMT = NULL;
if (pTemplate->SupportsIClassX())
{
for (pComMT = pTemplate->GetClassComMT(); pComMT && !pComMT->IsComVisible(); pComMT = pComMT->GetParentClassComMT());
}
for (pComMT = pTemplate->GetClassComMT(); pComMT && !pComMT->IsComVisible(); pComMT = pComMT->GetParentClassComMT());

// If the CLR part of the object is not visible then delegate the call to the
// base COM object if it implements IProvideClassInfo.
Expand Down Expand Up @@ -686,14 +683,11 @@ HRESULT GetITypeInfoForEEClass(MethodTable *pClass, ITypeInfo **ppTI, bool bClas
EX_TRY
{
pTemplate = ComCallWrapperTemplate::GetTemplate(pClass);
if (pTemplate->SupportsIClassX())
{
// Find the first COM visible IClassX starting at ComMethodTable passed in and
// walking up the hierarchy.
pComMT = pTemplate->GetClassComMT();
while (pComMT && !pComMT->IsComVisible())
pComMT = pComMT->GetParentClassComMT();
}
// Find the first COM visible IClassX starting at ComMethodTable passed in and
// walking up the hierarchy.
pComMT = pTemplate->GetClassComMT();
while (pComMT && !pComMT->IsComVisible())
pComMT = pComMT->GetParentClassComMT();
}
EX_CATCH
{
Expand Down
Loading