Code:
/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Globalization / CultureTable.cs / 3 / CultureTable.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== namespace System.Globalization { using System.Runtime.Remoting; using System; using System.Text; using System.Threading; using System.Collections; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.IO; using Microsoft.Win32; using System.Runtime.Versioning; /*============================================================================== * * Data table for CultureInfo classes. Used by System.Globalization.CultureInfo. * ==============================================================================*/ // Only statics, does not need to be marked with the serializable attribute internal class CultureTable : BaseInfoTable { // WARNING! // // This value must be the kept in sync with the field order in the file or everything'll die // This is currently copied from culture.h which is generated by nlpgen.pl // Currently ILANGUAGE is the first field in the record internal const int ILANGUAGE = 0; // Currently we need to know offset into record (in words) of ILANGUAGE to look up records by LCID internal const string TraditionalChineseCultureName = "zh-CHT"; internal const string SimplifiedChineseCultureName = "zh-CHS"; internal const string NewTraditionalChineseCultureName = "zh-Hant"; internal const string NewSimplifiedChineseCultureName = "zh-Hans"; // // This is the mask used to check if the flags for GetCultures() is valid. // private const CultureTypes CultureTypesMask = ~( CultureTypes.NeutralCultures | CultureTypes.SpecificCultures | CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture| CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures | CultureTypes.FrameworkCultures); // Hashtable for indexing name to get nDataItem. private Hashtable hashByName; private Hashtable hashByRegionName; private Hashtable hashByLcid; unsafe private CultureNameOffsetItem* m_pCultureNameIndex; unsafe private RegionNameOffsetItem* m_pRegionNameIndex; unsafe private IDOffsetItem* m_pCultureIDIndex; private static CultureTable m_defaultInstance; [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] static CultureTable() { m_defaultInstance = new CultureTable("culture.nlp", true); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] unsafe internal CultureTable(String fileName, bool fromAssembly) : base(fileName, fromAssembly) { if (!IsValid) // intialized in SetDataItemPointers return; hashByName = new Hashtable(); hashByLcid = new Hashtable(); hashByRegionName = new Hashtable(); // Set up index table for finding data item from culture or region name. m_pCultureNameIndex = (CultureNameOffsetItem*)(m_pDataFileStart + m_pCultureHeader->cultureNameTableOffset); m_pRegionNameIndex = (RegionNameOffsetItem*)(m_pDataFileStart + m_pCultureHeader->regionNameTableOffset); // Set up index table for finding data item from LCID. m_pCultureIDIndex = (IDOffsetItem*)(m_pDataFileStart + m_pCultureHeader->cultureIDTableOffset); } // TypeLoadExceptionMessage is going to be used at the time of failing to load CultureTable type and // then m_defaultInstance will be null and we cannot call any NLS+ code. so we cannot call the resource // manager to get any string because resource manager will call culture info code again. So we had to // use non resource string for throwing this exception. // Note, failing to load CUltureTable is rare to happen and we just got it when injecting OOM fault // to the CLR while trying loading some types. internal const string TypeLoadExceptionMessage = "Failure has occurred while loading a type."; internal static CultureTable Default { get { // // In case the CultureTable class failed during the type initilaization then we'll have m_defaultInstance = null. // to be reliable we throw exception instead of getting access violation. // if (m_defaultInstance == null) throw new TypeLoadException(TypeLoadExceptionMessage); return (m_defaultInstance); } } //////////////////////////////////////////////////////////////////////// // // Set Data Item Pointers that are unique to culture table // //////////////////////////////////////////////////////////////////////// internal override unsafe void SetDataItemPointers() { if (Validate()) { m_itemSize = m_pCultureHeader->sizeCultureItem; m_numItem = m_pCultureHeader->numCultureItems; m_pDataPool = (ushort*)(m_pDataFileStart + m_pCultureHeader->offsetToDataPool); m_pItemData = m_pDataFileStart + m_pCultureHeader->offsetToCultureItemData; } else { m_valid = false; } } #region CustomCultureValidation // // ValidateString catch the buffer overrun. // Note, offsets and sizes here are in characters not in bytes. // private unsafe static String CheckAndGetTheString(ushort *pDataPool, uint offsetInPool, int poolSize) { if (offsetInPool + 2 > poolSize) // string offset + string length + null termination. return null; char* pCharValues = unchecked((char*)(pDataPool + offsetInPool)); int stringLength = (int) pCharValues[0]; if (offsetInPool + stringLength + 2 > poolSize) // string length + string + null termination return null; return new String(pCharValues + 1, 0, stringLength); } // // ValidateString catch the buffer overrun. // Note, offsets and sizes here are in characters not in bytes. // private unsafe static bool ValidateString(ushort *pDataPool, uint offsetInPool, int poolSize) { if (offsetInPool + 2 > poolSize) // string offset + string length + null termination. return false; char* pCharValues = unchecked((char*)(pDataPool + offsetInPool)); int stringLength = (int) pCharValues[0]; if (offsetInPool + stringLength + 2 > poolSize) // string length + string + null termination return false; return true; } // // ValidateString catch the buffer overrun. // Note, offsets and sizes here are in characters not in bytes. // private unsafe static bool ValidateUintArray(ushort *pDataPool, uint offsetInPool, int poolSize) { if (offsetInPool == 0) return true; if (offsetInPool + 2 > poolSize) // string offset + string length + null termination. return false; // Get location of count and make sure its on an odd word // (odd words would end in 2 as pointers, we want pCount%4 to be 2 so that // when we get past the count our uints are uint aligned) ushort* pCount = pDataPool + offsetInPool; if (((int)(pCount) & 2) != 2) return false; int arrayLength = pCount[0]; if (offsetInPool + (arrayLength * 2) + 2 > poolSize) // array length * 2 (words/dword) + string + null termination return false; return true; } // // ValidateStringArray catch the buffer overrun. // Note, offsets and sizes here are in characters not in bytes. // private unsafe static bool ValidateStringArray(ushort *pDataPool, uint offsetInPool, int poolSize) { if (!ValidateUintArray(pDataPool, offsetInPool, poolSize)) return false; // Get our count ushort* pCount = pDataPool + offsetInPool; int arrayLength = pCount[0]; if (arrayLength == 0) return true; // Get our dword * uint* uints = (uint*)(pCount + 1); for (int i=0; ifileSize) 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->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; } /* SSS_WARNINGS_OFF */ if (!ValidateString(pDataPool, cultureData->sEnglishCountry, poolSizeInChar)) { return false; } /* SSS_WARNINGS_ON */ /* SSS_WARNINGS_OFF */ if (!ValidateString(pDataPool, cultureData->sNativeCountry, poolSizeInChar)) { return false; } /* SSS_WARNINGS_ON */ /* SSS_WARNINGS_OFF */ if (!ValidateString(pDataPool, cultureData->sAbbrevCountry, poolSizeInChar)) { return false; } /* SSS_WARNINGS_ON */ /* SSS_WARNINGS_OFF */ if (!ValidateString(pDataPool, cultureData->sISO3166CountryName, poolSizeInChar)) { return false; } /* SSS_WARNINGS_ON */ 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; } /* SSS_WARNINGS_OFF */ if (!ValidateString(pDataPool, cultureData->sISO3166CountryName2, poolSizeInChar)) { return false; } /* SSS_WARNINGS_ON */ 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; } /* Object cultureTableData = (object) *cultureData; Type type = cultureTableData.GetType(); FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); for (int i=0; i numCultureNames - 1; while (left <= right) { int mid = (left+right)/2; int result = CompareStringToStringPoolStringBinary(name, m_pCultureNameIndex[mid].strOffset); if (result == 0) { cti = new CultureTableItem(); int index = cti.dataItem = m_pCultureNameIndex[mid].dataItemIndex; culture = cti.culture = m_pCultureNameIndex[mid].actualCultureID; actualName = cti.name = GetStringPoolString(m_pCultureNameIndex[mid].strOffset); // m_pCultureNameIndex[i].dateItemIndex is the record number for // the information of a culture. // The trick that we play to remove es-ES-Ts is to put a duplicate entry // in the name offset table for es-ES, so that es-ES-Ts is not in the name offset table // Therefore, es-ES-Ts becomes an invalid name. // However, the data item for es-ES-Ts is still there. It is just that // you can not find it by calling GetDataItemFromName. hashByName[name] = cti; return (index); } if (result < 0) { right = mid - 1; } else { left = mid + 1; } } culture = -1; return (-1); } //=================================GetDataItemFromRegionName============================ // Action: Given a region name, return a index which points to a data item in // the Culture Data Table // Returns: the data item index. Or -1 if the region name is invalid. // Arguments: // name region name // // Note: The input region name is expected to be lower case, however // the names in the table may be mixed case. (So its case insensitive // for the table names, but not for the input name which must be lower case) // ============================================================================= unsafe internal int GetDataItemFromRegionName(String name) { BCLDebug.Assert(name!=null,"CultureTable.GetDataItemFromRegionName(): name!=null"); Object dataItem; if ((dataItem = hashByRegionName[name]) != null) { return (Int32)dataItem; } int left = 0; int right = m_pCultureHeader->numRegionNames - 1; while (left <= right) { int mid = (left+right)/2; int result = CompareStringToStringPoolStringBinary(name, m_pRegionNameIndex[mid].strOffset); if (result == 0) { int index = m_pRegionNameIndex[mid].dataItemIndex; hashByRegionName[name] = index; // m_pRegionNameIndex[i].dateItemIndex is the record number for // the information of a culture. return (index); } if (result < 0) { right = mid - 1; } else { left = mid + 1; } } return (-1); } /*=================================GetDataItemFromCultureID============================ **Action: Given a culture ID, return a index which points to a data item in ** the Culture Data Table **Returns: the data item index. Or -1 if the culture ID is invalid. **Arguments: ** cultureID **Exceptions: None. ==============================================================================*/ // WARNING: This doesn't have checks for es-es-TR hack, so you have to watch out if // you're using a traditional spanish LCID. To be careful, don't call this, but // make a new culture and ask it for the m_dataItem instead. unsafe internal int GetDataItemFromCultureID(int cultureID, out String actualName) { BCLDebug.Assert(cultureID!=0,"CultureTable.GetDataItemFromCultureID(): cultureID!=0"); CultureTableItem cti = (CultureTableItem)hashByLcid[cultureID]; if(null != cti && 0 != cti.culture) { actualName = cti.name; return (cti.dataItem); } int left = 0; int right = m_pCultureHeader->numCultureNames - 1; while (left <= right) { int mid = (left+right)/2; int result = cultureID - this.m_pCultureIDIndex[mid].actualCultureID; if (result == 0) { cti = new CultureTableItem(); int index = cti.dataItem = m_pCultureIDIndex[mid].dataItemIndex; int culture = cti.culture = cultureID; actualName = cti.name = GetStringPoolString(m_pCultureIDIndex[mid].strOffset); hashByLcid[cultureID] = cti; return (index); } if (result < 0) { right = mid - 1; } else { left = mid + 1; } } actualName = ""; return (-1); } /* internal static bool IsNeutralCulture(int cultureID) { //BCLDebug.Assert(cultureID != -1, "-1 cultureID value passed to IsNeutralCulture."); if (CultureInfo.GetSubLangID(cultureID) == 0) { return (true); } switch (cultureID) { case CultureInfo.zh_CHT_CultureID: case CultureInfo.sr_CultureID: return (true); } return (false); } */ internal static bool IsInstalledLCID(int cultureID) { #if !FEATURE_PAL if ((Environment.OSInfo & Environment.OSName.Win9x) != 0) { return CultureInfo.IsWin9xInstalledCulture( String.Format(CultureInfo.InvariantCulture, "{0,8:X08}", cultureID), cultureID); } else #endif { return CultureInfo.IsValidLCID(cultureID, CultureInfo.LCID_INSTALLED); } } // // IsExistingCulture is used when caching the name and lcid mapping to detect if it is // a framework culture or synthetic cultures. internal unsafe bool IsExistingCulture(int lcid) { if (lcid == 0) return false; string notUsed; return (GetDataItemFromCultureID(lcid, out notUsed) >= 0); } internal static bool IsOldNeutralChineseCulture(CultureInfo ci) { if ((ci.LCID == 0x7c04 && ci.Name.Equals(TraditionalChineseCultureName)) || (ci.LCID == 0x0004 && ci.Name.Equals(SimplifiedChineseCultureName))) { return true; } return false; } internal static bool IsNewNeutralChineseCulture(CultureInfo ci) { if ((ci.LCID == 0x7c04 && ci.Name.Equals(NewTraditionalChineseCultureName)) || (ci.LCID == 0x0004 && ci.Name.Equals(NewSimplifiedChineseCultureName))) { return true; } return false; } // // Enumerate the cultures according the CultureTypes flags: // // o NeutralCultures // Enumerate neutral custom and framework cultures. // // o SpecificCultures // Enumerate specific custom and framework cultures. Also it includes the synthetic cultures. // // o InstalledWin32Cultures // It enumerates the replacement cultures, framework culture, and synthetic cultures that are installed in the OS too. // // o UserCustomCulture // It enumerates all custom cultures. // // o ReplacementCultures // It enumerates all replacement custom cultures. // // o WindowsOnlyCultures // It enumerates all synthetic and replacement synthetic cultures. // // o FrameworkCultures // It enumerates all framework and replacement framework cultures. // // o AllCultures // It enumerates all cultures. // [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] unsafe internal CultureInfo [] GetCultures(CultureTypes types) { if ((int)types <= 0 || ((int) types & (int)CultureTypesMask) != 0) { throw new ArgumentOutOfRangeException( "types", String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures)); } ArrayList cultures = new ArrayList(); bool isAddSpecific = ((types & CultureTypes.SpecificCultures) != 0); bool isAddNeutral = ((types & CultureTypes.NeutralCultures) != 0); bool isAddInstalled = ((types & CultureTypes.InstalledWin32Cultures) != 0); bool isAddUserCustom = ((types & CultureTypes.UserCustomCulture) != 0); bool isAddReplacement = ((types & CultureTypes.ReplacementCultures) != 0); bool isAddFramework = ((types & CultureTypes.FrameworkCultures) != 0); bool isAddWindowsOnly = ((types & CultureTypes.WindowsOnlyCultures) != 0); #if !FEATURE_PAL StringBuilder dir = new StringBuilder(Path.MAX_PATH); dir.Append(Environment.InternalWindowsDirectory); dir.Append("\\Globalization\\"); string customCulturesDir = dir.ToString(); new FileIOPermission(FileIOPermissionAccess.PathDiscovery, customCulturesDir).Assert(); try { if (Directory.Exists(customCulturesDir)) { // We must now handle customized cultures, since they were requested. DirectoryInfo di = new DirectoryInfo(customCulturesDir); foreach (FileInfo fi in di.GetFiles("*.nlp")) { if (fi.Name.Length > 4) { try { CultureInfo ci = new CultureInfo(fi.Name.Substring(0, fi.Name.Length - 4), true); CultureTypes ciTypes = ci.CultureTypes; if (!IsNewNeutralChineseCulture(ci) && // we don't zh-Hant or zh-Hans ((isAddUserCustom && ((ciTypes & CultureTypes.UserCustomCulture) != 0)) || (isAddReplacement && ((ciTypes & CultureTypes.ReplacementCultures) != 0)) || (isAddSpecific && ((ciTypes & CultureTypes.SpecificCultures) != 0)) || (isAddNeutral && ((ciTypes & CultureTypes.NeutralCultures) != 0)) || (isAddFramework && ((ciTypes & CultureTypes.FrameworkCultures) != 0)) || (isAddInstalled && ((ciTypes & CultureTypes.InstalledWin32Cultures) != 0)) || (isAddWindowsOnly && ((ciTypes & CultureTypes.WindowsOnlyCultures) != 0)))) cultures.Add(ci); } catch (ArgumentException) { } // Ignore the "invalid" case here. We skip bogus files. } } } } finally { CodeAccessPermission.RevertAssert(); } // If we fail to assert, no customized culture should be added. #endif // !FEATURE_PAL if (isAddNeutral || isAddSpecific || isAddFramework || isAddInstalled) { for (int i = 0; i < m_pCultureHeader->numCultureNames; i++) { int cultureID = this.m_pCultureIDIndex[i].actualCultureID; if (CultureInfo.GetSortID(cultureID) != 0 || cultureID == CultureTableRecord.SPANISH_TRADITIONAL_SORT) { // // This is an alternate sort culture. For now, do nothing. // Eventually we may add a new CultureTypes flag. // } else { CultureInfo ci = new CultureInfo(cultureID); CultureTypes ciTypes = ci.CultureTypes; // // Invariant culture (ci.Name.Length = 0) will be returned with the Neutral cultures enumeration. // and will not be returned from specific cultures enumeration. // if (((ciTypes & CultureTypes.ReplacementCultures) == 0) && ( isAddFramework || (isAddSpecific && ci.Name.Length>0 && ((ciTypes & CultureTypes.SpecificCultures) != 0)) || (isAddNeutral && (((ciTypes & CultureTypes.NeutralCultures) != 0) || ci.Name.Length==0)) || (isAddInstalled && ((ciTypes & CultureTypes.InstalledWin32Cultures) != 0)))) cultures.Add(ci); } if (cultureID == CultureInfo.zh_CHS_CultureID || cultureID == CultureInfo.zh_CHT_CultureID) { // We have two identical zh-Hant records (with LCID 0x7c04) and two identical zh-Hans (with LCID 0x0004) record. This is needed to keep the # of index count to be the same // accross lang and name index tables. // When we are see 0004, skip the next record. i++; } } } #if !FEATURE_PAL // // IMPORTANT: WindowsOnlyCultures will enumerate all synthetic cultures which cause time and space first time creation. // if (isAddWindowsOnly || isAddSpecific || isAddInstalled) { CultureTableRecord.InitSyntheticMapping(); BCLDebug.Assert(CultureTableRecord.SyntheticLcidToNameCache != null, "[CultureTable::GetCultures] cache should be created any way."); foreach (int cultureID in CultureTableRecord.SyntheticLcidToNameCache.Keys) { // We don't enumerate alternative sorts. if (CultureInfo.GetSortID(cultureID) == 0) { CultureInfo ci = new CultureInfo(cultureID); if ((ci.CultureTypes & CultureTypes.ReplacementCultures) == 0) cultures.Add(ci); } } } #endif // !FEATURE_PAL CultureInfo [] result = new CultureInfo[cultures.Count]; cultures.CopyTo(result, 0); return (result); } } // CultureTable class // internal class for hashing culture table items (LCID/data item) // Used since the dataItem's LANGID may not account for the additional // sort ID information that may be needed. internal class CultureTableItem { internal int dataItem; internal int culture; internal string name; } /*============================================================================= * * The native struct of a record in the Culture ID Offset Table. * Every instance of this class will be mapped to a memory address in the native side. * The memory address is memory mapped from culture.nlp. * * Every primary language will have its corresponding IDOffset record. From the data * in IDOffset, we can get the index which points to a record in Culture Data Table for * a given culture ID. * * Used by GetDataItem(int cultureID) to retrieve the InternalDataItem for a given * culture ID. ==============================================================================*/ [StructLayout(LayoutKind.Sequential)] internal struct IDOffsetItem { // DWORD: the LCID value to be used with the name internal int actualCultureID; // WORD: Index which points to a record in Culture Data Table (InternalDataItem*) for a primary language. internal ushort dataItemIndex; // WORD: Offset (in words) to a string in the String Pool Table. internal ushort strOffset; } /*============================================================================= ** ** The native struct of a record in the Culture Name Offset Table. ** Every instance of this class will be mapped to a memory address in the native side. ** The memory address is memory mapped from culture.nlp. ** ** Every culture name will have its corresponding NameOffset record. From the data ** in NameOffset, we can get the index which points to a record in the Cutlure Data Table ** for a given culture name. ** ** Used by GetDataItem(String name) to retrieve the InteralDataItem for a given ** culture name. ==============================================================================*/ [StructLayout(LayoutKind.Sequential)] internal struct CultureNameOffsetItem { // WORD: Offset (in words) to a string in the String Pool Table. internal ushort strOffset; // WORD: Index to a record in Culture Data Table. internal ushort dataItemIndex; // DWORD: the LCID value to be used with the name internal int actualCultureID; } [StructLayout(LayoutKind.Sequential)] internal struct RegionNameOffsetItem { // WORD: Offset (in words) to a string in the String Pool Table. internal ushort strOffset; // WORD: Index to a record in Culture Data Table. internal ushort dataItemIndex; } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SqlCacheDependencySection.cs
- TextControlDesigner.cs
- WindowsTooltip.cs
- WebHttpBinding.cs
- CodeSubDirectory.cs
- CompilationSection.cs
- RayMeshGeometry3DHitTestResult.cs
- RectAnimationBase.cs
- WebResourceUtil.cs
- FormsAuthenticationModule.cs
- TextServicesManager.cs
- SecurityContextKeyIdentifierClause.cs
- AnnotationObservableCollection.cs
- DocumentCollection.cs
- CalendarKeyboardHelper.cs
- TabletCollection.cs
- CalendarDay.cs
- XpsS0ValidatingLoader.cs
- SqlSelectClauseBuilder.cs
- TextTreeFixupNode.cs
- DrawListViewSubItemEventArgs.cs
- SqlProfileProvider.cs
- ObjectComplexPropertyMapping.cs
- Point4D.cs
- VerificationException.cs
- MessageDecoder.cs
- SmiMetaData.cs
- DropSourceBehavior.cs
- DiagnosticsElement.cs
- ToolboxDataAttribute.cs
- StyleHelper.cs
- SpotLight.cs
- PersonalizationStateInfoCollection.cs
- FixedNode.cs
- PropertyGridCommands.cs
- StateMachine.cs
- FormsIdentity.cs
- DataControlLinkButton.cs
- TextOutput.cs
- DecoratedNameAttribute.cs
- WindowsClaimSet.cs
- RecognizedPhrase.cs
- Stack.cs
- BaseComponentEditor.cs
- WsatServiceCertificate.cs
- AnnotationObservableCollection.cs
- ModelPerspective.cs
- RestClientProxyHandler.cs
- HMACSHA1.cs
- Int32CollectionValueSerializer.cs
- DataServiceProviderMethods.cs
- Style.cs
- TextParagraphView.cs
- Validator.cs
- XmlDocument.cs
- Journal.cs
- SimpleModelProvider.cs
- Helpers.cs
- TextServicesCompartmentEventSink.cs
- HelloOperationAsyncResult.cs
- BezierSegment.cs
- RoutedEventConverter.cs
- TextControlDesigner.cs
- SqlPersistenceWorkflowInstanceDescription.cs
- MulticastIPAddressInformationCollection.cs
- AnnotationHighlightLayer.cs
- ServiceBehaviorAttribute.cs
- WindowsStatic.cs
- VectorCollectionValueSerializer.cs
- PropertyValidationContext.cs
- Compiler.cs
- SQLInt32.cs
- TaiwanLunisolarCalendar.cs
- InheritanceContextChangedEventManager.cs
- AliasGenerator.cs
- ZipIOExtraField.cs
- SqlException.cs
- UserPreferenceChangedEventArgs.cs
- WindowsAuthenticationModule.cs
- ProxyAttribute.cs
- RegexBoyerMoore.cs
- StackOverflowException.cs
- StrongNameMembershipCondition.cs
- AutomationElement.cs
- ActivitySurrogate.cs
- X509RawDataKeyIdentifierClause.cs
- CommandField.cs
- Soap.cs
- AddInContractAttribute.cs
- MenuItem.cs
- WebPartZoneBase.cs
- RenderingEventArgs.cs
- Keywords.cs
- WmlPhoneCallAdapter.cs
- Sql8ExpressionRewriter.cs
- ToolBarButton.cs
- DiscoveryUtility.cs
- OutKeywords.cs
- ViewRendering.cs
- TextEditorCopyPaste.cs