Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Explicitly handle char marshalling in OleVariant::GetNativeMethodTableForVarType. #26218

Merged
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
74 changes: 39 additions & 35 deletions src/vm/olevariant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,50 +803,54 @@ MethodTable* OleVariant::GetNativeMethodTableForVarType(VARTYPE vt, MethodTable*
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
THROWS;
GC_TRIGGERS;
MODE_ANY;
}
CONTRACTL_END;

if (vt & VT_ARRAY)
{
GCX_COOP();
if (vt & VT_ARRAY)
{
return MscorlibBinder::GetClass(CLASS__INTPTR);
}
return MscorlibBinder::GetClass(CLASS__INTPTR);
}

switch (vt)
{
case VT_DATE:
return MscorlibBinder::GetClass(CLASS__DOUBLE);
case VT_CY:
return MscorlibBinder::GetClass(CLASS__CURRENCY);
case VTHACK_WINBOOL:
return MscorlibBinder::GetClass(CLASS__INT32);
case VT_BOOL:
return MscorlibBinder::GetClass(CLASS__INT16);
case VTHACK_CBOOL:
return MscorlibBinder::GetClass(CLASS__BYTE);
case VT_DISPATCH:
case VT_UNKNOWN:
case VT_LPSTR:
case VT_LPWSTR:
case VT_BSTR:
case VT_USERDEFINED:
case VT_SAFEARRAY:
case VT_CARRAY:
return MscorlibBinder::GetClass(CLASS__INTPTR);
case VT_VARIANT:
return MscorlibBinder::GetClass(CLASS__NATIVEVARIANT);
default:
PREFIX_ASSUME(pManagedMT != NULL);
return pManagedMT;
}
switch (vt)
{
case VT_DATE:
return MscorlibBinder::GetClass(CLASS__DOUBLE);
case VT_CY:
return MscorlibBinder::GetClass(CLASS__CURRENCY);
case VTHACK_WINBOOL:
return MscorlibBinder::GetClass(CLASS__INT32);
case VT_BOOL:
return MscorlibBinder::GetClass(CLASS__INT16);
case VTHACK_CBOOL:
return MscorlibBinder::GetClass(CLASS__BYTE);
case VT_DISPATCH:
case VT_UNKNOWN:
case VT_LPSTR:
case VT_LPWSTR:
case VT_BSTR:
case VT_USERDEFINED:
case VT_SAFEARRAY:
case VT_CARRAY:
return MscorlibBinder::GetClass(CLASS__INTPTR);
case VT_VARIANT:
return MscorlibBinder::GetClass(CLASS__NATIVEVARIANT);
case VTHACK_ANSICHAR:
return MscorlibBinder::GetClass(CLASS__BYTE);
case VT_UI2:
// When CharSet = CharSet.Unicode, System.Char arrays are marshaled as VT_UI2.
// However, since System.Char itself is CharSet.Ansi, the native size of
// System.Char is 1 byte instead of 2. So here we explicitly return System.UInt16's
// MethodTable to ensure the correct size.
return MscorlibBinder::GetClass(CLASS__UINT16);
default:
PREFIX_ASSUME(pManagedMT != NULL);
return pManagedMT;
}
}


//
// GetMarshalerForVarType returns the marshaler for the
// given VARTYPE.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum StructID
SequentialDoubleWrapperId,
AggregateSequentialWrapperId,
FixedBufferClassificationTestId,
UnicodeCharArrayClassificationId,
HFAId,
DoubleHFAId
}
Expand Down Expand Up @@ -327,6 +328,8 @@ public static int Main()
[DllImport("MarshalStructAsParam")]
static extern bool MarshalStructAsParam_AsSeqByValFixedBufferClassificationTest(FixedArrayClassificationTest str, float f);
[DllImport("MarshalStructAsParam")]
static extern bool MarshalStructAsParam_AsSeqByValUnicodeCharArrayClassification(UnicodeCharArrayClassification str, float f);
[DllImport("MarshalStructAsParam")]
static extern int GetStringLength(AutoString str);

[DllImport("MarshalStructAsParam")]
Expand Down Expand Up @@ -680,6 +683,19 @@ unsafe private static void MarshalStructAsParam_AsSeqByVal(StructID id)
failures++;
}
break;
case StructID.UnicodeCharArrayClassificationId:
Console.WriteLine("\tCalling MarshalStructAsParam_AsSeqByValUnicodeCharArrayClassification with nonblittable struct...");
unsafe
{
UnicodeCharArrayClassification str = new UnicodeCharArrayClassification { arr = new char[6] };
str.f = 56.789f;
if (!MarshalStructAsParam_AsSeqByValUnicodeCharArrayClassification(str, str.f))
{
Console.WriteLine("\tFAILED! Managed to Native failed in MarshalStructAsParam_AsSeqByValUnicodeCharArrayClassification. Expected:True;Actual:False");
failures++;
}
}
break;
case StructID.HFAId:
{
HFA hfa = new HFA
Expand Down Expand Up @@ -2345,6 +2361,7 @@ private static void RunMarshalSeqStructAsParamByVal()
MarshalStructAsParam_AsSeqByVal(StructID.SequentialDoubleWrapperId);
MarshalStructAsParam_AsSeqByVal(StructID.AggregateSequentialWrapperId);
MarshalStructAsParam_AsSeqByVal(StructID.FixedBufferClassificationTestId);
MarshalStructAsParam_AsSeqByVal(StructID.UnicodeCharArrayClassificationId);
MarshalStructAsParam_AsSeqByVal(StructID.HFAId);
MarshalStructAsParam_AsSeqByVal(StructID.DoubleHFAId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,11 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE MarshalStructAsParam_AsSeqByValFixe
return str.f == f;
}

extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE MarshalStructAsParam_AsSeqByValUnicodeCharArrayClassification(UnicodeCharArrayClassification str, float f)
{
return str.f == f;
}

////////////////////////////////////////////////////////////////////////////////////
extern "C" DLL_EXPORT int GetStringLength(AutoString str)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -957,3 +957,9 @@ union OverlappingMultipleEightbyteMultiple
int i[3];
};
};

struct UnicodeCharArrayClassification
{
WCHAR arr[6];
float f;
};
8 changes: 8 additions & 0 deletions tests/src/Interop/StructMarshalling/PInvoke/Struct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,11 @@ public unsafe struct FixedArrayClassificationTest
public Int32Wrapper[] arr;
public float f;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct UnicodeCharArrayClassification
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] arr;
public float f;
}