CultureInfo.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 / CultureInfo.cs / 1667663 / CultureInfo.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
////////////////////////////////////////////////////////////////////////////
// 
//  Class:    CultureInfo 
//
// 
//  Purpose:  This class represents the software preferences of a particular
//            culture or community.  It includes information such as the
//            language, writing system, and a calendar used by the culture
//            as well as methods for common operations such as printing 
//            dates and sorting strings.
// 
//  Date:     [....] 31, 1999 
//
// 
//  !!!! NOTE WHEN CHANGING THIS CLASS !!!!
//
//  If adding or removing members to this class, please update CultureInfoBaseObject
//  in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be 
//  different than the order in which members are declared. For instance, all
//  reference types will come first in the class before value types (like ints, bools, etc) 
//  regardless of the order in which they are declared. The best way to see the 
//  actual order of the class is to do a !dumpobj on an instance of the managed
//  object inside of the debugger. 
//
////////////////////////////////////////////////////////////////////////////

namespace System.Globalization { 
    using System;
    using System.Security; 
    using System.Threading; 
    using System.Collections;
    using System.Runtime; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization;
    using System.Runtime.Versioning; 
    using System.Security.Permissions;
    using System.Reflection; 
    using Microsoft.Win32; 
    using System.Diagnostics.Contracts;
 
    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class CultureInfo : ICloneable, IFormatProvider {
        //--------------------------------------------------------------------// 
        //                        Internal Information                        //
        //-------------------------------------------------------------------// 
 
        //-------------------------------------------------------------------//
        // Data members to be serialized: 
        //-------------------------------------------------------------------//

        // We use an RFC4646 type string to construct CultureInfo.
        // This string is stored in m_name and is authoritative. 
        // We use the m_cultureData to get the data for our object
 
        // WARNING 
        // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h
        // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot 
        // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject
        // WARNING: must be manually structured to match the true loaded class layout
        // WARNING
        internal bool m_isReadOnly; 
        internal CompareInfo compareInfo;
        internal TextInfo textInfo; 
        // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK) 
#if !FEATURE_CORECLR
        [NonSerialized]internal RegionInfo regionInfo; 
#endif
        internal NumberFormatInfo numInfo;
        internal DateTimeFormatInfo dateTimeInfo;
        internal Calendar calendar; 
#if !FEATURE_CORECLR
        [OptionalField(VersionAdded = 1)] 
        internal int m_dataItem;       // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) 
        [OptionalField(VersionAdded = 1)]
        internal int cultureID  = 0x007f;  // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) 
#endif // !FEATURE_CORECLR
        //
        // The CultureData instance that we are going to read data from.
        // For supported culture, this will be the CultureData instance that read data from mscorlib assembly. 
        // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
        // 
        [NonSerialized]internal CultureData m_cultureData; 

        [NonSerialized]internal bool m_isInherited; 
#if FEATURE_LEAK_CULTURE_INFO
        [NonSerialized]private bool m_isSafeCrossDomain;
#endif // !FEATURE_CORECLR
        [NonSerialized] 
        private int m_createdDomainID;
#if !FEATURE_CORECLR 
        [NonSerialized]private CultureInfo m_consoleFallbackCulture; 
#endif // !FEATURE_CORECLR
 
        // Names are confusing.  Here are 3 names we have:
        //
        //  new CultureInfo()   m_name        m_nonSortName   m_sortName
        //      en-US           en-US           en-US           en-US 
        //      de-de_phoneb    de-DE_phoneb    de-DE           de-DE_phoneb
        //      fj-fj (custom)  fj-FJ           fj-FJ           en-US (if specified sort is en-US) 
        //      en              en 
        //
        // Note that in Silverlight we ask the OS for the text and sort behavior, so the 
        // textinfo and compareinfo names are the same as the name

        // Note that the name used to be serialized for Everett; it is now serialized
        // because alernate sorts can have alternate names. 
        // This has a de-DE, de-DE_phoneb or fj-FJ style name
        internal string m_name; 
 
        // This will hold the non sorting name to be returned from CultureInfo.Name property.
        // This has a de-DE style name even for de-DE_phoneb type cultures 
        [NonSerialized]private string m_nonSortName;

        // This will hold the sorting name to be returned from CultureInfo.SortName property.
        // This might be completely unrelated to the culture name if a custom culture.  Ie en-US for fj-FJ. 
        // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
        [NonSerialized]private string m_sortName; 
 

        //--------------------------------------------------------------------// 
        //
        // Static data members
        //
        //-------------------------------------------------------------------// 

        //Get the current user default culture.  This one is almost always used, so we create it by default. 
        private static CultureInfo s_userDefaultCulture; 

        // 
        // All of the following will be created on demand.
        //

        //The Invariant culture; 
        private static CultureInfo s_InvariantCultureInfo;
 
        //The culture used in the user interface. This is mostly used to load correct localized resources. 
        private static CultureInfo s_userDefaultUICulture;
 
        //This is the UI culture used to install the OS.
        private static CultureInfo s_InstalledUICultureInfo;

        //This is a cache of all previously created cultures.  Valid keys are LCIDs or the name.  We use two hashtables to track them, 
        // depending on how they are called.
        private static Hashtable s_LcidCachedCultures; 
        private static Hashtable s_NameCachedCultures; 

        //The parent culture. 
        [NonSerialized]private CultureInfo m_parent;

        // LOCALE constants of interest to us internally and privately for LCID functions
        // (ie: avoid using these and use names if possible) 
        internal const int LOCALE_NEUTRAL              = 0x0000;
        private  const int LOCALE_USER_DEFAULT         = 0x0400; 
        private  const int LOCALE_SYSTEM_DEFAULT       = 0x0800; 
        internal const int LOCALE_CUSTOM_DEFAULT       = 0x0c00;
        internal const int LOCALE_CUSTOM_UNSPECIFIED   = 0x1000; 
        internal const int LOCALE_INVARIANT            = 0x007F;
        private  const int LOCALE_TRADITIONAL_SPANISH  = 0x040a;

        // 
        // The CultureData  instance that reads the data provided by our CultureData class.
        // 
        //Using a field initializer rather than a static constructor so that the whole class can be lazy 
        //init.
        private static readonly bool init = Init(); 
        private static bool Init()
        {

            if (s_InvariantCultureInfo == null) 
            {
                CultureInfo temp = new CultureInfo("", false); 
                temp.m_isReadOnly = true; 
                s_InvariantCultureInfo = temp;
            } 
            // First we set it to Invariant in case someone needs it before we're done finding it.
            // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid
            // s_userDefaultCulture to be used in Thread.CurrentCulture.
            s_userDefaultCulture = s_userDefaultUICulture = s_InvariantCultureInfo; 

            s_userDefaultCulture = InitUserDefaultCulture(); 
            s_userDefaultUICulture = InitUserDefaultUICulture(); 
            return true;
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        static CultureInfo InitUserDefaultCulture()
        { 
            String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT);
            if (strDefault == null) 
            { 
                strDefault = GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT);
 
                if (strDefault == null)
                {
                    // If system default doesn't work, keep using the invariant
                    return (CultureInfo.InvariantCulture); 
                }
            } 
            CultureInfo temp = GetCultureByName(strDefault, true); 

            temp.m_isReadOnly = true; 

            return (temp);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        static CultureInfo InitUserDefaultUICulture() 
        { 
            String strDefault = GetUserDefaultUILanguage();
 
            // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible.
            if (strDefault == UserDefaultCulture.Name)
            {
                return (UserDefaultCulture); 
            }
 
            CultureInfo temp = GetCultureByName( strDefault, true); 

            if (temp == null) 
            {
                return (CultureInfo.InvariantCulture);
            }
 
            temp.m_isReadOnly = true;
 
            return (temp); 
        }
 


        ////////////////////////////////////////////////////////////////////////
        // 
        //  CultureInfo Constructors
        // 
        //////////////////////////////////////////////////////////////////////// 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
#if !FEATURE_CORECLR
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public CultureInfo(String name) : this(name, true) {
        } 
 

        public CultureInfo(String name, bool useUserOverride) { 
            if (name==null) {
                throw new ArgumentNullException("name",
                    Environment.GetResourceString("ArgumentNull_String"));
            } 
            Contract.EndContractBlock();
 
            // Get our data providing record 
            this.m_cultureData = CultureData.GetCultureData(name, useUserOverride);
 
            if (this.m_cultureData == null)
                throw new CultureNotFoundException(
                    "name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            this.m_name = this.m_cultureData.CultureName;
            this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); 
        } 

 
#if  FEATURE_USE_LCID
        public CultureInfo(int culture) : this(culture, true) {
        }
 
        public CultureInfo(int culture, bool useUserOverride) {
            // We don't check for other invalid LCIDS here... 
            if (culture < 0) { 
                throw new ArgumentOutOfRangeException("culture",
                    Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
            }
            Contract.EndContractBlock();

            InitializeFromCultureId(culture, useUserOverride); 
        }
 
        private void InitializeFromCultureId(int culture, bool useUserOverride) 
        {
            switch (culture) 
            {
                case LOCALE_CUSTOM_DEFAULT:
                case LOCALE_SYSTEM_DEFAULT:
                case LOCALE_NEUTRAL: 
                case LOCALE_USER_DEFAULT:
                case LOCALE_CUSTOM_UNSPECIFIED: 
                    // Can't support unknown custom cultures and we do not support neutral or 
                    // non-custom user locales.
                    throw new CultureNotFoundException( 
                        "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));

                default:
                    // Now see if this LCID is supported in the system default CultureData  table. 
                    this.m_cultureData = CultureData.GetCultureData(culture, useUserOverride);
                    break; 
            } 
            this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
            this.m_name = this.m_cultureData.CultureName; 
        }
#endif // FEATURE_USE_LCID

        // 
        // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to
        // other object (like CultureInfo or DateTimeFormatInfo). 
        // 

        internal static void CheckDomainSafetyObject(Object obj, Object container) 
        {
            if (obj.GetType().Assembly != typeof(System.Globalization.CultureInfo).Assembly) {

                throw new InvalidOperationException( 
                            String.Format(
                                CultureInfo.CurrentCulture, 
                                Environment.GetResourceString("InvalidOperation_SubclassedObject"), 
                                obj.GetType(),
                                container.GetType())); 
            }
            Contract.EndContractBlock();
        }
 
#region Serialization
        // We need to store the override from the culture data record. 
        private bool    m_useUserOverride; 

        [OnDeserialized] 
        private void OnDeserialized(StreamingContext ctx)
        {
#if  FEATURE_USE_LCID
            // Whidbey+ should remember our name 
            // but v1 and v1.1 did not store name -- only lcid
            // Whidbey did not store actual alternate sort name in m_name 
            //   like we do in v4 so we can't use name for alternate sort 
            // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl
            if (m_name == null || IsAlternateSortLcid(cultureID)) 
            {
                Contract.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0");
                InitializeFromCultureId(cultureID, m_useUserOverride);
            } 
            else
            { 
#endif 
                Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null");
                // 

                this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride);
                if (this.m_cultureData == null)
                    throw new CultureNotFoundException( 
                        "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported"));
 
#if  FEATURE_USE_LCID 
            }
#endif 
            m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));

            // in case we have non customized CultureInfo object we shouldn't allow any customized object
            // to be attached to it for cross app domain safety. 
            if (this.GetType().Assembly == typeof(System.Globalization.CultureInfo).Assembly)
            { 
                if (textInfo != null) 
                {
                    CheckDomainSafetyObject(textInfo, this); 
                }

                if (compareInfo != null)
                { 
                    CheckDomainSafetyObject(compareInfo, this);
                } 
            } 
        }
 
#if  FEATURE_USE_LCID
        //  A locale ID is a 32 bit value which is the combination of a
        //  language ID, a sort ID, and a reserved area.  The bits are
        //  allocated as follows: 
        //
        //  +------------------------+-------+--------------------------------+ 
        //  |        Reserved        |Sort ID|           Language ID          | 
        //  +------------------------+-------+--------------------------------+
        //  31                     20 19   16 15                             0   bit 
        private const int LOCALE_SORTID_MASK = 0x000f0000;

        static private bool IsAlternateSortLcid(int lcid)
        { 
            if(lcid == LOCALE_TRADITIONAL_SPANISH)
            { 
                return true; 
            }
 
            return (lcid & LOCALE_SORTID_MASK) != 0;
        }
#endif
 
        [OnSerializing]
        private void OnSerializing(StreamingContext ctx) 
        { 
            this.m_name              = this.m_cultureData.CultureName;
            this.m_useUserOverride   = this.m_cultureData.UseUserOverride; 
#if FEATURE_USE_LCID
            // for compatibility with v2 serialize cultureID
            this.cultureID = this.m_cultureData.ILANGUAGE;
#endif 
        }
#endregion Serialization 
 
        // Is it safe to send this CultureInfo as an instance member of a Thread cross AppDomain boundaries?
        // For Silverlight, the answer is always no. 
        internal bool IsSafeCrossDomain {
            get {
                Contract.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0");
#if FEATURE_LEAK_CULTURE_INFO 
                return m_isSafeCrossDomain;
#else 
                return false; 
#endif
            } 
        }

        internal int CreatedDomainID {
            get { 
                Contract.Assert(m_createdDomainID != 0,  "[CultureInfo.CreatedDomain] m_createdDomainID != 0");
                return m_createdDomainID; 
            } 
        }
 
        // Is it safe to pass the CultureInfo cross AppDomain boundaries, not necessarily as an instance
        // member of Thread. This is different from IsSafeCrossDomain, which implies passing the CultureInfo
        // as a Thread instance member.
        internal bool CanSendCrossDomain() 
        {
            bool isSafe = false; 
            if (this.GetType() == typeof(System.Globalization.CultureInfo)) 
            {
                isSafe = true; 
            }
            return isSafe;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal void StartCrossDomainTracking() { 
 
            // If we have decided about cross domain safety of this instance, we are done
            if (m_createdDomainID != 0) 
                return;

            // If FEATURE_LEAK_CULTURE_INFO isn't enabled, we never want to pass
            // CultureInfo as an instance member of a Thread. 
#if FEATURE_LEAK_CULTURE_INFO
            if (CanSendCrossDomain()) 
            { 
                m_isSafeCrossDomain = true;
            } 
#endif

            // m_createdDomainID has to be assigned last. We use it to signal that we have
            // completed the check. 
            System.Threading.Thread.MemoryBarrier();
            m_createdDomainID = Thread.GetDomainID(); 
        } 

        // Constructor called by SQL Server's special munged culture - creates a culture with 
        // a TextInfo and CompareInfo that come from a supplied alternate source. This object
        // is ALWAYS read-only.
        // Note that we really cannot use an LCID version of this override as the cached
        // name we create for it has to include both names, and the logic for this is in 
        // the GetCultureInfo override *only*.
        internal CultureInfo(String cultureName, String textAndCompareCultureName) 
        { 
            if (cultureName==null) {
                throw new ArgumentNullException("cultureName", 
                    Environment.GetResourceString("ArgumentNull_String"));
            }
            Contract.EndContractBlock();
 
            this.m_cultureData = CultureData.GetCultureData(cultureName, false);
            if (this.m_cultureData == null) 
                throw new CultureNotFoundException( 
                    "cultureName", cultureName, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            this.m_name = this.m_cultureData.CultureName;

            CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName);
            this.compareInfo = altCulture.CompareInfo; 
            this.textInfo = altCulture.TextInfo;
        } 
 
        // We do this to try to return the system UI language and the default user languages
        // The callers should have a fallback if this fails (like Invariant) 
        private static CultureInfo GetCultureByName(String name, bool userOverride)
        {
            // Try to get our culture
            try 
            {
                return userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name); 
            } 
            catch (ArgumentException)
            { 
            }

            return null;
        } 

        // 
        // Return a specific culture.  A tad irrelevent now since we always return valid data 
        // for neutral locales.
        // 
        // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
        // if we can't find a bigger name.  That doesn't help with things like "zh" though, so
        // the approach is of questionable value
        // 
#if !FEATURE_CORECLR
        public static CultureInfo CreateSpecificCulture(String name) { 
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo culture; 

            try {
                culture = new CultureInfo(name);
            } catch(ArgumentException) { 
                // When CultureInfo throws this exception, it may be because someone passed the form
                // like "az-az" because it came out of an http accept lang. We should try a little 
                // parsing to perhaps fall back to "az" here and use *it* to create the neutral. 

                int idx; 

                culture = null;
                for(idx = 0; idx < name.Length; idx++) {
                    if('-' == name[idx]) { 
                        try {
                            culture = new CultureInfo(name.Substring(0, idx)); 
                            break; 
                        } catch(ArgumentException) {
                            // throw the original exception so the name in the string will be right 
                            throw;
                        }
                    }
                } 

                if(null == culture) { 
                    // nothing to save here; throw the original exception 
                    throw;
                } 
            }

            //In the most common case, they've given us a specific culture, so we'll just return that.
            if (!(culture.IsNeutralCulture)) { 
                return culture;
            } 
 
            return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE));
        } 
#endif // !FEATURE_CORECLR

        internal static bool VerifyCultureName(String cultureName, bool throwException)
        { 
            // This function is used by ResourceManager.GetResourceFileName().
            // ResourceManager searches for resource using CultureInfo.Name, 
            // so we should check against CultureInfo.Name. 

            for (int i=0; i() != null);
                return Thread.CurrentThread.CurrentCulture;
            }
        } 

        // 
        // This is the equivalence of the Win32 GetUserDefaultLCID() 
        //
        internal static CultureInfo UserDefaultCulture { 
            get
            {
                Contract.Ensures(Contract.Result() != null);
 
                CultureInfo temp = s_userDefaultCulture;
                if (temp == null) 
                { 
                    //
                    // setting the s_userDefaultCulture with invariant culture before intializing it is a protection 
                    // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo
                    // creation path. the recursion can happen if the current user culture is a replaced custom culture.
                    //
 
                    s_userDefaultCulture = CultureInfo.InvariantCulture;
                    temp = InitUserDefaultCulture(); 
                    s_userDefaultCulture = temp; 
                }
                return (temp); 
            }
        }

        // 
        //  This is the equivalence of the Win32 GetUserDefaultUILanguage()
        // 
        internal static CultureInfo UserDefaultUICulture { 
            get {
                Contract.Ensures(Contract.Result() != null); 

                CultureInfo temp = s_userDefaultUICulture;
                if (temp == null)
                { 
                    //
                    // setting the s_userDefaultCulture with invariant culture before intializing it is a protection 
                    // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo 
                    // creation path. the recursion can happen if the current user culture is a replaced custom culture.
                    // 

                    s_userDefaultUICulture = CultureInfo.InvariantCulture;

                    temp = InitUserDefaultUICulture(); 
                    s_userDefaultUICulture = temp;
                } 
                return (temp); 
            }
        } 


        public static CultureInfo CurrentUICulture {
#if !FEATURE_CORECLR 
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
            get { 
                Contract.Ensures(Contract.Result() != null);
                return Thread.CurrentThread.CurrentUICulture; 
            }
        }

 
        //
        // This is the equivalence of the Win32 GetSystemDefaultUILanguage() 
        // 
        //
        public static CultureInfo InstalledUICulture { 
            get {
                Contract.Ensures(Contract.Result() != null);

                CultureInfo temp = s_InstalledUICultureInfo; 
                if (temp == null) {
                    String strDefault = GetSystemDefaultUILanguage(); 
                    temp = GetCultureByName(strDefault, true); 

                    if (temp == null) 
                    {
                        temp = InvariantCulture;
                    }
 
                    temp.m_isReadOnly = true;
                    s_InstalledUICultureInfo = temp; 
                } 
                return (temp);
            } 
        }

        ////////////////////////////////////////////////////////////////////////
        // 
        //  InvariantCulture
        // 
        //  This instance provides methods, for example for casing and sorting, 
        //  that are independent of the system and current user settings.  It
        //  should be used only by processes such as some system services that 
        //  require such invariant results (eg. file systems).  In general,
        //  the results are not linguistically correct and do not match any
        //  culture info.
        // 
        ////////////////////////////////////////////////////////////////////////
 
 
        public static CultureInfo InvariantCulture {
            [Pure] 
#if !FEATURE_CORECLR
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif
            get { 
                Contract.Ensures(Contract.Result() != null);
                return (s_InvariantCultureInfo); 
            } 
        }
 

        ////////////////////////////////////////////////////////////////////////
        //
        //  Parent 
        //
        //  Return the parent CultureInfo for the current instance. 
        // 
        ////////////////////////////////////////////////////////////////////////
 
        public virtual CultureInfo Parent
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                Contract.Ensures(Contract.Result() != null); 
 
                if (null == m_parent)
                { 
                    try
                    {
                        string parentName = this.m_cultureData.SPARENT;
 
                        if (String.IsNullOrEmpty(parentName))
                        { 
                            m_parent = InvariantCulture; 
                        }
                        else 
                        {
                            m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
                        }
                    } 
                    catch (ArgumentException)
                    { 
                        // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant 
                        // We can't allow ourselves to fail.  In case of custom cultures the parent of the
                        // current custom culture isn't installed. 
                        m_parent =  InvariantCulture;
                    }
                }
                return m_parent; 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  LCID
        //
        //  Returns a properly formed culture identifier for the current
        //  culture info. 
        //
        //////////////////////////////////////////////////////////////////////// 
 
#if FEATURE_USE_LCID
        public virtual int LCID { 
#if !FEATURE_CORECLR
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif
            get { 
                return (this.m_cultureData.ILANGUAGE);
            } 
        } 
#endif
 
        ////////////////////////////////////////////////////////////////////////
        //
        //  BaseInputLanguage
        // 
        //  Essentially an LCID, though one that may be different than LCID in the case
        //  of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED). 
        // 
        ////////////////////////////////////////////////////////////////////////
#if FEATURE_USE_LCID 
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int KeyboardLayoutId
        {
            get 
            {
                int keyId = this.m_cultureData.IINPUTLANGUAGEHANDLE; 
 
                // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID.
                return (keyId); 
            }
        }
#endif
 
#if !FEATURE_CORECLR && !CORIOLIS
        public static CultureInfo[] GetCultures(CultureTypes types) { 
            Contract.Ensures(Contract.Result() != null); 
            // internally we treat UserCustomCultures as Supplementals but v2
            // treats as Supplementals and Replacements 
            if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture)
            {
                types |= CultureTypes.ReplacementCultures;
            } 
            return (CultureData.GetCultures(types));
        } 
#endif 

        //////////////////////////////////////////////////////////////////////// 
        //
        //  Name
        //
        //  Returns the full name of the CultureInfo. The name is in format like 
        //  "en-US"  This version does NOT include sort information in the name.
        // 
        //////////////////////////////////////////////////////////////////////// 
        public virtual String Name {
            get { 
                Contract.Ensures(Contract.Result() != null);

                // We return non sorting name here.
                if (this.m_nonSortName == null) { 
                    this.m_nonSortName = this.m_cultureData.SNAME;
                    if (this.m_nonSortName == null) { 
                        this.m_nonSortName = String.Empty; 
                    }
                } 
                return this.m_nonSortName;
            }
        }
 
        // This one has the sort information (ie: de-DE_phoneb)
        internal String SortName 
        { 
            get
            { 
                if (this.m_sortName == null)
                {
                    this.m_sortName = this.m_cultureData.SCOMPAREINFO;
                } 

                return this.m_sortName; 
            } 
        }
 
        //
#if !FEATURE_CORECLR
        [System.Runtime.InteropServices.ComVisible(false)]
        public String IetfLanguageTag 
        {
            get 
            { 
                Contract.Ensures(Contract.Result() != null);
 
                // special case the compatibility cultures
                switch (this.Name)
                {
                    case "zh-CHT": 
                        return "zh-Hant";
                    case "zh-CHS": 
                        return "zh-Hans"; 
                    default:
                        return this.Name; 
                }
            }
        }
#endif 

        //////////////////////////////////////////////////////////////////////// 
        // 
        //  DisplayName
        // 
        //  Returns the full name of the CultureInfo in the localized language.
        //  For example, if the localized language of the runtime is Spanish and the CultureInfo is
        //  US English, "Ingles (Estados Unidos)" will be returned.
        // 
        ////////////////////////////////////////////////////////////////////////
        public virtual String DisplayName 
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                Contract.Ensures(Contract.Result() != null);
                Contract.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set");
 
                return m_cultureData.SLOCALIZEDDISPLAYNAME;
            } 
        } 

        //////////////////////////////////////////////////////////////////////// 
        //
        //  GetNativeName
        //
        //  Returns the full name of the CultureInfo in the native language. 
        //  For example, if the CultureInfo is US English, "English
        //  (United States)" will be returned. 
        // 
        ////////////////////////////////////////////////////////////////////////
        public virtual String NativeName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SNATIVEDISPLAYNAME); 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  GetEnglishName
        //
        //  Returns the full name of the CultureInfo in English.
        //  For example, if the CultureInfo is US English, "English 
        //  (United States)" will be returned.
        // 
        //////////////////////////////////////////////////////////////////////// 
        public virtual String EnglishName {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SENGDISPLAYNAME);
            } 
        }
 
        // ie: en 
        public virtual String TwoLetterISOLanguageName {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SISO639LANGNAME);
            } 
        }
 
#if !FEATURE_CORECLR && !CORIOLIS 
        // ie: eng
        public virtual String ThreeLetterISOLanguageName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SISO639LANGNAME2); 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  ThreeLetterWindowsLanguageName
        //
        //  Returns the 3 letter windows language name for the current instance.  eg: "ENU"
        //  The ISO names are much preferred 
        //
        //////////////////////////////////////////////////////////////////////// 
        public virtual String ThreeLetterWindowsLanguageName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SABBREVLANGNAME);
            }
        } 
#endif
 
        //////////////////////////////////////////////////////////////////////// 
        //
        //  CompareInfo               Read-Only Property 
        //
        //  Gets the CompareInfo for this culture.
        //
        //////////////////////////////////////////////////////////////////////// 
        public virtual CompareInfo CompareInfo
        { 
            get 
            {
                Contract.Ensures(Contract.Result() != null); 

                if (this.compareInfo == null)
                {
                    // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from 
                    // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
                    CompareInfo temp = UseUserOverride 
                                        ? GetCultureInfo(this.m_name).CompareInfo 
                                        : new CompareInfo(this);
                    if (OkayToCacheClassWithCompatibilityBehavior) 
                    {
                        this.compareInfo = temp;
                    }
                    else 
                    {
                        return temp; 
                    } 
                }
                return (compareInfo); 
            }
        }

        static private bool OkayToCacheClassWithCompatibilityBehavior 
        {
            get 
            { 
                // only cache compareInfo and textInfo once the AppDomain compatibility settings
                // are available for the domain (It doesn't matter which compatibility switch we check 
                // for -- it will only have a value once the compatibility switches have been initialized)
                Nullable compatSwitch = AppDomain.CurrentDomain.IsCompatibilitySwitchSet("a");
                return compatSwitch.HasValue;
            } 
        }
 
#if !FEATURE_CORECLR 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  RegionInfo
        //
        //  Gets the RegionInfo for this culture.
        // 
        ////////////////////////////////////////////////////////////////////////
        private RegionInfo Region 
        { 
            get
            { 
                if (regionInfo==null)
                {
                    // Make a new regionInfo
                    RegionInfo tempRegionInfo = new RegionInfo(this.m_cultureData); 
                    regionInfo = tempRegionInfo;
                } 
                return (regionInfo); 
            }
        } 
#endif // FEATURE_CORECLR


 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  TextInfo 
        //
        //  Gets the TextInfo for this culture. 
        //
        ////////////////////////////////////////////////////////////////////////

 
        public virtual TextInfo TextInfo {
            get { 
                Contract.Ensures(Contract.Result() != null); 

                if (textInfo==null) 
                {
                    // Make a new textInfo
                    TextInfo tempTextInfo = new TextInfo(this.m_cultureData);
                    tempTextInfo.SetReadOnlyState(m_isReadOnly); 

                    if (OkayToCacheClassWithCompatibilityBehavior) 
                    { 
                        textInfo = tempTextInfo;
                    } 
                    else
                    {
                        return tempTextInfo;
                    } 
                }
                return (textInfo); 
            } 
        }
 
        ////////////////////////////////////////////////////////////////////////
        //
        //  Equals
        // 
        //  Implements Object.Equals().  Returns a boolean indicating whether
        //  or not object refers to the same CultureInfo as the current instance. 
        // 
        ////////////////////////////////////////////////////////////////////////
 

        public override bool Equals(Object value)
        {
            if (Object.ReferenceEquals(this, value)) 
                return true;
 
            CultureInfo that = value as CultureInfo; 

            if (that != null) 
            {
                // using CompareInfo to verify the data passed through the constructor
                // CultureInfo(String cultureName, String textAndCompareCultureName)
 
                return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo));
            } 
 
            return (false);
        } 


        ////////////////////////////////////////////////////////////////////////
        // 
        //  GetHashCode
        // 
        //  Implements Object.GetHashCode().  Returns the hash code for the 
        //  CultureInfo.  The hash code is guaranteed to be the same for CultureInfo A
        //  and B where A.Equals(B) is true. 
        //
        ////////////////////////////////////////////////////////////////////////

#if !FEATURE_CORECLR 
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public override int GetHashCode() 
        {
            return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode()); 
        }


        //////////////////////////////////////////////////////////////////////// 
        //
        //  ToString 
        // 
        //  Implements Object.ToString().  Returns the name of the CultureInfo,
        //  eg. "de-DE_phoneb", "en-US", or "fj-FJ". 
        //
        ////////////////////////////////////////////////////////////////////////

 
        public override String ToString()
        { 
            Contract.Ensures(Contract.Result() != null); 

            Contract.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set"); 
            return m_name;
        }

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public virtual Object GetFormat(Type formatType) { 
            if (formatType == typeof(NumberFormatInfo)) { 
                return (NumberFormat);
            } 
            if (formatType == typeof(DateTimeFormatInfo)) {
                return (DateTimeFormat);
            }
            return (null); 
        }
 
        public virtual bool IsNeutralCulture { 
            get {
                return this.m_cultureData.IsNeutralCulture; 
            }
        }

#if !FEATURE_CORECLR 
        [System.Runtime.InteropServices.ComVisible(false)]
        public CultureTypes CultureTypes 
        { 
            get
            { 
                CultureTypes types = 0;

                if (m_cultureData.IsNeutralCulture)
                    types |= CultureTypes.NeutralCultures; 
                else
                    types |= CultureTypes.SpecificCultures; 
 
                types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0;
 
// Disable  warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
#pragma warning disable 618
                types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0;
 
#pragma warning restore 618
                types |= m_cultureData.IsUserCustomCulture ? CultureTypes.UserCustomCulture : 0; 
                types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; 

                return types; 
            }
        }
#endif
 
        public virtual NumberFormatInfo NumberFormat {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                Contract.Ensures(Contract.Result() != null); 

                if (numInfo == null) {
                    NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData);
                    temp.isReadOnly = m_isReadOnly; 
                    numInfo = temp;
                } 
                return (numInfo); 
            }
            set { 
                if (value == null) {
                    throw new ArgumentNullException("value",
                        Environment.GetResourceString("ArgumentNull_Obj"));
                } 
                Contract.EndContractBlock();
                VerifyWritable(); 
                numInfo = value; 
            }
        } 

        ////////////////////////////////////////////////////////////////////////
        //
        // GetDateTimeFormatInfo 
        //
        // Create a DateTimeFormatInfo, and fill in the properties according to 
        // the CultureID. 
        //
        //////////////////////////////////////////////////////////////////////// 


        public virtual DateTimeFormatInfo DateTimeFormat {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null); 
 
                if (dateTimeInfo == null) {
                    // Change the calendar of DTFI to the specified calendar of this CultureInfo. 
                    DateTimeFormatInfo temp = new DateTimeFormatInfo(
                        this.m_cultureData, this.Calendar);
                    temp.m_isReadOnly = m_isReadOnly;
                    System.Threading.Thread.MemoryBarrier(); 
                    dateTimeInfo = temp;
                } 
                return (dateTimeInfo); 
            }
 
            set {
                if (value == null) {
                    throw new ArgumentNullException("value",
                        Environment.GetResourceString("ArgumentNull_Obj")); 
                }
                Contract.EndContractBlock(); 
                VerifyWritable(); 
                dateTimeInfo = value;
            } 
        }


 
        public void ClearCachedData() {
            s_userDefaultUICulture = null; 
            s_userDefaultCulture = null; 

            RegionInfo.s_currentRegionInfo = null; 
#if !FEATURE_CORECLR && !FEATURE_PAL // System.TimeZone does not exist in CoreCLR or in Coriolis
            TimeZone.ResetTimeZone();
#endif // FEATURE_CORECLR
            TimeZoneInfo.ClearCachedData(); 
            // Delete the cached cultures.
            s_LcidCachedCultures = null; 
            s_NameCachedCultures = null; 

            CultureData.ClearCachedData(); 
        }

        /*=================================GetCalendarInstance==========================
        **Action: Map a Win32 CALID to an instance of supported calendar. 
        **Returns: An instance of calendar.
        **Arguments: calType    The Win32 CALID 
        **Exceptions: 
        **      Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
        **      If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar. 
        ============================================================================*/
        internal static Calendar GetCalendarInstance(int calType) {
            if (calType==Calendar.CAL_GREGORIAN) {
                return (new GregorianCalendar()); 
            }
            return GetCalendarInstanceRare(calType); 
        } 

        //This function exists as a shortcut to prevent us from loading all of the non-gregorian 
        //calendars unless they're required.
        internal static Calendar GetCalendarInstanceRare(int calType) {
            Contract.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN");
 
            switch (calType) {
                case Calendar.CAL_GREGORIAN_US:               // Gregorian (U.S.) calendar 
                case Calendar.CAL_GREGORIAN_ME_FRENCH:        // Gregorian Middle East French calendar 
                case Calendar.CAL_GREGORIAN_ARABIC:           // Gregorian Arabic calendar
                case Calendar.CAL_GREGORIAN_XLIT_ENGLISH:     // Gregorian Transliterated English calendar 
                case Calendar.CAL_GREGORIAN_XLIT_FRENCH:      // Gregorian Transliterated French calendar
                    return (new GregorianCalendar((GregorianCalendarTypes)calType));
                case Calendar.CAL_TAIWAN:                     // Taiwan Era calendar
                    return (new TaiwanCalendar()); 
                case Calendar.CAL_JAPAN:                      // Japanese Emperor Era calendar
                    return (new JapaneseCalendar()); 
                case Calendar.CAL_KOREA:                      // Korean Tangun Era calendar 
                    return (new KoreanCalendar());
                case Calendar.CAL_THAI:                       // Thai calendar 
                    return (new ThaiBuddhistCalendar());
                case Calendar.CAL_HIJRI:                      // Hijri (Arabic Lunar) calendar
                    return (new HijriCalendar());
                case Calendar.CAL_HEBREW:                     // Hebrew (Lunar) calendar 
                    return (new HebrewCalendar());
                case Calendar.CAL_UMALQURA: 
                    return (new UmAlQuraCalendar()); 
#if !FEATURE_ONLY_CORE_CALENDARS
                case Calendar.CAL_PERSIAN: 
                    return (new PersianCalendar());
                case Calendar.CAL_CHINESELUNISOLAR:
                    return (new ChineseLunisolarCalendar());
                case Calendar.CAL_JAPANESELUNISOLAR: 
                    return (new JapaneseLunisolarCalendar());
                case Calendar.CAL_KOREANLUNISOLAR: 
                    return (new KoreanLunisolarCalendar()); 
                case Calendar.CAL_TAIWANLUNISOLAR:
                    return (new TaiwanLunisolarCalendar()); 
#endif // !FEATURE_ONLY_CORE_CALENDARS
            }
            return (new GregorianCalendar());
        } 

 
        /*=================================Calendar========================== 
        **Action: Return/set the default calendar used by this culture.
        ** This value can be overridden by regional option if this is a current culture. 
        **Returns:
        **Arguments:
        **Exceptions:
        **  ArgumentNull_Obj if the set value is null. 
        ============================================================================*/
 
 
        public virtual Calendar Calendar {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                if (calendar == null) {
                    Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); 
                    // Get the default calendar for this culture.  Note that the value can be
                    // from registry if this is a user default culture. 
                    Calendar newObj = this.m_cultureData.DefaultCalendar; 

                    System.Threading.Thread.MemoryBarrier(); 
                    newObj.SetReadOnlyState(m_isReadOnly);
                    calendar = newObj;
                }
                return (calendar); 
            }
        } 
 
        /*=================================OptionCalendars==========================
        **Action: Return an array of the optional calendar for this culture. 
        **Returns: an array of Calendar.
        **Arguments:
        **Exceptions:
        ============================================================================*/ 

 
        public virtual Calendar[] OptionalCalendars { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                Contract.Ensures(Contract.Result() != null);

                //
                // This property always returns a new copy of the calendar array. 
                //
                int[] calID = this.m_cultureData.CalendarIds; 
                Calendar [] cals = new Calendar[calID.Length]; 
                for (int i = 0; i < cals.Length; i++) {
                    cals[i] = GetCalendarInstance(calID[i]); 
                }
                return (cals);
            }
        } 

 
        public bool UseUserOverride { 
            get {
                return (this.m_cultureData.UseUserOverride); 
            }
        }

#if !FEATURE_CORECLR && !CORIOLIS 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(false)] 
        public CultureInfo GetConsoleFallbackUICulture() 
        {
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo temp = m_consoleFallbackCulture;
            if (temp == null)
            { 
                temp = CreateSpecificCulture(this.m_cultureData.SCONSOLEFALLBACKNAME);
                temp.m_isReadOnly = true; 
                m_consoleFallbackCulture = temp; 
            }
            return (temp); 
        }
#endif

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public virtual Object Clone()
        { 
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo ci = (CultureInfo)MemberwiseClone(); 
            ci.m_isReadOnly = false;

            //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
            //they've already been allocated.  If this is a derived type, we'll take a more generic codepath. 
            if (!m_isInherited)
            { 
                if (this.dateTimeInfo != null) 
                {
                    ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone(); 
                }
                if (this.numInfo != null)
                {
                    ci.numInfo = (NumberFormatInfo)this.numInfo.Clone(); 
                }
 
            } 
            else
            { 
                ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
                ci.NumberFormat   = (NumberFormatInfo)this.NumberFormat.Clone();
            }
 
            if (textInfo != null)
            { 
                ci.textInfo = (TextInfo) textInfo.Clone(); 
            }
 
            if (calendar != null)
            {
                ci.calendar = (Calendar) calendar.Clone();
            } 

            return (ci); 
        } 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public static CultureInfo ReadOnly(CultureInfo ci) {
            if (ci == null) {
                throw new ArgumentNullException("ci"); 
            }
            Contract.Ensures(Contract.Result() != null); 
            Contract.EndContractBlock(); 

            if (ci.IsReadOnly) { 
                return (ci);
            }
            CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
 
            if (!ci.IsNeutralCulture)
            { 
                //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless 
                //they've already been allocated.  If this is a derived type, we'll take a more generic codepath.
                if (!ci.m_isInherited) { 
                    if (ci.dateTimeInfo != null) {
                        newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo);
                    }
                    if (ci.numInfo != null) { 
                        newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo);
                    } 
 
                } else {
                    newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat); 
                    newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
                }
            }
 
            if (ci.textInfo != null)
            { 
                newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo); 
            }
 
            if (ci.calendar != null)
            {
                newInfo.calendar = Calendar.ReadOnly(ci.calendar);
            } 

            // Don't set the read-only flag too early. 
            // We should set the read-only flag here.  Otherwise, info.DateTimeFormat will not be able to set. 
            newInfo.m_isReadOnly = true;
 
            return (newInfo);
        }

 
        public bool IsReadOnly {
            get { 
                return (m_isReadOnly); 
            }
        } 

        private void VerifyWritable() {
            if (m_isReadOnly) {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); 
            }
            Contract.EndContractBlock(); 
        } 

        // For resource lookup, we consider a culture the invariant culture by name equality. 
        // We perform this check frequently during resource lookup, so adding a property for
        // improved readability.
        internal bool HasInvariantCultureName
        { 
            get { return Name == CultureInfo.InvariantCulture.Name; }
        } 
 
        // Helper function both both overloads of GetCachedReadOnlyCulture.  If lcid is 0, we use the name.
        // If lcid is -1, use the altName and create one of those special SQL cultures. 
        internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName)
        {
            // There is a race condition in this code with the side effect that the second thread's value
            // clobbers the first in the dictionary. This is an acceptable ---- since the CultureInfo objects 
            // are content equal (but not reference equal). Since we make no guarantees there, this ---- is
            // acceptable. 
            // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus 
            // Hashtable thread safety.
 
            // retval is our return value.
            CultureInfo retval;

            // Temporary hashtable for the names. 
            Hashtable tempNameHT = s_NameCachedCultures;
 
            if (name != null) 
            {
                name = CultureData.AnsiToLower(name); 
            }

            if (altName != null)
            { 
                altName = CultureData.AnsiToLower(altName);
            } 
 
            // We expect the same result for both hashtables, but will test individually for added safety.
            if (tempNameHT == null) 
            {
                tempNameHT = Hashtable.Synchronized(new Hashtable());
            }
            else 
            {
                // If we are called by name, check if the object exists in the hashtable.  If so, return it. 
                if (lcid == -1) 
                {
                    retval = (CultureInfo)tempNameHT[name + '\xfffd' + altName]; 
                    if (retval != null)
                    {
                        return retval;
                    } 
                }
                else if (lcid == 0) 
                { 
                    retval = (CultureInfo)tempNameHT[name];
                    if (retval != null) 
                    {
                        return retval;
                    }
                } 
            }
#if FEATURE_USE_LCID 
            // Next, the Lcid table. 
            Hashtable tempLcidHT = s_LcidCachedCultures;
 
            if (tempLcidHT == null)
            {
                // Case insensitive is not an issue here, save the constructor call.
                tempLcidHT = Hashtable.Synchronized(new Hashtable()); 
            }
            else 
            { 
                // If we were called by Lcid, check if the object exists in the table.  If so, return it.
                if (lcid > 0) 
                {
                    retval = (CultureInfo) tempLcidHT[lcid];
                    if (retval != null)
                    { 
                        return retval;
                    } 
                } 
            }
#endif 
            // We now have two temporary hashtables and the desired object was not found.
            // We'll construct it.  We catch any exceptions from the constructor call and return null.
            try
            { 
                switch(lcid)
                { 
                    case -1: 
                        // call the private constructor
                        retval = new CultureInfo(name, altName); 
                        break;

                    case 0:
                        retval = new CultureInfo(name, false); 
                        break;
 
                    default: 
#if FEATURE_USE_LCID
                        retval = new CultureInfo(lcid, false); 
                        break;
#else
                        return null;
#endif 
                }
            } 
            catch(ArgumentException) 
            {
                return null; 
            }

            // Set it to read-only
            retval.m_isReadOnly = true; 

            if (lcid == -1) 
            { 
                // This new culture will be added only to the name hash table.
                tempNameHT[name + '\xfffd' + altName] = retval; 

                // when lcid == -1 then TextInfo object is already get created and we need to set it as read only.
                retval.TextInfo.SetReadOnlyState(true);
            } 
            else
            { 
                // Remember our name (as constructed).  Do NOT use alternate sort name versions because 
                // we have internal state representing the sort.  (So someone would get the wrong cached version)
                string newName = CultureData.AnsiToLower(retval.m_name); 

                // We add this new culture info object to both tables.
                tempNameHT[newName] = retval;
#if FEATURE_USE_LCID 
                const int LCID_ZH_CHS_HANS = 0x0004;
                const int LCID_ZH_CHT_HANT = 0x7c04; 
 
                if ((retval.LCID == LCID_ZH_CHS_HANS && newName == "zh-hans")
                 || (retval.LCID == LCID_ZH_CHT_HANT && newName == "zh-hant")) 
                {
                    // do nothing because we only want zh-CHS and zh-CHT to cache
                    // by lcid
                } 
                else
                { 
                    tempLcidHT[retval.LCID] = retval; 
                }
 
#endif
            }

#if FEATURE_USE_LCID 
            // Copy the two hashtables to the corresponding member variables.  This will potentially overwrite
            // new tables simultaneously created by a new thread, but maximizes thread safety. 
            if(-1 != lcid) 
            {
                // Only when we modify the lcid hash table, is there a need to overwrite. 
                s_LcidCachedCultures = tempLcidHT;
            }
#endif
 
            s_NameCachedCultures = tempNameHT;
 
            // Finally, return our new CultureInfo object. 
            return retval;
        } 

#if FEATURE_USE_LCID
        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found).  (LCID version)... use named version 
        public static CultureInfo GetCultureInfo(int culture)
        { 
            // Must check for -1 now since the helper function uses the value to signal 
            // the altCulture code path for SQL Server.
            // Also check for zero as this would fail trying to add as a key to the hash. 
            if (culture <= 0) {
                throw new ArgumentOutOfRangeException("culture",
                    Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 
            CultureInfo retval = GetCultureInfoHelper(culture, null, null); 
            if (null == retval)
            { 
                throw new CultureNotFoundException(
                    "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
            }
            return retval; 
        }
#endif 
 
        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found).  (Named version) 
        public static CultureInfo GetCultureInfo(string name)
        {
            // Make sure we have a valid, non-zero length string as name
            if (name == null) 
            {
                throw new ArgumentNullException("name"); 
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 

            CultureInfo retval = GetCultureInfoHelper(0, name, null);
            if (retval == null)
            { 
                throw new CultureNotFoundException(
                    "name", name, Environment.GetResourceString("Argument_CultureNotSupported")); 
 
            }
            return retval; 
        }

        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found). 
        public static CultureInfo GetCultureInfo(string name, string altName)
        { 
            // Make sure we have a valid, non-zero length string as name 
            if (null == name)
            { 
                throw new ArgumentNullException("name");
            }

            if (null == altName) 
            {
                throw new ArgumentNullException("altName"); 
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 

            CultureInfo retval = GetCultureInfoHelper(-1, name, altName);
            if (retval == null)
            { 
                throw new CultureNotFoundException("name or altName",
                                        String.Format( 
                                            CultureInfo.CurrentCulture, 
                                            Environment.GetResourceString("Argument_OneOfCulturesNotSupported"),
                                            name, 
                                            altName));
            }
            return retval;
        } 

 
#if !FEATURE_CORECLR 
        // This function is deprecated, we don't like it
        public static CultureInfo GetCultureInfoByIetfLanguageTag(string name) 
        {
            Contract.Ensures(Contract.Result() != null);

            // Disallow old zh-CHT/zh-CHS names 
            if (name == "zh-CHT" || name == "zh-CHS")
            { 
                throw new CultureNotFoundException( 
                            "name",
                            String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) 
                            );
            }

            CultureInfo ci = GetCultureInfo(name); 

            // Disallow alt sorts and es-es_TS 
            if (ci.LCID > 0xffff || ci.LCID == 0x040a) 
            {
                throw new CultureNotFoundException( 
                            "name",
                            String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
                            );
            } 

            return ci; 
        } 
#endif
        private static bool? s_isTaiwanSku; 
        internal static bool Is----Sku
        {
            get
            { 
                if (s_isTaiwanSku == null)
                { 
                    s_isTaiwanSku = (GetSystemDefaultUILanguage() == "zh-TW"); 
                }
                return (bool)s_isTaiwanSku; 
            }
        }

        // 
        //  Helper Methods.
        // 
 
        // Get Locale Info Ex calls.  So we don't have to muck with the different int/string return types we declared two of these:
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern String nativeGetLocaleInfoEx(String localeName, uint field);
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field);
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeSetThreadLocale(String localeName); 

        [System.Security.SecurityCritical] 
        private static String GetDefaultLocaleName(int localeType) 
        {
            Contract.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT"); 

            string localeName = null;
            if(InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName)))
            { 
                return localeName;
            } 
            return string.Empty; 
        }
 
        // Get the default locale name
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [SuppressUnmanagedCodeSecurity] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString); 

        [System.Security.SecuritySafeCritical] // auto-generated 
        private static String GetUserDefaultUILanguage()
        {
            string userDefaultUiLanguage = null;
            if(InternalGetUserDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref userDefaultUiLanguage))) 
            {
                return userDefaultUiLanguage; 
            } 
            return String.Empty;
        } 

        // Get the user's default UI language, return locale name
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [SuppressUnmanagedCodeSecurity]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage);
 
        [System.Security.SecuritySafeCritical] // auto-generated
        private static String GetSystemDefaultUILanguage()
        {
            string systemDefaultUiLanguage = null; 
            if(InternalGetSystemDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref systemDefaultUiLanguage)))
            { 
                return systemDefaultUiLanguage; 
            }
            return String.Empty; 

        }

        [System.Security.SecurityCritical] // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        [SuppressUnmanagedCodeSecurity] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage);

/* Disabled for CLR v4
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern String[] nativeGetResourceFallbackArray(); 
*/
    } 
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
////////////////////////////////////////////////////////////////////////////
// 
//  Class:    CultureInfo 
//
// 
//  Purpose:  This class represents the software preferences of a particular
//            culture or community.  It includes information such as the
//            language, writing system, and a calendar used by the culture
//            as well as methods for common operations such as printing 
//            dates and sorting strings.
// 
//  Date:     [....] 31, 1999 
//
// 
//  !!!! NOTE WHEN CHANGING THIS CLASS !!!!
//
//  If adding or removing members to this class, please update CultureInfoBaseObject
//  in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be 
//  different than the order in which members are declared. For instance, all
//  reference types will come first in the class before value types (like ints, bools, etc) 
//  regardless of the order in which they are declared. The best way to see the 
//  actual order of the class is to do a !dumpobj on an instance of the managed
//  object inside of the debugger. 
//
////////////////////////////////////////////////////////////////////////////

namespace System.Globalization { 
    using System;
    using System.Security; 
    using System.Threading; 
    using System.Collections;
    using System.Runtime; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization;
    using System.Runtime.Versioning; 
    using System.Security.Permissions;
    using System.Reflection; 
    using Microsoft.Win32; 
    using System.Diagnostics.Contracts;
 
    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public class CultureInfo : ICloneable, IFormatProvider {
        //--------------------------------------------------------------------// 
        //                        Internal Information                        //
        //-------------------------------------------------------------------// 
 
        //-------------------------------------------------------------------//
        // Data members to be serialized: 
        //-------------------------------------------------------------------//

        // We use an RFC4646 type string to construct CultureInfo.
        // This string is stored in m_name and is authoritative. 
        // We use the m_cultureData to get the data for our object
 
        // WARNING 
        // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h
        // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot 
        // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject
        // WARNING: must be manually structured to match the true loaded class layout
        // WARNING
        internal bool m_isReadOnly; 
        internal CompareInfo compareInfo;
        internal TextInfo textInfo; 
        // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK) 
#if !FEATURE_CORECLR
        [NonSerialized]internal RegionInfo regionInfo; 
#endif
        internal NumberFormatInfo numInfo;
        internal DateTimeFormatInfo dateTimeInfo;
        internal Calendar calendar; 
#if !FEATURE_CORECLR
        [OptionalField(VersionAdded = 1)] 
        internal int m_dataItem;       // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) 
        [OptionalField(VersionAdded = 1)]
        internal int cultureID  = 0x007f;  // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett) 
#endif // !FEATURE_CORECLR
        //
        // The CultureData instance that we are going to read data from.
        // For supported culture, this will be the CultureData instance that read data from mscorlib assembly. 
        // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
        // 
        [NonSerialized]internal CultureData m_cultureData; 

        [NonSerialized]internal bool m_isInherited; 
#if FEATURE_LEAK_CULTURE_INFO
        [NonSerialized]private bool m_isSafeCrossDomain;
#endif // !FEATURE_CORECLR
        [NonSerialized] 
        private int m_createdDomainID;
#if !FEATURE_CORECLR 
        [NonSerialized]private CultureInfo m_consoleFallbackCulture; 
#endif // !FEATURE_CORECLR
 
        // Names are confusing.  Here are 3 names we have:
        //
        //  new CultureInfo()   m_name        m_nonSortName   m_sortName
        //      en-US           en-US           en-US           en-US 
        //      de-de_phoneb    de-DE_phoneb    de-DE           de-DE_phoneb
        //      fj-fj (custom)  fj-FJ           fj-FJ           en-US (if specified sort is en-US) 
        //      en              en 
        //
        // Note that in Silverlight we ask the OS for the text and sort behavior, so the 
        // textinfo and compareinfo names are the same as the name

        // Note that the name used to be serialized for Everett; it is now serialized
        // because alernate sorts can have alternate names. 
        // This has a de-DE, de-DE_phoneb or fj-FJ style name
        internal string m_name; 
 
        // This will hold the non sorting name to be returned from CultureInfo.Name property.
        // This has a de-DE style name even for de-DE_phoneb type cultures 
        [NonSerialized]private string m_nonSortName;

        // This will hold the sorting name to be returned from CultureInfo.SortName property.
        // This might be completely unrelated to the culture name if a custom culture.  Ie en-US for fj-FJ. 
        // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
        [NonSerialized]private string m_sortName; 
 

        //--------------------------------------------------------------------// 
        //
        // Static data members
        //
        //-------------------------------------------------------------------// 

        //Get the current user default culture.  This one is almost always used, so we create it by default. 
        private static CultureInfo s_userDefaultCulture; 

        // 
        // All of the following will be created on demand.
        //

        //The Invariant culture; 
        private static CultureInfo s_InvariantCultureInfo;
 
        //The culture used in the user interface. This is mostly used to load correct localized resources. 
        private static CultureInfo s_userDefaultUICulture;
 
        //This is the UI culture used to install the OS.
        private static CultureInfo s_InstalledUICultureInfo;

        //This is a cache of all previously created cultures.  Valid keys are LCIDs or the name.  We use two hashtables to track them, 
        // depending on how they are called.
        private static Hashtable s_LcidCachedCultures; 
        private static Hashtable s_NameCachedCultures; 

        //The parent culture. 
        [NonSerialized]private CultureInfo m_parent;

        // LOCALE constants of interest to us internally and privately for LCID functions
        // (ie: avoid using these and use names if possible) 
        internal const int LOCALE_NEUTRAL              = 0x0000;
        private  const int LOCALE_USER_DEFAULT         = 0x0400; 
        private  const int LOCALE_SYSTEM_DEFAULT       = 0x0800; 
        internal const int LOCALE_CUSTOM_DEFAULT       = 0x0c00;
        internal const int LOCALE_CUSTOM_UNSPECIFIED   = 0x1000; 
        internal const int LOCALE_INVARIANT            = 0x007F;
        private  const int LOCALE_TRADITIONAL_SPANISH  = 0x040a;

        // 
        // The CultureData  instance that reads the data provided by our CultureData class.
        // 
        //Using a field initializer rather than a static constructor so that the whole class can be lazy 
        //init.
        private static readonly bool init = Init(); 
        private static bool Init()
        {

            if (s_InvariantCultureInfo == null) 
            {
                CultureInfo temp = new CultureInfo("", false); 
                temp.m_isReadOnly = true; 
                s_InvariantCultureInfo = temp;
            } 
            // First we set it to Invariant in case someone needs it before we're done finding it.
            // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid
            // s_userDefaultCulture to be used in Thread.CurrentCulture.
            s_userDefaultCulture = s_userDefaultUICulture = s_InvariantCultureInfo; 

            s_userDefaultCulture = InitUserDefaultCulture(); 
            s_userDefaultUICulture = InitUserDefaultUICulture(); 
            return true;
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated
        static CultureInfo InitUserDefaultCulture()
        { 
            String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT);
            if (strDefault == null) 
            { 
                strDefault = GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT);
 
                if (strDefault == null)
                {
                    // If system default doesn't work, keep using the invariant
                    return (CultureInfo.InvariantCulture); 
                }
            } 
            CultureInfo temp = GetCultureByName(strDefault, true); 

            temp.m_isReadOnly = true; 

            return (temp);
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        static CultureInfo InitUserDefaultUICulture() 
        { 
            String strDefault = GetUserDefaultUILanguage();
 
            // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible.
            if (strDefault == UserDefaultCulture.Name)
            {
                return (UserDefaultCulture); 
            }
 
            CultureInfo temp = GetCultureByName( strDefault, true); 

            if (temp == null) 
            {
                return (CultureInfo.InvariantCulture);
            }
 
            temp.m_isReadOnly = true;
 
            return (temp); 
        }
 


        ////////////////////////////////////////////////////////////////////////
        // 
        //  CultureInfo Constructors
        // 
        //////////////////////////////////////////////////////////////////////// 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
#if !FEATURE_CORECLR
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public CultureInfo(String name) : this(name, true) {
        } 
 

        public CultureInfo(String name, bool useUserOverride) { 
            if (name==null) {
                throw new ArgumentNullException("name",
                    Environment.GetResourceString("ArgumentNull_String"));
            } 
            Contract.EndContractBlock();
 
            // Get our data providing record 
            this.m_cultureData = CultureData.GetCultureData(name, useUserOverride);
 
            if (this.m_cultureData == null)
                throw new CultureNotFoundException(
                    "name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            this.m_name = this.m_cultureData.CultureName;
            this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo)); 
        } 

 
#if  FEATURE_USE_LCID
        public CultureInfo(int culture) : this(culture, true) {
        }
 
        public CultureInfo(int culture, bool useUserOverride) {
            // We don't check for other invalid LCIDS here... 
            if (culture < 0) { 
                throw new ArgumentOutOfRangeException("culture",
                    Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); 
            }
            Contract.EndContractBlock();

            InitializeFromCultureId(culture, useUserOverride); 
        }
 
        private void InitializeFromCultureId(int culture, bool useUserOverride) 
        {
            switch (culture) 
            {
                case LOCALE_CUSTOM_DEFAULT:
                case LOCALE_SYSTEM_DEFAULT:
                case LOCALE_NEUTRAL: 
                case LOCALE_USER_DEFAULT:
                case LOCALE_CUSTOM_UNSPECIFIED: 
                    // Can't support unknown custom cultures and we do not support neutral or 
                    // non-custom user locales.
                    throw new CultureNotFoundException( 
                        "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));

                default:
                    // Now see if this LCID is supported in the system default CultureData  table. 
                    this.m_cultureData = CultureData.GetCultureData(culture, useUserOverride);
                    break; 
            } 
            this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
            this.m_name = this.m_cultureData.CultureName; 
        }
#endif // FEATURE_USE_LCID

        // 
        // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to
        // other object (like CultureInfo or DateTimeFormatInfo). 
        // 

        internal static void CheckDomainSafetyObject(Object obj, Object container) 
        {
            if (obj.GetType().Assembly != typeof(System.Globalization.CultureInfo).Assembly) {

                throw new InvalidOperationException( 
                            String.Format(
                                CultureInfo.CurrentCulture, 
                                Environment.GetResourceString("InvalidOperation_SubclassedObject"), 
                                obj.GetType(),
                                container.GetType())); 
            }
            Contract.EndContractBlock();
        }
 
#region Serialization
        // We need to store the override from the culture data record. 
        private bool    m_useUserOverride; 

        [OnDeserialized] 
        private void OnDeserialized(StreamingContext ctx)
        {
#if  FEATURE_USE_LCID
            // Whidbey+ should remember our name 
            // but v1 and v1.1 did not store name -- only lcid
            // Whidbey did not store actual alternate sort name in m_name 
            //   like we do in v4 so we can't use name for alternate sort 
            // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl
            if (m_name == null || IsAlternateSortLcid(cultureID)) 
            {
                Contract.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0");
                InitializeFromCultureId(cultureID, m_useUserOverride);
            } 
            else
            { 
#endif 
                Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null");
                // 

                this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride);
                if (this.m_cultureData == null)
                    throw new CultureNotFoundException( 
                        "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported"));
 
#if  FEATURE_USE_LCID 
            }
#endif 
            m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));

            // in case we have non customized CultureInfo object we shouldn't allow any customized object
            // to be attached to it for cross app domain safety. 
            if (this.GetType().Assembly == typeof(System.Globalization.CultureInfo).Assembly)
            { 
                if (textInfo != null) 
                {
                    CheckDomainSafetyObject(textInfo, this); 
                }

                if (compareInfo != null)
                { 
                    CheckDomainSafetyObject(compareInfo, this);
                } 
            } 
        }
 
#if  FEATURE_USE_LCID
        //  A locale ID is a 32 bit value which is the combination of a
        //  language ID, a sort ID, and a reserved area.  The bits are
        //  allocated as follows: 
        //
        //  +------------------------+-------+--------------------------------+ 
        //  |        Reserved        |Sort ID|           Language ID          | 
        //  +------------------------+-------+--------------------------------+
        //  31                     20 19   16 15                             0   bit 
        private const int LOCALE_SORTID_MASK = 0x000f0000;

        static private bool IsAlternateSortLcid(int lcid)
        { 
            if(lcid == LOCALE_TRADITIONAL_SPANISH)
            { 
                return true; 
            }
 
            return (lcid & LOCALE_SORTID_MASK) != 0;
        }
#endif
 
        [OnSerializing]
        private void OnSerializing(StreamingContext ctx) 
        { 
            this.m_name              = this.m_cultureData.CultureName;
            this.m_useUserOverride   = this.m_cultureData.UseUserOverride; 
#if FEATURE_USE_LCID
            // for compatibility with v2 serialize cultureID
            this.cultureID = this.m_cultureData.ILANGUAGE;
#endif 
        }
#endregion Serialization 
 
        // Is it safe to send this CultureInfo as an instance member of a Thread cross AppDomain boundaries?
        // For Silverlight, the answer is always no. 
        internal bool IsSafeCrossDomain {
            get {
                Contract.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0");
#if FEATURE_LEAK_CULTURE_INFO 
                return m_isSafeCrossDomain;
#else 
                return false; 
#endif
            } 
        }

        internal int CreatedDomainID {
            get { 
                Contract.Assert(m_createdDomainID != 0,  "[CultureInfo.CreatedDomain] m_createdDomainID != 0");
                return m_createdDomainID; 
            } 
        }
 
        // Is it safe to pass the CultureInfo cross AppDomain boundaries, not necessarily as an instance
        // member of Thread. This is different from IsSafeCrossDomain, which implies passing the CultureInfo
        // as a Thread instance member.
        internal bool CanSendCrossDomain() 
        {
            bool isSafe = false; 
            if (this.GetType() == typeof(System.Globalization.CultureInfo)) 
            {
                isSafe = true; 
            }
            return isSafe;
        }
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal void StartCrossDomainTracking() { 
 
            // If we have decided about cross domain safety of this instance, we are done
            if (m_createdDomainID != 0) 
                return;

            // If FEATURE_LEAK_CULTURE_INFO isn't enabled, we never want to pass
            // CultureInfo as an instance member of a Thread. 
#if FEATURE_LEAK_CULTURE_INFO
            if (CanSendCrossDomain()) 
            { 
                m_isSafeCrossDomain = true;
            } 
#endif

            // m_createdDomainID has to be assigned last. We use it to signal that we have
            // completed the check. 
            System.Threading.Thread.MemoryBarrier();
            m_createdDomainID = Thread.GetDomainID(); 
        } 

        // Constructor called by SQL Server's special munged culture - creates a culture with 
        // a TextInfo and CompareInfo that come from a supplied alternate source. This object
        // is ALWAYS read-only.
        // Note that we really cannot use an LCID version of this override as the cached
        // name we create for it has to include both names, and the logic for this is in 
        // the GetCultureInfo override *only*.
        internal CultureInfo(String cultureName, String textAndCompareCultureName) 
        { 
            if (cultureName==null) {
                throw new ArgumentNullException("cultureName", 
                    Environment.GetResourceString("ArgumentNull_String"));
            }
            Contract.EndContractBlock();
 
            this.m_cultureData = CultureData.GetCultureData(cultureName, false);
            if (this.m_cultureData == null) 
                throw new CultureNotFoundException( 
                    "cultureName", cultureName, Environment.GetResourceString("Argument_CultureNotSupported"));
 
            this.m_name = this.m_cultureData.CultureName;

            CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName);
            this.compareInfo = altCulture.CompareInfo; 
            this.textInfo = altCulture.TextInfo;
        } 
 
        // We do this to try to return the system UI language and the default user languages
        // The callers should have a fallback if this fails (like Invariant) 
        private static CultureInfo GetCultureByName(String name, bool userOverride)
        {
            // Try to get our culture
            try 
            {
                return userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name); 
            } 
            catch (ArgumentException)
            { 
            }

            return null;
        } 

        // 
        // Return a specific culture.  A tad irrelevent now since we always return valid data 
        // for neutral locales.
        // 
        // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
        // if we can't find a bigger name.  That doesn't help with things like "zh" though, so
        // the approach is of questionable value
        // 
#if !FEATURE_CORECLR
        public static CultureInfo CreateSpecificCulture(String name) { 
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo culture; 

            try {
                culture = new CultureInfo(name);
            } catch(ArgumentException) { 
                // When CultureInfo throws this exception, it may be because someone passed the form
                // like "az-az" because it came out of an http accept lang. We should try a little 
                // parsing to perhaps fall back to "az" here and use *it* to create the neutral. 

                int idx; 

                culture = null;
                for(idx = 0; idx < name.Length; idx++) {
                    if('-' == name[idx]) { 
                        try {
                            culture = new CultureInfo(name.Substring(0, idx)); 
                            break; 
                        } catch(ArgumentException) {
                            // throw the original exception so the name in the string will be right 
                            throw;
                        }
                    }
                } 

                if(null == culture) { 
                    // nothing to save here; throw the original exception 
                    throw;
                } 
            }

            //In the most common case, they've given us a specific culture, so we'll just return that.
            if (!(culture.IsNeutralCulture)) { 
                return culture;
            } 
 
            return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE));
        } 
#endif // !FEATURE_CORECLR

        internal static bool VerifyCultureName(String cultureName, bool throwException)
        { 
            // This function is used by ResourceManager.GetResourceFileName().
            // ResourceManager searches for resource using CultureInfo.Name, 
            // so we should check against CultureInfo.Name. 

            for (int i=0; i() != null);
                return Thread.CurrentThread.CurrentCulture;
            }
        } 

        // 
        // This is the equivalence of the Win32 GetUserDefaultLCID() 
        //
        internal static CultureInfo UserDefaultCulture { 
            get
            {
                Contract.Ensures(Contract.Result() != null);
 
                CultureInfo temp = s_userDefaultCulture;
                if (temp == null) 
                { 
                    //
                    // setting the s_userDefaultCulture with invariant culture before intializing it is a protection 
                    // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo
                    // creation path. the recursion can happen if the current user culture is a replaced custom culture.
                    //
 
                    s_userDefaultCulture = CultureInfo.InvariantCulture;
                    temp = InitUserDefaultCulture(); 
                    s_userDefaultCulture = temp; 
                }
                return (temp); 
            }
        }

        // 
        //  This is the equivalence of the Win32 GetUserDefaultUILanguage()
        // 
        internal static CultureInfo UserDefaultUICulture { 
            get {
                Contract.Ensures(Contract.Result() != null); 

                CultureInfo temp = s_userDefaultUICulture;
                if (temp == null)
                { 
                    //
                    // setting the s_userDefaultCulture with invariant culture before intializing it is a protection 
                    // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo 
                    // creation path. the recursion can happen if the current user culture is a replaced custom culture.
                    // 

                    s_userDefaultUICulture = CultureInfo.InvariantCulture;

                    temp = InitUserDefaultUICulture(); 
                    s_userDefaultUICulture = temp;
                } 
                return (temp); 
            }
        } 


        public static CultureInfo CurrentUICulture {
#if !FEATURE_CORECLR 
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
            get { 
                Contract.Ensures(Contract.Result() != null);
                return Thread.CurrentThread.CurrentUICulture; 
            }
        }

 
        //
        // This is the equivalence of the Win32 GetSystemDefaultUILanguage() 
        // 
        //
        public static CultureInfo InstalledUICulture { 
            get {
                Contract.Ensures(Contract.Result() != null);

                CultureInfo temp = s_InstalledUICultureInfo; 
                if (temp == null) {
                    String strDefault = GetSystemDefaultUILanguage(); 
                    temp = GetCultureByName(strDefault, true); 

                    if (temp == null) 
                    {
                        temp = InvariantCulture;
                    }
 
                    temp.m_isReadOnly = true;
                    s_InstalledUICultureInfo = temp; 
                } 
                return (temp);
            } 
        }

        ////////////////////////////////////////////////////////////////////////
        // 
        //  InvariantCulture
        // 
        //  This instance provides methods, for example for casing and sorting, 
        //  that are independent of the system and current user settings.  It
        //  should be used only by processes such as some system services that 
        //  require such invariant results (eg. file systems).  In general,
        //  the results are not linguistically correct and do not match any
        //  culture info.
        // 
        ////////////////////////////////////////////////////////////////////////
 
 
        public static CultureInfo InvariantCulture {
            [Pure] 
#if !FEATURE_CORECLR
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif
            get { 
                Contract.Ensures(Contract.Result() != null);
                return (s_InvariantCultureInfo); 
            } 
        }
 

        ////////////////////////////////////////////////////////////////////////
        //
        //  Parent 
        //
        //  Return the parent CultureInfo for the current instance. 
        // 
        ////////////////////////////////////////////////////////////////////////
 
        public virtual CultureInfo Parent
        {
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                Contract.Ensures(Contract.Result() != null); 
 
                if (null == m_parent)
                { 
                    try
                    {
                        string parentName = this.m_cultureData.SPARENT;
 
                        if (String.IsNullOrEmpty(parentName))
                        { 
                            m_parent = InvariantCulture; 
                        }
                        else 
                        {
                            m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
                        }
                    } 
                    catch (ArgumentException)
                    { 
                        // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant 
                        // We can't allow ourselves to fail.  In case of custom cultures the parent of the
                        // current custom culture isn't installed. 
                        m_parent =  InvariantCulture;
                    }
                }
                return m_parent; 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  LCID
        //
        //  Returns a properly formed culture identifier for the current
        //  culture info. 
        //
        //////////////////////////////////////////////////////////////////////// 
 
#if FEATURE_USE_LCID
        public virtual int LCID { 
#if !FEATURE_CORECLR
            [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif
            get { 
                return (this.m_cultureData.ILANGUAGE);
            } 
        } 
#endif
 
        ////////////////////////////////////////////////////////////////////////
        //
        //  BaseInputLanguage
        // 
        //  Essentially an LCID, though one that may be different than LCID in the case
        //  of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED). 
        // 
        ////////////////////////////////////////////////////////////////////////
#if FEATURE_USE_LCID 
        [System.Runtime.InteropServices.ComVisible(false)]
        public virtual int KeyboardLayoutId
        {
            get 
            {
                int keyId = this.m_cultureData.IINPUTLANGUAGEHANDLE; 
 
                // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID.
                return (keyId); 
            }
        }
#endif
 
#if !FEATURE_CORECLR && !CORIOLIS
        public static CultureInfo[] GetCultures(CultureTypes types) { 
            Contract.Ensures(Contract.Result() != null); 
            // internally we treat UserCustomCultures as Supplementals but v2
            // treats as Supplementals and Replacements 
            if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture)
            {
                types |= CultureTypes.ReplacementCultures;
            } 
            return (CultureData.GetCultures(types));
        } 
#endif 

        //////////////////////////////////////////////////////////////////////// 
        //
        //  Name
        //
        //  Returns the full name of the CultureInfo. The name is in format like 
        //  "en-US"  This version does NOT include sort information in the name.
        // 
        //////////////////////////////////////////////////////////////////////// 
        public virtual String Name {
            get { 
                Contract.Ensures(Contract.Result() != null);

                // We return non sorting name here.
                if (this.m_nonSortName == null) { 
                    this.m_nonSortName = this.m_cultureData.SNAME;
                    if (this.m_nonSortName == null) { 
                        this.m_nonSortName = String.Empty; 
                    }
                } 
                return this.m_nonSortName;
            }
        }
 
        // This one has the sort information (ie: de-DE_phoneb)
        internal String SortName 
        { 
            get
            { 
                if (this.m_sortName == null)
                {
                    this.m_sortName = this.m_cultureData.SCOMPAREINFO;
                } 

                return this.m_sortName; 
            } 
        }
 
        //
#if !FEATURE_CORECLR
        [System.Runtime.InteropServices.ComVisible(false)]
        public String IetfLanguageTag 
        {
            get 
            { 
                Contract.Ensures(Contract.Result() != null);
 
                // special case the compatibility cultures
                switch (this.Name)
                {
                    case "zh-CHT": 
                        return "zh-Hant";
                    case "zh-CHS": 
                        return "zh-Hans"; 
                    default:
                        return this.Name; 
                }
            }
        }
#endif 

        //////////////////////////////////////////////////////////////////////// 
        // 
        //  DisplayName
        // 
        //  Returns the full name of the CultureInfo in the localized language.
        //  For example, if the localized language of the runtime is Spanish and the CultureInfo is
        //  US English, "Ingles (Estados Unidos)" will be returned.
        // 
        ////////////////////////////////////////////////////////////////////////
        public virtual String DisplayName 
        { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get 
            {
                Contract.Ensures(Contract.Result() != null);
                Contract.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set");
 
                return m_cultureData.SLOCALIZEDDISPLAYNAME;
            } 
        } 

        //////////////////////////////////////////////////////////////////////// 
        //
        //  GetNativeName
        //
        //  Returns the full name of the CultureInfo in the native language. 
        //  For example, if the CultureInfo is US English, "English
        //  (United States)" will be returned. 
        // 
        ////////////////////////////////////////////////////////////////////////
        public virtual String NativeName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SNATIVEDISPLAYNAME); 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  GetEnglishName
        //
        //  Returns the full name of the CultureInfo in English.
        //  For example, if the CultureInfo is US English, "English 
        //  (United States)" will be returned.
        // 
        //////////////////////////////////////////////////////////////////////// 
        public virtual String EnglishName {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SENGDISPLAYNAME);
            } 
        }
 
        // ie: en 
        public virtual String TwoLetterISOLanguageName {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SISO639LANGNAME);
            } 
        }
 
#if !FEATURE_CORECLR && !CORIOLIS 
        // ie: eng
        public virtual String ThreeLetterISOLanguageName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get {
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SISO639LANGNAME2); 
            }
        } 
 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  ThreeLetterWindowsLanguageName
        //
        //  Returns the 3 letter windows language name for the current instance.  eg: "ENU"
        //  The ISO names are much preferred 
        //
        //////////////////////////////////////////////////////////////////////// 
        public virtual String ThreeLetterWindowsLanguageName { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                Contract.Ensures(Contract.Result() != null);
                return (this.m_cultureData.SABBREVLANGNAME);
            }
        } 
#endif
 
        //////////////////////////////////////////////////////////////////////// 
        //
        //  CompareInfo               Read-Only Property 
        //
        //  Gets the CompareInfo for this culture.
        //
        //////////////////////////////////////////////////////////////////////// 
        public virtual CompareInfo CompareInfo
        { 
            get 
            {
                Contract.Ensures(Contract.Result() != null); 

                if (this.compareInfo == null)
                {
                    // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from 
                    // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
                    CompareInfo temp = UseUserOverride 
                                        ? GetCultureInfo(this.m_name).CompareInfo 
                                        : new CompareInfo(this);
                    if (OkayToCacheClassWithCompatibilityBehavior) 
                    {
                        this.compareInfo = temp;
                    }
                    else 
                    {
                        return temp; 
                    } 
                }
                return (compareInfo); 
            }
        }

        static private bool OkayToCacheClassWithCompatibilityBehavior 
        {
            get 
            { 
                // only cache compareInfo and textInfo once the AppDomain compatibility settings
                // are available for the domain (It doesn't matter which compatibility switch we check 
                // for -- it will only have a value once the compatibility switches have been initialized)
                Nullable compatSwitch = AppDomain.CurrentDomain.IsCompatibilitySwitchSet("a");
                return compatSwitch.HasValue;
            } 
        }
 
#if !FEATURE_CORECLR 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  RegionInfo
        //
        //  Gets the RegionInfo for this culture.
        // 
        ////////////////////////////////////////////////////////////////////////
        private RegionInfo Region 
        { 
            get
            { 
                if (regionInfo==null)
                {
                    // Make a new regionInfo
                    RegionInfo tempRegionInfo = new RegionInfo(this.m_cultureData); 
                    regionInfo = tempRegionInfo;
                } 
                return (regionInfo); 
            }
        } 
#endif // FEATURE_CORECLR


 
        ////////////////////////////////////////////////////////////////////////
        // 
        //  TextInfo 
        //
        //  Gets the TextInfo for this culture. 
        //
        ////////////////////////////////////////////////////////////////////////

 
        public virtual TextInfo TextInfo {
            get { 
                Contract.Ensures(Contract.Result() != null); 

                if (textInfo==null) 
                {
                    // Make a new textInfo
                    TextInfo tempTextInfo = new TextInfo(this.m_cultureData);
                    tempTextInfo.SetReadOnlyState(m_isReadOnly); 

                    if (OkayToCacheClassWithCompatibilityBehavior) 
                    { 
                        textInfo = tempTextInfo;
                    } 
                    else
                    {
                        return tempTextInfo;
                    } 
                }
                return (textInfo); 
            } 
        }
 
        ////////////////////////////////////////////////////////////////////////
        //
        //  Equals
        // 
        //  Implements Object.Equals().  Returns a boolean indicating whether
        //  or not object refers to the same CultureInfo as the current instance. 
        // 
        ////////////////////////////////////////////////////////////////////////
 

        public override bool Equals(Object value)
        {
            if (Object.ReferenceEquals(this, value)) 
                return true;
 
            CultureInfo that = value as CultureInfo; 

            if (that != null) 
            {
                // using CompareInfo to verify the data passed through the constructor
                // CultureInfo(String cultureName, String textAndCompareCultureName)
 
                return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo));
            } 
 
            return (false);
        } 


        ////////////////////////////////////////////////////////////////////////
        // 
        //  GetHashCode
        // 
        //  Implements Object.GetHashCode().  Returns the hash code for the 
        //  CultureInfo.  The hash code is guaranteed to be the same for CultureInfo A
        //  and B where A.Equals(B) is true. 
        //
        ////////////////////////////////////////////////////////////////////////

#if !FEATURE_CORECLR 
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
#endif 
        public override int GetHashCode() 
        {
            return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode()); 
        }


        //////////////////////////////////////////////////////////////////////// 
        //
        //  ToString 
        // 
        //  Implements Object.ToString().  Returns the name of the CultureInfo,
        //  eg. "de-DE_phoneb", "en-US", or "fj-FJ". 
        //
        ////////////////////////////////////////////////////////////////////////

 
        public override String ToString()
        { 
            Contract.Ensures(Contract.Result() != null); 

            Contract.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set"); 
            return m_name;
        }

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public virtual Object GetFormat(Type formatType) { 
            if (formatType == typeof(NumberFormatInfo)) { 
                return (NumberFormat);
            } 
            if (formatType == typeof(DateTimeFormatInfo)) {
                return (DateTimeFormat);
            }
            return (null); 
        }
 
        public virtual bool IsNeutralCulture { 
            get {
                return this.m_cultureData.IsNeutralCulture; 
            }
        }

#if !FEATURE_CORECLR 
        [System.Runtime.InteropServices.ComVisible(false)]
        public CultureTypes CultureTypes 
        { 
            get
            { 
                CultureTypes types = 0;

                if (m_cultureData.IsNeutralCulture)
                    types |= CultureTypes.NeutralCultures; 
                else
                    types |= CultureTypes.SpecificCultures; 
 
                types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0;
 
// Disable  warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
#pragma warning disable 618
                types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0;
 
#pragma warning restore 618
                types |= m_cultureData.IsUserCustomCulture ? CultureTypes.UserCustomCulture : 0; 
                types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0; 

                return types; 
            }
        }
#endif
 
        public virtual NumberFormatInfo NumberFormat {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get 
            {
                Contract.Ensures(Contract.Result() != null); 

                if (numInfo == null) {
                    NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData);
                    temp.isReadOnly = m_isReadOnly; 
                    numInfo = temp;
                } 
                return (numInfo); 
            }
            set { 
                if (value == null) {
                    throw new ArgumentNullException("value",
                        Environment.GetResourceString("ArgumentNull_Obj"));
                } 
                Contract.EndContractBlock();
                VerifyWritable(); 
                numInfo = value; 
            }
        } 

        ////////////////////////////////////////////////////////////////////////
        //
        // GetDateTimeFormatInfo 
        //
        // Create a DateTimeFormatInfo, and fill in the properties according to 
        // the CultureID. 
        //
        //////////////////////////////////////////////////////////////////////// 


        public virtual DateTimeFormatInfo DateTimeFormat {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null); 
 
                if (dateTimeInfo == null) {
                    // Change the calendar of DTFI to the specified calendar of this CultureInfo. 
                    DateTimeFormatInfo temp = new DateTimeFormatInfo(
                        this.m_cultureData, this.Calendar);
                    temp.m_isReadOnly = m_isReadOnly;
                    System.Threading.Thread.MemoryBarrier(); 
                    dateTimeInfo = temp;
                } 
                return (dateTimeInfo); 
            }
 
            set {
                if (value == null) {
                    throw new ArgumentNullException("value",
                        Environment.GetResourceString("ArgumentNull_Obj")); 
                }
                Contract.EndContractBlock(); 
                VerifyWritable(); 
                dateTimeInfo = value;
            } 
        }


 
        public void ClearCachedData() {
            s_userDefaultUICulture = null; 
            s_userDefaultCulture = null; 

            RegionInfo.s_currentRegionInfo = null; 
#if !FEATURE_CORECLR && !FEATURE_PAL // System.TimeZone does not exist in CoreCLR or in Coriolis
            TimeZone.ResetTimeZone();
#endif // FEATURE_CORECLR
            TimeZoneInfo.ClearCachedData(); 
            // Delete the cached cultures.
            s_LcidCachedCultures = null; 
            s_NameCachedCultures = null; 

            CultureData.ClearCachedData(); 
        }

        /*=================================GetCalendarInstance==========================
        **Action: Map a Win32 CALID to an instance of supported calendar. 
        **Returns: An instance of calendar.
        **Arguments: calType    The Win32 CALID 
        **Exceptions: 
        **      Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
        **      If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar. 
        ============================================================================*/
        internal static Calendar GetCalendarInstance(int calType) {
            if (calType==Calendar.CAL_GREGORIAN) {
                return (new GregorianCalendar()); 
            }
            return GetCalendarInstanceRare(calType); 
        } 

        //This function exists as a shortcut to prevent us from loading all of the non-gregorian 
        //calendars unless they're required.
        internal static Calendar GetCalendarInstanceRare(int calType) {
            Contract.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN");
 
            switch (calType) {
                case Calendar.CAL_GREGORIAN_US:               // Gregorian (U.S.) calendar 
                case Calendar.CAL_GREGORIAN_ME_FRENCH:        // Gregorian Middle East French calendar 
                case Calendar.CAL_GREGORIAN_ARABIC:           // Gregorian Arabic calendar
                case Calendar.CAL_GREGORIAN_XLIT_ENGLISH:     // Gregorian Transliterated English calendar 
                case Calendar.CAL_GREGORIAN_XLIT_FRENCH:      // Gregorian Transliterated French calendar
                    return (new GregorianCalendar((GregorianCalendarTypes)calType));
                case Calendar.CAL_TAIWAN:                     // Taiwan Era calendar
                    return (new TaiwanCalendar()); 
                case Calendar.CAL_JAPAN:                      // Japanese Emperor Era calendar
                    return (new JapaneseCalendar()); 
                case Calendar.CAL_KOREA:                      // Korean Tangun Era calendar 
                    return (new KoreanCalendar());
                case Calendar.CAL_THAI:                       // Thai calendar 
                    return (new ThaiBuddhistCalendar());
                case Calendar.CAL_HIJRI:                      // Hijri (Arabic Lunar) calendar
                    return (new HijriCalendar());
                case Calendar.CAL_HEBREW:                     // Hebrew (Lunar) calendar 
                    return (new HebrewCalendar());
                case Calendar.CAL_UMALQURA: 
                    return (new UmAlQuraCalendar()); 
#if !FEATURE_ONLY_CORE_CALENDARS
                case Calendar.CAL_PERSIAN: 
                    return (new PersianCalendar());
                case Calendar.CAL_CHINESELUNISOLAR:
                    return (new ChineseLunisolarCalendar());
                case Calendar.CAL_JAPANESELUNISOLAR: 
                    return (new JapaneseLunisolarCalendar());
                case Calendar.CAL_KOREANLUNISOLAR: 
                    return (new KoreanLunisolarCalendar()); 
                case Calendar.CAL_TAIWANLUNISOLAR:
                    return (new TaiwanLunisolarCalendar()); 
#endif // !FEATURE_ONLY_CORE_CALENDARS
            }
            return (new GregorianCalendar());
        } 

 
        /*=================================Calendar========================== 
        **Action: Return/set the default calendar used by this culture.
        ** This value can be overridden by regional option if this is a current culture. 
        **Returns:
        **Arguments:
        **Exceptions:
        **  ArgumentNull_Obj if the set value is null. 
        ============================================================================*/
 
 
        public virtual Calendar Calendar {
            [System.Security.SecuritySafeCritical]  // auto-generated 
            get {
                Contract.Ensures(Contract.Result() != null);
                if (calendar == null) {
                    Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0"); 
                    // Get the default calendar for this culture.  Note that the value can be
                    // from registry if this is a user default culture. 
                    Calendar newObj = this.m_cultureData.DefaultCalendar; 

                    System.Threading.Thread.MemoryBarrier(); 
                    newObj.SetReadOnlyState(m_isReadOnly);
                    calendar = newObj;
                }
                return (calendar); 
            }
        } 
 
        /*=================================OptionCalendars==========================
        **Action: Return an array of the optional calendar for this culture. 
        **Returns: an array of Calendar.
        **Arguments:
        **Exceptions:
        ============================================================================*/ 

 
        public virtual Calendar[] OptionalCalendars { 
            [System.Security.SecuritySafeCritical]  // auto-generated
            get { 
                Contract.Ensures(Contract.Result() != null);

                //
                // This property always returns a new copy of the calendar array. 
                //
                int[] calID = this.m_cultureData.CalendarIds; 
                Calendar [] cals = new Calendar[calID.Length]; 
                for (int i = 0; i < cals.Length; i++) {
                    cals[i] = GetCalendarInstance(calID[i]); 
                }
                return (cals);
            }
        } 

 
        public bool UseUserOverride { 
            get {
                return (this.m_cultureData.UseUserOverride); 
            }
        }

#if !FEATURE_CORECLR && !CORIOLIS 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [System.Runtime.InteropServices.ComVisible(false)] 
        public CultureInfo GetConsoleFallbackUICulture() 
        {
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo temp = m_consoleFallbackCulture;
            if (temp == null)
            { 
                temp = CreateSpecificCulture(this.m_cultureData.SCONSOLEFALLBACKNAME);
                temp.m_isReadOnly = true; 
                m_consoleFallbackCulture = temp; 
            }
            return (temp); 
        }
#endif

        [System.Security.SecuritySafeCritical]  // auto-generated 
        public virtual Object Clone()
        { 
            Contract.Ensures(Contract.Result() != null); 

            CultureInfo ci = (CultureInfo)MemberwiseClone(); 
            ci.m_isReadOnly = false;

            //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
            //they've already been allocated.  If this is a derived type, we'll take a more generic codepath. 
            if (!m_isInherited)
            { 
                if (this.dateTimeInfo != null) 
                {
                    ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone(); 
                }
                if (this.numInfo != null)
                {
                    ci.numInfo = (NumberFormatInfo)this.numInfo.Clone(); 
                }
 
            } 
            else
            { 
                ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
                ci.NumberFormat   = (NumberFormatInfo)this.NumberFormat.Clone();
            }
 
            if (textInfo != null)
            { 
                ci.textInfo = (TextInfo) textInfo.Clone(); 
            }
 
            if (calendar != null)
            {
                ci.calendar = (Calendar) calendar.Clone();
            } 

            return (ci); 
        } 

 
        [System.Security.SecuritySafeCritical]  // auto-generated
        public static CultureInfo ReadOnly(CultureInfo ci) {
            if (ci == null) {
                throw new ArgumentNullException("ci"); 
            }
            Contract.Ensures(Contract.Result() != null); 
            Contract.EndContractBlock(); 

            if (ci.IsReadOnly) { 
                return (ci);
            }
            CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
 
            if (!ci.IsNeutralCulture)
            { 
                //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless 
                //they've already been allocated.  If this is a derived type, we'll take a more generic codepath.
                if (!ci.m_isInherited) { 
                    if (ci.dateTimeInfo != null) {
                        newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo);
                    }
                    if (ci.numInfo != null) { 
                        newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo);
                    } 
 
                } else {
                    newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat); 
                    newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
                }
            }
 
            if (ci.textInfo != null)
            { 
                newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo); 
            }
 
            if (ci.calendar != null)
            {
                newInfo.calendar = Calendar.ReadOnly(ci.calendar);
            } 

            // Don't set the read-only flag too early. 
            // We should set the read-only flag here.  Otherwise, info.DateTimeFormat will not be able to set. 
            newInfo.m_isReadOnly = true;
 
            return (newInfo);
        }

 
        public bool IsReadOnly {
            get { 
                return (m_isReadOnly); 
            }
        } 

        private void VerifyWritable() {
            if (m_isReadOnly) {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly")); 
            }
            Contract.EndContractBlock(); 
        } 

        // For resource lookup, we consider a culture the invariant culture by name equality. 
        // We perform this check frequently during resource lookup, so adding a property for
        // improved readability.
        internal bool HasInvariantCultureName
        { 
            get { return Name == CultureInfo.InvariantCulture.Name; }
        } 
 
        // Helper function both both overloads of GetCachedReadOnlyCulture.  If lcid is 0, we use the name.
        // If lcid is -1, use the altName and create one of those special SQL cultures. 
        internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName)
        {
            // There is a race condition in this code with the side effect that the second thread's value
            // clobbers the first in the dictionary. This is an acceptable ---- since the CultureInfo objects 
            // are content equal (but not reference equal). Since we make no guarantees there, this ---- is
            // acceptable. 
            // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus 
            // Hashtable thread safety.
 
            // retval is our return value.
            CultureInfo retval;

            // Temporary hashtable for the names. 
            Hashtable tempNameHT = s_NameCachedCultures;
 
            if (name != null) 
            {
                name = CultureData.AnsiToLower(name); 
            }

            if (altName != null)
            { 
                altName = CultureData.AnsiToLower(altName);
            } 
 
            // We expect the same result for both hashtables, but will test individually for added safety.
            if (tempNameHT == null) 
            {
                tempNameHT = Hashtable.Synchronized(new Hashtable());
            }
            else 
            {
                // If we are called by name, check if the object exists in the hashtable.  If so, return it. 
                if (lcid == -1) 
                {
                    retval = (CultureInfo)tempNameHT[name + '\xfffd' + altName]; 
                    if (retval != null)
                    {
                        return retval;
                    } 
                }
                else if (lcid == 0) 
                { 
                    retval = (CultureInfo)tempNameHT[name];
                    if (retval != null) 
                    {
                        return retval;
                    }
                } 
            }
#if FEATURE_USE_LCID 
            // Next, the Lcid table. 
            Hashtable tempLcidHT = s_LcidCachedCultures;
 
            if (tempLcidHT == null)
            {
                // Case insensitive is not an issue here, save the constructor call.
                tempLcidHT = Hashtable.Synchronized(new Hashtable()); 
            }
            else 
            { 
                // If we were called by Lcid, check if the object exists in the table.  If so, return it.
                if (lcid > 0) 
                {
                    retval = (CultureInfo) tempLcidHT[lcid];
                    if (retval != null)
                    { 
                        return retval;
                    } 
                } 
            }
#endif 
            // We now have two temporary hashtables and the desired object was not found.
            // We'll construct it.  We catch any exceptions from the constructor call and return null.
            try
            { 
                switch(lcid)
                { 
                    case -1: 
                        // call the private constructor
                        retval = new CultureInfo(name, altName); 
                        break;

                    case 0:
                        retval = new CultureInfo(name, false); 
                        break;
 
                    default: 
#if FEATURE_USE_LCID
                        retval = new CultureInfo(lcid, false); 
                        break;
#else
                        return null;
#endif 
                }
            } 
            catch(ArgumentException) 
            {
                return null; 
            }

            // Set it to read-only
            retval.m_isReadOnly = true; 

            if (lcid == -1) 
            { 
                // This new culture will be added only to the name hash table.
                tempNameHT[name + '\xfffd' + altName] = retval; 

                // when lcid == -1 then TextInfo object is already get created and we need to set it as read only.
                retval.TextInfo.SetReadOnlyState(true);
            } 
            else
            { 
                // Remember our name (as constructed).  Do NOT use alternate sort name versions because 
                // we have internal state representing the sort.  (So someone would get the wrong cached version)
                string newName = CultureData.AnsiToLower(retval.m_name); 

                // We add this new culture info object to both tables.
                tempNameHT[newName] = retval;
#if FEATURE_USE_LCID 
                const int LCID_ZH_CHS_HANS = 0x0004;
                const int LCID_ZH_CHT_HANT = 0x7c04; 
 
                if ((retval.LCID == LCID_ZH_CHS_HANS && newName == "zh-hans")
                 || (retval.LCID == LCID_ZH_CHT_HANT && newName == "zh-hant")) 
                {
                    // do nothing because we only want zh-CHS and zh-CHT to cache
                    // by lcid
                } 
                else
                { 
                    tempLcidHT[retval.LCID] = retval; 
                }
 
#endif
            }

#if FEATURE_USE_LCID 
            // Copy the two hashtables to the corresponding member variables.  This will potentially overwrite
            // new tables simultaneously created by a new thread, but maximizes thread safety. 
            if(-1 != lcid) 
            {
                // Only when we modify the lcid hash table, is there a need to overwrite. 
                s_LcidCachedCultures = tempLcidHT;
            }
#endif
 
            s_NameCachedCultures = tempNameHT;
 
            // Finally, return our new CultureInfo object. 
            return retval;
        } 

#if FEATURE_USE_LCID
        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found).  (LCID version)... use named version 
        public static CultureInfo GetCultureInfo(int culture)
        { 
            // Must check for -1 now since the helper function uses the value to signal 
            // the altCulture code path for SQL Server.
            // Also check for zero as this would fail trying to add as a key to the hash. 
            if (culture <= 0) {
                throw new ArgumentOutOfRangeException("culture",
                    Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 
            CultureInfo retval = GetCultureInfoHelper(culture, null, null); 
            if (null == retval)
            { 
                throw new CultureNotFoundException(
                    "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
            }
            return retval; 
        }
#endif 
 
        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found).  (Named version) 
        public static CultureInfo GetCultureInfo(string name)
        {
            // Make sure we have a valid, non-zero length string as name
            if (name == null) 
            {
                throw new ArgumentNullException("name"); 
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 

            CultureInfo retval = GetCultureInfoHelper(0, name, null);
            if (retval == null)
            { 
                throw new CultureNotFoundException(
                    "name", name, Environment.GetResourceString("Argument_CultureNotSupported")); 
 
            }
            return retval; 
        }

        // Gets a cached copy of the specified culture from an internal hashtable (or creates it
        // if not found). 
        public static CultureInfo GetCultureInfo(string name, string altName)
        { 
            // Make sure we have a valid, non-zero length string as name 
            if (null == name)
            { 
                throw new ArgumentNullException("name");
            }

            if (null == altName) 
            {
                throw new ArgumentNullException("altName"); 
            } 
            Contract.Ensures(Contract.Result() != null);
            Contract.EndContractBlock(); 

            CultureInfo retval = GetCultureInfoHelper(-1, name, altName);
            if (retval == null)
            { 
                throw new CultureNotFoundException("name or altName",
                                        String.Format( 
                                            CultureInfo.CurrentCulture, 
                                            Environment.GetResourceString("Argument_OneOfCulturesNotSupported"),
                                            name, 
                                            altName));
            }
            return retval;
        } 

 
#if !FEATURE_CORECLR 
        // This function is deprecated, we don't like it
        public static CultureInfo GetCultureInfoByIetfLanguageTag(string name) 
        {
            Contract.Ensures(Contract.Result() != null);

            // Disallow old zh-CHT/zh-CHS names 
            if (name == "zh-CHT" || name == "zh-CHS")
            { 
                throw new CultureNotFoundException( 
                            "name",
                            String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name) 
                            );
            }

            CultureInfo ci = GetCultureInfo(name); 

            // Disallow alt sorts and es-es_TS 
            if (ci.LCID > 0xffff || ci.LCID == 0x040a) 
            {
                throw new CultureNotFoundException( 
                            "name",
                            String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
                            );
            } 

            return ci; 
        } 
#endif
        private static bool? s_isTaiwanSku; 
        internal static bool Is----Sku
        {
            get
            { 
                if (s_isTaiwanSku == null)
                { 
                    s_isTaiwanSku = (GetSystemDefaultUILanguage() == "zh-TW"); 
                }
                return (bool)s_isTaiwanSku; 
            }
        }

        // 
        //  Helper Methods.
        // 
 
        // Get Locale Info Ex calls.  So we don't have to muck with the different int/string return types we declared two of these:
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern String nativeGetLocaleInfoEx(String localeName, uint field);
 
        [System.Security.SecuritySafeCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field);
 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool nativeSetThreadLocale(String localeName); 

        [System.Security.SecurityCritical] 
        private static String GetDefaultLocaleName(int localeType) 
        {
            Contract.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT"); 

            string localeName = null;
            if(InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName)))
            { 
                return localeName;
            } 
            return string.Empty; 
        }
 
        // Get the default locale name
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [SuppressUnmanagedCodeSecurity] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString); 

        [System.Security.SecuritySafeCritical] // auto-generated 
        private static String GetUserDefaultUILanguage()
        {
            string userDefaultUiLanguage = null;
            if(InternalGetUserDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref userDefaultUiLanguage))) 
            {
                return userDefaultUiLanguage; 
            } 
            return String.Empty;
        } 

        // Get the user's default UI language, return locale name
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [SuppressUnmanagedCodeSecurity]
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] 
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage);
 
        [System.Security.SecuritySafeCritical] // auto-generated
        private static String GetSystemDefaultUILanguage()
        {
            string systemDefaultUiLanguage = null; 
            if(InternalGetSystemDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref systemDefaultUiLanguage)))
            { 
                return systemDefaultUiLanguage; 
            }
            return String.Empty; 

        }

        [System.Security.SecurityCritical] // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        [SuppressUnmanagedCodeSecurity] 
        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [return: MarshalAs(UnmanagedType.Bool)] 
        private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage);

/* Disabled for CLR v4
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern String[] nativeGetResourceFallbackArray(); 
*/
    } 
}


// 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