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
11 changes: 11 additions & 0 deletions src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,17 @@ internal static unsafe void ConvertToNative(string? strManaged, IntPtr nativeHom
managed.Slice(0, numChars).CopyTo(native);
native[numChars] = '\0';
}

internal static unsafe string ConvertToManaged(IntPtr nativeHome, int length)
{
int end = SpanHelpers.IndexOf(ref *(char*)nativeHome, '\0', length);
if (end != -1)
{
length = end;
}

return new string((char*)nativeHome, 0, length);
}
} // class WSTRBufferMarshaler
#if FEATURE_COMINTEROP

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/src/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,7 @@ DEFINE_METHOD(CSTRMARSHALER, CLEAR_NATIVE, ClearNative,

DEFINE_CLASS(FIXEDWSTRMARSHALER, StubHelpers, FixedWSTRMarshaler)
DEFINE_METHOD(FIXEDWSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_Int_RetVoid)
DEFINE_METHOD(FIXEDWSTRMARSHALER, CONVERT_TO_MANAGED, ConvertToManaged, SM_IntPtr_Int_RetStr)

DEFINE_CLASS(BSTRMARSHALER, StubHelpers, BSTRMarshaler)
DEFINE_METHOD(BSTRMARSHALER, CONVERT_TO_NATIVE, ConvertToNative, SM_Str_IntPtr_RetIntPtr)
Expand Down
7 changes: 2 additions & 5 deletions src/coreclr/src/vm/ilmarshalers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1909,11 +1909,8 @@ void ILFixedWSTRMarshaler::EmitConvertContentsNativeToCLR(ILCodeStream* pslILEmi
STANDARD_VM_CONTRACT;

EmitLoadNativeHomeAddr(pslILEmit);
pslILEmit->EmitDUP();
pslILEmit->EmitCALL(METHOD__STRING__WCSLEN, 1, 1);
pslILEmit->EmitCALL(METHOD__STUBHELPERS__CHECK_STRING_LENGTH, 1, 0);

pslILEmit->EmitNEWOBJ(METHOD__STRING__CTOR_CHARPTR, 1);
pslILEmit->EmitLDC(m_pargs->fs.fixedStringLength);
pslILEmit->EmitCALL(METHOD__FIXEDWSTRMARSHALER__CONVERT_TO_MANAGED, 2, 1);
EmitStoreManagedValue(pslILEmit);
}

Expand Down
15 changes: 15 additions & 0 deletions src/tests/Interop/StringMarshalling/LPTSTR/LPTSTRTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,20 @@ private static void RunByValTStrTests()
ReverseByValStringUni(ref uniStr);

Assert.AreEqual(Helpers.Reverse(InitialString), uniStr.str);

ReverseCopyByValStringAnsi(new ByValStringInStructAnsi { str = LongString }, out ByValStringInStructSplitAnsi ansiStrSplit);

Assert.AreEqual(Helpers.Reverse(LongString[^10..]), ansiStrSplit.str1);
Assert.AreEqual(Helpers.Reverse(LongString[..^10]), ansiStrSplit.str2);

ReverseCopyByValStringUni(new ByValStringInStructUnicode { str = LongString }, out ByValStringInStructSplitUnicode uniStrSplit);

Assert.AreEqual(Helpers.Reverse(LongString[^10..]), uniStrSplit.str1);
Assert.AreEqual(Helpers.Reverse(LongString[..^10]), uniStrSplit.str2);

ReverseCopyByValStringUni(new ByValStringInStructUnicode { str = LongUnicodeString }, out ByValStringInStructSplitUnicode uniStrSplit2);

Assert.AreEqual(Helpers.Reverse(LongUnicodeString[^10..]), uniStrSplit2.str1);
Assert.AreEqual(Helpers.Reverse(LongUnicodeString[..^10]), uniStrSplit2.str2);
}
}
12 changes: 12 additions & 0 deletions src/tests/Interop/StringMarshalling/LPTSTR/LPTStrTestNative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,15 @@ extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseByValStringUni(ByValStringIn
{
StringMarshalingTests<LPWSTR, TP_slen>::ReverseInplace(str->str);
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseCopyByValStringAnsi(ByValStringInStructAnsi str, ByValStringInStructAnsi* out)
{
*out = str;
StringMarshalingTests<char*, default_callconv_strlen>::ReverseInplace(out->str);
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE ReverseCopyByValStringUni(ByValStringInStructUnicode str, ByValStringInStructUnicode* out)
{
*out = str;
StringMarshalingTests<LPWSTR, TP_slen>::ReverseInplace(out->str);
}
18 changes: 18 additions & 0 deletions src/tests/Interop/StringMarshalling/LPTSTR/LPTStrTestNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,31 @@ public struct ByValStringInStructAnsi
public string str;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct ByValStringInStructSplitAnsi
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str2;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ByValStringInStructUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string str;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct ByValStringInStructSplitUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string str2;
}

[DllImport(nameof(LPTStrTestNative), CharSet = CharSet.Unicode)]
public static extern bool Verify_NullTerminators_PastEnd(StringBuilder builder, int length);

Expand Down