From 0994a1c6b87f50dcec538e900af20bee99f15ab5 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Tue, 29 Jan 2019 02:16:16 +0100 Subject: [PATCH] Add Marshal ansi conversion to shared partition (dotnet/coreclr#22243) * Add Marshal ansi conversion to shared partition * Ignore bestFit/throwOnUnmappableChar on Unix * Use same assert in StringToAnsiString * wideCharLen parameter rename Commit migrated from https://github.com/dotnet/coreclr/commit/930abba4060fb528db2bb9835a1bc5a6e684bfec --- .../src/Microsoft/Win32/Win32Native.cs | 3 -- .../Runtime/InteropServices/Marshal.CoreCLR.cs | 4 +-- .../src/System/String.CoreCLR.cs | 34 ---------------------- .../src/System/StubHelpers.cs | 10 +++---- .../System/Runtime/InteropServices/Marshal.Unix.cs | 19 ++++++++++++ .../Runtime/InteropServices/Marshal.Windows.cs | 33 +++++++++++++++++++++ 6 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs b/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs index 65047b8..4374c73 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs @@ -154,9 +154,6 @@ namespace Microsoft.Win32 [DllImport(Interop.Libraries.Kernel32, SetLastError = true)] internal static extern IntPtr GetStdHandle(int nStdHandle); // param is NOT a handle, but it returns one! - [DllImport(Interop.Libraries.Kernel32)] - internal static extern unsafe int WideCharToMultiByte(uint cp, uint flags, char* pwzSource, int cchSource, byte* pbDestBuffer, int cbDestBuffer, IntPtr null1, IntPtr null2); - [DllImport(Interop.Libraries.Kernel32, CharSet = CharSet.Auto, SetLastError = true, BestFitMapping = false)] internal static extern bool SetEnvironmentVariable(string lpName, string lpValue); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index b1f6212..d3ad1c9 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -361,7 +361,7 @@ namespace System.Runtime.InteropServices throw new OutOfMemoryException(); } - s.ConvertToAnsi((byte*)hglobal, nb, false, false); + StringToAnsiString(s, (byte*)hglobal, nb); return hglobal; } @@ -610,7 +610,7 @@ namespace System.Runtime.InteropServices throw new OutOfMemoryException(); } - s.ConvertToAnsi((byte*)hglobal, nb, false, false); + StringToAnsiString(s, (byte*)hglobal, nb); return hglobal; } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/String.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/String.CoreCLR.cs index b4a5019..0695f46 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/String.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/String.CoreCLR.cs @@ -120,39 +120,5 @@ namespace System return encoding.GetBytes(pwzChar, Length, pbNativeBuffer, cbNativeBuffer); } } - - internal unsafe int ConvertToAnsi(byte* pbNativeBuffer, int cbNativeBuffer, bool fBestFit, bool fThrowOnUnmappableChar) - { - Debug.Assert(cbNativeBuffer >= (Length + 1) * Marshal.SystemMaxDBCSCharSize, "Insufficient buffer length passed to ConvertToAnsi"); - - const uint CP_ACP = 0; - int nb; - - const uint WC_NO_BEST_FIT_CHARS = 0x00000400; - - uint flgs = (fBestFit ? 0 : WC_NO_BEST_FIT_CHARS); - uint DefaultCharUsed = 0; - - fixed (char* pwzChar = &_firstChar) - { - nb = Win32Native.WideCharToMultiByte( - CP_ACP, - flgs, - pwzChar, - this.Length, - pbNativeBuffer, - cbNativeBuffer, - IntPtr.Zero, - (fThrowOnUnmappableChar ? new IntPtr(&DefaultCharUsed) : IntPtr.Zero)); - } - - if (0 != DefaultCharUsed) - { - throw new ArgumentException(SR.Interop_Marshal_Unmappable_Char); - } - - pbNativeBuffer[nb] = 0; - return nb; - } } } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs index 84ba25b..d9d229b 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs @@ -27,7 +27,7 @@ namespace System.StubHelpers byte[] buffer = new byte[checked((str.Length + 1) * Marshal.SystemMaxDBCSCharSize)]; fixed (byte* bufferPtr = &buffer[0]) { - cbLength = str.ConvertToAnsi(bufferPtr, buffer.Length, fBestFit, fThrowOnUnmappableChar); + cbLength = Marshal.StringToAnsiString(str, bufferPtr, buffer.Length, fBestFit, fThrowOnUnmappableChar); } return buffer; } @@ -37,7 +37,7 @@ namespace System.StubHelpers int cbAllocLength = (1 + 1) * Marshal.SystemMaxDBCSCharSize; byte* bufferPtr = stackalloc byte[cbAllocLength]; - int cbLength = managedChar.ToString().ConvertToAnsi(bufferPtr, cbAllocLength, fBestFit, fThrowOnUnmappableChar); + int cbLength = Marshal.StringToAnsiString(managedChar.ToString(), bufferPtr, cbAllocLength, fBestFit, fThrowOnUnmappableChar); Debug.Assert(cbLength > 0, "Zero bytes returned from DoAnsiConversion in AnsiCharMarshaler.ConvertToNative"); return bufferPtr[0]; @@ -78,8 +78,8 @@ namespace System.StubHelpers pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb); } - nb = strManaged.ConvertToAnsi(pbNativeBuffer, nb, - fBestFit: 0 != (flags & 0xFF), fThrowOnUnmappableChar: 0 != (flags >> 8)); + nb = Marshal.StringToAnsiString(strManaged, pbNativeBuffer, nb, + bestFit: 0 != (flags & 0xFF), throwOnUnmappableChar: 0 != (flags >> 8)); } else { @@ -1048,7 +1048,7 @@ namespace System.StubHelpers if (IsIn(dwFlags)) { - int length = pManagedHome.ToString().ConvertToAnsi( + int length = Marshal.StringToAnsiString(pManagedHome.ToString(), ptr, allocSize, IsBestFit(dwFlags), IsThrowOn(dwFlags)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs index 930baf9..32c7e63 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs @@ -2,10 +2,29 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; +using System.Text; + namespace System.Runtime.InteropServices { public static partial class Marshal { private static bool IsWin32Atom(IntPtr ptr) => false; + + internal static unsafe int StringToAnsiString(string s, byte* buffer, int bufferLength, bool bestFit = false, bool throwOnUnmappableChar = false) + { + Debug.Assert(bufferLength >= (s.Length + 1) * SystemMaxDBCSCharSize, "Insufficient buffer length passed to StringToAnsiString"); + + int convertedBytes; + + fixed (char* pChar = s) + { + convertedBytes = Encoding.UTF8.GetBytes(pChar, s.Length, buffer, bufferLength); + } + + buffer[convertedBytes] = 0; + + return convertedBytes; + } } } \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs index 7ea4d3a..2750243 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics; + namespace System.Runtime.InteropServices { public static partial class Marshal @@ -19,5 +21,36 @@ namespace System.Runtime.InteropServices long lPtr = (long)ptr; return 0 == (lPtr & HIWORDMASK); } + + internal static unsafe int StringToAnsiString(string s, byte* buffer, int bufferLength, bool bestFit = false, bool throwOnUnmappableChar = false) + { + Debug.Assert(bufferLength >= (s.Length + 1) * SystemMaxDBCSCharSize, "Insufficient buffer length passed to StringToAnsiString"); + + int nb; + + uint flags = bestFit ? 0 : Interop.Kernel32.WC_NO_BEST_FIT_CHARS; + uint defaultCharUsed = 0; + + fixed (char* pwzChar = s) + { + nb = Interop.Kernel32.WideCharToMultiByte( + Interop.Kernel32.CP_ACP, + flags, + pwzChar, + s.Length, + buffer, + bufferLength, + IntPtr.Zero, + throwOnUnmappableChar ? new IntPtr(&defaultCharUsed) : IntPtr.Zero); + } + + if (defaultCharUsed != 0) + { + throw new ArgumentException(SR.Interop_Marshal_Unmappable_Char); + } + + buffer[nb] = 0; + return nb; + } } } \ No newline at end of file -- 2.7.4