Skip to content

Commit 07f8ebd

Browse files
__ComObject doesn't support dynamic interface map (#112375)
* __ComObject doesn't support dynamic interface map In #105965, an interface was added to __ComObject. This made some previous checks fail as they were written assuming __ComObject didn't have any interfaces.
1 parent bc72823 commit 07f8ebd

File tree

7 files changed

+122
-4
lines changed

7 files changed

+122
-4
lines changed

src/coreclr/vm/methodtable.h

+6-3
Original file line numberDiff line numberDiff line change
@@ -1090,9 +1090,12 @@ class MethodTable
10901090
{
10911091
LIMITED_METHOD_DAC_CONTRACT;
10921092

1093-
// currently all ComObjects except
1094-
// for __ComObject have dynamic Interface maps
1095-
return GetNumInterfaces() > 0 && IsComObjectType() && !ParentEquals(g_pObjectClass);
1093+
// All ComObjects except for __ComObject
1094+
// have dynamic Interface maps
1095+
return GetNumInterfaces() > 0
1096+
&& IsComObjectType()
1097+
&& !ParentEquals(g_pObjectClass)
1098+
&& this != g_pBaseCOMObject;
10961099
}
10971100
#endif // FEATURE_COMINTEROP
10981101

src/tests/Interop/COM/NETClients/MiscTypes/Program.cs

+11
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ public static int TestEntryPoint()
7979
return 100;
8080
}
8181

82+
private class InterfaceImpl : Server.Contract.IInterface2
83+
{
84+
}
85+
8286
private static void ValidationTests()
8387
{
8488
Console.WriteLine($"Running {nameof(ValidationTests)} ...");
@@ -209,6 +213,13 @@ private static void ValidationTests()
209213
var expected = new Guid("{8EFAD956-B33D-46CB-90F4-45F55BA68A96}");
210214
Assert.Equal(expected, miscTypeTesting.Marshal_Variant(expected));
211215
}
216+
217+
Console.WriteLine("-- Interfaces...");
218+
{
219+
var interfaceMaybe = miscTypeTesting.Marshal_Interface(new InterfaceImpl());
220+
Assert.True(interfaceMaybe is Server.Contract.IInterface1);
221+
Assert.True(interfaceMaybe is Server.Contract.IInterface2);
222+
}
212223
}
213224

214225
private static void ValidateNegativeTests()

src/tests/Interop/COM/NETServer/MiscTypesTesting.cs

+14
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,18 @@ void Server.Contract.IMiscTypesTesting.Marshal_ByRefVariant(ref object result, o
4545
{
4646
result = value;
4747
}
48+
49+
private class InterfaceImpl : Server.Contract.IInterface2
50+
{
51+
}
52+
53+
Server.Contract.IInterface2 Server.Contract.IMiscTypesTesting.Marshal_Interface(object inst)
54+
{
55+
if (inst is not Server.Contract.IInterface2)
56+
{
57+
throw new InvalidCastException();
58+
}
59+
60+
return new InterfaceImpl();
61+
}
4862
}

src/tests/Interop/COM/NativeClients/MiscTypes/MiscTypes.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,35 @@ void ValidationTests()
331331
HRESULT hr = miscTypesTesting->Marshal_Variant(args.Input, &args.Result);
332332
THROW_FAIL_IF_FALSE(hr == 0x80131531); // COR_E_INVALIDOLEVARIANTTYPE
333333
}
334+
335+
::printf("-- Interfaces...\n");
336+
{
337+
struct InterfaceImpl : IInterface2
338+
{
339+
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) override
340+
{
341+
if (riid == __uuidof(IInterface1) || riid == __uuidof(IInterface2))
342+
{
343+
*ppvObject = static_cast<IInterface2*>(this);
344+
}
345+
else if (riid == __uuidof(IUnknown))
346+
{
347+
*ppvObject = static_cast<IUnknown*>(this);
348+
}
349+
else
350+
{
351+
*ppvObject = nullptr;
352+
return E_NOINTERFACE;
353+
}
354+
return S_OK;
355+
}
356+
STDMETHOD_(ULONG, AddRef)() override { return 1; }
357+
STDMETHOD_(ULONG, Release)() override { return 1; }
358+
} iface{};
359+
ComSmartPtr<IInterface2> result;
360+
HRESULT hr = miscTypesTesting->Marshal_Interface(&iface, &result);
361+
THROW_IF_FAILED(hr);
362+
}
334363
}
335364

336365
void ValidationByRefTests()

src/tests/Interop/COM/NativeServer/MiscTypesTesting.h

+31-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@
88

99
class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting
1010
{
11+
struct InterfaceImpl : public UnknownImpl, public IInterface2
12+
{
13+
public: // IInterface1
14+
public: // IInterface2
15+
public: // IUnknown
16+
STDMETHOD(QueryInterface)(
17+
/* [in] */ REFIID riid,
18+
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
19+
{
20+
return DoQueryInterface(riid, ppvObject, static_cast<IInterface1 *>(this), static_cast<IInterface2 *>(this));
21+
}
22+
23+
DEFINE_REF_COUNTING();
24+
};
1125
public: // IMiscTypesTesting
1226
DEF_FUNC(Marshal_Variant)(_In_ VARIANT obj, _Out_ VARIANT* result)
1327
{
@@ -24,6 +38,22 @@ class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting
2438
return E_NOTIMPL;
2539
}
2640

41+
DEF_FUNC(Marshal_Interface)(_In_ IUnknown* input, _Outptr_ IInterface2** value)
42+
{
43+
HRESULT hr;
44+
45+
IInterface2* ifaceMaybe = nullptr;
46+
hr = input->QueryInterface(__uuidof(IInterface2), (void**)&ifaceMaybe);
47+
if (FAILED(hr))
48+
return hr;
49+
(void)ifaceMaybe->Release();
50+
51+
InterfaceImpl* inst = new InterfaceImpl();
52+
hr = inst->QueryInterface(__uuidof(IInterface2), (void**)value);
53+
(void)inst->Release();
54+
return hr;
55+
}
56+
2757
public: // IUnknown
2858
STDMETHOD(QueryInterface)(
2959
/* [in] */ REFIID riid,
@@ -33,4 +63,4 @@ class MiscTypesTesting : public UnknownImpl, public IMiscTypesTesting
3363
}
3464

3565
DEFINE_REF_COUNTING();
36-
};
66+
};

src/tests/Interop/COM/ServerContracts/Server.Contracts.cs

+17
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,20 @@ string Add_BStr(
184184
void Pass_Through_LCID(out int lcid);
185185
}
186186

187+
[ComVisible(true)]
188+
[Guid("4242A2F9-995D-4302-A722-02058CF58158")]
189+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
190+
public interface IInterface1
191+
{
192+
}
193+
194+
[ComVisible(true)]
195+
[Guid("7AC820FE-E227-4C4D-A8B0-FCA68C459B43")]
196+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
197+
public interface IInterface2 : IInterface1
198+
{
199+
}
200+
187201
[ComVisible(true)]
188202
[Guid("7FBB8677-BDD0-4E5A-B38B-CA92A4555466")]
189203
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
@@ -195,6 +209,9 @@ public interface IMiscTypesTesting
195209
object Marshal_Instance_Variant([MarshalAs(UnmanagedType.LPWStr)] string init);
196210

197211
void Marshal_ByRefVariant(ref object result, object value);
212+
213+
[return: MarshalAs(UnmanagedType.Interface)]
214+
IInterface2 Marshal_Interface([MarshalAs(UnmanagedType.Interface)] object inst);
198215
}
199216

200217
public struct HResult

src/tests/Interop/COM/ServerContracts/Server.Contracts.h

+14
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,16 @@ IStringTesting : IUnknown
366366
/*[out]*/ LCID* outLcid) = 0;
367367
};
368368

369+
struct __declspec(uuid("4242A2F9-995D-4302-A722-02058CF58158"))
370+
IInterface1 : IUnknown
371+
{
372+
};
373+
374+
struct __declspec(uuid("7AC820FE-E227-4C4D-A8B0-FCA68C459B43"))
375+
IInterface2 : public IInterface1
376+
{
377+
};
378+
369379
struct __declspec(uuid("7FBB8677-BDD0-4E5A-B38B-CA92A4555466"))
370380
IMiscTypesTesting : IUnknown
371381
{
@@ -380,6 +390,10 @@ IMiscTypesTesting : IUnknown
380390
virtual HRESULT STDMETHODCALLTYPE Marshal_ByRefVariant (
381391
/*[inout]*/ VARIANT* result,
382392
/*[in]*/ VARIANT value) = 0;
393+
394+
virtual HRESULT STDMETHODCALLTYPE Marshal_Interface (
395+
/*[in]*/ IUnknown* value,
396+
/*[out,ret]*/ IInterface2** iface) = 0;
383397
};
384398

385399
struct __declspec(uuid("592386a5-6837-444d-9de3-250815d18556"))

0 commit comments

Comments
 (0)