Cleanup the native globalization code (#9887)
authorTarek Mahmoud Sayed <tarekms@microsoft.com>
Thu, 2 Mar 2017 02:20:18 +0000 (18:20 -0800)
committerGitHub <noreply@github.com>
Thu, 2 Mar 2017 02:20:18 +0000 (18:20 -0800)
* Cleanup the native globalization code

After we merged the globalization code used for Windows and Linux, this change is cleaning up the native VM globalization code

* Added a comment to the normalization code

src/classlibnative/inc/calendardata.h [deleted file]
src/classlibnative/inc/nlsinfo.h
src/classlibnative/nls/CMakeLists.txt
src/classlibnative/nls/calendardata.cpp [deleted file]
src/classlibnative/nls/nlsinfo.cpp
src/mscorlib/src/System/Globalization/Calendar.cs
src/vm/ecalllist.h
src/vm/mscorlib.cpp
src/vm/mscorlib.h
src/vm/object.h

diff --git a/src/classlibnative/inc/calendardata.h b/src/classlibnative/inc/calendardata.h
deleted file mode 100644 (file)
index f30660e..0000000
+++ /dev/null
@@ -1,165 +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.
-////////////////////////////////////////////////////////////////////////////
-//
-//  Class:    CalendarData
-//
-
-//
-//  Purpose:  This module implements the methods of the CalendarData
-//            class.  These methods are the helper functions for the
-//            Locale class.
-//
-//  Date:     July 4, 2007
-//
-////////////////////////////////////////////////////////////////////////////
-
-#ifndef _CALENDARDATA_H
-#define _CALENDARDATA_H
-
-//
-// Data store for the calendar data.
-//
-class CalendarData : Object
-{
-
-    //
-    // WARNING: These properties should stay in-sync with CalendarData.cs
-    //
-private:    
-    // Identity
-    STRINGREF   sNativeName               ; // Calendar Name for the locale (fallback for calendar only records)
-
-    // Formats
-    PTRARRAYREF saShortDates              ; // Short Data format, default first
-    PTRARRAYREF saYearMonths              ; // Year/Month Data format, default first
-    PTRARRAYREF saLongDates               ; // Long Data format, default first
-    STRINGREF   sMonthDay                 ; // Month/Day format
-
-    // Calendar Parts Names
-    PTRARRAYREF saEraNames                ; // Names of Eras
-    PTRARRAYREF saAbbrevEraNames          ; // Abbreviated Era Names
-    PTRARRAYREF saAbbrevEnglishEraNames   ; // Abbreviated Era Names in English
-    PTRARRAYREF saDayNames                ; // Day Names, null to use locale data, starts on Sunday
-    PTRARRAYREF saAbbrevDayNames          ; // Abbrev Day Names, null to use locale data, starts on Sunday
-    PTRARRAYREF saSuperShortDayNames      ; // Super short Day of week names
-    PTRARRAYREF saMonthNames              ; // Month Names (13)
-    PTRARRAYREF saAbbrevMonthNames        ; // Abbrev Month Names (13)
-    PTRARRAYREF saMonthGenitiveNames      ; // Genitive Month Names (13)
-    PTRARRAYREF saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
-    PTRARRAYREF saLeapYearMonthNames      ; // Multiple strings for the month names in a leap year.
-
-    // Year, digits have to be at end to make marshaller happy?
-    INT32       iTwoDigitYearMax          ; // Max 2 digit year (for Y2K bug data entry)
-    INT32       iCurrentEra               ; // our current era #
-
-    // Use overrides?
-    CLR_BOOL    bUseUserOverrides        ; // True if we want user overrides.
-
-    //
-    // Helpers
-    //
-    static BOOL CallGetCalendarInfoEx(LPCWSTR localeName, int calendar, int calType, STRINGREF* pOutputStrRef);
-    static BOOL CallGetCalendarInfoEx(LPCWSTR localeName, int calendar, int calType, INT32* pOutputInt32);
-    static BOOL GetCalendarDayInfo(LPCWSTR localeName, int calendar, int calType, PTRARRAYREF* pOutputStrings);
-    static BOOL GetCalendarMonthInfo(LPCWSTR localeName, int calendar, int calType, PTRARRAYREF* pOutputStrings);
-// TODO: NLS Arrowhead -Windows 7 If the OS had data this could use it, but Windows doesn't expose data for eras in enough detail    
-//    static BOOL GetCalendarEraInfo(LPCWSTR localeName, int calendar, PTRARRAYREF* pOutputEras);
-    static BOOL CallEnumCalendarInfo(__in_z LPCWSTR localeName, __in int calendar, __in int calType, 
-                                        __in int lcType, __inout PTRARRAYREF* pOutputStrings);
-
-    static void CheckSpecialCalendar(INT32* pCalendarInt, StackSString* pLocaleNameStackBuffer);
-public:
-    //
-    //  ecall function for methods in CalendarData
-    //
-    static FCDECL1(INT32, nativeGetTwoDigitYearMax, INT32 nValue);
-    static FCDECL3(FC_BOOL_RET, nativeGetCalendarData, CalendarData* calendarDataUNSAFE, StringObject* pLocaleNameUNSAFE, INT32 calendar);
-    static FCDECL3(INT32, nativeGetCalendars, StringObject* pLocaleNameUNSAFE, CLR_BOOL bUseOverrides, I4Array* calendars);
-    static FCDECL3(Object*, nativeEnumTimeFormats, StringObject* pLocaleNameUNSAFE, INT32 dwFlags, CLR_BOOL useUserOverride);
-};
-
-typedef CalendarData* CALENDARDATAREF;
-
-#ifndef LOCALE_RETURN_GENITIVE_NAMES
-#define LOCALE_RETURN_GENITIVE_NAMES    0x10000000   //Flag to return the Genitive forms of month names
-#endif
-
-#ifndef CAL_RETURN_GENITIVE_NAMES
-#define CAL_RETURN_GENITIVE_NAMES       LOCALE_RETURN_GENITIVE_NAMES  // return genitive forms of month names
-#endif
-
-#ifndef CAL_SERASTRING
-#define CAL_SERASTRING                  0x00000004  // era name for IYearOffsetRanges, eg A.D.
-#endif
-
-#ifndef CAL_SMONTHDAY
-#define CAL_SMONTHDAY                   0x00000038  // Month/day pattern (reserve for potential inclusion in a future version)
-#define CAL_SABBREVERASTRING            0x00000039  // Abbreviated era string (eg: AD)
-#endif
-
-#define RESERVED_CAL_JULIAN                 13  // Julian calendar (data looks like GREGORIAN_US)
-#define RESERVED_CAL_JAPANESELUNISOLAR      14  // Japaenese Lunisolar calendar (data looks like CAL_JAPANESE)
-#define RESERVED_CAL_CHINESELUNISOLAR       15  // Algorithmic
-#define RESERVED_CAL_SAKA                   16  // reserved to match Office but not implemented in our code
-#define RESERVED_CAL_LUNAR_ETO_CHN          17  // reserved to match Office but not implemented in our code
-#define RESERVED_CAL_LUNAR_ETO_KOR          18  // reserved to match Office but not implemented in our code
-#define RESERVED_CAL_LUNAR_ETO_ROKUYOU      19  // reserved to match Office but not implemented in our code
-#define RESERVED_CAL_KOREANLUNISOLAR        20  // Algorithmic
-#define RESERVED_CAL_TAIWANLUNISOLAR        21  // Algorithmic
-#define RESERVED_CAL_PERSIAN                22  // Algorithmic
-
-// These are vista properties
-#ifndef CAL_UMALQURA
-#define CAL_UMALQURA 23
-#endif
-
-#ifndef CAL_SSHORTESTDAYNAME1
-#define CAL_SSHORTESTDAYNAME1 0x00000031
-#define CAL_SSHORTESTDAYNAME2 0x00000032
-#define CAL_SSHORTESTDAYNAME3 0x00000033
-#define CAL_SSHORTESTDAYNAME4 0x00000034
-#define CAL_SSHORTESTDAYNAME5 0x00000035
-#define CAL_SSHORTESTDAYNAME6 0x00000036
-#define CAL_SSHORTESTDAYNAME7 0x00000037
-#endif
-
-#ifndef CAL_ITWODIGITYEARMAX
-    #define CAL_ITWODIGITYEARMAX    0x00000030  // two digit year max
-#endif // CAL_ITWODIGITYEARMAX
-#ifndef CAL_RETURN_NUMBER
-    #define CAL_RETURN_NUMBER       0x20000000   // return number instead of string
-#endif // CAL_RETURN_NUMBER
-
-#ifndef LOCALE_SNAME
-#define LOCALE_SNAME                  0x0000005c   // locale name (ie: en-us)
-#define LOCALE_SDURATION              0x0000005d   // time duration format
-#define LOCALE_SKEYBOARDSTOINSTALL    0x0000005e
-#define LOCALE_SSHORTESTDAYNAME1      0x00000060   // Shortest day name for Monday
-#define LOCALE_SSHORTESTDAYNAME2      0x00000061   // Shortest day name for Tuesday
-#define LOCALE_SSHORTESTDAYNAME3      0x00000062   // Shortest day name for Wednesday
-#define LOCALE_SSHORTESTDAYNAME4      0x00000063   // Shortest day name for Thursday
-#define LOCALE_SSHORTESTDAYNAME5      0x00000064   // Shortest day name for Friday
-#define LOCALE_SSHORTESTDAYNAME6      0x00000065   // Shortest day name for Saturday
-#define LOCALE_SSHORTESTDAYNAME7      0x00000066   // Shortest day name for Sunday
-#define LOCALE_SISO639LANGNAME2       0x00000067   // 3 character ISO abbreviated language name
-#define LOCALE_SISO3166CTRYNAME2      0x00000068   // 3 character ISO country name
-#define LOCALE_SNAN                   0x00000069   // Not a Number
-#define LOCALE_SPOSINFINITY           0x0000006a   // + Infinity
-#define LOCALE_SNEGINFINITY           0x0000006b   // - Infinity
-#define LOCALE_SSCRIPTS               0x0000006c   // Typical scripts in the locale
-#define LOCALE_SPARENT                0x0000006d   // Fallback name for resources
-#define LOCALE_SCONSOLEFALLBACKNAME   0x0000006e   // Fallback name for within the console
-#define LOCALE_SLANGDISPLAYNAME       0x0000006f   // Lanugage Display Name for a language
-#endif  // LOCALE_SNAME
-#ifndef LOCALE_SSHORTTIME
-#define LOCALE_SSHORTTIME             0x00000079   // short time format (ie: no seconds, just h:mm)
-#endif // LOCALE_SSHORTTIME
-
-#ifndef TIME_NOSECONDS
-#define TIME_NOSECONDS            0x00000002  // do not use seconds
-#endif
-
-#endif
-
index 3373f1d..6c32fed 100644 (file)
 #ifndef _NLSINFO_H_
 #define _NLSINFO_H_
 
-#define DEFAULT_SORT_VERSION 0
-#define SORT_VERSION_WHIDBEY 0x00001000
-#define SORT_VERSION_V4      0x00060101
-
 //
 //This structure must map 1-for-1 with the InternalDataItem structure in
 //System.Globalization.EncodingTable.
@@ -53,56 +49,23 @@ typedef int (*PFN_NORMALIZATION_NORMALIZE_STRING)
 typedef BYTE* (*PFN_NORMALIZATION_INIT_NORMALIZATION)
     ( int NormForm, BYTE* pTableData);
 
-////////////////////////////////////////////////////////////////////////////
-//
-// Forward declarations
-//
-////////////////////////////////////////////////////////////////////////////
-
-class CharTypeTable;
-class CasingTable;
-class SortingTable;
-class NativeTextInfo;
-
-class COMNlsInfo {
-
+class COMNlsInfo
+{
 public:
 
-    static INT32 GetCHTLanguage();
-    static INT32 CallGetSystemDefaultUILanguage();
     static INT32 CallGetUserDefaultUILanguage();
-    static LANGID GetDownLevelSystemDefaultUILanguage();
-
-    //
-    //  Native helper functions for methods in CultureInfo.
-    //
-    static BOOL QCALLTYPE InternalGetDefaultLocaleName(INT32 langType, QCall::StringHandleOnStack defaultLocaleName);
-    static BOOL QCALLTYPE InternalGetUserDefaultUILanguage(QCall::StringHandleOnStack userDefaultUiLanguage);
-    static BOOL QCALLTYPE InternalGetSystemDefaultUILanguage(QCall::StringHandleOnStack systemDefaultUiLanguage);
 
     //
     // Native helper functions for methods in DateTimeFormatInfo
     //
     static FCDECL1(FC_BOOL_RET,  nativeSetThreadLocale, StringObject* localeNameUNSAFE);
-    static FCDECL2(Object*, nativeGetLocaleInfoEx, StringObject* localeNameUNSAFE, INT32 lcType);
-    static FCDECL2(INT32, nativeGetLocaleInfoExInt, StringObject* localeNameUNSAFE, INT32 lcType);
 
     //
     //  Native helper functions for CultureData
     //
-    static FCDECL3(FC_BOOL_RET, nativeGetNumberFormatInfoValues, StringObject* localeNameUNSAFE, NumberFormatInfo* nfi, CLR_BOOL useUserOverride);
-    static FCDECL1(Object*, LCIDToLocaleName, LCID lcid);
-    static FCDECL1(INT32, LocaleNameToLCID, StringObject* localeNameUNSAFE);
 
-    static INT32 QCALLTYPE InternalCompareString (INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR string1, INT32 offset1, INT32 length1, LPCWSTR string2, INT32 offset2, INT32 length2, INT32 flags);
     static INT32 QCALLTYPE InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR pString, INT32 length, INT32 dwFlagsIn, INT64 additionalEntropy);
 
-    static BOOL QCALLTYPE InternalIsSortable(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR pString, INT32 length);
-    static INT_PTR QCALLTYPE InternalInitSortHandle(LPCWSTR localeName, INT_PTR* handleOrigin);
-    static INT_PTR InitSortHandleHelper(LPCWSTR localeName, INT_PTR* handleOrigin);
-    static INT_PTR InternalInitOsSortHandle(LPCWSTR localeName, INT_PTR* handleOrigin);
-    static BOOL QCALLTYPE InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation);
-
     //
     //  Native helper function for methods in EncodingTable
     //
@@ -111,30 +74,12 @@ public:
     static FCDECL0(CodePageDataItem *, nativeGetCodePageTableDataPointer);
 
     //
-    //  Native helper function for methods in CharacterInfo
-    //
-    static FCDECL0(void, AllocateCharTypeTable);
-
-    //
-    //  Native helper function for methods in TextInfo
-    //
-    static FCDECL5(FC_CHAR_RET, InternalChangeCaseChar, INT_PTR handle, INT_PTR handleOrigin, StringObject* localeNameUNSAFE, CLR_CHAR wch, CLR_BOOL bIsToUpper);
-    static FCDECL5(Object*, InternalChangeCaseString, INT_PTR handle, INT_PTR handleOrigin, StringObject* localeNameUNSAFE, StringObject* pString, CLR_BOOL bIsToUpper);
-    static FCDECL6(INT32, InternalGetCaseInsHash, INT_PTR handle, INT_PTR handleOrigin, StringObject* localeNameUNSAFE, LPVOID strA, CLR_BOOL bForceRandomizedHashing, INT64 additionalEntropy);
-    static INT32 QCALLTYPE InternalCompareStringOrdinalIgnoreCase(LPCWSTR string1, INT32 index1, LPCWSTR string2, INT32 index2, INT32 length1, INT32 length2);
-
-    static BOOL QCALLTYPE InternalTryFindStringOrdinalIgnoreCase(
-        __in                   DWORD       dwFindNLSStringFlags, // mutually exclusive flags: FIND_FROMSTART, FIND_STARTSWITH, FIND_FROMEND, FIND_ENDSWITH
-        __in_ecount(cchSource) LPCWSTR     lpStringSource,       // the string we search in
-        __in                   int         cchSource,            // number of characters lpStringSource after sourceIndex
-        __in                   int         sourceIndex,          // index from where the search will start in lpStringSource
-        __in_ecount(cchValue)  LPCWSTR     lpStringValue,        // the string we search for
-        __in                   int         cchValue,
-        __out                  int*        foundIndex);          // the index in lpStringSource where we found lpStringValue
-
-    //
     // Native helper function for methods in Normalization
     //
+    // On Windows 7 we use the normalization data embedded inside the corelib to get better results.
+    // On Windows 8 and up we use the OS for normalization. 
+    // That is why we need to keep these fcalls and not doing it through pinvokes.
+
     static FCDECL6(int, nativeNormalizationNormalizeString,
         int NormForm, int& iError,
         StringObject* inString, int inLength,
@@ -145,53 +90,7 @@ public:
 
     static void QCALLTYPE nativeNormalizationInitNormalization(int NormForm, BYTE* pTableData);
 
-    //
-    // QCalls prototype
-    //
-
-    static int QCALLTYPE nativeEnumCultureNames(INT32 cultureTypes, QCall::ObjectHandleOnStack retStringArray);
-
-    static int QCALLTYPE InternalFindNLSStringEx(
-        __in_opt               INT_PTR     handle,               // optional sort handle
-        __in_opt               INT_PTR     handleOrigin,         // optional pointer to the native function that created the sort handle
-        __in_z                 LPCWSTR     lpLocaleName,         // locale name
-        __in                   int         dwFindNLSStringFlags, // search falg
-        __in_ecount(cchSource) LPCWSTR     lpStringSource,       // the string we search in
-        __in                   int         cchSource,            // number of characters lpStringSource after sourceIndex
-        __in                   int         sourceIndex,          // index from where the search will start in lpStringSource
-        __in_ecount(cchValue)  LPCWSTR     lpStringValue,        // the string we search for
-        __in                   int         cchValue,                    // length of the string we search for
-        __out_opt              LPINT       pcchFound);           // length of the string we found in source
-
-    static int QCALLTYPE InternalGetSortKey(
-        __in_opt               INT_PTR handle,        // PSORTHANDLE
-        __in_opt               INT_PTR handleOrigin,  // optional pointer to the native function that created the sort handle
-        __in_z                 LPCWSTR pLocaleName,   // locale name
-        __in                   int     flags,         // flags
-        __in_ecount(cchSource) LPCWSTR pStringSource, // Source string
-        __in                   int     cchSource,     // number of characters in lpStringSource
-        __in_ecount(cchTarget) PBYTE   pTarget,       // Target data buffer (may be null to count)
-        __in                   int     cchTarget);    // Character count for target buffer
-
-
 private:
-
-    //
-    //  Internal helper functions.
-    //
-    static LPVOID internalEnumSystemLocales(DWORD dwFlags);
-    static INT32  CompareOrdinal(__in_ecount(Length1) WCHAR* strAChars, int Length1, __in_ecount(Length2) WCHAR* strBChars, int Length2 );
-    static INT32  FastIndexOfString(__in WCHAR *sourceString, INT32 startIndex, INT32 endIndex, __in_ecount(patternLength) WCHAR *pattern, INT32 patternLength);
-    static INT32  FastIndexOfStringInsensitive(__in WCHAR *sourceString, INT32 startIndex, INT32 endIndex, __in_ecount(patternLength) WCHAR *pattern, INT32 patternLength);
-    static INT32  FastLastIndexOfString(__in WCHAR *sourceString, INT32 startIndex, INT32 endIndex, __in_ecount(patternLength) WCHAR *pattern, INT32 patternLength);
-    static INT32  FastLastIndexOfStringInsensitive(__in WCHAR *sourceString, INT32 startIndex, INT32 endIndex, __in_ecount(patternLength) WCHAR *pattern, INT32 patternLength);
-
-    static BOOL GetNativeDigitsFromWin32(LPCWSTR locale, PTRARRAYREF* pOutputStrAry, BOOL useUserOverride);
-    static BOOL CallGetLocaleInfoEx(LPCWSTR locale, int lcType, STRINGREF* pOutputStrRef, BOOL useUserOverride);
-    static BOOL CallGetLocaleInfoEx(LPCWSTR locale, int lcType, INT32* pOutputInt32, BOOL useUserOverride);
-
-    static BOOL IsWindows7();
-
     //
     //  Definitions.
     //
index 546566e..d6451b9 100644 (file)
@@ -1,5 +1,4 @@
 set( COMMLS_WKS_SOURCES
-  calendardata.cpp
   encodingdata.cpp
   nlsinfo.cpp
 )
diff --git a/src/classlibnative/nls/calendardata.cpp b/src/classlibnative/nls/calendardata.cpp
deleted file mode 100644 (file)
index 95d071c..0000000
+++ /dev/null
@@ -1,985 +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.
-////////////////////////////////////////////////////////////////////////////
-//
-//  Class:    CalendarData
-//
-
-//
-//  Purpose:  This module implements the methods of the CalendarData
-//            class.  These methods are the helper functions for the
-//            Locale class.
-//
-//  Date:     July 4, 2007
-//
-////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-#include "object.h"
-#include "excep.h"
-#include "vars.hpp"
-#include "interoputil.h"
-#include "corhost.h"
-
-#include <winnls.h>
-
-#include "calendardata.h"
-#include "nlsinfo.h"
-#include "newapis.h"
-
-////////////////////////////////////////////////////////////////////////
-//
-// Call the Win32 GetCalendarInfoEx() using the specified calendar and LCTYPE.
-// The return value can be INT32 or an allocated managed string object, depending on
-// which version's called.
-//
-// Parameters:
-//      OUT pOutputInt32    The output int32 value.
-//      OUT pOutputRef      The output string value.
-//
-////////////////////////////////////////////////////////////////////////
-BOOL CalendarData::CallGetCalendarInfoEx(LPCWSTR localeName, int calendar, int calType, INT32* pOutputInt32)
-{
-    CONTRACTL
-    {
-        GC_NOTRIGGER;
-        MODE_ANY;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    int result = 0;
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return result; )
-
-    // Just stick it right into the output int
-    _ASSERT((calType & CAL_RETURN_NUMBER) != 0);
-    result = NewApis::GetCalendarInfoEx(localeName, calendar, NULL, calType, NULL, 0, (LPDWORD)pOutputInt32);
-
-    END_SO_INTOLERANT_CODE
-
-    return (result != 0);
-}
-
-BOOL CalendarData::CallGetCalendarInfoEx(LPCWSTR localeName, int calendar, int calType, STRINGREF* pOutputStrRef)
-{
-    CONTRACTL
-    {
-        THROWS;                 // We can throw since we are allocating managed string.
-        DISABLED(GC_TRIGGERS); // Disabled 'cause it don't work right now
-        MODE_ANY;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    // The maximum size for values returned from GetLocaleInfo is 80 characters.
-    WCHAR buffer[80];
-    int result = 0;
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return result; )
-
-    _ASSERT((calType & CAL_RETURN_NUMBER) == 0);
-    result = NewApis::GetCalendarInfoEx(localeName, calendar, NULL, calType, buffer, 80, NULL);
-
-    if (result != 0)
-    {
-        _ASSERTE(pOutputStrRef != NULL);
-        *pOutputStrRef = StringObject::NewString(buffer, result - 1);
-    }
-
-    END_SO_INTOLERANT_CODE
-
-    return (result != 0);
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// Get the native day names
-//
-// NOTE: There's a disparity between .Net & windows day orders, the input day should
-//           start with Sunday
-//
-// Parameters:
-//      OUT pOutputStrings      The output string[] value.
-//
-////////////////////////////////////////////////////////////////////////
-BOOL CalendarData::GetCalendarDayInfo(LPCWSTR localeName, int calendar, int calType, PTRARRAYREF* pOutputStrings)
-{
-    CONTRACTL
-    {
-        THROWS;                 // We can throw since we are allocating managed string.
-        INJECT_FAULT(COMPlusThrowOM());
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    // The maximum size for values returned from GetLocaleInfo is 80 characters.
-    WCHAR buffer[80];
-    int result = 0;
-
-    _ASSERT((calType & CAL_RETURN_NUMBER) == 0);
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return result;)
-
-    //
-    // We'll need a new array of 7 items
-    //
-    // Allocate the array of STRINGREFs.  We don't need to check for null because the GC will throw
-    // an OutOfMemoryException if there's not enough memory.
-    //
-    PTRARRAYREF ResultArray = (PTRARRAYREF)AllocateObjectArray(7, g_pStringClass);
-    
-    GCPROTECT_BEGIN(ResultArray);
-
-    // Get each one of them
-    for (int i = 0; i < 7; i++, calType++)
-    {
-        result = NewApis::GetCalendarInfoEx(localeName, calendar, NULL, calType, buffer, 80, NULL);
-
-        // Note that the returned string is null terminated, so even an empty string will be 1
-        if (result != 0)
-        {
-            // Make a string for this entry
-            STRINGREF stringResult = StringObject::NewString(buffer, result - 1);
-            ResultArray->SetAt(i, (OBJECTREF)stringResult);
-        }
-
-        // On the first iteration we need to go from CAL_SDAYNAME7 to CAL_SDAYNAME1, so subtract 7 before the ++ happens
-        // This is because the framework starts on sunday and windows starts on monday when counting days
-        if (i == 0) calType -= 7;
-    }
-    GCPROTECT_END();
-
-    _ASSERTE(pOutputStrings != NULL);
-    *pOutputStrings = ResultArray;
-
-    END_SO_INTOLERANT_CODE
-
-    return (result != 0);
-}
-
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Get the native month names
-//
-// Parameters:
-//      OUT pOutputStrings      The output string[] value.
-//
-////////////////////////////////////////////////////////////////////////
-BOOL CalendarData::GetCalendarMonthInfo(LPCWSTR localeName, int calendar, int calType, PTRARRAYREF* pOutputStrings)
-{
-    CONTRACTL
-    {
-        THROWS;                 // We can throw since we are allocating managed string.
-        INJECT_FAULT(COMPlusThrowOM());
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    // The maximum size for values returned from GetLocaleInfo is 80 characters.
-    WCHAR buffer[80];
-    int result = 0;
-
-    _ASSERT((calType & CAL_RETURN_NUMBER) == 0);
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return result;)
-
-    //
-    // We'll need a new array of 13 items
-    //
-    // Allocate the array of STRINGREFs.  We don't need to check for null because the GC will throw
-    // an OutOfMemoryException if there's not enough memory.
-    //
-    PTRARRAYREF ResultArray = (PTRARRAYREF)AllocateObjectArray(13, g_pStringClass);
-    
-    GCPROTECT_BEGIN(ResultArray);
-
-    // Get each one of them
-    for (int i = 0; i < 13; i++, calType++)
-    {
-        result = NewApis::GetCalendarInfoEx(localeName, calendar, NULL, calType, buffer, 80, NULL);
-
-        // If we still have failure, then mark as empty string
-        if (result == 0)
-        {
-            buffer[0] = W('0');
-            result = 1;
-
-
-        }
-
-        // Note that the returned string is null terminated, so even an empty string will be 1
-        // Make a string for this entry
-        STRINGREF stringResult = StringObject::NewString(buffer, result - 1);
-        ResultArray->SetAt(i, (OBJECTREF)stringResult);
-    }
-    GCPROTECT_END();
-
-    _ASSERTE(pOutputStrings != NULL);
-    *pOutputStrings = ResultArray;
-
-    END_SO_INTOLERANT_CODE
-
-    return (result != 0);
-}
-
-//
-// struct to help our calendar data enumaration callback
-//
-struct enumData
-{
-    int     count;          // # of strings found so far
-    LPWSTR  userOverride;   // pointer to user override string if used
-    LPWSTR  stringsBuffer;  // pointer to a buffer to use for the strings.
-    LPWSTR  endOfBuffer;    // pointer to the end of the stringsBuffer ( must be < this to write)
-};
-
-//
-// callback itself
-//
-BOOL CALLBACK EnumCalendarInfoCallback(__in_z LPWSTR lpCalendarInfoString, __in CALID Calendar, __in_opt LPWSTR pReserved, __in LPARAM lParam)
-{
-    CONTRACTL
-    {
-        GC_NOTRIGGER;
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-        PRECONDITION(CheckPointer(lpCalendarInfoString));
-        PRECONDITION(CheckPointer((LPVOID)lParam));
-    } CONTRACTL_END;
-
-    // Cast our data to the right type
-    enumData* pData = (enumData*)lParam;
-
-    // If we had a user override, check to make sure this differs
-    if (pData->userOverride == NULL ||
-        wcscmp(pData->userOverride, lpCalendarInfoString) != 0)
-    {
-        // They're different, add it to our buffer
-        LPWSTR pStart = pData->stringsBuffer;
-        LPCWSTR pEnd = pData->endOfBuffer;
-        while (pStart < pEnd && *lpCalendarInfoString != 0)
-        {
-            *(pStart++) = *(lpCalendarInfoString++);
-        }
-
-        // Add a \0
-        if (pStart < pEnd)
-        {
-            *(pStart++) = 0;
-
-            // Did it finish?
-            if (pStart <= pEnd)
-            {
-                // It finished, use it
-                pData->count++;
-                pData->stringsBuffer = pStart;
-            }
-        }
-    }
-
-    return TRUE;
-}
-
-//
-// CallEnumCalendarInfo
-//
-// Get the list of whichever calendar property from the OS.  If user override is passed in, then check GetLocaleInfo as well
-// to see if a user override is set.
-//
-// We build a list of strings, first calling getlocaleinfo if necessary, and then the enums.  The strings are null terminated,
-// with a double null ending the list.  Once we have the list we can allocate our COMStrings and arrays from the count.
-//
-// We need a helper structure to pass as an lParam
-//
-BOOL CalendarData::CallEnumCalendarInfo(__in_z LPCWSTR localeName, __in int calendar, __in int calType,
-                                        __in int lcType, __inout PTRARRAYREF* pOutputStrings)
-{
-    CONTRACTL
-    {
-        THROWS;                 // We can throw since we are allocating managed string.
-        INJECT_FAULT(COMPlusThrowOM());
-        DISABLED(GC_TRIGGERS); // Disabled 'cause it don't work right now
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    BOOL result = TRUE;
-
-    // Our longest string in culture.xml is shorter than this and it has lots of \x type characters, so this should be long enough by far.
-    WCHAR   stringBuffer[512];
-
-    struct enumData data;
-    data.count = 0;
-    data.userOverride = NULL;
-    data.stringsBuffer = stringBuffer;
-    data.endOfBuffer = stringBuffer + 512;   // We're adding WCHAR sizes
-
-    // First call GetLocaleInfo if necessary
-    if ((lcType && ((lcType & LOCALE_NOUSEROVERRIDE) == 0)) &&
-        // Get user locale, see if it matches localeName.
-        // Note that they should match exactly, including letter case
-        NewApis::GetUserDefaultLocaleName(stringBuffer, 512) && wcscmp(localeName, stringBuffer) == 0)
-    {
-        // They want user overrides, see if the user calendar matches the input calendar
-        CALID userCalendar = 0;
-        NewApis::GetLocaleInfoEx(localeName, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, (LPWSTR)&userCalendar,
-                                            sizeof(userCalendar) / sizeof(WCHAR) );
-
-        // If the calendars were the same, see if the locales were the same
-        if ((int)userCalendar == calendar) // todo: cast to compile on MAC
-        {
-            // They matched, get the user override since locale & calendar match
-            int i = NewApis::GetLocaleInfoEx(localeName, lcType, stringBuffer, 512);
-
-            // if it succeeded, advance the pointer and remember the override for the later callers
-            if (i > 0)
-            {
-                // Remember this was the override (so we can look for duplicates later in the enum function)
-                data.userOverride = data.stringsBuffer;
-
-                // Advance to the next free spot (i includes counting the \0)
-                data.stringsBuffer += i;
-
-                // And our count...
-                data.count++;
-            }
-        }
-    }
-
-    // Now call the enumeration API. Work is done by our callback function
-    NewApis::EnumCalendarInfoExEx(EnumCalendarInfoCallback, localeName, calendar, calType, (LPARAM)&data);
-
-    // Now we have a list of data, fail if we didn't find anything.
-    if (data.count == 0) return FALSE;
-
-    // Now we need to allocate our stringarray and populate it
-    STATIC_CONTRACT_SO_TOLERANT;
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), return (result); )
-
-    // Get our array object (will throw, don't have to check it)
-    PTRARRAYREF dataArray = (PTRARRAYREF) AllocateObjectArray(data.count, g_pStringClass);
-
-    GCPROTECT_BEGIN(dataArray);
-    LPCWSTR buffer = stringBuffer;   // Restart @ buffer beginning
-    for(DWORD i = 0; i < (DWORD)data.count; i++)
-    {
-        OBJECTREF o = (OBJECTREF) StringObject::NewString(buffer);
-
-        if (calType == CAL_SABBREVERASTRING || calType == CAL_SERASTRING)
-        {
-            // Eras are enumerated backwards.  (oldest era name first, but
-            // Japanese calendar has newest era first in array, and is only
-            // calendar with multiple eras)
-            dataArray->SetAt((DWORD)data.count - i - 1, o);
-        }
-        else
-        {
-            dataArray->SetAt(i, o);
-        }
-
-        buffer += (lstrlenW(buffer) + 1);
-    }
-    GCPROTECT_END();
-
-    _ASSERTE(pOutputStrings != NULL);
-    *pOutputStrings = dataArray;
-
-    END_SO_INTOLERANT_CODE
-
-    return result;
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-// For calendars like Gregorain US/Taiwan/UmAlQura, they are not available
-// in all OS or all localized versions of OS.
-// If OS does not support these calendars, we will fallback by using the
-// appropriate fallback calendar and locale combination to retrieve data from OS.
-//
-// Parameters:
-//  __deref_inout pCalendarInt:
-//    Pointer to the calendar ID. This will be updated to new fallback calendar ID if needed.
-//  __in_out pLocaleNameStackBuffer
-//    Pointer to the StackSString object which holds the locale name to be checked.
-//    This will be updated to new fallback locale name if needed.
-//
-////////////////////////////////////////////////////////////////////////
-
-void CalendarData::CheckSpecialCalendar(INT32* pCalendarInt, StackSString* pLocaleNameStackBuffer)
-{
-    // Gregorian-US isn't always available in the OS, however it is the same for all locales
-    switch (*pCalendarInt)
-    {
-        case CAL_GREGORIAN_US:
-            // See if this works
-            if (0 == NewApis::GetCalendarInfoEx(*pLocaleNameStackBuffer, *pCalendarInt, NULL, CAL_SCALNAME, NULL, 0, NULL))
-            {
-                // Failed, set it to a locale (fa-IR) that's alway has Gregorian US available in the OS
-                pLocaleNameStackBuffer->Set(W("fa-IR"), 5);
-            }
-            // See if that works
-            if (0 == NewApis::GetCalendarInfoEx(*pLocaleNameStackBuffer, *pCalendarInt, NULL, CAL_SCALNAME, NULL, 0, NULL))
-            {
-                // Failed again, just use en-US with the gregorian calendar
-                pLocaleNameStackBuffer->Set(W("en-US"), 5);
-                *pCalendarInt = CAL_GREGORIAN;
-            }
-            break;
-        case CAL_TAIWAN:
-            // Taiwan calendar data is not always in all language version of OS due to Geopolical reasons.
-            // It is only available in zh-TW localized versions of Windows.
-            // Let's check if OS supports it.  If not, fallback to Greogrian localized for Taiwan calendar.
-            if (0 == NewApis::GetCalendarInfoEx(*pLocaleNameStackBuffer, *pCalendarInt, NULL, CAL_SCALNAME, NULL, 0, NULL))
-            {
-                *pCalendarInt = CAL_GREGORIAN;
-            }
-            break;
-        case CAL_UMALQURA:
-            // UmAlQura is only available in Vista and above, so we will need to fallback to Hijri if it is not available in the OS.
-            if (0 == NewApis::GetCalendarInfoEx(*pLocaleNameStackBuffer, *pCalendarInt, NULL, CAL_SCALNAME, NULL, 0, NULL))
-            {
-                // There are no differences in DATA between UmAlQura and Hijri, and
-                // UmAlQura isn't available before Vista, so just use Hijri..
-                *pCalendarInt = CAL_HIJRI;
-            }
-            break;
-    }
-}
-
-////////////////////////////////////////////////////////////////////////
-//
-//  Implementation for CalendarInfo.nativeGetCalendarData
-//
-//  Retrieve calendar properties from the native side
-//
-//  Parameters:
-//      pCalendarData: This is passed from a managed structure CalendarData.cs
-//      pLocaleNameUNSAFE: Locale name associated with the locale for this calendar
-//      calendar: Calendar ID
-//
-//  NOTE: Calendars depend on the locale name that creates it.  Only a few
-//            properties are available without locales using CalendarData.GetCalendar(int)
-//
-////////////////////////////////////////////////////////////////////////
-
-FCIMPL3(FC_BOOL_RET, CalendarData::nativeGetCalendarData, CalendarData* calendarDataUNSAFE, StringObject* pLocaleNameUNSAFE, INT32 calendar)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(pLocaleNameUNSAFE));
-    } CONTRACTL_END;
-
-
-    // The maximum allowed string length in GetLocaleInfo is 80 WCHARs.
-    BOOL ret = TRUE;
-
-    struct _gc
-    {
-        STRINGREF       localeName;
-        CALENDARDATAREF calendarData;
-    } gc;
-
-    // Dereference our gc objects
-    gc.localeName = (STRINGREF)pLocaleNameUNSAFE;
-    gc.calendarData = (CALENDARDATAREF)calendarDataUNSAFE;
-
-    // Need to set up the frame since we will be allocating managed strings.
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
-    // create a local copy of the string in order to pass it to helper methods that trigger GCs like GetCalendarDayInfo and GetCalendarMonthInfo
-    StackSString localeNameStackBuffer( gc.localeName->GetBuffer() );
-
-    // Conveniently this is the same as LOCALE_NOUSEROVERRIDE, so we can use this for both
-    int useOverrides = (gc.calendarData->bUseUserOverrides) ? 0 : CAL_NOUSEROVERRIDE;
-
-    // Helper string
-    STRINGREF stringResult = NULL;
-
-    //
-    // Windows doesn't support some calendars right now, so remap those.
-    //
-    if (calendar >= 13 && calendar < 23)
-    {
-        switch (calendar)
-        {
-            case RESERVED_CAL_PERSIAN: // don't change if we have Persian calendar
-                break;
-
-            case RESERVED_CAL_JAPANESELUNISOLAR:    // Data looks like Japanese
-                calendar=CAL_JAPAN;
-                break;
-            case RESERVED_CAL_JULIAN:               // Data looks like gregorian US
-            case RESERVED_CAL_CHINESELUNISOLAR:     // Algorithmic, so actual data is irrelevent
-            case RESERVED_CAL_SAKA:                 // reserved to match Office but not implemented in our code, so data is irrelevent
-            case RESERVED_CAL_LUNAR_ETO_CHN:        // reserved to match Office but not implemented in our code, so data is irrelevent
-            case RESERVED_CAL_LUNAR_ETO_KOR:        // reserved to match Office but not implemented in our code, so data is irrelevent
-            case RESERVED_CAL_LUNAR_ETO_ROKUYOU:    // reserved to match Office but not implemented in our code, so data is irrelevent
-            case RESERVED_CAL_KOREANLUNISOLAR:      // Algorithmic, so actual data is irrelevent
-            case RESERVED_CAL_TAIWANLUNISOLAR:      // Algorithmic, so actual data is irrelevent
-            default:
-                calendar = CAL_GREGORIAN_US;
-                break;
-        }
-    }
-
-    //
-    // Speical handling for some special calendar due to OS limitation.
-    // This includes calendar like Taiwan calendar, UmAlQura calendar, etc.
-    //
-    CheckSpecialCalendar(&calendar, &localeNameStackBuffer);
-
-
-    // Numbers
-    ret &= CallGetCalendarInfoEx(localeNameStackBuffer, calendar,
-                                 CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER | useOverrides,
-                                 &(gc.calendarData->iTwoDigitYearMax));
-
-    if (ret == FALSE) // failed call
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_ITWODIGITYEARMAX");
-    }
-
-    _ASSERTE(ret == TRUE);
-
-    // Strings
-    if (CallGetCalendarInfoEx(localeNameStackBuffer, calendar, CAL_SCALNAME , &stringResult))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->sNativeName), stringResult, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SCALNAME");
-        ret = FALSE;
-    }
-    if (CallGetCalendarInfoEx(localeNameStackBuffer, calendar, CAL_SMONTHDAY | useOverrides, &stringResult))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->sMonthDay), stringResult, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read RESERVED_CAL_SMONTHDAY");
-        ret = FALSE;
-    }
-
-    // String Arrays
-    // Formats
-    PTRARRAYREF array = NULL;
-    if (CallEnumCalendarInfo(localeNameStackBuffer, calendar, CAL_SSHORTDATE, LOCALE_SSHORTDATE | useOverrides, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saShortDates), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SSHORTDATE");
-        ret = FALSE;
-    }
-    if (CallEnumCalendarInfo(localeNameStackBuffer, calendar, CAL_SLONGDATE, LOCALE_SLONGDATE | useOverrides, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saLongDates), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SLONGDATE");
-        ret = FALSE;
-    }
-
-    // Get the YearMonth pattern.
-    // Before Windows Vista, NLS would not write the Year/Month pattern into the reg key.
-    // This causes GetLocaleInfo() to retrieve the Gregorian localized calendar pattern even when the calendar is not Gregorian localized.
-    // So we will call GetLocaleInfo() only when the reg key for sYearMonth is there.
-    //
-    // If the key does not exist, leave yearMonthPattern to be null, so that we will pick up the default table value.
-
-    int useOverridesForYearMonthPattern = useOverrides;
-    if (useOverridesForYearMonthPattern == 0)
-    {
-        HKEY hkey = NULL;
-        useOverridesForYearMonthPattern = CAL_NOUSEROVERRIDE;
-        if (WszRegOpenKeyEx(HKEY_CURRENT_USER, W("Control Panel\\International"), 0, KEY_READ, &hkey) == ERROR_SUCCESS)
-        {
-            if (WszRegQueryValueEx(hkey, W("sYearMonth"), 0, NULL, NULL, NULL) == ERROR_SUCCESS)
-            {
-                // The sYearMonth key exists.  Call GetLocaleInfo() to read it.
-                useOverridesForYearMonthPattern = 0; // now we can use the overrides
-            }
-            RegCloseKey(hkey);
-        }
-    }
-
-    if (CallEnumCalendarInfo(localeNameStackBuffer, calendar, CAL_SYEARMONTH, LOCALE_SYEARMONTH | useOverridesForYearMonthPattern, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saYearMonths), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SYEARMONTH");
-        ret = FALSE;
-    }
-
-    // Day & Month Names
-    // These are all single calType entries, 1 per day, so we have to make 7 or 13 calls to collect all the names
-
-    // Day
-    // Note that we're off-by-one since managed starts on sunday and windows starts on monday
-    if (GetCalendarDayInfo(localeNameStackBuffer, calendar, CAL_SDAYNAME7, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saDayNames), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SDAYNAME7");
-        ret = FALSE;
-    }
-    if (GetCalendarDayInfo(localeNameStackBuffer, calendar, CAL_SABBREVDAYNAME7, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saAbbrevDayNames), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SABBREVDAYNAME7");
-        ret = FALSE;
-    }
-
-    // Month names
-    if (GetCalendarMonthInfo(localeNameStackBuffer, calendar, CAL_SMONTHNAME1, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saMonthNames), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SMONTHNAME1");
-        ret = FALSE;
-    }
-
-    if (GetCalendarMonthInfo(localeNameStackBuffer, calendar, CAL_SABBREVMONTHNAME1, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saAbbrevMonthNames), array, NULL);
-    else
-    {
-        _ASSERTE(!"nativeGetCalendarData could not read CAL_SABBREVMONTHNAME1");
-        ret = FALSE;
-    }
-
-    //
-    // The following LCTYPE are not supported in some platforms.  If the call fails,
-    // don't return a failure.
-    //
-    if (GetCalendarDayInfo(localeNameStackBuffer, calendar, CAL_SSHORTESTDAYNAME7, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saSuperShortDayNames), array, NULL);
-
-
-    // Gregorian may have genitive month names
-    if (calendar == CAL_GREGORIAN)
-    {
-        if (GetCalendarMonthInfo(localeNameStackBuffer, calendar, CAL_SMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, &array))
-            SetObjectReference((OBJECTREF*)&(gc.calendarData->saMonthGenitiveNames), array, NULL);
-        // else we ignore the error and let managed side copy the normal month names
-        if (GetCalendarMonthInfo(localeNameStackBuffer, calendar, CAL_SABBREVMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, &array))
-            SetObjectReference((OBJECTREF*)&(gc.calendarData->saAbbrevMonthGenitiveNames), array, NULL);
-        // else we ignore the error and let managed side copy the normal month names
-    }
-
-//  leap year names are only different for month 6 in Hebrew calendar
-//    PTRARRAYREF saLeapYearMonthNames      ; // Multiple strings for the month names in a leap year. (Hebrew's the only one that has these)
-
-    // Calendar Parts Names
-    if (CallEnumCalendarInfo(localeNameStackBuffer, calendar, CAL_SERASTRING, NULL, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saEraNames), array, NULL);
-    // else we set the era in managed code
-    if (CallEnumCalendarInfo(localeNameStackBuffer, calendar, CAL_SABBREVERASTRING, NULL, &array))
-        SetObjectReference((OBJECTREF*)&(gc.calendarData->saAbbrevEraNames), array, NULL);
-    // else we set the era in managed code
-
-    //    PTRARRAYREF saAbbrevEnglishEraNames   ; // Abbreviated Era Names in English
-
-    //
-    // Calendar Era Info
-    // Note that calendar era data (offsets, etc) is hard coded for each calendar since this
-    // data is implementation specific and not dynamic (except perhaps Japanese)
-    //
-
-    HELPER_METHOD_FRAME_END();
-
-    FC_RETURN_BOOL(ret);
-}
-FCIMPLEND
-
-//
-// Get the system two digit year max value for the specified calendar
-//
-FCIMPL1(INT32, CalendarData::nativeGetTwoDigitYearMax, INT32 calendar)
-{
-    FCALL_CONTRACT;
-
-    DWORD dwTwoDigitYearMax = (DWORD) -1;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_0();
-
-    WCHAR strName[LOCALE_NAME_MAX_LENGTH];
-
-    // Really we should just be able to pass NULL for the locale name since that
-    // causes the OS to look up the user default locale name.  The downlevel APIS could
-    // emulate this as necessary
-    if (NewApis::GetUserDefaultLocaleName(strName,NumItems(strName)) == 0 ||
-        NewApis::GetCalendarInfoEx(strName, calendar, NULL, CAL_ITWODIGITYEARMAX | CAL_RETURN_NUMBER, NULL, 0,&dwTwoDigitYearMax) == 0)
-    {
-        dwTwoDigitYearMax = (DWORD) -1;
-        goto lExit;
-    }
-
-lExit: ;
-    HELPER_METHOD_FRAME_END();
-
-    return (dwTwoDigitYearMax);
-}
-FCIMPLEND
-
-//
-// nativeGetCalendars
-//
-// Get the list of acceptable calendars for this user/locale
-//
-// Might be a better way to marshal the int[] for calendars
-// We expect the input array to be 23 ints long.  We then fill up the first "count" ints and return the count.
-// The caller should then make it a smaller array.
-//
-
-// Perhaps we could do something more like this...
-//U1ARRAYREF rgbOut = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cb);
-//memcpyNoGCRefs(rgbOut->GetDirectPointerToNonObjectElements(), rgbKey, cb * sizeof(BYTE));
-//
-//refRetVal = rgbOut;
-//
-//HELPER_METHOD_FRAME_END();
-//return (U1Array*) OBJECTREFToObject(refRetVal);
-
-//
-// struct to help our calendar data enumaration callback
-//
-struct enumCalendarsData
-{
-    int     count;          // # of strings found so far
-    CALID   userOverride;   // user override value (if found)
-    INT32*  calendarList;   // list of calendars found so far
-};
-
-//
-// callback itself
-//
-BOOL CALLBACK EnumCalendarsCallback(__in_z LPWSTR lpCalendarInfoString, __in CALID Calendar, __in_opt LPWSTR pReserved, __in LPARAM lParam)
-{
-    CONTRACTL
-    {
-        GC_NOTRIGGER;
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-        PRECONDITION(CheckPointer(lpCalendarInfoString));
-        PRECONDITION(CheckPointer((LPVOID)lParam));
-    } CONTRACTL_END;
-
-    // Cast our data to the right type
-    enumCalendarsData* pData = (enumCalendarsData*)lParam;
-
-    // If we had a user override, check to make sure this differs
-    if (pData->userOverride == Calendar)
-    {
-        // Its the same, just return
-        return TRUE;
-    }
-
-    // They're different, add it to our buffer, check we have room
-    if (pData->count < 23)
-    {
-        pData->calendarList[pData->count++] = Calendar;
-    }
-
-    return TRUE;
-}
-
-FCIMPL3(INT32, CalendarData::nativeGetCalendars, StringObject* pLocaleNameUNSAFE, CLR_BOOL useOverrides, I4Array* calendarsUNSAFE)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(pLocaleNameUNSAFE));
-    } CONTRACTL_END;
-
-    int ret = 0;
-
-    struct _gc
-    {
-        STRINGREF                localeName;
-        I4ARRAYREF               calendarsRef;
-    } gc;
-
-    // Dereference our string
-    gc.localeName   = (STRINGREF)pLocaleNameUNSAFE;
-    gc.calendarsRef = (I4ARRAYREF)calendarsUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
-    int    calendarBuffer[23];
-    struct enumCalendarsData data;
-    data.count = 0;
-    data.userOverride = 0;
-    data.calendarList = calendarBuffer;
-
-    // First call GetLocaleInfo if necessary
-    if (useOverrides)
-    {
-        // They want user overrides, see if the user calendar matches the input calendar
-
-        CALID userCalendar = 0;
-        NewApis::GetLocaleInfoEx( gc.localeName->GetBuffer(), LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
-                                            (LPWSTR)&userCalendar, sizeof(userCalendar) / sizeof(WCHAR) );
-
-        // If we got a default, then use it as the first calendar
-        if (userCalendar != 0)
-        {
-            data.userOverride = userCalendar;
-            data.calendarList[data.count++] = userCalendar;
-        }
-    }
-
-    // Now call the enumeration API. Work is done by our callback function
-    NewApis::EnumCalendarInfoExEx(EnumCalendarsCallback, gc.localeName->GetBuffer(), ENUM_ALL_CALENDARS, CAL_ICALINTVALUE, (LPARAM)&(data));
-
-    // Copy to the output array
-    for (int i = 0; i < data.count; i++)
-    {
-        (gc.calendarsRef->GetDirectPointerToNonObjectElements())[i] = calendarBuffer[i];
-    }
-
-    ret = data.count;
-    HELPER_METHOD_FRAME_END();
-
-    // Now we have a list of data, return the count
-    return ret;
-}
-FCIMPLEND
-
-//
-// nativeEnumTimeFormats
-//
-// Enumerate all of the time formats (long times) on the system.
-// Windows only has 1 time format so there's nothing like an LCTYPE here.
-//
-// Note that if the locale is the user default locale windows ALWAYS returns the user override value first.
-// (ie: there's no no-user-override option for this API)
-//
-// We reuse the enumData structure since it works for us.
-//
-
-//
-// callback itself
-//
-BOOL CALLBACK EnumTimeFormatsCallback(__in_z LPCWSTR lpTimeFormatString, __in LPARAM lParam)
-{
-    CONTRACTL
-    {
-        GC_NOTRIGGER;
-        MODE_COOPERATIVE;
-        SO_TOLERANT;
-        PRECONDITION(CheckPointer(lpTimeFormatString));
-        PRECONDITION(CheckPointer((LPVOID)lParam));
-    } CONTRACTL_END;
-
-    // Cast our data to the right type
-    enumData* pData = (enumData*)lParam;
-
-    // Don't have to worry about user overrides (the enum adds them)
-    // add it to our buffer
-    LPWSTR pStart = pData->stringsBuffer;
-    LPCWSTR pEnd = pData->endOfBuffer;
-    while (pStart < pEnd && *lpTimeFormatString != 0)
-    {
-        *(pStart++) = *(lpTimeFormatString++);
-    }
-
-    // Add a \0
-    if (pStart < pEnd)
-    {
-        *(pStart++) = 0;
-
-        // Did it finish?
-        if (pStart <= pEnd)
-        {
-            // It finished, use it
-            pData->count++;
-            pData->stringsBuffer = pStart;
-        }
-    }
-
-    return TRUE;
-}
-
-//
-// nativeEnumTimeFormats that calls the callback above
-//
-FCIMPL3(Object*, CalendarData::nativeEnumTimeFormats,
-        StringObject* pLocaleNameUNSAFE, INT32 dwFlags, CLR_BOOL useUserOverride)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(pLocaleNameUNSAFE));
-    } CONTRACTL_END;
-
-
-    struct _gc
-    {
-        STRINGREF       localeName;
-        PTRARRAYREF     timeFormatsArray;
-    } gc;
-
-    // Dereference our gc objects
-    gc.localeName = (STRINGREF)pLocaleNameUNSAFE;
-    gc.timeFormatsArray = NULL;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
-    // Our longest string in culture.xml is shorter than this and it has lots of \x type characters, so this should be long enough by far.
-    WCHAR   stringBuffer[512];
-    struct enumData data;
-    data.count = 0;
-    data.userOverride = NULL;
-    data.stringsBuffer = stringBuffer;
-    data.endOfBuffer = stringBuffer + 512; // We're adding WCHAR sizes
-
-    // Now call the enumeration API. Work is done by our callback function
-    NewApis::EnumTimeFormatsEx((TIMEFMT_ENUMPROCEX)EnumTimeFormatsCallback, gc.localeName->GetBuffer(), dwFlags, (LPARAM)&data);
-
-    if (data.count > 0)
-    {
-        // Now we need to allocate our stringarray and populate it
-        // Get our array object (will throw, don't have to check it)
-        gc.timeFormatsArray = (PTRARRAYREF) AllocateObjectArray(data.count, g_pStringClass);
-
-        LPCWSTR buffer = stringBuffer;   // Restart @ buffer beginning
-        for(DWORD i = 0; i < (DWORD)data.count; i++) // todo: cast to compile on Mac
-        {
-            OBJECTREF o = (OBJECTREF) StringObject::NewString(buffer);
-            gc.timeFormatsArray->SetAt(i, o);
-
-            buffer += (lstrlenW(buffer) + 1);
-        }
-
-        if(!useUserOverride && data.count > 1)
-        {
-            // Since there is no "NoUserOverride" aware EnumTimeFormatsEx, we always get an override
-            // The override is the first entry if it is overriden.
-            // We can check if we have overrides by checking the GetLocaleInfo with no override
-            // If we do have an override, we don't know if it is a user defined override or if the
-            // user has just selected one of the predefined formats so we can't just remove it
-            // but we can move it down.
-            WCHAR timeFormatNoUserOverride[LOCALE_NAME_MAX_LENGTH];
-            DWORD lcType = (dwFlags == TIME_NOSECONDS) ? LOCALE_SSHORTTIME : LOCALE_STIMEFORMAT;
-            lcType |= LOCALE_NOUSEROVERRIDE;
-            int result = NewApis::GetLocaleInfoEx(gc.localeName->GetBuffer(), lcType, timeFormatNoUserOverride, LOCALE_NAME_MAX_LENGTH);
-            if(result != 0)
-            {
-                STRINGREF firstTimeFormat = (STRINGREF)gc.timeFormatsArray->GetAt(0);
-                if(wcscmp(timeFormatNoUserOverride, firstTimeFormat->GetBuffer())!=0)
-                {
-                    gc.timeFormatsArray->SetAt(0, gc.timeFormatsArray->GetAt(1));
-                    gc.timeFormatsArray->SetAt(1, firstTimeFormat);
-                }
-            }
-        }
-
-    }
-
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(gc.timeFormatsArray);
-}
-FCIMPLEND
-
-
index 7afe116..b1d65e3 100644 (file)
 //  Constant Declarations.
 //
 
-#ifndef COMPARE_OPTIONS_IGNORECASE
-#define COMPARE_OPTIONS_IGNORECASE  0x00000001
-#endif
-
-#ifndef LOCALE_SNAME
-#define LOCALE_SNAME                0x0000005c
-#endif
-
-#ifndef LOCALE_SNAN
-#define LOCALE_SNAN                 0x00000069
-#endif
-
-#ifndef LOCALE_SPOSINFINITY
-#define LOCALE_SPOSINFINITY         0x0000006a
-#endif
-
-#ifndef LOCALE_SNEGINFINITY
-#define LOCALE_SNEGINFINITY         0x0000006b
-#endif
-
-#ifndef LOCALE_SPARENT
-#define LOCALE_SPARENT              0x0000006d
-#endif
-
-#ifndef LOCALE_SCONSOLEFALLBACKNAME
-#define LOCALE_SCONSOLEFALLBACKNAME 0x0000006e   // Fallback name for within the console
-#endif
-
-#ifndef LOCALE_SISO3166CTRYNAME2
-#define LOCALE_SISO3166CTRYNAME2    0x00000068
-#endif
-
-#ifndef LOCALE_SISO639LANGNAME2
-#define LOCALE_SISO639LANGNAME2     0x00000067
-#endif
-
-#ifndef LOCALE_SSHORTESTDAYNAME1
-#define LOCALE_SSHORTESTDAYNAME1    0x00000060
-#endif
-
-// Windows 7 LCTypes
-#ifndef LOCALE_INEUTRAL
-#define LOCALE_INEUTRAL             0x00000071   // Returns 0 for specific cultures, 1 for neutral cultures.
-#endif
-
-#ifndef LCMAP_TITLECASE
-#define LCMAP_TITLECASE             0x00000300   // Title Case Letters
-#endif
-
-// Windows 8 LCTypes
-#ifndef LCMAP_SORTHANDLE
-#define LCMAP_SORTHANDLE   0x20000000
-#endif
-
-#ifndef LCMAP_HASH
-#define LCMAP_HASH   0x00040000
-#endif
-
-#ifndef LOCALE_REPLACEMENT
-#define LOCALE_REPLACEMENT          0x00000008   // locales that replace shipped locales (callback flag only)
-#endif // LOCALE_REPLACEMENT
-
-#define LOCALE_MAX_STRING_SIZE      530          // maximum sice of LOCALE_SKEYBOARDSTOINSTALL, currently 5 "long" + 2 "short" keyboard signatures (YI + 3).
-
 #define MAX_STRING_VALUE        512
 
 // TODO: NLS Arrowhead -Be nice if we could depend more on the OS for this
-// Language ID for CHT (Taiwan)
-#define LANGID_ZH_TW            0x0404
-// Language ID for CHT (Hong-Kong)
-#define LANGID_ZH_HK            0x0c04
-#define REGION_NAME_0404 W("\x53f0\x7063")
-#if BIGENDIAN
-#define INTERNATIONAL_CURRENCY_SYMBOL W("\x00a4")
-#else
-#define INTERNATIONAL_CURRENCY_SYMBOL W("\xa400")
-#endif
-
-inline BOOL IsCustomCultureId(LCID lcid)
-{
-    return (lcid == LOCALE_CUSTOM_DEFAULT || lcid == LOCALE_CUSTOM_UNSPECIFIED);
-}
-
-#ifndef FEATURE_COREFX_GLOBALIZATION
-//
-// Normalization Implementation
-//
-#define NORMALIZATION_DLL       MAKEDLLNAME(W("normalization"))
-HMODULE COMNlsInfo::m_hNormalization = NULL;
-PFN_NORMALIZATION_IS_NORMALIZED_STRING COMNlsInfo::m_pfnNormalizationIsNormalizedStringFunc = NULL;
-PFN_NORMALIZATION_NORMALIZE_STRING COMNlsInfo::m_pfnNormalizationNormalizeStringFunc = NULL;
-PFN_NORMALIZATION_INIT_NORMALIZATION COMNlsInfo::m_pfnNormalizationInitNormalizationFunc = NULL;
-#endif // FEATURE_COREFX_GLOBALIZATION
-
-
-// InternalIsSortable
-//
-// Called by CompareInfo.IsSortable() to determine if a string has entirely sortable (ie: defined) code points.
-BOOL QCALLTYPE COMNlsInfo::InternalIsSortable(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR localeName, LPCWSTR string, INT32 length)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        PRECONDITION(CheckPointer(string));
-    } CONTRACTL_END;
-    BOOL result = FALSE;
-    BEGIN_QCALL;
-
-    {
-        // Function should be COMPARE_STRING, dwFlags should be NULL, lpVersionInfo should be NULL for now
-        result = NewApis::IsNLSDefinedString(COMPARE_STRING, 0, NULL, string, length);
-    }
-
-    END_QCALL;
-    return result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-//  InternalGetUserDefaultLocaleName
-//
-//  Returns a string with the name of our LCID and returns 0 in LCID.
-//  If we cant return
-//
-////////////////////////////////////////////////////////////////////////////
-// This is new to longhorn
-BOOL QCALLTYPE COMNlsInfo::InternalGetDefaultLocaleName(INT32 langType, QCall::StringHandleOnStack defaultLocaleName)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        PRECONDITION((langType == LOCALE_SYSTEM_DEFAULT) || (langType == LOCALE_USER_DEFAULT));
-    } CONTRACTL_END;
-
-    BOOL result;
-    BEGIN_QCALL;
-
-    WCHAR strName[LOCALE_NAME_MAX_LENGTH];
-    int size = 0;
-
-    if (langType == LOCALE_SYSTEM_DEFAULT)
-    {
-        size = NewApis::GetSystemDefaultLocaleName(strName,NumItems(strName));
-    }
-    else
-    {
-        _ASSERT(langType == LOCALE_USER_DEFAULT);
-        size = NewApis::GetUserDefaultLocaleName(strName,NumItems(strName));
-    }
-
-    // Not found, either not longhorn (no LOCALE_SNAME) or not a valid name
-    if (size == 0)
-    {
-        result = false;
-    }
-    else
-    {
-        defaultLocaleName.Set(strName);
-        result = true;
-    }
-    END_QCALL;
-    return result;
-}
-
-BOOL QCALLTYPE COMNlsInfo::InternalGetSystemDefaultUILanguage(QCall::StringHandleOnStack systemDefaultUiLanguage)
-{
-    QCALL_CONTRACT;
-    BOOL result;
-    BEGIN_QCALL;
-
-    WCHAR localeName[LOCALE_NAME_MAX_LENGTH];
-
-    int systemDefaultUiLcid = GetSystemDefaultUILanguage();
-    if(systemDefaultUiLcid == LANGID_ZH_TW)
-    {
-        if (!NewApis::IsZhTwSku())
-        {
-             systemDefaultUiLcid = LANGID_ZH_HK;
-        } 
-    }
-    
-    int length = NewApis::LCIDToLocaleName(systemDefaultUiLcid, localeName, NumItems(localeName), 0);
-    if (length == 0)
-    {
-        result = false;
-    }
-    else
-    {
-        systemDefaultUiLanguage.Set(localeName);
-        result = true;
-    }
-
-    END_QCALL;
-    return result;
-}
-
-/*
- */
-BOOL QCALLTYPE COMNlsInfo::InternalGetUserDefaultUILanguage(QCall::StringHandleOnStack userDefaultUiLanguage)
-{
-    QCALL_CONTRACT;
-    BOOL result;
-    BEGIN_QCALL;
-
-    WCHAR wszBuffer[LOCALE_NAME_MAX_LENGTH];
-    LPCWSTR wszLangName=NULL;
-
-    int res= 0;
-    ULONG uLangCount=0;
-    ULONG uBufLen=0;
-    res= NewApis::GetUserPreferredUILanguages (MUI_LANGUAGE_NAME,&uLangCount,NULL,&uBufLen);
-    if (res == 0)
-        ThrowLastError();
-
-
-    NewArrayHolder<WCHAR> sPreferredLanguages(NULL);
-
-    if (uBufLen > 0 && uLangCount > 0 )
-    {
-        sPreferredLanguages = new WCHAR[uBufLen];
-        res= NewApis::GetUserPreferredUILanguages (MUI_LANGUAGE_NAME,&uLangCount,sPreferredLanguages,&uBufLen);
-
-        if (res == 0)
-            ThrowLastError();
-
-         wszLangName=sPreferredLanguages;
-// Review size_t to int conversion (possible loss of data).
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4267)
-#endif
-        res=wcslen(wszLangName)+1;
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-    }
-    else
-    {
-        res=0;
-    }
-
-    if (res == 0) {
-        res = NewApis::GetUserDefaultLocaleName(wszBuffer,NumItems(wszBuffer));
-        wszLangName=wszBuffer;
-    }
-
-
-    // If not found, either not longhorn (no LOCALE_SNAME) or not a valid name
-    if (res == 0)
-    {
-        // Didn't find string, return an empty string.
-        result = false;
-    }
-    else
-    {
-        userDefaultUiLanguage.Set(wszLangName);
-        result = true;
-    }
-
-    // Return the found language name.  LCID should be found one already.
-    END_QCALL;
-    return result;
-}
-
-INT32 COMNlsInfo::CallGetUserDefaultUILanguage()
-{
-    CONTRACTL
-    {
-        NOTHROW;
-        GC_NOTRIGGER;
-        MODE_ANY;
-        SO_TOLERANT;
-    } CONTRACTL_END;
-
-    static INT32 s_lcid = 0;
-
-    // The user UI language cannot change within a process (in fact it cannot change within a logon session),
-    // so we cache it. We dont take a lock while initializing s_lcid for the same reason. If two threads are
-    // racing to initialize s_lcid, the worst thing that'll happen is that one thread will call
-    // GetUserDefaultUILanguage needlessly, but the final result is going to be the same.
-    if (s_lcid == 0)
-    {
-        INT32 s_lcidTemp = GetUserDefaultUILanguage();
-        if (s_lcidTemp == LANGID_ZH_TW)
-        {
-            // If the UI language ID is 0x0404, we need to do extra check to decide
-            // the real UI language, since MUI (in CHT)/HK/TW Windows SKU all uses 0x0404 as their CHT language ID.
-            if (!NewApis::IsZhTwSku())
-            {
-                s_lcidTemp = LANGID_ZH_HK;
-            }
-        }
-        s_lcid = s_lcidTemp;
-    }
-
-    return s_lcid;
-}
-
-
-FCIMPL2(Object*, COMNlsInfo::nativeGetLocaleInfoEx, StringObject* localeNameUNSAFE, INT32 lcType)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    struct _gc
-    {
-        STRINGREF   localeName;
-        STRINGREF   refRetVal;
-    } gc;
-
-    // Dereference our string
-    gc.refRetVal = NULL;
-    gc.localeName = (STRINGREF)localeNameUNSAFE;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-    StackSString localeNameStackBuffer( gc.localeName->GetBuffer() );
-
-    WCHAR buffer[LOCALE_MAX_STRING_SIZE];
-    int result = NewApis::GetLocaleInfoEx(localeNameStackBuffer, lcType, buffer, NumItems(buffer));
-
-    // Make a string out of it
-    if (result != 0)
-    {
-        // Exclude the NULL char at the end, except that LOCALE_FONTSIGNATURE isn't
-        // really a string, so we need the last character too.
-        gc.refRetVal = StringObject::NewString(buffer, ((lcType & ~LOCALE_NOUSEROVERRIDE) == LOCALE_FONTSIGNATURE) ? result : result-1);
-    }
-    else
-    {
-    }
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(gc.refRetVal);
-}
-FCIMPLEND
-
-
-FCIMPL2(INT32, COMNlsInfo::nativeGetLocaleInfoExInt, StringObject* localeNameUNSAFE, INT32 lcType)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    INT32 result = 0;
-
-    // Dereference our string
-    STRINGREF localeName = (STRINGREF)localeNameUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(localeName);
-
-    lcType |= LOCALE_RETURN_NUMBER;
-
-    if (NewApis::GetLocaleInfoEx(localeName->GetBuffer(), lcType, (LPWSTR)&result, sizeof(INT32) / sizeof (WCHAR)) == 0)
-    {
-        // return value of 0 indicates failure and error value is supposed to be set.
-        // shouldn't ever really happen
-        _ASSERTE(!"catastrophic failure calling NewApis::nativeGetLocaleInfoExInt!  This could be a CultureInfo bug (bad localeName string) or maybe a GCHole.");
-    }
-
-    HELPER_METHOD_FRAME_END();
-
-    return result;
-}
-FCIMPLEND
-
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Call the Win32 GetLocaleInfo() using the specified lcid to retrieve
-// the native digits, probably from the registry override. The return
-// indicates whether the call was successful.
-//
-// Parameters:
-//       IN lcid            the LCID to make the Win32 call with
-//      OUT pOutputStrAry   The output managed string array.
-//
-////////////////////////////////////////////////////////////////////////
-BOOL COMNlsInfo::GetNativeDigitsFromWin32(LPCWSTR locale, PTRARRAYREF * pOutputStrAry, BOOL useUserOverride)
-{
-    CONTRACTL
-    {
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        THROWS;
-    } CONTRACTL_END;
-
-    WCHAR buffer[11];
-    int result = 0;
-
-    DWORD lcType = LOCALE_SNATIVEDIGITS;
-    if(!useUserOverride)
-    {
-        lcType |= LOCALE_NOUSEROVERRIDE;
-    }
-    result = NewApis::GetLocaleInfoEx(locale, lcType, buffer, 11);
-    // Be very unforgiving and only support strings of size 10 plus the NULL
-    if (result == 11)
-    {
-        // Break up the unmanaged ten-character ZLS into what NFI wants (a managed
-        // ten-string array).
-        //
-        // Allocate the array of STRINGREFs.  We don't need to check for null because the GC will throw
-        // an OutOfMemoryException if there's not enough memory.
-        //
-        PTRARRAYREF DigitArray = (PTRARRAYREF) AllocateObjectArray(10, g_pStringClass);
-
-        GCPROTECT_BEGIN(DigitArray);
-        for(DWORD i = 0;  i < 10; i++) {
-            OBJECTREF o = (OBJECTREF) StringObject::NewString(buffer + i, 1);
-            DigitArray->SetAt(i, o);
-        }
-        GCPROTECT_END();
-
-        _ASSERTE(pOutputStrAry != NULL);
-        *pOutputStrAry = DigitArray;
-    }
-
-    return (result == 11);
-}
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Call the Win32 GetLocaleInfoEx() using the specified lcid and LCTYPE.
-// The return value can be INT32 or an allocated managed string object, depending on
-// which version's called.
-//
-// Parameters:
-//      OUT pOutputInt32    The output int32 value.
-//      OUT pOutputRef      The output string value.
-//
-////////////////////////////////////////////////////////////////////////
-BOOL COMNlsInfo::CallGetLocaleInfoEx(LPCWSTR localeName, int lcType, INT32* pOutputInt32, BOOL useUserOverride)
-{
-    CONTRACTL
-    {
-        GC_NOTRIGGER;
-        MODE_ANY;
-        NOTHROW;
-    } CONTRACTL_END;
-
-    int result = 0;
-
-    _ASSERT((lcType & LOCALE_RETURN_NUMBER) != 0);
-    if(!useUserOverride)
-    {
-        lcType |= LOCALE_NOUSEROVERRIDE;
-    }
-    result = NewApis::GetLocaleInfoEx(localeName, lcType, (LPWSTR)pOutputInt32, sizeof(*pOutputInt32));
-
-    return (result != 0);
-}
-
-BOOL COMNlsInfo::CallGetLocaleInfoEx(LPCWSTR localeName, int lcType, STRINGREF* pOutputStrRef, BOOL useUserOverride)
-{
-    CONTRACTL
-    {
-        THROWS;                 // We can throw since we are allocating managed string.
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-    } CONTRACTL_END;
-
-    WCHAR buffer[LOCALE_NAME_MAX_LENGTH];
-    int result = 0;
-
-    _ASSERT((lcType & LOCALE_RETURN_NUMBER) == 0);
-    if(!useUserOverride)
-    {
-        lcType |= LOCALE_NOUSEROVERRIDE;
-    }
-    result = NewApis::GetLocaleInfoEx(localeName, lcType, buffer, LOCALE_NAME_MAX_LENGTH);
-
-    if (result != 0)
-    {
-        _ASSERTE(pOutputStrRef != NULL);
-        *pOutputStrRef = StringObject::NewString(buffer, result - 1);
-    }
-
-    return (result != 0);
-}
-
-FCIMPL1(Object*, COMNlsInfo::LCIDToLocaleName, LCID lcid)
-{
-    FCALL_CONTRACT;
-
-    STRINGREF refRetVal = NULL;
-
-    // The maximum size for locale name is 85 characters.
-    WCHAR localeName[LOCALE_NAME_MAX_LENGTH];
-    int result = 0;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_0();
-
-    // Note that this'll return neutral names (unlike native Vista APIs)
-    result = NewApis::LCIDToLocaleName(lcid, localeName, LOCALE_NAME_MAX_LENGTH, 0);
-
-    if (result != 0)
-    {
-        refRetVal = StringObject::NewString(localeName, result - 1);
-    }
-    else
-    {
-        refRetVal = StringObject::GetEmptyString();
-    }
-
-    HELPER_METHOD_FRAME_END();
-
-    return OBJECTREFToObject(refRetVal);
-}
-FCIMPLEND
-
-FCIMPL1(INT32, COMNlsInfo::LocaleNameToLCID, StringObject* localeNameUNSAFE)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    INT32 result = 0;
-
-    // Dereference our string
-    STRINGREF localeName = (STRINGREF)localeNameUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(localeName);
-
-    // Note that this'll return neutral names (unlike native Vista APIs)
-    result = NewApis::LocaleNameToLCID(localeName->GetBuffer(), 0);
-
-    HELPER_METHOD_FRAME_END();
-
-    return result;
-}
-FCIMPLEND
-
-////////////////////////////////////////////////////////////////////////
-//
-// Implementation of CultureInfo.nativeGetNumberFormatInfoValues.
-//
-// Retrieve NumberFormatInfo (NFI) properties from windows
-//
-// Parameters:
-//      IN/OUT pNumfmtUNSAFE
-//                  The pointer of the managed NumberFormatInfo passed
-//                  from the managed side.
-//                  Note that the native NumberFormatInfo* is defined
-//                  in COMNumber.h
-// Note:
-// Managed string will be allocated and assign to the string fields in
-//      the managed NumberFormatInfo passed in pNumftUNSAFE
-//
-////////////////////////////////////////////////////////////////////////
-
-
-/*
-    This is the list of the data members in the managed NumberFormatInfo and their
-    corresponding LCTYPE().
-
-    Win32 GetLocaleInfo() constants             Data members in NumberFormatInfo in the defined order.
-    LOCALE_SPOSITIVE                            // String positiveSign
-    LOCALE_SNEGATIVE                            // String negativeSign
-    LOCALE_SDECIMAL                             // String numberDecimalSeparator
-    LOCALE_SGROUPING                            // String numberGroupSeparator
-    LOCALE_SMONGROUPING                         // String currencyGroupSeparator
-    LOCALE_SMONDECIMALSEP                       // String currencyDecimalSeparator
-    LOCALE_SCURRENCY                            // String currencySymbol
-    N/A                                         // String ansiCurrencySymbol
-    N/A                                         // String nanSymbol
-    N/A                                         // String positiveInfinitySymbol
-    N/A                                         // String negativeInfinitySymbol
-    N/A                                         // String percentDecimalSeparator
-    N/A                                         // String percentGroupSeparator
-    N/A                                         // String percentSymbol
-    N/A                                         // String perMilleSymbol
-
-    N/A                                         // int m_dataItem
-
-    LOCALE_IDIGITS | LOCALE_RETURN_NUMBER,      // int numberDecimalDigits
-    LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER,  // int currencyDecimalDigits
-    LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER,    // int currencyPositivePattern
-    LOCALE_INEGCURR | LOCALE_RETURN_NUMBER,      // int currencyNegativePattern
-    LOCALE_INEGNUMBER| LOCALE_RETURN_NUMBER,    // int numberNegativePattern
-    N/A                                         // int percentPositivePattern
-    N/A                                         // int percentNegativePattern
-    N/A                                         // int percentDecimalDigits
-    N/A                                         // bool isReadOnly=false;
-    N/A                                         // internal bool m_useUserOverride;
-*/
-FCIMPL3(FC_BOOL_RET, COMNlsInfo::nativeGetNumberFormatInfoValues,
-        StringObject* localeNameUNSAFE, NumberFormatInfo* pNumfmtUNSAFE, CLR_BOOL useUserOverride) {
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    BOOL ret = TRUE;
-
-    struct _gc
-    {
-        STRINGREF   localeName;
-        STRINGREF   stringResult;
-        NUMFMTREF   numfmt;
-        PTRARRAYREF tempArray;
-    } gc;
-
-    // Dereference our string
-    gc.localeName = (STRINGREF)localeNameUNSAFE;
-    gc.numfmt = (NUMFMTREF) pNumfmtUNSAFE;
-    gc.stringResult = NULL;
-    gc.tempArray = NULL;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-    StackSString localeNameStackBuffer( gc.localeName->GetBuffer() );
-    
-    // Calling SString::ConvertToUnicode once
-    LPCWSTR pLocaleName = localeNameStackBuffer;
-    
-    //
-    // NOTE: We pass the stringResult allocated in the stack and assign it to the fields
-    // in numfmt after calling CallGetLocaleInfo().  The reason for this is that CallGetLocaleInfo()
-    // allocates a string object, and it may trigger a GC and cause numfmt to be moved.
-    // That's why we use the stringResult allocated in the stack since it will not be moved.
-    // After CallGetLocaleInfo(), we know that numfmt will not be moved, and it's safe to assign
-    // the stringResult to its field.
-    //
-
-    // String values
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SPOSITIVESIGN , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sPositive), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SNEGATIVESIGN , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sNegative), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SDECIMAL , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sNumberDecimal), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_STHOUSAND , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sNumberGroup), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SMONTHOUSANDSEP , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sCurrencyGroup), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SMONDECIMALSEP , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sCurrencyDecimal), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-    if (CallGetLocaleInfoEx(pLocaleName, LOCALE_SCURRENCY , &gc.stringResult, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sCurrency), gc.stringResult, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-
-
-    // Numeric values
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_IDIGITS | LOCALE_RETURN_NUMBER           , &(gc.numfmt->cNumberDecimals), useUserOverride);
-    _ASSERT(ret == TRUE);
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER       , &(gc.numfmt->cCurrencyDecimals), useUserOverride);
-    _ASSERT(ret == TRUE);
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_ICURRENCY | LOCALE_RETURN_NUMBER         , &(gc.numfmt->cPosCurrencyFormat), useUserOverride);
-    _ASSERT(ret == TRUE);
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_INEGCURR | LOCALE_RETURN_NUMBER          , &(gc.numfmt->cNegCurrencyFormat), useUserOverride);
-    _ASSERT(ret == TRUE);
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_INEGNUMBER| LOCALE_RETURN_NUMBER         , &(gc.numfmt->cNegativeNumberFormat), useUserOverride);
-    _ASSERT(ret == TRUE);
-    ret &= CallGetLocaleInfoEx(pLocaleName, LOCALE_IDIGITSUBSTITUTION | LOCALE_RETURN_NUMBER, &(gc.numfmt->iDigitSubstitution), useUserOverride);
-    _ASSERT(ret == TRUE);
-
-    // LOCALE_SNATIVEDIGITS (gc.tempArray of strings)
-    if (GetNativeDigitsFromWin32(pLocaleName, &gc.tempArray, useUserOverride)) {
-        SetObjectReference((OBJECTREF*)&(gc.numfmt->sNativeDigits), gc.tempArray, NULL);
-    }
-    else {
-        ret = FALSE;
-        _ASSERT(FALSE);
-    }
-
-    HELPER_METHOD_FRAME_END();
-    FC_RETURN_BOOL(ret);
-}
-FCIMPLEND
-
-
-////////////////////////////////////////////////////////////////////////
-//
-// Culture enumeration helper functions
-//
-////////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Enum values for System.Globalization.CultureTypes
-//
-////////////////////////////////////////////////////////////////////////////
-
-// Neutral cultures are cultures like "en", "de", "zh", etc, for enumeration this includes ALL neutrals regardless of other flags
-#define CULTURETYPES_NEUTRALCULTURES              0x0001
-
-// Non-netural cultuers.  Examples are "en-us", "zh-tw", etc., for enumeration this includes ALL specifics regardless of other flags
-#define CULTURETYPES_SPECIFICCULTURES             0x0002
-
-// Win32 installed cultures in the system and exists in the framework too., this is effectively all cultures
-#define CULTURETYPES_INSTALLEDWIN32CULTURES       0x0004
-
-// User defined custom culture
-#define CULTURETYPES_USERCUSTOMCULTURE            0x0008
-
-// User defined replacement custom culture.
-#define CULTURETYPES_REPLACEMENTCULTURES          0x0010
-// [Obsolete("This value has been deprecated.  Please use other values in CultureTypes.")]
-// Culture exists in Win32 but not in the Framework. // TODO: All cultures or no cultures?
-#define CULTURETYPES_WINDOWSONLYCULTURES          0x0020
-// [Obsolete("This value has been deprecated.  Please use other values in CultureTypes.")]
-// the language tag match a culture that ships with the .NET framework, effectively all cultures since we get them from windows
-#define CULTURETYPES_FRAMEWORKCULTURES            0x0040
-
-
-const LPCWSTR WHIDBEY_FRAMEWORK_CULTURE_LIST [] =
-{
-    W(""),
-    W("af"),
-    W("af-za"),
-    W("ar"),
-    W("ar-ae"),
-    W("ar-bh"),
-    W("ar-dz"),
-    W("ar-eg"),
-    W("ar-iq"),
-    W("ar-jo"),
-    W("ar-kw"),
-    W("ar-lb"),
-    W("ar-ly"),
-    W("ar-ma"),
-    W("ar-om"),
-    W("ar-qa"),
-    W("ar-sa"),
-    W("ar-sy"),
-    W("ar-tn"),
-    W("ar-ye"),
-    W("az"),
-    W("az-cyrl-az"),
-    W("az-latn-az"),
-    W("be"),
-    W("be-by"),
-    W("bg"),
-    W("bg-bg"),
-    W("ca"),
-    W("ca-es"),
-    W("cs"),
-    W("cs-cz"),
-    W("da"),
-    W("da-dk"),
-    W("de"),
-    W("de-at"),
-    W("de-ch"),
-    W("de-de"),
-    W("de-li"),
-    W("de-lu"),
-    W("dv"),
-    W("dv-mv"),
-    W("el"),
-    W("el-gr"),
-    W("en"),
-    W("en-029"),
-    W("en-au"),
-    W("en-bz"),
-    W("en-ca"),
-    W("en-gb"),
-    W("en-ie"),
-    W("en-jm"),
-    W("en-nz"),
-    W("en-ph"),
-    W("en-tt"),
-    W("en-us"),
-    W("en-za"),
-    W("en-zw"),
-    W("es"),
-    W("es-ar"),
-    W("es-bo"),
-    W("es-cl"),
-    W("es-co"),
-    W("es-cr"),
-    W("es-do"),
-    W("es-ec"),
-    W("es-es"),
-    W("es-gt"),
-    W("es-hn"),
-    W("es-mx"),
-    W("es-ni"),
-    W("es-pa"),
-    W("es-pe"),
-    W("es-pr"),
-    W("es-py"),
-    W("es-sv"),
-    W("es-uy"),
-    W("es-ve"),
-    W("et"),
-    W("et-ee"),
-    W("eu"),
-    W("eu-es"),
-    W("fa"),
-    W("fa-ir"),
-    W("fi"),
-    W("fi-fi"),
-    W("fo"),
-    W("fo-fo"),
-    W("fr"),
-    W("fr-be"),
-    W("fr-ca"),
-    W("fr-ch"),
-    W("fr-fr"),
-    W("fr-lu"),
-    W("fr-mc"),
-    W("gl"),
-    W("gl-es"),
-    W("gu"),
-    W("gu-in"),
-    W("he"),
-    W("he-il"),
-    W("hi"),
-    W("hi-in"),
-    W("hr"),
-    W("hr-hr"),
-    W("hu"),
-    W("hu-hu"),
-    W("hy"),
-    W("hy-am"),
-    W("id"),
-    W("id-id"),
-    W("is"),
-    W("is-is"),
-    W("it"),
-    W("it-ch"),
-    W("it-it"),
-    W("ja"),
-    W("ja-jp"),
-    W("ka"),
-    W("ka-ge"),
-    W("kk"),
-    W("kk-kz"),
-    W("kn"),
-    W("kn-in"),
-    W("ko"),
-    W("ko-kr"),
-    W("kok"),
-    W("kok-in"),
-    W("ky"),
-    W("ky-kg"),
-    W("lt"),
-    W("lt-lt"),
-    W("lv"),
-    W("lv-lv"),
-    W("mk"),
-    W("mk-mk"),
-    W("mn"),
-    W("mn-mn"),
-    W("mr"),
-    W("mr-in"),
-    W("ms"),
-    W("ms-bn"),
-    W("ms-my"),
-    W("nb-no"),
-    W("nl"),
-    W("nl-be"),
-    W("nl-nl"),
-    W("nn-no"),
-    W("no"),
-    W("pa"),
-    W("pa-in"),
-    W("pl"),
-    W("pl-pl"),
-    W("pt"),
-    W("pt-br"),
-    W("pt-pt"),
-    W("ro"),
-    W("ro-ro"),
-    W("ru"),
-    W("ru-ru"),
-    W("sa"),
-    W("sa-in"),
-    W("sk"),
-    W("sk-sk"),
-    W("sl"),
-    W("sl-si"),
-    W("sq"),
-    W("sq-al"),
-    W("sr"),
-    W("sr-cyrl-cs"),
-    W("sr-latn-cs"),
-    W("sv"),
-    W("sv-fi"),
-    W("sv-se"),
-    W("sw"),
-    W("sw-ke"),
-    W("syr"),
-    W("syr-sy"),
-    W("ta"),
-    W("ta-in"),
-    W("te"),
-    W("te-in"),
-    W("th"),
-    W("th-th"),
-    W("tr"),
-    W("tr-tr"),
-    W("tt"),
-    W("tt-ru"),
-    W("uk"),
-    W("uk-ua"),
-    W("ur"),
-    W("ur-pk"),
-    W("uz"),
-    W("uz-cyrl-uz"),
-    W("uz-latn-uz"),
-    W("vi"),
-    W("vi-vn"),
-    W("zh-chs"),
-    W("zh-cht"),
-    W("zh-cn"),
-    W("zh-hans"),
-    W("zh-hant"),
-    W("zh-hk"),
-    W("zh-mo"),
-    W("zh-sg"),
-    W("zh-tw")
-};
-#define WHIDBEY_FRAMEWORK_CULTURE_LIST_LENGTH (sizeof(WHIDBEY_FRAMEWORK_CULTURE_LIST) / sizeof(WHIDBEY_FRAMEWORK_CULTURE_LIST[0]))
-
-////////////////////////////////////////////////////////////////////////////
-//
-//  NlsCompareInvariantNoCase
-//
-//  This routine does fast caseless comparison without needing the tables.
-//  This helps us do the comparisons we need to load the tables :-)
-//
-//  Returns 0 if identical, <0 if pFirst if first string sorts first.
-//
-//  This is only intended to help with our locale name comparisons,
-//  which are effectively limited to A-Z, 0-9, a-z and - where A-Z and a-z
-//  compare as equal.
-//
-//  WARNING: [\]^_` will be less than A-Z because we make everything lower
-//           case before comparing them.
-//
-//  When bNullEnd is TRUE, both of the strings should be null-terminator to be considered equal.
-//  When bNullEnd is FALSE, the strings are considered equal when we reach the number of characters specifed by size
-//  or when null terminators are reached, whichever happens first (strncmp-like behavior)
-//
-////////////////////////////////////////////////////////////////////////////
-
-int NlsCompareInvariantNoCase(
-    LPCWSTR pFirst,
-    LPCWSTR pSecond,
-    int     size,
-    BOOL bNullEnd)
-{
-    int i=0;
-    WCHAR first;
-    WCHAR second;
-
-    for (;
-         size > 0 && (first = *pFirst) != 0 && (second = *pSecond) != 0;
-         size--, pFirst++, pSecond++)
-    {
-        // Make them lower case
-        if ((first >= 'A') && (first <= 'Z')) first |= 0x20;
-        if ((second >= 'A') && (second <= 'Z')) second |= 0x20;
-
-        // Get the diff
-        i = (first - second);
-
-        // Are they the same?
-        if (i == 0)
-            continue;
-
-        // Otherwise the difference.  Remember we made A-Z into lower case, so
-        // the characters [\]^_` will sort < A-Z and also < a-z.  (Those are the
-        // characters between A-Z and a-Z in ascii)
-        return i;
-    }
-
-    // When we are here, one of these holds:
-    //    size == 0
-    //    or one of the strings has a null terminator
-    //    or both of the string reaches null terminator
-
-    if (bNullEnd || size != 0)
-    {
-        // If bNullEnd is TRUE, always check for null terminator.
-        // If bNullEnd is FALSE, we still have to check if one of the strings is terminated eariler
-        // than another (hense the size != 0 check).
-
-        // See if one string ended first
-        if (*pFirst != 0 || *pSecond != 0)
-        {
-            // Which one?
-            return *pFirst == 0 ? -1 : 1;
-        }
-    }
-
-    // Return our difference (0)
-    return i;
-}
-
-BOOL IsWhidbeyFrameworkCulture(__in LPCWSTR lpLocaleString)
-{
-    int iBottom = 0;
-    int iTop = WHIDBEY_FRAMEWORK_CULTURE_LIST_LENGTH - 1;
-
-    // Do a binary search for our name
-    while (iBottom <= iTop)
-    {
-        int     iMiddle = (iBottom + iTop) / 2;
-        int     result = NlsCompareInvariantNoCase(lpLocaleString, WHIDBEY_FRAMEWORK_CULTURE_LIST[iMiddle], LOCALE_NAME_MAX_LENGTH, TRUE);
-        if (result == 0)
-        {
-            return TRUE;
-        }
-        if (result < 0)
-        {
-            // pLocaleName was < pTest
-            iTop = iMiddle - 1;
-        }
-        else
-        {
-            // pLocaleName was > pTest
-            iBottom = iMiddle + 1;
-        }
-    }
-
-    return FALSE;
-}
-
-// Just Check to see if the OS thinks it is a valid locle
-BOOL WINAPI IsOSValidLocaleName(__in LPCWSTR  lpLocaleName, bool bIsNeutralLocale)
-{
-#ifndef ENABLE_DOWNLEVEL_FOR_NLS
-    return ::IsValidLocaleName(lpLocaleName);
-#else
-    BOOL IsWindows7 = NewApis::IsWindows7Platform();
-    // if we're < Win7, we didn't know about neutrals or the invariant.
-    if (!IsWindows7 && (bIsNeutralLocale || (lpLocaleName[0] == 0)))
-    {
-        return false;
-    }
-
-    // Work around the name/lcid thingy (can't just link to ::IsValidLocaleName())
-    LCID lcid = NewApis::LocaleNameToLCID(lpLocaleName, 0);
-
-    if (IsCustomCultureId(lcid))
-    {
-        return false;
-    }
-
-    if (bIsNeutralLocale)
-    {
-        // In this case, we're running on Windows 7.
-        // For neutral locales, use GetLocaleInfoW.
-        // If GetLocaleInfoW works, then the OS knows about it.
-        return (::GetLocaleInfoW(lcid, LOCALE_ILANGUAGE, NULL, 0) != 0);
-    }
-
-    // This is not a custom locale.
-    // Call IsValidLocale() to check if the LCID is installed.
-    // IsValidLocale doesn't work for neutral locales.
-    return IsValidLocale(lcid, LCID_INSTALLED);
-#endif
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Check the dwFlags, which has the 'attributes' of the locale, and decide
-// if the locale should be included in the enumeration based on
-// the desired CultureTypes.
-//
-////////////////////////////////////////////////////////////////////////////
-
-BOOL ShouldIncludeByCultureType(INT32 cultureTypes, LPCWSTR lpLocaleString, INT32 dwFlags)
-{
-
-    if ((cultureTypes & CULTURETYPES_NEUTRALCULTURES) &&
-         ((dwFlags & LOCALE_NEUTRALDATA) || (lpLocaleString[0] == 0))) // Invariant culture get enumerated with the neutrals
-    {
-        return TRUE;
-    }
-
-    if ((cultureTypes & CULTURETYPES_SPECIFICCULTURES) &&
-        ((dwFlags & LOCALE_SPECIFICDATA) && (lpLocaleString[0] != 0))) // Invariant culture does not get enumerated with the specifics
-    {
-        return TRUE;
-    }
-
-    if (cultureTypes & CULTURETYPES_INSTALLEDWIN32CULTURES)
-    {
-        // The user asks for installed Win32 culture, so check
-        // if this locale is installed. In W7 and above, when ::IsValidLocaleName()
-        // returns true, it means that it is installed.
-        // In downlevel (including Vista), we will convert the name to LCID.
-        // When the LCID is not a custom locale, we will call ::IsValidLocale(.., LCID_INSTALLED)
-        // to verify if the locale is installed.
-        // In Vista, we treat custom locale as installed.
-        if (IsOSValidLocaleName(lpLocaleString, (dwFlags & LOCALE_NEUTRALDATA) == LOCALE_NEUTRALDATA))
-        {
-            return TRUE;
-        }
-    }
-
-    if ((cultureTypes & CULTURETYPES_USERCUSTOMCULTURE) &&
-        (dwFlags & LOCALE_SUPPLEMENTAL))
-    {
-        return TRUE;
-    }
-
-    if ((cultureTypes & CULTURETYPES_REPLACEMENTCULTURES) &&
-        (dwFlags & LOCALE_REPLACEMENT))
-    {
-        return TRUE;
-    }
-
-    if ((cultureTypes & CULTURETYPES_FRAMEWORKCULTURES) &&
-         IsWhidbeyFrameworkCulture(lpLocaleString))
-    {
-        return TRUE;
-    }
-
-    //
-    // No need to check CULTURETYPES_WINDOWSONLYCULTURES and CULTURETYPES_FRAMEWORKCULTURES
-    // since they are deprecated, and they are handled in the managed code before calling
-    // nativeEnumCultureNames.
-    //
-
-    return FALSE;
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Struct to hold context to be used in the callback for
-// EnumLocaleProcessingCallback
-//
-////////////////////////////////////////////////////////////////////////////
-
-typedef struct
-{
-    PTRARRAYREF pCultureNamesArray;
-    INT32 count;
-    INT32 cultureTypes;
-} ENUM_LOCALE_DATA;
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Callback for NewApis::EnumSystemLocalesEx to count the number of
-// locales to be enumerated.
-//
-////////////////////////////////////////////////////////////////////////////
-
-BOOL CALLBACK EnumLocaleCountCallback(__in_z LPCWSTR lpLocaleString, __in DWORD dwFlags, __in LPARAM lParam)
-{
-    ENUM_LOCALE_DATA* pData = (ENUM_LOCALE_DATA*)lParam;
-
-    if (ShouldIncludeByCultureType(pData->cultureTypes, lpLocaleString, dwFlags))
-    {
-        (pData->count)++;
-    }
-    return TRUE;
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Callback for NewApis::EnumSystemLocalesEx to add the locale name
-// into the allocated managed string array.
-//
-////////////////////////////////////////////////////////////////////////////
-
-BOOL CALLBACK EnumLocaleProcessingCallback(__in_z LPCWSTR lpLocaleString, __in DWORD dwFlags, __in LPARAM lParam)
-{
-    ENUM_LOCALE_DATA* pData = (ENUM_LOCALE_DATA*)lParam;
-
-    if (ShouldIncludeByCultureType(pData->cultureTypes, lpLocaleString, dwFlags))
-    {
-        GCX_COOP();
-
-        GCPROTECT_BEGIN(pData->pCultureNamesArray);
-
-        OBJECTREF cultureString = (OBJECTREF) StringObject::NewString(lpLocaleString);
-        pData->pCultureNamesArray->SetAt(pData->count, cultureString);
-        pData->count++;
-
-        GCPROTECT_END();
-    }
-
-    return TRUE;
-}
-
-
-////////////////////////////////////////////////////////////////////////////
-//
-// Called by CultureData.GetCultures() to enumerate the names of cultures.
-// It first calls NewApis::EnumSystemLocalesEx to count the number of
-// locales to be enumerated. And it will allocate an managed string
-// array with the count. And fill the array with the culture names in
-// the 2nd call to NewAPis::EnumSystemLocalesEx.
-//
-////////////////////////////////////////////////////////////////////////////
-
-
-int QCALLTYPE COMNlsInfo::nativeEnumCultureNames(INT32 cultureTypes, QCall::ObjectHandleOnStack retStringArray)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        // Check CultureTypes.WindowsOnlyCultures and CultureTYpes.FrameworkCultures are deprecated and is
-        // handled in the managed code side to provide fallback behavior.
-        //PRECONDITION((cultureTypes & (CULTURETYPES_WINDOWSONLYCULTURES | CULTURETYPES_FRAMEWORKCULTURES) == 0));
-    } CONTRACTL_END;
-
-
-    int result;
-    DWORD dwFlags = 0;
-    PTRARRAYREF cultureNamesArray = NULL;
-    ENUM_LOCALE_DATA enumData = { NULL, 0, cultureTypes};
-
-    BEGIN_QCALL;
-
-    //
-    // if CultureTypes.FrameworkCulture is specified we'll enumerate all cultures
-    // and filter according to the Whidbey framework culture list (for compatibility)
-    //
-
-    if (cultureTypes & CULTURETYPES_FRAMEWORKCULTURES)
-    {
-        dwFlags |= LOCALE_NEUTRALDATA | LOCALE_SPECIFICDATA;
-    }
-
-    // Map CultureTypes to Windows enumeration values.
-    if (cultureTypes & CULTURETYPES_NEUTRALCULTURES)
-    {
-        dwFlags |= LOCALE_NEUTRALDATA;
-    }
-
-    if (cultureTypes & CULTURETYPES_SPECIFICCULTURES)
-    {
-        dwFlags |= LOCALE_SPECIFICDATA;
-    }
-
-    if (cultureTypes & CULTURETYPES_INSTALLEDWIN32CULTURES)
-    {
-        // Windows 7 knows about neutrals, whereas Vista and lower don't.
-        if (NewApis::IsWindows7Platform())
-        {
-            dwFlags |= LOCALE_SPECIFICDATA | LOCALE_NEUTRALDATA;
-        }
-        else
-        {
-            dwFlags |= LOCALE_SPECIFICDATA;
-        }
-    }
-
-    dwFlags |= (cultureTypes & CULTURETYPES_USERCUSTOMCULTURE) ? LOCALE_SUPPLEMENTAL: 0;
-
-    // We need special handling for Replacement cultures because Windows does not have a way to enumerate it directly.
-    // Replacement locale check will be only used when CultureTypes.SpecificCultures is NOT used.
-    dwFlags |= (cultureTypes & CULTURETYPES_REPLACEMENTCULTURES) ? LOCALE_SPECIFICDATA | LOCALE_NEUTRALDATA: 0;
-
-
-    result = NewApis::EnumSystemLocalesEx((LOCALE_ENUMPROCEX)EnumLocaleCountCallback, dwFlags, (LPARAM)&enumData, NULL) == TRUE ? 1 : 0;
-
-    if (result)
-    {
-
-        GCX_COOP();
-
-        GCPROTECT_BEGIN(cultureNamesArray);
-
-        // Now we need to allocate our culture names string array and populate it
-        // Get our array object (will throw, don't have to check it)
-        cultureNamesArray = (PTRARRAYREF) AllocateObjectArray(enumData.count, g_pStringClass);
-
-        // In the context struct passed to EnumSystemLocalesEx, reset the count and assign the newly allocated string array
-        // to hold culture names to be enumerated.
-        enumData.count = 0;
-        enumData.pCultureNamesArray = cultureNamesArray;
-
-        result = NewApis::EnumSystemLocalesEx((LOCALE_ENUMPROCEX)EnumLocaleProcessingCallback, dwFlags, (LPARAM)&enumData, NULL);
-
-        if (result)
-        {
-            retStringArray.Set(cultureNamesArray);
-        }
-        GCPROTECT_END();
-    }
-    END_QCALL
-
-    return result;
-
-}
-
-//
-// InternalCompareString is used in the managed side to handle the synthetic CompareInfo methods (IndexOf, LastIndexOf, IsPrfix, and IsSuffix)
-//
-INT32 QCALLTYPE COMNlsInfo::InternalCompareString(
-    INT_PTR handle,
-    INT_PTR handleOrigin,
-    LPCWSTR localeName,
-    LPCWSTR string1, INT32 offset1, INT32 length1,
-    LPCWSTR string2, INT32 offset2, INT32 length2,
-    INT32 flags)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        PRECONDITION(CheckPointer(string1));
-        PRECONDITION(CheckPointer(string2));
-        PRECONDITION(CheckPointer(localeName));
-    } CONTRACTL_END;
-
-    INT32 result = 1;
-    BEGIN_QCALL;
-
-    {
-        result = NewApis::CompareStringEx(handle != NULL ? NULL : localeName, flags, &string1[offset1], length1, &string2[offset2], length2,NULL,NULL, (LPARAM) handle);
-    }
-
-    switch (result)
-    {
-        case CSTR_LESS_THAN:
-            result = -1;
-            break;
-
-        case CSTR_EQUAL:
-            result = 0;
-            break;
-
-        case CSTR_GREATER_THAN:
-            result = 1;
-            break;
-
-        case 0:
-        default:
-            _ASSERTE(!"catastrophic failure calling NewApis::CompareStringEx!  This could be a CultureInfo, RegionInfo, or Calendar bug (bad localeName string) or maybe a GCHole.");
-            break;
-    }
-
-    END_QCALL;
-    return result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-//
-//  UseConstantSpaceHashAlgorithm
-//  Check for the DWORD "NetFx45_CultureAwareComparerGetHashCode_LongStrings" CLR config option.
-//
-// .Net 4.5 introduces an opt-in algorithm for determining the hash code of strings that
-// uses a constant amount of memory instead of memory proportional to the size of the string
-//
-// A non-zero value will enable the new algorithm:
-//
-// 1) Config file (MyApp.exe.config)
-//        <?xml version ="1.0"?>
-//        <configuration>
-//         <runtime>
-//          <NetFx45_CultureAwareComparerGetHashCode_LongStrings enabled="1"/>
-//         </runtime>
-//        </configuration>
-// 2) Environment variable
-//        set NetFx45_CultureAwareComparerGetHashCode_LongStrings=1
-// 3) RegistryKey
-//        [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
-//        "NetFx45_CultureAwareComparerGetHashCode_LongStrings"=dword:00000001
-//
-////////////////////////////////////////////////////////////////////////////
-BOOL UseConstantSpaceHashAlgorithm()
-{
-    static bool configChecked = false;
-    static BOOL useConstantSpaceHashAlgorithm = FALSE;
-
-    if(!configChecked)
-    {
-        BEGIN_SO_INTOLERANT_CODE_NO_THROW_CHECK_THREAD(return false);
-        useConstantSpaceHashAlgorithm = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_NetFx45_CultureAwareComparerGetHashCode_LongStrings) != 0;
-        END_SO_INTOLERANT_CODE;
-
-        configChecked = true;
-    }
-    return useConstantSpaceHashAlgorithm;
-}
-
-
-
-////////////////////////////////////////////////////////////////////////////
-//
-//  InternalGetGlobalizedHashCode
-//
-////////////////////////////////////////////////////////////////////////////
-INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR string, INT32 length, INT32 dwFlagsIn, INT64 additionalEntropy)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        PRECONDITION(CheckPointer(localeName));
-        PRECONDITION(CheckPointer(string, NULL_OK));
-    } CONTRACTL_END;
-
-    INT32  iReturnHash  = 0;
-    BEGIN_QCALL;
-
-    int byteCount = 0;
-
-    //
-    //  Make sure there is a string.
-    //
-    if (!string) {
-        COMPlusThrowArgumentNull(W("string"),W("ArgumentNull_String"));
-    }
-
-    DWORD dwFlags = (LCMAP_SORTKEY | dwFlagsIn);
-
-    //
-    // Caller has already verified that the string is not of zero length
-    //
-    // Assert if we might hit an AV in LCMapStringEx for the invariant culture.
-    _ASSERTE(length > 0 || (dwFlags & LCMAP_LINGUISTIC_CASING) == 0);
-    {
-        byteCount=NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, NULL, 0, NULL, NULL, (LPARAM) handle);
-    }
-
-    //A count of 0 indicates that we either had an error or had a zero length string originally.
-    if (byteCount==0)
-    {
-        COMPlusThrow(kArgumentException, W("Arg_MustBeString"));
-    }
-
-    // We used to use a NewArrayHolder here, but it turns out that hurts our large # process
-    // scalability in ASP.Net hosting scenarios, using the quick bytes instead mostly stack
-    // allocates and ups throughput by 8% in 100 process case, 5% in 1000 process case
-    {
-        CQuickBytesSpecifySize<MAX_STRING_VALUE * sizeof(WCHAR)> qbBuffer;
-        BYTE* pByte = (BYTE*)qbBuffer.AllocThrows(byteCount);
-
-        {
-            NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, (LPWSTR)pByte, byteCount, NULL,NULL, (LPARAM) handle);
-        }
-
-        iReturnHash = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pByte, byteCount, true, additionalEntropy);
-    }
-    END_QCALL;
-    return(iReturnHash);
-}
-
-inline BOOL IsInvariantLocale(STRINGREF localeName)
-{
-   return localeName->GetStringLength() == 0;
-}
-
-// InternalChangeCaseChar
-//
-// Call LCMapStringEx with a char to make it upper or lower case
-// Note that if the locale is English or Invariant we'll try just mapping it if its < 0x7f
-FCIMPL5(FC_CHAR_RET, COMNlsInfo::InternalChangeCaseChar,
-        INT_PTR handle, // optional sort handle
-        INT_PTR handleOrigin, StringObject* localeNameUNSAFE, CLR_CHAR wch, CLR_BOOL bIsToUpper)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    CLR_CHAR retVal = '\0';
-    int ret_LCMapStringEx = -1;
-
-    // Dereference our string
-    STRINGREF localeName(localeNameUNSAFE);
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(localeName);
-
-    BOOL isInvariantLocale = IsInvariantLocale(localeName);
-    // Check for Invariant to avoid A/V in LCMapStringEx
-    DWORD linguisticCasing = (isInvariantLocale) ? 0 : LCMAP_LINGUISTIC_CASING;
-
-    {
-        ret_LCMapStringEx = NewApis::LCMapStringEx(handle != NULL ? NULL : localeName->GetBuffer(),
-                                   bIsToUpper?LCMAP_UPPERCASE | linguisticCasing:
-                                              LCMAP_LOWERCASE | linguisticCasing,
-                                   &wch,
-                                   1,
-                                   &retVal,
-                                   1,
-                                   NULL,
-                                   NULL,
-                                   (LPARAM) handle);
-    }
-
-    if (0 == ret_LCMapStringEx)
-    {
-        // return value of 0 indicates failure and error value is supposed to be set.
-        // shouldn't ever really happen
-        _ASSERTE(!"catastrophic failure calling NewApis::InternalChangeCaseChar!  This could be a CultureInfo or CompareInfo bug (bad localeName string) or maybe a GCHole.");
-    }
-
-    HELPER_METHOD_FRAME_END(); // localeName is now unprotected
-    return retVal;
-}
-FCIMPLEND
-
-// InternalChangeCaseString
-//
-// Call LCMapStringEx with a string to make it upper or lower case
-// Note that if the locale is English or Invariant we'll try just mapping it if its < 0x7f
-//
-// We typically expect the output string to be the same size as the input.  If not
-// we have to count, reallocate the output buffer, and try again.
-FCIMPL5(Object*, COMNlsInfo::InternalChangeCaseString,
-        INT_PTR handle, // optional sort handle
-        INT_PTR handleOrigin, StringObject* localeNameUNSAFE, StringObject* pStringUNSAFE, CLR_BOOL bIsToUpper)
-{
-    CONTRACTL
-    {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(pStringUNSAFE));
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-    } CONTRACTL_END;
-
-    struct _gc
-    {
-        STRINGREF pResult;
-        STRINGREF pString;
-        STRINGREF pLocale;
-    } gc;
-
-    gc.pResult = NULL;
-    gc.pString = ObjectToSTRINGREF(pStringUNSAFE);
-    gc.pLocale = ObjectToSTRINGREF(localeNameUNSAFE);
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc)
-
-    //
-    //  Get the length of the string.
-    //
-    int nLengthInput = gc.pString->GetStringLength();
-    int nLengthOutput = nLengthInput; //  initially we assume the string length does not change.
-
-    BOOL isInvariantLocale = IsInvariantLocale(gc.pLocale);
-    // Check for Invariant to avoid A/V in LCMapStringEx
-    DWORD linguisticCasing = (isInvariantLocale) ? 0 : LCMAP_LINGUISTIC_CASING;
-    // Check for Invariant to avoid A/V in LCMapStringEx
-
-    //
-    //  Check if we have the empty string.
-    //
-    if (nLengthInput == 0)
-    {
-        gc.pResult = ObjectToSTRINGREF(gc.pString);
-    }
-    else
-    {
-        //
-        //  Create the result string.
-        //
-        gc.pResult = StringObject::NewString(nLengthOutput);
-        LPWSTR pResultStr = gc.pResult->GetBuffer();
-
-        int result;
-        {
-            result = NewApis::LCMapStringEx(handle != NULL ? NULL : (gc.pLocale)->GetBuffer(),
-                                       bIsToUpper?LCMAP_UPPERCASE | linguisticCasing :
-                                                  LCMAP_LOWERCASE | linguisticCasing,
-                                       gc.pString->GetBuffer(),
-                                       nLengthInput,
-                                       pResultStr,
-                                       nLengthOutput,
-                                       NULL,
-                                       NULL,
-                                       (LPARAM) handle);
-        }
-
-        if(0 == result)
-        {
-            // Failure: Detect if that's due to insufficient buffer
-            if (GetLastError()!= ERROR_INSUFFICIENT_BUFFER)
-            {
-                ThrowLastError();
-            }
-            // need to update buffer
-            {
-                nLengthOutput = NewApis::LCMapStringEx(handle != NULL ? NULL : (gc.pLocale)->GetBuffer(),
-                                                        bIsToUpper?LCMAP_UPPERCASE | linguisticCasing :
-                                                                   LCMAP_LOWERCASE | linguisticCasing,
-                                                        gc.pString->GetBuffer(),
-                                                        nLengthInput,
-                                                        NULL,
-                                                        0,
-                                                        NULL,
-                                                        NULL,
-                                                        (LPARAM) handle);
-            }
-            if (nLengthOutput == 0)
-            {
-                // return value of 0 indicates failure and error value is supposed to be set.
-                // shouldn't ever really happen
-                _ASSERTE(!"catastrophic failure calling NewApis::InternalChangeCaseString!  This could be a CultureInfo or CompareInfo bug (bad localeName string) or maybe a GCHole.");
-            }
-            _ASSERTE(nLengthOutput > 0);
-            // NOTE: The length of the required buffer does not include the terminating null character.
-            // So it can be used as-is for our calculations -- the length we pass in to NewString also does
-            // not include the terminating null character.
-            // MSDN documentation could be interpreted to mean that the length returned includes the terminating
-            // NULL character, but that's not the case.
-
-            // NOTE: Also note that we let the GC take care of the previously allocated pResult.
-
-            gc.pResult = StringObject::NewString(nLengthOutput);
-            pResultStr = gc.pResult->GetBuffer();
-            {
-                result = NewApis::LCMapStringEx(handle != NULL ? NULL : (gc.pLocale)->GetBuffer(),
-                                           bIsToUpper?LCMAP_UPPERCASE | linguisticCasing :
-                                                      LCMAP_LOWERCASE | linguisticCasing,
-                                           gc.pString->GetBuffer(),
-                                           nLengthInput,
-                                           pResultStr,
-                                           nLengthOutput,
-                                           NULL,
-                                           NULL,
-                                           (LPARAM) handle);
-            }
-
-            if(0 == result)
-            {
-                // return value of 0 indicates failure and error value is supposed to be set.
-                // shouldn't ever really happen
-                _ASSERTE(!"catastrophic failure calling NewApis::InternalChangeCaseString!  This could be a CultureInfo or CompareInfo bug (bad localeName string) or maybe a GCHole.");
-            }
-        }
-
-        pResultStr[nLengthOutput] = 0;
-    }
-
-    HELPER_METHOD_FRAME_END();
+// Language ID for CHT (Taiwan)
+#define LANGID_ZH_TW            0x0404
+// Language ID for CHT (Hong-Kong)
+#define LANGID_ZH_HK            0x0c04
 
-    return OBJECTREFToObject(gc.pResult);
-}
-FCIMPLEND
+#ifndef FEATURE_COREFX_GLOBALIZATION
+//
+// Normalization Implementation
+//
+#define NORMALIZATION_DLL       MAKEDLLNAME(W("normalization"))
+HMODULE COMNlsInfo::m_hNormalization = NULL;
+PFN_NORMALIZATION_IS_NORMALIZED_STRING COMNlsInfo::m_pfnNormalizationIsNormalizedStringFunc = NULL;
+PFN_NORMALIZATION_NORMALIZE_STRING COMNlsInfo::m_pfnNormalizationNormalizeStringFunc = NULL;
+PFN_NORMALIZATION_INIT_NORMALIZATION COMNlsInfo::m_pfnNormalizationInitNormalizationFunc = NULL;
+#endif // FEATURE_COREFX_GLOBALIZATION
 
-/*================================InternalGetCaseInsHash================================
-**Action:
-**Returns:
-**Arguments:
-**Exceptions:
-==============================================================================*/
-FCIMPL6(INT32, COMNlsInfo::InternalGetCaseInsHash,
-        INT_PTR handle, // optional sort handle
-        INT_PTR handleOrigin, StringObject* localeNameUNSAFE, LPVOID pvStrA, CLR_BOOL bForceRandomizedHashing, INT64 additionalEntropy)
+INT32 COMNlsInfo::CallGetUserDefaultUILanguage()
 {
     CONTRACTL
     {
-        FCALL_CHECK;
-        PRECONDITION(CheckPointer(localeNameUNSAFE));
-        PRECONDITION(CheckPointer(pvStrA));
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_ANY;
+        SO_TOLERANT;
     } CONTRACTL_END;
 
-    STRINGREF localeName = ObjectToSTRINGREF(localeNameUNSAFE);
-    STRINGREF strA;
-
-    INT32 result;
-
-    BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException))
-
-    *((LPVOID *)&strA)=pvStrA;
-
+    static INT32 s_lcid = 0;
 
-    //
-    // If we know that we don't have any high characters (the common case) we can
-    // call a hash function that knows how to do a very fast case conversion.  If
-    // we find characters above 0x80, it's much faster to convert the entire string
-    // to Uppercase and then call the standard hash function on it.
-    //
-    // TODO: NLS Arrowhead -We aren't consistent with the fast casing cultures (any en?  fr? de?)
-    if (IsCultureEnglishOrInvariant((localeName)->GetBuffer()) &&           // If we're en-US or Invariant
-        ((IS_STRING_STATE_UNDETERMINED(strA->GetHighCharState()) &&          // and we're undetermined
-           IS_FAST_CASING(strA->InternalCheckHighChars())) ||       // and its fast casing when determined
-        IS_FAST_CASING(strA->GetHighCharState())))                         // or we're fast casing that's already determined
-    {
-        // Notice that for Turkish and Azeri we don't get here and shouldn't use this
-        // fast path because of their special Latin casing rules.
-        result = COMNlsHashProvider::s_NlsHashProvider.HashiStringKnownLower80(strA->GetBuffer(), strA->GetStringLength(), bForceRandomizedHashing, additionalEntropy);
-    }
-    else
+    // The user UI language cannot change within a process (in fact it cannot change within a logon session),
+    // so we cache it. We dont take a lock while initializing s_lcid for the same reason. If two threads are
+    // racing to initialize s_lcid, the worst thing that'll happen is that one thread will call
+    // GetUserDefaultUILanguage needlessly, but the final result is going to be the same.
+    if (s_lcid == 0)
     {
-        // Make it upper case
-        CQuickBytes newBuffer;
-        INT32 length = strA->GetStringLength();
-        WCHAR *pNewStr = (WCHAR *)newBuffer.AllocThrows((length + 1) * sizeof(WCHAR));
-
-        // Work around an A/V in LCMapStringEx for the invariant culture.
-        // Revisit this after Vista SP2 has been deployed everywhere. 
-        DWORD linguisticCasing = 0;
-        if (localeName->GetStringLength() > 0)  // if not the invariant culture...
-        {
-            linguisticCasing = LCMAP_LINGUISTIC_CASING;
-        }
-
-        int lcmapResult;
-        {
-            lcmapResult = NewApis::LCMapStringEx(handle != NULL ? NULL : localeName->GetBuffer(),
-                                                   LCMAP_UPPERCASE | linguisticCasing,
-                                                   strA->GetBuffer(),
-                                                   length,
-                                                   pNewStr,
-                                                   length,
-                                                   NULL, NULL, (LPARAM) handle);
-        }
-
-        if (lcmapResult == 0)
+        INT32 s_lcidTemp = GetUserDefaultUILanguage();
+        if (s_lcidTemp == LANGID_ZH_TW)
         {
-            // return value of 0 indicates failure and error value is supposed to be set.
-            // shouldn't ever really happen
-            _ASSERTE(!"catastrophic failure calling NewApis::InternalGetCaseInsHash!  This could be a CultureInfo or CompareInfo bug (bad localeName string) or maybe a GCHole.");
+            // If the UI language ID is 0x0404, we need to do extra check to decide
+            // the real UI language, since MUI (in CHT)/HK/TW Windows SKU all uses 0x0404 as their CHT language ID.
+            if (!NewApis::IsZhTwSku())
+            {
+                s_lcidTemp = LANGID_ZH_HK;
+            }
         }
-        pNewStr[length]='\0';
-
-        // Get hash for the upper case of the new string
-
-        result = COMNlsHashProvider::s_NlsHashProvider.HashString(pNewStr, length, (BOOL)bForceRandomizedHashing, additionalEntropy);
+        s_lcid = s_lcidTemp;
     }
 
-    END_SO_INTOLERANT_CODE
-
-    return result;
+    return s_lcid;
 }
-FCIMPLEND
 
-// Fast path for finding a String using OrdinalIgnoreCase rules
-// returns true if the fast path succeeded, with foundIndex set to the location where the String was found or -1
-// Returns false when FindStringOrdinal isn't handled (we don't have our own general version of this function to fall back on)
-// Note for future optimizations: kernel32!FindStringOrdinal(ignoreCase=TRUE) uses per-character table lookup
-// to map to upper case before comparison, but isn't otherwise optimized
-BOOL QCALLTYPE COMNlsInfo::InternalTryFindStringOrdinalIgnoreCase(
-    __in                   DWORD       dwFindNLSStringFlags, // mutually exclusive flags: FIND_FROMSTART, FIND_STARTSWITH, FIND_FROMEND, FIND_ENDSWITH
-    __in_ecount(cchSource) LPCWSTR     lpStringSource,       // the string we search in
-    __in                   int         cchSource,            // number of characters lpStringSource after sourceIndex
-    __in                   int         sourceIndex,          // index from where the search will start in lpStringSource
-    __in_ecount(cchValue)  LPCWSTR     lpStringValue,        // the string we search for
-    __in                   int         cchValue,
-    __out                  int*        foundIndex)           // the index in lpStringSource where we found lpStringValue
+////////////////////////////////////////////////////////////////////////////
+//
+//  InternalGetGlobalizedHashCode
+//
+////////////////////////////////////////////////////////////////////////////
+INT32 QCALLTYPE COMNlsInfo::InternalGetGlobalizedHashCode(INT_PTR handle, LPCWSTR localeName, LPCWSTR string, INT32 length, INT32 dwFlagsIn, INT64 additionalEntropy)
 {
     CONTRACTL
     {
         QCALL_CHECK;
-        PRECONDITION(lpStringSource != NULL);
-        PRECONDITION(lpStringValue != NULL);
-        PRECONDITION(cchSource>=0);
-        PRECONDITION(cchValue>=0);
-        PRECONDITION((dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION) == 0);
+        PRECONDITION(CheckPointer(localeName));
+        PRECONDITION(CheckPointer(string, NULL_OK));
     } CONTRACTL_END;
 
-    BOOL result = FALSE;
-
+    INT32  iReturnHash  = 0;
     BEGIN_QCALL;
 
-    LPCWSTR lpSearchStart = NULL;
-    if (dwFindNLSStringFlags & (FIND_FROMEND | FIND_ENDSWITH))
-    {
-        lpSearchStart = &lpStringSource[sourceIndex - cchSource + 1];
-    }
-    else {
-        lpSearchStart = &lpStringSource[sourceIndex];
-    }
-    {
-#ifndef FEATURE_CORESYSTEM
-        // kernel function pointer
-        typedef int (WINAPI *PFNFindStringOrdinal)(DWORD, LPCWSTR, INT, LPCWSTR, INT, BOOL);
-        static PFNFindStringOrdinal FindStringOrdinal = NULL;
-
-        // initizalize kernel32!FindStringOrdinal
-        if (FindStringOrdinal == NULL)
-        {
-            PFNFindStringOrdinal result  = NULL;
-
-            HMODULE hMod=WszGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W);
-            if(hMod != NULL)
-                result=(PFNFindStringOrdinal)GetProcAddress(hMod,"FindStringOrdinal");
-            
-            FindStringOrdinal = (result != NULL) ? result : (PFNFindStringOrdinal)-1;
-        }
+    int byteCount = 0;
 
-        // call into the kernel
-        if (FindStringOrdinal != (PFNFindStringOrdinal)-1)
-#endif
-        {
-            *foundIndex = FindStringOrdinal(
-                dwFindNLSStringFlags,
-                lpSearchStart,
-                cchSource,
-                lpStringValue,
-                cchValue,
-                TRUE);
-            result = TRUE;
-        }
-    }
-    // if we found the pattern string, fixup the index before we return
-    if (*foundIndex >= 0)
-    {
-        if (dwFindNLSStringFlags & (FIND_FROMEND | FIND_ENDSWITH))
-            *foundIndex += (sourceIndex - cchSource + 1);
-        else
-            *foundIndex += sourceIndex;
+    //
+    //  Make sure there is a string.
+    //
+    if (!string) {
+        COMPlusThrowArgumentNull(W("string"),W("ArgumentNull_String"));
     }
-    END_QCALL;
-
-    return result;
-}
-
-
-// InternalCompareStringOrdinalIgnoreCase
-//
-// Call ::CompareStringOrdinal for native ordinal behavior
-INT32 QCALLTYPE COMNlsInfo::InternalCompareStringOrdinalIgnoreCase(
-    LPCWSTR string1, INT32 index1,
-    LPCWSTR string2, INT32 index2,
-    INT32 length1,
-    INT32 length2)
-{
-    CONTRACTL
-    {
-        QCALL_CHECK;
-        PRECONDITION(CheckPointer(string1));
-        PRECONDITION(CheckPointer(string2));
-    } CONTRACTL_END;
 
-    INT32 result = 0;
+    DWORD dwFlags = (LCMAP_SORTKEY | dwFlagsIn);
 
-    BEGIN_QCALL;
     //
-    //  Get the arguments.
-    //  We assume the caller checked them before calling us
+    // Caller has already verified that the string is not of zero length
     //
-
-    // We don't allow the -1 that native code allows
-    _ASSERT(length1 >= 0);
-    _ASSERT(length2 >= 0);
-
-    // Do the comparison
+    // Assert if we might hit an AV in LCMapStringEx for the invariant culture.
+    _ASSERTE(length > 0 || (dwFlags & LCMAP_LINGUISTIC_CASING) == 0);
     {
-        result = NewApis::CompareStringOrdinal(string1 + index1, length1, string2 + index2, length2, TRUE);
+        byteCount=NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, NULL, 0, NULL, NULL, (LPARAM) handle);
     }
 
-    // The native call shouldn't fail
-    _ASSERT(result != 0);
-    if (result == 0)
+    //A count of 0 indicates that we either had an error or had a zero length string originally.
+    if (byteCount==0)
     {
-        // return value of 0 indicates failure and error value is supposed to be set.
-        // shouldn't ever really happen
-        _ASSERTE(!"catastrophic failure calling NewApis::CompareStringOrdinal!  This is usually due to bad arguments.");
+        COMPlusThrow(kArgumentException, W("Arg_MustBeString"));
     }
 
-    // Adjust the result to the expected -1, 0, 1 result
-    result -= 2;
+    // We used to use a NewArrayHolder here, but it turns out that hurts our large # process
+    // scalability in ASP.Net hosting scenarios, using the quick bytes instead mostly stack
+    // allocates and ups throughput by 8% in 100 process case, 5% in 1000 process case
+    {
+        CQuickBytesSpecifySize<MAX_STRING_VALUE * sizeof(WCHAR)> qbBuffer;
+        BYTE* pByte = (BYTE*)qbBuffer.AllocThrows(byteCount);
+
+        {
+            NewApis::LCMapStringEx(handle != NULL ? NULL : localeName, dwFlags, string, length, (LPWSTR)pByte, byteCount, NULL,NULL, (LPARAM) handle);
+        }
 
+        iReturnHash = COMNlsHashProvider::s_NlsHashProvider.HashSortKey(pByte, byteCount, true, additionalEntropy);
+    }
     END_QCALL;
-
-    return result;
+    return(iReturnHash);
 }
 
 /**
@@ -1964,7 +185,6 @@ FCIMPL0(CodePageDataItem *, COMNlsInfo::nativeGetCodePageTableDataPointer)
 }
 FCIMPLEND
 
-
 #ifndef FEATURE_COREFX_GLOBALIZATION
 //
 // Normalization
@@ -2105,13 +325,6 @@ void QCALLTYPE COMNlsInfo::nativeNormalizationInitNormalization(int NormForm, BY
 
 #endif // FEATURE_COREFX_GLOBALIZATION
 
-
-//
-// This table should be sorted using case-insensitive ordinal order.
-// In the managed code, String.CompareStringOrdinalWC() is used to sort this.
-//
-
-
 /**
  * This function returns the number of items in EncodingDataTable.
  */
@@ -2123,289 +336,3 @@ FCIMPL0(INT32, COMNlsInfo::nativeGetNumEncodingItems)
     return (m_nEncodingDataTableItems);
 }
 FCIMPLEND
-
-// Return true if we're on Windows 7 (ie: if we have neutral native support)
-BOOL COMNlsInfo::IsWindows7()
-{
-    static BOOL bChecked=FALSE;
-    static BOOL bIsWindows7=FALSE;
-
-    if (!bChecked)
-    {
-        // LOCALE_INEUTRAL is first supported on Windows 7
-        if (GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_INEUTRAL, NULL, 0) != 0)
-        {
-            // Success, we're win7
-            bIsWindows7 = TRUE;
-        }
-
-        // Either way we checked now
-        bChecked = TRUE;
-    }
-
-    return bIsWindows7;
-}
-
-//
-// QCall implementation
-//
-int QCALLTYPE COMNlsInfo::InternalFindNLSStringEx(
-    __in_opt               INT_PTR     handle,               // optional sort handle
-    __in_opt               INT_PTR     handleOrigin,
-    __in_z                 LPCWSTR     lpLocaleName,         // locale name
-    __in                   int         dwFindNLSStringFlags, // search falg
-    __in_ecount(cchSource) LPCWSTR     lpStringSource,       // the string we search in
-    __in                   int         cchSource,            // number of characters lpStringSource after sourceIndex
-    __in                   int         sourceIndex,          // index from where the search will start in lpStringSource
-    __in_ecount(cchValue)  LPCWSTR     lpStringValue,        // the string we search for
-    __in                   int         cchValue,                        // length of the string we search for
-    __out_opt              LPINT       pcchFound)               // length of the string we found in source     
-{
-    CONTRACTL {
-        QCALL_CHECK;
-        PRECONDITION(lpLocaleName != NULL);
-        PRECONDITION(lpStringSource != NULL);
-        PRECONDITION(lpStringValue != NULL);
-        PRECONDITION(cchSource>=0);
-        PRECONDITION(cchValue>=0);
-    } CONTRACTL_END;
-
-    int retValue = -1;
-
-    BEGIN_QCALL;
-
-
-    #define RESERVED_FIND_ASCII_STRING 0x20000000       // This flag used only to tell the sorting DLL can assume the string characters are in ASCII.
-
-
-    dwFindNLSStringFlags &= ~RESERVED_FIND_ASCII_STRING;
-
-    if (cchValue == 0)
-    {
-        retValue = sourceIndex;       // keep Whidbey compatibility
-        goto lExit;
-    }
-
-    if (sourceIndex<0 || cchSource<0 ||
-        ((dwFindNLSStringFlags & (FIND_FROMEND | FIND_ENDSWITH)) && (sourceIndex+1<cchSource)))
-    {
-        goto lExit;
-    }
-
-    if (dwFindNLSStringFlags & COMPARE_OPTIONS_ORDINAL)
-    {
-        if (dwFindNLSStringFlags & (FIND_FROMEND | FIND_ENDSWITH))
-        {
-            retValue = NewApis::LastIndexOfString(
-                        lpLocaleName,
-                        &lpStringSource[sourceIndex - cchSource + 1],
-                        cchSource,
-                        lpStringValue,
-                        cchValue,
-                        dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION,
-                        dwFindNLSStringFlags & FIND_ENDSWITH,
-                        pcchFound);
-            if (retValue >= 0)
-            {
-                retValue += sourceIndex - cchSource + 1;
-            }
-        }
-        else
-        {
-            retValue = NewApis::IndexOfString(
-                        lpLocaleName,
-                        &lpStringSource[sourceIndex],
-                        cchSource,
-                        lpStringValue,
-                        cchValue,
-                        dwFindNLSStringFlags & FIND_NLS_STRING_FLAGS_NEGATION,
-                        dwFindNLSStringFlags & FIND_STARTSWITH,
-                        pcchFound);
-
-            if  (retValue >= 0)
-            {
-                retValue += sourceIndex;
-            }
-        }
-    }
-    else
-    {
-        if (dwFindNLSStringFlags & (FIND_FROMEND | FIND_ENDSWITH))
-        {
-            {
-                retValue = NewApis::FindNLSStringEx(
-                                        handle != NULL ? NULL : lpLocaleName,
-                                        dwFindNLSStringFlags,
-                                        &lpStringSource[sourceIndex - cchSource + 1],
-                                        cchSource,
-                                        lpStringValue,
-                                        cchValue, 
-                                        pcchFound,
-                                        NULL, NULL, (LPARAM) handle);
-            }
-
-            if (retValue >= 0)
-            {
-                retValue += sourceIndex - cchSource + 1;
-            }
-        }
-        else
-        {
-            {
-                retValue = NewApis::FindNLSStringEx(
-                                        handle != NULL ? NULL : lpLocaleName,
-                                        dwFindNLSStringFlags,
-                                        &lpStringSource[sourceIndex],
-                                        cchSource,
-                                        lpStringValue,
-                                        cchValue, 
-                                        pcchFound, 
-                                        NULL, NULL, (LPARAM) handle);
-            }
-
-            if (retValue >= 0)
-            {
-                retValue += sourceIndex;
-            }
-        }
-    }
-
-lExit:
-
-    END_QCALL;
-
-    return retValue;
-}
-
-
-int QCALLTYPE COMNlsInfo::InternalGetSortKey(
-    __in_opt               INT_PTR handle,        // PSORTHANDLE
-    __in_opt               INT_PTR handleOrigin,
-    __in_z                 LPCWSTR pLocaleName,   // locale name
-    __in                   int     flags,         // flags
-    __in_ecount(cchSource) LPCWSTR pStringSource, // Source string
-    __in                   int     cchSource,     // number of characters in lpStringSource
-    __in_ecount(cchTarget) PBYTE   pTarget,       // Target data buffer (may be null to count)
-    __in                   int     cchTarget)     // Character count for target buffer
-{
-    CONTRACTL {
-        QCALL_CHECK;
-        PRECONDITION(pLocaleName != NULL);
-        PRECONDITION(pStringSource != NULL);
-//        PRECONDITION(pTarget != NULL);
-        PRECONDITION(cchSource>=0);
-//        PRECONDITION(cchTarget>=0);
-    } CONTRACTL_END;
-
-    int retValue = 0;
-
-    BEGIN_QCALL;
-
-
-    {
-        // Just call NewApis::LCMapStringEx to do our work
-        retValue = NewApis::LCMapStringEx(handle != NULL ? NULL : pLocaleName,
-                                          flags | LCMAP_SORTKEY,
-                                          pStringSource,
-                                          cchSource,
-                                          (LPWSTR)pTarget,
-                                          cchTarget,
-                                          NULL,
-                                          NULL,
-                                          (LPARAM) handle);
-    }
-    END_QCALL;
-
-    return retValue;
-}
-
-
-// We allow InternalInitSortHandle to return a NULL value
-// this is the case for Silverlight or when the appdomain has custom sorting.
-// So all the methods that take a SortHandle, also have to
-// be able to just call the slower api that looks up the tables based on the locale name
-INT_PTR QCALLTYPE COMNlsInfo::InternalInitSortHandle(LPCWSTR localeName, __out INT_PTR* handleOrigin)
-{
-    CONTRACTL {
-        QCALL_CHECK;
-        PRECONDITION(localeName != NULL);
-    } CONTRACTL_END;
-    
-    INT_PTR pSort = NULL;
-
-    BEGIN_QCALL;
-
-    pSort = InitSortHandleHelper(localeName, handleOrigin);
-
-    END_QCALL;
-
-    return pSort;
-}
-
-INT_PTR COMNlsInfo::InitSortHandleHelper(LPCWSTR localeName, __out INT_PTR* handleOrigin)
-{
-    CONTRACTL {
-        NOTHROW;
-        GC_NOTRIGGER;
-        MODE_ANY;
-        CANNOT_TAKE_LOCK;
-        PRECONDITION(localeName != NULL);
-    } CONTRACTL_END;
-
-    INT_PTR pSort = NULL;
-
-    // coreclr will try to initialize the handle and if running on downlevel it'll just return null
-    pSort = InternalInitOsSortHandle(localeName, handleOrigin);
-    return pSort;
-}
-
-
-// Can return NULL
-INT_PTR COMNlsInfo::InternalInitOsSortHandle(LPCWSTR localeName, __out INT_PTR* handleOrigin)
-{
-    CONTRACTL {
-        NOTHROW;
-        GC_NOTRIGGER;
-        MODE_ANY;
-        CANNOT_TAKE_LOCK;
-        PRECONDITION(localeName != NULL);
-    } CONTRACTL_END;
-    
-    INT_PTR pSort = NULL;
-
-    AppDomain* curDomain = GetAppDomain();
-
-    if (RunningOnWin8())
-    {
-        LPARAM lSortHandle;
-        int ret;
-
-        {
-            ret = NewApis::LCMapStringEx(localeName, LCMAP_SORTHANDLE, NULL, 0, (LPWSTR) &lSortHandle, sizeof(LPARAM), NULL, NULL, 0);
-            *handleOrigin = (INT_PTR) NewApis::LCMapStringEx;
-        }
-
-        if (ret != 0)
-        {
-            pSort = (INT_PTR) lSortHandle;
-        }
-    }
-
-    return pSort;
-}
-
-BOOL QCALLTYPE COMNlsInfo::InternalGetNlsVersionEx(INT_PTR handle, INT_PTR handleOrigin, LPCWSTR lpLocaleName, NLSVERSIONINFOEX * lpVersionInformation)
-{
-    CONTRACTL {
-        QCALL_CHECK;
-    } CONTRACTL_END;
-
-    BOOL ret = FALSE;
-
-    BEGIN_QCALL;
-    ret = GetNLSVersionEx(COMPARE_STRING, lpLocaleName, lpVersionInformation);
-    END_QCALL;
-    return ret;
-}
-
index 8d10353..422b72a 100644 (file)
@@ -846,7 +846,6 @@ namespace System.Globalization
 
         internal static int GetSystemTwoDigitYearSetting(CalendarId CalID, int defaultYearValue)
         {
-            // Call nativeGetTwoDigitYearMax
             int twoDigitYearMax = CalendarData.GetTwoDigitYearMax(CalID);
             if (twoDigitYearMax < 0)
             {
index 008a0e7..a420c52 100644 (file)
@@ -867,12 +867,6 @@ FCFuncEnd()
 #if !defined(FEATURE_COREFX_GLOBALIZATION)
 FCFuncStart(gCompareInfoFuncs)
     QCFuncElement("InternalGetGlobalizedHashCode", COMNlsInfo::InternalGetGlobalizedHashCode)
-    QCFuncElement("InternalCompareString", COMNlsInfo::InternalCompareString)
-    QCFuncElement("InternalFindNLSStringEx", COMNlsInfo::InternalFindNLSStringEx)
-    QCFuncElement("NativeInternalInitSortHandle", COMNlsInfo::InternalInitSortHandle)
-    QCFuncElement("InternalIsSortable", COMNlsInfo::InternalIsSortable)
-    QCFuncElement("InternalGetSortKey", COMNlsInfo::InternalGetSortKey)
-    QCFuncElement("InternalGetNlsVersionEx", COMNlsInfo::InternalGetNlsVersionEx)
 FCFuncEnd()
 
 FCFuncStart(gEncodingTableFuncs)
@@ -880,39 +874,6 @@ FCFuncStart(gEncodingTableFuncs)
     FCFuncElement("GetEncodingData", COMNlsInfo::nativeGetEncodingTableDataPointer)
     FCFuncElement("GetCodePageData", COMNlsInfo::nativeGetCodePageTableDataPointer)
 FCFuncEnd()
-
-FCFuncStart(gCalendarDataFuncs)
-    FCFuncElement("nativeGetTwoDigitYearMax", CalendarData::nativeGetTwoDigitYearMax)
-    FCFuncElement("nativeGetCalendarData", CalendarData::nativeGetCalendarData)
-    FCFuncElement("nativeGetCalendars", CalendarData::nativeGetCalendars)
-FCFuncEnd()
-
-FCFuncStart(gCultureDataFuncs)
-    FCFuncElement("nativeGetNumberFormatInfoValues", COMNlsInfo::nativeGetNumberFormatInfoValues)
-    FCFuncElement("nativeEnumTimeFormats", CalendarData::nativeEnumTimeFormats)
-    FCFuncElement("LCIDToLocaleName", COMNlsInfo::LCIDToLocaleName)
-    FCFuncElement("LocaleNameToLCID", COMNlsInfo::LocaleNameToLCID)    
-
-    QCFuncElement("nativeEnumCultureNames", COMNlsInfo::nativeEnumCultureNames)
-
-FCFuncEnd()
-
-FCFuncStart(gCultureInfoFuncs)
-    QCFuncElement("InternalGetDefaultLocaleName", COMNlsInfo::InternalGetDefaultLocaleName)
-    FCFuncElement("nativeGetLocaleInfoEx", COMNlsInfo::nativeGetLocaleInfoEx)
-    FCFuncElement("nativeGetLocaleInfoExInt", COMNlsInfo::nativeGetLocaleInfoExInt)
-    
-    QCFuncElement("InternalGetUserDefaultUILanguage", COMNlsInfo::InternalGetUserDefaultUILanguage)
-    QCFuncElement("InternalGetSystemDefaultUILanguage", COMNlsInfo::InternalGetSystemDefaultUILanguage)
-FCFuncEnd()
-
-FCFuncStart(gTextInfoFuncs)
-    FCFuncElement("InternalChangeCaseChar", COMNlsInfo::InternalChangeCaseChar)
-    FCFuncElement("InternalChangeCaseString", COMNlsInfo::InternalChangeCaseString)
-    FCFuncElement("InternalGetCaseInsHash", COMNlsInfo::InternalGetCaseInsHash)
-    QCFuncElement("InternalCompareStringOrdinalIgnoreCase", COMNlsInfo::InternalCompareStringOrdinalIgnoreCase)
-    QCFuncElement("InternalTryFindStringOrdinalIgnoreCase", COMNlsInfo::InternalTryFindStringOrdinalIgnoreCase)
-FCFuncEnd()
 #endif // !defined(FEATURE_COREFX_GLOBALIZATION)
 
 #ifdef FEATURE_COREFX_GLOBALIZATION
@@ -1403,16 +1364,9 @@ FCClassElement("AssemblyName", "System.Reflection", gAssemblyNameFuncs)
 FCClassElement("Assert", "System.Diagnostics", gDiagnosticsAssert)
 FCClassElement("BCLDebug", "System", gBCLDebugFuncs)
 FCClassElement("Buffer", "System", gBufferFuncs)
-#if !defined(FEATURE_COREFX_GLOBALIZATION)
-FCClassElement("CalendarData", "System.Globalization", gCalendarDataFuncs)
-#endif // !defined(FEATURE_COREFX_GLOBALIZATION)
 FCClassElement("CompareInfo", "System.Globalization", gCompareInfoFuncs)
 FCClassElement("CompatibilitySwitch", "System.Runtime.Versioning", gCompatibilitySwitchFuncs)
 FCClassElement("CriticalHandle", "System.Runtime.InteropServices", gCriticalHandleFuncs)
-#if !defined(FEATURE_COREFX_GLOBALIZATION)
-FCClassElement("CultureData", "System.Globalization", gCultureDataFuncs)
-FCClassElement("CultureInfo", "System.Globalization", gCultureInfoFuncs)
-#endif
 FCClassElement("Currency", "System", gCurrencyFuncs)
 FCClassElement("CustomAttribute", "System.Reflection", gCOMCustomAttributeFuncs)
 FCClassElement("CustomAttributeEncodedArgument", "System.Reflection", gCustomAttributeEncodedArgument)
@@ -1521,9 +1475,6 @@ FCClassElement("String", "System", gStringFuncs)
 FCClassElement("StringBuilder", "System.Text", gStringBufferFuncs)
 FCClassElement("StubHelpers", "System.StubHelpers", gStubHelperFuncs)
 FCClassElement("SynchronizationContext", "System.Threading", gContextSynchronizationFuncs)
-#if !defined(FEATURE_COREFX_GLOBALIZATION)
-FCClassElement("TextInfo", "System.Globalization", gTextInfoFuncs)
-#endif // !defined(FEATURE_COREFX_GLOBALIZATION)
 FCClassElement("Thread", "System.Threading", gThreadFuncs)
 FCClassElement("ThreadPool", "System.Threading", gThreadPoolFuncs)
 FCClassElement("TimerQueue", "System.Threading", gTimerFuncs)
index 4d98eba..963e890 100644 (file)
@@ -34,7 +34,6 @@
 #include "excep.h"
 #include "fcall.h"
 #include "nlsinfo.h"
-#include "calendardata.h"
 #include "commodule.h"
 #include "marshalnative.h"
 #include "system.h"
index 178ce2c..f0850b7 100644 (file)
@@ -304,29 +304,6 @@ DEFINE_FIELD_U(m_encodedEnumType,  CustomAttributeType,            m_enumType)
 DEFINE_FIELD_U(m_encodedArrayType, CustomAttributeType,            m_arrayType)
 DEFINE_FIELD_U(m_padding,          CustomAttributeType,            m_padding)
 
-#ifndef FEATURE_COREFX_GLOBALIZATION
-DEFINE_CLASS_U(Globalization,          CalendarData,           CalendarDataBaseObject)
-DEFINE_FIELD_U(sNativeName,            CalendarDataBaseObject, sNativeName)
-DEFINE_FIELD_U(saShortDates,           CalendarDataBaseObject, saShortDates)
-DEFINE_FIELD_U(saYearMonths,           CalendarDataBaseObject, saYearMonths)
-DEFINE_FIELD_U(saLongDates,            CalendarDataBaseObject, saLongDates)
-DEFINE_FIELD_U(sMonthDay,              CalendarDataBaseObject, sMonthDay)
-DEFINE_FIELD_U(saEraNames,             CalendarDataBaseObject, saEraNames)
-DEFINE_FIELD_U(saAbbrevEraNames,       CalendarDataBaseObject, saAbbrevEraNames)
-DEFINE_FIELD_U(saAbbrevEnglishEraNames,CalendarDataBaseObject, saAbbrevEnglishEraNames)
-DEFINE_FIELD_U(saDayNames,             CalendarDataBaseObject, saDayNames)
-DEFINE_FIELD_U(saAbbrevDayNames,       CalendarDataBaseObject, saAbbrevDayNames)
-DEFINE_FIELD_U(saSuperShortDayNames,   CalendarDataBaseObject, saSuperShortDayNames)
-DEFINE_FIELD_U(saMonthNames,           CalendarDataBaseObject, saMonthNames)
-DEFINE_FIELD_U(saAbbrevMonthNames,     CalendarDataBaseObject, saAbbrevMonthNames)
-DEFINE_FIELD_U(saMonthGenitiveNames,   CalendarDataBaseObject, saMonthGenitiveNames)
-DEFINE_FIELD_U(saAbbrevMonthGenitiveNames, CalendarDataBaseObject, saAbbrevMonthGenitiveNames)
-DEFINE_FIELD_U(saLeapYearMonthNames,   CalendarDataBaseObject, saLeapYearMonthNames)
-DEFINE_FIELD_U(iTwoDigitYearMax,       CalendarDataBaseObject, iTwoDigitYearMax)
-DEFINE_FIELD_U(iCurrentEra,            CalendarDataBaseObject, iCurrentEra)
-DEFINE_FIELD_U(bUseUserOverrides,      CalendarDataBaseObject, bUseUserOverrides)
-#endif
-
 DEFINE_CLASS_U(Globalization,          CultureInfo,        CultureInfoBaseObject)
 DEFINE_FIELD_U(compareInfo,        CultureInfoBaseObject,  compareInfo)
 DEFINE_FIELD_U(textInfo,           CultureInfoBaseObject,  textInfo)
index 1a9d8fd..65969bf 100644 (file)
@@ -1606,43 +1606,6 @@ public:
 
 }; // class CultureInfoBaseObject
 
-#ifndef FEATURE_COREFX_GLOBALIZATION
-typedef DPTR(class CalendarDataBaseObject) PTR_CalendarDataBaseObject;
-class CalendarDataBaseObject : public Object
-{
-public:   
-    /* 0x000 */ STRINGREF   sNativeName                 ; // Calendar Name for the locale
-    
-    // Formats
-    
-    /* 0x008 */ PTRARRAYREF saShortDates                ; // Short Data format, default first
-    /* 0x010 */ PTRARRAYREF saYearMonths                ; // Year/Month Data format, default first
-    /* 0x018 */ PTRARRAYREF saLongDates                 ; // Long Data format, default first
-    /* 0x020 */ STRINGREF   sMonthDay                   ; // Month/Day format
-
-    // Calendar Parts Names
-    /* 0x028 */ PTRARRAYREF saEraNames                  ; // Names of Eras
-    /* 0x030 */ PTRARRAYREF saAbbrevEraNames            ; // Abbreviated Era Names
-    /* 0x038 */ PTRARRAYREF saAbbrevEnglishEraNames     ; // Abbreviated Era Names in English
-    /* 0x040 */ PTRARRAYREF saDayNames                  ; // Day Names, null to use locale data, starts on Sunday
-    /* 0x048 */ PTRARRAYREF saAbbrevDayNames            ; // Abbrev Day Names, null to use locale data, starts on Sunday
-    /* 0x050 */ PTRARRAYREF saSuperShortDayNames        ; // Super short Day of week names
-    /* 0x058 */ PTRARRAYREF saMonthNames                ; // Month Names (13)
-    /* 0x060 */ PTRARRAYREF saAbbrevMonthNames          ; // Abbrev Month Names (13)
-    /* 0x068 */ PTRARRAYREF saMonthGenitiveNames        ; // Genitive Month Names (13)
-    /* 0x070 */ PTRARRAYREF saAbbrevMonthGenitiveNames  ; // Genitive Abbrev Month Names (13)
-    /* 0x078 */ PTRARRAYREF saLeapYearMonthNames        ; // Multiple strings for the month names in a leap year.
-
-    // Integers at end to make marshaller happier
-    /* 0x080 */ INT32       iTwoDigitYearMax            ; // Max 2 digit year (for Y2K bug data entry)
-    /* 0x084 */ INT32       iCurrentEra                 ; // current era # (usually 1)
-
-    // Use overrides?
-    /* 0x088 */ CLR_BOOL    bUseUserOverrides           ; // True if we want user overrides.
-}; // class CalendarDataBaseObject
-#endif
-
-
 typedef DPTR(class ThreadBaseObject) PTR_ThreadBaseObject;
 class ThreadBaseObject : public Object
 {