From a305404cb92a4921dedb2958983cbd1e5789ac6a Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 10 Apr 2024 18:41:52 +0800 Subject: [PATCH 01/11] Add native return test for basic supported types --- .../COM/NETClients/IDispatch/Program.cs | 30 +++ .../NativeServer/COMNativeServer.X.manifest | 5 + .../COM/NativeServer/DispatchCoerceTesting.h | 218 ++++++++++++++++++ .../Interop/COM/NativeServer/Servers.cpp | 6 + src/tests/Interop/COM/NativeServer/Servers.h | 4 + .../COM/ServerContracts/Server.CoClasses.cs | 19 ++ .../COM/ServerContracts/Server.Contracts.cs | 10 + .../COM/ServerContracts/Server.Contracts.h | 6 + .../COM/ServerContracts/ServerGuids.cs | 1 + 9 files changed, 299 insertions(+) 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 3de48ae59b7944..27441c8a979d96 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -215,6 +215,35 @@ 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 + VarEnum[] supportedTypes = + { + VarEnum.VT_I2, + VarEnum.VT_I4, + VarEnum.VT_R4, + VarEnum.VT_R8, + VarEnum.VT_CY, + VarEnum.VT_DATE, + VarEnum.VT_BSTR, + VarEnum.VT_ERROR, + VarEnum.VT_BOOL, + VarEnum.VT_DECIMAL, + }; + + foreach (VarEnum vt in supportedTypes) + { + Console.WriteLine($"{vt} should be supported."); + int result = dispatchCoerceTesting.ReturnToManaged((short)vt); + Assert.NotEqual(0, result); + } + } + [Fact] public static int TestEntryPoint() { @@ -233,6 +262,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/NativeServer/COMNativeServer.X.manifest b/src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest index 9f688bc8e22bab..12ac7bd541cdeb 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" /> + + + +HRESULT VerifyValues(_In_ const T expected, _In_ const T actual) +{ + return (expected == actual) ? S_OK : E_INVALIDARG; +} + +VARIANTARG *NextArg(_In_ VARIANTARG *args, _Inout_ size_t &currIndex) +{ + return (args + (currIndex--)); +}*/ + +class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting +{ +private: + static const WCHAR * const Names[]; + static const int NamesCount; + +public: // IDispatch + virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( + /* [out] */ __RPC__out uint32_t *pctinfo) + { + *pctinfo = 0; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( + /* [in] */ uint32_t iTInfo, + /* [in] */ LCID lcid, + /* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( + /* [in] */ __RPC__in REFIID, + /* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames, + /* [range][in] */ __RPC__in_range(0,16384) uint32_t cNames, + /* [in] */ LCID, + /* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId) + { + bool containsUnknown = false; + DISPID *curr = rgDispId; + for (uint32_t i = 0; i < cNames; ++i) + { + *curr = DISPID_UNKNOWN; + LPOLESTR name = rgszNames[i]; + for (int j = 1; j < NamesCount; ++j) + { + const WCHAR *nameMaybe = Names[j]; + if (::TP_wcmp_s(name, nameMaybe) == 0) + { + *curr = DISPID{ j }; + break; + } + } + + containsUnknown &= (*curr == DISPID_UNKNOWN); + curr++; + } + + return (containsUnknown) ? DISP_E_UNKNOWNNAME : S_OK; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( + /* [annotation][in] */ _In_ DISPID dispIdMember, + /* [annotation][in] */ _In_ REFIID riid, + /* [annotation][in] */ _In_ LCID lcid, + /* [annotation][in] */ _In_ uint16_t wFlags, + /* [annotation][out][in] */ _In_ DISPPARAMS *pDispParams, + /* [annotation][out] */ _Out_opt_ VARIANT *pVarResult, + /* [annotation][out] */ _Out_opt_ EXCEPINFO *pExcepInfo, + /* [annotation][out] */ _Out_opt_ uint32_t *puArgErr) + { + // + // Note that arguments are received in reverse order for IDispatch::Invoke() + // + + // HRESULT hr; + + switch (dispIdMember) + { + case 1: + { + return ReturnToManaged_Dispatch(pDispParams, pVarResult); + } + case 2: + { + return ManagedArgument_Dispatch(pDispParams, pVarResult); + } + } + + return E_NOTIMPL; + } + +public: // IDispatchCoerceTesting + // Methods should only be invoked via IDispatch + +private: + + HRESULT ReturnToManaged_Dispatch(_In_ DISPPARAMS *pDispParams, _Inout_ VARIANT *pVarResult) + { + HRESULT hr; + + short *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_I2; + currArg = NextArg(pDispParams->rgvarg, argIdx); + RETURN_IF_FAILED(VerifyValues(VARENUM(currType), VARENUM(currArg->vt))); + args[0] = &currArg->iVal; + } + + VARENUM resultType = (VARENUM)*args[0]; + V_VT(pVarResult) = resultType; + + switch (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; + } + 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; + } + +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") +}; + +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 05f26be8d4741d..58041dd51948ce 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -3,6 +3,7 @@ #include "stdafx.h" #include "Servers.h" +#include namespace { @@ -166,6 +167,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 +187,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 +219,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 c87288d2535b1a..44e5070a25a6b2 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 2479e6cd6f083a..f2c44e4cab4b85 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 dd0f71634e2bdc..ade29adbf08e71 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -319,6 +319,16 @@ 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); + } + [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 d2c26884589efa..719659b7ed905e 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 8b0c65a3ce1532..6c6b6569b634a7 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"; From 9f8f79df2b582eb8aea4135a9887eca289eb1e4b Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Wed, 10 Apr 2024 19:57:20 +0800 Subject: [PATCH 02/11] NETServer --- .../COM/NETServer/DispatchCoerceTesting.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs new file mode 100644 index 00000000000000..fc98f0b7abf022 --- /dev/null +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -0,0 +1,24 @@ +// 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) + { + return 42; + } + + public int ManagedArgument(int arg) + { + return arg; + } +} \ No newline at end of file From 9841cc7f688d59316255f2d2baa767fe661f01fe Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 27 Apr 2024 18:02:08 +0800 Subject: [PATCH 03/11] Basic parameter coerce --- .../COM/NativeClients/Dispatch/Client.cpp | 51 +++++++++++++++++++ .../Dispatch/CoreShim.X.manifest | 5 ++ 2 files changed, 56 insertions(+) diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp index 827b8d22876326..441f150ab78f01 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,52 @@ void Validate_Enumerator() ::printf(" -- Validate returned IEnumVARIANT\n"); ValidateReturnedEnumerator(&result); } + +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)); + + { + DISPPARAMS params; + params.cArgs = 1; + params.rgvarg = new VARIANTARG[params.cArgs]; + params.cNamedArgs = 0; + params.rgdispidNamedArgs = nullptr; + + VARIANT result; + + V_VT(¶ms.rgvarg[0]) = VT_I8; + V_I8(¶ms.rgvarg[0]) = 42; + + + THROW_IF_FAILED(dispatchCoerceTesting->Invoke( + methodId, + IID_NULL, + lcid, + DISPATCH_METHOD, + ¶ms, + &result, + nullptr, + nullptr + )); + + THROW_FAIL_IF_FALSE(V_I4(&result) == 42); + } +} diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest b/src/tests/Interop/COM/NativeClients/Dispatch/CoreShim.X.manifest index 0e635e03c3ee0d..94105dbcbf72fb 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 @@ + + + From e9b78e34bdbd09ff71729b17774604bd7c6e7853 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 2 May 2024 22:09:55 +0800 Subject: [PATCH 04/11] Validate managed parameter for supported types --- .../COM/NativeClients/Dispatch/Client.cpp | 111 ++++++++++++++---- 1 file changed, 85 insertions(+), 26 deletions(-) diff --git a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp index 441f150ab78f01..4c509a3df16240 100644 --- a/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp +++ b/src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp @@ -462,6 +462,71 @@ void Validate_Enumerator() 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; @@ -483,30 +548,24 @@ void Validate_ParamCoerce() lcid, &methodId)); - { - DISPPARAMS params; - params.cArgs = 1; - params.rgvarg = new VARIANTARG[params.cArgs]; - params.cNamedArgs = 0; - params.rgdispidNamedArgs = nullptr; - - VARIANT result; - - V_VT(¶ms.rgvarg[0]) = VT_I8; - V_I8(¶ms.rgvarg[0]) = 42; - - - THROW_IF_FAILED(dispatchCoerceTesting->Invoke( - methodId, - IID_NULL, - lcid, - DISPATCH_METHOD, - ¶ms, - &result, - nullptr, - nullptr - )); - - THROW_FAIL_IF_FALSE(V_I4(&result) == 42); - } + ::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); } From 08a961db72331955f23edb1641b1eee645712c6d Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 3 May 2024 14:06:56 +0800 Subject: [PATCH 05/11] Add test for rejected cases --- src/tests/Interop/COM/NETClients/IDispatch/Program.cs | 8 ++++++++ .../Interop/COM/NativeServer/DispatchCoerceTesting.h | 9 +++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 27441c8a979d96..9cef776ffb173d 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -242,6 +242,14 @@ static void Validate_ValueCoerce_ReturnToManaged() int result = dispatchCoerceTesting.ReturnToManaged((short)vt); Assert.NotEqual(0, result); } + + // DISP_E_PARAMNOTFOUND: Converts to Missing, rejected by VariantChangeTypeEx + var comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000)))); + Assert.Equal(unchecked((int)0x80020005), comException.HResult); + + // Invalid: Rejected before reaching coerce + var variantException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(0x7FFF)); + Assert.Equal(unchecked((int)0x80131531), variantException.HResult); } [Fact] diff --git a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h index 3410b82aaf1332..43d124ca96ebf6 100644 --- a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h +++ b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h @@ -128,9 +128,9 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting } VARENUM resultType = (VARENUM)*args[0]; - V_VT(pVarResult) = resultType; + V_VT(pVarResult) = resultType & 0x7FFF; - switch (resultType) + switch ((uint16_t)resultType) { case VT_BSTR: { @@ -159,6 +159,11 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting VarDecFromI4(123, &V_DECIMAL(pVarResult)); break; } + case ((VT_ERROR | 0x8000)): + { + V_I4(pVarResult) = DISP_E_PARAMNOTFOUND; + break; + } default: { V_I1(pVarResult) = 123; From 3a4a467b7182e13022cb27f9993d44c68d7ca6dc Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 3 May 2024 18:39:28 +0800 Subject: [PATCH 06/11] Add detailed expectation messages --- .../COM/NETClients/IDispatch/Program.cs | 28 +++++++++-- .../COM/NETServer/DispatchCoerceTesting.cs | 10 ++++ .../COM/NativeServer/DispatchCoerceTesting.h | 47 ++++++++++++++++++- .../COM/ServerContracts/Server.Contracts.cs | 4 ++ 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 9cef776ffb173d..10daee4dc3321e 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -238,18 +238,36 @@ static void Validate_ValueCoerce_ReturnToManaged() foreach (VarEnum vt in supportedTypes) { - Console.WriteLine($"{vt} should be supported."); + Console.WriteLine($"Converting {vt} to int should be supported."); int result = dispatchCoerceTesting.ReturnToManaged((short)vt); Assert.NotEqual(0, result); } - // DISP_E_PARAMNOTFOUND: Converts to Missing, rejected by VariantChangeTypeEx - var comException = Assert.Throws(() => dispatchCoerceTesting.ReturnToManaged(unchecked((short)((short)VarEnum.VT_ERROR | 0x8000)))); - Assert.Equal(unchecked((int)0x80020005), comException.HResult); - // 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)); } [Fact] diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs index fc98f0b7abf022..713b545bce71ed 100644 --- a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -21,4 +21,14 @@ public int ManagedArgument(int arg) { return arg; } + + public System.Reflection.Missing ReturnToManaged_Missing() + { + return Type.Missing; + } + + public DBNull ReturnToManaged_DBNull() + { + return DBNull.Value; + } } \ No newline at end of file diff --git a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h index 43d124ca96ebf6..27b886eaad47b5 100644 --- a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h +++ b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h @@ -94,6 +94,14 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting { return ManagedArgument_Dispatch(pDispParams, pVarResult); } + case 3: + { + return ReturnToManaged_Missing_Dispatch(pDispParams, pVarResult); + } + case 4: + { + return ReturnToManaged_DBNull_Dispatch(pDispParams, pVarResult); + } } return E_NOTIMPL; @@ -164,6 +172,11 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting V_I4(pVarResult) = DISP_E_PARAMNOTFOUND; break; } + case VT_UNKNOWN: + { + V_UNKNOWN(pVarResult) = static_cast(this); + break; + } default: { V_I1(pVarResult) = 123; @@ -202,6 +215,36 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting 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; + } + public: // IUnknown STDMETHOD(QueryInterface)( /* [in] */ REFIID riid, @@ -217,7 +260,9 @@ const WCHAR * const DispatchCoerceTesting::Names[] = { W("__RESERVED__"), W("ReturnToManaged"), - W("ManagedArgument") + W("ManagedArgument"), + W("ReturnToManaged_Missing"), + W("ReturnToManaged_DBNull") }; const int DispatchCoerceTesting::NamesCount = ARRAY_SIZE(DispatchCoerceTesting::Names); diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index ade29adbf08e71..8a774082c74a98 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -327,6 +327,10 @@ public interface IDispatchCoerceTesting int ReturnToManaged(short vt); int ManagedArgument(int arg); + + System.Reflection.Missing ReturnToManaged_Missing(); + + DBNull ReturnToManaged_DBNull(); } [ComVisible(true)] From 3c8feb174a425be8f088d7367538a37dbab52337 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 3 May 2024 19:10:44 +0800 Subject: [PATCH 07/11] LOCAL_BOOL --- .../COM/NETClients/IDispatch/Program.cs | 4 ++++ .../COM/NETServer/DispatchCoerceTesting.cs | 5 +++++ .../COM/NativeServer/DispatchCoerceTesting.h | 22 ++++++++++++++++++- .../COM/ServerContracts/Server.Contracts.cs | 2 ++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index 10daee4dc3321e..aa1cbff5b12c05 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -268,6 +268,10 @@ static void Validate_ValueCoerce_ReturnToManaged() 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.NotEqual("-1", dispatchCoerceTesting.BoolToString()); } [Fact] diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs index 713b545bce71ed..8309e106a887a8 100644 --- a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -31,4 +31,9 @@ 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/NativeServer/DispatchCoerceTesting.h b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h index 27b886eaad47b5..02de77ef370d03 100644 --- a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h +++ b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h @@ -102,6 +102,10 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting { return ReturnToManaged_DBNull_Dispatch(pDispParams, pVarResult); } + case 5: + { + return BoolToString_Dispatch(pDispParams, pVarResult); + } } return E_NOTIMPL; @@ -245,6 +249,21 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting 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, @@ -262,7 +281,8 @@ const WCHAR * const DispatchCoerceTesting::Names[] = W("ReturnToManaged"), W("ManagedArgument"), W("ReturnToManaged_Missing"), - W("ReturnToManaged_DBNull") + W("ReturnToManaged_DBNull"), + W("BoolToString") }; const int DispatchCoerceTesting::NamesCount = ARRAY_SIZE(DispatchCoerceTesting::Names); diff --git a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs index 8a774082c74a98..27ee5b3bfc3db4 100644 --- a/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs +++ b/src/tests/Interop/COM/ServerContracts/Server.Contracts.cs @@ -331,6 +331,8 @@ public interface IDispatchCoerceTesting System.Reflection.Missing ReturnToManaged_Missing(); DBNull ReturnToManaged_DBNull(); + + string BoolToString(); } [ComVisible(true)] From 9c41cd5b509701658507cf5bf61560f2e473c7c2 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 3 May 2024 20:54:07 +0800 Subject: [PATCH 08/11] Fix compilation --- src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs index 8309e106a887a8..afaed4480c4492 100644 --- a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -24,7 +24,7 @@ public int ManagedArgument(int arg) public System.Reflection.Missing ReturnToManaged_Missing() { - return Type.Missing; + return System.Reflection.Missing.Value; } public DBNull ReturnToManaged_DBNull() From 5fc2273a46a1ebb6b6f0f84f4373ebe059dfec89 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 4 May 2024 13:13:27 +0800 Subject: [PATCH 09/11] Remove unused code --- .../Interop/COM/NETServer/DispatchCoerceTesting.cs | 2 +- .../Interop/COM/NativeServer/DispatchCoerceTesting.h | 11 ----------- src/tests/Interop/COM/NativeServer/Servers.cpp | 1 - 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs index afaed4480c4492..0367c605df4830 100644 --- a/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs +++ b/src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs @@ -14,7 +14,7 @@ public class DispatchCoerceTesting : Server.Contract.IDispatchCoerceTesting { public int ReturnToManaged(short vt) { - return 42; + throw new NotImplementedException(); } public int ManagedArgument(int arg) diff --git a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h index 02de77ef370d03..c8b78f97f54bf1 100644 --- a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h +++ b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h @@ -5,17 +5,6 @@ #include "Servers.h" -/*template -HRESULT VerifyValues(_In_ const T expected, _In_ const T actual) -{ - return (expected == actual) ? S_OK : E_INVALIDARG; -} - -VARIANTARG *NextArg(_In_ VARIANTARG *args, _Inout_ size_t &currIndex) -{ - return (args + (currIndex--)); -}*/ - class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting { private: diff --git a/src/tests/Interop/COM/NativeServer/Servers.cpp b/src/tests/Interop/COM/NativeServer/Servers.cpp index 58041dd51948ce..ebe4f9df5acde2 100644 --- a/src/tests/Interop/COM/NativeServer/Servers.cpp +++ b/src/tests/Interop/COM/NativeServer/Servers.cpp @@ -3,7 +3,6 @@ #include "stdafx.h" #include "Servers.h" -#include namespace { From 9cbf281ea92fbf133f7dc63c8f43774c44660cc6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 4 May 2024 14:48:06 +0800 Subject: [PATCH 10/11] Be explicit about expected values. --- .../COM/NETClients/IDispatch/Program.cs | 29 ++++++++++--------- .../COM/NativeServer/DispatchCoerceTesting.h | 1 + 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index aa1cbff5b12c05..fd052a3b848938 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -222,25 +222,26 @@ static void Validate_ValueCoerce_ReturnToManaged() Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ..."); // Supported types - VarEnum[] supportedTypes = + (VarEnum type, int expectedValue)[] supportedTypes = { - VarEnum.VT_I2, - VarEnum.VT_I4, - VarEnum.VT_R4, - VarEnum.VT_R8, - VarEnum.VT_CY, - VarEnum.VT_DATE, - VarEnum.VT_BSTR, - VarEnum.VT_ERROR, - VarEnum.VT_BOOL, - VarEnum.VT_DECIMAL, + (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 (VarEnum vt in supportedTypes) + foreach (var (vt, expected) in supportedTypes) { Console.WriteLine($"Converting {vt} to int should be supported."); int result = dispatchCoerceTesting.ReturnToManaged((short)vt); - Assert.NotEqual(0, result); + Assert.Equal(expected, result); } // Invalid: Rejected before reaching coerce @@ -271,7 +272,7 @@ static void Validate_ValueCoerce_ReturnToManaged() // LOCAL_BOOL Console.WriteLine("VARIANT_BOOL should convert to non-numeric string."); - Assert.NotEqual("-1", dispatchCoerceTesting.BoolToString()); + Assert.Equal("True", dispatchCoerceTesting.BoolToString()); } [Fact] diff --git a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h index c8b78f97f54bf1..4e9bf3fa99a028 100644 --- a/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h +++ b/src/tests/Interop/COM/NativeServer/DispatchCoerceTesting.h @@ -129,6 +129,7 @@ class DispatchCoerceTesting : public UnknownImpl, public IDispatchCoerceTesting } VARENUM resultType = (VARENUM)*args[0]; + VariantInit(pVarResult); V_VT(pVarResult) = resultType & 0x7FFF; switch ((uint16_t)resultType) From 6a8e0cb5360a4a9a3c2c18cdbebddae5cc026404 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Sat, 4 May 2024 10:16:43 -0700 Subject: [PATCH 11/11] Update src/tests/Interop/COM/NETClients/IDispatch/Program.cs --- src/tests/Interop/COM/NETClients/IDispatch/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs index fd052a3b848938..c57f8c5149f27e 100644 --- a/src/tests/Interop/COM/NETClients/IDispatch/Program.cs +++ b/src/tests/Interop/COM/NETClients/IDispatch/Program.cs @@ -222,6 +222,7 @@ static void Validate_ValueCoerce_ReturnToManaged() Console.WriteLine($"Calling {nameof(DispatchCoerceTesting.ReturnToManaged)} ..."); // Supported types + // See returned values in DispatchCoerceTesting.h (VarEnum type, int expectedValue)[] supportedTypes = { (VarEnum.VT_EMPTY, 0),