From b364ef6c7872d90d75063570f25495286b87acfd Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Tue, 12 Mar 2019 20:34:45 -0700 Subject: Default Interface COM testing project (#23195) * Add tests for native COM client consuming managed COM server that consumes interfaces with default implementation. --- tests/issues.targets | 3 + tests/src/Interop/CMakeLists.txt | 1 + .../COM/NETServer/NETServer.DefaultInterfaces.il | 121 +++++++++++++++++++++ .../NETServer/NETServer.DefaultInterfaces.ilproj | 18 +++ .../COM/NativeClients/DefaultInterfaces.csproj | 23 ++++ .../NativeClients/DefaultInterfaces/App.manifest | 17 +++ .../NativeClients/DefaultInterfaces/CMakeLists.txt | 19 ++++ .../DefaultInterfaces/CoreShim.X.manifest | 16 +++ .../DefaultInterfaces/DefaultInterfacesTests.cpp | 83 ++++++++++++++ .../COM/NativeClients/Primitives/ClientTests.h | 52 --------- tests/src/Interop/COM/NativeServer/Servers.h | 56 ++++++++++ .../Interop/COM/ServerContracts/NativeServers.cs | 22 ++++ .../Interop/COM/ServerContracts/Server.Contracts.h | 57 +++------- .../src/Interop/COM/ServerContracts/ServerGuids.cs | 1 + 14 files changed, 396 insertions(+), 93 deletions(-) create mode 100644 tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il create mode 100644 tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.ilproj create mode 100644 tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj create mode 100644 tests/src/Interop/COM/NativeClients/DefaultInterfaces/App.manifest create mode 100644 tests/src/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt create mode 100644 tests/src/Interop/COM/NativeClients/DefaultInterfaces/CoreShim.X.manifest create mode 100644 tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp diff --git a/tests/issues.targets b/tests/issues.targets index eb34df3ca6..56b9dc4a7c 100644 --- a/tests/issues.targets +++ b/tests/issues.targets @@ -330,6 +330,9 @@ 20682 + + 20682 + 20682 diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index 66124deb93..b4dec5750d 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -82,6 +82,7 @@ if(WIN32) add_subdirectory(COM/NativeServer) add_subdirectory(COM/NativeClients/Primitives) add_subdirectory(COM/NativeClients/Licensing) + add_subdirectory(COM/NativeClients/DefaultInterfaces) add_subdirectory(IJW/FakeMscoree) # IJW isn't supported on ARM64 diff --git a/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il new file mode 100644 index 0000000000..3e4180c7b7 --- /dev/null +++ b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.il @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.assembly extern System.Runtime { } +.assembly extern System.Runtime.InteropServices { } + +.assembly NETServer.DefaultInterfaces { } + +// Interface used for defining a method on an interface +.class interface public abstract auto ansi Server.Contract.IDefaultInterfaceTesting +{ + .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = + ( 01 00 01 00 00 ) + // GUID: FB6DF997-4CEF-4DF7-ADBD-E7FA395A7E0C + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = + ( 01 00 24 46 42 36 44 46 39 39 37 2D 34 43 45 46 + 2D 34 44 46 37 2D 41 44 42 44 2D 45 37 46 41 33 + 39 35 41 37 45 30 43 00 00 ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ComInterfaceType) = + ( 01 00 01 00 00 00 00 00 ) + + .method public virtual + instance int32 DefOnInterfaceRet2() cil managed + { + // Default interface implementation + ldc.i4 2 + ret + } + + .method public hidebysig + instance void DefOnInterfaceNonVirtual() cil managed + { + // Non-virtual interface instance method + ret + } + + .method public hidebysig + static void DefOnInterfaceStatic() cil managed + { + // Static interface method + ret + } + + .method public abstract virtual + instance int32 DefOnClassRet3() cil managed + { + // Simple interface method + } + + .method public hidebysig + static void DefOnInterfaceStatic2() cil managed + { + // Static interface method + ret + } + + .method public hidebysig + instance void DefOnInterfaceNonVirtual2() cil managed + { + // Non-virtual interface instance method + ret + } + + .method public abstract virtual + instance int32 DefOnInterface2Ret5() cil managed + { + // Simple interface method + } +} + +// Interface defintion for overriding another interface's implementation +.class interface private abstract auto ansi Server.Contract.IDefaultInterfaceTesting2 + implements Server.Contract.IDefaultInterfaceTesting +{ + .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = + ( 01 00 01 00 00 ) + // GUID: 9B3CE792-F063-427D-B48E-4354094BF7A0 + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = + ( 01 00 24 39 42 33 43 45 37 39 32 2D 46 30 36 33 + 2D 34 32 37 44 2D 42 34 38 45 2D 34 33 35 34 30 + 39 34 42 46 37 41 30 00 00 ) + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.InterfaceTypeAttribute::.ctor(valuetype [System.Runtime.InteropServices]System.Runtime.InteropServices.ComInterfaceType) = + ( 01 00 01 00 00 00 00 00 ) + + .method public virtual final + instance int32 DefOnInterface2Ret5() cil managed + { + .override Server.Contract.IDefaultInterfaceTesting::DefOnInterface2Ret5 + ldc.i4 5 + ret + } +} + +// COM server consuming interfaces with default methods +.class public auto ansi beforefieldinit DefaultInterfaceTesting + extends [System.Runtime]System.Object + implements Server.Contract.IDefaultInterfaceTesting2 +{ + .custom instance void [System.Runtime]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 01 00 00 ) + // GUID: FAEF42AE-C1A4-419F-A912-B768AC2679EA + .custom instance void [System.Runtime.InteropServices]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = + ( 01 00 24 46 41 45 46 34 32 41 45 2D 43 31 41 34 + 2D 34 31 39 46 2D 41 39 31 32 2D 42 37 36 38 41 + 43 32 36 37 39 45 41 00 00 ) + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + ldarg.0 + call instance void [System.Runtime]System.Object::.ctor() + ret + } + + .method public hidebysig newslot virtual final + instance int32 DefOnClassRet3() cil managed + { + ldc.i4 3 + ret + } +} diff --git a/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.ilproj b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.ilproj new file mode 100644 index 0000000000..e68c1f64fb --- /dev/null +++ b/tests/src/Interop/COM/NETServer/NETServer.DefaultInterfaces.ilproj @@ -0,0 +1,18 @@ + + + + + $(MSBuildProjectName) + Debug + AnyCPU + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true + library + + + + + + + + diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj b/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj new file mode 100644 index 0000000000..040ec132bf --- /dev/null +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces.csproj @@ -0,0 +1,23 @@ + + + + + + true + true + + true + true + BLOCK_WINDOWS_NANO + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/App.manifest b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/App.manifest new file mode 100644 index 0000000000..43e14712a2 --- /dev/null +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/App.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt new file mode 100644 index 0000000000..e1448218f0 --- /dev/null +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required (VERSION 2.6) + +project (COMClientDefaultInterfaces) +include_directories( ${INC_PLATFORM_DIR} ) +include_directories( "../../ServerContracts" ) +include_directories( "../../NativeServer" ) +set(SOURCES + DefaultInterfacesTests.cpp + App.manifest) + +# add the executable +add_executable (COMClientDefaultInterfaces ${SOURCES}) +target_link_libraries(COMClientDefaultInterfaces ${LINK_LIBRARIES_ADDITIONAL}) + +# Copy CoreShim manifest to project output +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$/CoreShim.X.manifest INPUT ${CMAKE_CURRENT_SOURCE_DIR}/CoreShim.X.manifest) + +# add the install targets +install (TARGETS COMClientDefaultInterfaces DESTINATION bin) diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CoreShim.X.manifest b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CoreShim.X.manifest new file mode 100644 index 0000000000..ef07fb0354 --- /dev/null +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/CoreShim.X.manifest @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp new file mode 100644 index 0000000000..9d87215049 --- /dev/null +++ b/tests/src/Interop/COM/NativeClients/DefaultInterfaces/DefaultInterfacesTests.cpp @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include +#include +#include + +// COM headers +#include +#include + +#define COM_CLIENT +#include + +#define THROW_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { ::printf("FAILURE: 0x%08x = %s\n", hr, #exp); throw hr; } } +#define THROW_FAIL_IF_FALSE(exp) { if (!(exp)) { ::printf("FALSE: %s\n", #exp); throw E_FAIL; } } + +template +struct ComInit +{ + const HRESULT Result; + + ComInit() + : Result{ ::CoInitializeEx(nullptr, TM) } + { } + + ~ComInit() + { + if (SUCCEEDED(Result)) + ::CoUninitialize(); + } +}; + +using ComMTA = ComInit; + +void CallDefaultInterface(); + +int __cdecl main() +{ + ComMTA init; + if (FAILED(init.Result)) + return -1; + + try + { + CoreShimComActivation csact{ W("NetServer.DefaultInterfaces"), W("DefaultInterfaceTesting") }; + + CallDefaultInterface(); + } + catch (HRESULT hr) + { + ::printf("Test Failure: 0x%08x\n", hr); + return 101; + } + + return 100; +} + +void CallDefaultInterface() +{ + ::printf("Call functions on Default Interface...\n"); + + HRESULT hr; + + ComSmartPtr defInterface; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DefaultInterfaceTesting, nullptr, CLSCTX_INPROC, IID_IDefaultInterfaceTesting, (void**)&defInterface)); + + int i; + + THROW_IF_FAILED(defInterface->DefOnInterfaceRet2(&i)); + THROW_FAIL_IF_FALSE(i == 2); + + THROW_IF_FAILED(defInterface->DefOnClassRet3(&i)); + THROW_FAIL_IF_FALSE(i == 3); + + // + // Overridden default interface defintions do not work + // https://github.com/dotnet/coreclr/issues/15683 + // + //THROW_IF_FAILED(defInterface->DefOnInterface2Ret5(&i)); + //THROW_FAIL_IF_FALSE(i == 5); +} diff --git a/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h b/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h index 00370f2ce2..84733b4c3e 100644 --- a/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h +++ b/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h @@ -12,58 +12,6 @@ #define THROW_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { ::printf("FAILURE: 0x%08x = %s\n", hr, #exp); throw hr; } } #define THROW_FAIL_IF_FALSE(exp) { if (!(exp)) { ::printf("FALSE: %s\n", #exp); throw E_FAIL; } } -template -struct ComSmartPtr -{ - ComSmartPtr() - : p{} - { } - - ComSmartPtr(_In_ const ComSmartPtr &) = delete; - ComSmartPtr(_Inout_ ComSmartPtr &&) = delete; - - ComSmartPtr& operator=(_In_ const ComSmartPtr &) = delete; - ComSmartPtr& operator=(_Inout_ ComSmartPtr &&) = delete; - - ~ComSmartPtr() - { - if (p != nullptr) - p->Release(); - } - - operator T*() - { - return p; - } - - T** operator&() - { - return &p; - } - - T* operator->() - { - return p; - } - - void Attach(_In_opt_ T *t) - { - if (p != nullptr) - p->Release(); - - p = t; - } - - T *Detach() - { - T *tmp = p; - p = nullptr; - return tmp; - } - - T *p; -}; - void Run_NumericTests(); void Run_ArrayTests(); void Run_StringTests(); diff --git a/tests/src/Interop/COM/NativeServer/Servers.h b/tests/src/Interop/COM/NativeServer/Servers.h index 61f16ca13a..2ff3f88ce0 100644 --- a/tests/src/Interop/COM/NativeServer/Servers.h +++ b/tests/src/Interop/COM/NativeServer/Servers.h @@ -19,6 +19,7 @@ class DECLSPEC_UUID("4DBD9B61-E372-499F-84DE-EFC70AA8A009") EventTesting; 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; #define CLSID_NumericTesting __uuidof(NumericTesting) #define CLSID_ArrayTesting __uuidof(ArrayTesting) @@ -29,6 +30,7 @@ class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting; #define CLSID_AggregationTesting __uuidof(AggregationTesting) #define CLSID_ColorTesting __uuidof(ColorTesting) #define CLSID_LicenseTesting __uuidof(LicenseTesting) +#define CLSID_DefaultInterfaceTesting __uuidof(DefaultInterfaceTesting) #define IID_INumericTesting __uuidof(INumericTesting) #define IID_IArrayTesting __uuidof(IArrayTesting) @@ -40,6 +42,8 @@ class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting; #define IID_IAggregationTesting __uuidof(IAggregationTesting) #define IID_IColorTesting __uuidof(IColorTesting) #define IID_ILicenseTesting __uuidof(ILicenseTesting) +#define IID_IDefaultInterfaceTesting __uuidof(IDefaultInterfaceTesting) +#define IID_IDefaultInterfaceTesting2 __uuidof(IDefaultInterfaceTesting2) // Class used for COM activation when using CoreShim struct CoreShimComActivation @@ -64,6 +68,58 @@ private: } }; +template +struct ComSmartPtr +{ + ComSmartPtr() + : p{} + { } + + ComSmartPtr(_In_ const ComSmartPtr &) = delete; + ComSmartPtr(_Inout_ ComSmartPtr &&) = delete; + + ComSmartPtr& operator=(_In_ const ComSmartPtr &) = delete; + ComSmartPtr& operator=(_Inout_ ComSmartPtr &&) = delete; + + ~ComSmartPtr() + { + if (p != nullptr) + p->Release(); + } + + operator T*() + { + return p; + } + + T** operator&() + { + return &p; + } + + T* operator->() + { + return p; + } + + void Attach(_In_opt_ T *t) + { + if (p != nullptr) + p->Release(); + + p = t; + } + + T *Detach() + { + T *tmp = p; + p = nullptr; + return tmp; + } + + T *p; +}; + #ifndef COM_CLIENT #include diff --git a/tests/src/Interop/COM/ServerContracts/NativeServers.cs b/tests/src/Interop/COM/ServerContracts/NativeServers.cs index 0a14e4fdca..724f7e2bcc 100644 --- a/tests/src/Interop/COM/ServerContracts/NativeServers.cs +++ b/tests/src/Interop/COM/ServerContracts/NativeServers.cs @@ -161,6 +161,28 @@ namespace Server.Contract.Servers internal class LicenseTestingClass { } + +/** Implement when main line C# compiler supports default interfaces. + + /// + /// Managed definition of CoClass + /// + [ComImport] + [CoClass(typeof(DefaultInterfaceTestingClass))] + [Guid("FB6DF997-4CEF-4DF7-ADBD-E7FA395A7E0C")] + internal interface DefaultInterfaceTesting : Server.Contract.IDefaultInterfaceTesting + { + } + + /// + /// Managed activation for CoClass + /// + [ComImport] + [Guid(Server.Contract.Guids.DefaultInterfaceTesting)] + internal class DefaultInterfaceTestingClass + { + } +*/ } #pragma warning restore 618 // Must test deprecated features diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h index 1db14e4676..b985cd3547 100644 --- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h +++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h @@ -5,47 +5,6 @@ #include -// -// Forward references and typedefs -// - -struct __declspec(uuid("05655a94-a915-4926-815d-a9ea648baad9")) -/* interface */ INumericTesting; -struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43")) -/* interface */ IArrayTesting; -struct __declspec(uuid("7044c5c0-c6c6-4713-9294-b4a4e86d58cc")) -/* interface */ IStringTesting; -struct __declspec(uuid("592386a5-6837-444d-9de3-250815d18556")) -/* interface */ IErrorMarshalTesting; -struct __declspec(uuid("a5e04c1c-474e-46d2-bbc0-769d04e12b54")) -/* interface */ IDispatchTesting; -struct __declspec(uuid("83AFF8E4-C46A-45DB-9D91-2ADB5164545E")) -/* interface */ IEventTesting; -struct __declspec(uuid("98cc27f0-d521-4f79-8b63-e980e3a92974")) -/* interface */ IAggregationTesting; -struct __declspec(uuid("E6D72BA7-0936-4396-8A69-3B76DA1108DA")) -/* interface */ IColorTesting; -struct __declspec(uuid("6C9E230E-411F-4219-ABFD-E71F2B84FD50")) -/* interface */ ILicenseTesting; - -// -// Smart pointer typedef declarations -// - -_COM_SMARTPTR_TYPEDEF(INumericTesting, __uuidof(INumericTesting)); -_COM_SMARTPTR_TYPEDEF(IArrayTesting, __uuidof(IArrayTesting)); -_COM_SMARTPTR_TYPEDEF(IStringTesting, __uuidof(IStringTesting)); -_COM_SMARTPTR_TYPEDEF(IErrorMarshalTesting, __uuidof(IErrorMarshalTesting)); -_COM_SMARTPTR_TYPEDEF(IDispatchTesting, __uuidof(IDispatchTesting)); -_COM_SMARTPTR_TYPEDEF(IEventTesting, __uuidof(IEventTesting)); -_COM_SMARTPTR_TYPEDEF(IAggregationTesting, __uuidof(IAggregationTesting)); -_COM_SMARTPTR_TYPEDEF(IColorTesting, __uuidof(IColorTesting)); -_COM_SMARTPTR_TYPEDEF(ILicenseTesting, __uuidof(ILicenseTesting)); - -// -// Type library items -// - struct __declspec(uuid("05655a94-a915-4926-815d-a9ea648baad9")) INumericTesting : IUnknown { @@ -499,4 +458,20 @@ ILicenseTesting : IUnknown virtual HRESULT STDMETHODCALLTYPE SetNextLicense(_In_z_ LPCOLESTR lic) = 0; }; +struct __declspec(uuid("FB6DF997-4CEF-4DF7-ADBD-E7FA395A7E0C")) +IDefaultInterfaceTesting : IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE DefOnInterfaceRet2(_Out_ int *p) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefOnClassRet3(_Out_ int *p) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefOnInterface2Ret5(_Out_ int *p) = 0; +}; + +struct __declspec(uuid("9B3CE792-F063-427D-B48E-4354094BF7A0")) +IDefaultInterfaceTesting2 : IDefaultInterfaceTesting +{ + +}; + #pragma pack(pop) diff --git a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs index 2ebeed8840..98ed0aed85 100644 --- a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs +++ b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs @@ -18,5 +18,6 @@ namespace Server.Contract public const string AggregationTesting = "4CEFE36D-F377-4B6E-8C34-819A8BB9CB04"; public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65"; public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535"; + public const string DefaultInterfaceTesting = "FAEF42AE-C1A4-419F-A912-B768AC2679EA"; } } -- cgit v1.2.3