Inheritance: BaseInfoTable
        internal NumberFormatInfo(int dataItem, bool useUserOverride)
        {
            this.m_dataItem        = dataItem;
            this.m_useUserOverride = useUserOverride;

            if (this.m_dataItem != 0)
            {
                //
                //

                /*
                 * We don't have information for the following four.  All cultures use
                 * the same value set in the ctor of NumberFormatInfo.
                 * PercentGroupSize
                 * PercentDecimalDigits
                 * PercentGroupSeparator
                 * PerMilleSymbol
                 */

                // We directly use fields here since these data is coming from data table or Win32, so we
                // don't need to verify their values.

                this.percentDecimalDigits    = this.numberDecimalDigits = CultureTable.GetInt32Value(m_dataItem, CultureTable.IDIGITS, m_useUserOverride);
                this.numberNegativePattern   = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGNUMBER, m_useUserOverride);
                this.currencyDecimalDigits   = CultureTable.GetInt32Value(m_dataItem, CultureTable.ICURRDIGITS, m_useUserOverride);
                this.currencyPositivePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.ICURRENCY, m_useUserOverride);
                this.currencyNegativePattern = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGCURR, m_useUserOverride);
                this.percentNegativePattern  = CultureTable.GetInt32Value(m_dataItem, CultureTable.INEGATIVEPERCENT, m_useUserOverride);
                this.percentPositivePattern  = CultureTable.GetInt32Value(m_dataItem, CultureTable.IPOSITIVEPERCENT, m_useUserOverride);
                this.negativeSign            = CultureTable.GetStringValue(m_dataItem, CultureTable.SNEGATIVESIGN, m_useUserOverride);
                this.percentSymbol           = CultureTable.GetStringValue(m_dataItem, CultureTable.SPERCENT, m_useUserOverride);

                this.percentDecimalSeparator  = this.numberDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SDECIMAL, m_useUserOverride);
                this.percentGroupSizes        = this.numberGroupSizes = CultureInfo.ParseGroupString(CultureTable.GetStringValue(m_dataItem, CultureTable.SGROUPING, m_useUserOverride));
                this.percentGroupSeparator    = this.numberGroupSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.STHOUSAND, m_useUserOverride);
                this.positiveSign             = CultureTable.GetStringValue(m_dataItem, CultureTable.SPOSITIVESIGN, m_useUserOverride);
                this.currencyDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONDECIMALSEP, m_useUserOverride);

                //Special case for Italian.  The currency decimal separator in the control panel is the empty string. When the user
                //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the
                //decimal point doesn't show up.  We'll just hack this here because our default currency format will never use this.
                if (currencyDecimalSeparator.Length == 0)
                {
                    this.currencyDecimalSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONDECIMALSEP, false);
                }

                this.currencyGroupSizes     = CultureInfo.ParseGroupString(CultureTable.GetStringValue(m_dataItem, CultureTable.SMONGROUPING, m_useUserOverride));
                this.currencyGroupSeparator = CultureTable.GetStringValue(m_dataItem, CultureTable.SMONTHOUSANDSEP, m_useUserOverride);
                this.currencySymbol         = CultureTable.GetStringValue(m_dataItem, CultureTable.SCURRENCY, m_useUserOverride);
                this.ansiCurrencySymbol     = CultureTable.GetStringValue(m_dataItem, CultureTable.SANSICURRENCYSYMBOL, false);
                if (this.ansiCurrencySymbol.Length == 0)
                {
                    this.ansiCurrencySymbol = null;
                }
                this.negativeInfinitySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SNEGINFINITY, m_useUserOverride);
                this.positiveInfinitySymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SPOSINFINITY, m_useUserOverride);
                this.nanSymbol = CultureTable.GetStringValue(m_dataItem, CultureTable.SNAN, m_useUserOverride);
            }
        }
Exemple #2
0
 internal static bool IsValidSortID(int dataItem, int sortID)
 {
     BCLDebug.Assert(sortID >= 0 && sortID <= 0xffff, "sortID is invalid");    // SortID is 16-bit positive integer.
     return(
         sortID == 0 ||
         CultureTable.GetDefaultInt32Value(dataItem, CultureTable.IALTSORTID) == sortID
         );
 }
Exemple #3
0
        internal int culture;               // the culture ID used to create this instance.


        ////////////////////////////////////////////////////////////////////////
        //
        //  CompareInfo Constructor
        //
        //
        ////////////////////////////////////////////////////////////////////////


        // Constructs an instance that most closely corresponds to the NLS locale
        // identifier.
        internal unsafe CompareInfo(GlobalizationAssembly ga, int culture)
        {
            if (culture < 0)
            {
                throw new ArgumentOutOfRangeException("culture", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            }

            // NOTENOTE YSLin: In the future, move all the culture validation to the native code InitializeCompareInfo, since we make three
            // native calls below, which are expansive.

            //
            // Verify that this is a valid culture.
            //
            int dataItem = CultureTable.GetDataItemFromCultureID(CultureInfo.GetLangID(culture));

            if (dataItem == -1)
            {
                throw new ArgumentException(
                          String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture");
            }

            // We do the following because the native C++ SortingTable is based on the
            // WIN32 LCID.  It doesn't work for neutral cultures liek 0x0009.  So we convert culture
            // to a Win32 LCID here.

            // Note that we have to get Sort ID from culture.  This will affect the result of string comparison.
            this.win32LCID = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID);

            int sortID = CultureInfo.GetSortID(culture);

            if (sortID != 0)
            {
                // Need to verify if the Sort ID is valid.
                if (!CultureTable.IsValidSortID(dataItem, sortID))
                {
                    throw new ArgumentException(
                              String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture");
                }
                // This is an alterinative sort LCID.  Hey man, don't forget to take your SORTID with you.
                win32LCID |= sortID << 16;
            }

            // TODO: InitializeCompareInfo should use ga instead of getting the default instance.

            // Call to the native side to create/get the corresponding native C++ SortingTable for this culture.
            // The returned value is a 32-bit pointer to the native C++ SortingTable instance.
            // We cache this pointer so that we can call methods of the SortingTable directly.
            pSortingTable = InitializeCompareInfo(GlobalizationAssembly.m_defaultInstance.pNativeGlobalizationAssembly, win32LCID);
            // Since win32LCID can be different from the passed-in culture in the case of neutral cultures, store the culture ID in a different place.
            this.culture = culture;
        }
Exemple #4
0
        ////////////////////////////////////////////////////////////////////////
        //
        //  TextInfo Constructors
        //
        //  Implements CultureInfo.TextInfo.
        //
        ////////////////////////////////////////////////////////////////////////

        internal TextInfo(int cultureID, int nDataItem, bool useUserOverride)
        {
            m_nDataItem       = nDataItem;
            m_useUserOverride = useUserOverride;

            m_win32LangID = CultureTable.GetDefaultInt32Value(m_nDataItem, CultureTable.WIN32LANGID);

            BCLDebug.Assert(CultureInfo.GetSortID(m_win32LangID) == 0,
                            "CultureInfo.GetSortID(m_win32LangID) == 0");
            lock (typeof(TextInfo)) {
                // Calling this method need syncronization since shared
                // data is used in the native side.
                m_pNativeTextInfo = InternalAllocateCasingTable(m_win32LangID);
            }
        }
        /// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.CultureInfo3"]/*' />
        public CultureInfo(int culture, bool useUserOverride)
        {
            if (culture < 0)
            {
                throw new ArgumentOutOfRangeException("culture",
                                                      Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
            }

            if (culture == SPANISH_TRADITIONAL_SORT)
            {
                // HACKHACK
                // We are nuking 0x040a (Spanish Traditional sort) in NLS+.
                // So if you create 0x040a, it's just like 0x0c0a (Spanish International sort).
                // For a table setup reason, we can not really remove the data item for 0x040a in culture.nlp.
                // As a workaround, what we do is to make the data for 0x040a to be exactly the same as 0x0c0a.
                // Unfortunately, the culture name is the only exception.
                // So in the table, we still have "es-ES-Ts" in there which we can not make it "es-ES".
                // Again, this is for table setup reason.  So if we are creating
                // CultureInfo using 0x040a, hardcode culture name to be "es-ES" here so that we won't
                // get "es-ES-Ts" in the table.
                m_name = "es-ES";
            }
            m_dataItem = CultureTable.GetDataItemFromCultureID(GetLangID(culture));

            if (m_dataItem < 0)
            {
                throw new ArgumentException(
                          String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture");
            }
            this.m_useUserOverride = useUserOverride;

            int sortID;

            if ((sortID = GetSortID(culture)) != 0)
            {
                //
                // Check if the sort ID is valid.
                //
                if (!CultureTable.IsValidSortID(m_dataItem, sortID))
                {
                    throw new ArgumentException(
                              String.Format(Environment.GetResourceString("Argument_CultureNotSupported"), culture), "culture");
                }
            }
            this.cultureID = culture;
        }
        /// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.CultureInfo1"]/*' />
        public CultureInfo(String name, bool useUserOverride)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name",
                                                Environment.GetResourceString("ArgumentNull_String"));
            }

            this.m_dataItem = CultureTable.GetDataItemFromName(name);
            if (m_dataItem < 0)
            {
                throw new ArgumentException(
                          String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name");
            }
            this.m_useUserOverride = useUserOverride;

            this.cultureID = CultureTable.GetDefaultInt32Value(m_dataItem, CultureTable.ILANGUAGE);
        }
Exemple #7
0
        /*=================================GetCompareInfo==========================
         **Action: Get the CompareInfo for the specified culture.
         **Returns: The CompareInfo for the specified culture.
         **Arguments:
         **   name    the name of the culture.
         **Exceptions:
         **  ArgumentException if name is invalid.
         **============================================================================*/
        /// <include file='doc\CompareInfo.uex' path='docs/doc[@for="CompareInfo.GetCompareInfo3"]/*' />
        public static CompareInfo GetCompareInfo(String name)
        {
            if (name == null)
            {
                throw new ArgumentNullException("name");
            }

            int dataItem = CultureTable.GetDataItemFromName(name);

            if (dataItem == -1)
            {
                throw new ArgumentException(
                          String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name");
            }

            int culture = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID);

            return(GetCompareInfo(culture));
        }
Exemple #8
0
        /*=================================GetCompareInfo==========================
         **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture.
         **       The purpose of this method is to provide version for CompareInfo tables.
         **Returns: The CompareInfo for the specified culture.
         **Arguments:
         **   name    the name of the culture
         **   assembly   the assembly which contains the sorting table.
         **Exceptions:
         **  ArugmentNullException when the assembly is null
         **  ArgumentException if name is invalid.
         **============================================================================*/
        /// <include file='doc\CompareInfo.uex' path='docs/doc[@for="CompareInfo.GetCompareInfo1"]/*' />
        public static CompareInfo GetCompareInfo(String name, Assembly assembly)
        {
            if (name == null || assembly == null)
            {
                throw new ArgumentNullException(name == null ? "name" : "assembly");
            }

            if (assembly != typeof(Object).Module.Assembly)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib"));
            }

            int dataItem = CultureTable.GetDataItemFromName(name);

            if (dataItem == -1)
            {
                throw new ArgumentException(
                          String.Format(Environment.GetResourceString("Argument_InvalidCultureName"), name), "name");
            }

            int culture = CultureTable.GetDefaultInt32Value(dataItem, CultureTable.WIN32LANGID);

            return(GetCompareInfo(culture, assembly));
        }
 /// <include file='doc\CultureInfo.uex' path='docs/doc[@for="CultureInfo.GetCultures"]/*' />
 public static CultureInfo[] GetCultures(CultureTypes types)
 {
     return(CultureTable.GetCultures(types));
 }
Exemple #10
0
 static CultureTable()
 {
     m_defaultInstance = new CultureTable("culture.nlp", true);
 }
Exemple #11
0
        internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName)
        {
            CultureInfo info;
            Hashtable   nameCachedCultures = m_NameCachedCultures;

            if (name != null)
            {
                name = CultureTableRecord.AnsiToLower(name);
            }
            if (altName != null)
            {
                altName = CultureTableRecord.AnsiToLower(altName);
            }
            if (nameCachedCultures == null)
            {
                nameCachedCultures = Hashtable.Synchronized(new Hashtable());
            }
            else if (lcid == -1)
            {
                info = (CultureInfo)nameCachedCultures[name + ((char)0xfffd) + altName];
                if (info != null)
                {
                    return(info);
                }
            }
            else if (lcid == 0)
            {
                info = (CultureInfo)nameCachedCultures[name];
                if (info != null)
                {
                    return(info);
                }
            }
            Hashtable lcidCachedCultures = m_LcidCachedCultures;

            if (lcidCachedCultures == null)
            {
                lcidCachedCultures = Hashtable.Synchronized(new Hashtable());
            }
            else if (lcid > 0)
            {
                info = (CultureInfo)lcidCachedCultures[lcid];
                if (info != null)
                {
                    return(info);
                }
            }
            try
            {
                switch (lcid)
                {
                case -1:
                    info = new CultureInfo(name, altName);
                    goto Label_010A;

                case 0:
                    info = new CultureInfo(name, false);
                    goto Label_010A;
                }
                if ((m_userDefaultCulture != null) && (m_userDefaultCulture.LCID == lcid))
                {
                    info = (CultureInfo)m_userDefaultCulture.Clone();
                    info.m_cultureTableRecord = info.m_cultureTableRecord.CloneWithUserOverride(false);
                }
                else
                {
                    info = new CultureInfo(lcid, false);
                }
            }
            catch (ArgumentException)
            {
                return(null);
            }
Label_010A:
            info.m_isReadOnly = true;
            if (lcid == -1)
            {
                nameCachedCultures[name + ((char)0xfffd) + altName] = info;
                info.TextInfo.SetReadOnlyState(true);
            }
            else
            {
                if (!CultureTable.IsNewNeutralChineseCulture(info))
                {
                    lcidCachedCultures[info.LCID] = info;
                }
                string str = CultureTableRecord.AnsiToLower(info.m_name);
                nameCachedCultures[str] = info;
            }
            if (-1 != lcid)
            {
                m_LcidCachedCultures = lcidCachedCultures;
            }
            m_NameCachedCultures = nameCachedCultures;
            return(info);
        }
 static CultureTable()
 {
     m_defaultInstance = new CultureTable("culture.nlp", true);
 }
        //
        // this constructor will create the CultureTableRecord object and point to the 
        // culture table at the slot dataItem.
        //

        private unsafe CultureTableRecord(string regionName, int dataItem, bool useUserOverride)
        {
            BCLDebug.Assert(regionName != null && regionName.Length > 0,
                "[CultureTableRecord.CultureTableRecord(regionName,bool)]Expected non-null/empty name");

            BCLDebug.Assert(dataItem > 0, "[CultureTableRecord.CultureTableRecord(regionName, dataItem, bool)] dataItem > 0 should be true.");

            // Assuming it works we'll want these
            this.m_bUseUserOverride = useUserOverride;
            this.m_CultureName = regionName;
            this.m_CultureTable = CultureTable.Default;

            // Found it, use it
            this.m_pData = (CultureTableData*)(this.m_CultureTable.m_pItemData +
                this.m_CultureTable.m_itemSize * dataItem);
            this.m_pPool = this.m_CultureTable.m_pDataPool;

            // Use ID from the file
            this.m_CultureID = this.ILANGUAGE;
        }
        //
        // m_bUseUserOverride indicates that if we need to check for user-override values for this CultureInfo instance.
        // For the user default culture of the system, user can choose to override some of the values
        // associated with that culture.  For example, the default short-date format for en-US is
        // "M/d/yyyy", however, one may change it to "dd/MM/yyyy" from the Regional Option in
        // the control panel.
        // So when a CultureInfo is created, one can specify if the create CultureInfo should check
        // for user-override values, or should always get the default values.
        //
        //
        // AVOID USING P/INVOKE IN THIS CODEPATH.
        // AVOID USING P/INVOKE IN THIS CODEPATH.
        // AVOID USING P/INVOKE IN THIS CODEPATH.
        //
        // P/Invoke will cause COM to be initialized and sets the thread apartment model. Since CultureInfo is used early in the CLR process,
        // this will prevent Loader from having a chance to look at the executable and setting the apartment model to the one the application wants.



        //
        // Search order for creating a culture.
        //

        /*
           First, search by name
                if this is a known culture name from culture.nlp, and it is an alternative sort name (such as de-DE_phoneb)
                {
                    Get the name from the LANGID by removing the sort ID (so the name becomes de-DE). 
                    This is the name used for search replacment culture.
                }
                
                Check if this specified name has a custom/replacement culture file.
                if there is a custom/replacement culture file
                {
                    // This is a custom culture, or a replacement culture.
                    return; [CUSTOM/REPLACEMENT CULTURE (.NET CULTURE/SYNTHETIC CULTURE) FOUND BY NAME]
                }
                From culture.nlp, check if tihs is a vlid culture name
                if this is a valid culture name
                {
                    // This is a .NET culture.
                    return; [NON-REPLACEMENT .NET CULTURE FOUND BY NAME]
                }
                Check if this is a valid name from synthetic culture
                if this is a valid synthetic culture name
                {
                    // This is a synthetic culture. Set the cultureID, so we will
                    // create it when we search by LCID later.
                    // [SYNTHETIC CULTURE FOUND BY NAME]
                } else
                {
                    throw exception;    [INVALID NAME]
                }
           Then Search by LCID
                we'll come here only if the lcid is filled with synthetic culture Id.
                    // This is synthetic culture.
                    Get the name for this LANGID of this synthetic LCID.
                    if there is a replacement culture for this LCID by checking name.
                    {
                        Use it and return the replacement culture for synthetic culture.
                        return;  [REPLACEMENT SYNTHETIC CULTURE]
                    }
                    Init and return the synthetic culture.  
                    return;  [NON-REPLACEMENT SYNTHETIC CULTURE]
                    
                }
                otherwise throw exception
                
        */
        //
        // * IMPORTANT * cultureName should be in lower case.
        //
        private unsafe CultureTableRecord(String cultureName, bool useUserOverride)
        {
            BCLDebug.Assert(cultureName != null, "[CultureTableRecord::ctor] cultureName should be valid.");
            
            int cultureID = 0;
        
            // Special case for invariant name
            if (cultureName.Length == 0)
            {
                useUserOverride = false;
                cultureID = CultureInfo.LOCALE_INVARIANT;
            }

            this.m_bUseUserOverride = useUserOverride;

            // We prefer to look up by name (if available)
            int iDataItem = -1;
            if (cultureName.Length > 0)
            {
                // Check if this is an alternative sort name.
                String defaultTableActualName;
                int defaultTableCultureID;
                string name = cultureName;
                int defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureName(name, out defaultTableCultureID, out defaultTableActualName);
                if (defaultTableDataItem >= 0 && 
                    (CultureInfo.GetSortID(defaultTableCultureID) > 0 || defaultTableCultureID == SPANISH_TRADITIONAL_SORT))
                {
                    String replacmentCultureName;

                    int nonSortId;
                    if (defaultTableCultureID == SPANISH_TRADITIONAL_SORT)
                        nonSortId = SPANISH_INTERNATIONAL_SORT;
                    else
                        nonSortId = CultureInfo.GetLangID(defaultTableCultureID);
                        
                    // This is an alternative sort culture.
                    if (CultureTable.Default.GetDataItemFromCultureID(nonSortId, out replacmentCultureName) >= 0)
                    {                                                                                
                        // This is the replacement culture name for an alternative sort.
                        name = ValidateCulturePieceToLower(replacmentCultureName, "cultureName", MAXSIZE_FULLTAGNAME);
                    }                        
                }

                // If the compatibility flag is defined and culture is replacemet culture then we don't 
                // open the custom culture file. instead we'll try to get framework/OS culture.
                if (!Environment.GetCompatibilityFlag(CompatibilityFlag.DisableReplacementCustomCulture) ||
                    IsCustomCultureId(defaultTableCultureID))
                {

                    // we always try the replacement custom cultures first.
                    //  Before call this function, call ValidateCulturePieceToLower() to verify
                    //  that the name does not contain illegal characters (such as "." or backslash.
                    m_CultureTable = GetCustomCultureTable(name);
                }
                
                if (m_CultureTable != null)
                {
                    //
                    // [CUSTOM/REPLACEMENT CULTURE (.NET CULTURE/SYNTHETIC CULTURE) FOUND BY NAME]
                    //
                    iDataItem = this.m_CultureTable.GetDataItemFromCultureName(name, out this.m_ActualCultureID, out this.m_ActualName);
                    if (defaultTableDataItem >= 0)
                    {
                        // This is a replacment culture (since defaultTableDataItem >= 0), use the default ID/Name from the table.
                        // For de-DE_phoneb, this will set the the actualCultureID to be 0x10407, instead of the LCID for replacment cutlure 0x0407.
                        this.m_ActualCultureID = defaultTableCultureID;
                        this.m_ActualName = defaultTableActualName;
                    }                    
                }

                if (iDataItem < 0 && defaultTableDataItem >= 0)
                {
                    //
                    // [NON-REPLACEMENT .NET CULTURE FOUND BY NAME] 
                    //
                    this.m_CultureTable = CultureTable.Default;
                    this.m_ActualCultureID = defaultTableCultureID;
                    this.m_ActualName = defaultTableActualName;
                    iDataItem = defaultTableDataItem;
                }

            }

            // If we couldn't get it by name, try culture ID.
            if (iDataItem < 0 && cultureID > 0)
            {
                if (cultureID == CultureInfo.LOCALE_INVARIANT)
                {
                    // Special case for the Invariant culture.
                    iDataItem = CultureTable.Default.GetDataItemFromCultureID(cultureID, out this.m_ActualName);
                    if (iDataItem > 0) 
                    {
                        m_ActualCultureID   = cultureID;
                        m_CultureTable      = CultureTable.Default;
                    }
                }
            }

            // If we found one, use it and return
            if (iDataItem >= 0)
            {
                // Found it, use it
                this.m_pData = (CultureTableData*)(this.m_CultureTable.m_pItemData +
                    this.m_CultureTable.m_itemSize * iDataItem);
                this.m_pPool = this.m_CultureTable.m_pDataPool;
                // Use name & ID from the file ('cept spanish traditional, which has to stay the same)
                this.m_CultureName = this.SNAME;
                this.m_CultureID = (m_ActualCultureID == SPANISH_TRADITIONAL_SORT) ? m_ActualCultureID : this.ILANGUAGE;

                        
                return;
            }

            // Error, if we have a name throw that name
            if (cultureName != null)
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Environment.GetResourceString("Argument_InvalidCultureName"), cultureName), "name");

            // No name, throw the LCID
            throw new ArgumentException(
                String.Format(
                    CultureInfo.CurrentCulture,
                    Environment.GetResourceString("Argument_CultureNotSupported"), cultureID), "culture");
        }
        //
        // This constructor used only to create a Framework culture. it doesn't create custom 
        // culture nor synthetic culture.
        // This is used when requesting the native calendar name for a custom culture with 
        // empty string native calendar name.
        //
        internal unsafe CultureTableRecord(int cultureId, bool useUserOverride)
        {
            this.m_bUseUserOverride = useUserOverride;
            
            int defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureID(cultureId, out m_ActualName);
            if (defaultTableDataItem < 0)
            {
                throw new ArgumentException(
                    String.Format(
                        CultureInfo.CurrentCulture,
                        Environment.GetResourceString("Argument_CultureNotSupported"), cultureId), "culture");
            }
            
            m_ActualCultureID   = cultureId;
            m_CultureTable      = CultureTable.Default;
            
            m_pData = (CultureTableData*)(m_CultureTable.m_pItemData + m_CultureTable.m_itemSize * defaultTableDataItem);
            m_pPool = m_CultureTable.m_pDataPool;
            
            m_CultureName = SNAME;
            m_CultureID = (cultureId == SPANISH_TRADITIONAL_SORT) ? cultureId : ILANGUAGE;

            BCLDebug.Assert(!IsCustomCulture , "[CultureTableRecord::ctor] we shouldn't have custom culture.");
            BCLDebug.Assert(!IsSynthetic, "[CultureTableRecord::ctor] we shouldn't have synthetic culture.");
        }
        private unsafe CultureTable GetCustomCultureTable(string name)
        {
            CultureTable cultureTable = null;
            
            string customCultureFile = GetCustomCultureFile(name);
            if (customCultureFile == null)
            {
                return null;
            }

            try 
            {
                cultureTable = new CultureTable(customCultureFile, false);
                if (!cultureTable.IsValid)
                {
                    // If we have invalid culture table then we have custom culture. in that case we'll try 
                    // to see if the culture name is one of the framework or synthetic cultures and then 
                    // try to create it otherwise we'll throw.
                    
                    String  defaultTableActualName;
                    int     defaultTableCultureID;
                    int     defaultTableDataItem = CultureTable.Default.GetDataItemFromCultureName(
                                                    name, out defaultTableCultureID, out defaultTableActualName);

                    if (defaultTableDataItem < 0)       // not built in framework culture
                    {
                        
                    }

                    return null;  // returning null means fallback to framework or synthetic culture.
                }
            } 
            catch (FileNotFoundException)
            {
                //
                // getting here means custom culture file get unregistered/renamed from different AppDomain/Process.
                // just update the cache to point to the empty string as subsequent calls will not bother trying again.
                //
                cultureTable = null;
            }

            return cultureTable;
        }