CultureTable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / BCL / System / Globalization / CultureTable.cs / 1 / 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 [....] 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; } 
            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; } 
/*
            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; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   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 [....] 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; } 
            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; } 
/*
            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; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK