Add Marshal ansi conversion to shared partition (dotnet/coreclr#22243)
authorMarek Safar <marek.safar@gmail.com>
Tue, 29 Jan 2019 01:16:16 +0000 (02:16 +0100)
committerJan Kotas <jkotas@microsoft.com>
Tue, 29 Jan 2019 01:16:16 +0000 (17:16 -0800)
* 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/coreclr/src/System.Private.CoreLib/src/Microsoft/Win32/Win32Native.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/String.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs

index 65047b8..4374c73 100644 (file)
@@ -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);
 
index b1f6212..d3ad1c9 100644 (file)
@@ -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;
         }
 
index b4a5019..0695f46 100644 (file)
@@ -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;
-        }
     }
 }
index 84ba25b..d9d229b 100644 (file)
@@ -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));
index 930baf9..32c7e63 100644 (file)
@@ -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
index 7ea4d3a..2750243 100644 (file)
@@ -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