diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index f8ca9962d209eb..3087a28edc69d2 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1138,12 +1138,15 @@ class MethodTable { LIMITED_METHOD_DAC_CONTRACT; - // All ComObjects except for __ComObject - // have dynamic Interface maps - return GetNumInterfaces() > 0 - && IsComObjectType() - && !ParentEquals(g_pObjectClass) - && this != g_pBaseCOMObject; + // All ComObjects except for __ComObject have dynamic Interface maps + // to avoid costly QIs on required managed interfaces. The __ComObject + // type is inserted automatically when a COM object enters the runtime. + // For example, an incoming COM interface pointer or activation via a + // COM coclass. See ComObject::SupportsInterface() for relevant use of + // the dynamic interface map. + return IsComObjectType() + && GetNumInterfaces() > g_pBaseCOMObject->GetNumInterfaces() + && !ParentEquals(g_pObjectClass); } #endif // FEATURE_COMINTEROP diff --git a/src/tests/Interop/COM/NETClients/MiscTypes/Program.cs b/src/tests/Interop/COM/NETClients/MiscTypes/Program.cs index f01ddd3cfdad24..597e155a50bc1e 100644 --- a/src/tests/Interop/COM/NETClients/MiscTypes/Program.cs +++ b/src/tests/Interop/COM/NETClients/MiscTypes/Program.cs @@ -79,7 +79,7 @@ public static int TestEntryPoint() return 100; } - private class InterfaceImpl : Server.Contract.IInterface2 + private class InterfaceImpl : Server.Contract.IInterface1 { } @@ -214,9 +214,11 @@ private static void ValidationTests() Console.WriteLine("-- Interfaces..."); { + Assert.True(new MiscTypesTestingClass() is Server.Contract.IInterface1); + Assert.True(Activator.CreateInstance(typeof(MiscTypesTestingClass)) is Server.Contract.IInterface1); + var interfaceMaybe = miscTypeTesting.Marshal_Interface(new InterfaceImpl()); Assert.True(interfaceMaybe is Server.Contract.IInterface1); - Assert.True(interfaceMaybe is Server.Contract.IInterface2); } } diff --git a/src/tests/Interop/COM/NETServer/MiscTypesTesting.cs b/src/tests/Interop/COM/NETServer/MiscTypesTesting.cs index b9079b31b6c88b..766a768c197ad0 100644 --- a/src/tests/Interop/COM/NETServer/MiscTypesTesting.cs +++ b/src/tests/Interop/COM/NETServer/MiscTypesTesting.cs @@ -46,13 +46,13 @@ void Server.Contract.IMiscTypesTesting.Marshal_ByRefVariant(ref object result, o result = value; } - private class InterfaceImpl : Server.Contract.IInterface2 + private class InterfaceImpl : Server.Contract.IInterface1 { } - Server.Contract.IInterface2 Server.Contract.IMiscTypesTesting.Marshal_Interface(object inst) + Server.Contract.IInterface1 Server.Contract.IMiscTypesTesting.Marshal_Interface(object inst) { - if (inst is not Server.Contract.IInterface2) + if (inst is not Server.Contract.IInterface1) { throw new InvalidCastException(); } diff --git a/src/tests/Interop/COM/NativeClients/MiscTypes/MiscTypes.cpp b/src/tests/Interop/COM/NativeClients/MiscTypes/MiscTypes.cpp index c85df4871c43df..8ea031624f912d 100644 --- a/src/tests/Interop/COM/NativeClients/MiscTypes/MiscTypes.cpp +++ b/src/tests/Interop/COM/NativeClients/MiscTypes/MiscTypes.cpp @@ -91,16 +91,15 @@ struct VariantMarshalTest class InterfaceImpl : public UnknownImpl, - public IInterface2 + public IInterface1 { public: // IInterface1 -public: // IInterface2 public: // IUnknown STDMETHOD(QueryInterface)( /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) { - return DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this)); + return DoQueryInterface(riid, ppvObject, static_cast(this)); } DEFINE_REF_COUNTING(); @@ -354,7 +353,7 @@ void ValidationTests() ComSmartPtr iface; iface.Attach(new InterfaceImpl()); - ComSmartPtr result; + ComSmartPtr result; HRESULT hr = miscTypesTesting->Marshal_Interface(iface, &result); THROW_IF_FAILED(hr); } diff --git a/src/tests/Interop/COM/NativeServer/MiscTypesTesting.h b/src/tests/Interop/COM/NativeServer/MiscTypesTesting.h index b2c71e5082c625..a0b70aaec534fd 100644 --- a/src/tests/Interop/COM/NativeServer/MiscTypesTesting.h +++ b/src/tests/Interop/COM/NativeServer/MiscTypesTesting.h @@ -6,22 +6,22 @@ #include #include "Servers.h" -class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting +class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting, public IInterface1 { - struct InterfaceImpl : public UnknownImpl, public IInterface2 + struct InterfaceImpl : public UnknownImpl, public IInterface1 { public: // IInterface1 - public: // IInterface2 public: // IUnknown STDMETHOD(QueryInterface)( /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) { - return DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this)); + return DoQueryInterface(riid, ppvObject, static_cast(this)); } DEFINE_REF_COUNTING(); }; +public: // IInterface1 public: // IMiscTypesTesting DEF_FUNC(Marshal_Variant)(_In_ VARIANT obj, _Out_ VARIANT* result) { @@ -38,18 +38,18 @@ class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting return E_NOTIMPL; } - DEF_FUNC(Marshal_Interface)(_In_ IUnknown* input, _Outptr_ IInterface2** value) + DEF_FUNC(Marshal_Interface)(_In_ IUnknown* input, _Outptr_ IInterface1** value) { HRESULT hr; - IInterface2* ifaceMaybe = nullptr; - hr = input->QueryInterface(__uuidof(IInterface2), (void**)&ifaceMaybe); + IInterface1* ifaceMaybe = nullptr; + hr = input->QueryInterface(__uuidof(IInterface1), (void**)&ifaceMaybe); if (FAILED(hr)) return hr; (void)ifaceMaybe->Release(); InterfaceImpl* inst = new InterfaceImpl(); - hr = inst->QueryInterface(__uuidof(IInterface2), (void**)value); + hr = inst->QueryInterface(__uuidof(IInterface1), (void**)value); (void)inst->Release(); return hr; } @@ -59,7 +59,7 @@ class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting /* [in] */ REFIID riid, /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) { - return DoQueryInterface(riid, ppvObject, static_cast(this)); + return DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this)); } DEFINE_REF_COUNTING(); diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index a697d0359a2b62..88e4bcc0e4715e 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -184,17 +184,16 @@ string Add_BStr( void Pass_Through_LCID(out int lcid); } - [ComVisible(true)] - [Guid("4242A2F9-995D-4302-A722-02058CF58158")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IInterface1 + // This interface must not be an explicit COM interface to trigger + // the dynamic interface map codepath in ComObject. + public interface Interface0 { } [ComVisible(true)] - [Guid("7AC820FE-E227-4C4D-A8B0-FCA68C459B43")] + [Guid("4242A2F9-995D-4302-A722-02058CF58158")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - public interface IInterface2 : IInterface1 + public interface IInterface1 : Interface0 { } @@ -211,7 +210,7 @@ public interface IMiscTypesTesting void Marshal_ByRefVariant(ref object result, object value); [return: MarshalAs(UnmanagedType.Interface)] - IInterface2 Marshal_Interface([MarshalAs(UnmanagedType.Interface)] object inst); + IInterface1 Marshal_Interface([MarshalAs(UnmanagedType.Interface)] object inst); } public struct HResult diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index 76301fe0ae2b40..61a2c38884a225 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -371,11 +371,6 @@ IInterface1 : IUnknown { }; -struct __declspec(uuid("7AC820FE-E227-4C4D-A8B0-FCA68C459B43")) -IInterface2 : public IInterface1 -{ -}; - struct __declspec(uuid("7FBB8677-BDD0-4E5A-B38B-CA92A4555466")) IMiscTypesTesting : IUnknown { @@ -393,7 +388,7 @@ IMiscTypesTesting : IUnknown virtual HRESULT STDMETHODCALLTYPE Marshal_Interface ( /*[in]*/ IUnknown* value, - /*[out,ret]*/ IInterface2** iface) = 0; + /*[out,ret]*/ IInterface1** iface) = 0; }; struct __declspec(uuid("592386a5-6837-444d-9de3-250815d18556"))