diff --git a/src/coreclr/vm/comtoclrcall.cpp b/src/coreclr/vm/comtoclrcall.cpp index 30c5dc3bd9dd5..ca553e1e5cecc 100644 --- a/src/coreclr/vm/comtoclrcall.cpp +++ b/src/coreclr/vm/comtoclrcall.cpp @@ -1013,7 +1013,6 @@ void ComCallMethodDesc::InitNativeInfo() CONSISTENCY_CHECK_MSGF(false, ("BreakOnComToClrNativeInfoInit: '%s' ", szDebugName)); #endif // _DEBUG -#ifdef TARGET_X86 MetaSig fsig(pFD); fsig.NextArg(); @@ -1030,6 +1029,10 @@ void ComCallMethodDesc::InitNativeInfo() #endif ); + if (info.GetMarshalType() == MarshalInfo::MARSHAL_TYPE_UNKNOWN) + info.ThrowTypeLoadExceptionForInvalidFieldMarshal(pFD, info.GetErrorResourceId()); + +#ifdef TARGET_X86 if (IsFieldGetter()) { // getter takes 'this' and the output argument by-ref diff --git a/src/coreclr/vm/mlinfo.h b/src/coreclr/vm/mlinfo.h index 68546b167c21f..81fe67fdc2e1e 100644 --- a/src/coreclr/vm/mlinfo.h +++ b/src/coreclr/vm/mlinfo.h @@ -480,6 +480,12 @@ class MarshalInfo return m_ms == MarshalInfo::MARSHAL_SCENARIO_FIELD; } + UINT GetErrorResourceId() + { + LIMITED_METHOD_CONTRACT; + return m_resID; + } + private: UINT16 GetNativeSize(MarshalType mtype); diff --git a/src/tests/Interop/PInvoke/Variant/VariantTest.cs b/src/tests/Interop/PInvoke/Variant/VariantTest.cs index e15814a9cb6e0..64333f9a7e447 100644 --- a/src/tests/Interop/PInvoke/Variant/VariantTest.cs +++ b/src/tests/Interop/PInvoke/Variant/VariantTest.cs @@ -6,7 +6,20 @@ using TestLibrary; using static VariantNative; -#pragma warning disable CS0612, CS0618 +// Class used to validate the IClassX generation path doesn't fail. +// Support for this scenario is extremely limited so we simply validate +// it continues be generated and can be marshalled to native. +// +// This class must be marked public in order for the IDispatch path for +// field access to be validated. +public class GenerateIClassX +{ + public int FieldPrimitive; + public System.Collections.Generic.List FieldWithGeneric; + public object FieldRefType; + public DateTime FieldValueType; +} + partial class Test { private const byte NumericValue = 15; @@ -41,10 +54,13 @@ private unsafe static void TestByValue(bool hasComSupport) Assert.IsTrue(Marshal_ByValue_Null(DBNull.Value)); Assert.IsTrue(Marshal_ByValue_Missing(System.Reflection.Missing.Value)); Assert.IsTrue(Marshal_ByValue_Empty(null)); + if (hasComSupport) { Assert.IsTrue(Marshal_ByValue_Object(new object())); Assert.IsTrue(Marshal_ByValue_Object_IUnknown(new UnknownWrapper(new object()))); + Assert.IsTrue(Marshal_ByValue_Object(new GenerateIClassX())); + Assert.IsTrue(Marshal_ByValue_Object_IUnknown(new UnknownWrapper(new GenerateIClassX()))); } Assert.Throws(() => Marshal_ByValue_Invalid(TimeSpan.Zero)); @@ -123,6 +139,12 @@ private unsafe static void TestByRef(bool hasComSupport) obj = new UnknownWrapper(new object()); Assert.IsTrue(Marshal_ByRef_Object_IUnknown(ref obj)); + + obj = new GenerateIClassX(); + Assert.IsTrue(Marshal_ByRef_Object(ref obj)); + + obj = new UnknownWrapper(new GenerateIClassX()); + Assert.IsTrue(Marshal_ByRef_Object_IUnknown(ref obj)); } obj = DecimalValue; @@ -209,6 +231,12 @@ private unsafe static void TestFieldByValue(bool hasComSupport) wrapper.value = new UnknownWrapper(new object()); Assert.IsTrue(Marshal_Struct_ByValue_Object_IUnknown(wrapper)); + + wrapper.value = new GenerateIClassX(); + Assert.IsTrue(Marshal_Struct_ByValue_Object(wrapper)); + + wrapper.value = new UnknownWrapper(new GenerateIClassX()); + Assert.IsTrue(Marshal_Struct_ByValue_Object_IUnknown(wrapper)); } } @@ -283,6 +311,12 @@ private unsafe static void TestFieldByRef(bool hasComSupport) wrapper.value = new UnknownWrapper(new object()); Assert.IsTrue(Marshal_Struct_ByRef_Object_IUnknown(ref wrapper)); + + wrapper.value = new GenerateIClassX(); + Assert.IsTrue(Marshal_Struct_ByRef_Object(ref wrapper)); + + wrapper.value = new UnknownWrapper(new GenerateIClassX()); + Assert.IsTrue(Marshal_Struct_ByRef_Object_IUnknown(ref wrapper)); } } }