From d8c2e84e37a6a36956e3235754305b328c56c1d2 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 31 Aug 2020 14:48:33 -0700 Subject: [PATCH 1/4] Add IInspectable test. --- .../COM/NETClients/IInspectable/App.manifest | 18 +++++++ .../IInspectable/NETClientIInspectable.csproj | 22 ++++++++ .../COM/NETClients/IInspectable/Program.cs | 44 ++++++++++++++++ .../NativeServer/COMNativeServer.X.manifest | 5 ++ .../COM/NativeServer/InspectableTesting.h | 51 +++++++++++++++++++ .../Interop/COM/NativeServer/Servers.cpp | 5 ++ src/tests/Interop/COM/NativeServer/Servers.h | 5 ++ .../COM/ServerContracts/Server.CoClasses.cs | 13 +++++ .../COM/ServerContracts/Server.Contracts.cs | 16 ++++++ .../COM/ServerContracts/Server.Contracts.h | 12 +++++ .../COM/ServerContracts/ServerGuids.cs | 1 + 11 files changed, 192 insertions(+) create mode 100644 src/tests/Interop/COM/NETClients/IInspectable/App.manifest create mode 100644 src/tests/Interop/COM/NETClients/IInspectable/NETClientIInspectable.csproj create mode 100644 src/tests/Interop/COM/NETClients/IInspectable/Program.cs create mode 100644 src/tests/Interop/COM/NativeServer/InspectableTesting.h diff --git a/src/tests/Interop/COM/NETClients/IInspectable/App.manifest b/src/tests/Interop/COM/NETClients/IInspectable/App.manifest new file mode 100644 index 0000000000000..ca47bbbaad0d0 --- /dev/null +++ b/src/tests/Interop/COM/NETClients/IInspectable/App.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/src/tests/Interop/COM/NETClients/IInspectable/NETClientIInspectable.csproj b/src/tests/Interop/COM/NETClients/IInspectable/NETClientIInspectable.csproj new file mode 100644 index 0000000000000..acebae53a3c0f --- /dev/null +++ b/src/tests/Interop/COM/NETClients/IInspectable/NETClientIInspectable.csproj @@ -0,0 +1,22 @@ + + + Exe + App.manifest + + true + + true + + true + + + + + + + + + + + + diff --git a/src/tests/Interop/COM/NETClients/IInspectable/Program.cs b/src/tests/Interop/COM/NETClients/IInspectable/Program.cs new file mode 100644 index 0000000000000..5cea072c0c842 --- /dev/null +++ b/src/tests/Interop/COM/NETClients/IInspectable/Program.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace NetClient +{ + using System; + using System.Globalization; + using System.Reflection; + using System.Runtime.InteropServices; + + using TestLibrary; + using Server.Contract; + using Server.Contract.Servers; + + class Program + { + static void Validate_IInspectable() + { + var server = (InspectableTesting)new InspectableTestingClass(); + Assert.Throws(() => _ = (IInspectableTesting2)server); + } + + static int Main(string[] doNotUse) + { + // RegFree COM is not supported on Windows Nano + if (Utilities.IsWindowsNanoServer) + { + return 100; + } + + try + { + Validate_IInspectable(); + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + } +} diff --git a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest index 3c67514b47ecb..b70ce1ae8b560 100644 --- a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest +++ b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest @@ -51,6 +51,11 @@ + + + diff --git a/src/tests/Interop/COM/NativeServer/InspectableTesting.h b/src/tests/Interop/COM/NativeServer/InspectableTesting.h new file mode 100644 index 0000000000000..eb157048e154f --- /dev/null +++ b/src/tests/Interop/COM/NativeServer/InspectableTesting.h @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include "Servers.h" + +class InspectableTesting : public UnknownImpl, public IInspectableTesting, public IInspectableTesting2 +{ +public: // IInspectableTesting2 + DEF_FUNC(Add)( + /*[in]*/ int a, + /*[in]*/ int b, + /*[out] [retval] */ int* retVal) + { + *retVal = a + b; + return S_OK; + } + +public: // IInspectable + STDMETHOD(GetIids)( + /* [out] */ ULONG *iidCount, + /* [size_is][size_is][out] */ IID **iids) + { + return E_NOTIMPL; + } + + STDMETHOD(GetRuntimeClassName)( + /* [out] */ HSTRING *className) + { + className = nullptr; + return S_OK; + } + + STDMETHOD(GetTrustLevel)( + /* [out] */ TrustLevel *trustLevel) + { + *trustLevel = TrustLevel::FullTrust; + return S_OK; + } + +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), static_cast(this)); + } + + DEFINE_REF_COUNTING(); +}; diff --git a/src/tests/Interop/COM/NativeServer/Servers.cpp b/src/tests/Interop/COM/NativeServer/Servers.cpp index e433495e2c8b3..67824898a0302 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -167,6 +167,7 @@ STDAPI DllRegisterServer(void) RETURN_IF_FAILED(RegisterClsid(__uuidof(EventTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(AggregationTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(ColorTesting), L"Both")); + RETURN_IF_FAILED(RegisterClsid(__uuidof(InspectableTesting), L"Both")); return S_OK; } @@ -183,6 +184,7 @@ STDAPI DllUnregisterServer(void) RETURN_IF_FAILED(RemoveClsid(__uuidof(EventTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(AggregationTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(ColorTesting))); + RETURN_IF_FAILED(RemoveClsid(__uuidof(InspectableTesting))); return S_OK; } @@ -216,5 +218,8 @@ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FA if (rclsid == __uuidof(LicenseTesting)) return ClassFactoryLicense::Create(riid, ppv); + if (rclsid == __uuidof(InspectableTesting)) + return ClassFactoryBasic::Create(riid, ppv); + return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/src/tests/Interop/COM/NativeServer/Servers.h b/src/tests/Interop/COM/NativeServer/Servers.h index a0c53c336de45..6bf472c0314e9 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.h +++ b/src/tests/Interop/COM/NativeServer/Servers.h @@ -19,6 +19,7 @@ class DECLSPEC_UUID("4CEFE36D-F377-4B6E-8C34-819A8BB9CB04") AggregationTesting; class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting; class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting; class DECLSPEC_UUID("FAEF42AE-C1A4-419F-A912-B768AC2679EA") DefaultInterfaceTesting; +class DECLSPEC_UUID("CE137261-6F19-44F5-A449-EF963B3F987E") InspectableTesting; #define CLSID_NumericTesting __uuidof(NumericTesting) #define CLSID_ArrayTesting __uuidof(ArrayTesting) @@ -30,6 +31,7 @@ class DECLSPEC_UUID("FAEF42AE-C1A4-419F-A912-B768AC2679EA") DefaultInterfaceTest #define CLSID_ColorTesting __uuidof(ColorTesting) #define CLSID_LicenseTesting __uuidof(LicenseTesting) #define CLSID_DefaultInterfaceTesting __uuidof(DefaultInterfaceTesting) +#define CLSID_InspectableTesting __uidof(InspectableTesting) #define IID_INumericTesting __uuidof(INumericTesting) #define IID_IArrayTesting __uuidof(IArrayTesting) @@ -43,6 +45,8 @@ class DECLSPEC_UUID("FAEF42AE-C1A4-419F-A912-B768AC2679EA") DefaultInterfaceTest #define IID_ILicenseTesting __uuidof(ILicenseTesting) #define IID_IDefaultInterfaceTesting __uuidof(IDefaultInterfaceTesting) #define IID_IDefaultInterfaceTesting2 __uuidof(IDefaultInterfaceTesting2) +#define IID_IInspectableTesting __uuidof(IInspectableTesting) +#define IID_IInspectableTesting2 __uuidof(IInspectableTesting2) // Class used for COM activation when using CoreShim struct CoreShimComActivation @@ -81,4 +85,5 @@ struct CoreShimComActivation #include "AggregationTesting.h" #include "ColorTesting.h" #include "LicenseTesting.h" + #include "InspectableTesting.h" #endif diff --git a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs index 9d3af92727b00..b7b4754fcad34 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -207,6 +207,19 @@ internal interface ConsumeNETServerTesting : Server.Contract.IConsumeNETServer internal class ConsumeNETServerTestingClass { } + + [ComImport] + [CoClass(typeof(InspectableTestingClass))] + [Guid("3021236a-2a9e-4a29-bf14-533842c55262")] + internal interface InspectableTesting : Server.Contract.IInspectableTesting + { + } + + [ComImport] + [Guid(Server.Contract.Guids.InspectableTesting)] + internal class InspectableTestingClass + { + } } #pragma warning restore 618 // Must test deprecated features diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index 2a0de065f4fc7..4f345ec3dda0a 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -324,6 +324,22 @@ public interface IConsumeNETServer bool EqualByCCW(object obj); bool NotEqualByRCW(object obj); } + + [ComVisible(true)] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("3021236a-2a9e-4a29-bf14-533842c55262")] + internal interface IInspectableTesting + { + int Add(int i, int j); + } + + [ComImport] + [InterfaceType(ComInterfaceType.InterfaceIsIInspectable)] + [Guid("e9e1ccf9-8e93-4850-ac1c-a71692cb68c5")] + internal interface IInspectableTesting2 + { + int Add(int i, int j); + } } #pragma warning restore 618 // Must test deprecated features diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index 2e713cae64c18..6411f13bca947 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -4,6 +4,7 @@ #pragma pack(push, 8) #include +#include struct HFA_4 { @@ -486,4 +487,15 @@ IDefaultInterfaceTesting2 : IUnknown // Empty }; +struct __declspec(uuid("3021236a-2a9e-4a29-bf14-533842c55262")) +IInspectableTesting : IUnknown +{ +}; + +struct __declspec(uuid("e9e1ccf9-8e93-4850-ac1c-a71692cb68c5")) +IInspectableTesting2 : IInspectable +{ + virtual HRESULT STDMETHODCALLTYPE Add(_In_ int i, _In_ int j, _Out_ _Ret_ int* retVal) = 0; +}; + #pragma pack(pop) diff --git a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs index 89bd6d85acb66..953b9d4ff4adb 100644 --- a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs +++ b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs @@ -19,5 +19,6 @@ internal sealed class Guids public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; public const string DefaultInterfaceTesting = "FAEF42AE-C1A4-419F-A912-B768AC2679EA"; public const string ConsumeNETServerTesting = "DE4ACF53-5957-4D31-8BE2-EA6C80683246"; + public const string InspectableTesting = "CE137261-6F19-44F5-A449-EF963B3F987E"; } } From b6ab544b6d743d9af1835f172e455375d8dba6b5 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 31 Aug 2020 14:51:51 -0700 Subject: [PATCH 2/4] Add com interface type check during cast. Signed-off-by: Jeremy Koritzinsky --- src/coreclr/src/vm/runtimecallablewrapper.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreclr/src/vm/runtimecallablewrapper.cpp b/src/coreclr/src/vm/runtimecallablewrapper.cpp index 16d7e5e86302b..27ed0b7580974 100644 --- a/src/coreclr/src/vm/runtimecallablewrapper.cpp +++ b/src/coreclr/src/vm/runtimecallablewrapper.cpp @@ -2633,6 +2633,11 @@ BOOL ComObject::SupportsInterface(OBJECTREF oref, MethodTable* pIntfTable) // Make sure the interface method table has been restored. pIntfTable->CheckRestore(); + if (pIntfTable->GetComInterfaceType() == ifInspectable) + { + COMPlusThrow(kPlatformNotSupportedException, IDS_EE_NO_IINSPECTABLE); + } + // Check to see if the static class definition indicates we implement the interface. MethodTable *pMT = oref->GetMethodTable(); if (pMT->CanCastToInterface(pIntfTable)) From 7918a19ab57d223c60ba283148a3d4fb2782e00b Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 31 Aug 2020 15:39:06 -0700 Subject: [PATCH 3/4] Update App.manifest --- src/tests/Interop/COM/NETClients/IInspectable/App.manifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Interop/COM/NETClients/IInspectable/App.manifest b/src/tests/Interop/COM/NETClients/IInspectable/App.manifest index ca47bbbaad0d0..f52f61b1999b0 100644 --- a/src/tests/Interop/COM/NETClients/IInspectable/App.manifest +++ b/src/tests/Interop/COM/NETClients/IInspectable/App.manifest @@ -2,7 +2,7 @@ From 165d3f8d29cc776b0e96101333772307de1bebea Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 1 Sep 2020 09:56:25 -0700 Subject: [PATCH 4/4] Remove extra interface member. --- src/tests/Interop/COM/ServerContracts/Server.Contracts.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index 4f345ec3dda0a..820093fdbcd5e 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -330,7 +330,6 @@ public interface IConsumeNETServer [Guid("3021236a-2a9e-4a29-bf14-533842c55262")] internal interface IInspectableTesting { - int Add(int i, int j); } [ComImport]