dd6867c77866c9b301dbe7c10d0061c3e8817670
[platform/upstream/coreclr.git] / src / mscorlib / src / System / Globalization / CultureInfo.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 ////////////////////////////////////////////////////////////////////////////
6 //
7 //
8 //
9 //  Purpose:  This class represents the software preferences of a particular
10 //            culture or community.  It includes information such as the
11 //            language, writing system, and a calendar used by the culture
12 //            as well as methods for common operations such as printing
13 //            dates and sorting strings.
14 //
15 //
16 //
17 //  !!!! NOTE WHEN CHANGING THIS CLASS !!!!
18 //
19 //  If adding or removing members to this class, please update CultureInfoBaseObject
20 //  in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be
21 //  different than the order in which members are declared. For instance, all
22 //  reference types will come first in the class before value types (like ints, bools, etc)
23 //  regardless of the order in which they are declared. The best way to see the
24 //  actual order of the class is to do a !dumpobj on an instance of the managed
25 //  object inside of the debugger.
26 //
27 ////////////////////////////////////////////////////////////////////////////
28
29 namespace System.Globalization {
30     using System;
31     using System.Security;
32     using System.Threading;
33     using System.Collections;
34     using System.Runtime;
35     using System.Runtime.CompilerServices;
36     using System.Runtime.InteropServices;
37     using System.Runtime.Serialization;
38     using System.Runtime.Versioning;
39     using System.Security.Permissions;
40     using System.Reflection;
41     using Microsoft.Win32;
42     using System.Diagnostics.Contracts;
43     using System.Resources;
44
45     [Serializable]
46     [System.Runtime.InteropServices.ComVisible(true)]
47     public partial class CultureInfo : ICloneable, IFormatProvider {
48         //--------------------------------------------------------------------//
49         //                        Internal Information                        //
50         //--------------------------------------------------------------------//
51
52         //--------------------------------------------------------------------//
53         // Data members to be serialized:
54         //--------------------------------------------------------------------//
55
56         // We use an RFC4646 type string to construct CultureInfo.
57         // This string is stored in m_name and is authoritative.
58         // We use the m_cultureData to get the data for our object
59
60         // WARNING
61         // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h
62         // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot
63         // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject
64         // WARNING: must be manually structured to match the true loaded class layout
65         // WARNING
66         internal bool m_isReadOnly;
67         internal CompareInfo compareInfo;
68         internal TextInfo textInfo;
69         // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK)
70 #if !FEATURE_CORECLR
71         [NonSerialized]internal RegionInfo regionInfo;
72 #endif
73         internal NumberFormatInfo numInfo;
74         internal DateTimeFormatInfo dateTimeInfo;
75         internal Calendar calendar;
76         [OptionalField(VersionAdded = 1)]
77         internal int m_dataItem;       // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
78         [OptionalField(VersionAdded = 1)]
79         internal int cultureID  = 0x007f;  // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
80         //
81         // The CultureData instance that we are going to read data from.
82         // For supported culture, this will be the CultureData instance that read data from mscorlib assembly.
83         // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
84         //
85         [NonSerialized]internal CultureData m_cultureData;
86         
87         [NonSerialized]internal bool m_isInherited;
88 #if FEATURE_LEAK_CULTURE_INFO
89         [NonSerialized]private bool m_isSafeCrossDomain;
90         [NonSerialized]private int m_createdDomainID;
91 #endif // !FEATURE_CORECLR
92 #if !FEATURE_CORECLR
93         [NonSerialized]private CultureInfo m_consoleFallbackCulture;
94 #endif // !FEATURE_CORECLR
95
96         // Names are confusing.  Here are 3 names we have:
97         //
98         //  new CultureInfo()   m_name        m_nonSortName   m_sortName
99         //      en-US           en-US           en-US           en-US
100         //      de-de_phoneb    de-DE_phoneb    de-DE           de-DE_phoneb
101         //      fj-fj (custom)  fj-FJ           fj-FJ           en-US (if specified sort is en-US)
102         //      en              en              
103         //
104         // Note that in Silverlight we ask the OS for the text and sort behavior, so the 
105         // textinfo and compareinfo names are the same as the name
106
107         // Note that the name used to be serialized for Everett; it is now serialized
108         // because alernate sorts can have alternate names.
109         // This has a de-DE, de-DE_phoneb or fj-FJ style name
110         internal string m_name;
111
112         // This will hold the non sorting name to be returned from CultureInfo.Name property.
113         // This has a de-DE style name even for de-DE_phoneb type cultures
114         [NonSerialized]private string m_nonSortName;
115
116         // This will hold the sorting name to be returned from CultureInfo.SortName property.
117         // This might be completely unrelated to the culture name if a custom culture.  Ie en-US for fj-FJ.
118         // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
119         [NonSerialized]private string m_sortName;
120
121
122         //--------------------------------------------------------------------//
123         //
124         // Static data members
125         //
126         //--------------------------------------------------------------------//
127
128         //Get the current user default culture.  This one is almost always used, so we create it by default.
129         private static volatile CultureInfo s_userDefaultCulture;
130
131         //
132         // All of the following will be created on demand.
133         //
134
135         //The Invariant culture;
136         private static volatile CultureInfo s_InvariantCultureInfo;
137
138         //The culture used in the user interface. This is mostly used to load correct localized resources.
139         private static volatile CultureInfo s_userDefaultUICulture;
140
141         //This is the UI culture used to install the OS.
142         private static volatile CultureInfo s_InstalledUICultureInfo;
143
144         //These are defaults that we use if a thread has not opted into having an explicit culture
145         private static volatile CultureInfo s_DefaultThreadCurrentUICulture;
146         private static volatile CultureInfo s_DefaultThreadCurrentCulture;
147
148         //This is a cache of all previously created cultures.  Valid keys are LCIDs or the name.  We use two hashtables to track them,
149         // depending on how they are called.
150         private static volatile Hashtable s_LcidCachedCultures;
151         private static volatile Hashtable s_NameCachedCultures;
152
153 #if FEATURE_APPX
154         // When running under AppX, we use this to get some information about the language list
155         [SecurityCritical]
156         private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager;
157
158         [ThreadStatic]
159         private static bool ts_IsDoingAppXCultureInfoLookup;
160 #endif
161
162         //The parent culture.
163         [NonSerialized]private CultureInfo m_parent;
164
165         // LOCALE constants of interest to us internally and privately for LCID functions
166         // (ie: avoid using these and use names if possible)
167         internal const int LOCALE_NEUTRAL              = 0x0000;
168         private  const int LOCALE_USER_DEFAULT         = 0x0400;
169         private  const int LOCALE_SYSTEM_DEFAULT       = 0x0800;
170         internal const int LOCALE_CUSTOM_DEFAULT       = 0x0c00;
171         internal const int LOCALE_CUSTOM_UNSPECIFIED   = 0x1000;
172         internal const int LOCALE_INVARIANT            = 0x007F;
173         private  const int LOCALE_TRADITIONAL_SPANISH  = 0x040a;
174
175         //
176         // The CultureData  instance that reads the data provided by our CultureData class.
177         //
178         //Using a field initializer rather than a static constructor so that the whole class can be lazy
179         //init.
180         private static readonly bool init = Init();
181         private static bool Init()
182         {
183
184             if (s_InvariantCultureInfo == null) 
185             {
186                 CultureInfo temp = new CultureInfo("", false);
187                 temp.m_isReadOnly = true;
188                 s_InvariantCultureInfo = temp;
189             }
190             // First we set it to Invariant in case someone needs it before we're done finding it.
191             // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid
192             // s_userDefaultCulture to be used in Thread.CurrentCulture.
193             s_userDefaultCulture = s_userDefaultUICulture = s_InvariantCultureInfo;
194
195             s_userDefaultCulture = InitUserDefaultCulture();
196             s_userDefaultUICulture = InitUserDefaultUICulture();
197             return true;
198         }
199
200         [System.Security.SecuritySafeCritical]  // auto-generated
201         static CultureInfo InitUserDefaultCulture()
202         {
203             String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT);
204             if (strDefault == null)
205             {
206                 strDefault = GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT);
207
208                 if (strDefault == null)
209                 {
210                     // If system default doesn't work, keep using the invariant
211                     return (CultureInfo.InvariantCulture);
212                 }
213             }
214             CultureInfo temp = GetCultureByName(strDefault, true);
215
216             temp.m_isReadOnly = true;
217
218             return (temp);
219         }
220
221         static CultureInfo InitUserDefaultUICulture()
222         {
223             String strDefault = GetUserDefaultUILanguage();
224
225             // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible.
226             if (strDefault == UserDefaultCulture.Name)
227             {
228                 return (UserDefaultCulture);
229             }
230
231             CultureInfo temp = GetCultureByName( strDefault, true);
232
233             if (temp == null)
234             {
235                 return (CultureInfo.InvariantCulture);
236             }
237
238             temp.m_isReadOnly = true;
239
240             return (temp);
241         }
242
243 #if FEATURE_APPX
244         [SecuritySafeCritical]
245         internal static CultureInfo GetCultureInfoForUserPreferredLanguageInAppX()
246         {
247             // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive
248             // call to itself, return null, since we don't want to stack overflow.  For example, 
249             // this can happen if some code in this method ends up calling CultureInfo.CurrentCulture
250             // (which is common on check'd build because of BCLDebug logging which calls Int32.ToString()).  
251             // In this case, returning null will mean CultureInfo.CurrentCulture gets the default Win32 
252             // value, which should be fine. 
253             if(ts_IsDoingAppXCultureInfoLookup)
254             {
255                 return null;
256             }
257
258             // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
259             // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
260             // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
261             // which should be fine because we should only ever need to access FX resources during NGEN.
262             // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
263             // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
264             if (AppDomain.IsAppXNGen)
265             {
266                 return null;
267             }
268
269             CultureInfo toReturn = null;
270
271             try 
272             {
273                 ts_IsDoingAppXCultureInfoLookup = true;
274
275                 if(s_WindowsRuntimeResourceManager == null)
276                 {
277                     s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager();
278                 }
279
280                 toReturn = s_WindowsRuntimeResourceManager.GlobalResourceContextBestFitCultureInfo;
281             } 
282             finally 
283             {
284                ts_IsDoingAppXCultureInfoLookup = false;
285             }
286  
287             return toReturn;
288         }
289
290         [SecuritySafeCritical]
291         internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci)
292         {
293             // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
294             // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
295             // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
296             // which should be fine because we should only ever need to access FX resources during NGEN.
297             // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
298             // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
299             if (AppDomain.IsAppXNGen)
300             {
301                 return false;
302             }
303
304             if (s_WindowsRuntimeResourceManager == null)
305             {
306                 s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager();
307             }
308
309             return s_WindowsRuntimeResourceManager.SetGlobalResourceContextDefaultCulture(ci);
310         }
311 #endif
312
313         ////////////////////////////////////////////////////////////////////////
314         //
315         //  CultureInfo Constructors
316         //
317         ////////////////////////////////////////////////////////////////////////
318
319
320         public CultureInfo(String name) : this(name, true) {
321         }
322
323
324         public CultureInfo(String name, bool useUserOverride) {
325             if (name==null) {
326                 throw new ArgumentNullException("name",
327                     Environment.GetResourceString("ArgumentNull_String"));
328             }
329             Contract.EndContractBlock();
330
331             // Get our data providing record
332             this.m_cultureData = CultureData.GetCultureData(name, useUserOverride);
333
334             if (this.m_cultureData == null) {
335                 throw new CultureNotFoundException("name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
336             }
337
338             this.m_name = this.m_cultureData.CultureName;
339             this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
340         }
341
342
343 #if FEATURE_USE_LCID
344         public CultureInfo(int culture) : this(culture, true) {
345         }
346
347         public CultureInfo(int culture, bool useUserOverride) {
348             // We don't check for other invalid LCIDS here...
349             if (culture < 0) {
350                 throw new ArgumentOutOfRangeException("culture",
351                     Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
352             }
353             Contract.EndContractBlock();
354
355             InitializeFromCultureId(culture, useUserOverride);
356         }
357
358         private void InitializeFromCultureId(int culture, bool useUserOverride)
359         {
360             switch (culture)
361             {
362                 case LOCALE_CUSTOM_DEFAULT:
363                 case LOCALE_SYSTEM_DEFAULT:
364                 case LOCALE_NEUTRAL:
365                 case LOCALE_USER_DEFAULT:
366                 case LOCALE_CUSTOM_UNSPECIFIED:
367                     // Can't support unknown custom cultures and we do not support neutral or
368                     // non-custom user locales.
369                     throw new CultureNotFoundException(
370                         "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
371
372                 default:
373                     // Now see if this LCID is supported in the system default CultureData  table.
374                     this.m_cultureData = CultureData.GetCultureData(culture, useUserOverride);
375                     break;
376             }
377             this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
378             this.m_name = this.m_cultureData.CultureName;
379         }
380 #endif // FEATURE_USE_LCID
381
382         //
383         // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to 
384         // other object (like CultureInfo or DateTimeFormatInfo).
385         //
386
387         internal static void CheckDomainSafetyObject(Object obj, Object container)
388         {
389             if (obj.GetType().Assembly != typeof(System.Globalization.CultureInfo).Assembly) {
390                 
391                 throw new InvalidOperationException(
392                             String.Format(
393                                 CultureInfo.CurrentCulture, 
394                                 Environment.GetResourceString("InvalidOperation_SubclassedObject"), 
395                                 obj.GetType(),
396                                 container.GetType()));
397             }
398             Contract.EndContractBlock();
399         }
400
401 #region Serialization
402         // We need to store the override from the culture data record.
403         private bool    m_useUserOverride;
404
405         [OnDeserialized]
406         private void OnDeserialized(StreamingContext ctx)
407         {
408 #if FEATURE_USE_LCID
409             // Whidbey+ should remember our name
410             // but v1 and v1.1 did not store name -- only lcid
411             // Whidbey did not store actual alternate sort name in m_name
412             //   like we do in v4 so we can't use name for alternate sort
413             // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl
414             if (m_name == null || IsAlternateSortLcid(cultureID))
415             {
416                 Contract.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0");
417                 InitializeFromCultureId(cultureID, m_useUserOverride);
418             }
419             else
420             {
421 #endif
422                 Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null");
423
424                 this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride);
425                 if (this.m_cultureData == null)
426                     throw new CultureNotFoundException(
427                         "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported"));
428                     
429 #if FEATURE_USE_LCID
430             }
431 #endif
432             m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
433
434             // in case we have non customized CultureInfo object we shouldn't allow any customized object  
435             // to be attached to it for cross app domain safety.
436             if (this.GetType().Assembly == typeof(System.Globalization.CultureInfo).Assembly)
437             {
438                 if (textInfo != null)
439                 {
440                     CheckDomainSafetyObject(textInfo, this);
441                 }
442                 
443                 if (compareInfo != null)
444                 {
445                     CheckDomainSafetyObject(compareInfo, this);
446                 }
447             }
448         }
449
450 #if FEATURE_USE_LCID
451         //  A locale ID is a 32 bit value which is the combination of a
452         //  language ID, a sort ID, and a reserved area.  The bits are
453         //  allocated as follows:
454         //
455         //  +------------------------+-------+--------------------------------+
456         //  |        Reserved        |Sort ID|           Language ID          |
457         //  +------------------------+-------+--------------------------------+
458         //  31                     20 19   16 15                             0   bit
459         private const int LOCALE_SORTID_MASK = 0x000f0000;
460
461         static private bool IsAlternateSortLcid(int lcid)
462         {
463             if(lcid == LOCALE_TRADITIONAL_SPANISH)
464             {
465                 return true;
466             }
467
468             return (lcid & LOCALE_SORTID_MASK) != 0;
469         }
470 #endif
471
472         [OnSerializing]
473         private void OnSerializing(StreamingContext ctx)
474         {
475             this.m_name              = this.m_cultureData.CultureName;
476             this.m_useUserOverride   = this.m_cultureData.UseUserOverride;
477 #if FEATURE_USE_LCID
478             // for compatibility with v2 serialize cultureID
479             this.cultureID = this.m_cultureData.ILANGUAGE;
480 #endif
481         }
482 #endregion Serialization
483
484 #if FEATURE_LEAK_CULTURE_INFO
485         // Is it safe to send this CultureInfo as an instance member of a Thread cross AppDomain boundaries?
486         // For Silverlight, the answer is always no.
487         internal bool IsSafeCrossDomain {
488             get {
489                 Contract.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0");
490                 return m_isSafeCrossDomain;
491             }
492         }
493
494         internal int CreatedDomainID {
495             get {
496                 Contract.Assert(m_createdDomainID != 0,  "[CultureInfo.CreatedDomain] m_createdDomainID != 0");
497                 return m_createdDomainID;
498             }
499         }
500
501         internal void StartCrossDomainTracking() {
502         
503             // If we have decided about cross domain safety of this instance, we are done
504             if (m_createdDomainID != 0)
505                 return;
506
507             // If FEATURE_LEAK_CULTURE_INFO isn't enabled, we never want to pass
508             // CultureInfo as an instance member of a Thread. 
509             if (CanSendCrossDomain())
510             {
511                 m_isSafeCrossDomain = true;
512             }
513
514             // m_createdDomainID has to be assigned last. We use it to signal that we have
515             // completed the check.
516             System.Threading.Thread.MemoryBarrier();
517             m_createdDomainID = Thread.GetDomainID();
518         }
519 #endif // FEATURE_LEAK_CULTURE_INFO
520
521         // Is it safe to pass the CultureInfo cross AppDomain boundaries, not necessarily as an instance
522         // member of Thread. This is different from IsSafeCrossDomain, which implies passing the CultureInfo
523         // as a Thread instance member. 
524         internal bool CanSendCrossDomain()
525         {
526             bool isSafe = false;
527             if (this.GetType() == typeof(System.Globalization.CultureInfo))
528             {
529                 isSafe = true;
530             }
531             return isSafe;
532         }
533
534         // Constructor called by SQL Server's special munged culture - creates a culture with
535         // a TextInfo and CompareInfo that come from a supplied alternate source. This object
536         // is ALWAYS read-only.
537         // Note that we really cannot use an LCID version of this override as the cached
538         // name we create for it has to include both names, and the logic for this is in
539         // the GetCultureInfo override *only*.
540         internal CultureInfo(String cultureName, String textAndCompareCultureName)
541         {
542             if (cultureName==null) {
543                 throw new ArgumentNullException("cultureName",
544                     Environment.GetResourceString("ArgumentNull_String"));
545             }
546             Contract.EndContractBlock();
547
548             this.m_cultureData = CultureData.GetCultureData(cultureName, false);
549             if (this.m_cultureData == null)
550                 throw new CultureNotFoundException(
551                     "cultureName", cultureName, Environment.GetResourceString("Argument_CultureNotSupported"));
552             
553             this.m_name = this.m_cultureData.CultureName;            
554
555             CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName);
556             this.compareInfo = altCulture.CompareInfo;
557             this.textInfo = altCulture.TextInfo;
558         }
559
560         // We do this to try to return the system UI language and the default user languages
561         // The callers should have a fallback if this fails (like Invariant)
562         private static CultureInfo GetCultureByName(String name, bool userOverride)
563         {           
564             // Try to get our culture
565             try
566             {
567                 return userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name);
568             }
569             catch (ArgumentException)
570             {
571             }
572
573             return null;
574         }
575
576         //
577         // Return a specific culture.  A tad irrelevent now since we always return valid data
578         // for neutral locales.
579         //
580         // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
581         // if we can't find a bigger name.  That doesn't help with things like "zh" though, so
582         // the approach is of questionable value
583         //
584 #if !FEATURE_CORECLR
585         public static CultureInfo CreateSpecificCulture(String name) {
586             Contract.Ensures(Contract.Result<CultureInfo>() != null);
587
588             CultureInfo culture;
589
590             try {
591                 culture = new CultureInfo(name);
592             } catch(ArgumentException) {
593                 // When CultureInfo throws this exception, it may be because someone passed the form
594                 // like "az-az" because it came out of an http accept lang. We should try a little
595                 // parsing to perhaps fall back to "az" here and use *it* to create the neutral.
596
597                 int idx;
598
599                 culture = null;
600                 for(idx = 0; idx < name.Length; idx++) {
601                     if('-' == name[idx]) {
602                         try {
603                             culture = new CultureInfo(name.Substring(0, idx));
604                             break;
605                         } catch(ArgumentException) {
606                             // throw the original exception so the name in the string will be right
607                             throw;
608                         }
609                     }
610                 }
611
612                 if(null == culture) {
613                     // nothing to save here; throw the original exception
614                     throw;
615                 }
616             }
617
618             //In the most common case, they've given us a specific culture, so we'll just return that.
619             if (!(culture.IsNeutralCulture)) {
620                 return culture;
621             }
622
623             return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE));
624         }
625 #endif // !FEATURE_CORECLR
626
627         internal static bool VerifyCultureName(String cultureName, bool throwException) 
628         {
629             // This function is used by ResourceManager.GetResourceFileName(). 
630             // ResourceManager searches for resource using CultureInfo.Name,
631             // so we should check against CultureInfo.Name.
632
633             for (int i=0; i<cultureName.Length; i++) {
634                 char c = cultureName[i];
635
636                 if (Char.IsLetterOrDigit(c) || c=='-' || c=='_') {
637                     continue;
638                 }
639                 if (throwException) {
640                     throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", cultureName));
641                 }
642                 return false;
643             }
644             return true;
645             
646         }
647
648         internal static bool VerifyCultureName(CultureInfo culture, bool throwException) {
649             Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null");
650
651             //If we have an instance of one of our CultureInfos, the user can't have changed the
652             //name and we know that all names are valid in files.
653             if (!culture.m_isInherited) {
654                 return true;
655             }
656
657             return VerifyCultureName(culture.Name, throwException);
658
659         }
660
661         ////////////////////////////////////////////////////////////////////////
662         //
663         //  CurrentCulture
664         //
665         //  This instance provides methods based on the current user settings.
666         //  These settings are volatile and may change over the lifetime of the
667         //  thread.
668         //
669         ////////////////////////////////////////////////////////////////////////
670
671
672         public static CultureInfo CurrentCulture
673         {
674             get {
675                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
676
677 #if !FEATURE_CORECLR
678                 return Thread.CurrentThread.CurrentCulture;
679 #else
680                 // In the case of CoreCLR, Thread.m_CurrentCulture and
681                 // Thread.m_CurrentUICulture are thread static so as not to let
682                 // CultureInfo objects leak across AppDomain boundaries. The
683                 // fact that these fields are thread static introduces overhead
684                 // in accessing them (through Thread.CurrentCulture). There is
685                 // also overhead in accessing Thread.CurrentThread. In this
686                 // case, we can avoid the overhead of Thread.CurrentThread
687                 // because these fields are thread static, and so do not
688                 // require a Thread instance to be accessed.
689 #if FEATURE_APPX
690                 if(AppDomain.IsAppXModel()) {
691                     CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
692                     if (culture != null)
693                         return culture;
694                 }
695 #endif
696                 return Thread.m_CurrentCulture ??
697                     s_DefaultThreadCurrentCulture ??
698                     s_userDefaultCulture ??
699                     UserDefaultCulture;
700 #endif
701             }
702
703             set {
704 #if FEATURE_APPX
705                     if (value == null) {
706                         throw new ArgumentNullException("value");
707                     }                    
708
709                     if (AppDomain.IsAppXModel()) {
710                         if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
711                             // successfully set the culture, otherwise fallback to legacy path
712                             return; 
713                         }
714                     }
715 #endif
716                     Thread.CurrentThread.CurrentCulture = value;
717             }
718         }
719
720         //
721         // This is the equivalence of the Win32 GetUserDefaultLCID()
722         //
723         internal static CultureInfo UserDefaultCulture {
724             get
725             {
726                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
727
728                 CultureInfo temp = s_userDefaultCulture;
729                 if (temp == null)
730                 {
731                     //
732                     // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
733                     // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo
734                     // creation path. the recursion can happen if the current user culture is a replaced custom culture.
735                     //
736                     
737                     s_userDefaultCulture = CultureInfo.InvariantCulture;
738                     temp = InitUserDefaultCulture();
739                     s_userDefaultCulture = temp;
740                 }
741                 return (temp);
742             }
743         }
744
745         //
746         //  This is the equivalence of the Win32 GetUserDefaultUILanguage()
747         //
748         internal static CultureInfo UserDefaultUICulture {
749             get {
750                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
751
752                 CultureInfo temp = s_userDefaultUICulture;
753                 if (temp == null) 
754                 {
755                     //
756                     // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
757                     // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo
758                     // creation path. the recursion can happen if the current user culture is a replaced custom culture.
759                     //
760                     
761                     s_userDefaultUICulture = CultureInfo.InvariantCulture;
762                     
763                     temp = InitUserDefaultUICulture();
764                     s_userDefaultUICulture = temp;
765                 }
766                 return (temp);
767             }
768         }
769
770
771         public static CultureInfo CurrentUICulture {
772             get {
773                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
774
775 #if !FEATURE_CORECLR
776                 return Thread.CurrentThread.CurrentUICulture;
777 #else
778                 // In the case of CoreCLR, Thread.m_CurrentCulture and
779                 // Thread.m_CurrentUICulture are thread static so as not to let
780                 // CultureInfo objects leak across AppDomain boundaries. The
781                 // fact that these fields are thread static introduces overhead
782                 // in accessing them (through Thread.CurrentCulture). There is
783                 // also overhead in accessing Thread.CurrentThread. In this
784                 // case, we can avoid the overhead of Thread.CurrentThread
785                 // because these fields are thread static, and so do not
786                 // require a Thread instance to be accessed.
787 #if FEATURE_APPX
788                 if(AppDomain.IsAppXModel()) {
789                     CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
790                     if (culture != null)
791                         return culture;
792                 }
793 #endif
794                 return Thread.m_CurrentUICulture ??
795                     s_DefaultThreadCurrentUICulture ??
796                     s_userDefaultUICulture ??
797                     UserDefaultUICulture;
798 #endif
799             }
800
801             set {
802 #if FEATURE_APPX
803                     if (value == null) {
804                         throw new ArgumentNullException("value");
805                     }                    
806
807                     if (AppDomain.IsAppXModel()) {
808                         if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
809                             // successfully set the culture, otherwise fallback to legacy path
810                             return; 
811                         }
812                     }
813 #endif
814                     Thread.CurrentThread.CurrentUICulture = value;
815             }
816         }
817
818
819         //
820         // This is the equivalence of the Win32 GetSystemDefaultUILanguage()
821         //
822         public static CultureInfo InstalledUICulture {
823             get {
824                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
825
826                 CultureInfo temp = s_InstalledUICultureInfo;
827                 if (temp == null) {
828                     String strDefault = GetSystemDefaultUILanguage();
829                     temp = GetCultureByName(strDefault, true);
830
831                     if (temp == null)
832                     {
833                         temp = InvariantCulture;
834                     }
835
836                     temp.m_isReadOnly = true;
837                     s_InstalledUICultureInfo = temp;
838                 }
839                 return (temp);
840             }
841         }
842
843         public static CultureInfo DefaultThreadCurrentCulture {
844             get {
845                 return s_DefaultThreadCurrentCulture;
846             }
847
848             [System.Security.SecuritySafeCritical]  // auto-generated
849 #pragma warning disable 618
850             [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
851 #pragma warning restore 618
852             set {
853
854                 // If you add pre-conditions to this method, check to see if you also need to 
855                 // add them to Thread.CurrentCulture.set.
856
857                 s_DefaultThreadCurrentCulture = value;
858             }
859         }
860
861         public static CultureInfo DefaultThreadCurrentUICulture {
862             get {
863                 return s_DefaultThreadCurrentUICulture;
864             }
865
866             [System.Security.SecuritySafeCritical]  // auto-generated
867 #pragma warning disable 618
868             [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
869 #pragma warning restore 618
870             set {
871
872                 //If they're trying to use a Culture with a name that we can't use in resource lookup,
873                 //don't even let them set it on the thread.
874
875                 // If you add more pre-conditions to this method, check to see if you also need to 
876                 // add them to Thread.CurrentUICulture.set.
877
878                 if (value != null) 
879                 {                   
880                     CultureInfo.VerifyCultureName(value, true);
881                 }
882
883                 s_DefaultThreadCurrentUICulture = value;
884             }
885         }
886
887         ////////////////////////////////////////////////////////////////////////
888         //
889         //  InvariantCulture
890         //
891         //  This instance provides methods, for example for casing and sorting,
892         //  that are independent of the system and current user settings.  It
893         //  should be used only by processes such as some system services that
894         //  require such invariant results (eg. file systems).  In general,
895         //  the results are not linguistically correct and do not match any
896         //  culture info.
897         //
898         ////////////////////////////////////////////////////////////////////////
899
900
901         public static CultureInfo InvariantCulture {
902             [Pure]
903             get {
904                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
905                 return (s_InvariantCultureInfo);
906             }
907         }
908
909
910         ////////////////////////////////////////////////////////////////////////
911         //
912         //  Parent
913         //
914         //  Return the parent CultureInfo for the current instance.
915         //
916         ////////////////////////////////////////////////////////////////////////
917
918         public virtual CultureInfo Parent
919         {
920             [System.Security.SecuritySafeCritical]  // auto-generated
921             get
922             {
923                 Contract.Ensures(Contract.Result<CultureInfo>() != null);
924
925                 if (null == m_parent)
926                 {
927                     try
928                     {
929                         string parentName = this.m_cultureData.SPARENT;
930
931                         if (String.IsNullOrEmpty(parentName))
932                         {
933                             m_parent = InvariantCulture;
934                         }
935                         else
936                         {
937                             m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
938                         }
939                     }
940                     catch (ArgumentException)
941                     {
942                         // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
943                         // We can't allow ourselves to fail.  In case of custom cultures the parent of the
944                         // current custom culture isn't installed.
945                         m_parent =  InvariantCulture;
946                     }
947                 }
948                 return m_parent;
949             }
950         }
951
952         ////////////////////////////////////////////////////////////////////////
953         //
954         //  LCID
955         //
956         //  Returns a properly formed culture identifier for the current
957         //  culture info.
958         //
959         ////////////////////////////////////////////////////////////////////////
960
961 #if FEATURE_USE_LCID
962         public virtual int LCID {
963             get {
964                 return (this.m_cultureData.ILANGUAGE);
965             }
966         }
967 #endif
968
969         ////////////////////////////////////////////////////////////////////////
970         //
971         //  BaseInputLanguage
972         //
973         //  Essentially an LCID, though one that may be different than LCID in the case
974         //  of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED).
975         //
976         ////////////////////////////////////////////////////////////////////////
977 #if FEATURE_USE_LCID
978         [System.Runtime.InteropServices.ComVisible(false)]
979         public virtual int KeyboardLayoutId
980         {
981             get
982             {
983                 int keyId = this.m_cultureData.IINPUTLANGUAGEHANDLE;
984
985                 // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID.
986                 return (keyId);
987             }
988         }
989 #endif
990
991 #if !FEATURE_CORECLR
992         public static CultureInfo[] GetCultures(CultureTypes types) {
993             Contract.Ensures(Contract.Result<CultureInfo[]>() != null);
994             // internally we treat UserCustomCultures as Supplementals but v2
995             // treats as Supplementals and Replacements
996             if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture)
997             {
998                 types |= CultureTypes.ReplacementCultures;
999             }
1000             return (CultureData.GetCultures(types));
1001         }
1002 #endif
1003
1004         ////////////////////////////////////////////////////////////////////////
1005         //
1006         //  Name
1007         //
1008         //  Returns the full name of the CultureInfo. The name is in format like
1009         //  "en-US"  This version does NOT include sort information in the name.
1010         //
1011         ////////////////////////////////////////////////////////////////////////
1012         public virtual String Name {
1013             get {
1014                 Contract.Ensures(Contract.Result<String>() != null);
1015
1016                 // We return non sorting name here.
1017                 if (this.m_nonSortName == null) {
1018                     this.m_nonSortName = this.m_cultureData.SNAME;
1019                     if (this.m_nonSortName == null) {
1020                         this.m_nonSortName = String.Empty;
1021                     }
1022                 }
1023                 return this.m_nonSortName;
1024             }
1025         }
1026
1027         // This one has the sort information (ie: de-DE_phoneb)
1028         internal String SortName
1029         {
1030             get
1031             {
1032                 if (this.m_sortName == null)
1033                 {
1034                     this.m_sortName = this.m_cultureData.SCOMPAREINFO;
1035                 }
1036
1037                 return this.m_sortName;
1038             }
1039         }
1040
1041 #if !FEATURE_CORECLR
1042         [System.Runtime.InteropServices.ComVisible(false)]
1043         public String IetfLanguageTag
1044         {
1045             get
1046             {
1047                 Contract.Ensures(Contract.Result<String>() != null);
1048
1049                 // special case the compatibility cultures
1050                 switch (this.Name)
1051                 {
1052                     case "zh-CHT":
1053                         return "zh-Hant";
1054                     case "zh-CHS":
1055                         return "zh-Hans";
1056                     default:
1057                         return this.Name;
1058                 }
1059             }
1060         }
1061 #endif
1062
1063         ////////////////////////////////////////////////////////////////////////
1064         //
1065         //  DisplayName
1066         //
1067         //  Returns the full name of the CultureInfo in the localized language.
1068         //  For example, if the localized language of the runtime is Spanish and the CultureInfo is
1069         //  US English, "Ingles (Estados Unidos)" will be returned.
1070         //
1071         ////////////////////////////////////////////////////////////////////////
1072         public virtual String DisplayName
1073         {
1074             [System.Security.SecuritySafeCritical]  // auto-generated
1075             get
1076             {
1077                 Contract.Ensures(Contract.Result<String>() != null);
1078                 Contract.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set");
1079
1080                 return m_cultureData.SLOCALIZEDDISPLAYNAME;
1081             }
1082         }
1083
1084         ////////////////////////////////////////////////////////////////////////
1085         //
1086         //  GetNativeName
1087         //
1088         //  Returns the full name of the CultureInfo in the native language.
1089         //  For example, if the CultureInfo is US English, "English
1090         //  (United States)" will be returned.
1091         //
1092         ////////////////////////////////////////////////////////////////////////
1093         public virtual String NativeName {
1094             [System.Security.SecuritySafeCritical]  // auto-generated
1095             get {
1096                 Contract.Ensures(Contract.Result<String>() != null);
1097                 return (this.m_cultureData.SNATIVEDISPLAYNAME);
1098             }
1099         }
1100
1101         ////////////////////////////////////////////////////////////////////////
1102         //
1103         //  GetEnglishName
1104         //
1105         //  Returns the full name of the CultureInfo in English.
1106         //  For example, if the CultureInfo is US English, "English
1107         //  (United States)" will be returned.
1108         //
1109         ////////////////////////////////////////////////////////////////////////
1110         public virtual String EnglishName {
1111             [System.Security.SecuritySafeCritical]  // auto-generated
1112             get {
1113                 Contract.Ensures(Contract.Result<String>() != null);
1114                 return (this.m_cultureData.SENGDISPLAYNAME);
1115             }
1116         }
1117       
1118         // ie: en
1119         public virtual String TwoLetterISOLanguageName {
1120             [System.Security.SecuritySafeCritical]  // auto-generated
1121             get {
1122                 Contract.Ensures(Contract.Result<String>() != null);
1123                 return (this.m_cultureData.SISO639LANGNAME);
1124             }
1125         }
1126
1127 #if !FEATURE_CORECLR
1128         // ie: eng
1129         public virtual String ThreeLetterISOLanguageName {
1130             [System.Security.SecuritySafeCritical]  // auto-generated
1131             get {
1132                 Contract.Ensures(Contract.Result<String>() != null);
1133                 return (this.m_cultureData.SISO639LANGNAME2);
1134             }
1135         }
1136
1137         ////////////////////////////////////////////////////////////////////////
1138         //
1139         //  ThreeLetterWindowsLanguageName
1140         //
1141         //  Returns the 3 letter windows language name for the current instance.  eg: "ENU"
1142         //  The ISO names are much preferred
1143         //
1144         ////////////////////////////////////////////////////////////////////////
1145         public virtual String ThreeLetterWindowsLanguageName {
1146             [System.Security.SecuritySafeCritical]  // auto-generated
1147             get {
1148                 Contract.Ensures(Contract.Result<String>() != null);
1149                 return (this.m_cultureData.SABBREVLANGNAME);
1150             }
1151         }
1152 #endif
1153
1154         ////////////////////////////////////////////////////////////////////////
1155         //
1156         //  CompareInfo               Read-Only Property
1157         //
1158         //  Gets the CompareInfo for this culture.
1159         //
1160         ////////////////////////////////////////////////////////////////////////
1161         public virtual CompareInfo CompareInfo
1162         {
1163             get
1164             {
1165                 Contract.Ensures(Contract.Result<CompareInfo>() != null);
1166
1167                 if (this.compareInfo == null)
1168                 {
1169                     // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from
1170                     // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
1171                     CompareInfo temp = UseUserOverride 
1172                                         ? GetCultureInfo(this.m_name).CompareInfo 
1173                                         : new CompareInfo(this);
1174                     if (CompatibilitySwitches.IsCompatibilityBehaviorDefined)
1175                     {
1176                         this.compareInfo = temp;
1177                     }
1178                     else
1179                     {
1180                         return temp;
1181                     }
1182                 }
1183                 return (compareInfo);
1184             }
1185         }
1186
1187 #if !FEATURE_CORECLR
1188         ////////////////////////////////////////////////////////////////////////
1189         //
1190         //  RegionInfo
1191         //
1192         //  Gets the RegionInfo for this culture.
1193         //
1194         ////////////////////////////////////////////////////////////////////////
1195         private RegionInfo Region
1196         {
1197             get
1198             {
1199                 if (regionInfo==null)
1200                 {
1201                     // Make a new regionInfo
1202                     RegionInfo tempRegionInfo = new RegionInfo(this.m_cultureData);
1203                     regionInfo = tempRegionInfo;
1204                 }
1205                 return (regionInfo);
1206             }
1207         }
1208 #endif // FEATURE_CORECLR
1209
1210
1211
1212         ////////////////////////////////////////////////////////////////////////
1213         //
1214         //  TextInfo
1215         //
1216         //  Gets the TextInfo for this culture.
1217         //
1218         ////////////////////////////////////////////////////////////////////////
1219
1220
1221         public virtual TextInfo TextInfo {
1222             get {
1223                 Contract.Ensures(Contract.Result<TextInfo>() != null);
1224
1225                 if (textInfo==null) 
1226                 {
1227                     // Make a new textInfo
1228                     TextInfo tempTextInfo = new TextInfo(this.m_cultureData);
1229                     tempTextInfo.SetReadOnlyState(m_isReadOnly);
1230
1231                     if (CompatibilitySwitches.IsCompatibilityBehaviorDefined)
1232                     {
1233                         textInfo = tempTextInfo;
1234                     }
1235                     else
1236                     {
1237                         return tempTextInfo;
1238                     }
1239                 }
1240                 return (textInfo);
1241             }
1242         }
1243
1244         ////////////////////////////////////////////////////////////////////////
1245         //
1246         //  Equals
1247         //
1248         //  Implements Object.Equals().  Returns a boolean indicating whether
1249         //  or not object refers to the same CultureInfo as the current instance.
1250         //
1251         ////////////////////////////////////////////////////////////////////////
1252
1253
1254         public override bool Equals(Object value)
1255         {
1256             if (Object.ReferenceEquals(this, value))
1257                 return true;
1258
1259             CultureInfo that = value as CultureInfo;
1260
1261             if (that != null)
1262             {
1263                 // using CompareInfo to verify the data passed through the constructor
1264                 // CultureInfo(String cultureName, String textAndCompareCultureName)
1265
1266                 return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo));
1267             }
1268
1269             return (false);
1270         }
1271
1272
1273         ////////////////////////////////////////////////////////////////////////
1274         //
1275         //  GetHashCode
1276         //
1277         //  Implements Object.GetHashCode().  Returns the hash code for the
1278         //  CultureInfo.  The hash code is guaranteed to be the same for CultureInfo A
1279         //  and B where A.Equals(B) is true.
1280         //
1281         ////////////////////////////////////////////////////////////////////////
1282
1283         public override int GetHashCode()
1284         {
1285             return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode());
1286         }
1287
1288
1289         ////////////////////////////////////////////////////////////////////////
1290         //
1291         //  ToString
1292         //
1293         //  Implements Object.ToString().  Returns the name of the CultureInfo,
1294         //  eg. "de-DE_phoneb", "en-US", or "fj-FJ".
1295         //
1296         ////////////////////////////////////////////////////////////////////////
1297
1298
1299         public override String ToString()
1300         {
1301             Contract.Ensures(Contract.Result<String>() != null);
1302
1303             Contract.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set");
1304             return m_name;
1305         }
1306
1307
1308         public virtual Object GetFormat(Type formatType) {
1309             if (formatType == typeof(NumberFormatInfo)) {
1310                 return (NumberFormat);
1311             }
1312             if (formatType == typeof(DateTimeFormatInfo)) {
1313                 return (DateTimeFormat);
1314             }
1315             return (null);
1316         }
1317
1318         public virtual bool IsNeutralCulture {
1319             get {
1320                 return this.m_cultureData.IsNeutralCulture;
1321             }
1322         }
1323
1324 #if !FEATURE_CORECLR
1325         [System.Runtime.InteropServices.ComVisible(false)]
1326         public CultureTypes CultureTypes
1327         {
1328             get
1329             {
1330                 CultureTypes types = 0;
1331
1332                 if (m_cultureData.IsNeutralCulture)
1333                     types |= CultureTypes.NeutralCultures;
1334                 else 
1335                     types |= CultureTypes.SpecificCultures;
1336
1337                 types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0;
1338
1339 // Disable  warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
1340 #pragma warning disable 618
1341                 types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0;
1342
1343 #pragma warning restore 618
1344                 types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0;
1345                 types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0;
1346
1347                 return types;
1348             }
1349         }
1350 #endif
1351
1352         public virtual NumberFormatInfo NumberFormat {
1353             get 
1354             {
1355                 Contract.Ensures(Contract.Result<NumberFormatInfo>() != null);
1356
1357                 if (numInfo == null) {
1358                     NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData);
1359                     temp.isReadOnly = m_isReadOnly;
1360                     numInfo = temp;
1361                 }
1362                 return (numInfo);
1363             }
1364             set {
1365                 if (value == null) {
1366                     throw new ArgumentNullException("value",
1367                         Environment.GetResourceString("ArgumentNull_Obj"));
1368                 }
1369                 Contract.EndContractBlock();
1370                 VerifyWritable();
1371                 numInfo = value;
1372             }
1373         }
1374
1375         ////////////////////////////////////////////////////////////////////////
1376         //
1377         // GetDateTimeFormatInfo
1378         //
1379         // Create a DateTimeFormatInfo, and fill in the properties according to
1380         // the CultureID.
1381         //
1382         ////////////////////////////////////////////////////////////////////////
1383
1384
1385         public virtual DateTimeFormatInfo DateTimeFormat {
1386             get {
1387                 Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
1388
1389                 if (dateTimeInfo == null) {
1390                     // Change the calendar of DTFI to the specified calendar of this CultureInfo.
1391                     DateTimeFormatInfo temp = new DateTimeFormatInfo(
1392                         this.m_cultureData, this.Calendar);
1393                     temp.m_isReadOnly = m_isReadOnly;
1394                     System.Threading.Thread.MemoryBarrier();
1395                     dateTimeInfo = temp;
1396                 }
1397                 return (dateTimeInfo);
1398             }
1399
1400             set {
1401                 if (value == null) {
1402                     throw new ArgumentNullException("value",
1403                         Environment.GetResourceString("ArgumentNull_Obj"));
1404                 }
1405                 Contract.EndContractBlock();
1406                 VerifyWritable();
1407                 dateTimeInfo = value;
1408             }
1409         }
1410
1411
1412
1413         public void ClearCachedData() {
1414             s_userDefaultUICulture = null;
1415             s_userDefaultCulture = null;
1416
1417             RegionInfo.s_currentRegionInfo = null;
1418 #if !FEATURE_CORECLR // System.TimeZone does not exist in CoreCLR
1419             TimeZone.ResetTimeZone();
1420 #endif // FEATURE_CORECLR
1421             TimeZoneInfo.ClearCachedData();
1422             // Delete the cached cultures.
1423             s_LcidCachedCultures = null;
1424             s_NameCachedCultures = null;
1425
1426             CultureData.ClearCachedData();
1427         }
1428
1429         /*=================================GetCalendarInstance==========================
1430         **Action: Map a Win32 CALID to an instance of supported calendar.
1431         **Returns: An instance of calendar.
1432         **Arguments: calType    The Win32 CALID
1433         **Exceptions:
1434         **      Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
1435         **      If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar.
1436         ============================================================================*/
1437         internal static Calendar GetCalendarInstance(int calType) {
1438             if (calType==Calendar.CAL_GREGORIAN) {
1439                 return (new GregorianCalendar());
1440             }
1441             return GetCalendarInstanceRare(calType);
1442         }
1443
1444         //This function exists as a shortcut to prevent us from loading all of the non-gregorian
1445         //calendars unless they're required.
1446         internal static Calendar GetCalendarInstanceRare(int calType) {
1447             Contract.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN");
1448
1449             switch (calType) {
1450                 case Calendar.CAL_GREGORIAN_US:               // Gregorian (U.S.) calendar
1451                 case Calendar.CAL_GREGORIAN_ME_FRENCH:        // Gregorian Middle East French calendar
1452                 case Calendar.CAL_GREGORIAN_ARABIC:           // Gregorian Arabic calendar
1453                 case Calendar.CAL_GREGORIAN_XLIT_ENGLISH:     // Gregorian Transliterated English calendar
1454                 case Calendar.CAL_GREGORIAN_XLIT_FRENCH:      // Gregorian Transliterated French calendar
1455                     return (new GregorianCalendar((GregorianCalendarTypes)calType));
1456                 case Calendar.CAL_TAIWAN:                     // Taiwan Era calendar
1457                     return (new TaiwanCalendar());
1458                 case Calendar.CAL_JAPAN:                      // Japanese Emperor Era calendar
1459                     return (new JapaneseCalendar());
1460                 case Calendar.CAL_KOREA:                      // Korean Tangun Era calendar
1461                     return (new KoreanCalendar());
1462                 case Calendar.CAL_THAI:                       // Thai calendar
1463                     return (new ThaiBuddhistCalendar());
1464                 case Calendar.CAL_HIJRI:                      // Hijri (Arabic Lunar) calendar
1465                     return (new HijriCalendar());
1466                 case Calendar.CAL_HEBREW:                     // Hebrew (Lunar) calendar
1467                     return (new HebrewCalendar());
1468                 case Calendar.CAL_UMALQURA:
1469                     return (new UmAlQuraCalendar());
1470                 case Calendar.CAL_PERSIAN:
1471                     return (new PersianCalendar());
1472                 case Calendar.CAL_CHINESELUNISOLAR:
1473                     return (new ChineseLunisolarCalendar());
1474                 case Calendar.CAL_JAPANESELUNISOLAR:
1475                     return (new JapaneseLunisolarCalendar());
1476                 case Calendar.CAL_KOREANLUNISOLAR:
1477                     return (new KoreanLunisolarCalendar());
1478                 case Calendar.CAL_TAIWANLUNISOLAR:
1479                     return (new TaiwanLunisolarCalendar());
1480             }
1481             return (new GregorianCalendar());
1482         }
1483
1484
1485         /*=================================Calendar==========================
1486         **Action: Return/set the default calendar used by this culture.
1487         ** This value can be overridden by regional option if this is a current culture.
1488         **Returns:
1489         **Arguments:
1490         **Exceptions:
1491         **  ArgumentNull_Obj if the set value is null.
1492         ============================================================================*/
1493
1494
1495         public virtual Calendar Calendar {
1496             get {
1497                 Contract.Ensures(Contract.Result<Calendar>() != null);
1498                 if (calendar == null) {
1499                     Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0");
1500                     // Get the default calendar for this culture.  Note that the value can be
1501                     // from registry if this is a user default culture.
1502                     Calendar newObj = this.m_cultureData.DefaultCalendar;
1503
1504                     System.Threading.Thread.MemoryBarrier();
1505                     newObj.SetReadOnlyState(m_isReadOnly);
1506                     calendar = newObj;
1507                 }
1508                 return (calendar);
1509             }
1510         }
1511
1512         /*=================================OptionCalendars==========================
1513         **Action: Return an array of the optional calendar for this culture.
1514         **Returns: an array of Calendar.
1515         **Arguments:
1516         **Exceptions:
1517         ============================================================================*/
1518
1519
1520         public virtual Calendar[] OptionalCalendars {
1521             get {
1522                 Contract.Ensures(Contract.Result<Calendar[]>() != null);
1523
1524                 //
1525                 // This property always returns a new copy of the calendar array.
1526                 //
1527                 int[] calID = this.m_cultureData.CalendarIds;
1528                 Calendar [] cals = new Calendar[calID.Length];
1529                 for (int i = 0; i < cals.Length; i++) {
1530                     cals[i] = GetCalendarInstance(calID[i]);
1531                 }
1532                 return (cals);
1533             }
1534         }
1535
1536
1537         public bool UseUserOverride {
1538             get {
1539                 return (this.m_cultureData.UseUserOverride);
1540             }
1541         }
1542
1543 #if !FEATURE_CORECLR
1544         [System.Security.SecuritySafeCritical]  // auto-generated
1545         [System.Runtime.InteropServices.ComVisible(false)]
1546         public CultureInfo GetConsoleFallbackUICulture()
1547         {
1548             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1549
1550             CultureInfo temp = m_consoleFallbackCulture;
1551             if (temp == null)
1552             {
1553                 temp = CreateSpecificCulture(this.m_cultureData.SCONSOLEFALLBACKNAME);
1554                 temp.m_isReadOnly = true;
1555                 m_consoleFallbackCulture = temp;
1556             }
1557             return (temp);
1558         }
1559 #endif
1560
1561         public virtual Object Clone()
1562         {
1563             Contract.Ensures(Contract.Result<Object>() != null);
1564
1565             CultureInfo ci = (CultureInfo)MemberwiseClone();
1566             ci.m_isReadOnly = false;
1567
1568             //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
1569             //they've already been allocated.  If this is a derived type, we'll take a more generic codepath.
1570             if (!m_isInherited) 
1571             {
1572                 if (this.dateTimeInfo != null)
1573                 {
1574                     ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone();
1575                 }
1576                 if (this.numInfo != null)
1577                 {
1578                     ci.numInfo = (NumberFormatInfo)this.numInfo.Clone();
1579                 }
1580
1581             }
1582             else
1583             {
1584                 ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
1585                 ci.NumberFormat   = (NumberFormatInfo)this.NumberFormat.Clone();
1586             }
1587
1588             if (textInfo != null)
1589             {
1590                 ci.textInfo = (TextInfo) textInfo.Clone();
1591             }
1592
1593             if (calendar != null)
1594             {
1595                 ci.calendar = (Calendar) calendar.Clone();
1596             }
1597
1598             return (ci);
1599         }
1600
1601
1602         public static CultureInfo ReadOnly(CultureInfo ci) {
1603             if (ci == null) {
1604                 throw new ArgumentNullException("ci");
1605             }
1606             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1607             Contract.EndContractBlock();
1608
1609             if (ci.IsReadOnly) {
1610                 return (ci);
1611             }
1612             CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
1613
1614             if (!ci.IsNeutralCulture)
1615             {
1616                 //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
1617                 //they've already been allocated.  If this is a derived type, we'll take a more generic codepath.
1618                 if (!ci.m_isInherited) {
1619                     if (ci.dateTimeInfo != null) {
1620                         newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo);
1621                     }
1622                     if (ci.numInfo != null) {
1623                         newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo);
1624                     }
1625
1626                 } else {
1627                     newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat);
1628                     newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
1629                 }
1630             }
1631             
1632             if (ci.textInfo != null)
1633             {
1634                 newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo);
1635             }
1636
1637             if (ci.calendar != null)
1638             {
1639                 newInfo.calendar = Calendar.ReadOnly(ci.calendar);
1640             }
1641
1642             // Don't set the read-only flag too early.
1643             // We should set the read-only flag here.  Otherwise, info.DateTimeFormat will not be able to set.
1644             newInfo.m_isReadOnly = true;
1645
1646             return (newInfo);
1647         }
1648
1649
1650         public bool IsReadOnly {
1651             get {
1652                 return (m_isReadOnly);
1653             }
1654         }
1655
1656         private void VerifyWritable() {
1657             if (m_isReadOnly) {
1658                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
1659             }
1660             Contract.EndContractBlock();
1661         }
1662
1663         // For resource lookup, we consider a culture the invariant culture by name equality. 
1664         // We perform this check frequently during resource lookup, so adding a property for
1665         // improved readability.
1666         internal bool HasInvariantCultureName
1667         {
1668             get { return Name == CultureInfo.InvariantCulture.Name; }
1669         }
1670
1671         // Helper function both both overloads of GetCachedReadOnlyCulture.  If lcid is 0, we use the name.
1672         // If lcid is -1, use the altName and create one of those special SQL cultures.
1673         internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName)
1674         {
1675             // There is a race condition in this code with the side effect that the second thread's value
1676             // clobbers the first in the dictionary. This is an acceptable race condition since the CultureInfo objects
1677             // are content equal (but not reference equal). Since we make no guarantees there, this race condition is
1678             // acceptable.
1679             // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus 
1680             // Hashtable thread safety.
1681
1682             // retval is our return value.
1683             CultureInfo retval;
1684
1685             // Temporary hashtable for the names.
1686             Hashtable tempNameHT = s_NameCachedCultures;
1687
1688             if (name != null)
1689             {
1690                 name = CultureData.AnsiToLower(name);
1691             }
1692             
1693             if (altName != null)
1694             {
1695                 altName = CultureData.AnsiToLower(altName);
1696             }
1697
1698             // We expect the same result for both hashtables, but will test individually for added safety.
1699             if (tempNameHT == null)
1700             {
1701                 tempNameHT = Hashtable.Synchronized(new Hashtable());
1702             }
1703             else
1704             {
1705                 // If we are called by name, check if the object exists in the hashtable.  If so, return it.
1706                 if (lcid == -1)
1707                 {
1708                     retval = (CultureInfo)tempNameHT[name + '\xfffd' + altName];
1709                     if (retval != null)
1710                     {
1711                         return retval;
1712                     }
1713                 }
1714                 else if (lcid == 0)
1715                 {
1716                     retval = (CultureInfo)tempNameHT[name];
1717                     if (retval != null)
1718                     {
1719                         return retval;
1720                     }
1721                 }
1722             }
1723 #if FEATURE_USE_LCID
1724             // Next, the Lcid table.
1725             Hashtable tempLcidHT = s_LcidCachedCultures;
1726
1727             if (tempLcidHT == null)
1728             {
1729                 // Case insensitive is not an issue here, save the constructor call.
1730                 tempLcidHT = Hashtable.Synchronized(new Hashtable());
1731             }
1732             else
1733             {
1734                 // If we were called by Lcid, check if the object exists in the table.  If so, return it.
1735                 if (lcid > 0)
1736                 {
1737                     retval = (CultureInfo) tempLcidHT[lcid];
1738                     if (retval != null)
1739                     {
1740                         return retval;
1741                     }
1742                 }
1743             }
1744 #endif
1745             // We now have two temporary hashtables and the desired object was not found.
1746             // We'll construct it.  We catch any exceptions from the constructor call and return null.
1747             try
1748             {
1749                 switch(lcid)
1750                 {
1751                     case -1:
1752                         // call the private constructor
1753                         retval = new CultureInfo(name, altName);
1754                         break;
1755
1756                     case 0:
1757                         retval = new CultureInfo(name, false);
1758                         break;
1759
1760                     default:
1761 #if FEATURE_USE_LCID
1762                         retval = new CultureInfo(lcid, false);
1763                         break;
1764 #else
1765                         return null;
1766 #endif
1767                 }
1768             }
1769             catch(ArgumentException)
1770             {
1771                 return null;
1772             }
1773
1774             // Set it to read-only
1775             retval.m_isReadOnly = true;
1776
1777             if (lcid == -1)
1778             {
1779                 // This new culture will be added only to the name hash table.
1780                 tempNameHT[name + '\xfffd' + altName] = retval;
1781
1782                 // when lcid == -1 then TextInfo object is already get created and we need to set it as read only.
1783                 retval.TextInfo.SetReadOnlyState(true);
1784             }
1785             else
1786             {
1787                 // Remember our name (as constructed).  Do NOT use alternate sort name versions because
1788                 // we have internal state representing the sort.  (So someone would get the wrong cached version)
1789                 string newName = CultureData.AnsiToLower(retval.m_name);
1790                 
1791                 // We add this new culture info object to both tables.
1792                 tempNameHT[newName] = retval;
1793 #if FEATURE_USE_LCID
1794                 const int LCID_ZH_CHS_HANS = 0x0004;
1795                 const int LCID_ZH_CHT_HANT = 0x7c04;
1796
1797                 if ((retval.LCID == LCID_ZH_CHS_HANS && newName == "zh-hans")
1798                  || (retval.LCID == LCID_ZH_CHT_HANT && newName == "zh-hant"))
1799                 {
1800                     // do nothing because we only want zh-CHS and zh-CHT to cache
1801                     // by lcid
1802                 }
1803                 else
1804                 {
1805                     tempLcidHT[retval.LCID] = retval;
1806                 }
1807
1808 #endif
1809             }
1810
1811 #if FEATURE_USE_LCID
1812             // Copy the two hashtables to the corresponding member variables.  This will potentially overwrite
1813             // new tables simultaneously created by a new thread, but maximizes thread safety.
1814             if(-1 != lcid)
1815             {
1816                 // Only when we modify the lcid hash table, is there a need to overwrite.
1817                 s_LcidCachedCultures = tempLcidHT;
1818             }
1819 #endif
1820
1821             s_NameCachedCultures = tempNameHT;
1822
1823             // Finally, return our new CultureInfo object.
1824             return retval;
1825         }
1826
1827 #if FEATURE_USE_LCID
1828         // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1829         // if not found).  (LCID version)... use named version
1830         public static CultureInfo GetCultureInfo(int culture)
1831         {
1832             // Must check for -1 now since the helper function uses the value to signal
1833             // the altCulture code path for SQL Server.
1834             // Also check for zero as this would fail trying to add as a key to the hash.
1835             if (culture <= 0) {
1836                 throw new ArgumentOutOfRangeException("culture",
1837                     Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
1838             }
1839             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1840             Contract.EndContractBlock();
1841             CultureInfo retval = GetCultureInfoHelper(culture, null, null);
1842             if (null == retval)
1843             {
1844                 throw new CultureNotFoundException(
1845                     "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
1846             }
1847             return retval;
1848         }
1849 #endif
1850
1851         // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1852         // if not found).  (Named version)
1853         public static CultureInfo GetCultureInfo(string name)
1854         {
1855             // Make sure we have a valid, non-zero length string as name
1856             if (name == null)
1857             {
1858                 throw new ArgumentNullException("name");
1859             }
1860             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1861             Contract.EndContractBlock();
1862
1863             CultureInfo retval = GetCultureInfoHelper(0, name, null);
1864             if (retval == null)
1865             {
1866                 throw new CultureNotFoundException(
1867                     "name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
1868                 
1869             }
1870             return retval;
1871         }
1872
1873         // Gets a cached copy of the specified culture from an internal hashtable (or creates it
1874         // if not found).
1875         public static CultureInfo GetCultureInfo(string name, string altName)
1876         {
1877             // Make sure we have a valid, non-zero length string as name
1878             if (null == name)
1879             {
1880                 throw new ArgumentNullException("name");
1881             }
1882
1883             if (null == altName)
1884             {
1885                 throw new ArgumentNullException("altName");
1886             }
1887             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1888             Contract.EndContractBlock();
1889
1890             CultureInfo retval = GetCultureInfoHelper(-1, name, altName);
1891             if (retval == null)
1892             {
1893                 throw new CultureNotFoundException("name or altName",
1894                                         String.Format(
1895                                             CultureInfo.CurrentCulture, 
1896                                             Environment.GetResourceString("Argument_OneOfCulturesNotSupported"), 
1897                                             name,
1898                                             altName));
1899             }
1900             return retval;
1901         }
1902
1903
1904 #if !FEATURE_CORECLR
1905         // This function is deprecated, we don't like it
1906         public static CultureInfo GetCultureInfoByIetfLanguageTag(string name)
1907         {
1908             Contract.Ensures(Contract.Result<CultureInfo>() != null);
1909
1910             // Disallow old zh-CHT/zh-CHS names
1911             if (name == "zh-CHT" || name == "zh-CHS")
1912             {
1913                 throw new CultureNotFoundException(
1914                             "name",
1915                             String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
1916                             );
1917             }
1918             
1919             CultureInfo ci = GetCultureInfo(name);
1920
1921             // Disallow alt sorts and es-es_TS
1922             if (ci.LCID > 0xffff || ci.LCID == 0x040a)
1923             {
1924                 throw new CultureNotFoundException(
1925                             "name",
1926                             String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
1927                             );
1928             }
1929             
1930             return ci;
1931         }
1932 #endif
1933         private static volatile bool s_isTaiwanSku;
1934         private static volatile bool s_haveIsTaiwanSku;
1935         internal static bool IsTaiwanSku
1936         {
1937             get
1938             {
1939                 if (!s_haveIsTaiwanSku)
1940                 {
1941                     s_isTaiwanSku = (GetSystemDefaultUILanguage() == "zh-TW");
1942                     s_haveIsTaiwanSku = true;
1943                 }
1944                 return (bool)s_isTaiwanSku;
1945             }
1946         }
1947
1948         //
1949         //  Helper Methods.
1950         //
1951         
1952         // Get Locale Info Ex calls.  So we don't have to muck with the different int/string return types we declared two of these:
1953         [System.Security.SecurityCritical]  // auto-generated
1954         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1955         internal static extern String nativeGetLocaleInfoEx(String localeName, uint field);
1956         
1957         [System.Security.SecuritySafeCritical]  // auto-generated
1958         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1959         internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field);
1960
1961         [System.Security.SecurityCritical]  // auto-generated
1962         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1963         internal static extern bool nativeSetThreadLocale(String localeName);
1964
1965         [System.Security.SecurityCritical]
1966         private static String GetDefaultLocaleName(int localeType)
1967         {
1968             Contract.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT");
1969
1970             string localeName = null;
1971             if(InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName)))
1972             {
1973                 return localeName;
1974             }
1975             return string.Empty;
1976         }
1977
1978         // Get the default locale name
1979         [System.Security.SecurityCritical]  // auto-generated
1980         [SuppressUnmanagedCodeSecurity]
1981         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1982         [return: MarshalAs(UnmanagedType.Bool)]
1983         private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString);
1984
1985         [System.Security.SecuritySafeCritical] // auto-generated
1986         private static String GetUserDefaultUILanguage()
1987         {
1988             string userDefaultUiLanguage = null;
1989             if(InternalGetUserDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref userDefaultUiLanguage)))
1990             {
1991                 return userDefaultUiLanguage;
1992             }
1993             return String.Empty;
1994         }
1995         
1996         // Get the user's default UI language, return locale name
1997         [System.Security.SecurityCritical]  // auto-generated
1998         [SuppressUnmanagedCodeSecurity]
1999         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
2000         [return: MarshalAs(UnmanagedType.Bool)]
2001         private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage);
2002
2003         [System.Security.SecuritySafeCritical] // auto-generated
2004         private static String GetSystemDefaultUILanguage()
2005         {
2006             string systemDefaultUiLanguage = null;
2007             if(InternalGetSystemDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref systemDefaultUiLanguage)))
2008             {
2009                 return systemDefaultUiLanguage;
2010             }
2011             return String.Empty;
2012
2013         }
2014
2015         [System.Security.SecurityCritical] // auto-generated
2016         [MethodImplAttribute(MethodImplOptions.InternalCall)]
2017         [SuppressUnmanagedCodeSecurity]
2018         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
2019         [return: MarshalAs(UnmanagedType.Bool)]
2020         private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage);
2021
2022 // Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
2023 #if FEATURE_CORECLR
2024         [System.Security.SecurityCritical]  // auto-generated
2025         [MethodImplAttribute(MethodImplOptions.InternalCall)]
2026         internal static extern String[] nativeGetResourceFallbackArray();
2027 #endif
2028     }
2029 }
2030