From 4b11dc566a5bbfa1378d6266525c281b028abcc8 Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Fri, 10 Feb 2017 20:35:12 +0900 Subject: Imported Upstream version 1.0.0.9910 --- src/mscorlib/corefx/System/Buffers/ArrayPool.cs | 25 +-- .../corefx/System/Buffers/ConfigurableArrayPool.cs | 2 +- .../TlsOverPerCoreLockedStacksArrayPool.Unix.cs | 28 --- .../TlsOverPerCoreLockedStacksArrayPool.Windows.cs | 20 -- .../Buffers/TlsOverPerCoreLockedStacksArrayPool.cs | 46 +--- .../corefx/System/Globalization/Calendar.cs | 9 - .../System/Globalization/CalendarData.Unix.cs | 7 - .../System/Globalization/CalendarWeekRule.cs | 1 - .../Globalization/CalendricalCalculationsHelper.cs | 8 +- .../corefx/System/Globalization/CharUnicodeInfo.cs | 32 +-- .../Globalization/ChineseLunisolarCalendar.cs | 10 +- .../System/Globalization/CompareInfo.Windows.cs | 4 +- .../System/Globalization/CultureData.Unix.cs | 7 - .../System/Globalization/CultureData.Windows.cs | 3 +- .../Globalization/CultureNotFoundException.cs | 11 +- .../corefx/System/Globalization/CultureTypes.cs | 4 +- .../System/Globalization/DateTimeFormatInfo.cs | 8 +- .../corefx/System/Globalization/DigitShapes.cs | 1 + .../Globalization/EastAsianLunisolarCalendar.cs | 1 - .../System/Globalization/GregorianCalendar.cs | 5 - .../corefx/System/Globalization/HebrewCalendar.cs | 1 - .../System/Globalization/HijriCalendar.Win32.cs | 36 +-- .../corefx/System/Globalization/HijriCalendar.cs | 5 - .../System/Globalization/IdnMapping.Windows.cs | 2 +- .../System/Globalization/JapaneseCalendar.Win32.cs | 22 +- .../System/Globalization/JapaneseCalendar.cs | 6 - .../Globalization/JapaneseLunisolarCalendar.cs | 6 +- .../corefx/System/Globalization/JulianCalendar.cs | 5 - .../corefx/System/Globalization/KoreanCalendar.cs | 6 - .../Globalization/KoreanLunisolarCalendar.cs | 6 +- .../System/Globalization/NumberFormatInfo.cs | 54 ++--- .../corefx/System/Globalization/RegionInfo.cs | 2 - .../corefx/System/Globalization/SortKey.cs | 1 - .../corefx/System/Globalization/SortVersion.cs | 50 ++--- .../corefx/System/Globalization/StringInfo.cs | 3 - .../corefx/System/Globalization/TaiwanCalendar.cs | 6 - .../Globalization/TaiwanLunisolarCalendar.cs | 6 +- .../System/Globalization/TextElementEnumerator.cs | 1 - .../corefx/System/Globalization/TextInfo.Unix.cs | 2 - .../corefx/System/Globalization/TextInfo.cs | 3 - .../System/Globalization/ThaiBuddhistCalendar.cs | 6 - .../System/Globalization/UmAlQuraCalendar.cs | 2 +- .../corefx/System/IO/FileStream.NetStandard17.cs | 76 ------- src/mscorlib/corefx/System/IO/FileStream.Win32.cs | 76 +++---- src/mscorlib/corefx/System/IO/FileStream.cs | 94 +++++--- .../System/IO/FileStreamCompletionSource.Win32.cs | 6 +- src/mscorlib/corefx/System/IO/Path.Unix.cs | 62 +----- src/mscorlib/corefx/System/IO/Path.Windows.cs | 32 +-- src/mscorlib/corefx/System/IO/Path.cs | 33 ++- .../corefx/System/IO/PathHelper.Windows.cs | 245 +++++++++++---------- .../System/IO/PathInternal.CaseSensitivity.cs | 75 ------- src/mscorlib/corefx/System/IO/PathInternal.Unix.cs | 42 +--- .../System/IO/PathInternal.Windows.StringBuffer.cs | 18 +- .../corefx/System/IO/PathInternal.Windows.cs | 124 ++++------- src/mscorlib/corefx/System/IO/PathInternal.cs | 58 ----- src/mscorlib/corefx/System/IO/Win32Marshal.cs | 45 +--- .../System/Runtime/InteropServices/NativeBuffer.cs | 157 ------------- .../Runtime/InteropServices/SafeHeapHandle.cs | 109 --------- .../Runtime/InteropServices/SafeHeapHandleCache.cs | 97 -------- .../System/Runtime/InteropServices/StringBuffer.cs | 199 ++++++----------- .../corefx/System/Security/SecureString.Windows.cs | 8 +- 61 files changed, 568 insertions(+), 1451 deletions(-) delete mode 100644 src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs delete mode 100644 src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs delete mode 100644 src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs delete mode 100644 src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs delete mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs delete mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs delete mode 100644 src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs (limited to 'src/mscorlib/corefx/System') diff --git a/src/mscorlib/corefx/System/Buffers/ArrayPool.cs b/src/mscorlib/corefx/System/Buffers/ArrayPool.cs index 441e48dab4..77a07f7fa5 100644 --- a/src/mscorlib/corefx/System/Buffers/ArrayPool.cs +++ b/src/mscorlib/corefx/System/Buffers/ArrayPool.cs @@ -29,26 +29,13 @@ namespace System.Buffers /// array than was requested. Renting a buffer from it with will result in an /// existing buffer being taken from the pool if an appropriate buffer is available or in a new /// buffer being allocated if one is not available. + /// byte[] and char[] are the most commonly pooled array types. For these we use a special pool type + /// optimized for very fast access speeds, at the expense of more memory consumption. + /// The shared pool instance is created lazily on first access. /// - public static ArrayPool Shared => SharedPool.Value; - - /// Stores a cached pool instance for T[]. - /// - /// Separated out into a nested class to enable lazy-initialization of the pool provided by - /// the runtime, only forced when Shared is used (and not when Create is called or when - /// other non-Shared accesses happen). - /// - private static class SharedPool - { - /// Per-type cached pool. - /// - /// byte[] and char[] are the most commonly pooled array types. For these we use a special pool type - /// optimized for very fast access speeds, at the expense of more memory consumption. - /// - internal readonly static ArrayPool Value = - typeof(T) == typeof(byte) || typeof(T) == typeof(char) ? new TlsOverPerCoreLockedStacksArrayPool() : - Create(); - } + public static ArrayPool Shared { get; } = + typeof(T) == typeof(byte) || typeof(T) == typeof(char) ? new TlsOverPerCoreLockedStacksArrayPool() : + Create(); /// /// Creates a new instance using default configuration options. diff --git a/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs b/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs index 1e0e769530..f7b6034d20 100644 --- a/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs +++ b/src/mscorlib/corefx/System/Buffers/ConfigurableArrayPool.cs @@ -70,7 +70,7 @@ namespace System.Buffers { // No need for events with the empty array. Our pool is effectively infinite // and we'll never allocate for rents and never store for returns. - return EmptyArray.Value; + return Array.Empty(); } var log = ArrayPoolEventSource.Log; diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs deleted file mode 100644 index 8a1d006b12..0000000000 --- a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Unix.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Win32; -using System.Runtime.CompilerServices; - -namespace System.Buffers -{ - internal sealed partial class TlsOverPerCoreLockedStacksArrayPool - { - /// Get an identifier for the current thread to use to index into the stacks. - private static int ExecutionId - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - // On Unix, CurrentProcessorNumber is implemented in terms of sched_getcpu, which - // doesn't exist on all platforms. On those it doesn't exist on, GetCurrentProcessorNumber - // returns -1. As a fallback in that case and to spread the threads across the buckets - // by default, we use the current managed thread ID as a proxy. - int id = CurrentProcessorNumber; - if (id < 0) id = Environment.CurrentManagedThreadId; - return id; - } - } - } -} diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs deleted file mode 100644 index d42242c910..0000000000 --- a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.Windows.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Win32; -using System.Runtime.CompilerServices; -using System.Threading; - -namespace System.Buffers -{ - internal sealed partial class TlsOverPerCoreLockedStacksArrayPool : ArrayPool - { - /// Get an identifier for the current thread to use to index into the stacks. - private static int ExecutionId - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { return CurrentProcessorNumber; } - } - } -} diff --git a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index debc33615f..64c5cebe85 100644 --- a/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/mscorlib/corefx/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -45,11 +45,6 @@ namespace System.Buffers /// A per-thread array of arrays, to cache one array per array size per thread. [ThreadStatic] private static T[][] t_tlsBuckets; - /// - /// Cached processor number used as a hint for which per-core stack to access. - /// - [ThreadStatic] - private static int? t_cachedProcessorNumber; /// Initialize the pool. public TlsOverPerCoreLockedStacksArrayPool() @@ -72,22 +67,6 @@ namespace System.Buffers /// Gets an ID for the pool to use with events. private int Id => GetHashCode(); - /// Gets the processor number associated with the current thread. - /// Uses a cached value if one exists on the current thread. - private static int CurrentProcessorNumber - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - int? num = t_cachedProcessorNumber; - if (!num.HasValue) - { - t_cachedProcessorNumber = num = Environment.CurrentProcessorNumber; - } - return num.GetValueOrDefault(); - } - } - public override T[] Rent(int minimumLength) { // Arrays can't be smaller than zero. We allow requesting zero-length arrays (even though @@ -101,7 +80,7 @@ namespace System.Buffers { // No need to log the empty array. Our pool is effectively infinite // and we'll never allocate for rents and never store for returns. - return EmptyArray.Value; + return Array.Empty(); } ArrayPoolEventSource log = ArrayPoolEventSource.Log; @@ -249,7 +228,7 @@ namespace System.Buffers // Try to push on to the associated stack first. If that fails, // round-robin through the other stacks. LockedStack[] stacks = _perCoreStacks; - int index = ExecutionId % stacks.Length; + int index = Environment.CurrentExecutionId % stacks.Length; for (int i = 0; i < stacks.Length; i++) { if (stacks[index].TryPush(array)) return; @@ -265,7 +244,7 @@ namespace System.Buffers // round-robin through the other stacks. T[] arr; LockedStack[] stacks = _perCoreStacks; - int index = ExecutionId % stacks.Length; + int index = Environment.CurrentExecutionId % stacks.Length; for (int i = 0; i < stacks.Length; i++) { if ((arr = stacks[index].TryPop()) != null) return arr; @@ -285,7 +264,7 @@ namespace System.Buffers public bool TryPush(T[] array) { bool enqueued = false; - MonitorEnterWithProcNumberFlush(this); + Monitor.Enter(this); if (_count < MaxBuffersPerArraySizePerCore) { _arrays[_count++] = array; @@ -299,7 +278,7 @@ namespace System.Buffers public T[] TryPop() { T[] arr = null; - MonitorEnterWithProcNumberFlush(this); + Monitor.Enter(this); if (_count > 0) { arr = _arrays[--_count]; @@ -308,21 +287,6 @@ namespace System.Buffers Monitor.Exit(this); return arr; } - - /// - /// Enters the monitor on the object. If there is any contention while trying - /// to acquire the monitor, it flushes the cached processor number so that subsequent - /// attempts to access the per-core stacks will use an updated processor number. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void MonitorEnterWithProcNumberFlush(object obj) - { - if (!Monitor.TryEnter(obj)) - { - t_cachedProcessorNumber = null; - Monitor.Enter(obj); - } - } } } } diff --git a/src/mscorlib/corefx/System/Globalization/Calendar.cs b/src/mscorlib/corefx/System/Globalization/Calendar.cs index 78e9f00d08..0ff5040c74 100644 --- a/src/mscorlib/corefx/System/Globalization/Calendar.cs +++ b/src/mscorlib/corefx/System/Globalization/Calendar.cs @@ -29,7 +29,6 @@ namespace System.Globalization // since most of the calendars (or all?) have the same way of calcuating hour/minute/second. [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public abstract partial class Calendar : ICloneable { // Number of 100ns (10E-7 second) ticks per time unit @@ -77,7 +76,6 @@ namespace System.Globalization // The minimum supported DateTime range for the calendar. - [System.Runtime.InteropServices.ComVisible(false)] public virtual DateTime MinSupportedDateTime { get @@ -88,7 +86,6 @@ namespace System.Globalization // The maximum supported DateTime range for the calendar. - [System.Runtime.InteropServices.ComVisible(false)] public virtual DateTime MaxSupportedDateTime { get @@ -97,7 +94,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public virtual CalendarAlgorithmType AlgorithmType { get @@ -138,7 +134,6 @@ namespace System.Globalization // Detect if the object is readonly. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public bool IsReadOnly { get { return (_isReadOnly); } @@ -151,7 +146,6 @@ namespace System.Globalization // Is the implementation of ICloneable. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public virtual object Clone() { object o = MemberwiseClone(); @@ -167,7 +161,6 @@ namespace System.Globalization // readonly. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public static Calendar ReadOnly(Calendar calendar) { if (calendar == null) { throw new ArgumentNullException(nameof(calendar)); } @@ -708,7 +701,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public virtual int GetLeapMonth(int year) { return (GetLeapMonth(year, CurrentEra)); @@ -718,7 +710,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public virtual int GetLeapMonth(int year, int era) { if (!IsLeapYear(year, era)) diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs index 270d62f143..19c81f17b0 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs @@ -64,7 +64,6 @@ namespace System.Globalization } // Call native side to figure out which calendars are allowed - [SecuritySafeCritical] internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars) { // NOTE: there are no 'user overrides' on Linux @@ -87,7 +86,6 @@ namespace System.Globalization // PAL Layer ends here - [SecuritySafeCritical] private static bool GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string calendarString) { return Interop.CallStringMethod( @@ -239,7 +237,6 @@ namespace System.Globalization return index - startIndex; } - [SecuritySafeCritical] private static bool EnumMonthNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] monthNames) { monthNames = null; @@ -261,7 +258,6 @@ namespace System.Globalization return result; } - [SecuritySafeCritical] private static bool EnumEraNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] eraNames) { bool result = EnumCalendarInfo(localeName, calendarId, dataType, out eraNames); @@ -277,7 +273,6 @@ namespace System.Globalization return result; } - [SecuritySafeCritical] internal static bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] calendarData) { calendarData = null; @@ -292,7 +287,6 @@ namespace System.Globalization return result; } - [SecuritySafeCritical] private static bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, CallbackContext callbackContext) { GCHandle context = GCHandle.Alloc(callbackContext); @@ -306,7 +300,6 @@ namespace System.Globalization } } - [SecuritySafeCritical] private static void EnumCalendarInfoCallback(string calendarString, IntPtr context) { CallbackContext callbackContext = (CallbackContext)((GCHandle)context).Target; diff --git a/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs b/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs index 490951e1f0..4013ce7237 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs @@ -7,7 +7,6 @@ using System; namespace System.Globalization { [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public enum CalendarWeekRule { FirstDay = 0, // Week 1 begins on the first day of the year diff --git a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs index 149e63c689..7de75d6aee 100644 --- a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs @@ -22,8 +22,8 @@ namespace System.Globalization private const int SecondsPerMinute = 60; private const int MinutesPerDegree = 60; - private static readonly long StartOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); - private static readonly long StartOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); + private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); + private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; @@ -146,7 +146,7 @@ namespace System.Globalization private static double CenturiesFrom1900(int gregorianYear) { long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1)); - return (double)(july1stOfYear - StartOf1900Century) / DaysInUniformLengthCentury; + return (double)(july1stOfYear - s_startOf1900Century) / DaysInUniformLengthCentury; } // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges @@ -154,7 +154,7 @@ namespace System.Globalization { Debug.Assert(gregorianYear < 1620 || 2020 <= gregorianYear); long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1)); - double daysSinceStartOf1810 = january1stOfYear - StartOf1810; + double daysSinceStartOf1810 = january1stOfYear - s_startOf1810; double x = TwelveHours + daysSinceStartOf1810; return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay; } diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs index dc38ca405b..38ce441a78 100644 --- a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs @@ -194,7 +194,7 @@ namespace System.Globalization // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table. // Note that & has the lower precedence than addition, so don't forget the parathesis. index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)]; - + fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index])) { byte* pBytePtr = (byte*)pUshortPtr; @@ -238,46 +238,46 @@ namespace System.Globalization return (InternalGetNumericValue(InternalConvertToUtf32(s, index))); } - public static int GetDecimalDigitValue(char ch) + public static int GetDecimalDigitValue(char ch) { - return (sbyte) (InternalGetDigitValues(ch) >> 8); + return (sbyte)(InternalGetDigitValues(ch) >> 8); } - public static int GetDecimalDigitValue(String s, int index) + public static int GetDecimalDigitValue(String s, int index) { - if (s == null) + if (s == null) { throw new ArgumentNullException(nameof(s)); } - - if (index < 0 || index >= s.Length) + + if (index < 0 || index >= s.Length) { throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } Contract.EndContractBlock(); - return (sbyte) (InternalGetDigitValues(InternalConvertToUtf32(s, index)) >> 8); + return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) >> 8); } - + public static int GetDigitValue(char ch) { - return (sbyte) (InternalGetDigitValues(ch) & 0x00FF); + return (sbyte)(InternalGetDigitValues(ch) & 0x00FF); } - public static int GetDigitValue(String s, int index) + public static int GetDigitValue(String s, int index) { - if (s == null) + if (s == null) { throw new ArgumentNullException(nameof(s)); } - - if (index < 0 || index >= s.Length) + + if (index < 0 || index >= s.Length) { throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); } - + Contract.EndContractBlock(); - return (sbyte) (InternalGetDigitValues(InternalConvertToUtf32(s, index)) & 0x00FF); + return (sbyte)(InternalGetDigitValues(InternalConvertToUtf32(s, index)) & 0x00FF); } public static UnicodeCategory GetUnicodeCategory(char ch) diff --git a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs index 271d9802ce..5002555384 100644 --- a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs @@ -42,7 +42,6 @@ namespace System.Globalization internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY); internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999); - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -52,7 +51,6 @@ namespace System.Globalization } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -318,9 +316,9 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", @@ -330,7 +328,7 @@ namespace System.Globalization } Contract.EndContractBlock(); - return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) @@ -362,7 +360,6 @@ namespace System.Globalization { } - [System.Runtime.InteropServices.ComVisible(false)] public override int GetEra(DateTime time) { CheckTicksRange(time.Ticks); @@ -387,7 +384,6 @@ namespace System.Globalization } - [System.Runtime.InteropServices.ComVisible(false)] public override int[] Eras { get diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs index 4ebaf9cb10..d4936522dd 100644 --- a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs @@ -351,7 +351,7 @@ namespace System.Globalization private unsafe SortKey CreateSortKey(String source, CompareOptions options) { - if (source==null) { throw new ArgumentNullException(nameof(source)); } + if (source == null) { throw new ArgumentNullException(nameof(source)); } Contract.EndContractBlock(); if ((options & ValidSortkeyCtorMaskOffFlags) != 0) @@ -362,7 +362,7 @@ namespace System.Globalization throw new NotImplementedException(); } - private static unsafe bool IsSortable(char *text, int length) + private static unsafe bool IsSortable(char* text, int length) { // CompareInfo c = CultureInfo.InvariantCulture.CompareInfo; // return (InternalIsSortable(c.m_dataHandle, c.m_handleOrigin, c.m_sortName, text, text.Length)); diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs index 7f2f17d9f5..ba96189458 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs @@ -24,7 +24,6 @@ namespace System.Globalization /// This method uses the sRealName field (which is initialized by the constructor before this is called) to /// initialize the rest of the state of CultureData based on the underlying OS globalization library. /// - [SecuritySafeCritical] private unsafe bool InitCultureData() { Debug.Assert(_sRealName != null); @@ -87,7 +86,6 @@ namespace System.Globalization return true; } - [SecuritySafeCritical] internal static bool GetLocaleName(string localeName, out string windowsName) { // Get the locale name from ICU @@ -104,7 +102,6 @@ namespace System.Globalization return true; } - [SecuritySafeCritical] internal static bool GetDefaultLocaleName(out string windowsName) { // Get the default (system) locale name from ICU @@ -129,7 +126,6 @@ namespace System.Globalization // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the // "windows" name, which can be specific for downlevel (< windows 7) os's. - [SecuritySafeCritical] private string GetLocaleInfo(string localeName, LocaleStringData type) { Debug.Assert(localeName != null, "[CultureData.GetLocaleInfo] Expected localeName to be not be null"); @@ -155,7 +151,6 @@ namespace System.Globalization return StringBuilderCache.GetStringAndRelease(sb); } - [SecuritySafeCritical] private int GetLocaleInfo(LocaleNumberData type) { Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleNumberData)] Expected _sWindowsName to be populated already"); @@ -179,7 +174,6 @@ namespace System.Globalization return value; } - [SecuritySafeCritical] private int[] GetLocaleInfo(LocaleGroupingData type) { Debug.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleGroupingData)] Expected _sWindowsName to be populated already"); @@ -205,7 +199,6 @@ namespace System.Globalization return GetTimeFormatString(false); } - [SecuritySafeCritical] private string GetTimeFormatString(bool shortFormat) { Debug.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatString(bool shortFormat)] Expected _sWindowsName to be populated already"); diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs index d1c99da607..0c264e5f8b 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs @@ -663,11 +663,10 @@ namespace System.Globalization { get { throw new NotImplementedException(); } } - + internal bool IsReplacementCulture { get { throw new NotImplementedException(); } } - } } diff --git a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs index 64782d28c0..d296ad88e5 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs @@ -3,14 +3,13 @@ // See the LICENSE file in the project root for more information. using System; -using System.Threading; using System.Runtime.Serialization; +using System.Threading; namespace System.Globalization { [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public partial class CultureNotFoundException : ArgumentException, ISerializable + public class CultureNotFoundException : ArgumentException, ISerializable { private string _invalidCultureName; // unrecognized culture name private int? _invalidCultureId; // unrecognized culture Lcid @@ -66,14 +65,8 @@ namespace System.Globalization _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string)); } - [System.Security.SecurityCritical] // auto-generated_required public override void GetObjectData(SerializationInfo info, StreamingContext context) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } - base.GetObjectData(info, context); info.AddValue("InvalidCultureId", _invalidCultureId, typeof(int?)); info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string)); diff --git a/src/mscorlib/corefx/System/Globalization/CultureTypes.cs b/src/mscorlib/corefx/System/Globalization/CultureTypes.cs index 80b588aabb..35ddff6086 100644 --- a/src/mscorlib/corefx/System/Globalization/CultureTypes.cs +++ b/src/mscorlib/corefx/System/Globalization/CultureTypes.cs @@ -7,7 +7,7 @@ // the rest are obsolete or not valid on Linux namespace System.Globalization -{ +{ [Serializable] [Flags] public enum CultureTypes @@ -25,4 +25,4 @@ namespace System.Globalization [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")] FrameworkCultures = 0x0040, // will return only the v2 cultures marked as Framework culture. } -} +} diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs index 216fc603d0..b79ce90424 100644 --- a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs @@ -514,7 +514,6 @@ namespace System.Globalization public String AMDesignator { - // auto-generated get { if (this.amDesignator == null) @@ -1031,7 +1030,6 @@ namespace System.Globalization public String PMDesignator { - // auto-generated get { if (this.pmDesignator == null) @@ -2163,7 +2161,7 @@ namespace System.Globalization // // Positive TimeSpan Pattern // - + [NonSerialized] private string _fullTimeSpanPositivePattern; internal String FullTimeSpanPositivePattern { @@ -2187,7 +2185,7 @@ namespace System.Globalization // // Negative TimeSpan Pattern // - + [NonSerialized] private string _fullTimeSpanNegativePattern; internal String FullTimeSpanNegativePattern { @@ -2343,7 +2341,7 @@ namespace System.Globalization // // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens. // - + [NonSerialized] private TokenHashValue[] _dtfiTokenHash; private const int TOKEN_HASH_SIZE = 199; diff --git a/src/mscorlib/corefx/System/Globalization/DigitShapes.cs b/src/mscorlib/corefx/System/Globalization/DigitShapes.cs index 7e40033a2f..0e4dcc87c3 100644 --- a/src/mscorlib/corefx/System/Globalization/DigitShapes.cs +++ b/src/mscorlib/corefx/System/Globalization/DigitShapes.cs @@ -5,6 +5,7 @@ // // The enumeration constants used in NumberFormatInfo.DigitSubstitution. // + namespace System.Globalization { [Serializable] diff --git a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs index 84a44a990d..f82fad8e5b 100644 --- a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs @@ -14,7 +14,6 @@ namespace System.Globalization //////////////////////////////////////////////////////////////////////////// [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public abstract class EastAsianLunisolarCalendar : Calendar { internal const int LeapMonth = 0; diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs index c2ed2e012b..be5b65b385 100644 --- a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs @@ -19,7 +19,6 @@ namespace System.Globalization // 1 BeforeCurrentEra (BC) [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class GregorianCalendar : Calendar { @@ -66,7 +65,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -75,7 +73,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -84,7 +81,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -510,7 +506,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { if (era != CurrentEra && era != ADEra) diff --git a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs index 7e63708382..b4f54f8fbb 100644 --- a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs @@ -63,7 +63,6 @@ namespace System.Globalization [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class HebrewCalendar : Calendar { public static readonly int HebrewEra = 1; diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs index 5f46dce61d..869b809bff 100644 --- a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs +++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Win32.cs @@ -8,9 +8,10 @@ namespace System.Globalization { public partial class HijriCalendar : Calendar { - private static int GetHijriDateAdjustment() + private int GetHijriDateAdjustment() { - if (_hijriAdvance == Int32.MinValue) { + if (_hijriAdvance == Int32.MinValue) + { // Never been set before. Use the system value from registry. _hijriAdvance = GetAdvanceHijriDate(); } @@ -36,11 +37,13 @@ namespace System.Globalization ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date. ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date. ============================================================================*/ - private static int GetAdvanceHijriDate() { + private static int GetAdvanceHijriDate() + { int hijriAdvance = 0; Microsoft.Win32.RegistryKey key = null; - try { + try + { // Open in read-only mode. // Use InternalOpenSubKey so that we avoid the security check. key = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER).OpenSubKey(InternationalRegKey, false); @@ -49,21 +52,28 @@ namespace System.Globalization catch (ObjectDisposedException) { return 0; } catch (ArgumentException) { return 0; } - if (key != null) { - try { + if (key != null) + { + try + { Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false); - if (value == null) { + if (value == null) + { return (0); } String str = value.ToString(); - if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) { + if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) + { if (str.Length == HijriAdvanceRegKeyEntry.Length) hijriAdvance = -1; - else { + else + { str = str.Substring(HijriAdvanceRegKeyEntry.Length); - try { + try + { int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture); - if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) { + if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) + { hijriAdvance = advance; } } @@ -75,10 +85,10 @@ namespace System.Globalization } } } - finally { + finally + { key.Close(); } - } return (hijriAdvance); } diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs index 156b2104bd..0c72d9eaf5 100644 --- a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs @@ -45,7 +45,6 @@ namespace System.Globalization */ [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public partial class HijriCalendar : Calendar { public static readonly int HijriEra = 1; @@ -72,7 +71,6 @@ namespace System.Globalization internal static readonly DateTime calendarMaxValue = DateTime.MaxValue; - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -82,7 +80,6 @@ namespace System.Globalization } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -91,7 +88,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -565,7 +561,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { CheckYearRange(year, era); diff --git a/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs b/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs index f39457b750..3d3292e3db 100644 --- a/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs +++ b/src/mscorlib/corefx/System/Globalization/IdnMapping.Windows.cs @@ -7,7 +7,7 @@ using System.Runtime.InteropServices; namespace System.Globalization { - sealed partial class IdnMapping + public sealed partial class IdnMapping { private unsafe string GetAsciiCore(char* unicode, int count) { diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs index bbde320041..a83c4fad9e 100644 --- a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs +++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Win32.cs @@ -33,7 +33,7 @@ namespace System.Globalization // Look in the registry key and see if we can find any ranges int iFoundEras = 0; EraInfo[] registryEraRanges = null; - + try { // Need to access registry @@ -59,7 +59,7 @@ namespace System.Globalization // Remember we found one. registryEraRanges[iFoundEras] = era; - iFoundEras++; + iFoundEras++; } } } @@ -109,7 +109,7 @@ namespace System.Globalization else { // Rest are until the next era (remember most recent era is first in array) - registryEraRanges[i].maxEraYear = registryEraRanges[i-1].yearOffset + 1 - registryEraRanges[i].yearOffset; + registryEraRanges[i].maxEraYear = registryEraRanges[i - 1].yearOffset + 1 - registryEraRanges[i].yearOffset; } } @@ -147,7 +147,7 @@ namespace System.Globalization { // Need inputs if (value == null || data == null) return null; - + // // Get Date // @@ -159,9 +159,9 @@ namespace System.Globalization int month; int day; - if (!Int32.TryParse(value.Substring(0,4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) || - !Int32.TryParse(value.Substring(5,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) || - !Int32.TryParse(value.Substring(8,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day)) + if (!Int32.TryParse(value.Substring(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) || + !Int32.TryParse(value.Substring(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) || + !Int32.TryParse(value.Substring(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day)) { // Couldn't convert integer, fail return null; @@ -171,7 +171,7 @@ namespace System.Globalization // Get Strings // // Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups) - String[] names = data.Split(new char[] {'_'}); + String[] names = data.Split('_'); // Should have exactly 4 parts // 0 - Era Name @@ -192,18 +192,18 @@ namespace System.Globalization // Note that the era # and max era year need cleaned up after sorting // Don't use the full English Era Name (names[2]) // - return new EraInfo( 0, year, month, day, year - 1, 1, 0, + return new EraInfo(0, year, month, day, year - 1, 1, 0, names[0], names[1], names[3]); } // PAL Layer ends here - private static string[] JapaneseErasEnglishNames = new String[] { "M", "T", "S", "H" }; + private static string[] s_japaneseErasEnglishNames = new String[] { "M", "T", "S", "H" }; private static string GetJapaneseEnglishEraName(int era) { Debug.Assert(era > 0); - return era <= JapaneseErasEnglishNames.Length ? JapaneseErasEnglishNames[era - 1] : " "; + return era <= s_japaneseErasEnglishNames.Length ? s_japaneseErasEnglishNames[era - 1] : " "; } } } diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs index 0b0fa77fc0..f0216c8f51 100644 --- a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs @@ -39,13 +39,11 @@ namespace System.Globalization [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public partial class JapaneseCalendar : Calendar { internal static readonly DateTime calendarMinValue = new DateTime(1868, 9, 8); - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -54,7 +52,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -63,7 +60,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -233,7 +229,6 @@ namespace System.Globalization [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - [System.Runtime.InteropServices.ComVisible(false)] public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) { return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); @@ -281,7 +276,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { return (helper.GetLeapMonth(year, era)); diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs index ecdaced2d7..cc3d34954d 100644 --- a/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs @@ -206,9 +206,9 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", @@ -220,7 +220,7 @@ namespace System.Globalization } Contract.EndContractBlock(); - return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) diff --git a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs index a4277c6d49..43e6ad07a2 100644 --- a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs @@ -19,7 +19,6 @@ namespace System.Globalization //* Julia 0001/01/03 9999/10/19 [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class JulianCalendar : Calendar { public static readonly int JulianEra = 1; @@ -49,7 +48,6 @@ namespace System.Globalization internal int MaxYear = 9999; - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -58,7 +56,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -67,7 +64,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -346,7 +342,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { CheckYearEraRange(year, era); diff --git a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs index 27d0aa812a..b015aa0716 100644 --- a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs @@ -25,7 +25,6 @@ namespace System.Globalization [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class KoreanCalendar : Calendar { // @@ -51,7 +50,6 @@ namespace System.Globalization internal GregorianCalendarHelper helper; - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -60,7 +58,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -69,7 +66,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -160,7 +156,6 @@ namespace System.Globalization [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - [System.Runtime.InteropServices.ComVisible(false)] public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) { return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); @@ -199,7 +194,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { return (helper.GetLeapMonth(year, era)); diff --git a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs index 07d85a461e..6d091285b2 100644 --- a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs @@ -1251,9 +1251,9 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", @@ -1264,7 +1264,7 @@ namespace System.Globalization MAX_LUNISOLAR_YEAR)); } Contract.EndContractBlock(); - return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) diff --git a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs index 813554fd21..54cf492135 100644 --- a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs @@ -289,7 +289,7 @@ namespace System.Globalization if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "CurrencyDecimalDigits", + nameof(CurrencyDecimalDigits), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -357,14 +357,14 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("CurrencyGroupSizes", + throw new ArgumentNullException(nameof(CurrencyGroupSizes), SR.ArgumentNull_Obj); } Contract.EndContractBlock(); VerifyWritable(); Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize("CurrencyGroupSizes", inputSizes); + CheckGroupSize(nameof(CurrencyGroupSizes), inputSizes); currencyGroupSizes = inputSizes; } } @@ -381,14 +381,14 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("NumberGroupSizes", + throw new ArgumentNullException(nameof(NumberGroupSizes), SR.ArgumentNull_Obj); } Contract.EndContractBlock(); VerifyWritable(); Int32[] inputSizes = (Int32[])value.Clone(); - CheckGroupSize("NumberGroupSizes", inputSizes); + CheckGroupSize(nameof(NumberGroupSizes), inputSizes); numberGroupSizes = inputSizes; } } @@ -422,7 +422,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyGroupSeparator(value, "CurrencyGroupSeparator"); + VerifyGroupSeparator(value, nameof(CurrencyGroupSeparator)); currencyGroupSeparator = value; } } @@ -435,7 +435,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("CurrencySymbol", + throw new ArgumentNullException(nameof(CurrencySymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -475,7 +475,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("NaNSymbol", + throw new ArgumentNullException(nameof(NaNSymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -494,7 +494,7 @@ namespace System.Globalization if (value < 0 || value > 15) { throw new ArgumentOutOfRangeException( - "CurrencyNegativePattern", + nameof(CurrencyNegativePattern), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -519,7 +519,7 @@ namespace System.Globalization if (value < 0 || value > 4) { throw new ArgumentOutOfRangeException( - "NumberNegativePattern", + nameof(NumberNegativePattern), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -544,7 +544,7 @@ namespace System.Globalization if (value < 0 || value > 3) { throw new ArgumentOutOfRangeException( - "PercentPositivePattern", + nameof(PercentPositivePattern), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -569,7 +569,7 @@ namespace System.Globalization if (value < 0 || value > 11) { throw new ArgumentOutOfRangeException( - "PercentNegativePattern", + nameof(PercentNegativePattern), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -593,7 +593,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("NegativeInfinitySymbol", + throw new ArgumentNullException(nameof(NegativeInfinitySymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -610,7 +610,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("NegativeSign", + throw new ArgumentNullException(nameof(NegativeSign), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -628,7 +628,7 @@ namespace System.Globalization if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "NumberDecimalDigits", + nameof(NumberDecimalDigits), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -648,7 +648,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyDecimalSeparator(value, "NumberDecimalSeparator"); + VerifyDecimalSeparator(value, nameof(NumberDecimalSeparator)); numberDecimalSeparator = value; } } @@ -660,7 +660,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyGroupSeparator(value, "NumberGroupSeparator"); + VerifyGroupSeparator(value, nameof(NumberGroupSeparator)); numberGroupSeparator = value; } } @@ -674,7 +674,7 @@ namespace System.Globalization if (value < 0 || value > 3) { throw new ArgumentOutOfRangeException( - "CurrencyPositivePattern", + nameof(CurrencyPositivePattern), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -698,7 +698,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("PositiveInfinitySymbol", + throw new ArgumentNullException(nameof(PositiveInfinitySymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -715,7 +715,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("PositiveSign", + throw new ArgumentNullException(nameof(PositiveSign), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -733,7 +733,7 @@ namespace System.Globalization if (value < 0 || value > 99) { throw new ArgumentOutOfRangeException( - "PercentDecimalDigits", + nameof(PercentDecimalDigits), String.Format( CultureInfo.CurrentCulture, SR.ArgumentOutOfRange_Range, @@ -753,7 +753,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyDecimalSeparator(value, "PercentDecimalSeparator"); + VerifyDecimalSeparator(value, nameof(PercentDecimalSeparator)); percentDecimalSeparator = value; } } @@ -765,7 +765,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyGroupSeparator(value, "PercentGroupSeparator"); + VerifyGroupSeparator(value, nameof(PercentGroupSeparator)); percentGroupSeparator = value; } } @@ -781,7 +781,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("PercentSymbol", + throw new ArgumentNullException(nameof(PercentSymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -798,7 +798,7 @@ namespace System.Globalization { if (value == null) { - throw new ArgumentNullException("PerMilleSymbol", + throw new ArgumentNullException(nameof(PerMilleSymbol), SR.ArgumentNull_String); } Contract.EndContractBlock(); @@ -813,7 +813,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyNativeDigits(value, "NativeDigits"); + VerifyNativeDigits(value, nameof(NativeDigits)); nativeDigits = value; } } @@ -824,7 +824,7 @@ namespace System.Globalization set { VerifyWritable(); - VerifyDigitSubstitution(value, "DigitSubstitution"); + VerifyDigitSubstitution(value, nameof(DigitSubstitution)); digitSubstitution = (int) value; } } diff --git a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs index 0645ded0ab..15679d24dd 100644 --- a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs @@ -87,7 +87,6 @@ namespace System.Globalization SetName(name); } - [System.Security.SecuritySafeCritical] // auto-generated public RegionInfo(int culture) { if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region @@ -132,7 +131,6 @@ namespace System.Globalization [OnSerializing] private void OnSerializing(StreamingContext ctx) { } - [System.Security.SecurityCritical] // auto-generated [OnDeserialized] private void OnDeserialized(StreamingContext ctx) { diff --git a/src/mscorlib/corefx/System/Globalization/SortKey.cs b/src/mscorlib/corefx/System/Globalization/SortKey.cs index fc151fa37e..9e22a6f332 100644 --- a/src/mscorlib/corefx/System/Globalization/SortKey.cs +++ b/src/mscorlib/corefx/System/Globalization/SortKey.cs @@ -19,7 +19,6 @@ namespace System.Globalization { using System.Diagnostics; using System.Diagnostics.Contracts; - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public partial class SortKey { diff --git a/src/mscorlib/corefx/System/Globalization/SortVersion.cs b/src/mscorlib/corefx/System/Globalization/SortVersion.cs index 72aa6d6b7b..983179c149 100644 --- a/src/mscorlib/corefx/System/Globalization/SortVersion.cs +++ b/src/mscorlib/corefx/System/Globalization/SortVersion.cs @@ -5,7 +5,7 @@ using System; using System.Diagnostics.Contracts; -namespace System.Globalization +namespace System.Globalization { [Serializable] public sealed class SortVersion : IEquatable @@ -13,48 +13,48 @@ namespace System.Globalization private int _nlsVersion; private Guid _sortId; - public int FullVersion + public int FullVersion { - get + get { return _nlsVersion; } } - public Guid SortId + public Guid SortId { - get + get { return _sortId; } } - public SortVersion(int fullVersion, Guid sortId) - { + public SortVersion(int fullVersion, Guid sortId) + { _sortId = sortId; _nlsVersion = fullVersion; } - internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion) + internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion) { _nlsVersion = nlsVersion; - if (customVersion == Guid.Empty) + if (customVersion == Guid.Empty) { - byte b1 = (byte) (effectiveId >> 24); - byte b2 = (byte) ((effectiveId & 0x00FF0000) >> 16); - byte b3 = (byte) ((effectiveId & 0x0000FF00) >> 8); - byte b4 = (byte) (effectiveId & 0xFF); - customVersion = new Guid(0,0,0,0,0,0,0,b1,b2,b3,b4); + byte b1 = (byte)(effectiveId >> 24); + byte b2 = (byte)((effectiveId & 0x00FF0000) >> 16); + byte b3 = (byte)((effectiveId & 0x0000FF00) >> 8); + byte b4 = (byte)(effectiveId & 0xFF); + customVersion = new Guid(0, 0, 0, 0, 0, 0, 0, b1, b2, b3, b4); } _sortId = customVersion; } - public override bool Equals(object obj) + public override bool Equals(object obj) { SortVersion n = obj as SortVersion; - if (n != null) + if (n != null) { return this.Equals(n); } @@ -62,9 +62,9 @@ namespace System.Globalization return false; } - public bool Equals(SortVersion other) + public bool Equals(SortVersion other) { - if (other == null) + if (other == null) { return false; } @@ -72,19 +72,19 @@ namespace System.Globalization return _nlsVersion == other._nlsVersion && _sortId == other._sortId; } - public override int GetHashCode() - { - return _nlsVersion * 7 | _sortId.GetHashCode(); + public override int GetHashCode() + { + return _nlsVersion * 7 | _sortId.GetHashCode(); } - public static bool operator ==(SortVersion left, SortVersion right) + public static bool operator ==(SortVersion left, SortVersion right) { - if (((object) left) != null) + if (((object)left) != null) { return left.Equals(right); } - if (((object) right) != null) + if (((object)right) != null) { return right.Equals(left); } @@ -93,7 +93,7 @@ namespace System.Globalization return true; } - public static bool operator !=(SortVersion left, SortVersion right) + public static bool operator !=(SortVersion left, SortVersion right) { return !(left == right); } diff --git a/src/mscorlib/corefx/System/Globalization/StringInfo.cs b/src/mscorlib/corefx/System/Globalization/StringInfo.cs index 7558002413..f1dd30561b 100644 --- a/src/mscorlib/corefx/System/Globalization/StringInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/StringInfo.cs @@ -20,7 +20,6 @@ using System.Runtime.Serialization; namespace System.Globalization { [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class StringInfo { [OptionalField(VersionAdded = 2)] @@ -53,7 +52,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override bool Equals(Object value) { StringInfo that = value as StringInfo; @@ -64,7 +62,6 @@ namespace System.Globalization return (false); } - [System.Runtime.InteropServices.ComVisible(false)] public override int GetHashCode() { return _str.GetHashCode(); diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs index 36edd5b2fd..2e735e0cb9 100644 --- a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs @@ -22,7 +22,6 @@ namespace System.Globalization ============================================================================*/ [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class TaiwanCalendar : Calendar { // @@ -65,7 +64,6 @@ namespace System.Globalization internal static readonly DateTime calendarMinValue = new DateTime(1912, 1, 1); - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -74,7 +72,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -83,7 +80,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -166,7 +162,6 @@ namespace System.Globalization [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - [System.Runtime.InteropServices.ComVisible(false)] public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) { return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); @@ -205,7 +200,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { return (helper.GetLeapMonth(year, era)); diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs index 42b7f2473b..1f75ac9a04 100644 --- a/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs @@ -264,9 +264,9 @@ namespace System.Globalization } } - internal override int GetYearInfo(int LunarYear, int Index) + internal override int GetYearInfo(int lunarYear, int index) { - if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) + if ((lunarYear < MIN_LUNISOLAR_YEAR) || (lunarYear > MAX_LUNISOLAR_YEAR)) { throw new ArgumentOutOfRangeException( "year", @@ -278,7 +278,7 @@ namespace System.Globalization } Contract.EndContractBlock(); - return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index]; + return s_yinfo[lunarYear - MIN_LUNISOLAR_YEAR, index]; } internal override int GetYear(int year, DateTime time) diff --git a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs index c0ffc65307..464897b03f 100644 --- a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs +++ b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs @@ -21,7 +21,6 @@ namespace System.Globalization // [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class TextElementEnumerator : IEnumerator { private String _str; diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs index 3d9b777f64..67836d89d6 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs +++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs @@ -33,7 +33,6 @@ namespace System.Globalization { } - [SecuritySafeCritical] private unsafe string ChangeCase(string s, bool toUpper) { Debug.Assert(s != null); @@ -78,7 +77,6 @@ namespace System.Globalization return result; } - [SecuritySafeCritical] private unsafe char ChangeCase(char c, bool toUpper) { char dst = default(char); diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.cs index 5bb376f19c..172bbd25b2 100644 --- a/src/mscorlib/corefx/System/Globalization/TextInfo.cs +++ b/src/mscorlib/corefx/System/Globalization/TextInfo.cs @@ -188,7 +188,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public int LCID { get @@ -220,7 +219,6 @@ namespace System.Globalization // Detect if the object is readonly. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public bool IsReadOnly { get { return (_isReadOnly); } @@ -248,7 +246,6 @@ namespace System.Globalization // readonly. // //////////////////////////////////////////////////////////////////////// - [System.Runtime.InteropServices.ComVisible(false)] public static TextInfo ReadOnly(TextInfo textInfo) { if (textInfo == null) { throw new ArgumentNullException(nameof(textInfo)); } diff --git a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs index 8ebbfa0a69..9e6e30406c 100644 --- a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs @@ -21,7 +21,6 @@ namespace System.Globalization ============================================================================*/ [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public class ThaiBuddhistCalendar : Calendar { // Initialize our era info. @@ -38,7 +37,6 @@ namespace System.Globalization internal GregorianCalendarHelper helper; - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MinSupportedDateTime { get @@ -47,7 +45,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override DateTime MaxSupportedDateTime { get @@ -56,7 +53,6 @@ namespace System.Globalization } } - [System.Runtime.InteropServices.ComVisible(false)] public override CalendarAlgorithmType AlgorithmType { get @@ -128,7 +124,6 @@ namespace System.Globalization [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - [System.Runtime.InteropServices.ComVisible(false)] public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) { return (helper.GetWeekOfYear(time, rule, firstDayOfWeek)); @@ -167,7 +162,6 @@ namespace System.Globalization // if this calendar does not have leap month, or this year is not a leap year. // - [System.Runtime.InteropServices.ComVisible(false)] public override int GetLeapMonth(int year, int era) { return (helper.GetLeapMonth(year, era)); diff --git a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs index 997c5f2316..7b47d9c02b 100644 --- a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs +++ b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs @@ -41,7 +41,7 @@ namespace System.Globalization private static DateMapping[] InitDateMapping() { - short[] rawData = new short[] + short[] rawData = new short[] { //These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 diff --git a/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs b/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs deleted file mode 100644 index dc1385fbc0..0000000000 --- a/src/mscorlib/corefx/System/IO/FileStream.NetStandard17.cs +++ /dev/null @@ -1,76 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using Microsoft.Win32.SafeHandles; -using System.Threading.Tasks; -using System.Diagnostics; -using System.Threading; - -namespace System.IO -{ - public partial class FileStream : Stream - { - public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) - { - if (array == null) - throw new ArgumentNullException(nameof(array)); - if (offset < 0) - throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); - if (numBytes < 0) - throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); - if (array.Length - offset < numBytes) - throw new ArgumentException(SR.Argument_InvalidOffLen); - - if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); - if (!CanRead) throw new NotSupportedException(SR.NotSupported_UnreadableStream); - - if (!IsAsync) - return base.BeginRead(array, offset, numBytes, callback, state); - else - return TaskToApm.Begin(ReadAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); - } - - public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) - { - if (array == null) - throw new ArgumentNullException(nameof(array)); - if (offset < 0) - throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); - if (numBytes < 0) - throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); - if (array.Length - offset < numBytes) - throw new ArgumentException(SR.Argument_InvalidOffLen); - - if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); - if (!CanWrite) throw new NotSupportedException(SR.NotSupported_UnwritableStream); - - if (!IsAsync) - return base.BeginWrite(array, offset, numBytes, callback, state); - else - return TaskToApm.Begin(WriteAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); - } - - public override int EndRead(IAsyncResult asyncResult) - { - if (asyncResult == null) - throw new ArgumentNullException(nameof(asyncResult)); - - if (!IsAsync) - return base.EndRead(asyncResult); - else - return TaskToApm.End(asyncResult); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - if (asyncResult == null) - throw new ArgumentNullException(nameof(asyncResult)); - - if (!IsAsync) - base.EndWrite(asyncResult); - else - TaskToApm.End(asyncResult); - } - } -} diff --git a/src/mscorlib/corefx/System/IO/FileStream.Win32.cs b/src/mscorlib/corefx/System/IO/FileStream.Win32.cs index 350d948b00..683eef5e43 100644 --- a/src/mscorlib/corefx/System/IO/FileStream.Win32.cs +++ b/src/mscorlib/corefx/System/IO/FileStream.Win32.cs @@ -55,7 +55,7 @@ namespace System.IO private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options) { - Interop.mincore.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); + Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int fAccess = ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | @@ -74,13 +74,13 @@ namespace System.IO // For mitigating local elevation of privilege attack through named pipes // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context - flagsAndAttributes |= (Interop.mincore.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.mincore.SecurityOptions.SECURITY_ANONYMOUS); + flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS); // Don't pop up a dialog for reading from an empty floppy drive - uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); + uint oldMode = Interop.Kernel32.SetErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS); try { - SafeFileHandle fileHandle = Interop.mincore.SafeCreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); + SafeFileHandle fileHandle = Interop.Kernel32.SafeCreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); fileHandle.IsAsync = _useAsyncIO; if (fileHandle.IsInvalid) @@ -92,8 +92,8 @@ namespace System.IO // probably be consistent w/ every other directory. int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && _path.Equals(Directory.InternalGetDirectoryRoot(_path))) - errorCode = Interop.mincore.Errors.ERROR_ACCESS_DENIED; + if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND && _path.Equals(Directory.InternalGetDirectoryRoot(_path))) + errorCode = Interop.Errors.ERROR_ACCESS_DENIED; throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path); } @@ -102,7 +102,7 @@ namespace System.IO } finally { - Interop.mincore.SetErrorMode(oldMode); + Interop.Kernel32.SetErrorMode(oldMode); } } @@ -112,8 +112,8 @@ namespace System.IO // constructors that take a String. Everyone else can call // CreateFile themselves then use the constructor that takes an // IntPtr. Disallows "con:", "com1:", "lpt1:", etc. - int fileType = Interop.mincore.GetFileType(_fileHandle); - if (fileType != Interop.mincore.FileTypes.FILE_TYPE_DISK) + int fileType = Interop.Kernel32.GetFileType(_fileHandle); + if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK) { _fileHandle.Dispose(); throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles); @@ -163,11 +163,11 @@ namespace System.IO private void InitFromHandle(SafeFileHandle handle) { - int handleType = Interop.mincore.GetFileType(_fileHandle); - Debug.Assert(handleType == Interop.mincore.FileTypes.FILE_TYPE_DISK || handleType == Interop.mincore.FileTypes.FILE_TYPE_PIPE || handleType == Interop.mincore.FileTypes.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); + int handleType = Interop.Kernel32.GetFileType(_fileHandle); + Debug.Assert(handleType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK || handleType == Interop.Kernel32.FileTypes.FILE_TYPE_PIPE || handleType == Interop.Kernel32.FileTypes.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!"); - _canSeek = handleType == Interop.mincore.FileTypes.FILE_TYPE_DISK; - _isPipe = handleType == Interop.mincore.FileTypes.FILE_TYPE_PIPE; + _canSeek = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK; + _isPipe = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_PIPE; // This is necessary for async IO using IO Completion ports via our // managed Threadpool API's. This calls the OS's @@ -196,7 +196,7 @@ namespace System.IO } else if (!_useAsyncIO) { - if (handleType != Interop.mincore.FileTypes.FILE_TYPE_PIPE) + if (handleType != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE) VerifyHandleIsSync(); } @@ -211,13 +211,13 @@ namespace System.IO return handle.IsAsync.HasValue ? handle.IsAsync.Value : false; } - private unsafe static Interop.mincore.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) + private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share) { - Interop.mincore.SECURITY_ATTRIBUTES secAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); + Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES); if ((share & FileShare.Inheritable) != 0) { - secAttrs = new Interop.mincore.SECURITY_ATTRIBUTES(); - secAttrs.nLength = (uint)sizeof(Interop.mincore.SECURITY_ATTRIBUTES); + secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES(); + secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES); secAttrs.bInheritHandle = Interop.BOOL.TRUE; } @@ -234,7 +234,7 @@ namespace System.IO // cause an app to block incorrectly, introducing a deadlock (depending // on whether a write will wake up an already-blocked thread or this // Win32FileStream's thread). - Debug.Assert(Interop.mincore.GetFileType(_fileHandle) != Interop.mincore.FileTypes.FILE_TYPE_PIPE); + Debug.Assert(Interop.Kernel32.GetFileType(_fileHandle) != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE); byte* bytes = stackalloc byte[1]; int numBytesReadWritten; @@ -246,11 +246,11 @@ namespace System.IO // accidentally read synchronously from an async pipe. if ((_access & FileAccess.Read) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor { - r = Interop.mincore.ReadFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); + r = Interop.Kernel32.ReadFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); } else if ((_access & FileAccess.Write) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor { - r = Interop.mincore.WriteFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); + r = Interop.Kernel32.WriteFile(_fileHandle, bytes, 0, out numBytesReadWritten, IntPtr.Zero); } if (r == 0) @@ -273,9 +273,9 @@ namespace System.IO private long GetLengthInternal() { - Interop.mincore.FILE_STANDARD_INFO info = new Interop.mincore.FILE_STANDARD_INFO(); + Interop.Kernel32.FILE_STANDARD_INFO info = new Interop.Kernel32.FILE_STANDARD_INFO(); - if (!Interop.mincore.GetFileInformationByHandleEx(_fileHandle, Interop.mincore.FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, out info, (uint)Marshal.SizeOf())) + if (!Interop.Kernel32.GetFileInformationByHandleEx(_fileHandle, Interop.Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, out info, (uint)Marshal.SizeOf())) throw Win32Marshal.GetExceptionForLastWin32Error(); long len = info.EndOfFile; // If we're writing near the end of the file, we must include our @@ -334,7 +334,7 @@ namespace System.IO private void FlushOSBuffer() { - if (!Interop.mincore.FlushFileBuffers(_fileHandle)) + if (!Interop.Kernel32.FlushFileBuffers(_fileHandle)) { throw Win32Marshal.GetExceptionForLastWin32Error(); } @@ -426,10 +426,10 @@ namespace System.IO VerifyOSHandlePosition(); if (_filePosition != value) SeekCore(value, SeekOrigin.Begin); - if (!Interop.mincore.SetEndOfFile(_fileHandle)) + if (!Interop.Kernel32.SetEndOfFile(_fileHandle)) { int errorCode = Marshal.GetLastWin32Error(); - if (errorCode == Interop.mincore.Errors.ERROR_INVALID_PARAMETER) + if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER) throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_FileLengthTooBig); throw Win32Marshal.GetExceptionForWin32Error(errorCode); } @@ -658,7 +658,7 @@ namespace System.IO Debug.Assert(origin >= SeekOrigin.Begin && origin <= SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End"); long ret = 0; - if (!Interop.mincore.SetFilePointerEx(_fileHandle, offset, out ret, (uint)origin)) + if (!Interop.Kernel32.SetFilePointerEx(_fileHandle, offset, out ret, (uint)origin)) { int errorCode = GetLastWin32ErrorAndDisposeHandleIfInvalid(); throw Win32Marshal.GetExceptionForWin32Error(errorCode); @@ -1277,12 +1277,12 @@ namespace System.IO int r = 0; int numBytesRead = 0; - fixed (byte* p = bytes) + fixed (byte* p = &bytes[0]) { if (_useAsyncIO) - r = Interop.mincore.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); + r = Interop.Kernel32.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped); else - r = Interop.mincore.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero); + r = Interop.Kernel32.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero); } if (r == 0) @@ -1322,12 +1322,12 @@ namespace System.IO int numBytesWritten = 0; int r = 0; - fixed (byte* p = bytes) + fixed (byte* p = &bytes[0]) { if (_useAsyncIO) - r = Interop.mincore.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped); + r = Interop.Kernel32.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped); else - r = Interop.mincore.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); + r = Interop.Kernel32.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero); } if (r == 0) @@ -1363,7 +1363,7 @@ namespace System.IO // Note that _parent.Dispose doesn't throw so we don't need to special case. // SetHandleAsInvalid only sets _closed field to true (without // actually closing handle) so we don't need to call that as well. - if (errorCode == Interop.mincore.Errors.ERROR_INVALID_HANDLE) + if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE) { _fileHandle.Dispose(); @@ -1473,7 +1473,7 @@ namespace System.IO { // Try to cancel the I/O. We ignore the return value, as cancellation is opportunistic and we // don't want to fail the operation because we couldn't cancel it. - Interop.mincore.CancelIoEx(innerAwaitable._fileStream._fileHandle, innerAwaitable._nativeOverlapped); + Interop.Kernel32.CancelIoEx(innerAwaitable._fileStream._fileHandle, innerAwaitable._nativeOverlapped); } } } @@ -1538,7 +1538,7 @@ namespace System.IO case ERROR_HANDLE_EOF: // logically success with 0 bytes read (read at end of file) Debug.Assert(readAwaitable._numBytes == 0, $"Expected 0 bytes read, got {readAwaitable._numBytes}"); break; - case Interop.mincore.Errors.ERROR_OPERATION_ABORTED: // canceled + case Interop.Errors.ERROR_OPERATION_ABORTED: // canceled throw new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)); default: // error throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode); @@ -1748,7 +1748,7 @@ namespace System.IO int lengthLow = unchecked((int)(length)); int lengthHigh = unchecked((int)(length >> 32)); - if (!Interop.mincore.LockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) + if (!Interop.Kernel32.LockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) { throw Win32Marshal.GetExceptionForLastWin32Error(); } @@ -1761,7 +1761,7 @@ namespace System.IO int lengthLow = unchecked((int)(length)); int lengthHigh = unchecked((int)(length >> 32)); - if (!Interop.mincore.UnlockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) + if (!Interop.Kernel32.UnlockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh)) { throw Win32Marshal.GetExceptionForLastWin32Error(); } diff --git a/src/mscorlib/corefx/System/IO/FileStream.cs b/src/mscorlib/corefx/System/IO/FileStream.cs index 398f5a6162..7db8518435 100644 --- a/src/mscorlib/corefx/System/IO/FileStream.cs +++ b/src/mscorlib/corefx/System/IO/FileStream.cs @@ -139,20 +139,6 @@ namespace System.IO this(path, mode, access, share, bufferSize, useAsync ? FileOptions.Asynchronous : FileOptions.None) { } - internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy) - : this(path, mode, access, share, bufferSize, options, msgPath, bFromProxy, useLongPath: false) - { - } - - internal FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, string msgPath, bool bFromProxy, bool useLongPath) - : this(path, mode, access, share, bufferSize, options) - { - // msgPath is the path that is handed back to untrusted code, CoreCLR is always full trust - // bFromProxy is also related to asserting rights for limited trust and also can be ignored - // useLongPath was used to get around the legacy MaxPath check, this is no longer applicable as everything supports long paths - // checkHost is also related to limited trust scenarios - } - public FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) { if (path == null) @@ -225,24 +211,6 @@ namespace System.IO return handle.IsAsync.HasValue ? handle.IsAsync.Value : false; } - // InternalOpen, InternalCreate, and InternalAppend: - // Factory methods for FileStream used by File, FileInfo, and ReadLinesIterator - // Specifies default access and sharing options for FileStreams created by those classes - internal static FileStream InternalOpen(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) - { - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize, useAsync); - } - - internal static FileStream InternalCreate(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) - { - return new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, bufferSize, useAsync); - } - - internal static FileStream InternalAppend(string path, int bufferSize = DefaultBufferSize, bool useAsync = DefaultIsAsync) - { - return new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read, bufferSize, useAsync); - } - [Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")] public virtual IntPtr Handle { get { return SafeFileHandle.DangerousGetHandle(); } } @@ -650,5 +618,67 @@ namespace System.IO // on Dispose(false) call. Dispose(false); } + + public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (numBytes < 0) + throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); + if (array.Length - offset < numBytes) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); + if (!CanRead) throw new NotSupportedException(SR.NotSupported_UnreadableStream); + + if (!IsAsync) + return base.BeginRead(array, offset, numBytes, callback, state); + else + return TaskToApm.Begin(ReadAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); + } + + public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback callback, object state) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (offset < 0) + throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_NeedNonNegNum); + if (numBytes < 0) + throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_NeedNonNegNum); + if (array.Length - offset < numBytes) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + if (IsClosed) throw new ObjectDisposedException(SR.ObjectDisposed_FileClosed); + if (!CanWrite) throw new NotSupportedException(SR.NotSupported_UnwritableStream); + + if (!IsAsync) + return base.BeginWrite(array, offset, numBytes, callback, state); + else + return TaskToApm.Begin(WriteAsyncInternal(array, offset, numBytes, CancellationToken.None), callback, state); + } + + public override int EndRead(IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException(nameof(asyncResult)); + + if (!IsAsync) + return base.EndRead(asyncResult); + else + return TaskToApm.End(asyncResult); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + if (asyncResult == null) + throw new ArgumentNullException(nameof(asyncResult)); + + if (!IsAsync) + base.EndWrite(asyncResult); + else + TaskToApm.End(asyncResult); + } } } diff --git a/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs b/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs index 532dbb0615..159e416e63 100644 --- a/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs +++ b/src/mscorlib/corefx/System/IO/FileStreamCompletionSource.Win32.cs @@ -178,7 +178,7 @@ namespace System.IO if (result == ResultError) { int errorCode = unchecked((int)(packedResult & uint.MaxValue)); - if (errorCode == Interop.mincore.Errors.ERROR_OPERATION_ABORTED) + if (errorCode == Interop.Errors.ERROR_OPERATION_ABORTED) { TrySetCanceled(_cancellationToken.IsCancellationRequested ? _cancellationToken : new CancellationToken(true)); } @@ -204,13 +204,13 @@ namespace System.IO // If the handle is still valid, attempt to cancel the IO if (!completionSource._stream._fileHandle.IsInvalid && - !Interop.mincore.CancelIoEx(completionSource._stream._fileHandle, completionSource._overlapped)) + !Interop.Kernel32.CancelIoEx(completionSource._stream._fileHandle, completionSource._overlapped)) { int errorCode = Marshal.GetLastWin32Error(); // ERROR_NOT_FOUND is returned if CancelIoEx cannot find the request to cancel. // This probably means that the IO operation has completed. - if (errorCode != Interop.mincore.Errors.ERROR_NOT_FOUND) + if (errorCode != Interop.Errors.ERROR_NOT_FOUND) { throw Win32Marshal.GetExceptionForWin32Error(errorCode); } diff --git a/src/mscorlib/corefx/System/IO/Path.Unix.cs b/src/mscorlib/corefx/System/IO/Path.Unix.cs index 2dd1907007..c566fa0066 100644 --- a/src/mscorlib/corefx/System/IO/Path.Unix.cs +++ b/src/mscorlib/corefx/System/IO/Path.Unix.cs @@ -10,16 +10,11 @@ namespace System.IO { public static partial class Path { - public static readonly char DirectorySeparatorChar = '/'; - public static readonly char VolumeSeparatorChar = '/'; - public static readonly char PathSeparator = ':'; - - private const string DirectorySeparatorCharAsString = "/"; - public static char[] GetInvalidFileNameChars() => new char[] { '\0', '/' }; - internal static readonly int MaxPath = Interop.Sys.MaxPath; - private static readonly int MaxLongPath = MaxPath; + public static char[] GetInvalidPathChars() => new char[] { '\0' }; + + internal static int MaxPath => Interop.Sys.MaxPath; private static readonly bool s_isMac = Interop.Sys.GetUnixName() == "OSX"; @@ -47,12 +42,12 @@ namespace System.IO Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path, "Either we've removed characters, or the string should be unmodified from the input path."); - if (collapsedString.Length > MaxPath) + if (collapsedString.Length > Interop.Sys.MaxPath) { throw new PathTooLongException(SR.IO_PathTooLong); } - string result = collapsedString.Length == 0 ? DirectorySeparatorCharAsString : collapsedString; + string result = collapsedString.Length == 0 ? PathInternal.DirectorySeparatorCharAsString : collapsedString; return result; } @@ -125,15 +120,15 @@ namespace System.IO } } - if (++componentCharCount > PathInternal.MaxComponentLength) + if (++componentCharCount > Interop.Sys.MaxName) { throw new PathTooLongException(SR.IO_PathTooLong); } // Normalize the directory separator if needed - if (c != Path.DirectorySeparatorChar && c == Path.AltDirectorySeparatorChar) + if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar) { - c = Path.DirectorySeparatorChar; + c = PathInternal.DirectorySeparatorChar; flippedSeparator = true; } @@ -169,7 +164,7 @@ namespace System.IO return string.IsNullOrEmpty(path) ? DefaultTempPath : PathInternal.IsDirectorySeparator(path[path.Length - 1]) ? path : - path + DirectorySeparatorChar; + path + PathInternal.DirectorySeparatorChar; } public static string GetTempFileName() @@ -197,58 +192,23 @@ namespace System.IO return false; PathInternal.CheckInvalidPathChars(path); - return path.Length > 0 && path[0] == DirectorySeparatorChar; + return path.Length > 0 && path[0] == PathInternal.DirectorySeparatorChar; } public static string GetPathRoot(string path) { if (path == null) return null; - return IsPathRooted(path) ? DirectorySeparatorCharAsString : String.Empty; + return IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString : String.Empty; } private static unsafe void GetCryptoRandomBytes(byte* bytes, int byteCount) { -#if FEATURE_CORECLR // We want to avoid dependencies on the Crypto library when compiling in CoreCLR. This // will use the existing PAL implementation. byte[] buffer = new byte[KeyLength]; Microsoft.Win32.Win32Native.Random(bStrong: true, buffer: buffer, length: KeyLength); Runtime.InteropServices.Marshal.Copy(buffer, 0, (IntPtr)bytes, KeyLength); -#else - if (s_isMac) - { - GetCryptoRandomBytesApple(bytes, byteCount); - } - else - { - GetCryptoRandomBytesOpenSsl(bytes, byteCount); - } -#endif - } - -#if !FEATURE_CORECLR - private static unsafe void GetCryptoRandomBytesApple(byte* bytes, int byteCount) - { - Debug.Assert(bytes != null); - Debug.Assert(byteCount >= 0); - - if (Interop.CommonCrypto.CCRandomGenerateBytes(bytes, byteCount) != 0) - { - throw new InvalidOperationException(SR.InvalidOperation_Cryptography); - } - } - - private static unsafe void GetCryptoRandomBytesOpenSsl(byte* bytes, int byteCount) - { - Debug.Assert(bytes != null); - Debug.Assert(byteCount >= 0); - - if (!Interop.Crypto.GetRandomBytes(bytes, byteCount)) - { - throw new InvalidOperationException(SR.InvalidOperation_Cryptography); - } } -#endif /// Gets whether the system is case-sensitive. internal static bool IsCaseSensitive { get { return !s_isMac; } } diff --git a/src/mscorlib/corefx/System/IO/Path.Windows.cs b/src/mscorlib/corefx/System/IO/Path.Windows.cs index b597efc54e..ce867efd2c 100644 --- a/src/mscorlib/corefx/System/IO/Path.Windows.cs +++ b/src/mscorlib/corefx/System/IO/Path.Windows.cs @@ -9,14 +9,8 @@ namespace System.IO { public static partial class Path { - public static readonly char DirectorySeparatorChar = '\\'; - public static readonly char VolumeSeparatorChar = ':'; - public static readonly char PathSeparator = ';'; - - private const string DirectorySeparatorCharAsString = "\\"; - public static char[] GetInvalidFileNameChars() => new char[] - { + { '\"', '<', '>', '|', '\0', (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, @@ -24,10 +18,18 @@ namespace System.IO (char)31, ':', '*', '?', '\\', '/' }; + public static char[] GetInvalidPathChars() => new char[] + { + '|', '\0', + (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, + (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, + (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, + (char)31 + }; + // The max total path is 260, and the max individual component length is 255. // For example, D:\<256 char file name> isn't legal, even though it's under 260 chars. - internal static readonly int MaxPath = 260; - internal static readonly int MaxLongPath = short.MaxValue; + internal const int MaxPath = 260; // Expands the given path to a fully qualified path. public static string GetFullPath(string path) @@ -64,9 +66,9 @@ namespace System.IO // Move past the colon startIndex += 2; - if ((path.Length > 0 && path[0] == VolumeSeparatorChar) - || (path.Length >= startIndex && path[startIndex - 1] == VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) - || (path.Length > startIndex && path.IndexOf(VolumeSeparatorChar, startIndex) != -1)) + if ((path.Length > 0 && path[0] == PathInternal.VolumeSeparatorChar) + || (path.Length >= startIndex && path[startIndex - 1] == PathInternal.VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) + || (path.Length > startIndex && path.IndexOf(PathInternal.VolumeSeparatorChar, startIndex) != -1)) { throw new NotSupportedException(SR.Argument_PathFormatNotSupported); } @@ -92,7 +94,7 @@ namespace System.IO public static string GetTempPath() { StringBuilder sb = StringBuilderCache.Acquire(MaxPath); - uint r = Interop.mincore.GetTempPathW(MaxPath, sb); + uint r = Interop.Kernel32.GetTempPathW(MaxPath, sb); if (r == 0) throw Win32Marshal.GetExceptionForLastWin32Error(); return GetFullPath(StringBuilderCache.GetStringAndRelease(sb)); @@ -105,7 +107,7 @@ namespace System.IO string path = GetTempPath(); StringBuilder sb = StringBuilderCache.Acquire(MaxPath); - uint r = Interop.mincore.GetTempFileNameW(path, "tmp", 0, sb); + uint r = Interop.Kernel32.GetTempFileNameW(path, "tmp", 0, sb); if (r == 0) throw Win32Marshal.GetExceptionForLastWin32Error(); return StringBuilderCache.GetStringAndRelease(sb); @@ -121,7 +123,7 @@ namespace System.IO int length = path.Length; if ((length >= 1 && PathInternal.IsDirectorySeparator(path[0])) || - (length >= 2 && path[1] == VolumeSeparatorChar)) + (length >= 2 && path[1] == PathInternal.VolumeSeparatorChar)) return true; } return false; diff --git a/src/mscorlib/corefx/System/IO/Path.cs b/src/mscorlib/corefx/System/IO/Path.cs index 3b1ba6b07d..77b213968b 100644 --- a/src/mscorlib/corefx/System/IO/Path.cs +++ b/src/mscorlib/corefx/System/IO/Path.cs @@ -13,10 +13,12 @@ namespace System.IO // but they will handle most string operations. public static partial class Path { - // Platform specific alternate directory separator character. - // There is only one directory separator char on Unix, which is the same - // as the alternate separator on Windows, so same definition is used for both. - public static readonly char AltDirectorySeparatorChar = '/'; + // Public static readonly variant of the separators. The Path implementation itself is using + // internal const variant of the separators for better performance. + public static readonly char DirectorySeparatorChar = PathInternal.DirectorySeparatorChar; + public static readonly char AltDirectorySeparatorChar = PathInternal.AltDirectorySeparatorChar; + public static readonly char VolumeSeparatorChar = PathInternal.VolumeSeparatorChar; + public static readonly char PathSeparator = PathInternal.PathSeparator; // For generating random file names // 8 random bytes provides 12 chars in our encoding for the 8.3 name. @@ -90,11 +92,6 @@ namespace System.IO return null; } - public static char[] GetInvalidPathChars() - { - return PathInternal.GetInvalidPathChars(); - } - // Returns the extension of the given path. The returned value includes the // period (".") character of the extension except when you have a terminal period when you get string.Empty, such as ".exe" or // ".cpp". The returned value is null if the given path is @@ -290,7 +287,7 @@ namespace System.IO char ch = finalPath[finalPath.Length - 1]; if (!PathInternal.IsDirectoryOrVolumeSeparator(ch)) { - finalPath.Append(DirectorySeparatorChar); + finalPath.Append(PathInternal.DirectorySeparatorChar); } finalPath.Append(paths[i]); @@ -314,7 +311,7 @@ namespace System.IO char ch = path1[path1.Length - 1]; return PathInternal.IsDirectoryOrVolumeSeparator(ch) ? path1 + path2 : - path1 + DirectorySeparatorCharAsString + path2; + path1 + PathInternal.DirectorySeparatorCharAsString + path2; } private static string CombineNoChecks(string path1, string path2, string path3) @@ -340,11 +337,11 @@ namespace System.IO } else if (hasSep1) { - return path1 + path2 + DirectorySeparatorCharAsString + path3; + return path1 + path2 + PathInternal.DirectorySeparatorCharAsString + path3; } else if (hasSep2) { - return path1 + DirectorySeparatorCharAsString + path2 + path3; + return path1 + PathInternal.DirectorySeparatorCharAsString + path2 + path3; } else { @@ -352,9 +349,9 @@ namespace System.IO // a params string[]. Instead, try to use a cached StringBuilder. StringBuilder sb = StringBuilderCache.Acquire(path1.Length + path2.Length + path3.Length + 2); sb.Append(path1) - .Append(DirectorySeparatorChar) + .Append(PathInternal.DirectorySeparatorChar) .Append(path2) - .Append(DirectorySeparatorChar) + .Append(PathInternal.DirectorySeparatorChar) .Append(path3); return StringBuilderCache.GetStringAndRelease(sb); } @@ -396,19 +393,19 @@ namespace System.IO sb.Append(path1); if (!hasSep1) { - sb.Append(DirectorySeparatorChar); + sb.Append(PathInternal.DirectorySeparatorChar); } sb.Append(path2); if (!hasSep2) { - sb.Append(DirectorySeparatorChar); + sb.Append(PathInternal.DirectorySeparatorChar); } sb.Append(path3); if (!hasSep3) { - sb.Append(DirectorySeparatorChar); + sb.Append(PathInternal.DirectorySeparatorChar); } sb.Append(path4); diff --git a/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs b/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs index 4c2cdff45e..e2ead93185 100644 --- a/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs +++ b/src/mscorlib/corefx/System/IO/PathHelper.Windows.cs @@ -11,7 +11,7 @@ namespace System.IO /// /// Wrapper to help with path normalization. /// - unsafe internal class PathHelper + internal class PathHelper { // Can't be over 8.3 and be a short name private const int MaxShortName = 12; @@ -19,9 +19,6 @@ namespace System.IO private const char LastAnsi = (char)255; private const char Delete = (char)127; - [ThreadStatic] - private static StringBuffer t_fullPathBuffer; - /// /// Normalize the given path. /// @@ -44,10 +41,11 @@ namespace System.IO internal static string Normalize(string path, bool checkInvalidCharacters, bool expandShortPaths) { // Get the full path - StringBuffer fullPath = t_fullPathBuffer ?? (t_fullPathBuffer = new StringBuffer(PathInternal.MaxShortPath)); + StringBuffer fullPath = new StringBuffer(PathInternal.MaxShortPath); + try { - GetFullPathName(path, fullPath); + GetFullPathName(path, ref fullPath); // Trim whitespace off the end of the string. Win32 normalization trims only U+0020. fullPath.TrimEnd(PathInternal.s_trimEndChars); @@ -82,17 +80,16 @@ namespace System.IO // path that contains UNC or to see if the path was doing something like \\.\GLOBALROOT\Device\Mup\, // \\.\GLOBAL\UNC\, \\.\GLOBALROOT\GLOBAL??\UNC\, etc. bool specialPath = fullPath.Length > 1 && fullPath[0] == '\\' && fullPath[1] == '\\'; - bool isDevice = PathInternal.IsDevice(fullPath); + bool isDevice = PathInternal.IsDevice(ref fullPath); bool possibleBadUnc = specialPath && !isDevice; - uint index = specialPath ? 2u : 0; - uint lastSeparator = specialPath ? 1u : 0; - uint segmentLength; - char* start = fullPath.CharPointer; + int index = specialPath ? 2 : 0; + int lastSeparator = specialPath ? 1 : 0; + int segmentLength; char current; while (index < fullPath.Length) { - current = start[index]; + current = fullPath[index]; // Try to skip deeper analysis. '?' and higher are valid/ignorable except for '\', '|', and '~' if (current < '?' || current == '\\' || current == '|' || current == '~') @@ -111,7 +108,7 @@ namespace System.IO break; case '\\': segmentLength = index - lastSeparator - 1; - if (segmentLength > (uint)PathInternal.MaxComponentLength) + if (segmentLength > PathInternal.MaxComponentLength) throw new PathTooLongException(SR.IO_PathTooLong + fullPath.ToString()); lastSeparator = index; @@ -151,7 +148,7 @@ namespace System.IO throw new ArgumentException(SR.Arg_PathIllegalUNC); segmentLength = fullPath.Length - lastSeparator - 1; - if (segmentLength > (uint)PathInternal.MaxComponentLength) + if (segmentLength > PathInternal.MaxComponentLength) throw new PathTooLongException(SR.IO_PathTooLong); if (foundTilde && segmentLength <= MaxShortName) @@ -161,11 +158,11 @@ namespace System.IO // this is how we've always done this. This expansion is costly so we'll continue to let other short paths slide. if (expandShortPaths && possibleShortPath) { - return TryExpandShortFileName(fullPath, originalPath: path); + return TryExpandShortFileName(ref fullPath, originalPath: path); } else { - if (fullPath.Length == (uint)path.Length && fullPath.StartsWith(path)) + if (fullPath.Length == path.Length && fullPath.StartsWith(path)) { // If we have the exact same string we were passed in, don't bother to allocate another string from the StringBuilder. return path; @@ -184,12 +181,12 @@ namespace System.IO } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsDosUnc(StringBuffer buffer) + private static bool IsDosUnc(ref StringBuffer buffer) { - return !PathInternal.IsDevice(buffer) && buffer.Length > 1 && buffer[0] == '\\' && buffer[1] == '\\'; + return !PathInternal.IsDevice(ref buffer) && buffer.Length > 1 && buffer[0] == '\\' && buffer[1] == '\\'; } - private static void GetFullPathName(string path, StringBuffer fullPath) + private static unsafe void GetFullPathName(string path, ref StringBuffer fullPath) { // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. @@ -201,10 +198,10 @@ namespace System.IO fixed (char* pathStart = path) { uint result = 0; - while ((result = Interop.mincore.GetFullPathNameW(pathStart + startIndex, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity) + while ((result = Interop.Kernel32.GetFullPathNameW(pathStart + startIndex, (uint)fullPath.Capacity, fullPath.UnderlyingArray, IntPtr.Zero)) > fullPath.Capacity) { - // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. - fullPath.EnsureCharCapacity(result); + // Reported size is greater than the buffer size. Increase the capacity. + fullPath.EnsureCapacity(checked((int)result)); } if (result == 0) @@ -212,23 +209,23 @@ namespace System.IO // Failure, get the error and throw int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0) - errorCode = Interop.mincore.Errors.ERROR_BAD_PATHNAME; + errorCode = Interop.Errors.ERROR_BAD_PATHNAME; throw Win32Marshal.GetExceptionForWin32Error(errorCode, path); } - fullPath.Length = result; + fullPath.Length = checked((int)result); } } - private static uint GetInputBuffer(StringBuffer content, bool isDosUnc, out StringBuffer buffer) + private static int GetInputBuffer(ref StringBuffer content, bool isDosUnc, ref StringBuffer buffer) { - uint length = content.Length; + int length = content.Length; length += isDosUnc - ? (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength + ? PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength : PathInternal.DevicePrefixLength; - buffer = new StringBuffer(length); + buffer.EnsureCapacity(length + 1); if (isDosUnc) { @@ -238,28 +235,28 @@ namespace System.IO // Copy the source buffer over after the existing UNC prefix content.CopyTo( bufferIndex: PathInternal.UncPrefixLength, - destination: buffer, + destination: ref buffer, destinationIndex: PathInternal.UncExtendedPrefixLength, count: content.Length - PathInternal.UncPrefixLength); // Return the prefix difference - return (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength; + return PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength; } else { - uint prefixSize = (uint)PathInternal.ExtendedPathPrefix.Length; + int prefixSize = PathInternal.ExtendedPathPrefix.Length; buffer.CopyFrom(bufferIndex: 0, source: PathInternal.ExtendedPathPrefix); - content.CopyTo(bufferIndex: 0, destination: buffer, destinationIndex: prefixSize, count: content.Length); + content.CopyTo(bufferIndex: 0, destination: ref buffer, destinationIndex: prefixSize, count: content.Length); return prefixSize; } } - private static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath) + private static string TryExpandShortFileName(ref StringBuffer outputBuffer, string originalPath) { // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls. - Debug.Assert(!PathInternal.IsPartiallyQualified(outputBuffer), "should have resolved by now"); + Debug.Assert(!PathInternal.IsPartiallyQualified(ref outputBuffer), "should have resolved by now"); // We'll have one of a few cases by now (the normalized path will have already: // @@ -271,119 +268,131 @@ namespace System.IO // // Note that we will never get \??\ here as GetFullPathName() does not recognize \??\ and will return it as C:\??\ (or whatever the current drive is). - uint rootLength = PathInternal.GetRootLength(outputBuffer); - bool isDevice = PathInternal.IsDevice(outputBuffer); + int rootLength = PathInternal.GetRootLength(ref outputBuffer); + bool isDevice = PathInternal.IsDevice(ref outputBuffer); - StringBuffer inputBuffer = null; - bool isDosUnc = false; - uint rootDifference = 0; - bool wasDotDevice = false; - - // Add the extended prefix before expanding to allow growth over MAX_PATH - if (isDevice) + StringBuffer inputBuffer = new StringBuffer(0); + try { - // We have one of the following (\\?\ or \\.\) - inputBuffer = new StringBuffer(); - inputBuffer.Append(outputBuffer); + bool isDosUnc = false; + int rootDifference = 0; + bool wasDotDevice = false; - if (outputBuffer[2] == '.') + // Add the extended prefix before expanding to allow growth over MAX_PATH + if (isDevice) { - wasDotDevice = true; - inputBuffer[2] = '?'; + // We have one of the following (\\?\ or \\.\) + inputBuffer.Append(ref outputBuffer); + + if (outputBuffer[2] == '.') + { + wasDotDevice = true; + inputBuffer[2] = '?'; + } + } + else + { + isDosUnc = IsDosUnc(ref outputBuffer); + rootDifference = GetInputBuffer(ref outputBuffer, isDosUnc, ref inputBuffer); } - } - else - { - isDosUnc = IsDosUnc(outputBuffer); - rootDifference = GetInputBuffer(outputBuffer, isDosUnc, out inputBuffer); - } - rootLength += rootDifference; - uint inputLength = inputBuffer.Length; + rootLength += rootDifference; + int inputLength = inputBuffer.Length; - bool success = false; - uint foundIndex = inputBuffer.Length - 1; + bool success = false; + int foundIndex = inputBuffer.Length - 1; - while (!success) - { - uint result = Interop.mincore.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); + while (!success) + { + uint result = Interop.Kernel32.GetLongPathNameW(inputBuffer.UnderlyingArray, outputBuffer.UnderlyingArray, (uint)outputBuffer.Capacity); - // Replace any temporary null we added - if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\'; + // Replace any temporary null we added + if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\'; - if (result == 0) - { - // Look to see if we couldn't find the file - int error = Marshal.GetLastWin32Error(); - if (error != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND && error != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) + if (result == 0) { - // Some other failure, give up - break; - } + // Look to see if we couldn't find the file + int error = Marshal.GetLastWin32Error(); + if (error != Interop.Errors.ERROR_FILE_NOT_FOUND && error != Interop.Errors.ERROR_PATH_NOT_FOUND) + { + // Some other failure, give up + break; + } - // We couldn't find the path at the given index, start looking further back in the string. - foundIndex--; + // We couldn't find the path at the given index, start looking further back in the string. + foundIndex--; - for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ; - if (foundIndex == rootLength) + for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ; + if (foundIndex == rootLength) + { + // Can't trim the path back any further + break; + } + else + { + // Temporarily set a null in the string to get Windows to look further up the path + inputBuffer[foundIndex] = '\0'; + } + } + else if (result > outputBuffer.Capacity) { - // Can't trim the path back any further - break; + // Not enough space. The result count for this API does not include the null terminator. + outputBuffer.EnsureCapacity(checked((int)result)); + result = Interop.Kernel32.GetLongPathNameW(inputBuffer.UnderlyingArray, outputBuffer.UnderlyingArray, (uint)outputBuffer.Capacity); } else { - // Temporarily set a null in the string to get Windows to look further up the path - inputBuffer[foundIndex] = '\0'; + // Found the path + success = true; + outputBuffer.Length = checked((int)result); + if (foundIndex < inputLength - 1) + { + // It was a partial find, put the non-existent part of the path back + outputBuffer.Append(ref inputBuffer, foundIndex, inputBuffer.Length - foundIndex); + } } } - else if (result > outputBuffer.CharCapacity) + + // Strip out the prefix and return the string + ref StringBuffer bufferToUse = ref Choose(success, ref outputBuffer, ref inputBuffer); + + // Switch back from \\?\ to \\.\ if necessary + if (wasDotDevice) + bufferToUse[2] = '.'; + + string returnValue = null; + + int newLength = (int)(bufferToUse.Length - rootDifference); + if (isDosUnc) { - // Not enough space. The result count for this API does not include the null terminator. - outputBuffer.EnsureCharCapacity(result); - result = Interop.mincore.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity); + // Need to go from \\?\UNC\ to \\?\UN\\ + bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\'; + } + + // We now need to strip out any added characters at the front of the string + if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength)) + { + // Use the original path to avoid allocating + returnValue = originalPath; } else { - // Found the path - success = true; - outputBuffer.Length = result; - if (foundIndex < inputLength - 1) - { - // It was a partial find, put the non-existent part of the path back - outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex); - } + returnValue = bufferToUse.Substring(rootDifference, newLength); } - } - // Strip out the prefix and return the string - StringBuffer bufferToUse = success ? outputBuffer : inputBuffer; - - // Switch back from \\?\ to \\.\ if necessary - if (wasDotDevice) - bufferToUse[2] = '.'; - - string returnValue = null; - - int newLength = (int)(bufferToUse.Length - rootDifference); - if (isDosUnc) - { - // Need to go from \\?\UNC\ to \\?\UN\\ - bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\'; - } - - // We now need to strip out any added characters at the front of the string - if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength)) - { - // Use the original path to avoid allocating - returnValue = originalPath; + return returnValue; } - else + finally { - returnValue = bufferToUse.Substring(rootDifference, newLength); + inputBuffer.Free(); } + } - inputBuffer.Dispose(); - return returnValue; + // Helper method to workaround lack of operator ? support for ref values + private static ref StringBuffer Choose(bool condition, ref StringBuffer s1, ref StringBuffer s2) + { + if (condition) return ref s1; + else return ref s2; } } } diff --git a/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs b/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs deleted file mode 100644 index bea2df93b9..0000000000 --- a/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// 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.IO -{ - /// Contains internal path helpers that are shared between many projects. - internal static partial class PathInternal - { - private enum Tristate : byte - { - NotInitialized, - True, - False, - } - - private static Tristate s_isCaseSensitive = Tristate.NotInitialized; - - /// Returns a comparison that can be used to compare file and directory names for equality. - internal static StringComparison StringComparison - { - get - { - return IsCaseSensitive ? - StringComparison.Ordinal : - StringComparison.OrdinalIgnoreCase; - } - } - - /// Gets whether the system is case-sensitive. - internal static bool IsCaseSensitive - { - get - { - // This must be lazily initialized as there are dependencies on PathInternal's static constructor - // being fully initialized. (GetIsCaseSensitive() calls GetFullPath() which needs to use PathInternal) - if (s_isCaseSensitive == Tristate.NotInitialized) - s_isCaseSensitive = GetIsCaseSensitive() ? Tristate.True : Tristate.False; - - return s_isCaseSensitive == Tristate.True; - } - } - - /// - /// Determines whether the file system is case sensitive. - /// - /// - /// Ideally we'd use something like pathconf with _PC_CASE_SENSITIVE, but that is non-portable, - /// not supported on Windows or Linux, etc. For now, this function creates a tmp file with capital letters - /// and then tests for its existence with lower-case letters. This could return invalid results in corner - /// cases where, for example, different file systems are mounted with differing sensitivities. - /// - private static bool GetIsCaseSensitive() - { - try - { - string pathWithUpperCase = Path.Combine(Path.GetTempPath(), "CASESENSITIVETEST" + Guid.NewGuid().ToString("N")); - using (new FileStream(pathWithUpperCase, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, 0x1000, FileOptions.DeleteOnClose)) - { - string lowerCased = pathWithUpperCase.ToLowerInvariant(); - return !File.Exists(lowerCased); - } - } - catch (Exception exc) - { - // In case something goes terribly wrong, we don't want to fail just because - // of a casing test, so we assume case-insensitive-but-preserving. - Debug.Fail("Casing test failed: " + exc); - return false; - } - } - } -} diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs b/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs index 6c39f99556..08dc1d0251 100644 --- a/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs +++ b/src/mscorlib/corefx/System/IO/PathInternal.Unix.cs @@ -10,11 +10,15 @@ namespace System.IO /// Contains internal path helpers that are shared between many projects. internal static partial class PathInternal { + internal const char DirectorySeparatorChar = '/'; + internal const char AltDirectorySeparatorChar = '/'; + internal const char VolumeSeparatorChar = '/'; + internal const char PathSeparator = ':'; + + internal const string DirectorySeparatorCharAsString = "/"; + // There is only one invalid path character in Unix private const char InvalidPathChar = '\0'; - internal static char[] GetInvalidPathChars() => new char[] { InvalidPathChar }; - - internal static readonly int MaxComponentLength = Interop.Sys.MaxName; internal const string ParentDirectoryPrefix = @"../"; @@ -34,24 +38,8 @@ namespace System.IO { // The alternate directory separator char is the same as the directory separator, // so we only need to check one. - Debug.Assert(Path.DirectorySeparatorChar == Path.AltDirectorySeparatorChar); - return c == Path.DirectorySeparatorChar; - } - - /// - /// Returns true if the path is too long - /// - internal static bool IsPathTooLong(string fullPath) - { - return fullPath.Length >= Interop.Sys.MaxPath; - } - - /// - /// Returns true if the directory is too long - /// - internal static bool IsDirectoryTooLong(string fullPath) - { - return fullPath.Length >= Interop.Sys.MaxPath; + Debug.Assert(DirectorySeparatorChar == AltDirectorySeparatorChar); + return c == DirectorySeparatorChar; } /// @@ -101,15 +89,9 @@ namespace System.IO { // The directory separator, volume separator, and the alternate directory // separator should be the same on Unix, so we only need to check one. - Debug.Assert(Path.DirectorySeparatorChar == Path.AltDirectorySeparatorChar); - Debug.Assert(Path.DirectorySeparatorChar == Path.VolumeSeparatorChar); - return ch == Path.DirectorySeparatorChar; - } - - internal static bool HasInvalidVolumeSeparator(string path) - { - // This is only ever true for Windows - return false; + Debug.Assert(DirectorySeparatorChar == AltDirectorySeparatorChar); + Debug.Assert(DirectorySeparatorChar == VolumeSeparatorChar); + return ch == DirectorySeparatorChar; } internal static bool IsPartiallyQualified(string path) diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs b/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs index fec2218844..84953df37b 100644 --- a/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs +++ b/src/mscorlib/corefx/System/IO/PathInternal.Windows.StringBuffer.cs @@ -13,7 +13,7 @@ namespace System.IO /// /// Returns true if the path uses the extended syntax (\\?\) /// - internal static bool IsExtended(StringBuffer path) + internal static bool IsExtended(ref StringBuffer path) { // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths. // Skipping of normalization will *only* occur if back slashes ('\') are used. @@ -27,20 +27,24 @@ namespace System.IO /// /// Gets the length of the root of the path (drive, share, etc.). /// - internal unsafe static uint GetRootLength(StringBuffer path) + internal unsafe static int GetRootLength(ref StringBuffer path) { if (path.Length == 0) return 0; - return GetRootLength(path.CharPointer, path.Length); + + fixed (char* value = path.UnderlyingArray) + { + return GetRootLength(value, path.Length); + } } /// /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\") /// - internal static bool IsDevice(StringBuffer path) + internal static bool IsDevice(ref StringBuffer path) { // If the path begins with any two separators is will be recognized and normalized and prepped with // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not. - return IsExtended(path) + return IsExtended(ref path) || ( path.Length >= DevicePrefixLength @@ -63,7 +67,7 @@ namespace System.IO /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory /// will not be used to modify the path). /// - internal static bool IsPartiallyQualified(StringBuffer path) + internal static bool IsPartiallyQualified(ref StringBuffer path) { if (path.Length < 2) { @@ -82,7 +86,7 @@ namespace System.IO // The only way to specify a fixed path that doesn't begin with two slashes // is the drive, colon, slash format- i.e. C:\ return !((path.Length >= 3) - && (path[1] == Path.VolumeSeparatorChar) + && (path[1] == VolumeSeparatorChar) && IsDirectorySeparator(path[2])); } } diff --git a/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs b/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs index bd7f1eae41..0ec9b30f99 100644 --- a/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs +++ b/src/mscorlib/corefx/System/IO/PathInternal.Windows.cs @@ -40,6 +40,13 @@ namespace System.IO // Local and Global MS-DOS Device Names // https://msdn.microsoft.com/en-us/library/windows/hardware/ff554302.aspx + internal const char DirectorySeparatorChar = '\\'; + internal const char AltDirectorySeparatorChar = '/'; + internal const char VolumeSeparatorChar = ':'; + internal const char PathSeparator = ';'; + + internal const string DirectorySeparatorCharAsString = "\\"; + internal const string ExtendedPathPrefix = @"\\?\"; internal const string UncPathPrefix = @"\\"; internal const string UncExtendedPrefixToInsert = @"?\UNC\"; @@ -58,22 +65,6 @@ namespace System.IO internal const int UncExtendedPrefixLength = 8; internal const int MaxComponentLength = 255; - internal static char[] GetInvalidPathChars() => new char[] - { - '|', '\0', - (char)1, (char)2, (char)3, (char)4, (char)5, (char)6, (char)7, (char)8, (char)9, (char)10, - (char)11, (char)12, (char)13, (char)14, (char)15, (char)16, (char)17, (char)18, (char)19, (char)20, - (char)21, (char)22, (char)23, (char)24, (char)25, (char)26, (char)27, (char)28, (char)29, (char)30, - (char)31 - }; - - // [MS - FSA] 2.1.4.4 Algorithm for Determining if a FileName Is in an Expression - // https://msdn.microsoft.com/en-us/library/ff469270.aspx - private static readonly char[] s_wildcardChars = - { - '\"', '<', '>', '*', '?' - }; - /// /// Returns true if the given character is a valid drive letter /// @@ -82,24 +73,6 @@ namespace System.IO return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z')); } - /// - /// Returns true if the path is too long - /// - internal static bool IsPathTooLong(string fullPath) - { - // We'll never know precisely what will fail as paths get changed internally in Windows and - // may grow to exceed MaxLongPath. - return fullPath.Length >= MaxLongPath; - } - - /// - /// Returns true if the directory is too long - /// - internal static bool IsDirectoryTooLong(string fullPath) - { - return IsPathTooLong(fullPath); - } - /// /// Adds the extended path prefix (\\?\) if not already a device path, IF the path is not relative, /// AND the path is more than 259 characters. (> MAX_PATH + null) @@ -193,10 +166,12 @@ namespace System.IO for (int i = 0; i < path.Length; i++) { char c = path[i]; - - if (c <= '\u001f' || c == '|') + if (c <= '|') // fast path for common case - '|' is highest illegal character { - return true; + if (c <= '\u001f' || c == '|') + { + return true; + } } } @@ -206,13 +181,24 @@ namespace System.IO /// /// Check for known wildcard characters. '*' and '?' are the most common ones. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal unsafe static bool HasWildCardCharacters(string path) + internal static bool HasWildCardCharacters(string path) { // Question mark is part of dos device syntax so we have to skip if we are int startIndex = IsDevice(path) ? ExtendedPathPrefix.Length : 0; - return path.IndexOfAny(s_wildcardChars, startIndex) >= 0; + // [MS - FSA] 2.1.4.4 Algorithm for Determining if a FileName Is in an Expression + // https://msdn.microsoft.com/en-us/library/ff469270.aspx + for (int i = startIndex; i < path.Length; i++) + { + char c = path[i]; + if (c <= '?') // fast path for common case - '?' is highest wildcard character + { + if (c == '\"' || c == '<' || c == '>' || c == '*' || c == '?') + return true; + } + } + + return false; } /// @@ -222,15 +208,15 @@ namespace System.IO { fixed(char* value = path) { - return (int)GetRootLength(value, (uint)path.Length); + return GetRootLength(value, path.Length); } } - private unsafe static uint GetRootLength(char* path, uint pathLength) + private unsafe static int GetRootLength(char* path, int pathLength) { - uint i = 0; - uint volumeSeparatorLength = 2; // Length to the colon "C:" - uint uncRootLength = 2; // Length to the start of the server name "\\" + int i = 0; + int volumeSeparatorLength = 2; // Length to the colon "C:" + int uncRootLength = 2; // Length to the start of the server name "\\" bool extendedSyntax = StartsWithOrdinal(path, pathLength, ExtendedPathPrefix); bool extendedUncSyntax = StartsWithOrdinal(path, pathLength, UncExtendedPathPrefix); @@ -240,12 +226,12 @@ namespace System.IO if (extendedUncSyntax) { // "\\" -> "\\?\UNC\" - uncRootLength = (uint)UncExtendedPathPrefix.Length; + uncRootLength = UncExtendedPathPrefix.Length; } else { // "C:" -> "\\?\C:" - volumeSeparatorLength += (uint)ExtendedPathPrefix.Length; + volumeSeparatorLength += ExtendedPathPrefix.Length; } } @@ -263,7 +249,7 @@ namespace System.IO while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) i++; } } - else if (pathLength >= volumeSeparatorLength && path[volumeSeparatorLength - 1] == Path.VolumeSeparatorChar) + else if (pathLength >= volumeSeparatorLength && path[volumeSeparatorLength - 1] == VolumeSeparatorChar) { // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:) // If the colon is followed by a directory separator, move past it @@ -273,9 +259,9 @@ namespace System.IO return i; } - private unsafe static bool StartsWithOrdinal(char* source, uint sourceLength, string value) + private unsafe static bool StartsWithOrdinal(char* source, int sourceLength, string value) { - if (sourceLength < (uint)value.Length) return false; + if (sourceLength < value.Length) return false; for (int i = 0; i < value.Length; i++) { if (value[i] != source[i]) return false; @@ -314,7 +300,7 @@ namespace System.IO // The only way to specify a fixed path that doesn't begin with two slashes // is the drive, colon, slash format- i.e. C:\ return !((path.Length >= 3) - && (path[1] == Path.VolumeSeparatorChar) + && (path[1] == VolumeSeparatorChar) && IsDirectorySeparator(path[2]) // To match old behavior we'll check the drive character for validity as the path is technically // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream. @@ -350,7 +336,7 @@ namespace System.IO [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool IsDirectorySeparator(char c) { - return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar; + return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar; } /// @@ -401,7 +387,7 @@ namespace System.IO { current = path[i]; if (IsDirectorySeparator(current) - && (current != Path.DirectorySeparatorChar + && (current != DirectorySeparatorChar // Check for sequential separators past the first position (we need to keep initial two for UNC/extended) || (i > 0 && i + 1 < path.Length && IsDirectorySeparator(path[i + 1])))) { @@ -418,7 +404,7 @@ namespace System.IO if (IsDirectorySeparator(path[start])) { start++; - builder.Append(Path.DirectorySeparatorChar); + builder.Append(DirectorySeparatorChar); } for (int i = start; i < path.Length; i++) @@ -435,7 +421,7 @@ namespace System.IO } // Ensure it is the primary separator - current = Path.DirectorySeparatorChar; + current = DirectorySeparatorChar; } builder.Append(current); @@ -450,33 +436,7 @@ namespace System.IO /// The character to test. internal static bool IsDirectoryOrVolumeSeparator(char ch) { - return IsDirectorySeparator(ch) || Path.VolumeSeparatorChar == ch; - } - - /// - /// Validates volume separator only occurs as C: or \\?\C:. This logic is meant to filter out Alternate Data Streams. - /// - /// True if the path has an invalid volume separator. - internal static bool HasInvalidVolumeSeparator(string path) - { - // Toss out paths with colons that aren't a valid drive specifier. - // Cannot start with a colon and can only be of the form "C:" or "\\?\C:". - // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) - - // We don't care about skipping starting space for extended paths. Assume no knowledge of extended paths if we're forcing old path behavior. - int startIndex = IsExtended(path) ? ExtendedPathPrefix.Length : PathStartSkip(path); - - // If we start with a colon - if ((path.Length > startIndex && path[startIndex] == Path.VolumeSeparatorChar) - // Or have an invalid drive letter and colon - || (path.Length >= startIndex + 2 && path[startIndex + 1] == Path.VolumeSeparatorChar && !IsValidDriveChar(path[startIndex])) - // Or have any colons beyond the drive colon - || (path.Length > startIndex + 2 && path.IndexOf(Path.VolumeSeparatorChar, startIndex + 2) != -1)) - { - return true; - } - - return false; + return IsDirectorySeparator(ch) || VolumeSeparatorChar == ch; } } } diff --git a/src/mscorlib/corefx/System/IO/PathInternal.cs b/src/mscorlib/corefx/System/IO/PathInternal.cs index ee67680df5..6b4c3b2d30 100644 --- a/src/mscorlib/corefx/System/IO/PathInternal.cs +++ b/src/mscorlib/corefx/System/IO/PathInternal.cs @@ -40,64 +40,6 @@ namespace System.IO if (HasIllegalCharacters(path)) throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); } - - - /// - /// Returns true if the given StringBuilder starts with the given value. - /// - /// The string to compare against the start of the StringBuilder. - internal static bool StartsWithOrdinal(this StringBuilder builder, string value) - { - if (value == null || builder.Length < value.Length) - return false; - - for (int i = 0; i < value.Length; i++) - { - if (builder[i] != value[i]) return false; - } - return true; - } - - /// - /// Returns true if the given string starts with the given value. - /// - /// The string to compare against the start of the source string. - internal static bool StartsWithOrdinal(this string source, string value) - { - if (value == null || source.Length < value.Length) - return false; - - return source.StartsWith(value, StringComparison.Ordinal); - } - - /// - /// Trims the specified characters from the end of the StringBuilder. - /// - internal static StringBuilder TrimEnd(this StringBuilder builder, params char[] trimChars) - { - if (trimChars == null || trimChars.Length == 0) - return builder; - - int end = builder.Length - 1; - - for (; end >= 0; end--) - { - int i = 0; - char ch = builder[end]; - for (; i < trimChars.Length; i++) - { - if (trimChars[i] == ch) break; - } - if (i == trimChars.Length) - { - // Not a trim char - break; - } - } - - builder.Length = end + 1; - return builder; - } /// /// Returns the start index of the filename diff --git a/src/mscorlib/corefx/System/IO/Win32Marshal.cs b/src/mscorlib/corefx/System/IO/Win32Marshal.cs index b4dfa04468..ef76c27010 100644 --- a/src/mscorlib/corefx/System/IO/Win32Marshal.cs +++ b/src/mscorlib/corefx/System/IO/Win32Marshal.cs @@ -22,16 +22,6 @@ namespace System.IO return GetExceptionForWin32Error(errorCode, string.Empty); } - /// - /// Converts, resetting it, the last Win32 error into a corresponding object, optionally - /// including the specified path in the error message. - /// - internal static Exception GetExceptionForLastWin32Error(string path) - { - int errorCode = Marshal.GetLastWin32Error(); - return GetExceptionForWin32Error(errorCode, path); - } - /// /// Converts the specified Win32 error into a corresponding object. /// @@ -48,49 +38,49 @@ namespace System.IO { switch (errorCode) { - case Interop.mincore.Errors.ERROR_FILE_NOT_FOUND: + case Interop.Errors.ERROR_FILE_NOT_FOUND: if (path.Length == 0) return new FileNotFoundException(SR.IO_FileNotFound); else return new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path); - case Interop.mincore.Errors.ERROR_PATH_NOT_FOUND: + case Interop.Errors.ERROR_PATH_NOT_FOUND: if (path.Length == 0) return new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName); else return new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)); - case Interop.mincore.Errors.ERROR_ACCESS_DENIED: + case Interop.Errors.ERROR_ACCESS_DENIED: if (path.Length == 0) return new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName); else return new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path)); - case Interop.mincore.Errors.ERROR_ALREADY_EXISTS: + case Interop.Errors.ERROR_ALREADY_EXISTS: if (path.Length == 0) goto default; return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode)); - case Interop.mincore.Errors.ERROR_FILENAME_EXCED_RANGE: + case Interop.Errors.ERROR_FILENAME_EXCED_RANGE: return new PathTooLongException(SR.IO_PathTooLong); - case Interop.mincore.Errors.ERROR_INVALID_PARAMETER: + case Interop.Errors.ERROR_INVALID_PARAMETER: return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); - case Interop.mincore.Errors.ERROR_SHARING_VIOLATION: + case Interop.Errors.ERROR_SHARING_VIOLATION: if (path.Length == 0) return new IOException(SR.IO_SharingViolation_NoFileName, MakeHRFromErrorCode(errorCode)); else return new IOException(SR.Format(SR.IO_SharingViolation_File, path), MakeHRFromErrorCode(errorCode)); - case Interop.mincore.Errors.ERROR_FILE_EXISTS: + case Interop.Errors.ERROR_FILE_EXISTS: if (path.Length == 0) goto default; return new IOException(SR.Format(SR.IO_FileExists_Name, path), MakeHRFromErrorCode(errorCode)); - case Interop.mincore.Errors.ERROR_OPERATION_ABORTED: + case Interop.Errors.ERROR_OPERATION_ABORTED: return new OperationCanceledException(); default: @@ -108,27 +98,12 @@ namespace System.IO return unchecked(((int)0x80070000) | errorCode); } - /// - /// Returns a Win32 error code for the specified HRESULT if it came from FACILITY_WIN32 - /// If not, returns the HRESULT unchanged - /// - internal static int TryMakeWin32ErrorCodeFromHR(int hr) - { - if ((0xFFFF0000 & hr) == 0x80070000) - { - // Win32 error, Win32Marshal.GetExceptionForWin32Error expects the Win32 format - hr &= 0x0000FFFF; - } - - return hr; - } - /// /// Returns a string message for the specified Win32 error code. /// internal static string GetMessage(int errorCode) { - return Interop.mincore.GetMessage(errorCode); + return Interop.Kernel32.GetMessage(errorCode); } } } diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs deleted file mode 100644 index 875009aee2..0000000000 --- a/src/mscorlib/corefx/System/Runtime/InteropServices/NativeBuffer.cs +++ /dev/null @@ -1,157 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// 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.Runtime.CompilerServices; - -namespace System.Runtime.InteropServices -{ - /// - /// Wrapper for access to the native heap. Dispose to free the memory. Try to use with using statements. - /// Does not allocate zero size buffers, and will free the existing native buffer if capacity is dropped to zero. - /// - /// NativeBuffer utilizes a cache of heap buffers. - /// - /// - /// Suggested use through P/Invoke: define DllImport arguments that take a byte buffer as SafeHandle. - /// - /// Using SafeHandle will ensure that the buffer will not get collected during a P/Invoke. - /// (Notably AddRef and ReleaseRef will be called by the interop layer.) - /// - /// This class is not threadsafe, changing the capacity or disposing on multiple threads risks duplicate heap - /// handles or worse. - /// - internal class NativeBuffer : IDisposable - { - private readonly static SafeHeapHandleCache s_handleCache = new SafeHeapHandleCache(); - private readonly static SafeHandle s_emptyHandle = new EmptySafeHandle(); - private SafeHeapHandle _handle; - private ulong _capacity; - - /// - /// Create a buffer with at least the specified initial capacity in bytes. - /// - public NativeBuffer(ulong initialMinCapacity = 0) - { - EnsureByteCapacity(initialMinCapacity); - } - - protected unsafe void* VoidPointer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return _handle == null ? null : _handle.DangerousGetHandle().ToPointer(); - } - } - - protected unsafe byte* BytePointer - { - get - { - return (byte*)VoidPointer; - } - } - - /// - /// Get the handle for the buffer. - /// - public SafeHandle GetHandle() - { - // Marshalling code will throw on null for SafeHandle - return _handle ?? s_emptyHandle; - } - - /// - /// The capacity of the buffer in bytes. - /// - public ulong ByteCapacity - { - get { return _capacity; } - } - - /// - /// Ensure capacity in bytes is at least the given minimum. - /// - /// Thrown if unable to allocate memory when setting. - /// Thrown if attempting to set to a value that is larger than the maximum addressable memory. - public void EnsureByteCapacity(ulong minCapacity) - { - if (_capacity < minCapacity) - { - Resize(minCapacity); - _capacity = minCapacity; - } - } - - public unsafe byte this[ulong index] - { - get - { - if (index >= _capacity) throw new ArgumentOutOfRangeException(); - return BytePointer[index]; - } - set - { - if (index >= _capacity) throw new ArgumentOutOfRangeException(); - BytePointer[index] = value; - } - } - - private unsafe void Resize(ulong byteLength) - { - if (byteLength == 0) - { - ReleaseHandle(); - return; - } - - if (_handle == null) - { - _handle = s_handleCache.Acquire(byteLength); - } - else - { - _handle.Resize(byteLength); - } - } - - private void ReleaseHandle() - { - if (_handle != null) - { - s_handleCache.Release(_handle); - _capacity = 0; - _handle = null; - } - } - - /// - /// Release the backing buffer - /// - public virtual void Free() - { - ReleaseHandle(); - } - - public void Dispose() - { - Free(); - } - - private sealed class EmptySafeHandle : SafeHandle - { - public EmptySafeHandle() : base(IntPtr.Zero, true) { } - - public override bool IsInvalid - { - get { return true; } - } - - protected override bool ReleaseHandle() - { - return true; - } - } - } -} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs deleted file mode 100644 index 92b3d980db..0000000000 --- a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandle.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Runtime.InteropServices -{ - /// - /// Handle for heap memory that allows tracking of capacity and reallocating. - /// - internal sealed class SafeHeapHandle : SafeBuffer - { - /// - /// Allocate a buffer of the given size if requested. - /// - /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. - /// Thrown if the requested memory size cannot be allocated. - /// Thrown if size is greater than the maximum memory size. - public SafeHeapHandle(ulong byteLength) : base(ownsHandle: true) - { - Resize(byteLength); - } - - public override bool IsInvalid - { - get { return handle == IntPtr.Zero; } - } - - /// - /// Resize the buffer to the given size if requested. - /// - /// Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit. - /// Thrown if the requested memory size cannot be allocated. - /// Thrown if size is greater than the maximum memory size. - public void Resize(ulong byteLength) - { - if (IsClosed) throw new ObjectDisposedException(nameof(SafeHeapHandle)); - - ulong originalLength = 0; - if (handle == IntPtr.Zero) - { - handle = Marshal.AllocHGlobal((IntPtr)byteLength); - } - else - { - originalLength = ByteLength; - - // This may or may not be the same handle, may realloc in place. If the - // handle changes Windows will deal with the old handle, trying to free it will - // cause an error. - handle = Marshal.ReAllocHGlobal(pv: handle, cb: (IntPtr)byteLength); - } - - if (handle == IntPtr.Zero) - { - // Only real plausible answer - throw new OutOfMemoryException(); - } - - if (byteLength > originalLength) - { - // Add pressure - ulong addedBytes = byteLength - originalLength; - if (addedBytes > long.MaxValue) - { - GC.AddMemoryPressure(long.MaxValue); - GC.AddMemoryPressure((long)(addedBytes - long.MaxValue)); - } - else - { - GC.AddMemoryPressure((long)addedBytes); - } - } - else - { - // Shrank or did nothing, release pressure if needed - RemoveMemoryPressure(originalLength - byteLength); - } - - Initialize(byteLength); - } - - private void RemoveMemoryPressure(ulong removedBytes) - { - if (removedBytes == 0) return; - - if (removedBytes > long.MaxValue) - { - GC.RemoveMemoryPressure(long.MaxValue); - GC.RemoveMemoryPressure((long)(removedBytes - long.MaxValue)); - } - else - { - GC.RemoveMemoryPressure((long)removedBytes); - } - } - - protected override bool ReleaseHandle() - { - if (handle != IntPtr.Zero) - { - RemoveMemoryPressure(ByteLength); - Marshal.FreeHGlobal(handle); - } - - handle = IntPtr.Zero; - return true; - } - } -} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs deleted file mode 100644 index 725076ed66..0000000000 --- a/src/mscorlib/corefx/System/Runtime/InteropServices/SafeHeapHandleCache.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// 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.Threading; - -namespace System.Runtime.InteropServices -{ - /// - /// Allows limited thread safe reuse of heap buffers to limit memory pressure. - /// - /// This cache does not ensure that multiple copies of handles are not released back into the cache. - /// - internal sealed class SafeHeapHandleCache : IDisposable - { - private readonly ulong _minSize; - private readonly ulong _maxSize; - - // internal for testing - internal readonly SafeHeapHandle[] _handleCache; - - /// Smallest buffer size to allocate in bytes. - /// The largest buffer size to cache in bytes. - /// The maximum number of handles to cache. - public SafeHeapHandleCache(ulong minSize = 64, ulong maxSize = 1024 * 2, int maxHandles = 0) - { - _minSize = minSize; - _maxSize = maxSize; - _handleCache = new SafeHeapHandle[maxHandles > 0 ? maxHandles : Environment.ProcessorCount * 4]; - } - - /// - /// Get a HeapHandle - /// - public SafeHeapHandle Acquire(ulong minSize = 0) - { - if (minSize < _minSize) minSize = _minSize; - - SafeHeapHandle handle = null; - - for (int i = 0; i < _handleCache.Length; i++) - { - handle = Interlocked.Exchange(ref _handleCache[i], null); - if (handle != null) break; - } - - if (handle != null) - { - // One possible future consideration is to attempt cycling through to - // find one that might already have sufficient capacity - if (handle.ByteLength < minSize) - handle.Resize(minSize); - } - else - { - handle = new SafeHeapHandle(minSize); - } - - return handle; - } - - /// - /// Give a HeapHandle back for potential reuse - /// - public void Release(SafeHeapHandle handle) - { - if (handle.ByteLength <= _maxSize) - { - for (int i = 0; i < _handleCache.Length; i++) - { - // Push the handles down, walking the last one off the end to keep - // the top of the "stack" fresh - handle = Interlocked.Exchange(ref _handleCache[i], handle); - if (handle == null) return; - } - } - - handle.Dispose(); - } - - public void Dispose() - { - Dispose(disposing: true); - } - - private void Dispose(bool disposing) - { - if (disposing && _handleCache != null) - { - foreach (SafeHeapHandle handle in _handleCache) - { - if (handle != null) handle.Dispose(); - } - } - } - } -} diff --git a/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs b/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs index 29cef08b6c..fdd0b95590 100644 --- a/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs +++ b/src/mscorlib/corefx/System/Runtime/InteropServices/StringBuffer.cs @@ -2,69 +2,81 @@ // 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.Buffers; +using System.Runtime.CompilerServices; + namespace System.Runtime.InteropServices { /// - /// Native buffer that deals in char size increments. Dispose to free memory. Allows buffers larger - /// than a maximum size string to enable working with very large string arrays. Always makes ordinal - /// comparisons. + /// Buffer that deals in char size increments. Dispose to free memory. Always makes ordinal + /// comparisons. Not thread safe. /// /// A more performant replacement for StringBuilder when performing native interop. + /// + /// "No copy" valuetype. Has to be passed as "ref". + /// /// /// /// Suggested use through P/Invoke: define DllImport arguments that take a character buffer as SafeHandle and pass StringBuffer.GetHandle(). /// - internal class StringBuffer : NativeBuffer + internal struct StringBuffer { - private uint _length; + private char[] _buffer; + private int _length; /// /// Instantiate the buffer with capacity for at least the specified number of characters. Capacity /// includes the trailing null character. /// - public StringBuffer(uint initialCapacity = 0) - : base(initialCapacity * (ulong)sizeof(char)) + public StringBuffer(int initialCapacity) { + _buffer = ArrayPool.Shared.Rent(initialCapacity); + _length = 0; } /// /// Get/set the character at the given index. /// /// Thrown if attempting to index outside of the buffer length. - public unsafe char this[uint index] + public char this[int index] { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (index >= _length) throw new ArgumentOutOfRangeException(nameof(index)); - return CharPointer[index]; + return _buffer[index]; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { if (index >= _length) throw new ArgumentOutOfRangeException(nameof(index)); - CharPointer[index] = value; + _buffer[index] = value; } } + /// + /// Underlying storage of the buffer. Used for interop. + /// + public char[] UnderlyingArray => _buffer; + /// /// Character capacity of the buffer. Includes the count for the trailing null character. /// - public uint CharCapacity - { - get - { - ulong byteCapacity = ByteCapacity; - ulong charCapacity = byteCapacity == 0 ? 0 : byteCapacity / sizeof(char); - return charCapacity > uint.MaxValue ? uint.MaxValue : (uint)charCapacity; - } - } + public int Capacity => _buffer.Length; /// /// Ensure capacity in characters is at least the given minimum. /// /// Thrown if unable to allocate memory when setting. - public void EnsureCharCapacity(uint minCapacity) + public void EnsureCapacity(int minCapacity) { - EnsureByteCapacity(minCapacity * (ulong)sizeof(char)); + if (minCapacity > Capacity) + { + char[] oldBuffer = _buffer; + _buffer = ArrayPool.Shared.Rent(minCapacity); + Array.Copy(oldBuffer, 0, _buffer, 0, oldBuffer.Length); + ArrayPool.Shared.Return(oldBuffer); + } } /// @@ -72,59 +84,32 @@ namespace System.Runtime.InteropServices /// This is where the usable data ends. /// /// Thrown if unable to allocate memory when setting. - /// Thrown if the set size in bytes is uint.MaxValue (as space is implicitly reserved for the trailing null). - public unsafe uint Length + /// Thrown if the set size in bytes is int.MaxValue (as space is implicitly reserved for the trailing null). + public int Length { get { return _length; } set { - if (value == uint.MaxValue) throw new ArgumentOutOfRangeException(nameof(Length)); - // Null terminate - EnsureCharCapacity(value + 1); - CharPointer[value] = '\0'; + EnsureCapacity(checked(value + 1)); + _buffer[value] = '\0'; _length = value; } } - /// - /// For use when the native api null terminates but doesn't return a length. - /// If no null is found, the length will not be changed. - /// - public unsafe void SetLengthToFirstNull() - { - char* buffer = CharPointer; - uint capacity = CharCapacity; - for (uint i = 0; i < capacity; i++) - { - if (buffer[i] == '\0') - { - _length = i; - break; - } - } - } - - internal unsafe char* CharPointer - { - get - { - return (char*)VoidPointer; - } - } - /// /// True if the buffer contains the given character. /// public unsafe bool Contains(char value) { - char* start = CharPointer; - uint length = _length; - - for (uint i = 0; i < length; i++) + fixed (char* start = _buffer) { - if (*start++ == value) return true; + int length = _length; + for (int i = 0; i < length; i++) + { + if (start[i] == value) return true; + } } return false; @@ -136,7 +121,7 @@ namespace System.Runtime.InteropServices public bool StartsWith(string value) { if (value == null) throw new ArgumentNullException(nameof(value)); - if (_length < (uint)value.Length) return false; + if (_length < value.Length) return false; return SubstringEquals(value, startIndex: 0, count: value.Length); } @@ -150,53 +135,34 @@ namespace System.Runtime.InteropServices /// Thrown if or are outside the range /// of the buffer's length. /// - public unsafe bool SubstringEquals(string value, uint startIndex = 0, int count = -1) + public unsafe bool SubstringEquals(string value, int startIndex = 0, int count = -1) { if (value == null) return false; if (count < -1) throw new ArgumentOutOfRangeException(nameof(count)); if (startIndex > _length) throw new ArgumentOutOfRangeException(nameof(startIndex)); - uint realCount = count == -1 ? _length - startIndex : (uint)count; + int realCount = count == -1 ? _length - startIndex : (int)count; if (checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException(nameof(count)); int length = value.Length; // Check the substring length against the input length - if (realCount != (uint)length) return false; + if (realCount != length) return false; fixed (char* valueStart = value) + fixed (char* bufferStart = _buffer) { - char* bufferStart = CharPointer + startIndex; + char* subStringStart = bufferStart + startIndex; + for (int i = 0; i < length; i++) { - // Note that indexing in this case generates faster code than trying to copy the pointer and increment it - if (*bufferStart++ != valueStart[i]) return false; + if (subStringStart[i] != valueStart[i]) return false; } } return true; } - /// - /// Append the given string. - /// - /// The string to append. - /// The index in the input string to start appending from. - /// The count of characters to copy from the input string, or -1 for all remaining. - /// Thrown if is null. - /// - /// Thrown if or are outside the range - /// of characters. - /// - public void Append(string value, int startIndex = 0, int count = -1) - { - CopyFrom( - bufferIndex: _length, - source: value, - sourceIndex: startIndex, - count: count); - } - /// /// Append the given buffer. /// @@ -208,14 +174,13 @@ namespace System.Runtime.InteropServices /// Thrown if or are outside the range /// of characters. /// - public void Append(StringBuffer value, uint startIndex = 0) + public void Append(ref StringBuffer value, int startIndex = 0) { - if (value == null) throw new ArgumentNullException(nameof(value)); if (value.Length == 0) return; value.CopyTo( bufferIndex: startIndex, - destination: this, + destination: ref this, destinationIndex: _length, count: value.Length); } @@ -231,14 +196,13 @@ namespace System.Runtime.InteropServices /// Thrown if or are outside the range /// of characters. /// - public void Append(StringBuffer value, uint startIndex, uint count) + public void Append(ref StringBuffer value, int startIndex, int count) { - if (value == null) throw new ArgumentNullException(nameof(value)); if (count == 0) return; value.CopyTo( bufferIndex: startIndex, - destination: this, + destination: ref this, destinationIndex: _length, count: count); } @@ -252,29 +216,24 @@ namespace System.Runtime.InteropServices /// of characters. /// /// Thrown if is null. - public unsafe void CopyTo(uint bufferIndex, StringBuffer destination, uint destinationIndex, uint count) + public void CopyTo(int bufferIndex, ref StringBuffer destination, int destinationIndex, int count) { - if (destination == null) throw new ArgumentNullException(nameof(destination)); if (destinationIndex > destination._length) throw new ArgumentOutOfRangeException(nameof(destinationIndex)); if (bufferIndex >= _length) throw new ArgumentOutOfRangeException(nameof(bufferIndex)); if (_length < checked(bufferIndex + count)) throw new ArgumentOutOfRangeException(nameof(count)); if (count == 0) return; - uint lastIndex = checked(destinationIndex + count); - if (destination._length < lastIndex) destination.Length = lastIndex; - - Buffer.MemoryCopy( - source: CharPointer + bufferIndex, - destination: destination.CharPointer + destinationIndex, - destinationSizeInBytes: checked((long)(destination.ByteCapacity - (destinationIndex * sizeof(char)))), - sourceBytesToCopy: checked((long)count * sizeof(char))); + int lastIndex = checked(destinationIndex + count); + if (destination.Length < lastIndex) destination.Length = lastIndex; + + Array.Copy(UnderlyingArray, bufferIndex, destination.UnderlyingArray, destinationIndex, count); } /// /// Copy contents from the specified string into the buffer at the given index. Start index must be within the current length of /// the buffer, will grow as necessary. /// - public unsafe void CopyFrom(uint bufferIndex, string source, int sourceIndex = 0, int count = -1) + public void CopyFrom(int bufferIndex, string source, int sourceIndex = 0, int count = -1) { if (source == null) throw new ArgumentNullException(nameof(source)); if (bufferIndex > _length) throw new ArgumentOutOfRangeException(nameof(bufferIndex)); @@ -283,32 +242,22 @@ namespace System.Runtime.InteropServices if (count < 0 || source.Length - count < sourceIndex) throw new ArgumentOutOfRangeException(nameof(count)); if (count == 0) return; - uint lastIndex = bufferIndex + (uint)count; + int lastIndex = bufferIndex + (int)count; if (_length < lastIndex) Length = lastIndex; - fixed (char* content = source) - { - Buffer.MemoryCopy( - source: content + sourceIndex, - destination: CharPointer + bufferIndex, - destinationSizeInBytes: checked((long)(ByteCapacity - (bufferIndex * sizeof(char)))), - sourceBytesToCopy: (long)count * sizeof(char)); - } + source.CopyTo(sourceIndex, UnderlyingArray, bufferIndex, count); } /// /// Trim the specified values from the end of the buffer. If nothing is specified, nothing is trimmed. /// - public unsafe void TrimEnd(char[] values) + public void TrimEnd(char[] values) { if (values == null || values.Length == 0 || _length == 0) return; - char* end = CharPointer + _length - 1; - - while (_length > 0 && Array.IndexOf(values, *end) >= 0) + while (_length > 0 && Array.IndexOf(values, _buffer[_length - 1]) >= 0) { Length = _length - 1; - end--; } } @@ -316,11 +265,9 @@ namespace System.Runtime.InteropServices /// String representation of the entire buffer. If the buffer is larger than the maximum size string (int.MaxValue) this will throw. /// /// Thrown if the buffer is too big to fit into a string. - public unsafe override string ToString() + public override string ToString() { - if (_length == 0) return string.Empty; - if (_length > int.MaxValue) throw new InvalidOperationException(); - return new string(CharPointer, startIndex: 0, length: (int)_length); + return new string(_buffer, startIndex: 0, length: _length); } /// @@ -331,23 +278,23 @@ namespace System.Runtime.InteropServices /// Thrown if or are outside the range of the buffer's length /// or count is greater than the maximum string size (int.MaxValue). /// - public unsafe string Substring(uint startIndex, int count = -1) + public string Substring(int startIndex, int count = -1) { if (startIndex > (_length == 0 ? 0 : _length - 1)) throw new ArgumentOutOfRangeException(nameof(startIndex)); if (count < -1) throw new ArgumentOutOfRangeException(nameof(count)); - uint realCount = count == -1 ? _length - startIndex : (uint)count; + int realCount = count == -1 ? _length - startIndex : (int)count; if (realCount > int.MaxValue || checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException(nameof(count)); - if (realCount == 0) return string.Empty; // The buffer could be bigger than will fit into a string, but the substring might fit. As the starting // index might be bigger than int we need to index ourselves. - return new string(value: CharPointer + startIndex, startIndex: 0, length: (int)realCount); + return new string(_buffer, startIndex: startIndex, length: realCount); } - public override void Free() + public void Free() { - base.Free(); + ArrayPool.Shared.Return(_buffer); + _buffer = null; _length = 0; } } diff --git a/src/mscorlib/corefx/System/Security/SecureString.Windows.cs b/src/mscorlib/corefx/System/Security/SecureString.Windows.cs index 5f56353647..7ed0c6a15b 100644 --- a/src/mscorlib/corefx/System/Security/SecureString.Windows.cs +++ b/src/mscorlib/corefx/System/Security/SecureString.Windows.cs @@ -206,11 +206,11 @@ namespace System.Security else { uint defaultChar = '?'; - int resultByteLength = 1 + Interop.mincore.WideCharToMultiByte( - Interop.mincore.CP_ACP, Interop.mincore.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, null, 0, (IntPtr)(&defaultChar), IntPtr.Zero); + int resultByteLength = 1 + Interop.Kernel32.WideCharToMultiByte( + Interop.Kernel32.CP_ACP, Interop.Kernel32.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, null, 0, (IntPtr)(&defaultChar), IntPtr.Zero); ptr = globalAlloc ? Marshal.AllocHGlobal(resultByteLength) : Marshal.AllocCoTaskMem(resultByteLength); - Interop.mincore.WideCharToMultiByte( - Interop.mincore.CP_ACP, Interop.mincore.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, (byte*)ptr, resultByteLength - 1, (IntPtr)(&defaultChar), IntPtr.Zero); + Interop.Kernel32.WideCharToMultiByte( + Interop.Kernel32.CP_ACP, Interop.Kernel32.WC_NO_BEST_FIT_CHARS, (char*)bufferPtr, length, (byte*)ptr, resultByteLength - 1, (IntPtr)(&defaultChar), IntPtr.Zero); *(resultByteLength - 1 + (byte*)ptr) = 0; } result = ptr; -- cgit v1.2.3