Skip to content

Commit

Permalink
Check if the marshalling of a field is possible across all platforms. (
Browse files Browse the repository at this point in the history
…#53194)

* Check if the marshalling of a field is possible across all platforms.

* Add test for the generic field generation for IClassX.
  • Loading branch information
AaronRobinsonMSFT committed Jun 8, 2021
1 parent 77fb985 commit aa558fa
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/coreclr/vm/comtoclrcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1013,7 +1013,6 @@ void ComCallMethodDesc::InitNativeInfo()
CONSISTENCY_CHECK_MSGF(false, ("BreakOnComToClrNativeInfoInit: '%s' ", szDebugName));
#endif // _DEBUG

#ifdef TARGET_X86
MetaSig fsig(pFD);
fsig.NextArg();

Expand All @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/vm/mlinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
36 changes: 35 additions & 1 deletion src/tests/Interop/PInvoke/Variant/VariantTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> FieldWithGeneric;
public object FieldRefType;
public DateTime FieldValueType;
}

partial class Test
{
private const byte NumericValue = 15;
Expand Down Expand Up @@ -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<ArgumentException>(() => Marshal_ByValue_Invalid(TimeSpan.Zero));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
}

Expand Down Expand Up @@ -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));
}
}
}

0 comments on commit aa558fa

Please sign in to comment.