Example #1
0
        internal unsafe bool Validate()
        {
            if (memoryMapFile == null)  // we only validate custom cultures.
            {
                return(true);
            }

            long fileSize = memoryMapFile.FileSize;

            if (sizeof(EndianessHeader) + sizeof(CultureTableHeader) + sizeof(CultureTableData) + 2 * sizeof(int) > fileSize)
            {
                return(false);
            }

            // EndianessHeader
            EndianessHeader *pEndianHeader = (EndianessHeader *)m_pDataFileStart;

#if BIGENDIAN
            if (pEndianHeader->beOffset > fileSize)
            {
                return(false);
            }
#else
            if (pEndianHeader->leOffset > fileSize)
            {
                return(false);
            }
#endif // BIGENDIAN

            // CultureTableHeader
            if (m_pCultureHeader->offsetToCultureItemData + m_pCultureHeader->sizeCultureItem > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->cultureIDTableOffset > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->cultureNameTableOffset + sizeofNameOffsetItem > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->regionNameTableOffset > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->offsetToCalendarItemData + m_pCultureHeader->sizeCalendarItem > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->ietfNameTableOffset > fileSize)
            {
                return(false);
            }
            if (m_pCultureHeader->offsetToDataPool > fileSize)
            {
                return(false);
            }

            ushort *pDataPool = (ushort *)(m_pDataFileStart + m_pCultureHeader->offsetToDataPool);

            int poolSizeInChar = (int)(fileSize - ((long)pDataPool - (long)m_pDataFileStart)) / 2;    // number of characters in the pool

            if (poolSizeInChar <= 0)
            {
                return(false);
            }

            // SNAME
            uint sNameOffset = (uint)((char *)(m_pDataFileStart + m_pCultureHeader->cultureNameTableOffset))[0];

            // CultureTableData
            CultureTableData *cultureData = (CultureTableData *)(m_pDataFileStart + m_pCultureHeader->offsetToCultureItemData);

            if (cultureData->iLanguage == 0x7F || !IsValidLcid(cultureData->iLanguage, true))
            {
                return(false);
            }

            string cultureName = CheckAndGetTheString(pDataPool, cultureData->sName, poolSizeInChar);
            if (String.IsNullOrEmpty(cultureName))
            {
                return(false);
            }

            if (sNameOffset != cultureData->sName)
            {
                if (!cultureName.Equals(CheckAndGetTheString(pDataPool, sNameOffset, poolSizeInChar)))
                {
                    return(false);
                }
            }

            string parentName = CheckAndGetTheString(pDataPool, cultureData->sParent, poolSizeInChar);
            if (parentName == null || parentName.Equals(cultureName, StringComparison.OrdinalIgnoreCase))
            {
                return(false);
            }

            if (!IsValidLcid((int)cultureData->iTextInfo, false) || !IsValidLcid((int)cultureData->iCompareInfo, false))
            {
                return(false);
            }

            // We could use the reflection instead of checking each field manually but this was hurting
            // the performance (almost 35% from the creation time)

            if (!ValidateString(pDataPool, cultureData->waGrouping, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->waMonetaryGrouping, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sListSeparator, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sDecimalSeparator, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sThousandSeparator, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sCurrency, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sMonetaryDecimal, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sMonetaryThousand, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sPositiveSign, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNegativeSign, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sAM1159, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sPM2359, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saNativeDigits, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saTimeFormat, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saShortDate, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saLongDate, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saYearMonth, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saDuration, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->waCalendars, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sAbbrevLang, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sISO639Language, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sEnglishLanguage, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNativeLanguage, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sEnglishCountry, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNativeCountry, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sAbbrevCountry, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sISO3166CountryName, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sIntlMonetarySymbol, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sEnglishCurrency, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNativeCurrency, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->waFontSignature, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sISO639Language2, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sISO3166CountryName2, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saDayNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saAbbrevDayNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saMonthNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saAbbrevMonthNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saMonthGenitiveNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saAbbrevMonthGenitiveNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saNativeCalendarNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saAltSortID, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sEnglishDisplayName, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNativeDisplayName, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sPercent, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNaN, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sPositiveInfinity, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sNegativeInfinity, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sMonthDay, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sAdEra, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sAbbrevAdEra, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sRegionName, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sConsoleFallbackName, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saShortTime, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saSuperShortDayNames, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateStringArray(pDataPool, cultureData->saDateWords, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sSpecificCulture, poolSizeInChar))
            {
                return(false);
            }
            if (!ValidateString(pDataPool, cultureData->sIetfLanguage, poolSizeInChar))
            {
                return(false);
            }

/*
 *          Object cultureTableData = (object) *cultureData;
 *          Type type = cultureTableData.GetType();
 *          FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
 *
 *          for (int i=0; i<fields.Length; i++)
 *          {
 *              BCLDebug.Assert(
 *                      fields[i].Name[0] == 'i' ||
 *                      fields[i].Name[0] == 's' ||
 *                      fields[i].Name[0] == 'w' , "Invalid structure field name.");
 *
 *              if (fields[i].Name.Length<2 || (fields[i].Name[0] != 's' && fields[i].Name[0] != 'w'))
 *                  continue;
 *
 *              Object objectValue = type.InvokeMember(
 *                                          fields[i].Name,
 *                                          BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField,
 *                                          null,
 *                                          cultureTableData,
 *                                          null,
 *                                          CultureInfo.InvariantCulture);
 *              int value;
 *
 *              if (fields[i].FieldType == typeof(System.UInt16))
 *                  value = (int) (ushort) objectValue;
 *              else if (fields[i].FieldType == typeof(System.UInt32))
 *                  value = (int) (uint) objectValue;
 *              else
 *                  return false;
 *
 *              bool result = false;
 *              if (fields[i].Name[0] == 's')
 *              {
 *                  if (fields[i].Name[1] == 'a')
 *                      result = ValidateStringArray(value, poolSizeInChar);
 *                  else
 *                      result = ValidateString(value, poolSizeInChar);
 *              }
 *              else
 *              {
 *                  BCLDebug.Assert(fields[i].Name[1] == 'a', "Expected field starts with wa.");
 *                  result = ValidateString(value, poolSizeInChar);
 *              }
 *
 *              if (!result)
 *                  return false;
 *          }
 */
            return(true);
        }
        //
        // 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 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;
        }
        //
        // 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.");
        }