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."); }