Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions src/tests/Interop/COM/NETClients/IDispatch/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,67 @@ System.Collections.Generic.IEnumerable<int> 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<InvalidOleVariantTypeException>(() => 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<COMException>(() => 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<COMException>(() => dispatchCoerceTesting.ReturnToManaged_Missing());
Assert.Equal(unchecked((int)0x80020005), comException.HResult);

Console.WriteLine("Converting int to VT_NULL should be rejected.");
comException = Assert.Throws<COMException>(() => 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<InvalidCastException>(() => dispatchCoerceTesting.ReturnToManaged((short)VarEnum.VT_UNKNOWN));
Console.WriteLine("Converting VT_NULL to int should fail from VariantChangeTypeEx.");
Assert.Throws<InvalidCastException>(() => 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()
{
Expand All @@ -233,6 +294,7 @@ public static int TestEntryPoint()
Validate_StructNotSupported();
Validate_LCID_Marshaled();
Validate_Enumerator();
Validate_ValueCoerce_ReturnToManaged();
}
catch (Exception e)
{
Expand Down
39 changes: 39 additions & 0 deletions src/tests/Interop/COM/NETServer/DispatchCoerceTesting.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}
110 changes: 110 additions & 0 deletions src/tests/Interop/COM/NativeClients/Dispatch/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<COINIT TM>
struct ComInit
Expand Down Expand Up @@ -48,6 +49,7 @@ int __cdecl main()
Validate_Double_In_ReturnAndUpdateByRef();
Validate_LCID_Marshaled();
Validate_Enumerator();
Validate_ParamCoerce();
}
catch (HRESULT hr)
{
Expand Down Expand Up @@ -459,3 +461,111 @@ void Validate_Enumerator()
::printf(" -- Validate returned IEnumVARIANT\n");
ValidateReturnedEnumerator(&result);
}

void Validate_ParamCoerce_Type(ComSmartPtr<IDispatchCoerceTesting>& 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,
&params,
&result,
nullptr,
nullptr
));

THROW_FAIL_IF_FALSE(V_I4(&result) != 0);
}

void Validate_ParamCoerce()
{
HRESULT hr;

CoreShimComActivation csact{ W("NETServer"), W("DispatchCoerceTesting") };

ComSmartPtr<IDispatchCoerceTesting> 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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
<comClass
clsid="{0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726}"
threadingModel="Both" />

<!-- DispatchCoerceTesting -->
<comClass
clsid="{661F9962-3477-416B-BE40-4CBA3190A562}"
threadingModel="Both" />
</file>

</assembly>
5 changes: 5 additions & 0 deletions src/tests/Interop/COM/NativeServer/COMNativeServer.X.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
clsid="{4DBD9B61-E372-499F-84DE-EFC70AA8A009}"
threadingModel="Both" />

<!-- DispatchCoerceTesting -->
<comClass
clsid="{661F9962-3477-416B-BE40-4CBA3190A562}"
threadingModel="Both" />

<!-- AggregationTesting -->
<comClass
clsid="{4CEFE36D-F377-4B6E-8C34-819A8BB9CB04}"
Expand Down
Loading