From a225c6f34aa65154e37569d906779a715f6dd1b8 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sun, 5 May 2024 10:22:07 +0800 Subject: [PATCH] Add tests for OAVariantLib (#101841) * Add native return test for basic supported types --------- Co-authored-by: Aaron Robinson --- .../COM/NETClients/IDispatch/Program.cs | 62 ++++ .../COM/NETServer/DispatchCoerceTesting.cs | 39 +++ .../COM/NativeClients/Dispatch/Client.cpp | 110 +++++++ .../Dispatch/CoreShim.X.manifest | 5 + .../NativeServer/COMNativeServer.X.manifest | 5 + .../COM/NativeServer/DispatchCoerceTesting.h | 278 ++++++++++++++++++ .../Interop/COM/NativeServer/Servers.cpp | 5 + src/tests/Interop/COM/NativeServer/Servers.h | 4 + .../COM/ServerContracts/Server.CoClasses.cs | 19 ++ .../COM/ServerContracts/Server.Contracts.cs | 16 + .../COM/ServerContracts/Server.Contracts.h | 6 + .../COM/ServerContracts/ServerGuids.cs | 1 + 12 files changed, 550 insertions(+) create mode 100644 src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs create mode 100644 src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 3de48ae59b794..c57f8c5149f27 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -215,6 +215,67 @@ System.Collections.Generic.IEnumerable GetEnumerable(System.Collections.IEn } } + static void Validate_ValueCoerce_ReturnToManaged() + { + var dispatchCoerceTesting = (DispatchCoerceTesting)new DispatchCoerceTestingClass(); + + Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ..."); + + // Supported types + // See returned values in DispatchCoerceTesting.h + (VarEnum type, int expectedValue)[] supportedTypes = + { + (VarEnum.VT_EMPTY, 0), + (VarEnum.VT_I2, 123), + (VarEnum.VT_I4, 123), + (VarEnum.VT_R4, 1), + (VarEnum.VT_R8, 1), + (VarEnum.VT_CY, 123), + (VarEnum.VT_DATE, 1), + (VarEnum.VT_BSTR, 123), + (VarEnum.VT_ERROR, 123), + (VarEnum.VT_BOOL, -1), + (VarEnum.VT_DECIMAL, 123), + }; + + foreach (var (vt, expected) in supportedTypes) + { + Console.WriteLine($"Converting {vt} to int should be supported."); + int result = dispatchCoerceTesting.ReturnToManaged((short)vt); + Assert.Equal(expected, result); + } + + // Invalid: Rejected before reaching coerce + Console.WriteLine("Invalid variant type should throw InvalidOleVariantTypeException."); + var variantException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(0x7FFF)); + Assert.Equal(unchecked((int)0x80131531), variantException.HResult); + + // Not supported source or destination type: COMException { HResult: 0x80020005 } + + // DISP_E_PARAMNOTFOUND: Converts to Missing + Console.WriteLine("Converting from VT_ERROR with DISP_E_PARAMNOTFOUND should be rejected."); + var comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000)))); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + Console.WriteLine("Converting int to VT_MISSING should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_Missing()); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + Console.WriteLine("Converting int to VT_NULL should be rejected."); + comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged_DBNull()); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + // Rejected by VariantChangeTypeEx + Console.WriteLine("Converting VT_UNKNOWN to int should fail from VariantChangeTypeEx."); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_UNKNOWN)); + Console.WriteLine("Converting VT_NULL to int should fail from VariantChangeTypeEx."); + Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_NULL)); + + // LOCAL_BOOL + Console.WriteLine("VARIANT_BOOL should convert to non-numeric string."); + Assert.Equal("True", dispatchCoerceTesting.BoolToString()); + } + [Fact] public static int TestEntryPoint() { @@ -233,6 +294,7 @@ public static int TestEntryPoint() Validate_StructNotSupported(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ValueCoerce_ReturnToManaged(); } catch (Exception e) { diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs new file mode 100644 index 0000000000000..0367c605df483 --- /dev/null +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; +using Server.Contract; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.DispatchCoerceTesting)] +public class DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting +{ + public int ReturnToManaged(short vt) + { + throw new NotImplementedException(); + } + + public int ManagedArgument(int arg) + { + return arg; + } + + public System.Reflection.Missing ReturnToManaged_Missing() + { + return System.Reflection.Missing.Value; + } + + public DBNull ReturnToManaged_DBNull() + { + return DBNull.Value; + } + + public string BoolToString() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp index 827b8d2287632..4c509a3df1624 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp +++ b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp @@ -11,6 +11,7 @@ void Validate_Float_In_ReturnAndUpdateByRef(); void Validate_Double_In_ReturnAndUpdateByRef(); void Validate_LCID_Marshaled(); void Validate_Enumerator(); +void Validate_ParamCoerce(); template struct ComInit @@ -48,6 +49,7 @@ int __cdecl main() Validate_Double_In_ReturnAndUpdateByRef(); Validate_LCID_Marshaled(); Validate_Enumerator(); + Validate_ParamCoerce(); } catch (HRESULT hr) { @@ -459,3 +461,111 @@ void Validate_Enumerator() ::printf(" -- Validate returned IEnumVARIANT\n"); ValidateReturnedEnumerator(&result); } + +void Validate_ParamCoerce_Type(ComSmartPtr& dispatchCoerceTesting, VARENUM type, int lcid, DISPID methodId) +{ + HRESULT hr; + + DISPPARAMS params; + VARIANTARG arg; + params.cArgs = 1; + params.rgvarg = &arg; + params.cNamedArgs = 0; + params.rgdispidNamedArgs = nullptr; + + VARIANT result; + + V_VT(&arg) = type; + + switch (type) + { + case VT_BSTR: + { + BSTR str = ::SysAllocString(L"123"); + V_BSTR(&arg) = str; + break; + } + case VT_R4: + { + V_R4(&arg) = 1.23f; + break; + } + case VT_DATE: + case VT_R8: + { + V_R8(&arg) = 1.23; + break; + } + case VT_CY: + { + VarCyFromI4(123, &V_CY(&arg)); + break; + } + case VT_DECIMAL: + { + VarDecFromI4(123, &V_DECIMAL(&arg)); + break; + } + default: + { + V_I1(&arg) = 123; + break; + } + } + + THROW_IF_FAILED(dispatchCoerceTesting->Invoke( + methodId, + IID_NULL, + lcid, + DISPATCH_METHOD, + ¶ms, + &result, + nullptr, + nullptr + )); + + THROW_FAIL_IF_FALSE(V_I4(&result) != 0); +} + +void Validate_ParamCoerce() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer"), W("DispatchCoerceTesting") }; + + ComSmartPtr dispatchCoerceTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_DispatchCoerceTesting, nullptr, CLSCTX_INPROC, IID_IDispatchCoerceTesting, (void**)&dispatchCoerceTesting)); + + LPOLESTR numericMethodName = (LPOLESTR)W("ManagedArgument"); + LCID lcid = MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT); + DISPID methodId; + + ::wprintf(W("Invoke %s\n"), numericMethodName); + THROW_IF_FAILED(dispatchCoerceTesting->GetIDsOfNames( + IID_NULL, + &numericMethodName, + 1, + lcid, + &methodId)); + + ::wprintf(W("Validating VT_I2\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I2, lcid, methodId); + ::wprintf(W("Validating VT_I4\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_I4, lcid, methodId); + ::wprintf(W("Validating VT_R4\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R4, lcid, methodId); + ::wprintf(W("Validating VT_R8\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_R8, lcid, methodId); + ::wprintf(W("Validating VT_CY\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_CY, lcid, methodId); + ::wprintf(W("Validating VT_DATE\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DATE, lcid, methodId); + ::wprintf(W("Validating VT_BSTR\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BSTR, lcid, methodId); + ::wprintf(W("Validating VT_ERROR\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_ERROR, lcid, methodId); + ::wprintf(W("Validating VT_BOOL\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_BOOL, lcid, methodId); + ::wprintf(W("Validating VT_DECIMAL\n")); + Validate_ParamCoerce_Type(dispatchCoerceTesting, VT_DECIMAL, lcid, methodId); +} diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest index 0e635e03c3ee0..94105dbcbf72f 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest +++ b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest @@ -11,6 +11,11 @@ + + + diff --git a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest index 9f688bc8e22ba..12ac7bd541cde 100644 --- a/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest +++ b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest @@ -42,6 +42,11 @@ clsid="{4DBD9B61-E372-499F-84DE-EFC70AA8A009}" threadingModel="Both" /> + + + cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I2; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->iVal; + } + + VARENUM resultType = (VARENUM)*args[0]; + VariantInit(pVarResult); + V_VT(pVarResult) = resultType & 0x7FFF; + + switch ((uint16_t)resultType) + { + case VT_BSTR: + { + BSTR str = ::SysAllocString(L"123"); + V_BSTR(pVarResult) = str; + break; + } + case VT_R4: + { + V_R4(pVarResult) = 1.23f; + break; + } + case VT_DATE: + case VT_R8: + { + V_R8(pVarResult) = 1.23; + break; + } + case VT_CY: + { + VarCyFromI4(123, &V_CY(pVarResult)); + break; + } + case VT_DECIMAL: + { + VarDecFromI4(123, &V_DECIMAL(pVarResult)); + break; + } + case ((VT_ERROR | 0x8000)): + { + V_I4(pVarResult) = DISP_E_PARAMNOTFOUND; + break; + } + case VT_UNKNOWN: + { + V_UNKNOWN(pVarResult) = static_cast(this); + break; + } + default: + { + V_I1(pVarResult) = 123; + break; + } + } + + return S_OK; + } + + HRESULT ManagedArgument_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + int *args[1]; + size_t expectedArgCount = 1; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + VARENUM currType; + VARIANTARG *currArg; + size_t argIdx = expectedArgCount - 1; + + // Extract args + { + currType = VT_I4; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->intVal; + } + + V_VT(pVarResult) = VT_I2; + V_I2(pVarResult) = *args[0]; + return S_OK; + } + + HRESULT ReturnToManaged_Missing_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 1234; + return S_OK; + } + + HRESULT ReturnToManaged_DBNull_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 1234; + return S_OK; + } + + HRESULT BoolToString_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + size_t expectedArgCount = 0; + RETURN_IF_FAILED(VerifyValues(uint32_t(expectedArgCount), pDispParams->cArgs)); + + if (pVarResult == nullptr) + return E_POINTER; + + V_VT(pVarResult) = VT_BOOL; + V_BOOL(pVarResult) = VARIANT_TRUE; + 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)); + } + + DEFINE_REF_COUNTING(); +}; + +const WCHAR * const DispatchCoerceTesting::Names[] = +{ + W("__RESERVED__"), + W("ReturnToManaged"), + W("ManagedArgument"), + W("ReturnToManaged_Missing"), + W("ReturnToManaged_DBNull"), + W("BoolToString") +}; + +const int DispatchCoerceTesting::NamesCount = ARRAY_SIZE(DispatchCoerceTesting::Names); diff --git a/src/tests/Interop/COM/NativeServer/Servers.cpp b/src/tests/Interop/COM/NativeServer/Servers.cpp index 05f26be8d4741..ebe4f9df5acde 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -166,6 +166,7 @@ STDAPI DllRegisterServer(void) RETURN_IF_FAILED(RegisterClsid(__uuidof(ErrorMarshalTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchTesting), L"Both")); RETURN_IF_FAILED(RegisterClsid(__uuidof(EventTesting), L"Both")); + RETURN_IF_FAILED(RegisterClsid(__uuidof(DispatchCoerceTesting), 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")); @@ -185,6 +186,7 @@ STDAPI DllUnregisterServer(void) RETURN_IF_FAILED(RemoveClsid(__uuidof(ErrorMarshalTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(EventTesting))); + RETURN_IF_FAILED(RemoveClsid(__uuidof(DispatchCoerceTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(AggregationTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(ColorTesting))); RETURN_IF_FAILED(RemoveClsid(__uuidof(InspectableTesting))); @@ -216,6 +218,9 @@ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FA if (rclsid == __uuidof(EventTesting)) return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(DispatchCoerceTesting)) + return ClassFactoryBasic::Create(riid, ppv); + if (rclsid == __uuidof(AggregationTesting)) return ClassFactoryAggregate::Create(riid, ppv); diff --git a/src/tests/Interop/COM/NativeServer/Servers.h b/src/tests/Interop/COM/NativeServer/Servers.h index c87288d2535b1..44e5070a25a6b 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.h +++ b/src/tests/Interop/COM/NativeServer/Servers.h @@ -16,6 +16,7 @@ class DECLSPEC_UUID("CCFF894B-A27C-45E0-9B30-6C88D722E843") MiscTypesTesting; class DECLSPEC_UUID("71CF5C45-106C-4B32-B418-43A463C6041F") ErrorMarshalTesting; class DECLSPEC_UUID("0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726") DispatchTesting; class DECLSPEC_UUID("4DBD9B61-E372-499F-84DE-EFC70AA8A009") EventTesting; +class DECLSPEC_UUID("661F9962-3477-416B-BE40-4CBA3190A562") DispatchCoerceTesting; 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; @@ -30,6 +31,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define CLSID_ErrorMarshalTesting __uuidof(ErrorMarshalTesting) #define CLSID_DispatchTesting __uuidof(DispatchTesting) #define CLSID_EventTesting __uuidof(EventTesting) +#define CLSID_DispatchCoerceTesting __uuidof(DispatchCoerceTesting) #define CLSID_AggregationTesting __uuidof(AggregationTesting) #define CLSID_ColorTesting __uuidof(ColorTesting) #define CLSID_LicenseTesting __uuidof(LicenseTesting) @@ -45,6 +47,7 @@ class DECLSPEC_UUID("4F54231D-9E11-4C0B-8E0B-2EBD8B0E5811") TrackMyLifetimeTesti #define IID_IDispatchTesting __uuidof(IDispatchTesting) #define IID_TestingEvents __uuidof(TestingEvents) #define IID_IEventTesting __uuidof(IEventTesting) +#define IID_IDispatchCoerceTesting __uuidof(IDispatchCoerceTesting) #define IID_IAggregationTesting __uuidof(IAggregationTesting) #define IID_IColorTesting __uuidof(IColorTesting) #define IID_ILicenseTesting __uuidof(ILicenseTesting) @@ -89,6 +92,7 @@ struct CoreShimComActivation #include "ErrorMarshalTesting.h" #include "DispatchTesting.h" #include "EventTesting.h" + #include "DispatchCoerceTesting.h" #include "AggregationTesting.h" #include "ColorTesting.h" #include "LicenseTesting.h" diff --git a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs index 2479e6cd6f083..f2c44e4cab4b8 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.CoClasses.cs @@ -123,6 +123,25 @@ internal class DispatchTestingClass { } + /// + /// Managed definition of CoClass + /// + [ComImport] + [CoClass(typeof(DispatchCoerceTestingClass))] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + internal interface DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting + { + } + + /// + /// Managed activation for CoClass + /// + [ComImport] + [Guid(Server.Contract.Guids.DispatchCoerceTesting)] + internal class DispatchCoerceTestingClass + { + } + /// /// Managed definition of CoClass /// diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index dd0f71634e2bd..27ee5b3bfc3db 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -319,6 +319,22 @@ public interface TestingEvents void OnEvent([MarshalAs(UnmanagedType.BStr)] string msg); }; + [ComVisible(true)] + [Guid("B630A508-4DA5-4C14-A7AB-618AD66B2EBF")] + [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] + public interface IDispatchCoerceTesting + { + int ReturnToManaged(short vt); + + int ManagedArgument(int arg); + + System.Reflection.Missing ReturnToManaged_Missing(); + + DBNull ReturnToManaged_DBNull(); + + string BoolToString(); + } + [ComVisible(true)] [Guid("98cc27f0-d521-4f79-8b63-e980e3a92974")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h index d2c26884589ef..719659b7ed905 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.h +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.h @@ -452,6 +452,12 @@ TestingEvents : IDispatch // void OnEvent(_In_z_ BSTR t); }; +struct __declspec(uuid("b630a508-4da5-4c14-a7ab-618ad66b2ebf")) +IDispatchCoerceTesting : IDispatch +{ + // Methods should only be invoked via IDispatch +}; + struct __declspec(uuid("98cc27f0-d521-4f79-8b63-e980e3a92974")) IAggregationTesting : IUnknown { diff --git a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs index 8b0c65a3ce153..6c6b6569b634a 100644 --- a/src/tests/Interop/COM/ServerContracts/ServerGuids.cs +++ b/src/tests/Interop/COM/ServerContracts/ServerGuids.cs @@ -15,6 +15,7 @@ internal sealed class Guids public const string ErrorMarshalTesting = "71CF5C45-106C-4B32-B418-43A463C6041F"; public const string DispatchTesting = "0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726"; public const string EventTesting = "4DBD9B61-E372-499F-84DE-EFC70AA8A009"; + public const string DispatchCoerceTesting = "661F9962-3477-416B-BE40-4CBA3190A562"; 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";