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; i 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->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; inumCultureNames - 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
- RotationValidation.cs
- UnhandledExceptionEventArgs.cs
- DataError.cs
- HttpUnhandledOperationInvoker.cs
- Crypto.cs
- FileRegion.cs
- TextLine.cs
- NameSpaceExtractor.cs
- BindingNavigatorDesigner.cs
- FixedSOMPageConstructor.cs
- HttpHandlerActionCollection.cs
- DataSourceHelper.cs
- Graphics.cs
- coordinatorscratchpad.cs
- ContentControl.cs
- Evidence.cs
- StringToken.cs
- TcpConnectionPoolSettingsElement.cs
- SiteMapNodeItem.cs
- LinkedResource.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- StickyNoteContentControl.cs
- XmlElementAttributes.cs
- QilName.cs
- ContentPlaceHolder.cs
- DataSpaceManager.cs
- CryptoHelper.cs
- BulletDecorator.cs
- PageThemeParser.cs
- GenerateTemporaryAssemblyTask.cs
- NetworkAddressChange.cs
- OleDbReferenceCollection.cs
- M3DUtil.cs
- LabelAutomationPeer.cs
- TTSEngineTypes.cs
- Lease.cs
- RoleBoolean.cs
- AbandonedMutexException.cs
- Membership.cs
- ZipIORawDataFileBlock.cs
- MessageBuilder.cs
- DispatchChannelSink.cs
- HtmlTextArea.cs
- XmlSchemaImport.cs
- HtmlTable.cs
- TransformProviderWrapper.cs
- BuildProvider.cs
- MultiPageTextView.cs
- ViewBox.cs
- SuppressMessageAttribute.cs
- AffineTransform3D.cs
- EventQueueState.cs
- Pool.cs
- ResourceReader.cs
- QueryCacheKey.cs
- DPTypeDescriptorContext.cs
- XNodeNavigator.cs
- ServerIdentity.cs
- OpenFileDialog.cs
- UIElementAutomationPeer.cs
- NativeMethods.cs
- Geometry.cs
- EntityDataSourceChangedEventArgs.cs
- ListBoxChrome.cs
- CodeAttachEventStatement.cs
- StringStorage.cs
- MimeObjectFactory.cs
- TypeReference.cs
- OletxTransactionManager.cs
- DataServiceException.cs
- XmlNamespaceMapping.cs
- LineProperties.cs
- ImageMapEventArgs.cs
- XmlSchemaChoice.cs
- WebPartEventArgs.cs
- XhtmlBasicObjectListAdapter.cs
- DescendantBaseQuery.cs
- DataListItemEventArgs.cs
- MouseActionConverter.cs
- TimelineClockCollection.cs
- ObjectDataSourceFilteringEventArgs.cs
- HierarchicalDataBoundControlAdapter.cs
- cryptoapiTransform.cs
- ParameterBuilder.cs
- XhtmlConformanceSection.cs
- WebPartsSection.cs
- DbDataReader.cs
- DataTablePropertyDescriptor.cs
- Funcletizer.cs
- ClientSideQueueItem.cs
- _Win32.cs
- _UncName.cs
- SortKey.cs
- X509UI.cs
- ItemsPresenter.cs
- VariableExpressionConverter.cs
- SmtpSection.cs
- DeploymentExceptionMapper.cs
- SqlPersistenceProviderFactory.cs
- IUnknownConstantAttribute.cs