CultureData.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Globalization / CultureData.cs / 1305376 / CultureData.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System.Globalization
{ 
 
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
#if !FEATURE_CORECLR 
    using System.Reflection;
    using System.Resources; 
#endif 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Runtime.Versioning;
    using System.Diagnostics.Contracts;
    using System.Security;
    using System.Security.Principal; 

    // 
    // List of culture data 
    // Note the we cache overrides.
    // Note that localized names (resource names) aren't available from here. 
    //

    //
    // Our names are a tad confusing. 
    //
    // sWindowsName -- The name that windows thinks this culture is, ie: 
    //                            en-US if you pass in en-US 
    //                            de-DE_phoneb if you pass in de-DE_phoneb
    //                            fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine) 
    //                            fj if you pass in fj (neutral, post-Windows 7 machine)
    //
    // sRealName -- The name you used to construct the culture, in pretty form
    //                       en-US if you pass in EN-us 
    //                       en if you pass in en
    //                       de-DE_phoneb if you pass in de-DE_phoneb 
    // 
    // sSpecificCulture -- The specific culture for this culture
    //                             en-US for en-US 
    //                             en-US for en
    //                             de-DE_phoneb for alt sort
    //                             fj-FJ for fj (neutral)
    // 
    // sName -- The IETF name of this culture (ie: no sort info, could be neutral)
    //                en-US if you pass in en-US 
    //                en if you pass in en 
    //                de-DE if you pass in de-DE_phoneb
    // 

    // StructLayout is needed here otherwise compiler can re-arrange the fields.
    // We have to keep this in-[....] with the definition in comnlsinfo.h
    // 
    // WARNING WARNING WARNING
    // 
    // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CultureDataBaseObject) 
    // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureDataBaseObject
    // WARNING: must be manually structured to match the true loaded class layout 
    //
    internal class CultureData
    {
        const int undef = -1; 

        // Override flag 
        private String sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) 
        private String sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
 
        // Identity
        private String sName; // locale name (ie: en-us, NO sort info, but could be neutral)
        private String sParent; // Parent name (which may be a custom locale/culture)
        private String sLocalizedDisplayName; // Localized pretty name for this locale 
        private String sEnglishDisplayName; // English pretty name for this locale
        private String sNativeDisplayName; // Native pretty name for this locale 
        private String sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort 

        // Language 
        private String sISO639Language; // ISO 639 Language Name
        private String sLocalizedLanguage; // Localized name for this language
        private String sEnglishLanguage; // English name for this language
        private String sNativeLanguage; // Native name of this language 

        // Region 
        private String sRegionName; // (RegionInfo) 
        //        private int    iCountry=undef           ; // (user can override) ---- code (RegionInfo)
        private int iGeoId = undef; // GeoId 
        private String sLocalized----; // localized ---- name
        private String sEnglishCountry; // english ---- name (RegionInfo)
        private String sNativeCountry; // native ---- name
        private String sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US 

        // Numbers 
        private String sPositiveSign; // (user can override) positive sign 
        private String sNegativeSign; // (user can override) negative sign
        private String[] saNativeDigits; // (user can override) native characters for digits 0-9 
        // (nfi populates these 5, don't have to be = undef)
        private int iDigitSubstitution; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused)
        private int iLeadingZeros; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros
        private int iDigits; // (user can override) number of fractional digits 
        private int iNegativeNumber; // (user can override) negative number format
        private int[] waGrouping; // (user can override) grouping of digits 
        private String sDecimalSeparator; // (user can override) decimal separator 
        private String sThousandSeparator; // (user can override) thousands separator
        private String sNaN; // Not a Number 
        private String sPositiveInfinity; // + Infinity
        private String sNegativeInfinity; // - Infinity

        // Percent 
        private int iNegativePercent = undef; // Negative Percent (0-3)
        private int iPositivePercent = undef; // Positive Percent (0-11) 
        private String sPercent; // Percent (%) symbol 
        private String sPerMille; // PerMille (‰) symbol
 
        // Currency
        private String sCurrency; // (user can override) local monetary symbol
        private String sIntlMonetarySymbol; // international monetary symbol (RegionInfo)
        private String sEnglishCurrency; // English name for this currency 
        private String sNativeCurrency; // Native name for this currency
        // (nfi populates these 4, don't have to be = undef) 
        private int iCurrencyDigits; // (user can override) # local monetary fractional digits 
        private int iCurrency; // (user can override) positive currency format
        private int iNegativeCurrency; // (user can override) negative currency format 
        private int[] waMonetaryGrouping; // (user can override) monetary grouping of digits
        private String sMonetaryDecimal; // (user can override) monetary decimal separator
        private String sMonetaryThousand; // (user can override) monetary thousands separator
 
        // Misc
        private int iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) 
        private String sListSeparator; // (user can override) list separator 
        //        private int    iPaperSize               ; // default paper size (RegionInfo)
 
        // Time
        private String sAM1159; // (user can override) AM designator
        private String sPM2359; // (user can override) PM designator
        private String[] saLongTimes; // (user can override) time format 
        private String[] saShortTimes; // short time format
        private String[] saDurationFormats; // time duration format 
 
        // Calendar specific data
        private int iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) 
        private int iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really)
        private int[] waCalendars; // all available calendar type(s).  The first one is the default calendar

        // Store for specific data about each calendar 
        private CalendarData[] calendars; // Store for specific calendar data
 
        // Text information 
#if !FEATURE_CORECLR
        private int iReadingLayout = undef; // Reading layout data 
        // 0 - Left to right (eg en-US)
        // 1 - Right to left (eg arabic locales)
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
        // 3 - Vertical top to bottom with columns proceeding to the right 
#endif
        private String sTextInfo; // Text info name to use for custom 
        private String sCompareInfo; // Compare info name (including sorting key) to use if custom 
        private String sScripts; // Typical Scripts for this locale (latn;cyrl; etc)
 
        // CoreCLR depends on this even though its not exposed publicly.
#if !FEATURE_CORECLR
        private int iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP)
        private int iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) 
        private int iDefaultMacCodePage = undef; // default macintosh code page
        private int iDefaultEbcdicCodePage = undef; // default EBCDIC code page 
 
        // These are desktop only, not coreclr
        private int    iLanguage; // locale ID (0409) - NO sort information 
        private String sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU
        private String sAbbrevCountry; // abbreviated ---- name (RegionInfo) (Windows Region Name) ex: USA
        private String sISO639Language2; // 3 char ISO 639 lang name 2 ex: eng
        private String sISO3166CountryName2; // 3 char ISO 3166 ---- name 2 2(RegionInfo) ex: USA (ISO) 
        private int    iInputLanguageHandle=undef;// input language handle
        private String sConsoleFallbackName; // The culture name for the console fallback UI culture 
        private String sKeyboardsToInstall; // Keyboard installation string. 
        private String fontSignature; // Font signature (16 WORDS)
#endif 

        // The bools all need to be in one spot
        private bool bUseOverrides; // use user overrides?
        private bool bNeutral; // Flags for the culture (ie: neutral or not right now) 
#if !FEATURE_CORECLR
        private bool bWin32Installed; // Flags indicate if the culture is Win32 installed 
        private bool bFramework; // Flags for indicate if the culture is one of Whidbey cultures 
#endif
 
#if !FEATURE_CORECLR
        // Region Name to Culture Name mapping table
        // (In future would be nice to be in registry or something)
 
        //Using a field initializer rather than a static constructor so that the whole class can be lazy
        //init. 
        private static Dictionary RegionNames; 
        private static readonly bool init = Init();
        private static bool Init() 
        {
            RegionNames = new Dictionary
            {
                { "029", "en-029" }, 
                { "AE",  "ar-AE" },
                { "AF",  "prs-AF" }, 
                { "AL",  "sq-AL" }, 
                { "AM",  "hy-AM" },
                { "AR",  "es-AR" }, 
                { "AT",  "de-AT" },
                { "AU",  "en-AU" },
                { "AZ",  "az-Cyrl-AZ" },
                { "BA",  "bs-Latn-BA" }, 
                { "BD",  "bn-BD" },
                { "BE",  "nl-BE" }, 
                { "BG",  "bg-BG" }, 
                { "BH",  "ar-BH" },
                { "BN",  "ms-BN" }, 
                { "BO",  "es-BO" },
                { "BR",  "pt-BR" },
                { "BY",  "be-BY" },
                { "BZ",  "en-BZ" }, 
                { "CA",  "en-CA" },
                { "CH",  "it-CH" }, 
                { "CL",  "es-CL" }, 
                { "CN",  "zh-CN" },
                { "CO",  "es-CO" }, 
                { "CR",  "es-CR" },
                { "CS",  "sr-Cyrl-CS" },
                { "CZ",  "cs-CZ" },
                { "DE",  "de-DE" }, 
                { "DK",  "da-DK" },
                { "DO",  "es-DO" }, 
                { "DZ",  "ar-DZ" }, 
                { "EC",  "es-EC" },
                { "EE",  "et-EE" }, 
                { "EG",  "ar-EG" },
                { "ES",  "es-ES" },
                { "ET",  "am-ET" },
                { "FI",  "fi-FI" }, 
                { "FO",  "fo-FO" },
                { "FR",  "fr-FR" }, 
                { "GB",  "en-GB" }, 
                { "GE",  "ka-GE" },
                { "GL",  "kl-GL" }, 
                { "GR",  "el-GR" },
                { "GT",  "es-GT" },
                { "HK",  "zh-HK" },
                { "HN",  "es-HN" }, 
                { "HR",  "hr-HR" },
                { "HU",  "hu-HU" }, 
                { "ID",  "id-ID" }, 
                { "IE",  "en-IE" },
                { "IL",  "he-IL" }, 
                { "IN",  "hi-IN" },
                { "IQ",  "ar-IQ" },
                { "IR",  "fa-IR" },
                { "IS",  "is-IS" }, 
                { "IT",  "it-IT" },
                { "IV",  "" }, 
                { "JM",  "en-JM" }, 
                { "JO",  "ar-JO" },
                { "JP",  "ja-JP" }, 
                { "KE",  "sw-KE" },
                { "KG",  "ky-KG" },
                { "KH",  "km-KH" },
                { "KR",  "ko-KR" }, 
                { "KW",  "ar-KW" },
                { "KZ",  "kk-KZ" }, 
                { "LA",  "lo-LA" }, 
                { "LB",  "ar-LB" },
                { "LI",  "de-LI" }, 
                { "LK",  "si-LK" },
                { "LT",  "lt-LT" },
                { "LU",  "lb-LU" },
                { "LV",  "lv-LV" }, 
                { "LY",  "ar-LY" },
                { "MA",  "ar-MA" }, 
                { "MC",  "fr-MC" }, 
                { "ME",  "sr-Latn-ME" },
                { "MK",  "mk-MK" }, 
                { "MN",  "mn-MN" },
                { "MO",  "zh-MO" },
                { "MT",  "mt-MT" },
                { "MV",  "dv-MV" }, 
                { "MX",  "es-MX" },
                { "MY",  "ms-MY" }, 
                { "NG",  "ig-NG" }, 
                { "NI",  "es-NI" },
                { "NL",  "nl-NL" }, 
                { "NO",  "nn-NO" },
                { "NP",  "ne-NP" },
                { "NZ",  "en-NZ" },
                { "OM",  "ar-OM" }, 
                { "PA",  "es-PA" },
                { "PE",  "es-PE" }, 
                { "PH",  "en-PH" }, 
                { "PK",  "ur-PK" },
                { "PL",  "pl-PL" }, 
                { "PR",  "es-PR" },
                { "PT",  "pt-PT" },
                { "PY",  "es-PY" },
                { "QA",  "ar-QA" }, 
                { "RO",  "ro-RO" },
                { "RS",  "sr-Latn-RS" }, 
                { "RU",  "ru-RU" }, 
                { "RW",  "rw-RW" },
                { "SA",  "ar-SA" }, 
                { "SE",  "sv-SE" },
                { "SG",  "zh-SG" },
                { "SI",  "sl-SI" },
                { "SK",  "sk-SK" }, 
                { "SN",  "wo-SN" },
                { "SV",  "es-SV" }, 
                { "SY",  "ar-SY" }, 
                { "TH",  "th-TH" },
                { "TJ",  "tg-Cyrl-TJ" }, 
                { "TM",  "tk-TM" },
                { "TN",  "ar-TN" },
                { "TR",  "tr-TR" },
                { "TT",  "en-TT" }, 
                { "TW",  "zh-TW" },
                { "UA",  "uk-UA" }, 
                { "US",  "en-US" }, 
                { "UY",  "es-UY" },
                { "UZ",  "uz-Cyrl-UZ" }, 
                { "VE",  "es-VE" },
                { "VN",  "vi-VN" },
                { "YE",  "ar-YE" },
                { "ZA",  "af-ZA" }, 
                { "ZW",  "en-ZW" }
            }; 
            return true; 
        }
#endif 


        /////////////////////////////////////////////////////////////////////////
        // Build our invariant 
        //
        // We need an invariant instance, which we build hard-coded with the static constructor // 
        ///////////////////////////////////////////////////////////////////////// 
        internal static CultureData Invariant;
#if !FEATURE_CORECLR 
        internal static ResourceSet MscorlibResourceSet;
#endif

        static CultureData() 
        {
            // Make a new culturedata 
            CultureData invariant = new CultureData(); 

#if !FEATURE_CORECLR 
            // Call the native code to get the value of bWin32Installed.
            // For versions <= Vista, we set this to false for compatibility with v2.
            // For Windows 7, the flag is true.
            invariant.bUseOverrides = false; 
            invariant.sRealName = "";
 
            // Ask the native code to fill it out for us, we only need the field IsWin32Installed 
            nativeInitCultureData(invariant);
#endif 

            // Basics
            // Note that we override the resources since this IS NOT supposed to change (by definition)
            invariant.bUseOverrides = false; 
            invariant.sRealName = "";                     // Name you passed in (ie: en-US, en, or de-DE_phoneb)
            invariant.sWindowsName = "";                     // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) 
 
            // Identity
            invariant.sName = "";                     // locale name (ie: en-us) 
            invariant.sParent = "";                     // Parent name (which may be a custom locale/culture)
            invariant.bNeutral = false;                   // Flags for the culture (ie: neutral or not right now)
#if !FEATURE_CORECLR
            // Don't set invariant.bWin32Installed, we used nativeInitCultureData for that. 
            invariant.bFramework = true;
#endif 
            invariant.sEnglishDisplayName = "Invariant Language (Invariant ----)"; // English pretty name for this locale 
            invariant.sNativeDisplayName = "Invariant Language (Invariant ----)";  // Native pretty name for this locale
            invariant.sSpecificCulture = "";                     // The culture name to be used in CultureInfo.CreateSpecificCulture() 

            // Language
            invariant.sISO639Language = "iv";                   // ISO 639 Language Name
            invariant.sLocalizedLanguage = "Invariant Language";   // Display name for this Language 
            invariant.sEnglishLanguage = "Invariant Language";   // English name for this language
            invariant.sNativeLanguage = "Invariant Language";   // Native name of this language 
 
            // Region
            invariant.sRegionName = "IV";                   // (RegionInfo) 
            // Unused for now:
            //            invariant.iCountry              =1;                      // ---- code (RegionInfo)
            invariant.iGeoId = 244;                    // GeoId (Windows Only)
            invariant.sEnglishCountry = "Invariant ----";    // english ---- name (RegionInfo) 
            invariant.sNativeCountry = "Invariant ----";    // native ---- name (Windows Only)
            invariant.sISO3166CountryName = "IV";                   // (RegionInfo), ie: US 
 
            // Numbers
            invariant.sPositiveSign = "+";                    // positive sign 
            invariant.sNegativeSign = "-";                    // negative sign
            invariant.saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9
            invariant.iDigitSubstitution = 1;                      // Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only)
            invariant.iLeadingZeros = 1;                      // leading zeros 0=no leading zeros, 1=leading zeros 
            invariant.iDigits = 2;                      // number of fractional digits
            invariant.iNegativeNumber = 1;                      // negative number format 
            invariant.waGrouping = new int[] { 3 };          // grouping of digits 
            invariant.sDecimalSeparator = ".";                    // decimal separator
            invariant.sThousandSeparator = ",";                    // thousands separator 
            invariant.sNaN = "NaN";                  // Not a Number
            invariant.sPositiveInfinity = "Infinity";             // + Infinity
            invariant.sNegativeInfinity = "-Infinity";            // - Infinity
 
            // Percent
            invariant.iNegativePercent = 0;                      // Negative Percent (0-3) 
            invariant.iPositivePercent = 0;                      // Positive Percent (0-11) 
            invariant.sPercent = "%";                    // Percent (%) symbol
            invariant.sPerMille = "\x2030";               // PerMille(‰) symbol 

            // Currency
            invariant.sCurrency = "\x00a4";                // local monetary symbol "¤: for international monetary symbol
            invariant.sIntlMonetarySymbol = "XDR";                  // international monetary symbol (RegionInfo) 
            invariant.sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only)
            invariant.sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) 
            invariant.iCurrencyDigits = 2;                      // # local monetary fractional digits 
            invariant.iCurrency = 0;                      // positive currency format
            invariant.iNegativeCurrency = 0;                      // negative currency format 
            invariant.waMonetaryGrouping = new int[] { 3 };          // monetary grouping of digits
            invariant.sMonetaryDecimal = ".";                    // monetary decimal separator
            invariant.sMonetaryThousand = ",";                    // monetary thousands separator
 
            // Misc
            invariant.iMeasure = 0;                      // system of measurement 0=metric, 1=US (RegionInfo) 
            invariant.sListSeparator = ",";                    // list separator 
            // Unused for now:
            //            invariant.iPaperSize            =9;                      // default paper size (RegionInfo) 
            //            invariant.waFontSignature       ="\x0002\x0000\x0000\x0000\x0000\x0000\x0000\x8000\x0001\x0000\x0000\x8000\x0001\x0000\x0000\x8000"; // Font signature (16 WORDS) (Windows Only)

            // Time
            invariant.sAM1159 = "AM";                   // AM designator 
            invariant.sPM2359 = "PM";                   // PM designator
            invariant.saLongTimes = new String[] { "HH:mm:ss" };                             // time format 
            invariant.saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format 
            invariant.saDurationFormats = new String[] { "HH:mm:ss" };                             // time duration format
 
            // Calendar specific data
            invariant.iFirstDayOfWeek = 0;                      // first day of week
            invariant.iFirstWeekOfYear = 0;                      // first week of year
            invariant.waCalendars = new int[] { (int)CalendarId.GREGORIAN };       // all available calendar type(s).  The first one is the default calendar 

            // Store for specific data about each calendar 
            invariant.calendars = new CalendarData[CalendarData.MAX_CALENDARS]; 
            invariant.calendars[0] = CalendarData.Invariant;
 
            // Text information
#if !FEATURE_CORECLR
            invariant.iReadingLayout = 0;                      // Reading Layout = RTL
#endif 
            invariant.sTextInfo = "";                     // Text info name to use for custom
            invariant.sCompareInfo = "";                     // Compare info name (including sorting key) to use if custom 
            invariant.sScripts = "Latn;";                // Typical Scripts for this locale (latn,cyrl, etc) 

            // These are desktop only, not coreclr 
#if !FEATURE_CORECLR
            invariant.iLanguage = 0x007f;                 // locale ID (0409) - NO sort information
            invariant.iDefaultAnsiCodePage = 1252;                   // default ansi code page ID (ACP)
            invariant.iDefaultOemCodePage = 437;                    // default oem code page ID (OCP or OEM) 
            invariant.iDefaultMacCodePage = 10000;                  // default macintosh code page
            invariant.iDefaultEbcdicCodePage = 037;                    // default EBCDIC code page 
            invariant.sAbbrevLang = "IVL";                  // abbreviated language name (Windows Language Name) 
            invariant.sAbbrevCountry = "IVC";                  // abbreviated ---- name (RegionInfo) (Windows Region Name)
            invariant.sISO639Language2 = "ivl";                  // 3 char ISO 639 lang name 2 
            invariant.sISO3166CountryName2 = "ivc";                  // 3 char ISO 3166 ---- name 2 2(RegionInfo)
            invariant.iInputLanguageHandle = 0x007f;                 // input language handle
            invariant.sConsoleFallbackName = "";                     // The culture name for the console fallback UI culture
            invariant.sKeyboardsToInstall = "0409:00000409";        // Keyboard installation string. 
#endif
            // Remember it 
            Invariant = invariant; 
        }
 
#if !FEATURE_CORECLR
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsResourcePresent(String resourceKey)
        { 
            if (MscorlibResourceSet == null)
            { 
                MscorlibResourceSet = new ResourceSet(typeof(Environment).Assembly.GetManifestResourceStream("mscorlib.resources")); 
            }
            return MscorlibResourceSet.GetString(resourceKey) != null; 
        }
#endif

        /////////////// 
        // Constructors //
        /////////////// 
        // Cache of cultures we've already looked up 
        private static Dictionary s_cachedCultures;
 
        internal static CultureData GetCultureData(String cultureName, bool useUserOverride)
        {
            // First do a shortcut for Invariant
            if (String.IsNullOrEmpty(cultureName)) 
            {
                return CultureData.Invariant; 
            } 

            // Try the hash table first 
            String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
            Dictionary tempHashTable = s_cachedCultures;
            if (tempHashTable == null)
            { 
                // No table yet, make a new one
                tempHashTable = new Dictionary(); 
            } 
            else
            { 
                // Check the hash table
                CultureData retVal;
                lock (((ICollection)tempHashTable).SyncRoot)
                { 
                    tempHashTable.TryGetValue(hashName, out retVal);
                } 
                if (retVal != null) 
                {
                    return retVal; 
                }
            }

            // Not found in the hash table, need to see if we can build one that works for us 
            CultureData culture = CreateCultureData(cultureName, useUserOverride);
            if (culture == null) 
            { 
                return null;
            } 

            // Found one, add it to the cache
            lock (((ICollection)tempHashTable).SyncRoot)
            { 
                tempHashTable[hashName] = culture;
            } 
 
            // Copy the hashtable to the corresponding member variables.  This will potentially overwrite
            // new tables simultaneously created by a new thread, but maximizes thread safety. 
            s_cachedCultures = tempHashTable;

            return culture;
        } 

        private static CultureData CreateCultureData(string cultureName, bool useUserOverride) 
        { 
            CultureData culture = new CultureData();
            culture.bUseOverrides = useUserOverride; 
            culture.sRealName = cultureName;

            // Ask native code if that one's real
            if (culture.InitCultureData() == false) 
            {
#if !FEATURE_CORECLR 
                if (culture.InitCompatibilityCultureData() == false 
                 && culture.InitLegacyAlternateSortData() == false)
#endif 
                {
                    return null;
                }
            } 

            return culture; 
        } 

        [System.Security.SecuritySafeCritical] 
        private bool InitCultureData()
        {
            if (nativeInitCultureData(this) == false)
            { 
                return false;
            } 
 
#if !FEATURE_CORECLR
            if (CultureInfo.Is----Sku) 
            {
                Treat----ParentChainAsHaving----AsSpecific();
            }
#endif 
            return true;
        } 
 
#if !FEATURE_CORECLR
        [System.Security.SecuritySafeCritical] 
        private void Treat----ParentChainAsHaving----AsSpecific()
        {
            if (IsNeutralInParentChainOf----() && IsOsPriorToWin7() && !IsReplacementCulture)
            { 
                // force population of fields that should have information that is
                // different than zh-TW: 
                string s = SNATIVELANGUAGE; 
                s = SENGLISHLANGUAGE;
                s = SLOCALIZEDLANGUAGE; 
                s = STEXTINFO;
                s = SCOMPAREINFO;
                s = FONTSIGNATURE;
                int i = IDEFAULTANSICODEPAGE; 
                i = IDEFAULTOEMCODEPAGE;
                i = IDEFAULTMACCODEPAGE; 
 
                // all other fields will be populated with values that are the same
                // as those for ---- 
                this.sSpecificCulture = "zh-TW";
                this.sWindowsName = "zh-TW";
            }
        } 

        private bool IsNeutralInParentChainOf----() 
        { 
            return this.sRealName == "zh" || this.sRealName == "zh-Hant";
  } 

        static readonly Version s_win7Version = new Version(6, 1);
        static private bool IsOsPriorToWin7()
        { 
            return Environment.OSVersion.Platform == PlatformID.Win32NT &&
                   Environment.OSVersion.Version < s_win7Version; 
        } 
        static private bool IsOsWin7OrPrior()
        { 
            return Environment.OSVersion.Platform == PlatformID.Win32NT &&
                Environment.OSVersion.Version < new Version(6, 2); // Win7 is 6.1.Build.Revision so we have to check for anything less than 6.2
        }
 
        private bool InitCompatibilityCultureData()
        { 
            // for compatibility handle the deprecated ids: zh-chs, zh-cht 
            string cultureName = this.sRealName;
 
            string fallbackCultureName;
            string realCultureName;
            switch (AnsiToLower(cultureName))
            { 
                case "zh-chs":
                    fallbackCultureName = "zh-Hans"; 
                    realCultureName = "zh-CHS"; 
                    break;
                case "zh-cht": 
                    fallbackCultureName = "zh-Hant";
                    realCultureName = "zh-CHT";
                    break;
                default: 
                    return false;
            } 
 
            this.sRealName = fallbackCultureName;
            if (InitCultureData() == false) 
            {
                return false;
            }
            // fixup our data 
            this.sName = realCultureName; // the name that goes back to the user
            this.sParent = fallbackCultureName; 
            this.bFramework = true; 

            return true; 
        }

        private bool InitLegacyAlternateSortData()
        { 
            if (!CompareInfo.IsLegacy20SortingBehaviorRequested)
            { 
                return false; 
            }
 
            // For V2 compatability, handle deprecated alternate sorts
            string cultureName = this.sRealName;

            switch (AnsiToLower(cultureName)) 
            {
                case "ko-kr_unicod": 
                    cultureName = "ko-KR_unicod"; 
                    this.sRealName = "ko-KR";
                    this.iLanguage = 0x00010412; 
                    break;
                case "ja-jp_unicod":
                    cultureName = "ja-JP_unicod";
                    this.sRealName = "ja-JP"; 
                    this.iLanguage = 0x00010411;
                    break; 
                case "zh-hk_stroke": 
                    cultureName = "zh-HK_stroke";
                    this.sRealName = "zh-HK"; 
                    this.iLanguage = 0x00020c04;
                    break;
                default:
                    return false; 
            }
 
            if (nativeInitCultureData(this) == false) 
            {
                return false; 
            }

            this.sRealName = cultureName;
            this.sCompareInfo = cultureName; 
            this.bFramework = true;
 
            return true; 
        }
 
        // Cache of regions we've already looked up
        private static Dictionary s_cachedRegions;

#if FEATURE_WIN32_REGISTRY 
        private static String s_RegionKey = @"System\CurrentControlSet\Control\Nls\RegionMapping";
#endif // FEATURE_WIN32_REGISTRY 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride) 
        {
            // First do a shortcut for Invariant
            if (String.IsNullOrEmpty(cultureName))
            { 
                return CultureData.Invariant;
            } 
 
            //
            // First check if GetCultureData() can find it (ie: its a real culture) 
            //
            CultureData retVal = GetCultureData(cultureName, useUserOverride);
            if (retVal != null && (retVal.IsNeutralCulture == false)) return retVal;
 
            //
            // Not a specific culture, perhaps it's region-only name 
            // (Remember this isn't a core clr path where that's not supported) 
            //
 
            // If it was neutral remember that so that RegionInfo() can throw the right exception
            CultureData neutral = retVal;

            // Try the hash table next 
            String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
            Dictionary tempHashTable = s_cachedRegions; 
            if (tempHashTable == null) 
            {
                // No table yet, make a new one 
                tempHashTable = new Dictionary();
            }
            else
            { 
                // Check the hash table
                lock (((ICollection)tempHashTable).SyncRoot) 
                { 
                    tempHashTable.TryGetValue(hashName, out retVal);
                } 
                if (retVal != null)
                {
                    return retVal;
                } 
            }
 
            // 
            // Not found in the hash table, look it up the hard way
            // 
#if FEATURE_WIN32_REGISTRY
            // First try the registry in case there are overrides of our table
            try
            { 
                // Open in read-only mode.
                // Use InternalOpenSubKey so that we avoid the security check. 
                Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.InternalOpenSubKey(s_RegionKey, false); 

                if (key != null) 
                {
                    try
                    {
                        Object value = key.InternalGetValue(cultureName, null, false, false); 

                        if (value != null) 
                        { 
                            // Get the name of the locale to try.
                            String specificForRegion = value.ToString(); 

                            // See if it's real
                            retVal = GetCultureData(specificForRegion, useUserOverride);
                        } 
                    }
                    finally 
                    { 
                        key.Close();
                    } 
                }
            }
            // If this fails for any reason, we'll just ignore it, likely it just isn't there.
            catch (ObjectDisposedException) { } 
            catch (ArgumentException) { }
#endif // FEATURE_WIN32_REGISTRY 
 
            // If not a valid mapping from the registry we'll have to try the hard coded table
            if (retVal == null || (retVal.IsNeutralCulture == true)) 
            {
                // Not a valid mapping, try the hard coded table
                if (RegionNames.ContainsKey(cultureName))
                { 
                    // Make sure we can get culture data for it
                    retVal = GetCultureData(RegionNames[cultureName], useUserOverride); 
                } 
            }
 
            // If not found in the hard coded table we'll have to find a culture that works for us
            if (retVal == null || (retVal.IsNeutralCulture == true))
            {
                // Not found in the hard coded table, need to see if we can find a culture that works for us 
                // Not a real culture name, see if it matches a region name
                // (we just return the first culture we match) 
                CultureInfo[] specifics = SpecificCultures; 
                for (int i = 0; i < specifics.Length; i++)
                { 
                    if (String.Compare(specifics[i].m_cultureData.SREGIONNAME, cultureName, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        // Matched, use this culture
                        retVal = specifics[i].m_cultureData; 
                        break;
                    } 
                } 
            }
 
            // If we found one we can use, then cash it for next time
            if (retVal != null && (retVal.IsNeutralCulture == false))
            {
                // first add it to the cache 
                lock (((ICollection)tempHashTable).SyncRoot)
                { 
                    tempHashTable[hashName] = retVal; 
                }
 
                // Copy the hashtable to the corresponding member variables.  This will potentially overwrite
                // new tables simultaneously created by a new thread, but maximizes thread safety.
                s_cachedRegions = tempHashTable;
            } 
            else
            { 
                // Unable to find a matching culture/region, return null or neutral 
                // (regionInfo throws a more specific exception on neutrals)
                retVal = neutral; 
            }

            // Return the found culture to use, null, or the neutral culture.
            return retVal; 
        }
#endif 
 
#if FEATURE_USE_LCID
        // Obtain locale name from LCID 
        // NOTE: This will get neutral names, unlike the OS API
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern String LCIDToLocaleName(int lcid);
 
        // We'd rather people use the named version since this doesn't allow custom locales 
        internal static CultureData GetCultureData(int culture, bool bUseUserOverride)
        { 
            String localeName = null;
            CultureData retVal = null;

#if !FEATURE_CORECLR 
            // If V2 legacy sort is requested, then provide deprecated alternate sorts
            if (CompareInfo.IsLegacy20SortingBehaviorRequested) 
            { 
                switch (culture)
                { 
                    case 0x00010412:
                        localeName = "ko-KR_unicod";
                        break;
                    case 0x00010411: 
                        localeName = "ja-JP_unicod";
                        break; 
                    case 0x00020c04: 
                        localeName = "zh-HK_stroke";
                        break; 
                }
            }
#endif
 
            if (localeName == null)
            { 
                // Convert the lcid to a name, then use that 
                // Note that this'll return neutral names (unlike Vista native API)
                localeName = LCIDToLocaleName(culture); 
            }

            // If its not valid, then throw
            if (String.IsNullOrEmpty(localeName)) 
            {
                // Could be valid for Invariant 
                if (culture == 0x007f) 
                    return Invariant;
            } 
            else
            {
#if !FEATURE_CORECLR
                switch (localeName) 
                {
                    // for compatibility with Whidbey, when requesting 
                    // a locale from LCID, return the old localeName 
                    case "zh-Hans":
                        localeName = "zh-CHS"; 
                        break;
                    case "zh-Hant":
                        localeName = "zh-CHT";
                        break; 
                }
#endif 
                // Valid name, use it 
                retVal = GetCultureData(localeName, bUseUserOverride);
            } 

            // If not successful, throw
            if (retVal == null)
                throw new CultureNotFoundException( 
                    "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            // Return the one we found 
            return retVal;
        } 
#endif

        // Clear our internal caches
        internal static void ClearCachedData() 
        {
            s_cachedCultures = null; 
#if !FEATURE_CORECLR 
            s_cachedRegions = null;
            s_replacementCultureNames = null; 
#endif
        }

#if !FEATURE_CORECLR && !CORIOLIS 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static CultureInfo[] GetCultures(CultureTypes types) 
        { 
            // Disable  warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
#pragma warning disable 618 
            // Validate flags
            if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures |
                                                            CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture |
                                                            CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | 
                                                            CultureTypes.FrameworkCultures)) != 0)
            { 
                throw new ArgumentOutOfRangeException( 
                                "types",
                                String.Format( 
                                    CultureInfo.CurrentCulture,
                                    Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures));
            }
 
            //
            // CHANGE FROM Whidbey 
            // 
            // We have deprecated CultureTypes.FrameworkCultures.
            // When this enum is used, we will enumerate Whidbey framework cultures (for compatability). 
            //

            // We have deprecated CultureTypes.WindowsOnlyCultures.
            // When this enum is used, we will return an empty array for this enum. 
            if ((types & CultureTypes.WindowsOnlyCultures) != 0)
            { 
                // Remove the enum as it is an no-op. 
                types &= (~CultureTypes.WindowsOnlyCultures);
            } 

            String[] cultureNames = null;

            // 
            // Call nativeEnumCultureNames() to get a string array of culture names based on the specified
            // enumeration type. 
            // 
            // nativeEnumCulturNames is a QCall.  We need to use a reference to return the string array
            // allocated from the QCall.  That ref has to be wrapped as object handle. 
            // See vm\qcall.h for details in QCall.
            //

            if (nativeEnumCultureNames((int)types, JitHelpers.GetObjectHandleOnStack(ref cultureNames)) == 0) 
            {
                return new CultureInfo[0]; 
            } 

            int arrayLength = cultureNames.Length; 

            if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
            {
                arrayLength += 2; 
            }
 
            CultureInfo[] cultures = new CultureInfo[arrayLength]; 

            for (int i = 0; i < cultureNames.Length; i++) 
            {
                cultures[i] = new CultureInfo(cultureNames[i]);
            }
 
            if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
            { 
                Contract.Assert(arrayLength == cultureNames.Length + 2, "CultureData.nativeEnumCultureNames() Incorrect array size"); 
                cultures[cultureNames.Length] = new CultureInfo("zh-CHS");
                cultures[cultureNames.Length + 1] = new CultureInfo("zh-CHT"); 
            }

#pragma warning restore 618
 
            return cultures;
        } 
 
        internal static CultureInfo[] specificCultures;
 
        private static CultureInfo[] SpecificCultures
        {
            get
            { 
                if (specificCultures == null)
                    specificCultures = GetCultures(CultureTypes.SpecificCultures); 
 
                return specificCultures;
            } 
        }


        internal bool IsReplacementCulture 
        {
            get 
            { 
                return IsReplacementCultureName(this.SNAME);
            } 
        }

        internal static String[] s_replacementCultureNames;
 
        ////////////////////////////////////////////////////////////////////////
        // 
        // Cache for the known replacement cultures. 
        // This is used by CultureInfo.CultureType to check if a culture is a
        // replacement culture. 
        //
        ////////////////////////////////////////////////////////////////////////

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static bool IsReplacementCultureName(String name) 
        { 
            Contract.Assert(name != null, "IsReplacementCultureName(): name should not be null");
            String[] replacementCultureNames = s_replacementCultureNames; 
            if (replacementCultureNames == null)
            {
                if (nativeEnumCultureNames((int)CultureTypes.ReplacementCultures, JitHelpers.GetObjectHandleOnStack(ref replacementCultureNames)) == 0)
                { 
                    return false;
                } 
 
                // Even if we don't have any replacement cultures, the returned replacementCultureNames will still an empty string array, not null.
                Contract.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null"); 
                Array.Sort(replacementCultureNames);
                s_replacementCultureNames = replacementCultureNames;
            }
            return Array.BinarySearch(replacementCultureNames, name) >= 0; 
        }
#endif 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  All the accessors
        //
        //  Accessors for our data object items
        // 
        ////////////////////////////////////////////////////////////////////////
 
        /////////// 
        // Identity //
        /////////// 

        // The real name used to construct the locale (ie: de-DE_phoneb)
        internal String CultureName
        { 
            get
            { 
                Contract.Assert(this.sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                // since windows doesn't know about zh-CHS and zh-CHT,
                // we leave sRealName == zh-Hanx but we still need to 
                // pretend that it was zh-CHX.
                switch (this.sName)
                {
                    case "zh-CHS": 
                    case "zh-CHT":
                        return this.sName; 
                } 
                return this.sRealName;
            } 
        }

        // Are overrides enabled?
        internal bool UseUserOverride 
        {
            get 
            { 
                return this.bUseOverrides;
            } 
        }

        // locale name (ie: de-DE, NO sort information)
        internal String SNAME 
        {
            get 
            { 
                //                Contract.Assert(this.sName != null,
                //                    "[CultureData.SNAME] Expected this.sName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                if (this.sName == null)
                {
                    this.sName = String.Empty;
                } 
                return this.sName;
            } 
        } 

        // Parent name (which may be a custom locale/culture) 
        internal String SPARENT
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sParent == null) 
                { 
                    // Ask using the real name, so that we get parents of neutrals
                    this.sParent = DoGetLocaleInfo(this.sRealName, LOCALE_SPARENT); 

#if !FEATURE_CORECLR
                    // for compatibility, the chain should be:
                    // zh-CN -> zh-CHS -> zh-Hans -> zh 
                    // zh-TW -> zh-CHT -> zh-Hant -> zh
                    Contract.Assert(this.sName != "zh-CHS" && this.sName != "zh-CHT", 
                                    "sParent should have been initialized for zh-CHS and zh-CHT when they were constructed, otherwise we get recursion"); 
                    switch (this.sParent)
                    { 
                        case "zh-Hans":
                            this.sParent = "zh-CHS";
                            break;
                        case "zh-Hant": 
                            this.sParent = "zh-CHT";
                            break; 
                    } 
#endif
 
                }
                return this.sParent;
            }
        } 

        // Localized pretty name for this locale (ie: Inglis (estados Unitos)) 
        internal String SLOCALIZEDDISPLAYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sLocalizedDisplayName == null)
                { 
#if !FEATURE_CORECLR
                    if (this.IsUserCustomCulture && !CultureData.IsReplacementCultureName(this.SNAME)) 
                    { 
                        if (this.IsNeutralCulture)
                        { 
                            this.sLocalizedDisplayName = this.SNATIVELANGUAGE;
                        }
                        else
                        { 
                            this.sLocalizedDisplayName = this.SNATIVEDISPLAYNAME;
                        } 
                    } 
                    else
                    { 
                        String resourceKey = "Globalization.ci_" + this.sName;
                        if (IsResourcePresent(resourceKey))
                        {
                            this.sLocalizedDisplayName = Environment.GetResourceString(resourceKey); 
                        }
                    } 
#endif 
                    // If it hasn't been found (Windows 8 and up), fallback to the system
                    if (String.IsNullOrEmpty(this.sLocalizedDisplayName)) 
                    {
                        // If its neutral use the language name
                        if (this.IsNeutralCulture)
                        { 
                            this.sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE;
                        } 
                        else 
                        {
                            // We have to make the neutral distinction in case the OS returns a specific name 
                            if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name))
                            {
                                this.sLocalizedDisplayName = DoGetLocaleInfo(LOCALE_SLOCALIZEDDISPLAYNAME);
                            } 
                            if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
                            { 
                                this.sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; 
                            }
                        } 
                    }
                }

                return this.sLocalizedDisplayName; 
            }
        } 
 
        // English pretty name for this locale (ie: English (United States))
        internal String SENGDISPLAYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated
            get
            { 
                if (this.sEnglishDisplayName == null)
                { 
                    // If its neutral use the language name 
                    if (this.IsNeutralCulture)
                    { 
                        this.sEnglishDisplayName = this.SENGLISHLANGUAGE;
#if !FEATURE_CORECLR
                        // differentiate the legacy display names
                        switch (this.sName) 
                        {
                            case "zh-CHS": 
                            case "zh-CHT": 
                                this.sEnglishDisplayName += " Legacy";
                                break; 
                        }
#endif

                    } 
                    else
                    { 
                        this.sEnglishDisplayName = DoGetLocaleInfo(LOCALE_SENGLISHDISPLAYNAME); 

                        // if it isn't found build one: 
                        if (String.IsNullOrEmpty(this.sEnglishDisplayName))
                        {
                            // Our existing names mostly look like:
                            // "English" + "United States" -> "English (United States)" 
                            // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
                            if (this.SENGLISHLANGUAGE.EndsWith(')')) 
                            { 
                                // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
                                this.sEnglishDisplayName = 
                                    this.SENGLISHLANGUAGE.Substring(0, this.sEnglishLanguage.Length - 1) +
                                    ", " + this.SENGCOUNTRY + ")";
                            }
                            else 
                            {
                                // "English" + "United States" -> "English (United States)" 
                                this.sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")"; 
                            }
                        } 
                    }
                }
                return this.sEnglishDisplayName;
            } 
        }
 
        // Native pretty name for this locale (ie: Deutsch (Deutschland)) 
        internal String SNATIVEDISPLAYNAME
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sNativeDisplayName == null) 
                {
                    // If its neutral use the language name 
                    if (this.IsNeutralCulture) 
                    {
                        this.sNativeDisplayName = this.SNATIVELANGUAGE; 
#if !FEATURE_CORECLR
                        // differentiate the legacy display names
                        switch (this.sName)
                        { 
                            case "zh-CHS":
                                this.sNativeDisplayName += " \u65E7\u7248"; 
                                break; 
                            case "zh-CHT":
                                this.sNativeDisplayName += " \u820A\u7248"; 
                                break;
                        }
#endif
                    } 
                    else
                    { 
#if !FEATURE_CORECLR 
                        if (IsIncorrectNativeLanguageForSinhala())
                        { 
                            // work around bug in Windows 7 for native name of Sinhala
                            this.sNativeDisplayName ="\x0dc3\x0dd2\x0d82\x0dc4\x0dbd (\x0DC1\x0DCA\x200D\x0DBB\x0DD3\x0020\x0DBD\x0D82\x0D9A\x0DCF)";
                        }
                        else 
#endif
                        { 
                            this.sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME); 
                        }
 
                        // if it isn't found build one:
                        if (String.IsNullOrEmpty(this.sNativeDisplayName))
                        {
                            // These should primarily be "Deutsch (Deutschland)" type names 
                            this.sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")";
                        } 
                    } 
                }
                return this.sNativeDisplayName; 
            }
        }

        // The culture name to be used in CultureInfo.CreateSpecificCulture() 
        internal String SSPECIFICCULTURE
        { 
            get 
            {
                // This got populated when ComNlsInfo::nativeInitCultureData told us we had a culture 
                Contract.Assert(this.sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already");
                return this.sSpecificCulture;
            }
        } 

        ///////////// 
        // Language // 
        /////////////
 
        // iso 639 language name, ie: en
        internal String SISO639LANGNAME
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sISO639Language == null) 
                {
                    this.sISO639Language = DoGetLocaleInfo(LOCALE_SISO639LANGNAME); 
                }
                return this.sISO639Language;
            }
        } 

#if !FEATURE_CORECLR 
        // iso 639 language name, ie: eng 
        internal String SISO639LANGNAME2
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sISO639Language2 == null) 
                {
                    this.sISO639Language2 = DoGetLocaleInfo(LOCALE_SISO639LANGNAME2); 
                } 
                return this.sISO639Language2;
            } 
        }

        // abbreviated windows language name (ie: enu) (non-standard, avoid this)
        internal String SABBREVLANGNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sAbbrevLang == null) 
                {
                    this.sAbbrevLang = DoGetLocaleInfo(LOCALE_SABBREVLANGNAME);
                }
                return this.sAbbrevLang; 
            }
        } 
#endif 

        // Localized name for this language (Windows Only) ie: Inglis 
        // This is only valid for Windows 8 and higher neutrals:
        internal String SLOCALIZEDLANGUAGE
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sLocalizedLanguage == null) 
                {
                    if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) 
                    {
                        this.sLocalizedLanguage = DoGetLocaleInfo(LOCALE_SLOCALIZEDLANGUAGENAME);
                    }
                    // Some OS's might not have this resource or LCTYPE 
                    if (String.IsNullOrEmpty(this.sLocalizedLanguage))
                    { 
                        this.sLocalizedLanguage = SNATIVELANGUAGE; 
                    }
                } 

                return this.sLocalizedLanguage;
            }
        } 

        // English name for this language (Windows Only) ie: German 
        internal String SENGLISHLANGUAGE 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sEnglishLanguage == null)
                { 
                    this.sEnglishLanguage = DoGetLocaleInfo(LOCALE_SENGLISHLANGUAGENAME);
                } 
                return this.sEnglishLanguage; 
            }
        } 

        // Native name of this language (Windows Only) ie: Deutsch
        internal String SNATIVELANGUAGE
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            { 
                if (this.sNativeLanguage == null)
                { 
#if !FEATURE_CORECLR
                    if (IsIncorrectNativeLanguageForSinhala())
                    {
                        // work around bug in Windows 7 for native language of Sinhala 
                        this.sNativeLanguage = "\x0dc3\x0dd2\x0d82\x0dc4\x0dbd";
                    } 
                    else 
#endif
                    { 
                        this.sNativeLanguage = DoGetLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
                    }
                }
                return this.sNativeLanguage; 
            }
        } 
 
#if !FEATURE_CORECLR
        private bool IsIncorrectNativeLanguageForSinhala() 
        {
            return IsOsWin7OrPrior()
                && (sName == "si-LK" || sName == "si")
                && !IsReplacementCulture; 
        }
#endif 
 
        ///////////
        // Region // 
        ///////////

        // region name (eg US)
        internal String SREGIONNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sRegionName == null) 
                {
                    this.sRegionName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME);
                }
                return this.sRegionName; 
            }
        } 
 
        // (user can override) ---- code (RegionInfo)
#if !FEATURE_CORECLR 
        internal int ICOUNTRY
        {
            get
            { 
                return DoGetLocaleInfoInt(LOCALE_ICOUNTRY);
            } 
        } 
#endif
 
        // GeoId
        internal int IGEOID
        {
            get 
            {
                if (this.iGeoId == undef) 
                { 
                    this.iGeoId = DoGetLocaleInfoInt(LOCALE_IGEOID);
                } 
                return this.iGeoId;
            }
        }
 
        // localized name for the ----
        internal string SLOCALIZED---- 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sLocalized---- == null)
                {
#if !FEATURE_CORECLR 
                    if (this.IsUserCustomCulture && !CultureData.IsReplacementCultureName(this.SNAME))
                    { 
                        this.sLocalized---- = SNATIVECOUNTRY; 
                    }
                    else 
                    {
                        String resourceKey = "Globalization.ri_" + this.SREGIONNAME;
                        if (IsResourcePresent(resourceKey))
                        { 
                            this.sLocalized---- = Environment.GetResourceString(resourceKey);
                        } 
                    } 
#endif
                    // If it hasn't been found (Windows 8 and up), fallback to the system 
                    if (String.IsNullOrEmpty(this.sLocalized----))
                    {
                        // We have to make the neutral distinction in case the OS returns a specific name
                        if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) 
                        {
                            this.sLocalized---- = DoGetLocaleInfo(LOCALE_SLOCALIZEDCOUNTRYNAME); 
                        } 
                        if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
                        { 
                            this.sLocalized---- = SNATIVECOUNTRY;
                        }
                    }
                } 
                return this.sLocalized----;
            } 
        } 

        // english ---- name (RegionInfo) ie: Germany 
        internal String SENGCOUNTRY
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sEnglishCountry == null) 
                { 
                    this.sEnglishCountry = DoGetLocaleInfo(LOCALE_SENGLISHCOUNTRYNAME);
                } 
                return this.sEnglishCountry;
            }
        }
 
        // native ---- name (RegionInfo) ie: Deutschland
        internal String SNATIVECOUNTRY 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sNativeCountry == null)
                {
                    this.sNativeCountry = DoGetLocaleInfo(LOCALE_SNATIVECOUNTRYNAME); 
                }
                return this.sNativeCountry; 
            } 
        }
 
        // ISO 3166 ---- Name
        internal String SISO3166CTRYNAME
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sISO3166CountryName == null) 
                {
                    this.sISO3166CountryName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME); 
                }
                return this.sISO3166CountryName;
            }
        } 

#if !FEATURE_CORECLR 
        // ISO 3166 ---- Name 
        internal String SISO3166CTRYNAME2
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sISO3166CountryName2 == null) 
                {
                    this.sISO3166CountryName2 = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME2); 
                } 
                return this.sISO3166CountryName2;
            } 
        }

        // abbreviated ---- Name (windows version, non-standard, avoid)
        internal String SABBREVCTRYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sAbbrevCountry == null) 
                {
                    this.sAbbrevCountry = DoGetLocaleInfo(LOCALE_SABBREVCTRYNAME);
                }
                return this.sAbbrevCountry; 
            }
        } 
 
#if !FEATURE_CORECLR
        // Default ---- 
        private int IDEFAULT----
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                return DoGetLocaleInfoInt(LOCALE_IDEFAULT----); 
            } 
        }
#endif 

        // Console fallback name (ie: locale to use for console apps for unicode-only locales)
        internal int IINPUTLANGUAGEHANDLE
        { 
            get
            { 
                if (this.iInputLanguageHandle == undef) 
                {
                    if (IsUserCustomCulture) 
                    {
                        //
                        this.iInputLanguageHandle = 0x0409;
                    } 
                    else
                    { 
                        // Input Language is same as LCID for built-in cultures 
                        this.iInputLanguageHandle = this.ILANGUAGE;
                    } 
                }
                return this.iInputLanguageHandle;
            }
        } 

        // Console fallback name (ie: locale to use for console apps for unicode-only locales) 
        internal String SCONSOLEFALLBACKNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sConsoleFallbackName == null)
                { 
                    string consoleFallbackName = DoGetLocaleInfo(LOCALE_SCONSOLEFALLBACKNAME);
                    if (consoleFallbackName == "es-ES_tradnl") 
                    { 
                        consoleFallbackName = "es-ES";
                    } 
                    this.sConsoleFallbackName = consoleFallbackName;
                }
                return this.sConsoleFallbackName;
            } 
        }
#endif 
 
        /////////////
        // Numbers // 
        ////////////

        //                internal String sPositiveSign            ; // (user can override) positive sign
        //                internal String sNegativeSign            ; // (user can override) negative sign 
        //                internal String[] saNativeDigits         ; // (user can override) native characters for digits 0-9
        //                internal int iDigitSubstitution       ; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only) 
        //                internal int iDigits                  ; // (user can override) number of fractional digits 
        //                internal int iNegativeNumber          ; // (user can override) negative number format
 
#if !FEATURE_CORECLR
        // Leading zeroes
        private bool ILEADINGZEROS
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            { 
                return (DoGetLocaleInfoInt(LOCALE_ILZERO) == 1);
            } 
        }
#endif

 
        // (user can override) grouping of digits
        internal int[] WAGROUPING 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.waGrouping == null || UseUserOverride)
                {
                    this.waGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SGROUPING)); 
                }
                return this.waGrouping; 
            } 
        }
 

        //                internal String sDecimalSeparator        ; // (user can override) decimal separator
        //                internal String sThousandSeparator       ; // (user can override) thousands separator
 
        // Not a Number
        internal String SNAN 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sNaN == null || UseUserOverride)
                {
                    this.sNaN = DoGetLocaleInfo(LOCALE_SNAN); 
                }
                return this.sNaN; 
            } 
        }
 
        // + Infinity
        internal String SPOSINFINITY
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sPositiveInfinity == null || UseUserOverride) 
                {
                    this.sPositiveInfinity = DoGetLocaleInfo(LOCALE_SPOSINFINITY); 
                }
                return this.sPositiveInfinity;
            }
        } 

        // - Infinity 
        internal String SNEGINFINITY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sNegativeInfinity == null || UseUserOverride)
                { 
                    this.sNegativeInfinity = DoGetLocaleInfo(LOCALE_SNEGINFINITY);
                } 
                return this.sNegativeInfinity; 
            }
        } 


        ////////////
        // Percent // 
        ///////////
 
        // Negative Percent (0-3) 
        internal int INEGATIVEPERCENT
        { 
            get
            {
                if (this.iNegativePercent == undef || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code
                    this.iNegativePercent = DoGetLocaleInfoInt(LOCALE_INEGATIVEPERCENT); 
                } 
                return this.iNegativePercent;
            } 
        }

        // Positive Percent (0-11)
        internal int IPOSITIVEPERCENT 
        {
            get 
            { 
                if (this.iPositivePercent == undef || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code
                    this.iPositivePercent = DoGetLocaleInfoInt(LOCALE_IPOSITIVEPERCENT);
                }
                return this.iPositivePercent; 
            }
        } 
 
        // Percent (%) symbol
        internal String SPERCENT 
        {
            [System.Security.SecurityCritical]  // auto-generated
            get
            { 
                if (this.sPercent == null || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code 
                    this.sPercent = DoGetLocaleInfo(LOCALE_SPERCENT);
                } 
                return this.sPercent;
            }
        }
 
        // PerMille (‰) symbol
        internal String ----ILLE 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sPerMille == null || UseUserOverride)
                {
                    // Note that <= Windows Vista this is synthesized by native code 
                    this.sPerMille = DoGetLocaleInfo(LOCALE_----ILLE);
                } 
                return this.sPerMille; 
            }
        } 

        /////////////
        // Currency //
        ///////////// 

        // (user can override) local monetary symbol, eg: $ 
        internal String SCURRENCY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sCurrency == null || UseUserOverride)
                { 
                    this.sCurrency = DoGetLocaleInfo(LOCALE_SCURRENCY);
                } 
                return this.sCurrency; 
            }
        } 

        // international monetary symbol (RegionInfo), eg: USD
        internal String SINTLSYMBOL
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            { 
                if (this.sIntlMonetarySymbol == null || UseUserOverride)
                { 
                    this.sIntlMonetarySymbol = DoGetLocaleInfo(LOCALE_SINTLSYMBOL);
                }
                return this.sIntlMonetarySymbol;
            } 
        }
 
        // English name for this currency (RegionInfo), eg: US Dollar 
        internal String SENGLISHCURRENCY
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sEnglishCurrency == null) 
                {
                    this.sEnglishCurrency = DoGetLocaleInfo(LOCALE_SENGCURRNAME); 
                } 
                return this.sEnglishCurrency;
            } 
        }

        // Native name for this currency (RegionInfo), eg: Schweiz Frank
        internal String SNATIVECURRENCY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sNativeCurrency == null) 
                {
                    this.sNativeCurrency = DoGetLocaleInfo(LOCALE_SNATIVECURRNAME);
                }
                return this.sNativeCurrency; 
            }
        } 
 
        //                internal int iCurrencyDigits          ; // (user can override) # local monetary fractional digits
        //                internal int iCurrency                ; // (user can override) positive currency format 
        //                internal int iNegativeCurrency        ; // (user can override) negative currency format

        // (user can override) monetary grouping of digits
        internal int[] WAMONGROUPING 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.waMonetaryGrouping == null || UseUserOverride) 
                {
                    this.waMonetaryGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SMONGROUPING));
                }
                return this.waMonetaryGrouping; 
            }
        } 
 
        //                internal String sMonetaryDecimal         ; // (user can override) monetary decimal separator
        //                internal String sMonetaryThousand        ; // (user can override) monetary thousands separator 

        /////////
        // Misc //
        ///////// 

        // (user can override) system of measurement 0=metric, 1=US (RegionInfo) 
        internal int IMEASURE 
        {
            get 
            {
                if (this.iMeasure == undef || UseUserOverride)
                {
                    this.iMeasure = DoGetLocaleInfoInt(LOCALE_IMEASURE); 
                }
                return this.iMeasure; 
            } 
        }
 
        // (user can override) list Separator
        internal String SLIST
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sListSeparator == null || UseUserOverride) 
                {
                    this.sListSeparator = DoGetLocaleInfo(LOCALE_SLIST); 
                }
                return this.sListSeparator;
            }
        } 

#if !FEATURE_CORECLR 
        // Paper size 
        private int IPAPERSIZE
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            {
                return DoGetLocaleInfoInt(LOCALE_IPAPERSIZE); 
            }
        } 
#endif 

        //////////////////////////// 
        // Calendar/Time (Gregorian) //
        ////////////////////////////

        // (user can override) AM designator 
        internal String SAM1159
        { 
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sAM1159 == null || UseUserOverride)
                {
                    this.sAM1159 = DoGetLocaleInfo(LOCALE_S1159);
                } 
                return this.sAM1159;
            } 
        } 

        // (user can override) PM designator 
        internal String SPM2359
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sPM2359 == null || UseUserOverride) 
                { 
                    this.sPM2359 = DoGetLocaleInfo(LOCALE_S2359);
                } 
                return this.sPM2359;
            }
        }
 
        // (user can override) time format
        internal String[] LongTimes 
        { 
            get
            { 
                if (this.saLongTimes == null || UseUserOverride)
                {
                    String[] longTimes = DoEnumTimeFormats();
                    if (longTimes == null || longTimes.Length == 0) 
                    {
                        this.saLongTimes = Invariant.saLongTimes; 
                    } 
                    else
                    { 
                        this.saLongTimes = longTimes;
                    }
                }
                return this.saLongTimes; 
            }
        } 
 
        // short time format
        // Short times (derived from long times format) 
        //
        internal String[] ShortTimes
        {
            get 
            {
                if (this.saShortTimes == null || UseUserOverride) 
                { 
                    // Try to get the short times from the OS/culture.dll
                    String[] shortTimes = null; 
#if !__APPLE__
                    shortTimes = DoEnumShortTimeFormats();
#endif // !__APPLE__
 
                    if (shortTimes == null || shortTimes.Length == 0)
                    { 
                        // 
                        // If we couldn't find short times, then compute them from long times
                        // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll) 
                        //
                        shortTimes = DeriveShortTimesFromLong();
                    }
 
                    /* The above logic doesn't make sense on Mac, since the OS can provide us a "short time pattern".
                     * currently this is the 4th element in the array returned by LongTimes.  We'll add this to our array 
                     * if it doesn't exist. 
                     */
                    shortTimes = AdjustShortTimesForMac(shortTimes); 

                    // Found short times, use them
                    this.saShortTimes = shortTimes;
                } 
                return this.saShortTimes;
            } 
        } 

        private string[] AdjustShortTimesForMac(string[] shortTimes) 
        {
#if __APPLE__
            /*
             * NOTE: This code depends on the data from the OS being returned in a *specific* order.  The 
             * short time pattern must be the 4th element in the 4 element array returned by the data.  If
             * change the way the data is returned from the OS be sure to update this code. 
             */ 

            string[] longTimes = (string[])LongTimes.Clone(); 
            Contract.Assert(longTimes.Length == 4, "[System.Globalization.CultureData] LongTimes does not have exactly 4");

            if (longTimes.Length == 4) {
                string shortTimePattern = longTimes[3]; 
                int foundIndex = -1;
                for (int i = 0; i < shortTimes.Length; i++) { 
                    if (shortTimePattern.Equals(shortTimes[i])) { 
                        foundIndex = i;
                        break; 
                    }
                }

                if (foundIndex == -1) { 
                    // The OS short time didn't exist in the list we constructed, add it.
                    string[] t = new string[shortTimes.Length + 1]; 
                    t[0] = shortTimePattern; 
                    Array.Copy(shortTimes, 0, t, 1, shortTimes.Length);
                    shortTimes = t; 
                } else {
                    // The OS short time did exist, move it to the front.
                    string t = shortTimes[0];
                    shortTimes[0] = shortTimes[foundIndex]; 
                    shortTimes[foundIndex] = t;
                } 
            } 
#endif // __APPLE__
            return shortTimes; 
        }

        private string[] DeriveShortTimesFromLong()
        { 
            // Our logic is to look for h,H,m,s,t.  If we find an s, then we check the string
            // between it and the previous marker, if any.  If its a short, unescaped separator, 
            // then we don't retain that part. 
            // We then check after the ss and remove anything before the next h,H,m,t...
            string[] shortTimes = new string[LongTimes.Length]; 

            for (int i = 0; i < LongTimes.Length; i++)
            {
                shortTimes[i] = StripSecondsFromPattern(LongTimes[i]); 
            }
            return shortTimes; 
        } 

        private static string StripSecondsFromPattern(string time) 
        {
            bool bEscape = false;
            int iLastToken = -1;
 
            // Find the seconds
            for (int j = 0; j < time.Length; j++) 
            { 
                // Change escape mode?
                if (time[j] == '\'') 
                {
                    // Continue
                    bEscape = !bEscape;
                    continue; 
                }
 
                // See if there was a single \ 
                if (time[j] == '\\')
                { 
                    // Skip next char
                    j++;
                    continue;
                } 

                if (bEscape) 
                { 
                    continue;
                } 

                switch (time[j])
                {
                    // Check for seconds 
                    case 's':
                        // Found seconds, see if there was something unescaped and short between 
                        // the last marker and the seconds.  Windows says separator can be a 
                        // maximum of three characters (without null)
                        // If 1st or last characters were ', then ignore it 
                        if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 &&
                            (time[iLastToken + 1] != '\'') &&
                            (time[j - 1] != '\''))
                        { 
                            // There was something there we want to remember
                            if (iLastToken >= 0) 
                            { 
                                j = iLastToken + 1;
                            } 
                        }

                        bool containsSpace;
                        int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace); 
                        StringBuilder sb = new StringBuilder(time.Substring(0, j));
                        if (containsSpace) 
                        { 
                            sb.Append(' ');
                        } 
                        sb.Append(time.Substring(endIndex));
                        time = sb.ToString();
                        break;
                    case 'm': 
                    case 'H':
                    case 'h': 
                        iLastToken = j; 
                        break;
                } 
            }
            return time;
        }
 
        private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace)
        { 
            bool bEscape = false; 
            containsSpace = false;
            for (; index < time.Length; index++) 
            {
                switch (time[index])
                {
                    case '\'': 
                        bEscape = !bEscape;
                        continue; 
                    case '\\': 
                        index++;
                        if (time[index] == ' ') 
                        {
                            containsSpace = true;
                        }
                        continue; 
                    case ' ':
                        containsSpace = true; 
                        break; 
                    case 't':
                    case 'm': 
                    case 'H':
                    case 'h':
                        if (bEscape)
                        { 
                            continue;
                        } 
                        return index; 
                }
            } 
            containsSpace = false;
            return index;
        }
 
        // time duration format
        internal String[] SADURATION 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                //
                if (this.saDurationFormats == null || UseUserOverride)
                { 
                    String durationFormat = DoGetLocaleInfo(LOCALE_SDURATION);
                    this.saDurationFormats = new String[] { ReescapeWin32String(durationFormat) }; 
                } 
                return this.saDurationFormats;
            } 
        }

        // (user can override) first day of week
        internal int IFIRSTDAYOFWEEK 
        {
            get 
            { 
                if (this.iFirstDayOfWeek == undef || UseUserOverride)
                { 
                    // Have to convert it from windows to .Net formats
                    this.iFirstDayOfWeek = ConvertFirstDayOfWeekMonToSun(DoGetLocaleInfoInt(LOCALE_IFIRSTDAYOFWEEK));
                }
                return this.iFirstDayOfWeek; 
            }
        } 
 
        // (user can override) first week of year
        internal int IFIRSTWEEKOFYEAR 
        {
            get
            {
                if (this.iFirstWeekOfYear == undef || UseUserOverride) 
                {
                    this.iFirstWeekOfYear = DoGetLocaleInfoInt(LOCALE_IFIRSTWEEKOFYEAR); 
                } 
                return this.iFirstWeekOfYear;
            } 
        }

        // (user can override default only) short date format
        internal String[] ShortDates(int calendarId) 
        {
            return GetCalendar(calendarId).saShortDates; 
        } 

        // (user can override default only) long date format 
        internal String[] LongDates(int calendarId)
        {
            return GetCalendar(calendarId).saLongDates;
        } 

        // (user can override) date year/month format. 
        internal String[] YearMonths(int calendarId) 
        {
            return GetCalendar(calendarId).saYearMonths; 
        }

        // day names
        internal string[] DayNames(int calendarId) 
        {
            return GetCalendar(calendarId).saDayNames; 
        } 

        // abbreviated day names 
        internal string[] AbbreviatedDayNames(int calendarId)
        {
            // Get abbreviated day names for this calendar from the OS if necessary
            return GetCalendar(calendarId).saAbbrevDayNames; 
        }
 
        // The super short day names 
        internal string[] SuperShortDayNames(int calendarId)
        { 
            return GetCalendar(calendarId).saSuperShortDayNames;
        }

        // month names 
        internal string[] MonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saMonthNames; 
        }
 
        // Genitive month names
        internal string[] GenitiveMonthNames(int calendarId)
        {
            return GetCalendar(calendarId).saMonthGenitiveNames; 
        }
 
        // month names 
        internal string[] AbbreviatedMonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saAbbrevMonthNames;
        }

        // Genitive month names 
        internal string[] AbbreviatedGenitiveMonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saAbbrevMonthGenitiveNames; 
        }
 
        // Leap year month names
        // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name
        // the non-leap names skip the 7th name in the normal month name array
        internal string[] LeapYearMonthNames(int calendarId) 
        {
            return GetCalendar(calendarId).saLeapYearMonthNames; 
        } 

        // month/day format (single string, no override) 
        internal String MonthDay(int calendarId)
        {
            return GetCalendar(calendarId).sMonthDay;
        } 

 
 
        /////////////
        // Calendars // 
        /////////////

        // all available calendar type(s), The first one is the default calendar.
        internal int[] CalendarIds 
        {
            get 
            { 
                if (this.waCalendars == null)
                { 
                    // We pass in an array of ints, and native side fills it up with count calendars.
                    // We then have to copy that list to a new array of the right size.
                    // Default calendar should be first
                    // 
                    int[] calendarInts = new int[23];
                    Contract.Assert(this.sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                    int count = CalendarData.nativeGetCalendars(this.sWindowsName, this.bUseOverrides, calendarInts); 

                    // See if we had a calendar to add. 
                    if (count == 0)
                    {
                        // Failed for some reason, just grab Gregorian from Invariant
                        this.waCalendars = Invariant.waCalendars; 
                    }
                    else 
                    { 
                        // The OS may not return calendar 4 for zh-TW, but we've always allowed it.
                        // 
                        if (this.sWindowsName == "zh-TW")
                        {
                            bool found = false;
 
                            // Do we need to insert calendar 4?
                            for (int i = 0; i < count; i++) 
                            { 
                                // Stop if we found calendar four
                                if (calendarInts[i] == Calendar.CAL_TAIWAN) 
                                {
                                    found = true;
                                    break;
                                } 
                            }
 
                            // If not found then insert it 
                            if (!found)
                            { 
                                // Insert it as the 2nd calendar
                                count++;
                                // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added.
                                Array.Copy(calendarInts, 1, calendarInts, 2, 23 - 1 - 1); 
                                calendarInts[1] = Calendar.CAL_TAIWAN;
                            } 
                        } 

                        // It worked, remember the list 
                        int[] temp = new int[count];
                        Array.Copy(calendarInts, temp, count);

                        // Want 1st calendar to be default 
                        // Prior to Vista the enumeration didn't have default calendar first
                        // Only a coreclr concern, culture.dll does the right thing. 
#if FEATURE_CORECLR 
                        if (temp.Length > 1)
                        { 
                            int i = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
                            if (temp[1] == i)
                            {
                                temp[1] = temp[0]; 
                                temp[0] = i;
                            } 
                        } 
#endif
 
                        this.waCalendars = temp;
                    }
                }
 
                return this.waCalendars;
            } 
        } 

        // Native calendar names.  index of optional calendar - 1, empty if no optional calendar at that number 
        internal String CalendarName(int calendarId)
        {
            // Get the calendar
            return GetCalendar(calendarId).sNativeName; 
        }
 
        internal CalendarData GetCalendar(int calendarId) 
        {
            Contract.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS, 
                "[CultureData.GetCalendar] Expect calendarId to be in a valid range");

            // arrays are 0 based, calendarIds are 1 based
            int calendarIndex = calendarId - 1; 

            // Have to have calendars 
            if (calendars == null) 
            {
                calendars = new CalendarData[CalendarData.MAX_CALENDARS]; 
            }

            // we need the following local variable to avoid returning null
            // when another thread creates a new array of CalendarData (above) 
            // right after we insert the newly created CalendarData (below)
            CalendarData calendarData = calendars[calendarIndex]; 
            // Make sure that calendar has data 
            if (calendarData == null || UseUserOverride)
            { 
                Contract.Assert(this.sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
                calendarData = new CalendarData(this.sWindowsName, calendarId, this.UseUserOverride);
#if !FEATURE_CORECLR
                //Work around issue where Win7 data for MonthDay contains invalid two sets of data separated by semicolon 
                //even though MonthDay is not enumerated
                if (IsOsWin7OrPrior() && !IsUserCustomCulture && !IsReplacementCulture) 
                { 
                    calendarData.FixupWin7MonthDaySemicolonBug();
                } 
#endif
                calendars[calendarIndex] = calendarData;
            }
 
            return calendarData;
        } 
 
        internal int CurrentEra(int calendarId)
        { 
            return GetCalendar(calendarId).iCurrentEra;
        }

        /////////////////// 
        // Text Information //
        /////////////////// 
 
        // IsRightToLeft
#if !FEATURE_CORECLR 
        internal bool IsRightToLeft
        {
            get
            { 
                // Returns one of the following 4 reading layout values:
                // 0 - Left to right (eg en-US) 
                // 1 - Right to left (eg arabic locales) 
                // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
                // 3 - Vertical top to bottom with columns proceeding to the right 
                return (this.IREADINGLAYOUT == 1);
            }
        }
 
        // IREADINGLAYOUT
        // Returns one of the following 4 reading layout values: 
        // 0 - Left to right (eg en-US) 
        // 1 - Right to left (eg arabic locales)
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) 
        // 3 - Vertical top to bottom with columns proceeding to the right
        //
        // If exposed as a public API, we'd have an enum with those 4 values
        private int IREADINGLAYOUT 
        {
            get 
            { 
                if (this.iReadingLayout == undef || UseUserOverride)
                { 
                    Contract.Assert(this.sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
                    this.iReadingLayout = DoGetLocaleInfoInt(LOCALE_IREADINGLAYOUT);
                }
 
                return (this.iReadingLayout);
            } 
        } 
#endif // !FEATURE_CORECLR
 
        // The TextInfo name never includes that alternate sort and is always specific
        // For customs, it uses the SortLocale (since the textinfo is not exposed in Win7)
        // en -> en-US
        // en-US -> en-US 
        // fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj)
        // fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ) 
        // es-ES_tradnl -> es-ES 
        internal String STEXTINFO               // Text info name to use for text information
        { 
            [System.Security.SecuritySafeCritical]
            get
            {
#if FEATURE_CORECLR 
                // Note: Custom cultures might point at another culture's textinfo, however windows knows how
                // to redirect it to the desired textinfo culture, so this is OK. 
                Contract.Assert(this.sWindowsName != null, "[CultureData.STEXTINFO] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                return (this.sWindowsName);
#else 
                if (this.sTextInfo == null)
                {
                    // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts.
                    // It is also not supported downlevel without culture.dll. 
                    if (IsNeutralCulture || IsUserCustomCulture)
                    { 
                        string sortLocale = DoGetLocaleInfo(LOCALE_SSORTLOCALE); 
                        this.sTextInfo = GetCultureData(sortLocale, bUseOverrides).SNAME;
                    } 

                    if (this.sTextInfo == null)
                    {
                        this.sTextInfo = this.SNAME; // removes alternate sort 
                    }
                } 
 
                return this.sTextInfo;
#endif 
            }
        }

        // Compare info name (including sorting key) to use if custom 
        internal String SCOMPAREINFO
        { 
            [System.Security.SecuritySafeCritical] 
            get
            { 
#if FEATURE_CORECLR
                // Note: Custom cultures might point at another culture's compareinfo, however windows knows how
                // to redirect it to the desired compareinfo culture, so this is OK.
                Contract.Assert(this.sWindowsName != null, "[CultureData.SCOMPAREINFO] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                return (this.sWindowsName);
#else 
                if (this.sCompareInfo == null) 
                {
                    // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts. 
                    // It is also not supported downlevel without culture.dll.
                    // We really only need it for the custom locale case though
                    // since for all other cases, it is the same as sWindowsName
                    if (IsUserCustomCulture) 
                    {
                        this.sCompareInfo = DoGetLocaleInfo(LOCALE_SSORTLOCALE); 
                    } 

                    if (this.sCompareInfo == null) 
                    {
                        this.sCompareInfo = this.sWindowsName;
                    }
                } 

                return this.sCompareInfo; 
#endif 
            }
        } 

        internal bool IsUserCustomCulture
        {
            get 
            {
#if FEATURE_CORECLR 
                return false; 
#else
                return IsCustomCultureId(this.ILANGUAGE); 
#endif
            }
        }
 
#if !FEATURE_CORECLR
        // Typical Scripts for this locale (latn;cyrl; etc) 
        // 

        private String SSCRIPTS 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            { 
                if (this.sScripts == null)
                { 
                    this.sScripts = DoGetLocaleInfo(LOCALE_SSCRIPTS); 
                }
                return this.sScripts; 
            }
        }

        private String SOPENTYPELANGUAGETAG 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                return DoGetLocaleInfo(LOCALE_SOPENTYPELANGUAGETAG); 
            }
        }

        private String FONTSIGNATURE 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                if (this.fontSignature == null) 
                {
                    this.fontSignature = DoGetLocaleInfo(LOCALE_FONTSIGNATURE);
                }
                return this.fontSignature; 
            }
        } 
 
        private String SKEYBOARDSTOINSTALL
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            {
                return DoGetLocaleInfo(LOCALE_SKEYBOARDSTOINSTALL); 
            }
        } 
 
#endif
 
#if !FEATURE_CORECLR
        internal int IDEFAULTANSICODEPAGE   // default ansi code page ID (ACP)
        {
            get 
            {
                if (this.iDefaultAnsiCodePage == undef) 
                { 
                    this.iDefaultAnsiCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTANSICODEPAGE);
                } 
                return this.iDefaultAnsiCodePage;
            }
        }
 
        internal int IDEFAULTOEMCODEPAGE   // default oem code page ID (OCP or OEM)
        { 
            get 
            {
                if (this.iDefaultOemCodePage == undef) 
                {
                    this.iDefaultOemCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTCODEPAGE);
                }
                return this.iDefaultOemCodePage; 
            }
        } 
 
        internal int IDEFAULTMACCODEPAGE   // default macintosh code page
        { 
            get
            {
                if (this.iDefaultMacCodePage == undef)
                { 
                    this.iDefaultMacCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTMACCODEPAGE);
                } 
                return this.iDefaultMacCodePage; 
            }
        } 

        internal int IDEFAULTEBCDICCODEPAGE   // default EBCDIC code page
        {
            get 
            {
                if (this.iDefaultEbcdicCodePage == undef) 
                { 
                    this.iDefaultEbcdicCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTEBCDICCODEPAGE);
                } 
                return this.iDefaultEbcdicCodePage;
            }
        }
 
        // Obtain locale name from LCID
        // NOTE: This will get neutral names, unlike the OS API 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int LocaleNameToLCID(String localeName);

        // These are desktop only, not coreclr
        // locale ID (0409), including sort information 
        internal int ILANGUAGE
        { 
            get 
            {
                if (this.iLanguage == 0) 
                {
                    Contract.Assert(this.sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
                    this.iLanguage = LocaleNameToLCID(this.sRealName);
                } 
                return this.iLanguage;
            } 
        } 

        internal bool IsWin32Installed 
        {
            get { return this.bWin32Installed; }
        }
 
        internal bool IsFramework
        { 
            get { return this.bFramework; } 
        }
#endif // !FEATURE_CORECLR 

        ////////////////////
        // Derived properties //
        //////////////////// 

        internal bool IsNeutralCulture 
        { 
            get
            { 
                // NlsInfo::nativeInitCultureData told us if we're neutral or not
                return this.bNeutral;
            }
        } 

        internal bool IsInvariantCulture 
        { 
            get
            { 
                return String.IsNullOrEmpty(this.SNAME);
            }
        }
 
        // Get an instance of our default calendar
        internal Calendar DefaultCalendar 
        { 
            get
            { 
                int defaultCalId = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
                if (defaultCalId == 0)
                {
                    defaultCalId = this.CalendarIds[0]; 
                }
 
                return CultureInfo.GetCalendarInstance(defaultCalId); 
            }
        } 

        // All of our era names
        internal String[] EraNames(int calendarId)
        { 
            Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0");
 
            return this.GetCalendar(calendarId).saEraNames; 
        }
 
        internal String[] AbbrevEraNames(int calendarId)
        {
            Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
 
            return this.GetCalendar(calendarId).saAbbrevEraNames;
        } 
 
        internal String[] AbbreviatedEnglishEraNames(int calendarId)
        { 
            Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");

            return this.GetCalendar(calendarId).saAbbrevEnglishEraNames;
        } 

        // String array DEFAULTS 
        // Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to. 

 
        // Time separator (derived from time format)
        internal String TimeSeparator
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get
            { 
                string longTimeFormat = ReescapeWin32String(DoGetLocaleInfo(LOCALE_STIMEFORMAT)); 
                if (String.IsNullOrEmpty(longTimeFormat))
                { 
                    longTimeFormat = LongTimes[0];
                }

                // Compute STIME from time format 
                return GetTimeSeparator(longTimeFormat);
            } 
        } 

        // Date separator (derived from short date format) 
        internal String DateSeparator(int calendarId)
        {
            return GetDateSeparator(ShortDates(calendarId)[0]);
        } 

        ////////////////////////////////////// 
        // Helper Functions to get derived properties // 
        //////////////////////////////////////
 
        ////////////////////////////////////////////////////////////////////////////
        //
        // Unescape a NLS style quote string
        // 
        // This removes single quotes:
        //      'fred' -> fred 
        //      'fred -> fred 
        //      fred' -> fred
        //      fred's -> freds 
        //
        // This removes the first \ of escaped characters:
        //      fred\'s -> fred's
        //      a\\b -> a\b 
        //      a\b -> ab
        // 
        // We don't build the stringbuilder unless we find a ' or a \.  If we find a ' or a \, we 
        // always build a stringbuilder because we need to remove the ' or \.
        // 
        ////////////////////////////////////////////////////////////////////////////
        static private String UnescapeNlsString(String str, int start, int end)
        {
            StringBuilder result = null; 

            for (int i = start; i < str.Length && i <= end; i++) 
            { 
                switch (str[i])
                { 
                    case '\'':
                        if (result == null)
                        {
                            result = new StringBuilder(str, start, i - start, str.Length); 
                        }
                        break; 
                    case '\\': 
                        if (result == null)
                        { 
                            result = new StringBuilder(str, start, i - start, str.Length);
                        }
                        ++i;
                        if (i < str.Length) 
                        {
                            result.Append(str[i]); 
                        } 
                        break;
                    default: 
                        if (result != null)
                        {
                            result.Append(str[i]);
                        } 
                        break;
                } 
            } 

            if (result == null) 
                return (str.Substring(start, end - start + 1));

            return (result.ToString());
        } 

        //////////////////////////////////////////////////////////////////////////// 
        // 
        // Reescape a Win32 style quote string as a NLS+ style quoted string
        // 
        // This is also the escaping style used by custom culture data files
        //
        // NLS+ uses \ to escape the next character, whether in a quoted string or
        // not, so we always have to change \ to \\. 
        //
        // NLS+ uses \' to escape a quote inside a quoted string so we have to change 
        // '' to \' (if inside a quoted string) 
        //
        // We don't build the stringbuilder unless we find something to change 
        ////////////////////////////////////////////////////////////////////////////
        static internal String ReescapeWin32String(String str)
        {
            // If we don't have data, then don't try anything 
            if (str == null)
                return null; 
 
            StringBuilder result = null;
 
            bool inQuote = false;
            for (int i = 0; i < str.Length; i++)
            {
                // Look for quote 
                if (str[i] == '\'')
                { 
                    // Already in quote? 
                    if (inQuote)
                    { 
                        // See another single quote.  Is this '' of 'fred''s' or '''', or is it an ending quote?
                        if (i + 1 < str.Length && str[i + 1] == '\'')
                        {
                            // Found another ', so we have ''.  Need to add \' instead. 
                            // 1st make sure we have our stringbuilder
                            if (result == null) 
                                result = new StringBuilder(str, 0, i, str.Length * 2); 

                            // Append a \' and keep going (so we don't turn off quote mode) 
                            result.Append("\\'");
                            i++;
                            continue;
                        } 

                        // Turning off quote mode, fall through to add it 
                        inQuote = false; 
                    }
                    else 
                    {
                        // Found beginning quote, fall through to add it
                        inQuote = true;
                    } 
                }
                // Is there a single \ character? 
                else if (str[i] == '\\') 
                {
                    // Found a \, need to change it to \\ 
                    // 1st make sure we have our stringbuilder
                    if (result == null)
                        result = new StringBuilder(str, 0, i, str.Length * 2);
 
                    // Append our \\ to the string & continue
                    result.Append("\\\\"); 
                    continue; 
                }
 
                // If we have a builder we need to add our character
                if (result != null)
                    result.Append(str[i]);
            } 

            // Unchanged string? , just return input string 
            if (result == null) 
                return str;
 
            // String changed, need to use the builder
            return result.ToString();
        }
 
        static internal String[] ReescapeWin32Strings(String[] array)
        { 
            if (array != null) 
            {
                for (int i = 0; i < array.Length; i++) 
                {
                    array[i] = ReescapeWin32String(array[i]);
                }
            } 

            return array; 
        } 

        // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() 
        // and breaking changes here will not show up at build time, only at run time.
        static private String GetTimeSeparator(String format)
        {
            // Time format separator (ie: : in 12:39:00) 
            //
            // We calculate this from the provided time format 
            // 

            // 
            //  Find the time separator so that we can pretend we know STIME.
            //
            return GetSeparator(format, "Hhms");
        } 

        // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() 
        // and breaking changes here will not show up at build time, only at run time. 
        static private String GetDateSeparator(String format)
        { 
            // Date format separator (ie: / in 9/1/03)
            //
            // We calculate this from the provided short date
            // 

            // 
            //  Find the date separator so that we can pretend we know SDATE. 
            //
            return GetSeparator(format, "dyM"); 
        }

        private static string GetSeparator(string format, string timeParts)
        { 
            int index = IndexOfTimePart(format, 0, timeParts);
 
            if (index != -1) 
            {
                // Found a time part, find out when it changes 
                char cTimePart = format[index];

                do
                { 
                    index++;
                } while (index < format.Length && format[index] == cTimePart); 
 
                int separatorStart = index;
 
                // Now we need to find the end of the separator
                if (separatorStart < format.Length)
                {
                    int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts); 
                    if (separatorEnd != -1)
                    { 
                        // From [separatorStart, count) is our string, except we need to unescape 
                        return UnescapeNlsString(format, separatorStart, separatorEnd - 1);
                    } 
                }
            }

            return String.Empty; 
        }
 
        private static int IndexOfTimePart(string format, int startIndex, string timeParts) 
        {
            Contract.Assert(startIndex >= 0, "startIndex cannot be negative"); 
            Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters");
            bool inQuote = false;
            for (int i = startIndex; i < format.Length; ++i)
            { 
                // See if we have a time Part
                if (!inQuote && timeParts.IndexOf(format[i]) != -1) 
                { 
                    return i;
                } 
                switch (format[i])
                {
                    case '\\':
                        if (i + 1 < format.Length) 
                        {
                            ++i; 
                            switch (format[i]) 
                            {
                                case '\'': 
                                case '\\':
                                    break;
                                default:
                                    --i; //backup since we will move over this next 
                                    break;
                            } 
                        } 
                        break;
                    case '\'': 
                        inQuote = !inQuote;
                        break;
                }
            } 

            return -1; 
        } 

        [System.Security.SecurityCritical] 
        string DoGetLocaleInfo(uint lctype)
        {
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
            return DoGetLocaleInfo(this.sWindowsName, lctype); 
        }
 
        // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the 
        // "windows" name, which can be specific for downlevel (< windows 7) os's.
        [System.Security.SecurityCritical]  // auto-generated 
        string DoGetLocaleInfo(string localeName, uint lctype)
        {
            // Fix lctype if we don't want overrides
            if (!UseUserOverride) 
            {
                lctype |= LOCALE_NOUSEROVERRIDE; 
            } 

            // Ask OS for data 
            Contract.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null");
            string result = CultureInfo.nativeGetLocaleInfoEx(localeName, lctype);
            if (result == null)
            { 
                // Failed, just use empty string
                result = String.Empty; 
            } 

            return result; 
        }

        int DoGetLocaleInfoInt(uint lctype)
        { 
            // Fix lctype if we don't want overrides
            if (!UseUserOverride) 
            { 
                lctype |= LOCALE_NOUSEROVERRIDE;
            } 

            // Ask OS for data, note that we presume it returns success, so we have to know that
            // sWindowsName is valid before calling.
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            int result = CultureInfo.nativeGetLocaleInfoExInt(this.sWindowsName, lctype);
 
            return result; 
        }
 
        String[] DoEnumTimeFormats()
        {
            // Note that this gets overrides for us all the time
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, 0, UseUserOverride));
 
            return result; 
        }
 
        String[] DoEnumShortTimeFormats()
        {
            // Note that this gets overrides for us all the time
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, TIME_NOSECONDS, UseUserOverride));
 
            return result; 
        }
 
        /////////////////
        // Static Helpers //
        ////////////////
        internal static bool IsCustomCultureId(int cultureId) 
        {
            if (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED) 
                return true; 

            return false; 
        }

        ////////////////////////////////////////////////////////////////////////////
        // 
        // Parameters:
        //      calendarValueOnly   Retrieve the values which are affected by the calendar change of DTFI. 
        //                          This will cause values like longTimePattern not be retrieved since it is 
        //                          not affected by the Calendar property in DTFI.
        // 
        ////////////////////////////////////////////////////////////////////////////
        [System.Security.SecurityCritical]  // auto-generated
        internal void GetNFIValues(NumberFormatInfo nfi)
        { 
            if (this.IsInvariantCulture)
            { 
                nfi.positiveSign = this.sPositiveSign; 
                nfi.negativeSign = this.sNegativeSign;
 
#if !FEATURE_CORECLR
                nfi.nativeDigits = this.saNativeDigits;
                nfi.digitSubstitution = this.iDigitSubstitution;
#endif // !FEATURE_CORECLR 

                nfi.numberGroupSeparator = this.sThousandSeparator; 
                nfi.numberDecimalSeparator = this.sDecimalSeparator; 
                nfi.numberDecimalDigits = this.iDigits;
                nfi.numberNegativePattern = this.iNegativeNumber; 

                nfi.currencySymbol = this.sCurrency;
                nfi.currencyGroupSeparator = this.sMonetaryThousand;
                nfi.currencyDecimalSeparator = this.sMonetaryDecimal; 
                nfi.currencyDecimalDigits = this.iCurrencyDigits;
                nfi.currencyNegativePattern = this.iNegativeCurrency; 
                nfi.currencyPositivePattern = this.iCurrency; 

                nfi.percentNegativePattern = this.INEGATIVEPERCENT; 
                nfi.percentPositivePattern = this.IPOSITIVEPERCENT;
                nfi.percentSymbol = this.SPERCENT;
                nfi.perMilleSymbol = this.----ILLE;
 
                nfi.negativeInfinitySymbol = this.SNEGINFINITY;
                nfi.positiveInfinitySymbol = this.SPOSINFINITY; 
                nfi.nanSymbol = this.SNAN; 

            } 
            else
            {
                //
                // We don't have information for the following four.  All cultures use 
                // the same value of the number formatting values.
                // 
                // PercentDecimalDigits 
                // PercentDecimalSeparator
                // PercentGroupSize 
                // PercentGroupSeparator
                //

                // 
                // Ask native side for our data.
                // 
                Contract.Assert(this.sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                CultureData.nativeGetNumberFormatInfoValues(this.sWindowsName, nfi, UseUserOverride);
            } 


            //
            // Gather additional data 
            //
            nfi.numberGroupSizes = this.WAGROUPING; 
            nfi.currencyGroupSizes = this.WAMONGROUPING; 

            // 
            // We don't have percent values, so use the number values
            //
            nfi.percentDecimalDigits = nfi.numberDecimalDigits;
            nfi.percentDecimalSeparator = nfi.numberDecimalSeparator; 
            nfi.percentGroupSizes = nfi.numberGroupSizes;
            nfi.percentGroupSeparator = nfi.numberGroupSeparator; 
 
            //
            // Clean up a few odd values 
            //

            // Windows usually returns an empty positive sign, but we like it to be "+"
            if (nfi.positiveSign == null || nfi.positiveSign.Length == 0) nfi.positiveSign = "+"; 

            //Special case for Italian.  The currency decimal separator in the control panel is the empty string. When the user 
            //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the 
            //decimal point doesn't show up.  We'll just hack this here because our default currency format will never use nfi.
            if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0) 
            {
                nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator;
            }
 
#if !FEATURE_CORECLR
            // 
            if ((932 == this.IDEFAULTANSICODEPAGE) || 
               (949 == this.IDEFAULTANSICODEPAGE))
            { 
                // Legacy behavior for cultures that use Japanese/Korean default ANSI code pages
                // Note that this is a code point, not a character.  On Japanese/Korean machines this
                // will be rendered as their currency symbol, not rendered as a "\"
                nfi.ansiCurrencySymbol = "\x5c"; 
            }
#endif // !FEATURE_CORECLR 
        } 

        static private int ConvertFirstDayOfWeekMonToSun(int iTemp) 
        {
            // Convert Mon-Sun to Sun-Sat format
            iTemp++;
            if (iTemp > 6) 
            {
                // Wrap Sunday and convert invalid data to Sunday 
                iTemp = 0; 
            }
            return iTemp; 
        }

        // Helper
        // This is ONLY used for caching names and shouldn't be used for anything else 
        internal static string AnsiToLower(string testString)
        { 
            StringBuilder sb = new StringBuilder(testString.Length); 

            for (int ich = 0; ich < testString.Length; ich++) 
            {
                char ch = testString[ich];
                sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch);
            } 

            return (sb.ToString()); 
        } 

        // If we get a group from windows, then its in 3;0 format with the 0 backwards 
        // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa)
        static private int[] ConvertWin32GroupString(String win32Str)
        {
            // None of these cases make any sense 
            if (win32Str == null || win32Str.Length == 0 || win32Str[0] == '0')
            { 
                return (new int[] { 3 }); 
            }
 
            // Since its in n;n;n;n;n format, we can always get the length quickly
            int[] values;
            if (win32Str[win32Str.Length - 1] == '0')
            { 
                // Trailing 0 gets dropped. 1;0 -> 1
                values = new int[(win32Str.Length / 2)]; 
            } 
            else
            { 
                // Need extra space for trailing zero 1 -> 1;0
                values = new int[(win32Str.Length / 2) + 2];
                values[values.Length - 1] = 0;
            } 

            int i; 
            int j; 
            for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++)
            { 
                // Note that this # shouldn't ever be zero, 'cause 0 is only at end
                // But we'll test because its registry that could be anything
                if (win32Str[i] < '1' || win32Str[i] > '9')
                    return new int[] { 3 }; 

                values[j] = (int)(win32Str[i] - '0'); 
            } 

            return (values); 
        }

        // LCTYPES for GetLocaleInfo
        private const uint LOCALE_NOUSEROVERRIDE = 0x80000000;   // do not use user overrides 
        private const uint LOCALE_RETURN_NUMBER = 0x20000000;   // return number instead of string
 
        // Modifier for genitive names 
        private const uint LOCALE_RETURN_GENITIVE_NAMES = 0x10000000;   //Flag to return the Genitive forms of month names
 
        //
        //  The following LCTypes are mutually exclusive in that they may NOT
        //  be used in combination with each other.
        // 

        // 
        // These are the various forms of the name of the locale: 
        //
        private const uint LOCALE_SLOCALIZEDDISPLAYNAME = 0x00000002;   // localized name of locale, eg "German (Germany)" in UI language 
        private const uint LOCALE_SENGLISHDISPLAYNAME = 0x00000072;   // Display name (language + ---- usually) in English, eg "German (Germany)"
        private const uint LOCALE_SNATIVEDISPLAYNAME = 0x00000073;   // Display name in native locale language, eg "Deutsch (Deutschland)

        private const uint LOCALE_SLOCALIZEDLANGUAGENAME = 0x0000006f;   // Language Display Name for a language, eg "German" in UI language 
        private const uint LOCALE_SENGLISHLANGUAGENAME = 0x00001001;   // English name of language, eg "German"
        private const uint LOCALE_SNATIVELANGUAGENAME = 0x00000004;   // native name of language, eg "Deutsch" 
 
        private const uint LOCALE_SLOCALIZEDCOUNTRYNAME = 0x00000006;   // localized name of country, eg "Germany" in UI language
        private const uint LOCALE_SENGLISHCOUNTRYNAME = 0x00001002;   // English name of country, eg "Germany" 
        private const uint LOCALE_SNATIVECOUNTRYNAME = 0x00000008;   // native name of country, eg "Deutschland"


        //        private const uint LOCALE_ILANGUAGE              =0x00000001;   // language id // Don't use, use NewApis::LocaleNameToLCID instead (GetLocaleInfo doesn't return neutrals) 

        //        private const uint LOCALE_SLANGUAGE              =LOCALE_SLOCALIZEDDISPLAYNAME;   // localized name of language (use LOCALE_SLOCALIZEDDISPLAYNAME instead) 
        //        private const uint LOCALE_SENGLANGUAGE           =LOCALE_SENGLISHLANGUAGENAME;   // English name of language (use LOCALE_SENGLISHLANGUAGENAME instead) 
        private const uint LOCALE_SABBREVLANGNAME = 0x00000003;   // abbreviated language name
        //        private const uint LOCALE_SNATIVELANGNAME        =LOCALE_SNATIVELANGUAGENAME;   // native name of language (use LOCALE_SNATIVELANGUAGENAME instead) 

        private const uint LOCALE_ICOUNTRY = 0x00000005;   // ---- code
        //        private const uint LOCALE_SCOUNTRY               =LOCALE_SLOCALIZEDCOUNTRYNAME;   // localized name of country (use LOCALE_SLOCALIZEDCOUNTRYNAME instead)
        //        private const uint LOCALE_SENGCOUNTRY            =LOCALE_SENGLISHCOUNTRYNAME;   // English name of country (use LOCALE_SENGLISHCOUNTRYNAME instead) 
        private const uint LOCALE_SABBREVCTRYNAME = 0x00000007;   // abbreviated ---- name
        //        private const uint LOCALE_SNATIVECTRYNAME        =LOCALE_SNATIVECOUNTRYNAME;   // native name of country ( use LOCALE_SNATIVECOUNTRYNAME instead) 
        private const uint LOCALE_IGEOID = 0x0000005B;   // geographical location id 

        private const uint LOCALE_IDEFAULTLANGUAGE = 0x00000009;   // default language id 
        private const uint LOCALE_IDEFAULT---- = 0x0000000A;   // default ---- code
        private const uint LOCALE_IDEFAULTCODEPAGE = 0x0000000B;   // default oem code page
        private const uint LOCALE_IDEFAULTANSICODEPAGE = 0x00001004;   // default ansi code page
        private const uint LOCALE_IDEFAULTMACCODEPAGE = 0x00001011;   // default mac code page 

        private const uint LOCALE_SLIST = 0x0000000C;   // list item separator 
        private const uint LOCALE_IMEASURE = 0x0000000D;   // 0 = metric, 1 = US 

        private const uint LOCALE_SDECIMAL = 0x0000000E;   // decimal separator 
        private const uint LOCALE_STHOUSAND = 0x0000000F;   // thousand separator
        private const uint LOCALE_SGROUPING = 0x00000010;   // digit grouping
        private const uint LOCALE_IDIGITS = 0x00000011;   // number of fractional digits
        private const uint LOCALE_ILZERO = 0x00000012;   // leading zeros for decimal 
        private const uint LOCALE_INEGNUMBER = 0x00001010;   // negative number mode
        private const uint LOCALE_SNATIVEDIGITS = 0x00000013;   // native digits for 0-9 
 
        private const uint LOCALE_SCURRENCY = 0x00000014;   // local monetary symbol
        private const uint LOCALE_SINTLSYMBOL = 0x00000015;   // uintl monetary symbol 
        private const uint LOCALE_SMONDECIMALSEP = 0x00000016;   // monetary decimal separator
        private const uint LOCALE_SMONTHOUSANDSEP = 0x00000017;   // monetary thousand separator
        private const uint LOCALE_SMONGROUPING = 0x00000018;   // monetary grouping
        private const uint LOCALE_ICURRDIGITS = 0x00000019;   // # local monetary digits 
        private const uint LOCALE_IINTLCURRDIGITS = 0x0000001A;   // # uintl monetary digits
        private const uint LOCALE_ICURRENCY = 0x0000001B;   // positive currency mode 
        private const uint LOCALE_INEGCURR = 0x0000001C;   // negative currency mode 

        private const uint LOCALE_SDATE = 0x0000001D;   // date separator (derived from LOCALE_SSHORTDATE, use that instead) 
        private const uint LOCALE_STIME = 0x0000001E;   // time separator (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_SSHORTDATE = 0x0000001F;   // short date format string
        private const uint LOCALE_SLONGDATE = 0x00000020;   // long date format string
        private const uint LOCALE_STIMEFORMAT = 0x00001003;   // time format string 
        private const uint LOCALE_IDATE = 0x00000021;   // short date format ordering (derived from LOCALE_SSHORTDATE, use that instead)
        private const uint LOCALE_ILDATE = 0x00000022;   // long date format ordering (derived from LOCALE_SLONGDATE, use that instead) 
        private const uint LOCALE_ITIME = 0x00000023;   // time format specifier (derived from LOCALE_STIMEFORMAT, use that instead) 
        private const uint LOCALE_ITIMEMARKPOSN = 0x00001005;   // time marker position (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_ICENTURY = 0x00000024;   // century format specifier (short date, LOCALE_SSHORTDATE is preferred) 
        private const uint LOCALE_ITLZERO = 0x00000025;   // leading zeros in time field (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_IDAYLZERO = 0x00000026;   // leading zeros in day field (short date, LOCALE_SSHORTDATE is preferred)
        private const uint LOCALE_IMONLZERO = 0x00000027;   // leading zeros in month field (short date, LOCALE_SSHORTDATE is preferred)
        private const uint LOCALE_S1159 = 0x00000028;   // AM designator 
        private const uint LOCALE_S2359 = 0x00000029;   // PM designator
 
        private const uint LOCALE_ICALENDARTYPE = 0x00001009;   // type of calendar specifier 
        private const uint LOCALE_IOPTIONALCALENDAR = 0x0000100B;   // additional calendar types specifier
        private const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C;   // first day of week specifier 
        private const uint LOCALE_IFIRSTWEEKOFYEAR = 0x0000100D;   // first week of year specifier

        private const uint LOCALE_SDAYNAME1 = 0x0000002A;   // long name for Monday
        private const uint LOCALE_SDAYNAME2 = 0x0000002B;   // long name for Tuesday 
        private const uint LOCALE_SDAYNAME3 = 0x0000002C;   // long name for Wednesday
        private const uint LOCALE_SDAYNAME4 = 0x0000002D;   // long name for Thursday 
        private const uint LOCALE_SDAYNAME5 = 0x0000002E;   // long name for Friday 
        private const uint LOCALE_SDAYNAME6 = 0x0000002F;   // long name for Saturday
        private const uint LOCALE_SDAYNAME7 = 0x00000030;   // long name for Sunday 
        private const uint LOCALE_SABBREVDAYNAME1 = 0x00000031;   // abbreviated name for Monday
        private const uint LOCALE_SABBREVDAYNAME2 = 0x00000032;   // abbreviated name for Tuesday
        private const uint LOCALE_SABBREVDAYNAME3 = 0x00000033;   // abbreviated name for Wednesday
        private const uint LOCALE_SABBREVDAYNAME4 = 0x00000034;   // abbreviated name for Thursday 
        private const uint LOCALE_SABBREVDAYNAME5 = 0x00000035;   // abbreviated name for Friday
        private const uint LOCALE_SABBREVDAYNAME6 = 0x00000036;   // abbreviated name for Saturday 
        private const uint LOCALE_SABBREVDAYNAME7 = 0x00000037;   // abbreviated name for Sunday 
        private const uint LOCALE_SMONTHNAME1 = 0x00000038;   // long name for January
        private const uint LOCALE_SMONTHNAME2 = 0x00000039;   // long name for February 
        private const uint LOCALE_SMONTHNAME3 = 0x0000003A;   // long name for [....]
        private const uint LOCALE_SMONTHNAME4 = 0x0000003B;   // long name for April
        private const uint LOCALE_SMONTHNAME5 = 0x0000003C;   // long name for May
        private const uint LOCALE_SMONTHNAME6 = 0x0000003D;   // long name for June 
        private const uint LOCALE_SMONTHNAME7 = 0x0000003E;   // long name for July
        private const uint LOCALE_SMONTHNAME8 = 0x0000003F;   // long name for August 
        private const uint LOCALE_SMONTHNAME9 = 0x00000040;   // long name for September 
        private const uint LOCALE_SMONTHNAME10 = 0x00000041;   // long name for October
        private const uint LOCALE_SMONTHNAME11 = 0x00000042;   // long name for November 
        private const uint LOCALE_SMONTHNAME12 = 0x00000043;   // long name for December
        private const uint LOCALE_SMONTHNAME13 = 0x0000100E;   // long name for 13th month (if exists)
        private const uint LOCALE_SABBREVMONTHNAME1 = 0x00000044;   // abbreviated name for January
        private const uint LOCALE_SABBREVMONTHNAME2 = 0x00000045;   // abbreviated name for February 
        private const uint LOCALE_SABBREVMONTHNAME3 = 0x00000046;   // abbreviated name for [....]
        private const uint LOCALE_SABBREVMONTHNAME4 = 0x00000047;   // abbreviated name for April 
        private const uint LOCALE_SABBREVMONTHNAME5 = 0x00000048;   // abbreviated name for May 
        private const uint LOCALE_SABBREVMONTHNAME6 = 0x00000049;   // abbreviated name for June
        private const uint LOCALE_SABBREVMONTHNAME7 = 0x0000004A;   // abbreviated name for July 
        private const uint LOCALE_SABBREVMONTHNAME8 = 0x0000004B;   // abbreviated name for August
        private const uint LOCALE_SABBREVMONTHNAME9 = 0x0000004C;   // abbreviated name for September
        private const uint LOCALE_SABBREVMONTHNAME10 = 0x0000004D;   // abbreviated name for October
        private const uint LOCALE_SABBREVMONTHNAME11 = 0x0000004E;   // abbreviated name for November 
        private const uint LOCALE_SABBREVMONTHNAME12 = 0x0000004F;   // abbreviated name for December
        private const uint LOCALE_SABBREVMONTHNAME13 = 0x0000100F;   // abbreviated name for 13th month (if exists) 
 
        private const uint LOCALE_SPOSITIVESIGN = 0x00000050;   // positive sign
        private const uint LOCALE_SNEGATIVESIGN = 0x00000051;   // negative sign 
        private const uint LOCALE_IPOSSIGNPOSN = 0x00000052;   // positive sign position (derived from INEGCURR)
        private const uint LOCALE_INEGSIGNPOSN = 0x00000053;   // negative sign position (derived from INEGCURR)
        private const uint LOCALE_IPOSSYMPRECEDES = 0x00000054;   // mon sym precedes pos amt (derived from ICURRENCY)
        private const uint LOCALE_IPOSSEPBYSPACE = 0x00000055;   // mon sym sep by space from pos amt (derived from ICURRENCY) 
        private const uint LOCALE_INEGSYMPRECEDES = 0x00000056;   // mon sym precedes neg amt (derived from INEGCURR)
        private const uint LOCALE_INEGSEPBYSPACE = 0x00000057;   // mon sym sep by space from neg amt (derived from INEGCURR) 
 
        private const uint LOCALE_FONTSIGNATURE = 0x00000058;   // font signature
        private const uint LOCALE_SISO639LANGNAME = 0x00000059;   // ISO abbreviated language name 
        private const uint LOCALE_SISO3166CTRYNAME = 0x0000005A;   // ISO abbreviated ---- name

        private const uint LOCALE_IDEFAULTEBCDICCODEPAGE = 0x00001012;   // default ebcdic code page
        private const uint LOCALE_IPAPERSIZE = 0x0000100A;   // 1 = letter, 5 = legal, 8 = a3, 9 = a4 
        private const uint LOCALE_SENGCURRNAME = 0x00001007;   // english name of currency
        private const uint LOCALE_SNATIVECURRNAME = 0x00001008;   // native name of currency 
        private const uint LOCALE_SYEARMONTH = 0x00001006;   // year month format string 
        private const uint LOCALE_SSORTNAME = 0x00001013;   // sort name
        private const uint LOCALE_IDIGITSUBSTITUTION = 0x00001014;   // 0 = context, 1 = none, 2 = national 

        private const uint LOCALE_SNAME = 0x0000005c;   // locale name (with sort info) (ie: de-DE_phoneb)
        private const uint LOCALE_SDURATION = 0x0000005d;   // time duration format
        private const uint LOCALE_SKEYBOARDSTOINSTALL = 0x0000005e;   // (windows only) keyboards to install 
        private const uint LOCALE_SSHORTESTDAYNAME1 = 0x00000060;   // Shortest day name for Monday
        private const uint LOCALE_SSHORTESTDAYNAME2 = 0x00000061;   // Shortest day name for Tuesday 
        private const uint LOCALE_SSHORTESTDAYNAME3 = 0x00000062;   // Shortest day name for Wednesday 
        private const uint LOCALE_SSHORTESTDAYNAME4 = 0x00000063;   // Shortest day name for Thursday
        private const uint LOCALE_SSHORTESTDAYNAME5 = 0x00000064;   // Shortest day name for Friday 
        private const uint LOCALE_SSHORTESTDAYNAME6 = 0x00000065;   // Shortest day name for Saturday
        private const uint LOCALE_SSHORTESTDAYNAME7 = 0x00000066;   // Shortest day name for Sunday
        private const uint LOCALE_SISO639LANGNAME2 = 0x00000067;   // 3 character ISO abbreviated language name
        private const uint LOCALE_SISO3166CTRYNAME2 = 0x00000068;   // 3 character ISO ---- name 
        private const uint LOCALE_SNAN = 0x00000069;   // Not a Number
        private const uint LOCALE_SPOSINFINITY = 0x0000006a;   // + Infinity 
        private const uint LOCALE_SNEGINFINITY = 0x0000006b;   // - Infinity 
        private const uint LOCALE_SSCRIPTS = 0x0000006c;   // Typical scripts in the locale
        private const uint LOCALE_SPARENT = 0x0000006d;   // Fallback name for resources 
        private const uint LOCALE_SCONSOLEFALLBACKNAME = 0x0000006e;   // Fallback name for within the console
        //        private const uint LOCALE_SLANGDISPLAYNAME       =LOCALE_SLOCALIZEDLANGUAGENAME;   // Language Display Name for a language (use LOCALE_SLOCALIZEDLANGUAGENAME instead)

        // Windows 7 LCTYPES 
        private const uint LOCALE_IREADINGLAYOUT = 0x00000070;   // Returns one of the following 4 reading layout values:
        // 0 - Left to right (eg en-US) 
        // 1 - Right to left (eg arabic locales) 
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
        // 3 - Vertical top to bottom with columns proceeding to the right 
        private const uint LOCALE_INEUTRAL = 0x00000071;   // Returns 0 for specific cultures, 1 for neutral cultures.
        private const uint LOCALE_INEGATIVEPERCENT = 0x00000074;   // Returns 0-11 for the negative percent format
        private const uint LOCALE_IPOSITIVEPERCENT = 0x00000075;   // Returns 0-3 for the positive percent formatIPOSITIVEPERCENT
        private const uint LOCALE_SPERCENT = 0x00000076;   // Returns the percent symbol 
        private const uint LOCALE_----ILLE = 0x00000077;   // Returns the permille (U+2030) symbol
        private const uint LOCALE_SMONTHDAY = 0x00000078;   // Returns the preferred month/day format 
        private const uint LOCALE_SSHORTTIME = 0x00000079;   // Returns the preferred short time format (ie: no seconds, just h:mm) 
        private const uint LOCALE_SOPENTYPELANGUAGETAG = 0x0000007a;   // Open type language tag, eg: "latn" or "dflt"
        private const uint LOCALE_SSORTLOCALE = 0x0000007b;   // Name of locale to use for sorting/collation/casing behavior. 

        // Time formats enumerations
        internal const uint TIME_NOSECONDS = 0x00000002;   // Don't use seconds (get short time format for enumtimeformats on win7+)
 
        // Get our initial minimal culture data (name, parent, etc.)
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeInitCultureData(CultureData cultureData); 

        // Grab the NumberFormatInfo data
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeGetNumberFormatInfoValues(String localeName, NumberFormatInfo nfi, bool useUserOverride); 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride);

#if !FEATURE_CORECLR 
        [System.Security.SecurityCritical]  // auto-generated
        [SuppressUnmanagedCodeSecurityAttribute()] 
        [ResourceExposure(ResourceScope.None)] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        internal static extern int nativeEnumCultureNames(int cultureTypes, ObjectHandleOnStack retStringArray); 
#endif

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System.Globalization
{ 
 
    using System;
    using System.Collections; 
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
#if !FEATURE_CORECLR 
    using System.Reflection;
    using System.Resources; 
#endif 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Runtime.Versioning;
    using System.Diagnostics.Contracts;
    using System.Security;
    using System.Security.Principal; 

    // 
    // List of culture data 
    // Note the we cache overrides.
    // Note that localized names (resource names) aren't available from here. 
    //

    //
    // Our names are a tad confusing. 
    //
    // sWindowsName -- The name that windows thinks this culture is, ie: 
    //                            en-US if you pass in en-US 
    //                            de-DE_phoneb if you pass in de-DE_phoneb
    //                            fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine) 
    //                            fj if you pass in fj (neutral, post-Windows 7 machine)
    //
    // sRealName -- The name you used to construct the culture, in pretty form
    //                       en-US if you pass in EN-us 
    //                       en if you pass in en
    //                       de-DE_phoneb if you pass in de-DE_phoneb 
    // 
    // sSpecificCulture -- The specific culture for this culture
    //                             en-US for en-US 
    //                             en-US for en
    //                             de-DE_phoneb for alt sort
    //                             fj-FJ for fj (neutral)
    // 
    // sName -- The IETF name of this culture (ie: no sort info, could be neutral)
    //                en-US if you pass in en-US 
    //                en if you pass in en 
    //                de-DE if you pass in de-DE_phoneb
    // 

    // StructLayout is needed here otherwise compiler can re-arrange the fields.
    // We have to keep this in-[....] with the definition in comnlsinfo.h
    // 
    // WARNING WARNING WARNING
    // 
    // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CultureDataBaseObject) 
    // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureDataBaseObject
    // WARNING: must be manually structured to match the true loaded class layout 
    //
    internal class CultureData
    {
        const int undef = -1; 

        // Override flag 
        private String sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb) 
        private String sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
 
        // Identity
        private String sName; // locale name (ie: en-us, NO sort info, but could be neutral)
        private String sParent; // Parent name (which may be a custom locale/culture)
        private String sLocalizedDisplayName; // Localized pretty name for this locale 
        private String sEnglishDisplayName; // English pretty name for this locale
        private String sNativeDisplayName; // Native pretty name for this locale 
        private String sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort 

        // Language 
        private String sISO639Language; // ISO 639 Language Name
        private String sLocalizedLanguage; // Localized name for this language
        private String sEnglishLanguage; // English name for this language
        private String sNativeLanguage; // Native name of this language 

        // Region 
        private String sRegionName; // (RegionInfo) 
        //        private int    iCountry=undef           ; // (user can override) ---- code (RegionInfo)
        private int iGeoId = undef; // GeoId 
        private String sLocalized----; // localized ---- name
        private String sEnglishCountry; // english ---- name (RegionInfo)
        private String sNativeCountry; // native ---- name
        private String sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US 

        // Numbers 
        private String sPositiveSign; // (user can override) positive sign 
        private String sNegativeSign; // (user can override) negative sign
        private String[] saNativeDigits; // (user can override) native characters for digits 0-9 
        // (nfi populates these 5, don't have to be = undef)
        private int iDigitSubstitution; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused)
        private int iLeadingZeros; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros
        private int iDigits; // (user can override) number of fractional digits 
        private int iNegativeNumber; // (user can override) negative number format
        private int[] waGrouping; // (user can override) grouping of digits 
        private String sDecimalSeparator; // (user can override) decimal separator 
        private String sThousandSeparator; // (user can override) thousands separator
        private String sNaN; // Not a Number 
        private String sPositiveInfinity; // + Infinity
        private String sNegativeInfinity; // - Infinity

        // Percent 
        private int iNegativePercent = undef; // Negative Percent (0-3)
        private int iPositivePercent = undef; // Positive Percent (0-11) 
        private String sPercent; // Percent (%) symbol 
        private String sPerMille; // PerMille (‰) symbol
 
        // Currency
        private String sCurrency; // (user can override) local monetary symbol
        private String sIntlMonetarySymbol; // international monetary symbol (RegionInfo)
        private String sEnglishCurrency; // English name for this currency 
        private String sNativeCurrency; // Native name for this currency
        // (nfi populates these 4, don't have to be = undef) 
        private int iCurrencyDigits; // (user can override) # local monetary fractional digits 
        private int iCurrency; // (user can override) positive currency format
        private int iNegativeCurrency; // (user can override) negative currency format 
        private int[] waMonetaryGrouping; // (user can override) monetary grouping of digits
        private String sMonetaryDecimal; // (user can override) monetary decimal separator
        private String sMonetaryThousand; // (user can override) monetary thousands separator
 
        // Misc
        private int iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo) 
        private String sListSeparator; // (user can override) list separator 
        //        private int    iPaperSize               ; // default paper size (RegionInfo)
 
        // Time
        private String sAM1159; // (user can override) AM designator
        private String sPM2359; // (user can override) PM designator
        private String[] saLongTimes; // (user can override) time format 
        private String[] saShortTimes; // short time format
        private String[] saDurationFormats; // time duration format 
 
        // Calendar specific data
        private int iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really) 
        private int iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really)
        private int[] waCalendars; // all available calendar type(s).  The first one is the default calendar

        // Store for specific data about each calendar 
        private CalendarData[] calendars; // Store for specific calendar data
 
        // Text information 
#if !FEATURE_CORECLR
        private int iReadingLayout = undef; // Reading layout data 
        // 0 - Left to right (eg en-US)
        // 1 - Right to left (eg arabic locales)
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
        // 3 - Vertical top to bottom with columns proceeding to the right 
#endif
        private String sTextInfo; // Text info name to use for custom 
        private String sCompareInfo; // Compare info name (including sorting key) to use if custom 
        private String sScripts; // Typical Scripts for this locale (latn;cyrl; etc)
 
        // CoreCLR depends on this even though its not exposed publicly.
#if !FEATURE_CORECLR
        private int iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP)
        private int iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM) 
        private int iDefaultMacCodePage = undef; // default macintosh code page
        private int iDefaultEbcdicCodePage = undef; // default EBCDIC code page 
 
        // These are desktop only, not coreclr
        private int    iLanguage; // locale ID (0409) - NO sort information 
        private String sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU
        private String sAbbrevCountry; // abbreviated ---- name (RegionInfo) (Windows Region Name) ex: USA
        private String sISO639Language2; // 3 char ISO 639 lang name 2 ex: eng
        private String sISO3166CountryName2; // 3 char ISO 3166 ---- name 2 2(RegionInfo) ex: USA (ISO) 
        private int    iInputLanguageHandle=undef;// input language handle
        private String sConsoleFallbackName; // The culture name for the console fallback UI culture 
        private String sKeyboardsToInstall; // Keyboard installation string. 
        private String fontSignature; // Font signature (16 WORDS)
#endif 

        // The bools all need to be in one spot
        private bool bUseOverrides; // use user overrides?
        private bool bNeutral; // Flags for the culture (ie: neutral or not right now) 
#if !FEATURE_CORECLR
        private bool bWin32Installed; // Flags indicate if the culture is Win32 installed 
        private bool bFramework; // Flags for indicate if the culture is one of Whidbey cultures 
#endif
 
#if !FEATURE_CORECLR
        // Region Name to Culture Name mapping table
        // (In future would be nice to be in registry or something)
 
        //Using a field initializer rather than a static constructor so that the whole class can be lazy
        //init. 
        private static Dictionary RegionNames; 
        private static readonly bool init = Init();
        private static bool Init() 
        {
            RegionNames = new Dictionary
            {
                { "029", "en-029" }, 
                { "AE",  "ar-AE" },
                { "AF",  "prs-AF" }, 
                { "AL",  "sq-AL" }, 
                { "AM",  "hy-AM" },
                { "AR",  "es-AR" }, 
                { "AT",  "de-AT" },
                { "AU",  "en-AU" },
                { "AZ",  "az-Cyrl-AZ" },
                { "BA",  "bs-Latn-BA" }, 
                { "BD",  "bn-BD" },
                { "BE",  "nl-BE" }, 
                { "BG",  "bg-BG" }, 
                { "BH",  "ar-BH" },
                { "BN",  "ms-BN" }, 
                { "BO",  "es-BO" },
                { "BR",  "pt-BR" },
                { "BY",  "be-BY" },
                { "BZ",  "en-BZ" }, 
                { "CA",  "en-CA" },
                { "CH",  "it-CH" }, 
                { "CL",  "es-CL" }, 
                { "CN",  "zh-CN" },
                { "CO",  "es-CO" }, 
                { "CR",  "es-CR" },
                { "CS",  "sr-Cyrl-CS" },
                { "CZ",  "cs-CZ" },
                { "DE",  "de-DE" }, 
                { "DK",  "da-DK" },
                { "DO",  "es-DO" }, 
                { "DZ",  "ar-DZ" }, 
                { "EC",  "es-EC" },
                { "EE",  "et-EE" }, 
                { "EG",  "ar-EG" },
                { "ES",  "es-ES" },
                { "ET",  "am-ET" },
                { "FI",  "fi-FI" }, 
                { "FO",  "fo-FO" },
                { "FR",  "fr-FR" }, 
                { "GB",  "en-GB" }, 
                { "GE",  "ka-GE" },
                { "GL",  "kl-GL" }, 
                { "GR",  "el-GR" },
                { "GT",  "es-GT" },
                { "HK",  "zh-HK" },
                { "HN",  "es-HN" }, 
                { "HR",  "hr-HR" },
                { "HU",  "hu-HU" }, 
                { "ID",  "id-ID" }, 
                { "IE",  "en-IE" },
                { "IL",  "he-IL" }, 
                { "IN",  "hi-IN" },
                { "IQ",  "ar-IQ" },
                { "IR",  "fa-IR" },
                { "IS",  "is-IS" }, 
                { "IT",  "it-IT" },
                { "IV",  "" }, 
                { "JM",  "en-JM" }, 
                { "JO",  "ar-JO" },
                { "JP",  "ja-JP" }, 
                { "KE",  "sw-KE" },
                { "KG",  "ky-KG" },
                { "KH",  "km-KH" },
                { "KR",  "ko-KR" }, 
                { "KW",  "ar-KW" },
                { "KZ",  "kk-KZ" }, 
                { "LA",  "lo-LA" }, 
                { "LB",  "ar-LB" },
                { "LI",  "de-LI" }, 
                { "LK",  "si-LK" },
                { "LT",  "lt-LT" },
                { "LU",  "lb-LU" },
                { "LV",  "lv-LV" }, 
                { "LY",  "ar-LY" },
                { "MA",  "ar-MA" }, 
                { "MC",  "fr-MC" }, 
                { "ME",  "sr-Latn-ME" },
                { "MK",  "mk-MK" }, 
                { "MN",  "mn-MN" },
                { "MO",  "zh-MO" },
                { "MT",  "mt-MT" },
                { "MV",  "dv-MV" }, 
                { "MX",  "es-MX" },
                { "MY",  "ms-MY" }, 
                { "NG",  "ig-NG" }, 
                { "NI",  "es-NI" },
                { "NL",  "nl-NL" }, 
                { "NO",  "nn-NO" },
                { "NP",  "ne-NP" },
                { "NZ",  "en-NZ" },
                { "OM",  "ar-OM" }, 
                { "PA",  "es-PA" },
                { "PE",  "es-PE" }, 
                { "PH",  "en-PH" }, 
                { "PK",  "ur-PK" },
                { "PL",  "pl-PL" }, 
                { "PR",  "es-PR" },
                { "PT",  "pt-PT" },
                { "PY",  "es-PY" },
                { "QA",  "ar-QA" }, 
                { "RO",  "ro-RO" },
                { "RS",  "sr-Latn-RS" }, 
                { "RU",  "ru-RU" }, 
                { "RW",  "rw-RW" },
                { "SA",  "ar-SA" }, 
                { "SE",  "sv-SE" },
                { "SG",  "zh-SG" },
                { "SI",  "sl-SI" },
                { "SK",  "sk-SK" }, 
                { "SN",  "wo-SN" },
                { "SV",  "es-SV" }, 
                { "SY",  "ar-SY" }, 
                { "TH",  "th-TH" },
                { "TJ",  "tg-Cyrl-TJ" }, 
                { "TM",  "tk-TM" },
                { "TN",  "ar-TN" },
                { "TR",  "tr-TR" },
                { "TT",  "en-TT" }, 
                { "TW",  "zh-TW" },
                { "UA",  "uk-UA" }, 
                { "US",  "en-US" }, 
                { "UY",  "es-UY" },
                { "UZ",  "uz-Cyrl-UZ" }, 
                { "VE",  "es-VE" },
                { "VN",  "vi-VN" },
                { "YE",  "ar-YE" },
                { "ZA",  "af-ZA" }, 
                { "ZW",  "en-ZW" }
            }; 
            return true; 
        }
#endif 


        /////////////////////////////////////////////////////////////////////////
        // Build our invariant 
        //
        // We need an invariant instance, which we build hard-coded with the static constructor // 
        ///////////////////////////////////////////////////////////////////////// 
        internal static CultureData Invariant;
#if !FEATURE_CORECLR 
        internal static ResourceSet MscorlibResourceSet;
#endif

        static CultureData() 
        {
            // Make a new culturedata 
            CultureData invariant = new CultureData(); 

#if !FEATURE_CORECLR 
            // Call the native code to get the value of bWin32Installed.
            // For versions <= Vista, we set this to false for compatibility with v2.
            // For Windows 7, the flag is true.
            invariant.bUseOverrides = false; 
            invariant.sRealName = "";
 
            // Ask the native code to fill it out for us, we only need the field IsWin32Installed 
            nativeInitCultureData(invariant);
#endif 

            // Basics
            // Note that we override the resources since this IS NOT supposed to change (by definition)
            invariant.bUseOverrides = false; 
            invariant.sRealName = "";                     // Name you passed in (ie: en-US, en, or de-DE_phoneb)
            invariant.sWindowsName = "";                     // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in)) 
 
            // Identity
            invariant.sName = "";                     // locale name (ie: en-us) 
            invariant.sParent = "";                     // Parent name (which may be a custom locale/culture)
            invariant.bNeutral = false;                   // Flags for the culture (ie: neutral or not right now)
#if !FEATURE_CORECLR
            // Don't set invariant.bWin32Installed, we used nativeInitCultureData for that. 
            invariant.bFramework = true;
#endif 
            invariant.sEnglishDisplayName = "Invariant Language (Invariant ----)"; // English pretty name for this locale 
            invariant.sNativeDisplayName = "Invariant Language (Invariant ----)";  // Native pretty name for this locale
            invariant.sSpecificCulture = "";                     // The culture name to be used in CultureInfo.CreateSpecificCulture() 

            // Language
            invariant.sISO639Language = "iv";                   // ISO 639 Language Name
            invariant.sLocalizedLanguage = "Invariant Language";   // Display name for this Language 
            invariant.sEnglishLanguage = "Invariant Language";   // English name for this language
            invariant.sNativeLanguage = "Invariant Language";   // Native name of this language 
 
            // Region
            invariant.sRegionName = "IV";                   // (RegionInfo) 
            // Unused for now:
            //            invariant.iCountry              =1;                      // ---- code (RegionInfo)
            invariant.iGeoId = 244;                    // GeoId (Windows Only)
            invariant.sEnglishCountry = "Invariant ----";    // english ---- name (RegionInfo) 
            invariant.sNativeCountry = "Invariant ----";    // native ---- name (Windows Only)
            invariant.sISO3166CountryName = "IV";                   // (RegionInfo), ie: US 
 
            // Numbers
            invariant.sPositiveSign = "+";                    // positive sign 
            invariant.sNegativeSign = "-";                    // negative sign
            invariant.saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9
            invariant.iDigitSubstitution = 1;                      // Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only)
            invariant.iLeadingZeros = 1;                      // leading zeros 0=no leading zeros, 1=leading zeros 
            invariant.iDigits = 2;                      // number of fractional digits
            invariant.iNegativeNumber = 1;                      // negative number format 
            invariant.waGrouping = new int[] { 3 };          // grouping of digits 
            invariant.sDecimalSeparator = ".";                    // decimal separator
            invariant.sThousandSeparator = ",";                    // thousands separator 
            invariant.sNaN = "NaN";                  // Not a Number
            invariant.sPositiveInfinity = "Infinity";             // + Infinity
            invariant.sNegativeInfinity = "-Infinity";            // - Infinity
 
            // Percent
            invariant.iNegativePercent = 0;                      // Negative Percent (0-3) 
            invariant.iPositivePercent = 0;                      // Positive Percent (0-11) 
            invariant.sPercent = "%";                    // Percent (%) symbol
            invariant.sPerMille = "\x2030";               // PerMille(‰) symbol 

            // Currency
            invariant.sCurrency = "\x00a4";                // local monetary symbol "¤: for international monetary symbol
            invariant.sIntlMonetarySymbol = "XDR";                  // international monetary symbol (RegionInfo) 
            invariant.sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only)
            invariant.sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only) 
            invariant.iCurrencyDigits = 2;                      // # local monetary fractional digits 
            invariant.iCurrency = 0;                      // positive currency format
            invariant.iNegativeCurrency = 0;                      // negative currency format 
            invariant.waMonetaryGrouping = new int[] { 3 };          // monetary grouping of digits
            invariant.sMonetaryDecimal = ".";                    // monetary decimal separator
            invariant.sMonetaryThousand = ",";                    // monetary thousands separator
 
            // Misc
            invariant.iMeasure = 0;                      // system of measurement 0=metric, 1=US (RegionInfo) 
            invariant.sListSeparator = ",";                    // list separator 
            // Unused for now:
            //            invariant.iPaperSize            =9;                      // default paper size (RegionInfo) 
            //            invariant.waFontSignature       ="\x0002\x0000\x0000\x0000\x0000\x0000\x0000\x8000\x0001\x0000\x0000\x8000\x0001\x0000\x0000\x8000"; // Font signature (16 WORDS) (Windows Only)

            // Time
            invariant.sAM1159 = "AM";                   // AM designator 
            invariant.sPM2359 = "PM";                   // PM designator
            invariant.saLongTimes = new String[] { "HH:mm:ss" };                             // time format 
            invariant.saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format 
            invariant.saDurationFormats = new String[] { "HH:mm:ss" };                             // time duration format
 
            // Calendar specific data
            invariant.iFirstDayOfWeek = 0;                      // first day of week
            invariant.iFirstWeekOfYear = 0;                      // first week of year
            invariant.waCalendars = new int[] { (int)CalendarId.GREGORIAN };       // all available calendar type(s).  The first one is the default calendar 

            // Store for specific data about each calendar 
            invariant.calendars = new CalendarData[CalendarData.MAX_CALENDARS]; 
            invariant.calendars[0] = CalendarData.Invariant;
 
            // Text information
#if !FEATURE_CORECLR
            invariant.iReadingLayout = 0;                      // Reading Layout = RTL
#endif 
            invariant.sTextInfo = "";                     // Text info name to use for custom
            invariant.sCompareInfo = "";                     // Compare info name (including sorting key) to use if custom 
            invariant.sScripts = "Latn;";                // Typical Scripts for this locale (latn,cyrl, etc) 

            // These are desktop only, not coreclr 
#if !FEATURE_CORECLR
            invariant.iLanguage = 0x007f;                 // locale ID (0409) - NO sort information
            invariant.iDefaultAnsiCodePage = 1252;                   // default ansi code page ID (ACP)
            invariant.iDefaultOemCodePage = 437;                    // default oem code page ID (OCP or OEM) 
            invariant.iDefaultMacCodePage = 10000;                  // default macintosh code page
            invariant.iDefaultEbcdicCodePage = 037;                    // default EBCDIC code page 
            invariant.sAbbrevLang = "IVL";                  // abbreviated language name (Windows Language Name) 
            invariant.sAbbrevCountry = "IVC";                  // abbreviated ---- name (RegionInfo) (Windows Region Name)
            invariant.sISO639Language2 = "ivl";                  // 3 char ISO 639 lang name 2 
            invariant.sISO3166CountryName2 = "ivc";                  // 3 char ISO 3166 ---- name 2 2(RegionInfo)
            invariant.iInputLanguageHandle = 0x007f;                 // input language handle
            invariant.sConsoleFallbackName = "";                     // The culture name for the console fallback UI culture
            invariant.sKeyboardsToInstall = "0409:00000409";        // Keyboard installation string. 
#endif
            // Remember it 
            Invariant = invariant; 
        }
 
#if !FEATURE_CORECLR
        [System.Security.SecurityCritical]  // auto-generated
        private static bool IsResourcePresent(String resourceKey)
        { 
            if (MscorlibResourceSet == null)
            { 
                MscorlibResourceSet = new ResourceSet(typeof(Environment).Assembly.GetManifestResourceStream("mscorlib.resources")); 
            }
            return MscorlibResourceSet.GetString(resourceKey) != null; 
        }
#endif

        /////////////// 
        // Constructors //
        /////////////// 
        // Cache of cultures we've already looked up 
        private static Dictionary s_cachedCultures;
 
        internal static CultureData GetCultureData(String cultureName, bool useUserOverride)
        {
            // First do a shortcut for Invariant
            if (String.IsNullOrEmpty(cultureName)) 
            {
                return CultureData.Invariant; 
            } 

            // Try the hash table first 
            String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
            Dictionary tempHashTable = s_cachedCultures;
            if (tempHashTable == null)
            { 
                // No table yet, make a new one
                tempHashTable = new Dictionary(); 
            } 
            else
            { 
                // Check the hash table
                CultureData retVal;
                lock (((ICollection)tempHashTable).SyncRoot)
                { 
                    tempHashTable.TryGetValue(hashName, out retVal);
                } 
                if (retVal != null) 
                {
                    return retVal; 
                }
            }

            // Not found in the hash table, need to see if we can build one that works for us 
            CultureData culture = CreateCultureData(cultureName, useUserOverride);
            if (culture == null) 
            { 
                return null;
            } 

            // Found one, add it to the cache
            lock (((ICollection)tempHashTable).SyncRoot)
            { 
                tempHashTable[hashName] = culture;
            } 
 
            // Copy the hashtable to the corresponding member variables.  This will potentially overwrite
            // new tables simultaneously created by a new thread, but maximizes thread safety. 
            s_cachedCultures = tempHashTable;

            return culture;
        } 

        private static CultureData CreateCultureData(string cultureName, bool useUserOverride) 
        { 
            CultureData culture = new CultureData();
            culture.bUseOverrides = useUserOverride; 
            culture.sRealName = cultureName;

            // Ask native code if that one's real
            if (culture.InitCultureData() == false) 
            {
#if !FEATURE_CORECLR 
                if (culture.InitCompatibilityCultureData() == false 
                 && culture.InitLegacyAlternateSortData() == false)
#endif 
                {
                    return null;
                }
            } 

            return culture; 
        } 

        [System.Security.SecuritySafeCritical] 
        private bool InitCultureData()
        {
            if (nativeInitCultureData(this) == false)
            { 
                return false;
            } 
 
#if !FEATURE_CORECLR
            if (CultureInfo.Is----Sku) 
            {
                Treat----ParentChainAsHaving----AsSpecific();
            }
#endif 
            return true;
        } 
 
#if !FEATURE_CORECLR
        [System.Security.SecuritySafeCritical] 
        private void Treat----ParentChainAsHaving----AsSpecific()
        {
            if (IsNeutralInParentChainOf----() && IsOsPriorToWin7() && !IsReplacementCulture)
            { 
                // force population of fields that should have information that is
                // different than zh-TW: 
                string s = SNATIVELANGUAGE; 
                s = SENGLISHLANGUAGE;
                s = SLOCALIZEDLANGUAGE; 
                s = STEXTINFO;
                s = SCOMPAREINFO;
                s = FONTSIGNATURE;
                int i = IDEFAULTANSICODEPAGE; 
                i = IDEFAULTOEMCODEPAGE;
                i = IDEFAULTMACCODEPAGE; 
 
                // all other fields will be populated with values that are the same
                // as those for ---- 
                this.sSpecificCulture = "zh-TW";
                this.sWindowsName = "zh-TW";
            }
        } 

        private bool IsNeutralInParentChainOf----() 
        { 
            return this.sRealName == "zh" || this.sRealName == "zh-Hant";
  } 

        static readonly Version s_win7Version = new Version(6, 1);
        static private bool IsOsPriorToWin7()
        { 
            return Environment.OSVersion.Platform == PlatformID.Win32NT &&
                   Environment.OSVersion.Version < s_win7Version; 
        } 
        static private bool IsOsWin7OrPrior()
        { 
            return Environment.OSVersion.Platform == PlatformID.Win32NT &&
                Environment.OSVersion.Version < new Version(6, 2); // Win7 is 6.1.Build.Revision so we have to check for anything less than 6.2
        }
 
        private bool InitCompatibilityCultureData()
        { 
            // for compatibility handle the deprecated ids: zh-chs, zh-cht 
            string cultureName = this.sRealName;
 
            string fallbackCultureName;
            string realCultureName;
            switch (AnsiToLower(cultureName))
            { 
                case "zh-chs":
                    fallbackCultureName = "zh-Hans"; 
                    realCultureName = "zh-CHS"; 
                    break;
                case "zh-cht": 
                    fallbackCultureName = "zh-Hant";
                    realCultureName = "zh-CHT";
                    break;
                default: 
                    return false;
            } 
 
            this.sRealName = fallbackCultureName;
            if (InitCultureData() == false) 
            {
                return false;
            }
            // fixup our data 
            this.sName = realCultureName; // the name that goes back to the user
            this.sParent = fallbackCultureName; 
            this.bFramework = true; 

            return true; 
        }

        private bool InitLegacyAlternateSortData()
        { 
            if (!CompareInfo.IsLegacy20SortingBehaviorRequested)
            { 
                return false; 
            }
 
            // For V2 compatability, handle deprecated alternate sorts
            string cultureName = this.sRealName;

            switch (AnsiToLower(cultureName)) 
            {
                case "ko-kr_unicod": 
                    cultureName = "ko-KR_unicod"; 
                    this.sRealName = "ko-KR";
                    this.iLanguage = 0x00010412; 
                    break;
                case "ja-jp_unicod":
                    cultureName = "ja-JP_unicod";
                    this.sRealName = "ja-JP"; 
                    this.iLanguage = 0x00010411;
                    break; 
                case "zh-hk_stroke": 
                    cultureName = "zh-HK_stroke";
                    this.sRealName = "zh-HK"; 
                    this.iLanguage = 0x00020c04;
                    break;
                default:
                    return false; 
            }
 
            if (nativeInitCultureData(this) == false) 
            {
                return false; 
            }

            this.sRealName = cultureName;
            this.sCompareInfo = cultureName; 
            this.bFramework = true;
 
            return true; 
        }
 
        // Cache of regions we've already looked up
        private static Dictionary s_cachedRegions;

#if FEATURE_WIN32_REGISTRY 
        private static String s_RegionKey = @"System\CurrentControlSet\Control\Nls\RegionMapping";
#endif // FEATURE_WIN32_REGISTRY 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride) 
        {
            // First do a shortcut for Invariant
            if (String.IsNullOrEmpty(cultureName))
            { 
                return CultureData.Invariant;
            } 
 
            //
            // First check if GetCultureData() can find it (ie: its a real culture) 
            //
            CultureData retVal = GetCultureData(cultureName, useUserOverride);
            if (retVal != null && (retVal.IsNeutralCulture == false)) return retVal;
 
            //
            // Not a specific culture, perhaps it's region-only name 
            // (Remember this isn't a core clr path where that's not supported) 
            //
 
            // If it was neutral remember that so that RegionInfo() can throw the right exception
            CultureData neutral = retVal;

            // Try the hash table next 
            String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
            Dictionary tempHashTable = s_cachedRegions; 
            if (tempHashTable == null) 
            {
                // No table yet, make a new one 
                tempHashTable = new Dictionary();
            }
            else
            { 
                // Check the hash table
                lock (((ICollection)tempHashTable).SyncRoot) 
                { 
                    tempHashTable.TryGetValue(hashName, out retVal);
                } 
                if (retVal != null)
                {
                    return retVal;
                } 
            }
 
            // 
            // Not found in the hash table, look it up the hard way
            // 
#if FEATURE_WIN32_REGISTRY
            // First try the registry in case there are overrides of our table
            try
            { 
                // Open in read-only mode.
                // Use InternalOpenSubKey so that we avoid the security check. 
                Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.InternalOpenSubKey(s_RegionKey, false); 

                if (key != null) 
                {
                    try
                    {
                        Object value = key.InternalGetValue(cultureName, null, false, false); 

                        if (value != null) 
                        { 
                            // Get the name of the locale to try.
                            String specificForRegion = value.ToString(); 

                            // See if it's real
                            retVal = GetCultureData(specificForRegion, useUserOverride);
                        } 
                    }
                    finally 
                    { 
                        key.Close();
                    } 
                }
            }
            // If this fails for any reason, we'll just ignore it, likely it just isn't there.
            catch (ObjectDisposedException) { } 
            catch (ArgumentException) { }
#endif // FEATURE_WIN32_REGISTRY 
 
            // If not a valid mapping from the registry we'll have to try the hard coded table
            if (retVal == null || (retVal.IsNeutralCulture == true)) 
            {
                // Not a valid mapping, try the hard coded table
                if (RegionNames.ContainsKey(cultureName))
                { 
                    // Make sure we can get culture data for it
                    retVal = GetCultureData(RegionNames[cultureName], useUserOverride); 
                } 
            }
 
            // If not found in the hard coded table we'll have to find a culture that works for us
            if (retVal == null || (retVal.IsNeutralCulture == true))
            {
                // Not found in the hard coded table, need to see if we can find a culture that works for us 
                // Not a real culture name, see if it matches a region name
                // (we just return the first culture we match) 
                CultureInfo[] specifics = SpecificCultures; 
                for (int i = 0; i < specifics.Length; i++)
                { 
                    if (String.Compare(specifics[i].m_cultureData.SREGIONNAME, cultureName, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        // Matched, use this culture
                        retVal = specifics[i].m_cultureData; 
                        break;
                    } 
                } 
            }
 
            // If we found one we can use, then cash it for next time
            if (retVal != null && (retVal.IsNeutralCulture == false))
            {
                // first add it to the cache 
                lock (((ICollection)tempHashTable).SyncRoot)
                { 
                    tempHashTable[hashName] = retVal; 
                }
 
                // Copy the hashtable to the corresponding member variables.  This will potentially overwrite
                // new tables simultaneously created by a new thread, but maximizes thread safety.
                s_cachedRegions = tempHashTable;
            } 
            else
            { 
                // Unable to find a matching culture/region, return null or neutral 
                // (regionInfo throws a more specific exception on neutrals)
                retVal = neutral; 
            }

            // Return the found culture to use, null, or the neutral culture.
            return retVal; 
        }
#endif 
 
#if FEATURE_USE_LCID
        // Obtain locale name from LCID 
        // NOTE: This will get neutral names, unlike the OS API
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern String LCIDToLocaleName(int lcid);
 
        // We'd rather people use the named version since this doesn't allow custom locales 
        internal static CultureData GetCultureData(int culture, bool bUseUserOverride)
        { 
            String localeName = null;
            CultureData retVal = null;

#if !FEATURE_CORECLR 
            // If V2 legacy sort is requested, then provide deprecated alternate sorts
            if (CompareInfo.IsLegacy20SortingBehaviorRequested) 
            { 
                switch (culture)
                { 
                    case 0x00010412:
                        localeName = "ko-KR_unicod";
                        break;
                    case 0x00010411: 
                        localeName = "ja-JP_unicod";
                        break; 
                    case 0x00020c04: 
                        localeName = "zh-HK_stroke";
                        break; 
                }
            }
#endif
 
            if (localeName == null)
            { 
                // Convert the lcid to a name, then use that 
                // Note that this'll return neutral names (unlike Vista native API)
                localeName = LCIDToLocaleName(culture); 
            }

            // If its not valid, then throw
            if (String.IsNullOrEmpty(localeName)) 
            {
                // Could be valid for Invariant 
                if (culture == 0x007f) 
                    return Invariant;
            } 
            else
            {
#if !FEATURE_CORECLR
                switch (localeName) 
                {
                    // for compatibility with Whidbey, when requesting 
                    // a locale from LCID, return the old localeName 
                    case "zh-Hans":
                        localeName = "zh-CHS"; 
                        break;
                    case "zh-Hant":
                        localeName = "zh-CHT";
                        break; 
                }
#endif 
                // Valid name, use it 
                retVal = GetCultureData(localeName, bUseUserOverride);
            } 

            // If not successful, throw
            if (retVal == null)
                throw new CultureNotFoundException( 
                    "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            // Return the one we found 
            return retVal;
        } 
#endif

        // Clear our internal caches
        internal static void ClearCachedData() 
        {
            s_cachedCultures = null; 
#if !FEATURE_CORECLR 
            s_cachedRegions = null;
            s_replacementCultureNames = null; 
#endif
        }

#if !FEATURE_CORECLR && !CORIOLIS 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static CultureInfo[] GetCultures(CultureTypes types) 
        { 
            // Disable  warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
#pragma warning disable 618 
            // Validate flags
            if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures |
                                                            CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture |
                                                            CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | 
                                                            CultureTypes.FrameworkCultures)) != 0)
            { 
                throw new ArgumentOutOfRangeException( 
                                "types",
                                String.Format( 
                                    CultureInfo.CurrentCulture,
                                    Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures));
            }
 
            //
            // CHANGE FROM Whidbey 
            // 
            // We have deprecated CultureTypes.FrameworkCultures.
            // When this enum is used, we will enumerate Whidbey framework cultures (for compatability). 
            //

            // We have deprecated CultureTypes.WindowsOnlyCultures.
            // When this enum is used, we will return an empty array for this enum. 
            if ((types & CultureTypes.WindowsOnlyCultures) != 0)
            { 
                // Remove the enum as it is an no-op. 
                types &= (~CultureTypes.WindowsOnlyCultures);
            } 

            String[] cultureNames = null;

            // 
            // Call nativeEnumCultureNames() to get a string array of culture names based on the specified
            // enumeration type. 
            // 
            // nativeEnumCulturNames is a QCall.  We need to use a reference to return the string array
            // allocated from the QCall.  That ref has to be wrapped as object handle. 
            // See vm\qcall.h for details in QCall.
            //

            if (nativeEnumCultureNames((int)types, JitHelpers.GetObjectHandleOnStack(ref cultureNames)) == 0) 
            {
                return new CultureInfo[0]; 
            } 

            int arrayLength = cultureNames.Length; 

            if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
            {
                arrayLength += 2; 
            }
 
            CultureInfo[] cultures = new CultureInfo[arrayLength]; 

            for (int i = 0; i < cultureNames.Length; i++) 
            {
                cultures[i] = new CultureInfo(cultureNames[i]);
            }
 
            if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
            { 
                Contract.Assert(arrayLength == cultureNames.Length + 2, "CultureData.nativeEnumCultureNames() Incorrect array size"); 
                cultures[cultureNames.Length] = new CultureInfo("zh-CHS");
                cultures[cultureNames.Length + 1] = new CultureInfo("zh-CHT"); 
            }

#pragma warning restore 618
 
            return cultures;
        } 
 
        internal static CultureInfo[] specificCultures;
 
        private static CultureInfo[] SpecificCultures
        {
            get
            { 
                if (specificCultures == null)
                    specificCultures = GetCultures(CultureTypes.SpecificCultures); 
 
                return specificCultures;
            } 
        }


        internal bool IsReplacementCulture 
        {
            get 
            { 
                return IsReplacementCultureName(this.SNAME);
            } 
        }

        internal static String[] s_replacementCultureNames;
 
        ////////////////////////////////////////////////////////////////////////
        // 
        // Cache for the known replacement cultures. 
        // This is used by CultureInfo.CultureType to check if a culture is a
        // replacement culture. 
        //
        ////////////////////////////////////////////////////////////////////////

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static bool IsReplacementCultureName(String name) 
        { 
            Contract.Assert(name != null, "IsReplacementCultureName(): name should not be null");
            String[] replacementCultureNames = s_replacementCultureNames; 
            if (replacementCultureNames == null)
            {
                if (nativeEnumCultureNames((int)CultureTypes.ReplacementCultures, JitHelpers.GetObjectHandleOnStack(ref replacementCultureNames)) == 0)
                { 
                    return false;
                } 
 
                // Even if we don't have any replacement cultures, the returned replacementCultureNames will still an empty string array, not null.
                Contract.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null"); 
                Array.Sort(replacementCultureNames);
                s_replacementCultureNames = replacementCultureNames;
            }
            return Array.BinarySearch(replacementCultureNames, name) >= 0; 
        }
#endif 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  All the accessors
        //
        //  Accessors for our data object items
        // 
        ////////////////////////////////////////////////////////////////////////
 
        /////////// 
        // Identity //
        /////////// 

        // The real name used to construct the locale (ie: de-DE_phoneb)
        internal String CultureName
        { 
            get
            { 
                Contract.Assert(this.sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                // since windows doesn't know about zh-CHS and zh-CHT,
                // we leave sRealName == zh-Hanx but we still need to 
                // pretend that it was zh-CHX.
                switch (this.sName)
                {
                    case "zh-CHS": 
                    case "zh-CHT":
                        return this.sName; 
                } 
                return this.sRealName;
            } 
        }

        // Are overrides enabled?
        internal bool UseUserOverride 
        {
            get 
            { 
                return this.bUseOverrides;
            } 
        }

        // locale name (ie: de-DE, NO sort information)
        internal String SNAME 
        {
            get 
            { 
                //                Contract.Assert(this.sName != null,
                //                    "[CultureData.SNAME] Expected this.sName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                if (this.sName == null)
                {
                    this.sName = String.Empty;
                } 
                return this.sName;
            } 
        } 

        // Parent name (which may be a custom locale/culture) 
        internal String SPARENT
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sParent == null) 
                { 
                    // Ask using the real name, so that we get parents of neutrals
                    this.sParent = DoGetLocaleInfo(this.sRealName, LOCALE_SPARENT); 

#if !FEATURE_CORECLR
                    // for compatibility, the chain should be:
                    // zh-CN -> zh-CHS -> zh-Hans -> zh 
                    // zh-TW -> zh-CHT -> zh-Hant -> zh
                    Contract.Assert(this.sName != "zh-CHS" && this.sName != "zh-CHT", 
                                    "sParent should have been initialized for zh-CHS and zh-CHT when they were constructed, otherwise we get recursion"); 
                    switch (this.sParent)
                    { 
                        case "zh-Hans":
                            this.sParent = "zh-CHS";
                            break;
                        case "zh-Hant": 
                            this.sParent = "zh-CHT";
                            break; 
                    } 
#endif
 
                }
                return this.sParent;
            }
        } 

        // Localized pretty name for this locale (ie: Inglis (estados Unitos)) 
        internal String SLOCALIZEDDISPLAYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sLocalizedDisplayName == null)
                { 
#if !FEATURE_CORECLR
                    if (this.IsUserCustomCulture && !CultureData.IsReplacementCultureName(this.SNAME)) 
                    { 
                        if (this.IsNeutralCulture)
                        { 
                            this.sLocalizedDisplayName = this.SNATIVELANGUAGE;
                        }
                        else
                        { 
                            this.sLocalizedDisplayName = this.SNATIVEDISPLAYNAME;
                        } 
                    } 
                    else
                    { 
                        String resourceKey = "Globalization.ci_" + this.sName;
                        if (IsResourcePresent(resourceKey))
                        {
                            this.sLocalizedDisplayName = Environment.GetResourceString(resourceKey); 
                        }
                    } 
#endif 
                    // If it hasn't been found (Windows 8 and up), fallback to the system
                    if (String.IsNullOrEmpty(this.sLocalizedDisplayName)) 
                    {
                        // If its neutral use the language name
                        if (this.IsNeutralCulture)
                        { 
                            this.sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE;
                        } 
                        else 
                        {
                            // We have to make the neutral distinction in case the OS returns a specific name 
                            if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name))
                            {
                                this.sLocalizedDisplayName = DoGetLocaleInfo(LOCALE_SLOCALIZEDDISPLAYNAME);
                            } 
                            if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
                            { 
                                this.sLocalizedDisplayName = this.SNATIVEDISPLAYNAME; 
                            }
                        } 
                    }
                }

                return this.sLocalizedDisplayName; 
            }
        } 
 
        // English pretty name for this locale (ie: English (United States))
        internal String SENGDISPLAYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated
            get
            { 
                if (this.sEnglishDisplayName == null)
                { 
                    // If its neutral use the language name 
                    if (this.IsNeutralCulture)
                    { 
                        this.sEnglishDisplayName = this.SENGLISHLANGUAGE;
#if !FEATURE_CORECLR
                        // differentiate the legacy display names
                        switch (this.sName) 
                        {
                            case "zh-CHS": 
                            case "zh-CHT": 
                                this.sEnglishDisplayName += " Legacy";
                                break; 
                        }
#endif

                    } 
                    else
                    { 
                        this.sEnglishDisplayName = DoGetLocaleInfo(LOCALE_SENGLISHDISPLAYNAME); 

                        // if it isn't found build one: 
                        if (String.IsNullOrEmpty(this.sEnglishDisplayName))
                        {
                            // Our existing names mostly look like:
                            // "English" + "United States" -> "English (United States)" 
                            // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
                            if (this.SENGLISHLANGUAGE.EndsWith(')')) 
                            { 
                                // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
                                this.sEnglishDisplayName = 
                                    this.SENGLISHLANGUAGE.Substring(0, this.sEnglishLanguage.Length - 1) +
                                    ", " + this.SENGCOUNTRY + ")";
                            }
                            else 
                            {
                                // "English" + "United States" -> "English (United States)" 
                                this.sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")"; 
                            }
                        } 
                    }
                }
                return this.sEnglishDisplayName;
            } 
        }
 
        // Native pretty name for this locale (ie: Deutsch (Deutschland)) 
        internal String SNATIVEDISPLAYNAME
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sNativeDisplayName == null) 
                {
                    // If its neutral use the language name 
                    if (this.IsNeutralCulture) 
                    {
                        this.sNativeDisplayName = this.SNATIVELANGUAGE; 
#if !FEATURE_CORECLR
                        // differentiate the legacy display names
                        switch (this.sName)
                        { 
                            case "zh-CHS":
                                this.sNativeDisplayName += " \u65E7\u7248"; 
                                break; 
                            case "zh-CHT":
                                this.sNativeDisplayName += " \u820A\u7248"; 
                                break;
                        }
#endif
                    } 
                    else
                    { 
#if !FEATURE_CORECLR 
                        if (IsIncorrectNativeLanguageForSinhala())
                        { 
                            // work around bug in Windows 7 for native name of Sinhala
                            this.sNativeDisplayName ="\x0dc3\x0dd2\x0d82\x0dc4\x0dbd (\x0DC1\x0DCA\x200D\x0DBB\x0DD3\x0020\x0DBD\x0D82\x0D9A\x0DCF)";
                        }
                        else 
#endif
                        { 
                            this.sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME); 
                        }
 
                        // if it isn't found build one:
                        if (String.IsNullOrEmpty(this.sNativeDisplayName))
                        {
                            // These should primarily be "Deutsch (Deutschland)" type names 
                            this.sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")";
                        } 
                    } 
                }
                return this.sNativeDisplayName; 
            }
        }

        // The culture name to be used in CultureInfo.CreateSpecificCulture() 
        internal String SSPECIFICCULTURE
        { 
            get 
            {
                // This got populated when ComNlsInfo::nativeInitCultureData told us we had a culture 
                Contract.Assert(this.sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already");
                return this.sSpecificCulture;
            }
        } 

        ///////////// 
        // Language // 
        /////////////
 
        // iso 639 language name, ie: en
        internal String SISO639LANGNAME
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sISO639Language == null) 
                {
                    this.sISO639Language = DoGetLocaleInfo(LOCALE_SISO639LANGNAME); 
                }
                return this.sISO639Language;
            }
        } 

#if !FEATURE_CORECLR 
        // iso 639 language name, ie: eng 
        internal String SISO639LANGNAME2
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sISO639Language2 == null) 
                {
                    this.sISO639Language2 = DoGetLocaleInfo(LOCALE_SISO639LANGNAME2); 
                } 
                return this.sISO639Language2;
            } 
        }

        // abbreviated windows language name (ie: enu) (non-standard, avoid this)
        internal String SABBREVLANGNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sAbbrevLang == null) 
                {
                    this.sAbbrevLang = DoGetLocaleInfo(LOCALE_SABBREVLANGNAME);
                }
                return this.sAbbrevLang; 
            }
        } 
#endif 

        // Localized name for this language (Windows Only) ie: Inglis 
        // This is only valid for Windows 8 and higher neutrals:
        internal String SLOCALIZEDLANGUAGE
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sLocalizedLanguage == null) 
                {
                    if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) 
                    {
                        this.sLocalizedLanguage = DoGetLocaleInfo(LOCALE_SLOCALIZEDLANGUAGENAME);
                    }
                    // Some OS's might not have this resource or LCTYPE 
                    if (String.IsNullOrEmpty(this.sLocalizedLanguage))
                    { 
                        this.sLocalizedLanguage = SNATIVELANGUAGE; 
                    }
                } 

                return this.sLocalizedLanguage;
            }
        } 

        // English name for this language (Windows Only) ie: German 
        internal String SENGLISHLANGUAGE 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sEnglishLanguage == null)
                { 
                    this.sEnglishLanguage = DoGetLocaleInfo(LOCALE_SENGLISHLANGUAGENAME);
                } 
                return this.sEnglishLanguage; 
            }
        } 

        // Native name of this language (Windows Only) ie: Deutsch
        internal String SNATIVELANGUAGE
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            { 
                if (this.sNativeLanguage == null)
                { 
#if !FEATURE_CORECLR
                    if (IsIncorrectNativeLanguageForSinhala())
                    {
                        // work around bug in Windows 7 for native language of Sinhala 
                        this.sNativeLanguage = "\x0dc3\x0dd2\x0d82\x0dc4\x0dbd";
                    } 
                    else 
#endif
                    { 
                        this.sNativeLanguage = DoGetLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
                    }
                }
                return this.sNativeLanguage; 
            }
        } 
 
#if !FEATURE_CORECLR
        private bool IsIncorrectNativeLanguageForSinhala() 
        {
            return IsOsWin7OrPrior()
                && (sName == "si-LK" || sName == "si")
                && !IsReplacementCulture; 
        }
#endif 
 
        ///////////
        // Region // 
        ///////////

        // region name (eg US)
        internal String SREGIONNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sRegionName == null) 
                {
                    this.sRegionName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME);
                }
                return this.sRegionName; 
            }
        } 
 
        // (user can override) ---- code (RegionInfo)
#if !FEATURE_CORECLR 
        internal int ICOUNTRY
        {
            get
            { 
                return DoGetLocaleInfoInt(LOCALE_ICOUNTRY);
            } 
        } 
#endif
 
        // GeoId
        internal int IGEOID
        {
            get 
            {
                if (this.iGeoId == undef) 
                { 
                    this.iGeoId = DoGetLocaleInfoInt(LOCALE_IGEOID);
                } 
                return this.iGeoId;
            }
        }
 
        // localized name for the ----
        internal string SLOCALIZED---- 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sLocalized---- == null)
                {
#if !FEATURE_CORECLR 
                    if (this.IsUserCustomCulture && !CultureData.IsReplacementCultureName(this.SNAME))
                    { 
                        this.sLocalized---- = SNATIVECOUNTRY; 
                    }
                    else 
                    {
                        String resourceKey = "Globalization.ri_" + this.SREGIONNAME;
                        if (IsResourcePresent(resourceKey))
                        { 
                            this.sLocalized---- = Environment.GetResourceString(resourceKey);
                        } 
                    } 
#endif
                    // If it hasn't been found (Windows 8 and up), fallback to the system 
                    if (String.IsNullOrEmpty(this.sLocalized----))
                    {
                        // We have to make the neutral distinction in case the OS returns a specific name
                        if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name)) 
                        {
                            this.sLocalized---- = DoGetLocaleInfo(LOCALE_SLOCALIZEDCOUNTRYNAME); 
                        } 
                        if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
                        { 
                            this.sLocalized---- = SNATIVECOUNTRY;
                        }
                    }
                } 
                return this.sLocalized----;
            } 
        } 

        // english ---- name (RegionInfo) ie: Germany 
        internal String SENGCOUNTRY
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sEnglishCountry == null) 
                { 
                    this.sEnglishCountry = DoGetLocaleInfo(LOCALE_SENGLISHCOUNTRYNAME);
                } 
                return this.sEnglishCountry;
            }
        }
 
        // native ---- name (RegionInfo) ie: Deutschland
        internal String SNATIVECOUNTRY 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sNativeCountry == null)
                {
                    this.sNativeCountry = DoGetLocaleInfo(LOCALE_SNATIVECOUNTRYNAME); 
                }
                return this.sNativeCountry; 
            } 
        }
 
        // ISO 3166 ---- Name
        internal String SISO3166CTRYNAME
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sISO3166CountryName == null) 
                {
                    this.sISO3166CountryName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME); 
                }
                return this.sISO3166CountryName;
            }
        } 

#if !FEATURE_CORECLR 
        // ISO 3166 ---- Name 
        internal String SISO3166CTRYNAME2
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sISO3166CountryName2 == null) 
                {
                    this.sISO3166CountryName2 = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME2); 
                } 
                return this.sISO3166CountryName2;
            } 
        }

        // abbreviated ---- Name (windows version, non-standard, avoid)
        internal String SABBREVCTRYNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sAbbrevCountry == null) 
                {
                    this.sAbbrevCountry = DoGetLocaleInfo(LOCALE_SABBREVCTRYNAME);
                }
                return this.sAbbrevCountry; 
            }
        } 
 
#if !FEATURE_CORECLR
        // Default ---- 
        private int IDEFAULT----
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                return DoGetLocaleInfoInt(LOCALE_IDEFAULT----); 
            } 
        }
#endif 

        // Console fallback name (ie: locale to use for console apps for unicode-only locales)
        internal int IINPUTLANGUAGEHANDLE
        { 
            get
            { 
                if (this.iInputLanguageHandle == undef) 
                {
                    if (IsUserCustomCulture) 
                    {
                        //
                        this.iInputLanguageHandle = 0x0409;
                    } 
                    else
                    { 
                        // Input Language is same as LCID for built-in cultures 
                        this.iInputLanguageHandle = this.ILANGUAGE;
                    } 
                }
                return this.iInputLanguageHandle;
            }
        } 

        // Console fallback name (ie: locale to use for console apps for unicode-only locales) 
        internal String SCONSOLEFALLBACKNAME 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sConsoleFallbackName == null)
                { 
                    string consoleFallbackName = DoGetLocaleInfo(LOCALE_SCONSOLEFALLBACKNAME);
                    if (consoleFallbackName == "es-ES_tradnl") 
                    { 
                        consoleFallbackName = "es-ES";
                    } 
                    this.sConsoleFallbackName = consoleFallbackName;
                }
                return this.sConsoleFallbackName;
            } 
        }
#endif 
 
        /////////////
        // Numbers // 
        ////////////

        //                internal String sPositiveSign            ; // (user can override) positive sign
        //                internal String sNegativeSign            ; // (user can override) negative sign 
        //                internal String[] saNativeDigits         ; // (user can override) native characters for digits 0-9
        //                internal int iDigitSubstitution       ; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only) 
        //                internal int iDigits                  ; // (user can override) number of fractional digits 
        //                internal int iNegativeNumber          ; // (user can override) negative number format
 
#if !FEATURE_CORECLR
        // Leading zeroes
        private bool ILEADINGZEROS
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            { 
                return (DoGetLocaleInfoInt(LOCALE_ILZERO) == 1);
            } 
        }
#endif

 
        // (user can override) grouping of digits
        internal int[] WAGROUPING 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.waGrouping == null || UseUserOverride)
                {
                    this.waGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SGROUPING)); 
                }
                return this.waGrouping; 
            } 
        }
 

        //                internal String sDecimalSeparator        ; // (user can override) decimal separator
        //                internal String sThousandSeparator       ; // (user can override) thousands separator
 
        // Not a Number
        internal String SNAN 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sNaN == null || UseUserOverride)
                {
                    this.sNaN = DoGetLocaleInfo(LOCALE_SNAN); 
                }
                return this.sNaN; 
            } 
        }
 
        // + Infinity
        internal String SPOSINFINITY
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sPositiveInfinity == null || UseUserOverride) 
                {
                    this.sPositiveInfinity = DoGetLocaleInfo(LOCALE_SPOSINFINITY); 
                }
                return this.sPositiveInfinity;
            }
        } 

        // - Infinity 
        internal String SNEGINFINITY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sNegativeInfinity == null || UseUserOverride)
                { 
                    this.sNegativeInfinity = DoGetLocaleInfo(LOCALE_SNEGINFINITY);
                } 
                return this.sNegativeInfinity; 
            }
        } 


        ////////////
        // Percent // 
        ///////////
 
        // Negative Percent (0-3) 
        internal int INEGATIVEPERCENT
        { 
            get
            {
                if (this.iNegativePercent == undef || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code
                    this.iNegativePercent = DoGetLocaleInfoInt(LOCALE_INEGATIVEPERCENT); 
                } 
                return this.iNegativePercent;
            } 
        }

        // Positive Percent (0-11)
        internal int IPOSITIVEPERCENT 
        {
            get 
            { 
                if (this.iPositivePercent == undef || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code
                    this.iPositivePercent = DoGetLocaleInfoInt(LOCALE_IPOSITIVEPERCENT);
                }
                return this.iPositivePercent; 
            }
        } 
 
        // Percent (%) symbol
        internal String SPERCENT 
        {
            [System.Security.SecurityCritical]  // auto-generated
            get
            { 
                if (this.sPercent == null || UseUserOverride)
                { 
                    // Note that <= Windows Vista this is synthesized by native code 
                    this.sPercent = DoGetLocaleInfo(LOCALE_SPERCENT);
                } 
                return this.sPercent;
            }
        }
 
        // PerMille (‰) symbol
        internal String ----ILLE 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sPerMille == null || UseUserOverride)
                {
                    // Note that <= Windows Vista this is synthesized by native code 
                    this.sPerMille = DoGetLocaleInfo(LOCALE_----ILLE);
                } 
                return this.sPerMille; 
            }
        } 

        /////////////
        // Currency //
        ///////////// 

        // (user can override) local monetary symbol, eg: $ 
        internal String SCURRENCY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            {
                if (this.sCurrency == null || UseUserOverride)
                { 
                    this.sCurrency = DoGetLocaleInfo(LOCALE_SCURRENCY);
                } 
                return this.sCurrency; 
            }
        } 

        // international monetary symbol (RegionInfo), eg: USD
        internal String SINTLSYMBOL
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            { 
                if (this.sIntlMonetarySymbol == null || UseUserOverride)
                { 
                    this.sIntlMonetarySymbol = DoGetLocaleInfo(LOCALE_SINTLSYMBOL);
                }
                return this.sIntlMonetarySymbol;
            } 
        }
 
        // English name for this currency (RegionInfo), eg: US Dollar 
        internal String SENGLISHCURRENCY
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get
            {
                if (this.sEnglishCurrency == null) 
                {
                    this.sEnglishCurrency = DoGetLocaleInfo(LOCALE_SENGCURRNAME); 
                } 
                return this.sEnglishCurrency;
            } 
        }

        // Native name for this currency (RegionInfo), eg: Schweiz Frank
        internal String SNATIVECURRENCY 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.sNativeCurrency == null) 
                {
                    this.sNativeCurrency = DoGetLocaleInfo(LOCALE_SNATIVECURRNAME);
                }
                return this.sNativeCurrency; 
            }
        } 
 
        //                internal int iCurrencyDigits          ; // (user can override) # local monetary fractional digits
        //                internal int iCurrency                ; // (user can override) positive currency format 
        //                internal int iNegativeCurrency        ; // (user can override) negative currency format

        // (user can override) monetary grouping of digits
        internal int[] WAMONGROUPING 
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get 
            {
                if (this.waMonetaryGrouping == null || UseUserOverride) 
                {
                    this.waMonetaryGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SMONGROUPING));
                }
                return this.waMonetaryGrouping; 
            }
        } 
 
        //                internal String sMonetaryDecimal         ; // (user can override) monetary decimal separator
        //                internal String sMonetaryThousand        ; // (user can override) monetary thousands separator 

        /////////
        // Misc //
        ///////// 

        // (user can override) system of measurement 0=metric, 1=US (RegionInfo) 
        internal int IMEASURE 
        {
            get 
            {
                if (this.iMeasure == undef || UseUserOverride)
                {
                    this.iMeasure = DoGetLocaleInfoInt(LOCALE_IMEASURE); 
                }
                return this.iMeasure; 
            } 
        }
 
        // (user can override) list Separator
        internal String SLIST
        {
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sListSeparator == null || UseUserOverride) 
                {
                    this.sListSeparator = DoGetLocaleInfo(LOCALE_SLIST); 
                }
                return this.sListSeparator;
            }
        } 

#if !FEATURE_CORECLR 
        // Paper size 
        private int IPAPERSIZE
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            {
                return DoGetLocaleInfoInt(LOCALE_IPAPERSIZE); 
            }
        } 
#endif 

        //////////////////////////// 
        // Calendar/Time (Gregorian) //
        ////////////////////////////

        // (user can override) AM designator 
        internal String SAM1159
        { 
            [System.Security.SecurityCritical]  // auto-generated 
            get
            { 
                if (this.sAM1159 == null || UseUserOverride)
                {
                    this.sAM1159 = DoGetLocaleInfo(LOCALE_S1159);
                } 
                return this.sAM1159;
            } 
        } 

        // (user can override) PM designator 
        internal String SPM2359
        {
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                if (this.sPM2359 == null || UseUserOverride) 
                { 
                    this.sPM2359 = DoGetLocaleInfo(LOCALE_S2359);
                } 
                return this.sPM2359;
            }
        }
 
        // (user can override) time format
        internal String[] LongTimes 
        { 
            get
            { 
                if (this.saLongTimes == null || UseUserOverride)
                {
                    String[] longTimes = DoEnumTimeFormats();
                    if (longTimes == null || longTimes.Length == 0) 
                    {
                        this.saLongTimes = Invariant.saLongTimes; 
                    } 
                    else
                    { 
                        this.saLongTimes = longTimes;
                    }
                }
                return this.saLongTimes; 
            }
        } 
 
        // short time format
        // Short times (derived from long times format) 
        //
        internal String[] ShortTimes
        {
            get 
            {
                if (this.saShortTimes == null || UseUserOverride) 
                { 
                    // Try to get the short times from the OS/culture.dll
                    String[] shortTimes = null; 
#if !__APPLE__
                    shortTimes = DoEnumShortTimeFormats();
#endif // !__APPLE__
 
                    if (shortTimes == null || shortTimes.Length == 0)
                    { 
                        // 
                        // If we couldn't find short times, then compute them from long times
                        // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll) 
                        //
                        shortTimes = DeriveShortTimesFromLong();
                    }
 
                    /* The above logic doesn't make sense on Mac, since the OS can provide us a "short time pattern".
                     * currently this is the 4th element in the array returned by LongTimes.  We'll add this to our array 
                     * if it doesn't exist. 
                     */
                    shortTimes = AdjustShortTimesForMac(shortTimes); 

                    // Found short times, use them
                    this.saShortTimes = shortTimes;
                } 
                return this.saShortTimes;
            } 
        } 

        private string[] AdjustShortTimesForMac(string[] shortTimes) 
        {
#if __APPLE__
            /*
             * NOTE: This code depends on the data from the OS being returned in a *specific* order.  The 
             * short time pattern must be the 4th element in the 4 element array returned by the data.  If
             * change the way the data is returned from the OS be sure to update this code. 
             */ 

            string[] longTimes = (string[])LongTimes.Clone(); 
            Contract.Assert(longTimes.Length == 4, "[System.Globalization.CultureData] LongTimes does not have exactly 4");

            if (longTimes.Length == 4) {
                string shortTimePattern = longTimes[3]; 
                int foundIndex = -1;
                for (int i = 0; i < shortTimes.Length; i++) { 
                    if (shortTimePattern.Equals(shortTimes[i])) { 
                        foundIndex = i;
                        break; 
                    }
                }

                if (foundIndex == -1) { 
                    // The OS short time didn't exist in the list we constructed, add it.
                    string[] t = new string[shortTimes.Length + 1]; 
                    t[0] = shortTimePattern; 
                    Array.Copy(shortTimes, 0, t, 1, shortTimes.Length);
                    shortTimes = t; 
                } else {
                    // The OS short time did exist, move it to the front.
                    string t = shortTimes[0];
                    shortTimes[0] = shortTimes[foundIndex]; 
                    shortTimes[foundIndex] = t;
                } 
            } 
#endif // __APPLE__
            return shortTimes; 
        }

        private string[] DeriveShortTimesFromLong()
        { 
            // Our logic is to look for h,H,m,s,t.  If we find an s, then we check the string
            // between it and the previous marker, if any.  If its a short, unescaped separator, 
            // then we don't retain that part. 
            // We then check after the ss and remove anything before the next h,H,m,t...
            string[] shortTimes = new string[LongTimes.Length]; 

            for (int i = 0; i < LongTimes.Length; i++)
            {
                shortTimes[i] = StripSecondsFromPattern(LongTimes[i]); 
            }
            return shortTimes; 
        } 

        private static string StripSecondsFromPattern(string time) 
        {
            bool bEscape = false;
            int iLastToken = -1;
 
            // Find the seconds
            for (int j = 0; j < time.Length; j++) 
            { 
                // Change escape mode?
                if (time[j] == '\'') 
                {
                    // Continue
                    bEscape = !bEscape;
                    continue; 
                }
 
                // See if there was a single \ 
                if (time[j] == '\\')
                { 
                    // Skip next char
                    j++;
                    continue;
                } 

                if (bEscape) 
                { 
                    continue;
                } 

                switch (time[j])
                {
                    // Check for seconds 
                    case 's':
                        // Found seconds, see if there was something unescaped and short between 
                        // the last marker and the seconds.  Windows says separator can be a 
                        // maximum of three characters (without null)
                        // If 1st or last characters were ', then ignore it 
                        if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 &&
                            (time[iLastToken + 1] != '\'') &&
                            (time[j - 1] != '\''))
                        { 
                            // There was something there we want to remember
                            if (iLastToken >= 0) 
                            { 
                                j = iLastToken + 1;
                            } 
                        }

                        bool containsSpace;
                        int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace); 
                        StringBuilder sb = new StringBuilder(time.Substring(0, j));
                        if (containsSpace) 
                        { 
                            sb.Append(' ');
                        } 
                        sb.Append(time.Substring(endIndex));
                        time = sb.ToString();
                        break;
                    case 'm': 
                    case 'H':
                    case 'h': 
                        iLastToken = j; 
                        break;
                } 
            }
            return time;
        }
 
        private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace)
        { 
            bool bEscape = false; 
            containsSpace = false;
            for (; index < time.Length; index++) 
            {
                switch (time[index])
                {
                    case '\'': 
                        bEscape = !bEscape;
                        continue; 
                    case '\\': 
                        index++;
                        if (time[index] == ' ') 
                        {
                            containsSpace = true;
                        }
                        continue; 
                    case ' ':
                        containsSpace = true; 
                        break; 
                    case 't':
                    case 'm': 
                    case 'H':
                    case 'h':
                        if (bEscape)
                        { 
                            continue;
                        } 
                        return index; 
                }
            } 
            containsSpace = false;
            return index;
        }
 
        // time duration format
        internal String[] SADURATION 
        { 
            [System.Security.SecurityCritical]  // auto-generated
            get 
            {
                //
                if (this.saDurationFormats == null || UseUserOverride)
                { 
                    String durationFormat = DoGetLocaleInfo(LOCALE_SDURATION);
                    this.saDurationFormats = new String[] { ReescapeWin32String(durationFormat) }; 
                } 
                return this.saDurationFormats;
            } 
        }

        // (user can override) first day of week
        internal int IFIRSTDAYOFWEEK 
        {
            get 
            { 
                if (this.iFirstDayOfWeek == undef || UseUserOverride)
                { 
                    // Have to convert it from windows to .Net formats
                    this.iFirstDayOfWeek = ConvertFirstDayOfWeekMonToSun(DoGetLocaleInfoInt(LOCALE_IFIRSTDAYOFWEEK));
                }
                return this.iFirstDayOfWeek; 
            }
        } 
 
        // (user can override) first week of year
        internal int IFIRSTWEEKOFYEAR 
        {
            get
            {
                if (this.iFirstWeekOfYear == undef || UseUserOverride) 
                {
                    this.iFirstWeekOfYear = DoGetLocaleInfoInt(LOCALE_IFIRSTWEEKOFYEAR); 
                } 
                return this.iFirstWeekOfYear;
            } 
        }

        // (user can override default only) short date format
        internal String[] ShortDates(int calendarId) 
        {
            return GetCalendar(calendarId).saShortDates; 
        } 

        // (user can override default only) long date format 
        internal String[] LongDates(int calendarId)
        {
            return GetCalendar(calendarId).saLongDates;
        } 

        // (user can override) date year/month format. 
        internal String[] YearMonths(int calendarId) 
        {
            return GetCalendar(calendarId).saYearMonths; 
        }

        // day names
        internal string[] DayNames(int calendarId) 
        {
            return GetCalendar(calendarId).saDayNames; 
        } 

        // abbreviated day names 
        internal string[] AbbreviatedDayNames(int calendarId)
        {
            // Get abbreviated day names for this calendar from the OS if necessary
            return GetCalendar(calendarId).saAbbrevDayNames; 
        }
 
        // The super short day names 
        internal string[] SuperShortDayNames(int calendarId)
        { 
            return GetCalendar(calendarId).saSuperShortDayNames;
        }

        // month names 
        internal string[] MonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saMonthNames; 
        }
 
        // Genitive month names
        internal string[] GenitiveMonthNames(int calendarId)
        {
            return GetCalendar(calendarId).saMonthGenitiveNames; 
        }
 
        // month names 
        internal string[] AbbreviatedMonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saAbbrevMonthNames;
        }

        // Genitive month names 
        internal string[] AbbreviatedGenitiveMonthNames(int calendarId)
        { 
            return GetCalendar(calendarId).saAbbrevMonthGenitiveNames; 
        }
 
        // Leap year month names
        // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name
        // the non-leap names skip the 7th name in the normal month name array
        internal string[] LeapYearMonthNames(int calendarId) 
        {
            return GetCalendar(calendarId).saLeapYearMonthNames; 
        } 

        // month/day format (single string, no override) 
        internal String MonthDay(int calendarId)
        {
            return GetCalendar(calendarId).sMonthDay;
        } 

 
 
        /////////////
        // Calendars // 
        /////////////

        // all available calendar type(s), The first one is the default calendar.
        internal int[] CalendarIds 
        {
            get 
            { 
                if (this.waCalendars == null)
                { 
                    // We pass in an array of ints, and native side fills it up with count calendars.
                    // We then have to copy that list to a new array of the right size.
                    // Default calendar should be first
                    // 
                    int[] calendarInts = new int[23];
                    Contract.Assert(this.sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                    int count = CalendarData.nativeGetCalendars(this.sWindowsName, this.bUseOverrides, calendarInts); 

                    // See if we had a calendar to add. 
                    if (count == 0)
                    {
                        // Failed for some reason, just grab Gregorian from Invariant
                        this.waCalendars = Invariant.waCalendars; 
                    }
                    else 
                    { 
                        // The OS may not return calendar 4 for zh-TW, but we've always allowed it.
                        // 
                        if (this.sWindowsName == "zh-TW")
                        {
                            bool found = false;
 
                            // Do we need to insert calendar 4?
                            for (int i = 0; i < count; i++) 
                            { 
                                // Stop if we found calendar four
                                if (calendarInts[i] == Calendar.CAL_TAIWAN) 
                                {
                                    found = true;
                                    break;
                                } 
                            }
 
                            // If not found then insert it 
                            if (!found)
                            { 
                                // Insert it as the 2nd calendar
                                count++;
                                // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added.
                                Array.Copy(calendarInts, 1, calendarInts, 2, 23 - 1 - 1); 
                                calendarInts[1] = Calendar.CAL_TAIWAN;
                            } 
                        } 

                        // It worked, remember the list 
                        int[] temp = new int[count];
                        Array.Copy(calendarInts, temp, count);

                        // Want 1st calendar to be default 
                        // Prior to Vista the enumeration didn't have default calendar first
                        // Only a coreclr concern, culture.dll does the right thing. 
#if FEATURE_CORECLR 
                        if (temp.Length > 1)
                        { 
                            int i = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
                            if (temp[1] == i)
                            {
                                temp[1] = temp[0]; 
                                temp[0] = i;
                            } 
                        } 
#endif
 
                        this.waCalendars = temp;
                    }
                }
 
                return this.waCalendars;
            } 
        } 

        // Native calendar names.  index of optional calendar - 1, empty if no optional calendar at that number 
        internal String CalendarName(int calendarId)
        {
            // Get the calendar
            return GetCalendar(calendarId).sNativeName; 
        }
 
        internal CalendarData GetCalendar(int calendarId) 
        {
            Contract.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS, 
                "[CultureData.GetCalendar] Expect calendarId to be in a valid range");

            // arrays are 0 based, calendarIds are 1 based
            int calendarIndex = calendarId - 1; 

            // Have to have calendars 
            if (calendars == null) 
            {
                calendars = new CalendarData[CalendarData.MAX_CALENDARS]; 
            }

            // we need the following local variable to avoid returning null
            // when another thread creates a new array of CalendarData (above) 
            // right after we insert the newly created CalendarData (below)
            CalendarData calendarData = calendars[calendarIndex]; 
            // Make sure that calendar has data 
            if (calendarData == null || UseUserOverride)
            { 
                Contract.Assert(this.sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
                calendarData = new CalendarData(this.sWindowsName, calendarId, this.UseUserOverride);
#if !FEATURE_CORECLR
                //Work around issue where Win7 data for MonthDay contains invalid two sets of data separated by semicolon 
                //even though MonthDay is not enumerated
                if (IsOsWin7OrPrior() && !IsUserCustomCulture && !IsReplacementCulture) 
                { 
                    calendarData.FixupWin7MonthDaySemicolonBug();
                } 
#endif
                calendars[calendarIndex] = calendarData;
            }
 
            return calendarData;
        } 
 
        internal int CurrentEra(int calendarId)
        { 
            return GetCalendar(calendarId).iCurrentEra;
        }

        /////////////////// 
        // Text Information //
        /////////////////// 
 
        // IsRightToLeft
#if !FEATURE_CORECLR 
        internal bool IsRightToLeft
        {
            get
            { 
                // Returns one of the following 4 reading layout values:
                // 0 - Left to right (eg en-US) 
                // 1 - Right to left (eg arabic locales) 
                // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
                // 3 - Vertical top to bottom with columns proceeding to the right 
                return (this.IREADINGLAYOUT == 1);
            }
        }
 
        // IREADINGLAYOUT
        // Returns one of the following 4 reading layout values: 
        // 0 - Left to right (eg en-US) 
        // 1 - Right to left (eg arabic locales)
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales) 
        // 3 - Vertical top to bottom with columns proceeding to the right
        //
        // If exposed as a public API, we'd have an enum with those 4 values
        private int IREADINGLAYOUT 
        {
            get 
            { 
                if (this.iReadingLayout == undef || UseUserOverride)
                { 
                    Contract.Assert(this.sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
                    this.iReadingLayout = DoGetLocaleInfoInt(LOCALE_IREADINGLAYOUT);
                }
 
                return (this.iReadingLayout);
            } 
        } 
#endif // !FEATURE_CORECLR
 
        // The TextInfo name never includes that alternate sort and is always specific
        // For customs, it uses the SortLocale (since the textinfo is not exposed in Win7)
        // en -> en-US
        // en-US -> en-US 
        // fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj)
        // fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ) 
        // es-ES_tradnl -> es-ES 
        internal String STEXTINFO               // Text info name to use for text information
        { 
            [System.Security.SecuritySafeCritical]
            get
            {
#if FEATURE_CORECLR 
                // Note: Custom cultures might point at another culture's textinfo, however windows knows how
                // to redirect it to the desired textinfo culture, so this is OK. 
                Contract.Assert(this.sWindowsName != null, "[CultureData.STEXTINFO] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                return (this.sWindowsName);
#else 
                if (this.sTextInfo == null)
                {
                    // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts.
                    // It is also not supported downlevel without culture.dll. 
                    if (IsNeutralCulture || IsUserCustomCulture)
                    { 
                        string sortLocale = DoGetLocaleInfo(LOCALE_SSORTLOCALE); 
                        this.sTextInfo = GetCultureData(sortLocale, bUseOverrides).SNAME;
                    } 

                    if (this.sTextInfo == null)
                    {
                        this.sTextInfo = this.SNAME; // removes alternate sort 
                    }
                } 
 
                return this.sTextInfo;
#endif 
            }
        }

        // Compare info name (including sorting key) to use if custom 
        internal String SCOMPAREINFO
        { 
            [System.Security.SecuritySafeCritical] 
            get
            { 
#if FEATURE_CORECLR
                // Note: Custom cultures might point at another culture's compareinfo, however windows knows how
                // to redirect it to the desired compareinfo culture, so this is OK.
                Contract.Assert(this.sWindowsName != null, "[CultureData.SCOMPAREINFO] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                return (this.sWindowsName);
#else 
                if (this.sCompareInfo == null) 
                {
                    // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts. 
                    // It is also not supported downlevel without culture.dll.
                    // We really only need it for the custom locale case though
                    // since for all other cases, it is the same as sWindowsName
                    if (IsUserCustomCulture) 
                    {
                        this.sCompareInfo = DoGetLocaleInfo(LOCALE_SSORTLOCALE); 
                    } 

                    if (this.sCompareInfo == null) 
                    {
                        this.sCompareInfo = this.sWindowsName;
                    }
                } 

                return this.sCompareInfo; 
#endif 
            }
        } 

        internal bool IsUserCustomCulture
        {
            get 
            {
#if FEATURE_CORECLR 
                return false; 
#else
                return IsCustomCultureId(this.ILANGUAGE); 
#endif
            }
        }
 
#if !FEATURE_CORECLR
        // Typical Scripts for this locale (latn;cyrl; etc) 
        // 

        private String SSCRIPTS 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            { 
                if (this.sScripts == null)
                { 
                    this.sScripts = DoGetLocaleInfo(LOCALE_SSCRIPTS); 
                }
                return this.sScripts; 
            }
        }

        private String SOPENTYPELANGUAGETAG 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                return DoGetLocaleInfo(LOCALE_SOPENTYPELANGUAGETAG); 
            }
        }

        private String FONTSIGNATURE 
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                if (this.fontSignature == null) 
                {
                    this.fontSignature = DoGetLocaleInfo(LOCALE_FONTSIGNATURE);
                }
                return this.fontSignature; 
            }
        } 
 
        private String SKEYBOARDSTOINSTALL
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get
            {
                return DoGetLocaleInfo(LOCALE_SKEYBOARDSTOINSTALL); 
            }
        } 
 
#endif
 
#if !FEATURE_CORECLR
        internal int IDEFAULTANSICODEPAGE   // default ansi code page ID (ACP)
        {
            get 
            {
                if (this.iDefaultAnsiCodePage == undef) 
                { 
                    this.iDefaultAnsiCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTANSICODEPAGE);
                } 
                return this.iDefaultAnsiCodePage;
            }
        }
 
        internal int IDEFAULTOEMCODEPAGE   // default oem code page ID (OCP or OEM)
        { 
            get 
            {
                if (this.iDefaultOemCodePage == undef) 
                {
                    this.iDefaultOemCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTCODEPAGE);
                }
                return this.iDefaultOemCodePage; 
            }
        } 
 
        internal int IDEFAULTMACCODEPAGE   // default macintosh code page
        { 
            get
            {
                if (this.iDefaultMacCodePage == undef)
                { 
                    this.iDefaultMacCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTMACCODEPAGE);
                } 
                return this.iDefaultMacCodePage; 
            }
        } 

        internal int IDEFAULTEBCDICCODEPAGE   // default EBCDIC code page
        {
            get 
            {
                if (this.iDefaultEbcdicCodePage == undef) 
                { 
                    this.iDefaultEbcdicCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTEBCDICCODEPAGE);
                } 
                return this.iDefaultEbcdicCodePage;
            }
        }
 
        // Obtain locale name from LCID
        // NOTE: This will get neutral names, unlike the OS API 
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int LocaleNameToLCID(String localeName);

        // These are desktop only, not coreclr
        // locale ID (0409), including sort information 
        internal int ILANGUAGE
        { 
            get 
            {
                if (this.iLanguage == 0) 
                {
                    Contract.Assert(this.sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
                    this.iLanguage = LocaleNameToLCID(this.sRealName);
                } 
                return this.iLanguage;
            } 
        } 

        internal bool IsWin32Installed 
        {
            get { return this.bWin32Installed; }
        }
 
        internal bool IsFramework
        { 
            get { return this.bFramework; } 
        }
#endif // !FEATURE_CORECLR 

        ////////////////////
        // Derived properties //
        //////////////////// 

        internal bool IsNeutralCulture 
        { 
            get
            { 
                // NlsInfo::nativeInitCultureData told us if we're neutral or not
                return this.bNeutral;
            }
        } 

        internal bool IsInvariantCulture 
        { 
            get
            { 
                return String.IsNullOrEmpty(this.SNAME);
            }
        }
 
        // Get an instance of our default calendar
        internal Calendar DefaultCalendar 
        { 
            get
            { 
                int defaultCalId = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
                if (defaultCalId == 0)
                {
                    defaultCalId = this.CalendarIds[0]; 
                }
 
                return CultureInfo.GetCalendarInstance(defaultCalId); 
            }
        } 

        // All of our era names
        internal String[] EraNames(int calendarId)
        { 
            Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0");
 
            return this.GetCalendar(calendarId).saEraNames; 
        }
 
        internal String[] AbbrevEraNames(int calendarId)
        {
            Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
 
            return this.GetCalendar(calendarId).saAbbrevEraNames;
        } 
 
        internal String[] AbbreviatedEnglishEraNames(int calendarId)
        { 
            Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");

            return this.GetCalendar(calendarId).saAbbrevEnglishEraNames;
        } 

        // String array DEFAULTS 
        // Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to. 

 
        // Time separator (derived from time format)
        internal String TimeSeparator
        {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get
            { 
                string longTimeFormat = ReescapeWin32String(DoGetLocaleInfo(LOCALE_STIMEFORMAT)); 
                if (String.IsNullOrEmpty(longTimeFormat))
                { 
                    longTimeFormat = LongTimes[0];
                }

                // Compute STIME from time format 
                return GetTimeSeparator(longTimeFormat);
            } 
        } 

        // Date separator (derived from short date format) 
        internal String DateSeparator(int calendarId)
        {
            return GetDateSeparator(ShortDates(calendarId)[0]);
        } 

        ////////////////////////////////////// 
        // Helper Functions to get derived properties // 
        //////////////////////////////////////
 
        ////////////////////////////////////////////////////////////////////////////
        //
        // Unescape a NLS style quote string
        // 
        // This removes single quotes:
        //      'fred' -> fred 
        //      'fred -> fred 
        //      fred' -> fred
        //      fred's -> freds 
        //
        // This removes the first \ of escaped characters:
        //      fred\'s -> fred's
        //      a\\b -> a\b 
        //      a\b -> ab
        // 
        // We don't build the stringbuilder unless we find a ' or a \.  If we find a ' or a \, we 
        // always build a stringbuilder because we need to remove the ' or \.
        // 
        ////////////////////////////////////////////////////////////////////////////
        static private String UnescapeNlsString(String str, int start, int end)
        {
            StringBuilder result = null; 

            for (int i = start; i < str.Length && i <= end; i++) 
            { 
                switch (str[i])
                { 
                    case '\'':
                        if (result == null)
                        {
                            result = new StringBuilder(str, start, i - start, str.Length); 
                        }
                        break; 
                    case '\\': 
                        if (result == null)
                        { 
                            result = new StringBuilder(str, start, i - start, str.Length);
                        }
                        ++i;
                        if (i < str.Length) 
                        {
                            result.Append(str[i]); 
                        } 
                        break;
                    default: 
                        if (result != null)
                        {
                            result.Append(str[i]);
                        } 
                        break;
                } 
            } 

            if (result == null) 
                return (str.Substring(start, end - start + 1));

            return (result.ToString());
        } 

        //////////////////////////////////////////////////////////////////////////// 
        // 
        // Reescape a Win32 style quote string as a NLS+ style quoted string
        // 
        // This is also the escaping style used by custom culture data files
        //
        // NLS+ uses \ to escape the next character, whether in a quoted string or
        // not, so we always have to change \ to \\. 
        //
        // NLS+ uses \' to escape a quote inside a quoted string so we have to change 
        // '' to \' (if inside a quoted string) 
        //
        // We don't build the stringbuilder unless we find something to change 
        ////////////////////////////////////////////////////////////////////////////
        static internal String ReescapeWin32String(String str)
        {
            // If we don't have data, then don't try anything 
            if (str == null)
                return null; 
 
            StringBuilder result = null;
 
            bool inQuote = false;
            for (int i = 0; i < str.Length; i++)
            {
                // Look for quote 
                if (str[i] == '\'')
                { 
                    // Already in quote? 
                    if (inQuote)
                    { 
                        // See another single quote.  Is this '' of 'fred''s' or '''', or is it an ending quote?
                        if (i + 1 < str.Length && str[i + 1] == '\'')
                        {
                            // Found another ', so we have ''.  Need to add \' instead. 
                            // 1st make sure we have our stringbuilder
                            if (result == null) 
                                result = new StringBuilder(str, 0, i, str.Length * 2); 

                            // Append a \' and keep going (so we don't turn off quote mode) 
                            result.Append("\\'");
                            i++;
                            continue;
                        } 

                        // Turning off quote mode, fall through to add it 
                        inQuote = false; 
                    }
                    else 
                    {
                        // Found beginning quote, fall through to add it
                        inQuote = true;
                    } 
                }
                // Is there a single \ character? 
                else if (str[i] == '\\') 
                {
                    // Found a \, need to change it to \\ 
                    // 1st make sure we have our stringbuilder
                    if (result == null)
                        result = new StringBuilder(str, 0, i, str.Length * 2);
 
                    // Append our \\ to the string & continue
                    result.Append("\\\\"); 
                    continue; 
                }
 
                // If we have a builder we need to add our character
                if (result != null)
                    result.Append(str[i]);
            } 

            // Unchanged string? , just return input string 
            if (result == null) 
                return str;
 
            // String changed, need to use the builder
            return result.ToString();
        }
 
        static internal String[] ReescapeWin32Strings(String[] array)
        { 
            if (array != null) 
            {
                for (int i = 0; i < array.Length; i++) 
                {
                    array[i] = ReescapeWin32String(array[i]);
                }
            } 

            return array; 
        } 

        // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() 
        // and breaking changes here will not show up at build time, only at run time.
        static private String GetTimeSeparator(String format)
        {
            // Time format separator (ie: : in 12:39:00) 
            //
            // We calculate this from the provided time format 
            // 

            // 
            //  Find the time separator so that we can pretend we know STIME.
            //
            return GetSeparator(format, "Hhms");
        } 

        // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement() 
        // and breaking changes here will not show up at build time, only at run time. 
        static private String GetDateSeparator(String format)
        { 
            // Date format separator (ie: / in 9/1/03)
            //
            // We calculate this from the provided short date
            // 

            // 
            //  Find the date separator so that we can pretend we know SDATE. 
            //
            return GetSeparator(format, "dyM"); 
        }

        private static string GetSeparator(string format, string timeParts)
        { 
            int index = IndexOfTimePart(format, 0, timeParts);
 
            if (index != -1) 
            {
                // Found a time part, find out when it changes 
                char cTimePart = format[index];

                do
                { 
                    index++;
                } while (index < format.Length && format[index] == cTimePart); 
 
                int separatorStart = index;
 
                // Now we need to find the end of the separator
                if (separatorStart < format.Length)
                {
                    int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts); 
                    if (separatorEnd != -1)
                    { 
                        // From [separatorStart, count) is our string, except we need to unescape 
                        return UnescapeNlsString(format, separatorStart, separatorEnd - 1);
                    } 
                }
            }

            return String.Empty; 
        }
 
        private static int IndexOfTimePart(string format, int startIndex, string timeParts) 
        {
            Contract.Assert(startIndex >= 0, "startIndex cannot be negative"); 
            Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters");
            bool inQuote = false;
            for (int i = startIndex; i < format.Length; ++i)
            { 
                // See if we have a time Part
                if (!inQuote && timeParts.IndexOf(format[i]) != -1) 
                { 
                    return i;
                } 
                switch (format[i])
                {
                    case '\\':
                        if (i + 1 < format.Length) 
                        {
                            ++i; 
                            switch (format[i]) 
                            {
                                case '\'': 
                                case '\\':
                                    break;
                                default:
                                    --i; //backup since we will move over this next 
                                    break;
                            } 
                        } 
                        break;
                    case '\'': 
                        inQuote = !inQuote;
                        break;
                }
            } 

            return -1; 
        } 

        [System.Security.SecurityCritical] 
        string DoGetLocaleInfo(uint lctype)
        {
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
            return DoGetLocaleInfo(this.sWindowsName, lctype); 
        }
 
        // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the 
        // "windows" name, which can be specific for downlevel (< windows 7) os's.
        [System.Security.SecurityCritical]  // auto-generated 
        string DoGetLocaleInfo(string localeName, uint lctype)
        {
            // Fix lctype if we don't want overrides
            if (!UseUserOverride) 
            {
                lctype |= LOCALE_NOUSEROVERRIDE; 
            } 

            // Ask OS for data 
            Contract.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null");
            string result = CultureInfo.nativeGetLocaleInfoEx(localeName, lctype);
            if (result == null)
            { 
                // Failed, just use empty string
                result = String.Empty; 
            } 

            return result; 
        }

        int DoGetLocaleInfoInt(uint lctype)
        { 
            // Fix lctype if we don't want overrides
            if (!UseUserOverride) 
            { 
                lctype |= LOCALE_NOUSEROVERRIDE;
            } 

            // Ask OS for data, note that we presume it returns success, so we have to know that
            // sWindowsName is valid before calling.
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            int result = CultureInfo.nativeGetLocaleInfoExInt(this.sWindowsName, lctype);
 
            return result; 
        }
 
        String[] DoEnumTimeFormats()
        {
            // Note that this gets overrides for us all the time
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, 0, UseUserOverride));
 
            return result; 
        }
 
        String[] DoEnumShortTimeFormats()
        {
            // Note that this gets overrides for us all the time
            Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
            String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, TIME_NOSECONDS, UseUserOverride));
 
            return result; 
        }
 
        /////////////////
        // Static Helpers //
        ////////////////
        internal static bool IsCustomCultureId(int cultureId) 
        {
            if (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED) 
                return true; 

            return false; 
        }

        ////////////////////////////////////////////////////////////////////////////
        // 
        // Parameters:
        //      calendarValueOnly   Retrieve the values which are affected by the calendar change of DTFI. 
        //                          This will cause values like longTimePattern not be retrieved since it is 
        //                          not affected by the Calendar property in DTFI.
        // 
        ////////////////////////////////////////////////////////////////////////////
        [System.Security.SecurityCritical]  // auto-generated
        internal void GetNFIValues(NumberFormatInfo nfi)
        { 
            if (this.IsInvariantCulture)
            { 
                nfi.positiveSign = this.sPositiveSign; 
                nfi.negativeSign = this.sNegativeSign;
 
#if !FEATURE_CORECLR
                nfi.nativeDigits = this.saNativeDigits;
                nfi.digitSubstitution = this.iDigitSubstitution;
#endif // !FEATURE_CORECLR 

                nfi.numberGroupSeparator = this.sThousandSeparator; 
                nfi.numberDecimalSeparator = this.sDecimalSeparator; 
                nfi.numberDecimalDigits = this.iDigits;
                nfi.numberNegativePattern = this.iNegativeNumber; 

                nfi.currencySymbol = this.sCurrency;
                nfi.currencyGroupSeparator = this.sMonetaryThousand;
                nfi.currencyDecimalSeparator = this.sMonetaryDecimal; 
                nfi.currencyDecimalDigits = this.iCurrencyDigits;
                nfi.currencyNegativePattern = this.iNegativeCurrency; 
                nfi.currencyPositivePattern = this.iCurrency; 

                nfi.percentNegativePattern = this.INEGATIVEPERCENT; 
                nfi.percentPositivePattern = this.IPOSITIVEPERCENT;
                nfi.percentSymbol = this.SPERCENT;
                nfi.perMilleSymbol = this.----ILLE;
 
                nfi.negativeInfinitySymbol = this.SNEGINFINITY;
                nfi.positiveInfinitySymbol = this.SPOSINFINITY; 
                nfi.nanSymbol = this.SNAN; 

            } 
            else
            {
                //
                // We don't have information for the following four.  All cultures use 
                // the same value of the number formatting values.
                // 
                // PercentDecimalDigits 
                // PercentDecimalSeparator
                // PercentGroupSize 
                // PercentGroupSeparator
                //

                // 
                // Ask native side for our data.
                // 
                Contract.Assert(this.sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already"); 
                CultureData.nativeGetNumberFormatInfoValues(this.sWindowsName, nfi, UseUserOverride);
            } 


            //
            // Gather additional data 
            //
            nfi.numberGroupSizes = this.WAGROUPING; 
            nfi.currencyGroupSizes = this.WAMONGROUPING; 

            // 
            // We don't have percent values, so use the number values
            //
            nfi.percentDecimalDigits = nfi.numberDecimalDigits;
            nfi.percentDecimalSeparator = nfi.numberDecimalSeparator; 
            nfi.percentGroupSizes = nfi.numberGroupSizes;
            nfi.percentGroupSeparator = nfi.numberGroupSeparator; 
 
            //
            // Clean up a few odd values 
            //

            // Windows usually returns an empty positive sign, but we like it to be "+"
            if (nfi.positiveSign == null || nfi.positiveSign.Length == 0) nfi.positiveSign = "+"; 

            //Special case for Italian.  The currency decimal separator in the control panel is the empty string. When the user 
            //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the 
            //decimal point doesn't show up.  We'll just hack this here because our default currency format will never use nfi.
            if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0) 
            {
                nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator;
            }
 
#if !FEATURE_CORECLR
            // 
            if ((932 == this.IDEFAULTANSICODEPAGE) || 
               (949 == this.IDEFAULTANSICODEPAGE))
            { 
                // Legacy behavior for cultures that use Japanese/Korean default ANSI code pages
                // Note that this is a code point, not a character.  On Japanese/Korean machines this
                // will be rendered as their currency symbol, not rendered as a "\"
                nfi.ansiCurrencySymbol = "\x5c"; 
            }
#endif // !FEATURE_CORECLR 
        } 

        static private int ConvertFirstDayOfWeekMonToSun(int iTemp) 
        {
            // Convert Mon-Sun to Sun-Sat format
            iTemp++;
            if (iTemp > 6) 
            {
                // Wrap Sunday and convert invalid data to Sunday 
                iTemp = 0; 
            }
            return iTemp; 
        }

        // Helper
        // This is ONLY used for caching names and shouldn't be used for anything else 
        internal static string AnsiToLower(string testString)
        { 
            StringBuilder sb = new StringBuilder(testString.Length); 

            for (int ich = 0; ich < testString.Length; ich++) 
            {
                char ch = testString[ich];
                sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch);
            } 

            return (sb.ToString()); 
        } 

        // If we get a group from windows, then its in 3;0 format with the 0 backwards 
        // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa)
        static private int[] ConvertWin32GroupString(String win32Str)
        {
            // None of these cases make any sense 
            if (win32Str == null || win32Str.Length == 0 || win32Str[0] == '0')
            { 
                return (new int[] { 3 }); 
            }
 
            // Since its in n;n;n;n;n format, we can always get the length quickly
            int[] values;
            if (win32Str[win32Str.Length - 1] == '0')
            { 
                // Trailing 0 gets dropped. 1;0 -> 1
                values = new int[(win32Str.Length / 2)]; 
            } 
            else
            { 
                // Need extra space for trailing zero 1 -> 1;0
                values = new int[(win32Str.Length / 2) + 2];
                values[values.Length - 1] = 0;
            } 

            int i; 
            int j; 
            for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++)
            { 
                // Note that this # shouldn't ever be zero, 'cause 0 is only at end
                // But we'll test because its registry that could be anything
                if (win32Str[i] < '1' || win32Str[i] > '9')
                    return new int[] { 3 }; 

                values[j] = (int)(win32Str[i] - '0'); 
            } 

            return (values); 
        }

        // LCTYPES for GetLocaleInfo
        private const uint LOCALE_NOUSEROVERRIDE = 0x80000000;   // do not use user overrides 
        private const uint LOCALE_RETURN_NUMBER = 0x20000000;   // return number instead of string
 
        // Modifier for genitive names 
        private const uint LOCALE_RETURN_GENITIVE_NAMES = 0x10000000;   //Flag to return the Genitive forms of month names
 
        //
        //  The following LCTypes are mutually exclusive in that they may NOT
        //  be used in combination with each other.
        // 

        // 
        // These are the various forms of the name of the locale: 
        //
        private const uint LOCALE_SLOCALIZEDDISPLAYNAME = 0x00000002;   // localized name of locale, eg "German (Germany)" in UI language 
        private const uint LOCALE_SENGLISHDISPLAYNAME = 0x00000072;   // Display name (language + ---- usually) in English, eg "German (Germany)"
        private const uint LOCALE_SNATIVEDISPLAYNAME = 0x00000073;   // Display name in native locale language, eg "Deutsch (Deutschland)

        private const uint LOCALE_SLOCALIZEDLANGUAGENAME = 0x0000006f;   // Language Display Name for a language, eg "German" in UI language 
        private const uint LOCALE_SENGLISHLANGUAGENAME = 0x00001001;   // English name of language, eg "German"
        private const uint LOCALE_SNATIVELANGUAGENAME = 0x00000004;   // native name of language, eg "Deutsch" 
 
        private const uint LOCALE_SLOCALIZEDCOUNTRYNAME = 0x00000006;   // localized name of country, eg "Germany" in UI language
        private const uint LOCALE_SENGLISHCOUNTRYNAME = 0x00001002;   // English name of country, eg "Germany" 
        private const uint LOCALE_SNATIVECOUNTRYNAME = 0x00000008;   // native name of country, eg "Deutschland"


        //        private const uint LOCALE_ILANGUAGE              =0x00000001;   // language id // Don't use, use NewApis::LocaleNameToLCID instead (GetLocaleInfo doesn't return neutrals) 

        //        private const uint LOCALE_SLANGUAGE              =LOCALE_SLOCALIZEDDISPLAYNAME;   // localized name of language (use LOCALE_SLOCALIZEDDISPLAYNAME instead) 
        //        private const uint LOCALE_SENGLANGUAGE           =LOCALE_SENGLISHLANGUAGENAME;   // English name of language (use LOCALE_SENGLISHLANGUAGENAME instead) 
        private const uint LOCALE_SABBREVLANGNAME = 0x00000003;   // abbreviated language name
        //        private const uint LOCALE_SNATIVELANGNAME        =LOCALE_SNATIVELANGUAGENAME;   // native name of language (use LOCALE_SNATIVELANGUAGENAME instead) 

        private const uint LOCALE_ICOUNTRY = 0x00000005;   // ---- code
        //        private const uint LOCALE_SCOUNTRY               =LOCALE_SLOCALIZEDCOUNTRYNAME;   // localized name of country (use LOCALE_SLOCALIZEDCOUNTRYNAME instead)
        //        private const uint LOCALE_SENGCOUNTRY            =LOCALE_SENGLISHCOUNTRYNAME;   // English name of country (use LOCALE_SENGLISHCOUNTRYNAME instead) 
        private const uint LOCALE_SABBREVCTRYNAME = 0x00000007;   // abbreviated ---- name
        //        private const uint LOCALE_SNATIVECTRYNAME        =LOCALE_SNATIVECOUNTRYNAME;   // native name of country ( use LOCALE_SNATIVECOUNTRYNAME instead) 
        private const uint LOCALE_IGEOID = 0x0000005B;   // geographical location id 

        private const uint LOCALE_IDEFAULTLANGUAGE = 0x00000009;   // default language id 
        private const uint LOCALE_IDEFAULT---- = 0x0000000A;   // default ---- code
        private const uint LOCALE_IDEFAULTCODEPAGE = 0x0000000B;   // default oem code page
        private const uint LOCALE_IDEFAULTANSICODEPAGE = 0x00001004;   // default ansi code page
        private const uint LOCALE_IDEFAULTMACCODEPAGE = 0x00001011;   // default mac code page 

        private const uint LOCALE_SLIST = 0x0000000C;   // list item separator 
        private const uint LOCALE_IMEASURE = 0x0000000D;   // 0 = metric, 1 = US 

        private const uint LOCALE_SDECIMAL = 0x0000000E;   // decimal separator 
        private const uint LOCALE_STHOUSAND = 0x0000000F;   // thousand separator
        private const uint LOCALE_SGROUPING = 0x00000010;   // digit grouping
        private const uint LOCALE_IDIGITS = 0x00000011;   // number of fractional digits
        private const uint LOCALE_ILZERO = 0x00000012;   // leading zeros for decimal 
        private const uint LOCALE_INEGNUMBER = 0x00001010;   // negative number mode
        private const uint LOCALE_SNATIVEDIGITS = 0x00000013;   // native digits for 0-9 
 
        private const uint LOCALE_SCURRENCY = 0x00000014;   // local monetary symbol
        private const uint LOCALE_SINTLSYMBOL = 0x00000015;   // uintl monetary symbol 
        private const uint LOCALE_SMONDECIMALSEP = 0x00000016;   // monetary decimal separator
        private const uint LOCALE_SMONTHOUSANDSEP = 0x00000017;   // monetary thousand separator
        private const uint LOCALE_SMONGROUPING = 0x00000018;   // monetary grouping
        private const uint LOCALE_ICURRDIGITS = 0x00000019;   // # local monetary digits 
        private const uint LOCALE_IINTLCURRDIGITS = 0x0000001A;   // # uintl monetary digits
        private const uint LOCALE_ICURRENCY = 0x0000001B;   // positive currency mode 
        private const uint LOCALE_INEGCURR = 0x0000001C;   // negative currency mode 

        private const uint LOCALE_SDATE = 0x0000001D;   // date separator (derived from LOCALE_SSHORTDATE, use that instead) 
        private const uint LOCALE_STIME = 0x0000001E;   // time separator (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_SSHORTDATE = 0x0000001F;   // short date format string
        private const uint LOCALE_SLONGDATE = 0x00000020;   // long date format string
        private const uint LOCALE_STIMEFORMAT = 0x00001003;   // time format string 
        private const uint LOCALE_IDATE = 0x00000021;   // short date format ordering (derived from LOCALE_SSHORTDATE, use that instead)
        private const uint LOCALE_ILDATE = 0x00000022;   // long date format ordering (derived from LOCALE_SLONGDATE, use that instead) 
        private const uint LOCALE_ITIME = 0x00000023;   // time format specifier (derived from LOCALE_STIMEFORMAT, use that instead) 
        private const uint LOCALE_ITIMEMARKPOSN = 0x00001005;   // time marker position (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_ICENTURY = 0x00000024;   // century format specifier (short date, LOCALE_SSHORTDATE is preferred) 
        private const uint LOCALE_ITLZERO = 0x00000025;   // leading zeros in time field (derived from LOCALE_STIMEFORMAT, use that instead)
        private const uint LOCALE_IDAYLZERO = 0x00000026;   // leading zeros in day field (short date, LOCALE_SSHORTDATE is preferred)
        private const uint LOCALE_IMONLZERO = 0x00000027;   // leading zeros in month field (short date, LOCALE_SSHORTDATE is preferred)
        private const uint LOCALE_S1159 = 0x00000028;   // AM designator 
        private const uint LOCALE_S2359 = 0x00000029;   // PM designator
 
        private const uint LOCALE_ICALENDARTYPE = 0x00001009;   // type of calendar specifier 
        private const uint LOCALE_IOPTIONALCALENDAR = 0x0000100B;   // additional calendar types specifier
        private const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C;   // first day of week specifier 
        private const uint LOCALE_IFIRSTWEEKOFYEAR = 0x0000100D;   // first week of year specifier

        private const uint LOCALE_SDAYNAME1 = 0x0000002A;   // long name for Monday
        private const uint LOCALE_SDAYNAME2 = 0x0000002B;   // long name for Tuesday 
        private const uint LOCALE_SDAYNAME3 = 0x0000002C;   // long name for Wednesday
        private const uint LOCALE_SDAYNAME4 = 0x0000002D;   // long name for Thursday 
        private const uint LOCALE_SDAYNAME5 = 0x0000002E;   // long name for Friday 
        private const uint LOCALE_SDAYNAME6 = 0x0000002F;   // long name for Saturday
        private const uint LOCALE_SDAYNAME7 = 0x00000030;   // long name for Sunday 
        private const uint LOCALE_SABBREVDAYNAME1 = 0x00000031;   // abbreviated name for Monday
        private const uint LOCALE_SABBREVDAYNAME2 = 0x00000032;   // abbreviated name for Tuesday
        private const uint LOCALE_SABBREVDAYNAME3 = 0x00000033;   // abbreviated name for Wednesday
        private const uint LOCALE_SABBREVDAYNAME4 = 0x00000034;   // abbreviated name for Thursday 
        private const uint LOCALE_SABBREVDAYNAME5 = 0x00000035;   // abbreviated name for Friday
        private const uint LOCALE_SABBREVDAYNAME6 = 0x00000036;   // abbreviated name for Saturday 
        private const uint LOCALE_SABBREVDAYNAME7 = 0x00000037;   // abbreviated name for Sunday 
        private const uint LOCALE_SMONTHNAME1 = 0x00000038;   // long name for January
        private const uint LOCALE_SMONTHNAME2 = 0x00000039;   // long name for February 
        private const uint LOCALE_SMONTHNAME3 = 0x0000003A;   // long name for [....]
        private const uint LOCALE_SMONTHNAME4 = 0x0000003B;   // long name for April
        private const uint LOCALE_SMONTHNAME5 = 0x0000003C;   // long name for May
        private const uint LOCALE_SMONTHNAME6 = 0x0000003D;   // long name for June 
        private const uint LOCALE_SMONTHNAME7 = 0x0000003E;   // long name for July
        private const uint LOCALE_SMONTHNAME8 = 0x0000003F;   // long name for August 
        private const uint LOCALE_SMONTHNAME9 = 0x00000040;   // long name for September 
        private const uint LOCALE_SMONTHNAME10 = 0x00000041;   // long name for October
        private const uint LOCALE_SMONTHNAME11 = 0x00000042;   // long name for November 
        private const uint LOCALE_SMONTHNAME12 = 0x00000043;   // long name for December
        private const uint LOCALE_SMONTHNAME13 = 0x0000100E;   // long name for 13th month (if exists)
        private const uint LOCALE_SABBREVMONTHNAME1 = 0x00000044;   // abbreviated name for January
        private const uint LOCALE_SABBREVMONTHNAME2 = 0x00000045;   // abbreviated name for February 
        private const uint LOCALE_SABBREVMONTHNAME3 = 0x00000046;   // abbreviated name for [....]
        private const uint LOCALE_SABBREVMONTHNAME4 = 0x00000047;   // abbreviated name for April 
        private const uint LOCALE_SABBREVMONTHNAME5 = 0x00000048;   // abbreviated name for May 
        private const uint LOCALE_SABBREVMONTHNAME6 = 0x00000049;   // abbreviated name for June
        private const uint LOCALE_SABBREVMONTHNAME7 = 0x0000004A;   // abbreviated name for July 
        private const uint LOCALE_SABBREVMONTHNAME8 = 0x0000004B;   // abbreviated name for August
        private const uint LOCALE_SABBREVMONTHNAME9 = 0x0000004C;   // abbreviated name for September
        private const uint LOCALE_SABBREVMONTHNAME10 = 0x0000004D;   // abbreviated name for October
        private const uint LOCALE_SABBREVMONTHNAME11 = 0x0000004E;   // abbreviated name for November 
        private const uint LOCALE_SABBREVMONTHNAME12 = 0x0000004F;   // abbreviated name for December
        private const uint LOCALE_SABBREVMONTHNAME13 = 0x0000100F;   // abbreviated name for 13th month (if exists) 
 
        private const uint LOCALE_SPOSITIVESIGN = 0x00000050;   // positive sign
        private const uint LOCALE_SNEGATIVESIGN = 0x00000051;   // negative sign 
        private const uint LOCALE_IPOSSIGNPOSN = 0x00000052;   // positive sign position (derived from INEGCURR)
        private const uint LOCALE_INEGSIGNPOSN = 0x00000053;   // negative sign position (derived from INEGCURR)
        private const uint LOCALE_IPOSSYMPRECEDES = 0x00000054;   // mon sym precedes pos amt (derived from ICURRENCY)
        private const uint LOCALE_IPOSSEPBYSPACE = 0x00000055;   // mon sym sep by space from pos amt (derived from ICURRENCY) 
        private const uint LOCALE_INEGSYMPRECEDES = 0x00000056;   // mon sym precedes neg amt (derived from INEGCURR)
        private const uint LOCALE_INEGSEPBYSPACE = 0x00000057;   // mon sym sep by space from neg amt (derived from INEGCURR) 
 
        private const uint LOCALE_FONTSIGNATURE = 0x00000058;   // font signature
        private const uint LOCALE_SISO639LANGNAME = 0x00000059;   // ISO abbreviated language name 
        private const uint LOCALE_SISO3166CTRYNAME = 0x0000005A;   // ISO abbreviated ---- name

        private const uint LOCALE_IDEFAULTEBCDICCODEPAGE = 0x00001012;   // default ebcdic code page
        private const uint LOCALE_IPAPERSIZE = 0x0000100A;   // 1 = letter, 5 = legal, 8 = a3, 9 = a4 
        private const uint LOCALE_SENGCURRNAME = 0x00001007;   // english name of currency
        private const uint LOCALE_SNATIVECURRNAME = 0x00001008;   // native name of currency 
        private const uint LOCALE_SYEARMONTH = 0x00001006;   // year month format string 
        private const uint LOCALE_SSORTNAME = 0x00001013;   // sort name
        private const uint LOCALE_IDIGITSUBSTITUTION = 0x00001014;   // 0 = context, 1 = none, 2 = national 

        private const uint LOCALE_SNAME = 0x0000005c;   // locale name (with sort info) (ie: de-DE_phoneb)
        private const uint LOCALE_SDURATION = 0x0000005d;   // time duration format
        private const uint LOCALE_SKEYBOARDSTOINSTALL = 0x0000005e;   // (windows only) keyboards to install 
        private const uint LOCALE_SSHORTESTDAYNAME1 = 0x00000060;   // Shortest day name for Monday
        private const uint LOCALE_SSHORTESTDAYNAME2 = 0x00000061;   // Shortest day name for Tuesday 
        private const uint LOCALE_SSHORTESTDAYNAME3 = 0x00000062;   // Shortest day name for Wednesday 
        private const uint LOCALE_SSHORTESTDAYNAME4 = 0x00000063;   // Shortest day name for Thursday
        private const uint LOCALE_SSHORTESTDAYNAME5 = 0x00000064;   // Shortest day name for Friday 
        private const uint LOCALE_SSHORTESTDAYNAME6 = 0x00000065;   // Shortest day name for Saturday
        private const uint LOCALE_SSHORTESTDAYNAME7 = 0x00000066;   // Shortest day name for Sunday
        private const uint LOCALE_SISO639LANGNAME2 = 0x00000067;   // 3 character ISO abbreviated language name
        private const uint LOCALE_SISO3166CTRYNAME2 = 0x00000068;   // 3 character ISO ---- name 
        private const uint LOCALE_SNAN = 0x00000069;   // Not a Number
        private const uint LOCALE_SPOSINFINITY = 0x0000006a;   // + Infinity 
        private const uint LOCALE_SNEGINFINITY = 0x0000006b;   // - Infinity 
        private const uint LOCALE_SSCRIPTS = 0x0000006c;   // Typical scripts in the locale
        private const uint LOCALE_SPARENT = 0x0000006d;   // Fallback name for resources 
        private const uint LOCALE_SCONSOLEFALLBACKNAME = 0x0000006e;   // Fallback name for within the console
        //        private const uint LOCALE_SLANGDISPLAYNAME       =LOCALE_SLOCALIZEDLANGUAGENAME;   // Language Display Name for a language (use LOCALE_SLOCALIZEDLANGUAGENAME instead)

        // Windows 7 LCTYPES 
        private const uint LOCALE_IREADINGLAYOUT = 0x00000070;   // Returns one of the following 4 reading layout values:
        // 0 - Left to right (eg en-US) 
        // 1 - Right to left (eg arabic locales) 
        // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
        // 3 - Vertical top to bottom with columns proceeding to the right 
        private const uint LOCALE_INEUTRAL = 0x00000071;   // Returns 0 for specific cultures, 1 for neutral cultures.
        private const uint LOCALE_INEGATIVEPERCENT = 0x00000074;   // Returns 0-11 for the negative percent format
        private const uint LOCALE_IPOSITIVEPERCENT = 0x00000075;   // Returns 0-3 for the positive percent formatIPOSITIVEPERCENT
        private const uint LOCALE_SPERCENT = 0x00000076;   // Returns the percent symbol 
        private const uint LOCALE_----ILLE = 0x00000077;   // Returns the permille (U+2030) symbol
        private const uint LOCALE_SMONTHDAY = 0x00000078;   // Returns the preferred month/day format 
        private const uint LOCALE_SSHORTTIME = 0x00000079;   // Returns the preferred short time format (ie: no seconds, just h:mm) 
        private const uint LOCALE_SOPENTYPELANGUAGETAG = 0x0000007a;   // Open type language tag, eg: "latn" or "dflt"
        private const uint LOCALE_SSORTLOCALE = 0x0000007b;   // Name of locale to use for sorting/collation/casing behavior. 

        // Time formats enumerations
        internal const uint TIME_NOSECONDS = 0x00000002;   // Don't use seconds (get short time format for enumtimeformats on win7+)
 
        // Get our initial minimal culture data (name, parent, etc.)
        [System.Security.SecuritySafeCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeInitCultureData(CultureData cultureData); 

        // Grab the NumberFormatInfo data
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeGetNumberFormatInfoValues(String localeName, NumberFormatInfo nfi, bool useUserOverride); 
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride);

#if !FEATURE_CORECLR 
        [System.Security.SecurityCritical]  // auto-generated
        [SuppressUnmanagedCodeSecurityAttribute()] 
        [ResourceExposure(ResourceScope.None)] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        internal static extern int nativeEnumCultureNames(int cultureTypes, ObjectHandleOnStack retStringArray); 
#endif

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK