PerformanceCounterLib.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Services / Monitoring / system / Diagnosticts / PerformanceCounterLib.cs / 1407647 / PerformanceCounterLib.cs

                            namespace System.Diagnostics { 
    using System.Runtime.InteropServices;
    using System.Globalization;
    using System.Security.Permissions;
    using System.Security; 
    using System.Text;
    using System.Threading; 
    using System.Reflection; 
    using System.Collections;
    using System.ComponentModel; 
    using System.Collections.Specialized;
    using Microsoft.Win32;
    using System.IO;
    using System.Runtime.Serialization; 
    using System.Runtime.Versioning;
 
    internal class PerformanceCounterLib { 
        internal const string PerfShimName = "netfxperf.dll";
        internal const string OpenEntryPoint = "OpenPerformanceData"; 
        internal const string CollectEntryPoint = "CollectPerformanceData";
        internal const string CloseEntryPoint = "ClosePerformanceData";
        internal const string SingleInstanceName = "systemdiagnosticsperfcounterlibsingleinstance";
 
        private const string PerflibPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
        internal const string ServicePath = "SYSTEM\\CurrentControlSet\\Services"; 
        private const string categorySymbolPrefix = "OBJECT_"; 
        private const string conterSymbolPrefix = "DEVICE_COUNTER_";
        private const string helpSufix = "_HELP"; 
        private const string nameSufix = "_NAME";
        private const string textDefinition = "[text]";
        private const string infoDefinition = "[info]";
        private const string languageDefinition = "[languages]"; 
        private const string objectDefinition = "[objects]";
        private const string driverNameKeyword = "drivername"; 
        private const string symbolFileKeyword = "symbolfile"; 
        private const string defineKeyword = "#define";
        private const string languageKeyword = "language"; 
        private const string DllName = "netfxperf.dll";

        private const int EnglishLCID = 0x009;
 
        private static string computerName;
        private static string iniFilePath; 
        private static string symbolFilePath; 

        private PerformanceMonitor performanceMonitor; 
        private string machineName;
        private string perfLcid;

        private Hashtable customCategoryTable; 
        private static Hashtable libraryTable;
        private Hashtable categoryTable; 
        private Hashtable nameTable; 
        private Hashtable helpTable;
        private readonly object CategoryTableLock = new Object(); 
        private readonly object NameTableLock = new Object();
        private readonly object HelpTableLock = new Object();

        private static Object s_InternalSyncObject; 
        private static Object InternalSyncObject {
            get { 
                if (s_InternalSyncObject == null) { 
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); 
                }
                return s_InternalSyncObject;
            }
        } 

        internal PerformanceCounterLib(string machineName, string lcid) { 
            this.machineName = machineName; 
            this.perfLcid = lcid;
        } 

        /// 
        internal static string ComputerName {
            get { 
                if (computerName == null) {
                    lock (InternalSyncObject) { 
                        if (computerName == null) { 
                            StringBuilder sb = new StringBuilder(256);
                            SafeNativeMethods.GetComputerName(sb, new int[] {sb.Capacity}); 
                            computerName = sb.ToString();
                        }
                    }
                } 

                return computerName; 
            } 
        }
 
        private unsafe Hashtable CategoryTable {
            get {
                if (this.categoryTable == null) {
                    lock (this.CategoryTableLock) { 
                        if (this.categoryTable == null) {
                            byte[] perfData =  GetPerformanceData("Global"); 
 
                            fixed (byte* perfDataPtr = perfData) {
                                IntPtr dataRef = new IntPtr( (void*) perfDataPtr); 
                                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
                                Marshal.PtrToStructure(dataRef, dataBlock);
                                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength);
                                int categoryNumber = dataBlock.NumObjectTypes; 

                                // on some machines MSMQ claims to have 4 categories, even though it only has 2. 
                                // This causes us to walk past the end of our data, potentially crashing or reading 
                                // data we shouldn't.  We use endPerfData to make sure we don't go past the end
                                // of the perf data.  (ASURT 137097) 
                                long endPerfData = (long)(new IntPtr((void*)perfDataPtr)) + dataBlock.TotalByteLength;
                                Hashtable tempCategoryTable = new Hashtable(categoryNumber, StringComparer.OrdinalIgnoreCase);
                                for (int index = 0; index < categoryNumber && ((long) dataRef < endPerfData); index++) {
                                    NativeMethods.PERF_OBJECT_TYPE perfObject = new NativeMethods.PERF_OBJECT_TYPE(); 

                                    Marshal.PtrToStructure(dataRef, perfObject); 
 
                                    CategoryEntry newCategoryEntry = new CategoryEntry(perfObject);
                                    IntPtr nextRef =  (IntPtr)((long)dataRef + perfObject.TotalByteLength); 
                                    dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength);

                                    int index3 = 0;
                                    int previousCounterIndex = -1; 
                                    //Need to filter out counters that are repeated, some providers might
                                    //return several adyacent copies of the same counter. 
                                    for (int index2 = 0; index2 < newCategoryEntry.CounterIndexes.Length; ++ index2) { 
                                        NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION();
                                        Marshal.PtrToStructure(dataRef, perfCounter); 
                                        if (perfCounter.CounterNameTitleIndex != previousCounterIndex) {
                                            newCategoryEntry.CounterIndexes[index3] =  perfCounter.CounterNameTitleIndex;
                                            newCategoryEntry.HelpIndexes[index3] = perfCounter.CounterHelpTitleIndex;
                                            previousCounterIndex = perfCounter.CounterNameTitleIndex; 
                                            ++ index3;
                                        } 
                                        dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength); 
                                    }
 
                                    //Lets adjust the entry counter arrays in case there were repeated copies
                                    if (index3 <  newCategoryEntry.CounterIndexes.Length) {
                                        int[] adjustedCounterIndexes = new int[index3];
                                        int[] adjustedHelpIndexes = new int[index3]; 
                                        Array.Copy(newCategoryEntry.CounterIndexes, adjustedCounterIndexes, index3);
                                        Array.Copy(newCategoryEntry.HelpIndexes, adjustedHelpIndexes, index3); 
                                        newCategoryEntry.CounterIndexes = adjustedCounterIndexes; 
                                        newCategoryEntry.HelpIndexes = adjustedHelpIndexes;
                                    } 

                                    string categoryName = (string)this.NameTable[newCategoryEntry.NameIndex];
                                    if (categoryName != null)
                                        tempCategoryTable[categoryName] = newCategoryEntry; 

                                    dataRef = nextRef; 
                                } 

                                this.categoryTable = tempCategoryTable; 
                            }
                        }
                    }
                } 

                return this.categoryTable; 
            } 
        }
 
        internal Hashtable HelpTable {
            get {
                if (this.helpTable == null) {
                    lock(this.HelpTableLock) { 
                        if (this.helpTable == null)
                            this.helpTable = GetStringTable(true); 
                    } 
                }
 
                return this.helpTable;
            }
        }
 
        // Returns a temp file name
        private static string IniFilePath { 
            [ResourceExposure(ResourceScope.AppDomain)] 
            [ResourceConsumption(ResourceScope.AppDomain)]
            get { 
                if (iniFilePath == null) {
                    lock (InternalSyncObject) {
                        if (iniFilePath == null) {
                            // Need to assert Environment permissions here 
                            //                        the environment check is not exposed as a public
                            //                        method 
                            EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted); 
                            environmentPermission.Assert();
                            try { 
                                iniFilePath = Path.GetTempFileName();
                            }
                            finally {
                                 EnvironmentPermission.RevertAssert(); 
                            }
                        } 
                    } 
                }
 
                return iniFilePath;
            }
        }
 
        internal Hashtable NameTable {
            get { 
                if (this.nameTable == null) { 
                    lock(this.NameTableLock) {
                        if (this.nameTable == null) 
                            this.nameTable = GetStringTable(false);
                    }
                }
 
                return this.nameTable;
            } 
        } 

        // Returns a temp file name 
        private static string SymbolFilePath {
            [ResourceExposure(ResourceScope.AppDomain)]
            [ResourceConsumption(ResourceScope.AppDomain | ResourceScope.Machine)]
            get { 
                if (symbolFilePath == null) {
                    lock (InternalSyncObject) { 
                        if (symbolFilePath == null) { 
                            string tempPath;
 
                            EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted);
                            environmentPermission.Assert();
                            tempPath = Path.GetTempPath();
                            EnvironmentPermission.RevertAssert(); 

                            // We need both FileIOPermission EvironmentPermission 
                            PermissionSet ps = new PermissionSet(PermissionState.None); 
                            ps.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
                            ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Write, tempPath)); 
                            ps.Assert();
                            try {
                                symbolFilePath = Path.GetTempFileName();
                            } 
                            finally {
                                 PermissionSet.RevertAssert(); 
                            } 
                        }
                    } 
                }

                return symbolFilePath;
            } 
        }
 
        internal static bool CategoryExists(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            if (library.CategoryExists(category)) 
                return true;

            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    if (library.CategoryExists(category)) 
                        return true;
                    culture = culture.Parent; 
                }
            }

            return false; 
        }
 
        internal bool CategoryExists(string category) { 
            return CategoryTable.ContainsKey(category);
        } 

        internal static void CloseAllLibraries() {
            if (libraryTable != null) {
                foreach (PerformanceCounterLib library in libraryTable.Values) 
                    library.Close();
 
                libraryTable = null; 
            }
        } 

        internal static void CloseAllTables() {
            if (libraryTable != null) {
                foreach (PerformanceCounterLib library in libraryTable.Values) 
                    library.CloseTables();
            } 
        } 

        internal void CloseTables() { 
            this.nameTable = null;
            this.helpTable = null;
            this.categoryTable = null;
            this.customCategoryTable = null; 
        }
 
        internal void Close() { 
            if (this.performanceMonitor != null) {
                this.performanceMonitor.Close(); 
                this.performanceMonitor = null;
            }

            CloseTables(); 
        }
 
        internal static bool CounterExists(string machine, string category, string counter) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            bool categoryExists = false; 
            bool counterExists = library.CounterExists(category, counter, ref categoryExists);

            if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    counterExists = library.CounterExists(category, counter, ref categoryExists); 
                    if (counterExists)
                        break; 

                    culture = culture.Parent;
                }
            } 

            if (!categoryExists) { 
                // Consider adding diagnostic logic here, may be we can dump the nameTable... 
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
            } 

            return counterExists;
        }
 
        private bool CounterExists(string category, string counter, ref bool categoryExists) {
            categoryExists = false; 
            if (!CategoryTable.ContainsKey(category)) 
                return false;
            else 
                categoryExists = true;

            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category];
            for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex]; 
                if (counterName == null) 
                   counterName = String.Empty;
 
                if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0)
                    return true;
            }
 
            return false;
        } 
 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void CreateIniFile(string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string[] languageIds) {
            //SECREVIEW: PerformanceCounterPermission must have been demanded before
            FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted);
            permission.Assert(); 
            try {
                StreamWriter iniWriter = new StreamWriter(IniFilePath, false, Encoding.Unicode); 
                try { 
                    //NT4 won't be able to parse Unicode ini files without this
                    //extra white space. 
                    iniWriter.WriteLine("");
                    iniWriter.WriteLine(infoDefinition);
                    iniWriter.Write(driverNameKeyword);
                    iniWriter.Write("="); 
                    iniWriter.WriteLine(categoryName);
                    iniWriter.Write(symbolFileKeyword); 
                    iniWriter.Write("="); 
                    iniWriter.WriteLine(Path.GetFileName(SymbolFilePath));
                    iniWriter.WriteLine(""); 

                    iniWriter.WriteLine(languageDefinition);
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(languageId); 
                        iniWriter.Write("=");
                        iniWriter.Write(languageKeyword); 
                        iniWriter.WriteLine(languageId); 
                    }
                    iniWriter.WriteLine(""); 

                    iniWriter.WriteLine(objectDefinition);
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(categorySymbolPrefix); 
                        iniWriter.Write("1_");
                        iniWriter.Write(languageId); 
                        iniWriter.Write(nameSufix); 
                        iniWriter.Write("=");
                        iniWriter.WriteLine(categoryName); 
                    }
                    iniWriter.WriteLine("");

                    iniWriter.WriteLine(textDefinition); 
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(categorySymbolPrefix); 
                        iniWriter.Write("1_"); 
                        iniWriter.Write(languageId);
                        iniWriter.Write(nameSufix); 
                        iniWriter.Write("=");
                        iniWriter.WriteLine(categoryName);
                        iniWriter.Write(categorySymbolPrefix);
                        iniWriter.Write("1_"); 
                        iniWriter.Write(languageId);
                        iniWriter.Write(helpSufix); 
                        iniWriter.Write("="); 
                        if (categoryHelp == null || categoryHelp == String.Empty)
                            iniWriter.WriteLine(SR.GetString(SR.HelpNotAvailable)); 
                        else
                            iniWriter.WriteLine(categoryHelp);

 
                        int counterIndex = 0;
                        foreach (CounterCreationData counterData in creationData) { 
                            ++counterIndex; 
                            iniWriter.WriteLine("");
                            iniWriter.Write(conterSymbolPrefix); 
                            iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture));
                            iniWriter.Write("_");
                            iniWriter.Write(languageId);
                            iniWriter.Write(nameSufix); 
                            iniWriter.Write("=");
                            iniWriter.WriteLine(counterData.CounterName); 
 
                            iniWriter.Write(conterSymbolPrefix);
                            iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture)); 
                            iniWriter.Write("_");
                            iniWriter.Write(languageId);
                            iniWriter.Write(helpSufix);
                            iniWriter.Write("="); 

                            Debug.Assert(!String.IsNullOrEmpty(counterData.CounterHelp), "CounterHelp should have been fixed up by the caller"); 
                            iniWriter.WriteLine(counterData.CounterHelp); 
                        }
                    } 

                    iniWriter.WriteLine("");
                }
                finally { 
                    iniWriter.Close();
                } 
            } 
            finally {
                FileIOPermission.RevertAssert(); 
            }
        }

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void CreateRegistryEntry(string categoryName, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection creationData, ref bool iniRegistered) { 
            RegistryKey serviceParentKey = null; 
            RegistryKey serviceKey = null;
            RegistryKey linkageKey = null; 

            //SECREVIEW: Whoever is able to call this function, must already
            //                         have demmanded PerformanceCounterPermission
            //                         we can therefore assert the RegistryPermission. 
            RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted);
            registryPermission.Assert(); 
            try { 
                serviceParentKey = Registry.LocalMachine.OpenSubKey(ServicePath, true);
 
                serviceKey = serviceParentKey.OpenSubKey(categoryName + "\\Performance", true);
                if (serviceKey == null)
                    serviceKey = serviceParentKey.CreateSubKey(categoryName + "\\Performance");
 
                serviceKey.SetValue("Open","OpenPerformanceData");
                serviceKey.SetValue("Collect", "CollectPerformanceData"); 
                serviceKey.SetValue("Close","ClosePerformanceData"); 
                serviceKey.SetValue("Library", DllName);
                serviceKey.SetValue("IsMultiInstance", (int) categoryType, RegistryValueKind.DWord); 
                serviceKey.SetValue("CategoryOptions", 0x3, RegistryValueKind.DWord);

                string [] counters = new string[creationData.Count];
                string [] counterTypes = new string[creationData.Count]; 
                for (int i = 0; i < creationData.Count; i++) {
                    counters[i] = creationData[i].CounterName; 
                    counterTypes[i] = ((int) creationData[i].CounterType).ToString(CultureInfo.InvariantCulture); 
                }
 
                linkageKey = serviceParentKey.OpenSubKey(categoryName + "\\Linkage" , true);
                if (linkageKey == null)
                    linkageKey = serviceParentKey.CreateSubKey(categoryName + "\\Linkage" );
 
                linkageKey.SetValue("Export", new string[]{categoryName});
 
                serviceKey.SetValue("Counter Types", (object) counterTypes); 
                serviceKey.SetValue("Counter Names", (object) counters);
 
                object firstID = serviceKey.GetValue("First Counter");
                if (firstID != null)
                    iniRegistered  = true;
                else 
                    iniRegistered  = false;
            } 
            finally { 
                if (serviceKey != null)
                    serviceKey.Close(); 

                if (linkageKey != null)
                    linkageKey.Close();
 
                if (serviceParentKey != null)
                    serviceParentKey.Close(); 
 
                RegistryPermission.RevertAssert();
            } 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void CreateSymbolFile(CounterCreationDataCollection creationData) {
            //SECREVIEW: PerformanceCounterPermission must have been demanded before 
            FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted); 
            permission.Assert();
            try { 
                StreamWriter symbolWriter = new StreamWriter(SymbolFilePath);
                try {
                    symbolWriter.Write(defineKeyword);
                    symbolWriter.Write(" "); 
                    symbolWriter.Write(categorySymbolPrefix);
                    symbolWriter.WriteLine("1 0;"); 
 
                    for (int counterIndex = 1; counterIndex <= creationData.Count; ++ counterIndex) {
                        symbolWriter.Write(defineKeyword); 
                        symbolWriter.Write(" ");
                        symbolWriter.Write(conterSymbolPrefix);
                        symbolWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture));
                        symbolWriter.Write(" "); 
                        symbolWriter.Write((counterIndex * 2).ToString(CultureInfo.InvariantCulture));
                        symbolWriter.WriteLine(";"); 
                    } 

                    symbolWriter.WriteLine(""); 
                }
                finally {
                    symbolWriter.Close();
                } 
            }
            finally { 
                FileIOPermission.RevertAssert(); 
            }
        } 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void DeleteRegistryEntry(string categoryName) { 
            RegistryKey serviceKey = null;
 
            //SECREVIEW: Whoever is able to call this function, must already 
            //                         have demmanded PerformanceCounterPermission
            //                         we can therefore assert the RegistryPermission. 
            RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted);
            registryPermission.Assert();
            try {
                serviceKey = Registry.LocalMachine.OpenSubKey(ServicePath, true); 

                bool deleteCategoryKey = false; 
                using (RegistryKey categoryKey = serviceKey.OpenSubKey(categoryName, true)) { 
                    if (categoryKey != null) {
                        if (categoryKey.GetValueNames().Length == 0) { 
                            deleteCategoryKey = true;
                        }
                        else {
                            categoryKey.DeleteSubKeyTree("Linkage"); 
                            categoryKey.DeleteSubKeyTree("Performance");
                        } 
                    } 
                }
                if (deleteCategoryKey) 
                    serviceKey.DeleteSubKeyTree(categoryName);

            }
            finally { 
                if (serviceKey != null)
                    serviceKey.Close(); 
 
                RegistryPermission.RevertAssert();
            } 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void DeleteTemporaryFiles() {
            try { 
                File.Delete(IniFilePath); 
            }
            catch { 
            }

            try {
                File.Delete(SymbolFilePath); 
            }
            catch { 
            } 
        }
 
        // Ensures that the customCategoryTable is initialized and decides whether the category passed in
        //  1) is a custom category
        //  2) is a multi instance custom category
        // The return value is whether the category is a custom category or not. 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        internal bool FindCustomCategory(string category, out PerformanceCounterCategoryType categoryType) { 
            RegistryKey key = null;
            RegistryKey baseKey = null; 
            categoryType = PerformanceCounterCategoryType.Unknown;

            if (this.customCategoryTable == null) {
                Interlocked.CompareExchange(ref this.customCategoryTable, new Hashtable(StringComparer.OrdinalIgnoreCase), null); 
            }
 
            if (this.customCategoryTable.ContainsKey(category)) { 
                categoryType= (PerformanceCounterCategoryType) this.customCategoryTable[category];
                return true; 
            }
            else {
                //SECREVIEW: Whoever is able to call this function, must already
                //                         have demanded PerformanceCounterPermission 
                //                         we can therefore assert the RegistryPermission.
                PermissionSet ps = new PermissionSet(PermissionState.None); 
                ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); 
                ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
                ps.Assert(); 
                try {
                    string keyPath = ServicePath + "\\" + category + "\\Performance";
                    if (machineName == "." || String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) {
                        key = Registry.LocalMachine.OpenSubKey(keyPath); 
                    }
                    else { 
                        baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "\\\\" + this.machineName); 
                        if (baseKey != null) {
                            try { 
                                key = baseKey.OpenSubKey(keyPath);
                            } catch (SecurityException) {
                                // we may not have permission to read the registry key on the remote machine.  The security exception
                                // is thrown when RegOpenKeyEx returns ERROR_ACCESS_DENIED or ERROR_BAD_IMPERSONATION_LEVEL 
                                //
                                // In this case we return an 'Unknown' category type and 'false' to indicate the category is *not* custom. 
                                // 
                                categoryType = PerformanceCounterCategoryType.Unknown;
                                this.customCategoryTable[category] = categoryType; 
                                return false;
                            }
                        }
                    } 

                    if (key != null) { 
                        object systemDllName = key.GetValue("Library"); 
                        if (systemDllName != null && systemDllName is string && String.Compare((string)systemDllName, PerformanceCounterLib.PerfShimName, StringComparison.OrdinalIgnoreCase) == 0) {
 
                            object isMultiInstanceObject = key.GetValue("IsMultiInstance");
                            if (isMultiInstanceObject != null) {
                                categoryType = (PerformanceCounterCategoryType) isMultiInstanceObject;
                                if (categoryType < PerformanceCounterCategoryType.Unknown || categoryType > PerformanceCounterCategoryType.MultiInstance) 
                                    categoryType = PerformanceCounterCategoryType.Unknown;
                            } 
                            else 
                                categoryType = PerformanceCounterCategoryType.Unknown;
 
                            object objectID = key.GetValue("First Counter");
                            if (objectID != null) {
                                int firstID = (int)objectID;
 
                                this.customCategoryTable[category] = categoryType;
                                return true; 
                            } 
                        }
                    } 
                }
                finally {
                    if (key != null) key.Close();
                    if (baseKey != null) baseKey.Close(); 
                    PermissionSet.RevertAssert();
                } 
            } 
            return false;
        } 

        internal static string[] GetCategories(string machineName) {
            PerformanceCounterLib library;
            CultureInfo culture = CultureInfo.CurrentCulture; 
            while (culture != CultureInfo.InvariantCulture) {
                library = GetPerformanceCounterLib(machineName, culture); 
                string[] categories = library.GetCategories(); 
                if (categories.Length != 0 )
                    return categories; 
                culture = culture.Parent;
            }

            library = GetPerformanceCounterLib(machineName, new CultureInfo(EnglishLCID)); 
            return library.GetCategories();
        } 
 
        internal string[] GetCategories() {
            ICollection keys = CategoryTable.Keys; 
            string[] categories = new string[keys.Count];
            keys.CopyTo(categories, 0);
            return categories;
        } 

        internal static string GetCategoryHelp(string machine, string category) { 
            PerformanceCounterLib library; 
            string help;
 
            //First check the current culture for the category. This will allow
            //PerformanceCounterCategory.CategoryHelp to return localized strings.
            if(CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 

                while (culture != CultureInfo.InvariantCulture) { 
                    library = GetPerformanceCounterLib(machine, culture); 
                    help = library.GetCategoryHelp(category);
                    if (help != null) 
                        return help;
                    culture = culture.Parent;
                }
            } 

            //We did not find the category walking up the culture hierarchy. Try looking 
            // for the category in the default culture English. 
            library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            help = library.GetCategoryHelp(category); 

            if (help == null)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
 
            return help;
        } 
 
        private string GetCategoryHelp(string category) {
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null)
                return null;

            return (string)this.HelpTable[entry.HelpIndex]; 
        }
 
        internal static CategorySample GetCategorySample(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            CategorySample sample = library.GetCategorySample(category); 
            if (sample == null && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    sample = library.GetCategorySample(category);
                    if (sample != null) 
                        return sample; 
                    culture = culture.Parent;
                } 
            }
            if (sample == null)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
 
            return sample;
        } 
 
        private CategorySample GetCategorySample(string category) {
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null)
                return null;

            CategorySample sample = null; 
            byte[] dataRef = GetPerformanceData(entry.NameIndex.ToString(CultureInfo.InvariantCulture));
            if (dataRef == null) 
                throw new InvalidOperationException(SR.GetString(SR.CantReadCategory, category)); 

            sample = new CategorySample(dataRef, entry, this); 
            return sample;
        }

        internal static string[] GetCounters(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            bool categoryExists = false; 
            string[] counters = library.GetCounters(category, ref categoryExists); 

            if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture);
                    counters = library.GetCounters(category, ref categoryExists); 
                    if (categoryExists)
                        return counters; 
 
                    culture = culture.Parent;
                } 
            }

            if (!categoryExists)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); 

            return counters; 
        } 

        private string[] GetCounters(string category, ref bool categoryExists) { 
            categoryExists = false;
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category];
            if (entry == null)
                return null; 
            else
                categoryExists = true; 
 
            int index2 = 0;
            string[] counters = new string[entry.CounterIndexes.Length]; 
            for (int index = 0; index < counters.Length; ++ index) {
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex];
                if (counterName != null && counterName != String.Empty) { 
                    counters[index2] = counterName;
                    ++index2; 
                } 
            }
 
            //Lets adjust the array in case there were null entries
            if (index2 < counters.Length) {
                string[] adjustedCounters = new string[index2];
                Array.Copy(counters, adjustedCounters, index2); 
                counters = adjustedCounters;
            } 
 
            return counters;
        } 

        internal static string GetCounterHelp(string machine, string category, string counter) {
            PerformanceCounterLib library;
            bool categoryExists = false; 
            string help;
 
            //First check the current culture for the counter. This will allow 
            //PerformanceCounter.CounterHelp to return localized strings.
            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture);
                    help = library.GetCounterHelp(category, counter, ref categoryExists); 
                    if (categoryExists)
                        return help; 
                    culture = culture.Parent; 
                }
            } 

            //We did not find the counter walking up the culture hierarchy. Try looking
            // for the counter in the default culture English.
            library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); 
            help = library.GetCounterHelp(category, counter, ref categoryExists);
 
            if (!categoryExists) 
                throw new InvalidOperationException(SR.GetString(SR.MissingCategoryDetail, category));
 
            return help;
        }

        private string GetCounterHelp(string category, string counter, ref bool categoryExists) { 
            categoryExists = false;
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null) 
                return null;
            else 
                categoryExists = true;

            int helpIndex = -1;
            for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex]; 
                if (counterName == null) 
                   counterName = String.Empty;
 
                if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) {
                    helpIndex = entry.HelpIndexes[index];
                    break;
                } 
            }
 
            if (helpIndex == -1) 
                throw new InvalidOperationException(SR.GetString(SR.MissingCounter, counter));
 
            string help = (string)this.HelpTable[helpIndex];
            if (help == null)
                return String.Empty;
            else 
                return help;
        } 
 
        internal string GetCounterName(int index) {
            if (this.NameTable.ContainsKey(index)) 
                return (string)this.NameTable[index];

            return "";
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static string[] GetLanguageIds() {
            RegistryKey libraryParentKey = null; 
            string[] ids = new string[0];
            new RegistryPermission(PermissionState.Unrestricted).Assert();
            try {
                libraryParentKey = Registry.LocalMachine.OpenSubKey(PerflibPath); 

                if (libraryParentKey != null) 
                    ids = libraryParentKey.GetSubKeyNames(); 
            }
            finally { 
                if (libraryParentKey != null)
                    libraryParentKey.Close();

                RegistryPermission.RevertAssert(); 
            }
 
            return ids; 
        }
 
        internal static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture) {
            SharedUtils.CheckEnvironment();

            string lcidString = culture.LCID.ToString("X3", CultureInfo.InvariantCulture); 
            if (machineName.CompareTo(".") == 0)
                machineName = ComputerName.ToLower(CultureInfo.InvariantCulture); 
            else 
                machineName = machineName.ToLower(CultureInfo.InvariantCulture);
 
            if (PerformanceCounterLib.libraryTable == null) {
                lock (InternalSyncObject) {
                    if (PerformanceCounterLib.libraryTable == null)
                        PerformanceCounterLib.libraryTable = new Hashtable(); 
                }
            } 
 
            string libraryKey = machineName + ":" + lcidString;
            if (PerformanceCounterLib.libraryTable.Contains(libraryKey)) 
                return (PerformanceCounterLib)PerformanceCounterLib.libraryTable[libraryKey];
            else {
                PerformanceCounterLib library = new PerformanceCounterLib(machineName, lcidString);
                PerformanceCounterLib.libraryTable[libraryKey] = library; 
                return library;
            } 
        } 

        internal byte[] GetPerformanceData(string item) { 
            if (this.performanceMonitor == null) {
                lock (InternalSyncObject) {
                    if (this.performanceMonitor == null)
                        this.performanceMonitor = new PerformanceMonitor(this.machineName); 
                }
            } 
 
           return this.performanceMonitor.GetData(item);
        } 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private Hashtable GetStringTable(bool isHelp) { 
            Hashtable stringTable;
            RegistryKey libraryKey; 
 
            PermissionSet ps = new PermissionSet(PermissionState.None);
            ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); 
            ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
            ps.Assert();

            if (String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) 
                libraryKey = Registry.PerformanceData;
            else { 
                libraryKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, this.machineName); 
            }
 
            try {
                string[] names = null;
                int waitRetries = 14;   //((2^13)-1)*10ms == approximately 1.4mins
                int waitSleep = 0; 

                // In some stress situations, querying counter values from 
                // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009 
                // often returns null/empty data back. We should build fault-tolerance logic to
                // make it more reliable because getting null back once doesn't necessarily mean 
                // that the data is corrupted, most of the time we would get the data just fine
                // in subsequent tries.
                while (waitRetries > 0) {
                    try { 
                        if (!isHelp)
                            names = (string[])libraryKey.GetValue("Counter " + perfLcid); 
                        else 
                            names = (string[])libraryKey.GetValue("Explain " + perfLcid);
 
                        if ((names == null) || (names.Length == 0)) {
                            --waitRetries;
                            if (waitSleep == 0)
                                waitSleep = 10; 
                            else {
                                System.Threading.Thread.Sleep(waitSleep); 
                                waitSleep *= 2; 
                            }
                        } 
                        else
                            break;
                    }
                    catch (IOException) { 
                        // RegistryKey throws if it can't find the value.  We want to return an empty table
                        // and throw a different exception higher up the stack. 
                        names = null; 
                        break;
                    } 
                    catch (InvalidCastException) {
                        // Unable to cast object of type 'System.Byte[]' to type 'System.String[]'.
                        // this happens when the registry data store is corrupt and the type is not even REG_MULTI_SZ
                        names = null; 
                        break;
                    } 
                } 

                if (names == null) 
                    stringTable = new Hashtable();
                else {
                    stringTable = new Hashtable(names.Length/2);
 
                    for (int index = 0; index < (names.Length/2); ++ index) {
                        string nameString =  names[(index *2) + 1]; 
                        if (nameString == null) 
                            nameString = String.Empty;
 
                        int key;
                        if (!Int32.TryParse(names[index * 2], NumberStyles.Integer, CultureInfo.InvariantCulture, out key)) {
                            if (isHelp) {
                                // Category Help Table 
                                throw new InvalidOperationException(SR.GetString(SR.CategoryHelpCorrupt, names[index * 2]));
                            } 
                            else { 
                                // Counter Name Table
                                throw new InvalidOperationException(SR.GetString(SR.CounterNameCorrupt, names[index * 2])); 
                            }
                        }

                        stringTable[key] = nameString; 
                    }
                } 
            } 
            finally {
                libraryKey.Close(); 
            }

            return stringTable;
        } 

        internal static bool IsCustomCategory(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); 
            if (library.IsCustomCategory(category))
                return true; 

            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) { 
                    library = GetPerformanceCounterLib(machine, culture);
                    if (library.IsCustomCategory(category)) 
                        return true; 
                    culture = culture.Parent;
                } 
            }

            return false;
        } 

        internal static bool IsBaseCounter(int type) { 
            return (type == NativeMethods.PERF_AVERAGE_BASE || 
                    type == NativeMethods.PERF_COUNTER_MULTI_BASE ||
                    type == NativeMethods.PERF_RAW_BASE  || 
                    type == NativeMethods.PERF_LARGE_RAW_BASE  ||
                    type == NativeMethods.PERF_SAMPLE_BASE);
        }
 
        private bool IsCustomCategory(string category) {
            PerformanceCounterCategoryType categoryType; 
 
            return FindCustomCategory(category, out categoryType);
        } 

        internal static PerformanceCounterCategoryType GetCategoryType(string machine, string category) {
            PerformanceCounterCategoryType categoryType = PerformanceCounterCategoryType.Unknown;
 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            if (!library.FindCustomCategory(category, out categoryType)) { 
                if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                    CultureInfo culture = CultureInfo.CurrentCulture;
                    while (culture != CultureInfo.InvariantCulture) { 
                        library = GetPerformanceCounterLib(machine, culture);
                        if (library.FindCustomCategory(category, out categoryType))
                            return categoryType;
                        culture = culture.Parent; 
                    }
                } 
            } 
            return categoryType;
        } 

        /*
        // Creates a category with an ini file supplied by the user.  Currently this is not available.
        internal static void RegisterCategory(string machineName, string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string localizedIniFilePath) { 
            bool iniRegistered = false;
            CreateRegistryEntry(machineName, categoryName, creationData, ref iniRegistered); 
            if (!iniRegistered) 
                RegisterFiles(machineName, localizedIniFilePath, false);
 
            CloseAllTables();
        }
        */
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        internal static void RegisterCategory(string categoryName, PerformanceCounterCategoryType categoryType, string categoryHelp, CounterCreationDataCollection creationData) { 
            try {
                bool iniRegistered = false; 
                CreateRegistryEntry(categoryName, categoryType, creationData, ref iniRegistered);
                if (!iniRegistered) {
                    string[] languageIds = GetLanguageIds();
                    CreateIniFile(categoryName, categoryHelp, creationData, languageIds); 
                    CreateSymbolFile(creationData);
                    RegisterFiles(IniFilePath, false); 
                } 
                CloseAllTables();
                CloseAllLibraries(); 
            }
            finally {
                DeleteTemporaryFiles();
            } 
        }
 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void RegisterFiles(string arg0, bool unregister) { 
            Process p;
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.UseShellExecute = false;
            processStartInfo.CreateNoWindow = true; 
            processStartInfo.ErrorDialog = false;
            processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
            processStartInfo.WorkingDirectory = Environment.SystemDirectory; 

            if (unregister) 
                processStartInfo.FileName = Environment.SystemDirectory + "\\unlodctr.exe";
            else
                processStartInfo.FileName = Environment.SystemDirectory + "\\lodctr.exe";
 
            int res = 0;
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); 
            try { 
                processStartInfo.Arguments = "\"" + arg0 + "\"";
                p = Process.Start(processStartInfo); 
                p.WaitForExit();

                res = p.ExitCode;
            } 
            finally {
                SecurityPermission.RevertAssert(); 
            } 

 
            if (res == NativeMethods.ERROR_ACCESS_DENIED) {
                throw new UnauthorizedAccessException(SR.GetString(SR.CantChangeCategoryRegistration, arg0));
            }
 
            // Look at Q269225, unlodctr might return 2 when WMI is not installed.
            if (unregister && res == 2) 
                res = 0; 

            if (res != 0) 
                throw SharedUtils.CreateSafeWin32Exception(res);
        }

        internal static void UnregisterCategory(string categoryName) { 
            RegisterFiles(categoryName, true);
            DeleteRegistryEntry(categoryName); 
            CloseAllTables(); 
            CloseAllLibraries();
        } 
    }

    internal class PerformanceMonitor {
        private RegistryKey perfDataKey = null; 
        private string machineName;
 
        internal PerformanceMonitor(string machineName) { 
            this.machineName = machineName;
            Init(); 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private void Init() {
            try { 
                if (machineName != "." && String.Compare(machineName, PerformanceCounterLib.ComputerName, StringComparison.OrdinalIgnoreCase) != 0) { 
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                    perfDataKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, machineName); 
                }
                else
                    perfDataKey = Registry.PerformanceData;
            } 
            catch (UnauthorizedAccessException) {
                // we need to do this for compatibility with v1.1 and v1.0. 
                throw new Win32Exception(NativeMethods.ERROR_ACCESS_DENIED); 
            }
            catch (IOException e) { 
                // we need to do this for compatibility with v1.1 and v1.0.
                throw new Win32Exception(Marshal.GetHRForException(e));
            }
        } 

        internal void Close() { 
            if( perfDataKey != null) 
                perfDataKey.Close();
 
            perfDataKey = null;
        }

        // Win32 RegQueryValueEx for perf data could deadlock (for a Mutex) up to 2mins in some 
        // scenarios before they detect it and exit gracefully. In the mean time, ERROR_BUSY,
        // ERROR_NOT_READY etc can be seen by other concurrent calls (which is the reason for the 
        // wait loop and switch case below). We want to wait most certainly more than a 2min window. 
        // The curent wait time of up to 10mins takes care of the known stress deadlock issues. In most
        // cases we wouldn't wait for more than 2mins anyways but in worst cases how much ever time 
        // we wait may not be sufficient if the Win32 code keeps running into this deadlock again
        // and again. A condition very rare but possible in theory. We would get back to the user
        // in this case with InvalidOperationException after the wait time expires.
        internal byte[] GetData(string item) { 
            int waitRetries = 17;   //2^16*10ms == approximately 10mins
            int waitSleep = 0; 
            byte[] data = null; 
            int error = 0;
 
            // no need to revert here since we'll fall off the end of the method
            new RegistryPermission(PermissionState.Unrestricted).Assert();
            while (waitRetries > 0) {
                try { 
                    data = (byte[]) perfDataKey.GetValue(item);
                    return data; 
                } 
                catch (IOException e) {
                    error = Marshal.GetHRForException(e); 
                    switch (error) {
                        case NativeMethods.RPC_S_CALL_FAILED:
                        case NativeMethods.ERROR_INVALID_HANDLE:
                        case NativeMethods.RPC_S_SERVER_UNAVAILABLE: 
                            Init();
                            goto case NativeMethods.WAIT_TIMEOUT; 
 
                        case NativeMethods.WAIT_TIMEOUT:
                        case NativeMethods.ERROR_NOT_READY: 
                        case NativeMethods.ERROR_LOCK_FAILED:
                        case NativeMethods.ERROR_BUSY:
                            --waitRetries;
                            if (waitSleep == 0) { 
                                waitSleep = 10;
                            } 
                            else { 
                                System.Threading.Thread.Sleep(waitSleep);
                                waitSleep *= 2; 
                            }
                            break;

                        default: 
                            throw SharedUtils.CreateSafeWin32Exception(error);
                    } 
                } 
                catch (InvalidCastException e) {
                    throw new InvalidOperationException(SR.GetString(SR.CounterDataCorrupt, perfDataKey.ToString()), e); 
                }
            }

            throw SharedUtils.CreateSafeWin32Exception(error); 
        }
 
    } 

    internal class CategoryEntry { 
        internal int NameIndex;
        internal int HelpIndex;
        internal int[] CounterIndexes;
        internal int[] HelpIndexes; 

        internal CategoryEntry(NativeMethods.PERF_OBJECT_TYPE perfObject) { 
            this.NameIndex = perfObject.ObjectNameTitleIndex; 
            this.HelpIndex = perfObject.ObjectHelpTitleIndex;
            this.CounterIndexes = new int[perfObject.NumCounters]; 
            this.HelpIndexes = new int[perfObject.NumCounters];
        }
    }
 
    internal class CategorySample {
        internal readonly long SystemFrequency; 
        internal readonly long TimeStamp; 
        internal readonly long TimeStamp100nSec;
        internal readonly long CounterFrequency; 
        internal readonly long CounterTimeStamp;
        internal Hashtable CounterTable;
        internal Hashtable InstanceNameTable;
        internal bool IsMultiInstance; 
        private CategoryEntry entry;
        private PerformanceCounterLib library; 
 
        internal unsafe CategorySample(byte[] data, CategoryEntry entry, PerformanceCounterLib library) {
            this.entry = entry; 
            this.library = library;
            int categoryIndex = entry.NameIndex;
            NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
            fixed (byte* dataPtr = data) { 
                IntPtr dataRef = new IntPtr((void*) dataPtr);
 
                Marshal.PtrToStructure(dataRef, dataBlock); 
                this.SystemFrequency = dataBlock.PerfFreq;
                this.TimeStamp = dataBlock.PerfTime; 
                this.TimeStamp100nSec = dataBlock.PerfTime100nSec;
                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength);
                int numPerfObjects = dataBlock.NumObjectTypes;
                if (numPerfObjects == 0) { 
                    this.CounterTable = new Hashtable();
                    this.InstanceNameTable = new Hashtable(StringComparer.OrdinalIgnoreCase); 
                    return; 
                }
 
                //Need to find the right category, GetPerformanceData might return
                //several of them.
                NativeMethods.PERF_OBJECT_TYPE perfObject = null;
                bool foundCategory = false; 
                for (int index = 0; index < numPerfObjects; index++) {
                    perfObject = new NativeMethods.PERF_OBJECT_TYPE(); 
                    Marshal.PtrToStructure(dataRef, perfObject); 

                   if (perfObject.ObjectNameTitleIndex == categoryIndex) { 
                        foundCategory = true;
                        break;
                    }
 
                    dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength);
                } 
 
                if (!foundCategory)
                    throw new InvalidOperationException(SR.GetString(SR.CantReadCategoryIndex, categoryIndex.ToString(CultureInfo.CurrentCulture))); 

                this.CounterFrequency = perfObject.PerfFreq;
                this.CounterTimeStamp = perfObject.PerfTime;
                int counterNumber = perfObject.NumCounters; 
                int instanceNumber = perfObject.NumInstances;
 
                if (instanceNumber == -1) 
                    IsMultiInstance = false;
                else 
                    IsMultiInstance = true;

                // Move pointer forward to end of PERF_OBJECT_TYPE
                dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength); 

                CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; 
                this.CounterTable = new Hashtable(counterNumber); 
                for (int index = 0; index < samples.Length; ++ index) {
                    NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfCounter);
                    samples[index] = new CounterDefinitionSample(perfCounter, this, instanceNumber);
                    dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength);
 
                    int currentSampleType = samples[index].CounterType;
                    if (!PerformanceCounterLib.IsBaseCounter(currentSampleType)) { 
                        // We'll put only non-base counters in the table. 
                        if (currentSampleType != NativeMethods.PERF_COUNTER_NODATA)
                            this.CounterTable[samples[index].NameIndex] = samples[index]; 
                    }
                    else {
                        // it's a base counter, try to hook it up to the main counter.
                        Debug.Assert(index > 0, "Index > 0 because base counters should never be at index 0"); 
                        if (index > 0)
                            samples[index-1].BaseCounterDefinitionSample = samples[index]; 
                    } 
                }
 
                // now set up the InstanceNameTable.
                if (!IsMultiInstance) {
                    this.InstanceNameTable = new Hashtable(1, StringComparer.OrdinalIgnoreCase);
                    this.InstanceNameTable[PerformanceCounterLib.SingleInstanceName] = 0; 

                    for (int index = 0; index < samples.Length; ++ index)  { 
                        samples[index].SetInstanceValue(0, dataRef); 
                    }
                } 
                else {
                    string[] parentInstanceNames = null;
                    this.InstanceNameTable = new Hashtable(instanceNumber, StringComparer.OrdinalIgnoreCase);
                    for (int i = 0; i < instanceNumber; i++) { 
                        NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION();
                        Marshal.PtrToStructure(dataRef, perfInstance); 
                        if (perfInstance.ParentObjectTitleIndex > 0 && parentInstanceNames == null) 
                            parentInstanceNames = GetInstanceNamesFromIndex(perfInstance.ParentObjectTitleIndex);
 
                        string instanceName;
                        if (parentInstanceNames != null && perfInstance.ParentObjectInstance >= 0 && perfInstance.ParentObjectInstance < parentInstanceNames.Length - 1)
                            instanceName = parentInstanceNames[perfInstance.ParentObjectInstance] + "/" + Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));
                        else 
                            instanceName = Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));
 
                        //In some cases instance names are not unique (Process), same as perfmon 
                        //generate a unique name.
                        string newInstanceName = instanceName; 
                        int newInstanceNumber = 1;
                        while (true) {
                            if (!this.InstanceNameTable.ContainsKey(newInstanceName)) {
                                this.InstanceNameTable[newInstanceName] = i; 
                                break;
                            } 
                            else { 
                                newInstanceName =  instanceName + "#" + newInstanceNumber.ToString(CultureInfo.InvariantCulture);
                                ++  newInstanceNumber; 
                            }
                        }

 
                        dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength);
                        for (int index = 0; index < samples.Length; ++ index) 
                            samples[index].SetInstanceValue(i, dataRef); 

                        dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef)); 
                    }
                }
            }
        } 

        internal unsafe string[] GetInstanceNamesFromIndex(int categoryIndex) { 
            byte[] data = library.GetPerformanceData(categoryIndex.ToString(CultureInfo.InvariantCulture)); 
            fixed (byte* dataPtr = data) {
                IntPtr dataRef = new IntPtr((void*) dataPtr); 

                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
                Marshal.PtrToStructure(dataRef, dataBlock);
                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength); 
                int numPerfObjects = dataBlock.NumObjectTypes;
 
                NativeMethods.PERF_OBJECT_TYPE perfObject = null; 
                bool foundCategory = false;
                for (int index = 0; index < numPerfObjects; index++) { 
                    perfObject = new NativeMethods.PERF_OBJECT_TYPE();
                    Marshal.PtrToStructure(dataRef, perfObject);

                    if (perfObject.ObjectNameTitleIndex == categoryIndex) { 
                        foundCategory = true;
                        break; 
                    } 

                    dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength); 
                }

                if (!foundCategory)
                    return new string[0]; 

                int counterNumber = perfObject.NumCounters; 
                int instanceNumber = perfObject.NumInstances; 
                dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength);
 
                if (instanceNumber == -1)
                    return new string[0];

                CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; 
                for (int index = 0; index < samples.Length; ++ index) {
                    NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfCounter); 
                    dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength);
                } 

                string[] instanceNames = new string[instanceNumber];
                for (int i = 0; i < instanceNumber; i++) {
                    NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfInstance);
                    instanceNames[i] =  Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset)); 
                    dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength); 
                    dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef));
                } 

                return instanceNames;
            }
        } 

        internal CounterDefinitionSample GetCounterDefinitionSample(string counter) { 
            for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.library.NameTable[counterIndex]; 
                if (counterName != null) {
                    if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) {
                        CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex];
                        if (sample == null) { 
                            //This is a base counter and has not been added to the table
                            foreach (CounterDefinitionSample multiSample in this.CounterTable.Values) { 
                                if (multiSample.BaseCounterDefinitionSample != null && 
                                    multiSample.BaseCounterDefinitionSample.NameIndex == counterIndex)
                                    return multiSample.BaseCounterDefinitionSample; 
                            }

                            throw new InvalidOperationException(SR.GetString(SR.CounterLayout));
                        } 
                        return sample;
                    } 
                } 
            }
 
            throw new InvalidOperationException(SR.GetString(SR.CantReadCounter, counter));
        }

        internal InstanceDataCollectionCollection ReadCategory() { 

#pragma warning disable 618 
            InstanceDataCollectionCollection data = new InstanceDataCollectionCollection(); 
#pragma warning restore 618
            for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];

                string name = (string)library.NameTable[counterIndex];
                if (name != null && name != String.Empty) { 
                    CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex];
                    if (sample != null) 
                        //If the current index refers to a counter base, 
                        //the sample will be null
                        data.Add(name, sample.ReadInstanceData(name)); 
                }
            }

            return data; 
        }
    } 
 
    internal class CounterDefinitionSample {
        internal readonly int NameIndex; 
        internal readonly int CounterType;
        internal CounterDefinitionSample BaseCounterDefinitionSample;

        private readonly int size; 
        private readonly int offset;
        private long[] instanceValues; 
        private CategorySample categorySample; 

        internal CounterDefinitionSample(NativeMethods.PERF_COUNTER_DEFINITION perfCounter, CategorySample categorySample, int instanceNumber) { 
            this.NameIndex = perfCounter.CounterNameTitleIndex;
            this.CounterType = perfCounter.CounterType;
            this.offset = perfCounter.CounterOffset;
            this.size = perfCounter.CounterSize; 
            if (instanceNumber == -1) {
                this.instanceValues = new long[1]; 
            } 
            else
                this.instanceValues = new long[instanceNumber]; 

            this.categorySample = categorySample;
        }
 
        private long ReadValue(IntPtr pointer) {
            if (this.size == 4) { 
                return (long)(uint)Marshal.ReadInt32((IntPtr)((long)pointer + this.offset)); 
            }
            else if (this.size == 8) { 
                return (long)Marshal.ReadInt64((IntPtr)((long)pointer + this.offset));
            }

            return -1; 
        }
 
        internal CounterSample GetInstanceValue(string instanceName) { 

            if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) { 
                // Our native dll truncates instance names to 128 characters.  If we can't find the instance
                // with the full name, try truncating to 128 characters.
                if (instanceName.Length > SharedPerformanceCounter.InstanceNameMaxLength)
                    instanceName = instanceName.Substring(0, SharedPerformanceCounter.InstanceNameMaxLength); 

                if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) 
                    throw new InvalidOperationException(SR.GetString(SR.CantReadInstance, instanceName)); 
            }
 
            int index = (int)categorySample.InstanceNameTable[instanceName];
            long rawValue = this.instanceValues[index];
            long baseValue = 0;
            if (this.BaseCounterDefinitionSample != null) { 
                CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample;
                int baseIndex = (int)baseCategorySample.InstanceNameTable[instanceName]; 
                baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex]; 
            }
 
            return new CounterSample(rawValue,
                                                        baseValue,
                                                        categorySample.CounterFrequency,
                                                        categorySample.SystemFrequency, 
                                                        categorySample.TimeStamp,
                                                        categorySample.TimeStamp100nSec, 
                                                        (PerformanceCounterType)this.CounterType, 
                                                        categorySample.CounterTimeStamp);
 
        }

        internal InstanceDataCollection ReadInstanceData(string counterName) {
#pragma warning disable 618 
            InstanceDataCollection data = new InstanceDataCollection(counterName);
#pragma warning restore 618 
 
            string[] keys = new string[categorySample.InstanceNameTable.Count];
            categorySample.InstanceNameTable.Keys.CopyTo(keys, 0); 
            int[] indexes = new int[categorySample.InstanceNameTable.Count];
            categorySample.InstanceNameTable.Values.CopyTo(indexes, 0);
            for (int index = 0; index < keys.Length; ++ index) {
                long baseValue = 0; 
                if (this.BaseCounterDefinitionSample != null) {
                    CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample; 
                    int baseIndex = (int)baseCategorySample.InstanceNameTable[keys[index]]; 
                    baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex];
                } 

                CounterSample sample = new CounterSample(this.instanceValues[indexes[index]],
                                                        baseValue,
                                                        categorySample.CounterFrequency, 
                                                        categorySample.SystemFrequency,
                                                        categorySample.TimeStamp, 
                                                        categorySample.TimeStamp100nSec, 
                                                        (PerformanceCounterType)this.CounterType,
                                                        categorySample.CounterTimeStamp); 

                data.Add(keys[index], new InstanceData(keys[index], sample));
            }
 
            return data;
        } 
 
        internal CounterSample GetSingleValue() {
            long rawValue = this.instanceValues[0]; 
            long baseValue = 0;
            if (this.BaseCounterDefinitionSample != null)
                baseValue = this.BaseCounterDefinitionSample.instanceValues[0];
 
            return new CounterSample(rawValue,
                                                        baseValue, 
                                                        categorySample.CounterFrequency, 
                                                        categorySample.SystemFrequency,
                                                        categorySample.TimeStamp, 
                                                        categorySample.TimeStamp100nSec,
                                                        (PerformanceCounterType)this.CounterType,
                                                        categorySample.CounterTimeStamp);
        } 

        internal void SetInstanceValue(int index, IntPtr dataRef) { 
            long rawValue = ReadValue(dataRef); 
            this.instanceValues[index] = rawValue;
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
namespace System.Diagnostics { 
    using System.Runtime.InteropServices;
    using System.Globalization;
    using System.Security.Permissions;
    using System.Security; 
    using System.Text;
    using System.Threading; 
    using System.Reflection; 
    using System.Collections;
    using System.ComponentModel; 
    using System.Collections.Specialized;
    using Microsoft.Win32;
    using System.IO;
    using System.Runtime.Serialization; 
    using System.Runtime.Versioning;
 
    internal class PerformanceCounterLib { 
        internal const string PerfShimName = "netfxperf.dll";
        internal const string OpenEntryPoint = "OpenPerformanceData"; 
        internal const string CollectEntryPoint = "CollectPerformanceData";
        internal const string CloseEntryPoint = "ClosePerformanceData";
        internal const string SingleInstanceName = "systemdiagnosticsperfcounterlibsingleinstance";
 
        private const string PerflibPath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
        internal const string ServicePath = "SYSTEM\\CurrentControlSet\\Services"; 
        private const string categorySymbolPrefix = "OBJECT_"; 
        private const string conterSymbolPrefix = "DEVICE_COUNTER_";
        private const string helpSufix = "_HELP"; 
        private const string nameSufix = "_NAME";
        private const string textDefinition = "[text]";
        private const string infoDefinition = "[info]";
        private const string languageDefinition = "[languages]"; 
        private const string objectDefinition = "[objects]";
        private const string driverNameKeyword = "drivername"; 
        private const string symbolFileKeyword = "symbolfile"; 
        private const string defineKeyword = "#define";
        private const string languageKeyword = "language"; 
        private const string DllName = "netfxperf.dll";

        private const int EnglishLCID = 0x009;
 
        private static string computerName;
        private static string iniFilePath; 
        private static string symbolFilePath; 

        private PerformanceMonitor performanceMonitor; 
        private string machineName;
        private string perfLcid;

        private Hashtable customCategoryTable; 
        private static Hashtable libraryTable;
        private Hashtable categoryTable; 
        private Hashtable nameTable; 
        private Hashtable helpTable;
        private readonly object CategoryTableLock = new Object(); 
        private readonly object NameTableLock = new Object();
        private readonly object HelpTableLock = new Object();

        private static Object s_InternalSyncObject; 
        private static Object InternalSyncObject {
            get { 
                if (s_InternalSyncObject == null) { 
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); 
                }
                return s_InternalSyncObject;
            }
        } 

        internal PerformanceCounterLib(string machineName, string lcid) { 
            this.machineName = machineName; 
            this.perfLcid = lcid;
        } 

        /// 
        internal static string ComputerName {
            get { 
                if (computerName == null) {
                    lock (InternalSyncObject) { 
                        if (computerName == null) { 
                            StringBuilder sb = new StringBuilder(256);
                            SafeNativeMethods.GetComputerName(sb, new int[] {sb.Capacity}); 
                            computerName = sb.ToString();
                        }
                    }
                } 

                return computerName; 
            } 
        }
 
        private unsafe Hashtable CategoryTable {
            get {
                if (this.categoryTable == null) {
                    lock (this.CategoryTableLock) { 
                        if (this.categoryTable == null) {
                            byte[] perfData =  GetPerformanceData("Global"); 
 
                            fixed (byte* perfDataPtr = perfData) {
                                IntPtr dataRef = new IntPtr( (void*) perfDataPtr); 
                                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
                                Marshal.PtrToStructure(dataRef, dataBlock);
                                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength);
                                int categoryNumber = dataBlock.NumObjectTypes; 

                                // on some machines MSMQ claims to have 4 categories, even though it only has 2. 
                                // This causes us to walk past the end of our data, potentially crashing or reading 
                                // data we shouldn't.  We use endPerfData to make sure we don't go past the end
                                // of the perf data.  (ASURT 137097) 
                                long endPerfData = (long)(new IntPtr((void*)perfDataPtr)) + dataBlock.TotalByteLength;
                                Hashtable tempCategoryTable = new Hashtable(categoryNumber, StringComparer.OrdinalIgnoreCase);
                                for (int index = 0; index < categoryNumber && ((long) dataRef < endPerfData); index++) {
                                    NativeMethods.PERF_OBJECT_TYPE perfObject = new NativeMethods.PERF_OBJECT_TYPE(); 

                                    Marshal.PtrToStructure(dataRef, perfObject); 
 
                                    CategoryEntry newCategoryEntry = new CategoryEntry(perfObject);
                                    IntPtr nextRef =  (IntPtr)((long)dataRef + perfObject.TotalByteLength); 
                                    dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength);

                                    int index3 = 0;
                                    int previousCounterIndex = -1; 
                                    //Need to filter out counters that are repeated, some providers might
                                    //return several adyacent copies of the same counter. 
                                    for (int index2 = 0; index2 < newCategoryEntry.CounterIndexes.Length; ++ index2) { 
                                        NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION();
                                        Marshal.PtrToStructure(dataRef, perfCounter); 
                                        if (perfCounter.CounterNameTitleIndex != previousCounterIndex) {
                                            newCategoryEntry.CounterIndexes[index3] =  perfCounter.CounterNameTitleIndex;
                                            newCategoryEntry.HelpIndexes[index3] = perfCounter.CounterHelpTitleIndex;
                                            previousCounterIndex = perfCounter.CounterNameTitleIndex; 
                                            ++ index3;
                                        } 
                                        dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength); 
                                    }
 
                                    //Lets adjust the entry counter arrays in case there were repeated copies
                                    if (index3 <  newCategoryEntry.CounterIndexes.Length) {
                                        int[] adjustedCounterIndexes = new int[index3];
                                        int[] adjustedHelpIndexes = new int[index3]; 
                                        Array.Copy(newCategoryEntry.CounterIndexes, adjustedCounterIndexes, index3);
                                        Array.Copy(newCategoryEntry.HelpIndexes, adjustedHelpIndexes, index3); 
                                        newCategoryEntry.CounterIndexes = adjustedCounterIndexes; 
                                        newCategoryEntry.HelpIndexes = adjustedHelpIndexes;
                                    } 

                                    string categoryName = (string)this.NameTable[newCategoryEntry.NameIndex];
                                    if (categoryName != null)
                                        tempCategoryTable[categoryName] = newCategoryEntry; 

                                    dataRef = nextRef; 
                                } 

                                this.categoryTable = tempCategoryTable; 
                            }
                        }
                    }
                } 

                return this.categoryTable; 
            } 
        }
 
        internal Hashtable HelpTable {
            get {
                if (this.helpTable == null) {
                    lock(this.HelpTableLock) { 
                        if (this.helpTable == null)
                            this.helpTable = GetStringTable(true); 
                    } 
                }
 
                return this.helpTable;
            }
        }
 
        // Returns a temp file name
        private static string IniFilePath { 
            [ResourceExposure(ResourceScope.AppDomain)] 
            [ResourceConsumption(ResourceScope.AppDomain)]
            get { 
                if (iniFilePath == null) {
                    lock (InternalSyncObject) {
                        if (iniFilePath == null) {
                            // Need to assert Environment permissions here 
                            //                        the environment check is not exposed as a public
                            //                        method 
                            EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted); 
                            environmentPermission.Assert();
                            try { 
                                iniFilePath = Path.GetTempFileName();
                            }
                            finally {
                                 EnvironmentPermission.RevertAssert(); 
                            }
                        } 
                    } 
                }
 
                return iniFilePath;
            }
        }
 
        internal Hashtable NameTable {
            get { 
                if (this.nameTable == null) { 
                    lock(this.NameTableLock) {
                        if (this.nameTable == null) 
                            this.nameTable = GetStringTable(false);
                    }
                }
 
                return this.nameTable;
            } 
        } 

        // Returns a temp file name 
        private static string SymbolFilePath {
            [ResourceExposure(ResourceScope.AppDomain)]
            [ResourceConsumption(ResourceScope.AppDomain | ResourceScope.Machine)]
            get { 
                if (symbolFilePath == null) {
                    lock (InternalSyncObject) { 
                        if (symbolFilePath == null) { 
                            string tempPath;
 
                            EnvironmentPermission environmentPermission = new EnvironmentPermission(PermissionState.Unrestricted);
                            environmentPermission.Assert();
                            tempPath = Path.GetTempPath();
                            EnvironmentPermission.RevertAssert(); 

                            // We need both FileIOPermission EvironmentPermission 
                            PermissionSet ps = new PermissionSet(PermissionState.None); 
                            ps.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
                            ps.AddPermission(new FileIOPermission(FileIOPermissionAccess.Write, tempPath)); 
                            ps.Assert();
                            try {
                                symbolFilePath = Path.GetTempFileName();
                            } 
                            finally {
                                 PermissionSet.RevertAssert(); 
                            } 
                        }
                    } 
                }

                return symbolFilePath;
            } 
        }
 
        internal static bool CategoryExists(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            if (library.CategoryExists(category)) 
                return true;

            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    if (library.CategoryExists(category)) 
                        return true;
                    culture = culture.Parent; 
                }
            }

            return false; 
        }
 
        internal bool CategoryExists(string category) { 
            return CategoryTable.ContainsKey(category);
        } 

        internal static void CloseAllLibraries() {
            if (libraryTable != null) {
                foreach (PerformanceCounterLib library in libraryTable.Values) 
                    library.Close();
 
                libraryTable = null; 
            }
        } 

        internal static void CloseAllTables() {
            if (libraryTable != null) {
                foreach (PerformanceCounterLib library in libraryTable.Values) 
                    library.CloseTables();
            } 
        } 

        internal void CloseTables() { 
            this.nameTable = null;
            this.helpTable = null;
            this.categoryTable = null;
            this.customCategoryTable = null; 
        }
 
        internal void Close() { 
            if (this.performanceMonitor != null) {
                this.performanceMonitor.Close(); 
                this.performanceMonitor = null;
            }

            CloseTables(); 
        }
 
        internal static bool CounterExists(string machine, string category, string counter) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            bool categoryExists = false; 
            bool counterExists = library.CounterExists(category, counter, ref categoryExists);

            if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    counterExists = library.CounterExists(category, counter, ref categoryExists); 
                    if (counterExists)
                        break; 

                    culture = culture.Parent;
                }
            } 

            if (!categoryExists) { 
                // Consider adding diagnostic logic here, may be we can dump the nameTable... 
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
            } 

            return counterExists;
        }
 
        private bool CounterExists(string category, string counter, ref bool categoryExists) {
            categoryExists = false; 
            if (!CategoryTable.ContainsKey(category)) 
                return false;
            else 
                categoryExists = true;

            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category];
            for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex]; 
                if (counterName == null) 
                   counterName = String.Empty;
 
                if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0)
                    return true;
            }
 
            return false;
        } 
 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void CreateIniFile(string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string[] languageIds) {
            //SECREVIEW: PerformanceCounterPermission must have been demanded before
            FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted);
            permission.Assert(); 
            try {
                StreamWriter iniWriter = new StreamWriter(IniFilePath, false, Encoding.Unicode); 
                try { 
                    //NT4 won't be able to parse Unicode ini files without this
                    //extra white space. 
                    iniWriter.WriteLine("");
                    iniWriter.WriteLine(infoDefinition);
                    iniWriter.Write(driverNameKeyword);
                    iniWriter.Write("="); 
                    iniWriter.WriteLine(categoryName);
                    iniWriter.Write(symbolFileKeyword); 
                    iniWriter.Write("="); 
                    iniWriter.WriteLine(Path.GetFileName(SymbolFilePath));
                    iniWriter.WriteLine(""); 

                    iniWriter.WriteLine(languageDefinition);
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(languageId); 
                        iniWriter.Write("=");
                        iniWriter.Write(languageKeyword); 
                        iniWriter.WriteLine(languageId); 
                    }
                    iniWriter.WriteLine(""); 

                    iniWriter.WriteLine(objectDefinition);
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(categorySymbolPrefix); 
                        iniWriter.Write("1_");
                        iniWriter.Write(languageId); 
                        iniWriter.Write(nameSufix); 
                        iniWriter.Write("=");
                        iniWriter.WriteLine(categoryName); 
                    }
                    iniWriter.WriteLine("");

                    iniWriter.WriteLine(textDefinition); 
                    foreach (string languageId in languageIds) {
                        iniWriter.Write(categorySymbolPrefix); 
                        iniWriter.Write("1_"); 
                        iniWriter.Write(languageId);
                        iniWriter.Write(nameSufix); 
                        iniWriter.Write("=");
                        iniWriter.WriteLine(categoryName);
                        iniWriter.Write(categorySymbolPrefix);
                        iniWriter.Write("1_"); 
                        iniWriter.Write(languageId);
                        iniWriter.Write(helpSufix); 
                        iniWriter.Write("="); 
                        if (categoryHelp == null || categoryHelp == String.Empty)
                            iniWriter.WriteLine(SR.GetString(SR.HelpNotAvailable)); 
                        else
                            iniWriter.WriteLine(categoryHelp);

 
                        int counterIndex = 0;
                        foreach (CounterCreationData counterData in creationData) { 
                            ++counterIndex; 
                            iniWriter.WriteLine("");
                            iniWriter.Write(conterSymbolPrefix); 
                            iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture));
                            iniWriter.Write("_");
                            iniWriter.Write(languageId);
                            iniWriter.Write(nameSufix); 
                            iniWriter.Write("=");
                            iniWriter.WriteLine(counterData.CounterName); 
 
                            iniWriter.Write(conterSymbolPrefix);
                            iniWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture)); 
                            iniWriter.Write("_");
                            iniWriter.Write(languageId);
                            iniWriter.Write(helpSufix);
                            iniWriter.Write("="); 

                            Debug.Assert(!String.IsNullOrEmpty(counterData.CounterHelp), "CounterHelp should have been fixed up by the caller"); 
                            iniWriter.WriteLine(counterData.CounterHelp); 
                        }
                    } 

                    iniWriter.WriteLine("");
                }
                finally { 
                    iniWriter.Close();
                } 
            } 
            finally {
                FileIOPermission.RevertAssert(); 
            }
        }

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void CreateRegistryEntry(string categoryName, PerformanceCounterCategoryType categoryType, CounterCreationDataCollection creationData, ref bool iniRegistered) { 
            RegistryKey serviceParentKey = null; 
            RegistryKey serviceKey = null;
            RegistryKey linkageKey = null; 

            //SECREVIEW: Whoever is able to call this function, must already
            //                         have demmanded PerformanceCounterPermission
            //                         we can therefore assert the RegistryPermission. 
            RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted);
            registryPermission.Assert(); 
            try { 
                serviceParentKey = Registry.LocalMachine.OpenSubKey(ServicePath, true);
 
                serviceKey = serviceParentKey.OpenSubKey(categoryName + "\\Performance", true);
                if (serviceKey == null)
                    serviceKey = serviceParentKey.CreateSubKey(categoryName + "\\Performance");
 
                serviceKey.SetValue("Open","OpenPerformanceData");
                serviceKey.SetValue("Collect", "CollectPerformanceData"); 
                serviceKey.SetValue("Close","ClosePerformanceData"); 
                serviceKey.SetValue("Library", DllName);
                serviceKey.SetValue("IsMultiInstance", (int) categoryType, RegistryValueKind.DWord); 
                serviceKey.SetValue("CategoryOptions", 0x3, RegistryValueKind.DWord);

                string [] counters = new string[creationData.Count];
                string [] counterTypes = new string[creationData.Count]; 
                for (int i = 0; i < creationData.Count; i++) {
                    counters[i] = creationData[i].CounterName; 
                    counterTypes[i] = ((int) creationData[i].CounterType).ToString(CultureInfo.InvariantCulture); 
                }
 
                linkageKey = serviceParentKey.OpenSubKey(categoryName + "\\Linkage" , true);
                if (linkageKey == null)
                    linkageKey = serviceParentKey.CreateSubKey(categoryName + "\\Linkage" );
 
                linkageKey.SetValue("Export", new string[]{categoryName});
 
                serviceKey.SetValue("Counter Types", (object) counterTypes); 
                serviceKey.SetValue("Counter Names", (object) counters);
 
                object firstID = serviceKey.GetValue("First Counter");
                if (firstID != null)
                    iniRegistered  = true;
                else 
                    iniRegistered  = false;
            } 
            finally { 
                if (serviceKey != null)
                    serviceKey.Close(); 

                if (linkageKey != null)
                    linkageKey.Close();
 
                if (serviceParentKey != null)
                    serviceParentKey.Close(); 
 
                RegistryPermission.RevertAssert();
            } 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void CreateSymbolFile(CounterCreationDataCollection creationData) {
            //SECREVIEW: PerformanceCounterPermission must have been demanded before 
            FileIOPermission permission = new FileIOPermission(PermissionState.Unrestricted); 
            permission.Assert();
            try { 
                StreamWriter symbolWriter = new StreamWriter(SymbolFilePath);
                try {
                    symbolWriter.Write(defineKeyword);
                    symbolWriter.Write(" "); 
                    symbolWriter.Write(categorySymbolPrefix);
                    symbolWriter.WriteLine("1 0;"); 
 
                    for (int counterIndex = 1; counterIndex <= creationData.Count; ++ counterIndex) {
                        symbolWriter.Write(defineKeyword); 
                        symbolWriter.Write(" ");
                        symbolWriter.Write(conterSymbolPrefix);
                        symbolWriter.Write(counterIndex.ToString(CultureInfo.InvariantCulture));
                        symbolWriter.Write(" "); 
                        symbolWriter.Write((counterIndex * 2).ToString(CultureInfo.InvariantCulture));
                        symbolWriter.WriteLine(";"); 
                    } 

                    symbolWriter.WriteLine(""); 
                }
                finally {
                    symbolWriter.Close();
                } 
            }
            finally { 
                FileIOPermission.RevertAssert(); 
            }
        } 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void DeleteRegistryEntry(string categoryName) { 
            RegistryKey serviceKey = null;
 
            //SECREVIEW: Whoever is able to call this function, must already 
            //                         have demmanded PerformanceCounterPermission
            //                         we can therefore assert the RegistryPermission. 
            RegistryPermission registryPermission = new RegistryPermission(PermissionState.Unrestricted);
            registryPermission.Assert();
            try {
                serviceKey = Registry.LocalMachine.OpenSubKey(ServicePath, true); 

                bool deleteCategoryKey = false; 
                using (RegistryKey categoryKey = serviceKey.OpenSubKey(categoryName, true)) { 
                    if (categoryKey != null) {
                        if (categoryKey.GetValueNames().Length == 0) { 
                            deleteCategoryKey = true;
                        }
                        else {
                            categoryKey.DeleteSubKeyTree("Linkage"); 
                            categoryKey.DeleteSubKeyTree("Performance");
                        } 
                    } 
                }
                if (deleteCategoryKey) 
                    serviceKey.DeleteSubKeyTree(categoryName);

            }
            finally { 
                if (serviceKey != null)
                    serviceKey.Close(); 
 
                RegistryPermission.RevertAssert();
            } 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static void DeleteTemporaryFiles() {
            try { 
                File.Delete(IniFilePath); 
            }
            catch { 
            }

            try {
                File.Delete(SymbolFilePath); 
            }
            catch { 
            } 
        }
 
        // Ensures that the customCategoryTable is initialized and decides whether the category passed in
        //  1) is a custom category
        //  2) is a multi instance custom category
        // The return value is whether the category is a custom category or not. 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        internal bool FindCustomCategory(string category, out PerformanceCounterCategoryType categoryType) { 
            RegistryKey key = null;
            RegistryKey baseKey = null; 
            categoryType = PerformanceCounterCategoryType.Unknown;

            if (this.customCategoryTable == null) {
                Interlocked.CompareExchange(ref this.customCategoryTable, new Hashtable(StringComparer.OrdinalIgnoreCase), null); 
            }
 
            if (this.customCategoryTable.ContainsKey(category)) { 
                categoryType= (PerformanceCounterCategoryType) this.customCategoryTable[category];
                return true; 
            }
            else {
                //SECREVIEW: Whoever is able to call this function, must already
                //                         have demanded PerformanceCounterPermission 
                //                         we can therefore assert the RegistryPermission.
                PermissionSet ps = new PermissionSet(PermissionState.None); 
                ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); 
                ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
                ps.Assert(); 
                try {
                    string keyPath = ServicePath + "\\" + category + "\\Performance";
                    if (machineName == "." || String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) {
                        key = Registry.LocalMachine.OpenSubKey(keyPath); 
                    }
                    else { 
                        baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "\\\\" + this.machineName); 
                        if (baseKey != null) {
                            try { 
                                key = baseKey.OpenSubKey(keyPath);
                            } catch (SecurityException) {
                                // we may not have permission to read the registry key on the remote machine.  The security exception
                                // is thrown when RegOpenKeyEx returns ERROR_ACCESS_DENIED or ERROR_BAD_IMPERSONATION_LEVEL 
                                //
                                // In this case we return an 'Unknown' category type and 'false' to indicate the category is *not* custom. 
                                // 
                                categoryType = PerformanceCounterCategoryType.Unknown;
                                this.customCategoryTable[category] = categoryType; 
                                return false;
                            }
                        }
                    } 

                    if (key != null) { 
                        object systemDllName = key.GetValue("Library"); 
                        if (systemDllName != null && systemDllName is string && String.Compare((string)systemDllName, PerformanceCounterLib.PerfShimName, StringComparison.OrdinalIgnoreCase) == 0) {
 
                            object isMultiInstanceObject = key.GetValue("IsMultiInstance");
                            if (isMultiInstanceObject != null) {
                                categoryType = (PerformanceCounterCategoryType) isMultiInstanceObject;
                                if (categoryType < PerformanceCounterCategoryType.Unknown || categoryType > PerformanceCounterCategoryType.MultiInstance) 
                                    categoryType = PerformanceCounterCategoryType.Unknown;
                            } 
                            else 
                                categoryType = PerformanceCounterCategoryType.Unknown;
 
                            object objectID = key.GetValue("First Counter");
                            if (objectID != null) {
                                int firstID = (int)objectID;
 
                                this.customCategoryTable[category] = categoryType;
                                return true; 
                            } 
                        }
                    } 
                }
                finally {
                    if (key != null) key.Close();
                    if (baseKey != null) baseKey.Close(); 
                    PermissionSet.RevertAssert();
                } 
            } 
            return false;
        } 

        internal static string[] GetCategories(string machineName) {
            PerformanceCounterLib library;
            CultureInfo culture = CultureInfo.CurrentCulture; 
            while (culture != CultureInfo.InvariantCulture) {
                library = GetPerformanceCounterLib(machineName, culture); 
                string[] categories = library.GetCategories(); 
                if (categories.Length != 0 )
                    return categories; 
                culture = culture.Parent;
            }

            library = GetPerformanceCounterLib(machineName, new CultureInfo(EnglishLCID)); 
            return library.GetCategories();
        } 
 
        internal string[] GetCategories() {
            ICollection keys = CategoryTable.Keys; 
            string[] categories = new string[keys.Count];
            keys.CopyTo(categories, 0);
            return categories;
        } 

        internal static string GetCategoryHelp(string machine, string category) { 
            PerformanceCounterLib library; 
            string help;
 
            //First check the current culture for the category. This will allow
            //PerformanceCounterCategory.CategoryHelp to return localized strings.
            if(CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture; 

                while (culture != CultureInfo.InvariantCulture) { 
                    library = GetPerformanceCounterLib(machine, culture); 
                    help = library.GetCategoryHelp(category);
                    if (help != null) 
                        return help;
                    culture = culture.Parent;
                }
            } 

            //We did not find the category walking up the culture hierarchy. Try looking 
            // for the category in the default culture English. 
            library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            help = library.GetCategoryHelp(category); 

            if (help == null)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
 
            return help;
        } 
 
        private string GetCategoryHelp(string category) {
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null)
                return null;

            return (string)this.HelpTable[entry.HelpIndex]; 
        }
 
        internal static CategorySample GetCategorySample(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            CategorySample sample = library.GetCategorySample(category); 
            if (sample == null && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture); 
                    sample = library.GetCategorySample(category);
                    if (sample != null) 
                        return sample; 
                    culture = culture.Parent;
                } 
            }
            if (sample == null)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory));
 
            return sample;
        } 
 
        private CategorySample GetCategorySample(string category) {
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null)
                return null;

            CategorySample sample = null; 
            byte[] dataRef = GetPerformanceData(entry.NameIndex.ToString(CultureInfo.InvariantCulture));
            if (dataRef == null) 
                throw new InvalidOperationException(SR.GetString(SR.CantReadCategory, category)); 

            sample = new CategorySample(dataRef, entry, this); 
            return sample;
        }

        internal static string[] GetCounters(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            bool categoryExists = false; 
            string[] counters = library.GetCounters(category, ref categoryExists); 

            if (!categoryExists && CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture);
                    counters = library.GetCounters(category, ref categoryExists); 
                    if (categoryExists)
                        return counters; 
 
                    culture = culture.Parent;
                } 
            }

            if (!categoryExists)
                throw new InvalidOperationException(SR.GetString(SR.MissingCategory)); 

            return counters; 
        } 

        private string[] GetCounters(string category, ref bool categoryExists) { 
            categoryExists = false;
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category];
            if (entry == null)
                return null; 
            else
                categoryExists = true; 
 
            int index2 = 0;
            string[] counters = new string[entry.CounterIndexes.Length]; 
            for (int index = 0; index < counters.Length; ++ index) {
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex];
                if (counterName != null && counterName != String.Empty) { 
                    counters[index2] = counterName;
                    ++index2; 
                } 
            }
 
            //Lets adjust the array in case there were null entries
            if (index2 < counters.Length) {
                string[] adjustedCounters = new string[index2];
                Array.Copy(counters, adjustedCounters, index2); 
                counters = adjustedCounters;
            } 
 
            return counters;
        } 

        internal static string GetCounterHelp(string machine, string category, string counter) {
            PerformanceCounterLib library;
            bool categoryExists = false; 
            string help;
 
            //First check the current culture for the counter. This will allow 
            //PerformanceCounter.CounterHelp to return localized strings.
            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) {
                    library = GetPerformanceCounterLib(machine, culture);
                    help = library.GetCounterHelp(category, counter, ref categoryExists); 
                    if (categoryExists)
                        return help; 
                    culture = culture.Parent; 
                }
            } 

            //We did not find the counter walking up the culture hierarchy. Try looking
            // for the counter in the default culture English.
            library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); 
            help = library.GetCounterHelp(category, counter, ref categoryExists);
 
            if (!categoryExists) 
                throw new InvalidOperationException(SR.GetString(SR.MissingCategoryDetail, category));
 
            return help;
        }

        private string GetCounterHelp(string category, string counter, ref bool categoryExists) { 
            categoryExists = false;
            CategoryEntry entry = (CategoryEntry)this.CategoryTable[category]; 
            if (entry == null) 
                return null;
            else 
                categoryExists = true;

            int helpIndex = -1;
            for (int index = 0; index < entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.NameTable[counterIndex]; 
                if (counterName == null) 
                   counterName = String.Empty;
 
                if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) {
                    helpIndex = entry.HelpIndexes[index];
                    break;
                } 
            }
 
            if (helpIndex == -1) 
                throw new InvalidOperationException(SR.GetString(SR.MissingCounter, counter));
 
            string help = (string)this.HelpTable[helpIndex];
            if (help == null)
                return String.Empty;
            else 
                return help;
        } 
 
        internal string GetCounterName(int index) {
            if (this.NameTable.ContainsKey(index)) 
                return (string)this.NameTable[index];

            return "";
        } 

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private static string[] GetLanguageIds() {
            RegistryKey libraryParentKey = null; 
            string[] ids = new string[0];
            new RegistryPermission(PermissionState.Unrestricted).Assert();
            try {
                libraryParentKey = Registry.LocalMachine.OpenSubKey(PerflibPath); 

                if (libraryParentKey != null) 
                    ids = libraryParentKey.GetSubKeyNames(); 
            }
            finally { 
                if (libraryParentKey != null)
                    libraryParentKey.Close();

                RegistryPermission.RevertAssert(); 
            }
 
            return ids; 
        }
 
        internal static PerformanceCounterLib GetPerformanceCounterLib(string machineName, CultureInfo culture) {
            SharedUtils.CheckEnvironment();

            string lcidString = culture.LCID.ToString("X3", CultureInfo.InvariantCulture); 
            if (machineName.CompareTo(".") == 0)
                machineName = ComputerName.ToLower(CultureInfo.InvariantCulture); 
            else 
                machineName = machineName.ToLower(CultureInfo.InvariantCulture);
 
            if (PerformanceCounterLib.libraryTable == null) {
                lock (InternalSyncObject) {
                    if (PerformanceCounterLib.libraryTable == null)
                        PerformanceCounterLib.libraryTable = new Hashtable(); 
                }
            } 
 
            string libraryKey = machineName + ":" + lcidString;
            if (PerformanceCounterLib.libraryTable.Contains(libraryKey)) 
                return (PerformanceCounterLib)PerformanceCounterLib.libraryTable[libraryKey];
            else {
                PerformanceCounterLib library = new PerformanceCounterLib(machineName, lcidString);
                PerformanceCounterLib.libraryTable[libraryKey] = library; 
                return library;
            } 
        } 

        internal byte[] GetPerformanceData(string item) { 
            if (this.performanceMonitor == null) {
                lock (InternalSyncObject) {
                    if (this.performanceMonitor == null)
                        this.performanceMonitor = new PerformanceMonitor(this.machineName); 
                }
            } 
 
           return this.performanceMonitor.GetData(item);
        } 

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private Hashtable GetStringTable(bool isHelp) { 
            Hashtable stringTable;
            RegistryKey libraryKey; 
 
            PermissionSet ps = new PermissionSet(PermissionState.None);
            ps.AddPermission(new RegistryPermission(PermissionState.Unrestricted)); 
            ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
            ps.Assert();

            if (String.Compare(this.machineName, ComputerName, StringComparison.OrdinalIgnoreCase) == 0) 
                libraryKey = Registry.PerformanceData;
            else { 
                libraryKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, this.machineName); 
            }
 
            try {
                string[] names = null;
                int waitRetries = 14;   //((2^13)-1)*10ms == approximately 1.4mins
                int waitSleep = 0; 

                // In some stress situations, querying counter values from 
                // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009 
                // often returns null/empty data back. We should build fault-tolerance logic to
                // make it more reliable because getting null back once doesn't necessarily mean 
                // that the data is corrupted, most of the time we would get the data just fine
                // in subsequent tries.
                while (waitRetries > 0) {
                    try { 
                        if (!isHelp)
                            names = (string[])libraryKey.GetValue("Counter " + perfLcid); 
                        else 
                            names = (string[])libraryKey.GetValue("Explain " + perfLcid);
 
                        if ((names == null) || (names.Length == 0)) {
                            --waitRetries;
                            if (waitSleep == 0)
                                waitSleep = 10; 
                            else {
                                System.Threading.Thread.Sleep(waitSleep); 
                                waitSleep *= 2; 
                            }
                        } 
                        else
                            break;
                    }
                    catch (IOException) { 
                        // RegistryKey throws if it can't find the value.  We want to return an empty table
                        // and throw a different exception higher up the stack. 
                        names = null; 
                        break;
                    } 
                    catch (InvalidCastException) {
                        // Unable to cast object of type 'System.Byte[]' to type 'System.String[]'.
                        // this happens when the registry data store is corrupt and the type is not even REG_MULTI_SZ
                        names = null; 
                        break;
                    } 
                } 

                if (names == null) 
                    stringTable = new Hashtable();
                else {
                    stringTable = new Hashtable(names.Length/2);
 
                    for (int index = 0; index < (names.Length/2); ++ index) {
                        string nameString =  names[(index *2) + 1]; 
                        if (nameString == null) 
                            nameString = String.Empty;
 
                        int key;
                        if (!Int32.TryParse(names[index * 2], NumberStyles.Integer, CultureInfo.InvariantCulture, out key)) {
                            if (isHelp) {
                                // Category Help Table 
                                throw new InvalidOperationException(SR.GetString(SR.CategoryHelpCorrupt, names[index * 2]));
                            } 
                            else { 
                                // Counter Name Table
                                throw new InvalidOperationException(SR.GetString(SR.CounterNameCorrupt, names[index * 2])); 
                            }
                        }

                        stringTable[key] = nameString; 
                    }
                } 
            } 
            finally {
                libraryKey.Close(); 
            }

            return stringTable;
        } 

        internal static bool IsCustomCategory(string machine, string category) { 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID)); 
            if (library.IsCustomCategory(category))
                return true; 

            if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) {
                CultureInfo culture = CultureInfo.CurrentCulture;
                while (culture != CultureInfo.InvariantCulture) { 
                    library = GetPerformanceCounterLib(machine, culture);
                    if (library.IsCustomCategory(category)) 
                        return true; 
                    culture = culture.Parent;
                } 
            }

            return false;
        } 

        internal static bool IsBaseCounter(int type) { 
            return (type == NativeMethods.PERF_AVERAGE_BASE || 
                    type == NativeMethods.PERF_COUNTER_MULTI_BASE ||
                    type == NativeMethods.PERF_RAW_BASE  || 
                    type == NativeMethods.PERF_LARGE_RAW_BASE  ||
                    type == NativeMethods.PERF_SAMPLE_BASE);
        }
 
        private bool IsCustomCategory(string category) {
            PerformanceCounterCategoryType categoryType; 
 
            return FindCustomCategory(category, out categoryType);
        } 

        internal static PerformanceCounterCategoryType GetCategoryType(string machine, string category) {
            PerformanceCounterCategoryType categoryType = PerformanceCounterCategoryType.Unknown;
 
            PerformanceCounterLib library = GetPerformanceCounterLib(machine, new CultureInfo(EnglishLCID));
            if (!library.FindCustomCategory(category, out categoryType)) { 
                if (CultureInfo.CurrentCulture.Parent.LCID != EnglishLCID) { 
                    CultureInfo culture = CultureInfo.CurrentCulture;
                    while (culture != CultureInfo.InvariantCulture) { 
                        library = GetPerformanceCounterLib(machine, culture);
                        if (library.FindCustomCategory(category, out categoryType))
                            return categoryType;
                        culture = culture.Parent; 
                    }
                } 
            } 
            return categoryType;
        } 

        /*
        // Creates a category with an ini file supplied by the user.  Currently this is not available.
        internal static void RegisterCategory(string machineName, string categoryName, string categoryHelp, CounterCreationDataCollection creationData, string localizedIniFilePath) { 
            bool iniRegistered = false;
            CreateRegistryEntry(machineName, categoryName, creationData, ref iniRegistered); 
            if (!iniRegistered) 
                RegisterFiles(machineName, localizedIniFilePath, false);
 
            CloseAllTables();
        }
        */
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        internal static void RegisterCategory(string categoryName, PerformanceCounterCategoryType categoryType, string categoryHelp, CounterCreationDataCollection creationData) { 
            try {
                bool iniRegistered = false; 
                CreateRegistryEntry(categoryName, categoryType, creationData, ref iniRegistered);
                if (!iniRegistered) {
                    string[] languageIds = GetLanguageIds();
                    CreateIniFile(categoryName, categoryHelp, creationData, languageIds); 
                    CreateSymbolFile(creationData);
                    RegisterFiles(IniFilePath, false); 
                } 
                CloseAllTables();
                CloseAllLibraries(); 
            }
            finally {
                DeleteTemporaryFiles();
            } 
        }
 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static void RegisterFiles(string arg0, bool unregister) { 
            Process p;
            ProcessStartInfo processStartInfo = new ProcessStartInfo();
            processStartInfo.UseShellExecute = false;
            processStartInfo.CreateNoWindow = true; 
            processStartInfo.ErrorDialog = false;
            processStartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
            processStartInfo.WorkingDirectory = Environment.SystemDirectory; 

            if (unregister) 
                processStartInfo.FileName = Environment.SystemDirectory + "\\unlodctr.exe";
            else
                processStartInfo.FileName = Environment.SystemDirectory + "\\lodctr.exe";
 
            int res = 0;
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert(); 
            try { 
                processStartInfo.Arguments = "\"" + arg0 + "\"";
                p = Process.Start(processStartInfo); 
                p.WaitForExit();

                res = p.ExitCode;
            } 
            finally {
                SecurityPermission.RevertAssert(); 
            } 

 
            if (res == NativeMethods.ERROR_ACCESS_DENIED) {
                throw new UnauthorizedAccessException(SR.GetString(SR.CantChangeCategoryRegistration, arg0));
            }
 
            // Look at Q269225, unlodctr might return 2 when WMI is not installed.
            if (unregister && res == 2) 
                res = 0; 

            if (res != 0) 
                throw SharedUtils.CreateSafeWin32Exception(res);
        }

        internal static void UnregisterCategory(string categoryName) { 
            RegisterFiles(categoryName, true);
            DeleteRegistryEntry(categoryName); 
            CloseAllTables(); 
            CloseAllLibraries();
        } 
    }

    internal class PerformanceMonitor {
        private RegistryKey perfDataKey = null; 
        private string machineName;
 
        internal PerformanceMonitor(string machineName) { 
            this.machineName = machineName;
            Init(); 
        }

        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        private void Init() {
            try { 
                if (machineName != "." && String.Compare(machineName, PerformanceCounterLib.ComputerName, StringComparison.OrdinalIgnoreCase) != 0) { 
                    new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
                    perfDataKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.PerformanceData, machineName); 
                }
                else
                    perfDataKey = Registry.PerformanceData;
            } 
            catch (UnauthorizedAccessException) {
                // we need to do this for compatibility with v1.1 and v1.0. 
                throw new Win32Exception(NativeMethods.ERROR_ACCESS_DENIED); 
            }
            catch (IOException e) { 
                // we need to do this for compatibility with v1.1 and v1.0.
                throw new Win32Exception(Marshal.GetHRForException(e));
            }
        } 

        internal void Close() { 
            if( perfDataKey != null) 
                perfDataKey.Close();
 
            perfDataKey = null;
        }

        // Win32 RegQueryValueEx for perf data could deadlock (for a Mutex) up to 2mins in some 
        // scenarios before they detect it and exit gracefully. In the mean time, ERROR_BUSY,
        // ERROR_NOT_READY etc can be seen by other concurrent calls (which is the reason for the 
        // wait loop and switch case below). We want to wait most certainly more than a 2min window. 
        // The curent wait time of up to 10mins takes care of the known stress deadlock issues. In most
        // cases we wouldn't wait for more than 2mins anyways but in worst cases how much ever time 
        // we wait may not be sufficient if the Win32 code keeps running into this deadlock again
        // and again. A condition very rare but possible in theory. We would get back to the user
        // in this case with InvalidOperationException after the wait time expires.
        internal byte[] GetData(string item) { 
            int waitRetries = 17;   //2^16*10ms == approximately 10mins
            int waitSleep = 0; 
            byte[] data = null; 
            int error = 0;
 
            // no need to revert here since we'll fall off the end of the method
            new RegistryPermission(PermissionState.Unrestricted).Assert();
            while (waitRetries > 0) {
                try { 
                    data = (byte[]) perfDataKey.GetValue(item);
                    return data; 
                } 
                catch (IOException e) {
                    error = Marshal.GetHRForException(e); 
                    switch (error) {
                        case NativeMethods.RPC_S_CALL_FAILED:
                        case NativeMethods.ERROR_INVALID_HANDLE:
                        case NativeMethods.RPC_S_SERVER_UNAVAILABLE: 
                            Init();
                            goto case NativeMethods.WAIT_TIMEOUT; 
 
                        case NativeMethods.WAIT_TIMEOUT:
                        case NativeMethods.ERROR_NOT_READY: 
                        case NativeMethods.ERROR_LOCK_FAILED:
                        case NativeMethods.ERROR_BUSY:
                            --waitRetries;
                            if (waitSleep == 0) { 
                                waitSleep = 10;
                            } 
                            else { 
                                System.Threading.Thread.Sleep(waitSleep);
                                waitSleep *= 2; 
                            }
                            break;

                        default: 
                            throw SharedUtils.CreateSafeWin32Exception(error);
                    } 
                } 
                catch (InvalidCastException e) {
                    throw new InvalidOperationException(SR.GetString(SR.CounterDataCorrupt, perfDataKey.ToString()), e); 
                }
            }

            throw SharedUtils.CreateSafeWin32Exception(error); 
        }
 
    } 

    internal class CategoryEntry { 
        internal int NameIndex;
        internal int HelpIndex;
        internal int[] CounterIndexes;
        internal int[] HelpIndexes; 

        internal CategoryEntry(NativeMethods.PERF_OBJECT_TYPE perfObject) { 
            this.NameIndex = perfObject.ObjectNameTitleIndex; 
            this.HelpIndex = perfObject.ObjectHelpTitleIndex;
            this.CounterIndexes = new int[perfObject.NumCounters]; 
            this.HelpIndexes = new int[perfObject.NumCounters];
        }
    }
 
    internal class CategorySample {
        internal readonly long SystemFrequency; 
        internal readonly long TimeStamp; 
        internal readonly long TimeStamp100nSec;
        internal readonly long CounterFrequency; 
        internal readonly long CounterTimeStamp;
        internal Hashtable CounterTable;
        internal Hashtable InstanceNameTable;
        internal bool IsMultiInstance; 
        private CategoryEntry entry;
        private PerformanceCounterLib library; 
 
        internal unsafe CategorySample(byte[] data, CategoryEntry entry, PerformanceCounterLib library) {
            this.entry = entry; 
            this.library = library;
            int categoryIndex = entry.NameIndex;
            NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
            fixed (byte* dataPtr = data) { 
                IntPtr dataRef = new IntPtr((void*) dataPtr);
 
                Marshal.PtrToStructure(dataRef, dataBlock); 
                this.SystemFrequency = dataBlock.PerfFreq;
                this.TimeStamp = dataBlock.PerfTime; 
                this.TimeStamp100nSec = dataBlock.PerfTime100nSec;
                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength);
                int numPerfObjects = dataBlock.NumObjectTypes;
                if (numPerfObjects == 0) { 
                    this.CounterTable = new Hashtable();
                    this.InstanceNameTable = new Hashtable(StringComparer.OrdinalIgnoreCase); 
                    return; 
                }
 
                //Need to find the right category, GetPerformanceData might return
                //several of them.
                NativeMethods.PERF_OBJECT_TYPE perfObject = null;
                bool foundCategory = false; 
                for (int index = 0; index < numPerfObjects; index++) {
                    perfObject = new NativeMethods.PERF_OBJECT_TYPE(); 
                    Marshal.PtrToStructure(dataRef, perfObject); 

                   if (perfObject.ObjectNameTitleIndex == categoryIndex) { 
                        foundCategory = true;
                        break;
                    }
 
                    dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength);
                } 
 
                if (!foundCategory)
                    throw new InvalidOperationException(SR.GetString(SR.CantReadCategoryIndex, categoryIndex.ToString(CultureInfo.CurrentCulture))); 

                this.CounterFrequency = perfObject.PerfFreq;
                this.CounterTimeStamp = perfObject.PerfTime;
                int counterNumber = perfObject.NumCounters; 
                int instanceNumber = perfObject.NumInstances;
 
                if (instanceNumber == -1) 
                    IsMultiInstance = false;
                else 
                    IsMultiInstance = true;

                // Move pointer forward to end of PERF_OBJECT_TYPE
                dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength); 

                CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; 
                this.CounterTable = new Hashtable(counterNumber); 
                for (int index = 0; index < samples.Length; ++ index) {
                    NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfCounter);
                    samples[index] = new CounterDefinitionSample(perfCounter, this, instanceNumber);
                    dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength);
 
                    int currentSampleType = samples[index].CounterType;
                    if (!PerformanceCounterLib.IsBaseCounter(currentSampleType)) { 
                        // We'll put only non-base counters in the table. 
                        if (currentSampleType != NativeMethods.PERF_COUNTER_NODATA)
                            this.CounterTable[samples[index].NameIndex] = samples[index]; 
                    }
                    else {
                        // it's a base counter, try to hook it up to the main counter.
                        Debug.Assert(index > 0, "Index > 0 because base counters should never be at index 0"); 
                        if (index > 0)
                            samples[index-1].BaseCounterDefinitionSample = samples[index]; 
                    } 
                }
 
                // now set up the InstanceNameTable.
                if (!IsMultiInstance) {
                    this.InstanceNameTable = new Hashtable(1, StringComparer.OrdinalIgnoreCase);
                    this.InstanceNameTable[PerformanceCounterLib.SingleInstanceName] = 0; 

                    for (int index = 0; index < samples.Length; ++ index)  { 
                        samples[index].SetInstanceValue(0, dataRef); 
                    }
                } 
                else {
                    string[] parentInstanceNames = null;
                    this.InstanceNameTable = new Hashtable(instanceNumber, StringComparer.OrdinalIgnoreCase);
                    for (int i = 0; i < instanceNumber; i++) { 
                        NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION();
                        Marshal.PtrToStructure(dataRef, perfInstance); 
                        if (perfInstance.ParentObjectTitleIndex > 0 && parentInstanceNames == null) 
                            parentInstanceNames = GetInstanceNamesFromIndex(perfInstance.ParentObjectTitleIndex);
 
                        string instanceName;
                        if (parentInstanceNames != null && perfInstance.ParentObjectInstance >= 0 && perfInstance.ParentObjectInstance < parentInstanceNames.Length - 1)
                            instanceName = parentInstanceNames[perfInstance.ParentObjectInstance] + "/" + Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));
                        else 
                            instanceName = Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset));
 
                        //In some cases instance names are not unique (Process), same as perfmon 
                        //generate a unique name.
                        string newInstanceName = instanceName; 
                        int newInstanceNumber = 1;
                        while (true) {
                            if (!this.InstanceNameTable.ContainsKey(newInstanceName)) {
                                this.InstanceNameTable[newInstanceName] = i; 
                                break;
                            } 
                            else { 
                                newInstanceName =  instanceName + "#" + newInstanceNumber.ToString(CultureInfo.InvariantCulture);
                                ++  newInstanceNumber; 
                            }
                        }

 
                        dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength);
                        for (int index = 0; index < samples.Length; ++ index) 
                            samples[index].SetInstanceValue(i, dataRef); 

                        dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef)); 
                    }
                }
            }
        } 

        internal unsafe string[] GetInstanceNamesFromIndex(int categoryIndex) { 
            byte[] data = library.GetPerformanceData(categoryIndex.ToString(CultureInfo.InvariantCulture)); 
            fixed (byte* dataPtr = data) {
                IntPtr dataRef = new IntPtr((void*) dataPtr); 

                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK();
                Marshal.PtrToStructure(dataRef, dataBlock);
                dataRef = (IntPtr)((long)dataRef + dataBlock.HeaderLength); 
                int numPerfObjects = dataBlock.NumObjectTypes;
 
                NativeMethods.PERF_OBJECT_TYPE perfObject = null; 
                bool foundCategory = false;
                for (int index = 0; index < numPerfObjects; index++) { 
                    perfObject = new NativeMethods.PERF_OBJECT_TYPE();
                    Marshal.PtrToStructure(dataRef, perfObject);

                    if (perfObject.ObjectNameTitleIndex == categoryIndex) { 
                        foundCategory = true;
                        break; 
                    } 

                    dataRef = (IntPtr)((long)dataRef + perfObject.TotalByteLength); 
                }

                if (!foundCategory)
                    return new string[0]; 

                int counterNumber = perfObject.NumCounters; 
                int instanceNumber = perfObject.NumInstances; 
                dataRef = (IntPtr)((long)dataRef + perfObject.HeaderLength);
 
                if (instanceNumber == -1)
                    return new string[0];

                CounterDefinitionSample[] samples = new CounterDefinitionSample[counterNumber]; 
                for (int index = 0; index < samples.Length; ++ index) {
                    NativeMethods.PERF_COUNTER_DEFINITION perfCounter = new NativeMethods.PERF_COUNTER_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfCounter); 
                    dataRef = (IntPtr)((long)dataRef + perfCounter.ByteLength);
                } 

                string[] instanceNames = new string[instanceNumber];
                for (int i = 0; i < instanceNumber; i++) {
                    NativeMethods.PERF_INSTANCE_DEFINITION perfInstance = new NativeMethods.PERF_INSTANCE_DEFINITION(); 
                    Marshal.PtrToStructure(dataRef, perfInstance);
                    instanceNames[i] =  Marshal.PtrToStringUni((IntPtr)((long)dataRef + perfInstance.NameOffset)); 
                    dataRef = (IntPtr)((long)dataRef + perfInstance.ByteLength); 
                    dataRef = (IntPtr)((long)dataRef + Marshal.ReadInt32(dataRef));
                } 

                return instanceNames;
            }
        } 

        internal CounterDefinitionSample GetCounterDefinitionSample(string counter) { 
            for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];
                string counterName = (string)this.library.NameTable[counterIndex]; 
                if (counterName != null) {
                    if (String.Compare(counterName, counter, StringComparison.OrdinalIgnoreCase) == 0) {
                        CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex];
                        if (sample == null) { 
                            //This is a base counter and has not been added to the table
                            foreach (CounterDefinitionSample multiSample in this.CounterTable.Values) { 
                                if (multiSample.BaseCounterDefinitionSample != null && 
                                    multiSample.BaseCounterDefinitionSample.NameIndex == counterIndex)
                                    return multiSample.BaseCounterDefinitionSample; 
                            }

                            throw new InvalidOperationException(SR.GetString(SR.CounterLayout));
                        } 
                        return sample;
                    } 
                } 
            }
 
            throw new InvalidOperationException(SR.GetString(SR.CantReadCounter, counter));
        }

        internal InstanceDataCollectionCollection ReadCategory() { 

#pragma warning disable 618 
            InstanceDataCollectionCollection data = new InstanceDataCollectionCollection(); 
#pragma warning restore 618
            for (int index = 0; index < this.entry.CounterIndexes.Length; ++ index) { 
                int counterIndex = entry.CounterIndexes[index];

                string name = (string)library.NameTable[counterIndex];
                if (name != null && name != String.Empty) { 
                    CounterDefinitionSample sample = (CounterDefinitionSample)this.CounterTable[counterIndex];
                    if (sample != null) 
                        //If the current index refers to a counter base, 
                        //the sample will be null
                        data.Add(name, sample.ReadInstanceData(name)); 
                }
            }

            return data; 
        }
    } 
 
    internal class CounterDefinitionSample {
        internal readonly int NameIndex; 
        internal readonly int CounterType;
        internal CounterDefinitionSample BaseCounterDefinitionSample;

        private readonly int size; 
        private readonly int offset;
        private long[] instanceValues; 
        private CategorySample categorySample; 

        internal CounterDefinitionSample(NativeMethods.PERF_COUNTER_DEFINITION perfCounter, CategorySample categorySample, int instanceNumber) { 
            this.NameIndex = perfCounter.CounterNameTitleIndex;
            this.CounterType = perfCounter.CounterType;
            this.offset = perfCounter.CounterOffset;
            this.size = perfCounter.CounterSize; 
            if (instanceNumber == -1) {
                this.instanceValues = new long[1]; 
            } 
            else
                this.instanceValues = new long[instanceNumber]; 

            this.categorySample = categorySample;
        }
 
        private long ReadValue(IntPtr pointer) {
            if (this.size == 4) { 
                return (long)(uint)Marshal.ReadInt32((IntPtr)((long)pointer + this.offset)); 
            }
            else if (this.size == 8) { 
                return (long)Marshal.ReadInt64((IntPtr)((long)pointer + this.offset));
            }

            return -1; 
        }
 
        internal CounterSample GetInstanceValue(string instanceName) { 

            if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) { 
                // Our native dll truncates instance names to 128 characters.  If we can't find the instance
                // with the full name, try truncating to 128 characters.
                if (instanceName.Length > SharedPerformanceCounter.InstanceNameMaxLength)
                    instanceName = instanceName.Substring(0, SharedPerformanceCounter.InstanceNameMaxLength); 

                if (!categorySample.InstanceNameTable.ContainsKey(instanceName)) 
                    throw new InvalidOperationException(SR.GetString(SR.CantReadInstance, instanceName)); 
            }
 
            int index = (int)categorySample.InstanceNameTable[instanceName];
            long rawValue = this.instanceValues[index];
            long baseValue = 0;
            if (this.BaseCounterDefinitionSample != null) { 
                CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample;
                int baseIndex = (int)baseCategorySample.InstanceNameTable[instanceName]; 
                baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex]; 
            }
 
            return new CounterSample(rawValue,
                                                        baseValue,
                                                        categorySample.CounterFrequency,
                                                        categorySample.SystemFrequency, 
                                                        categorySample.TimeStamp,
                                                        categorySample.TimeStamp100nSec, 
                                                        (PerformanceCounterType)this.CounterType, 
                                                        categorySample.CounterTimeStamp);
 
        }

        internal InstanceDataCollection ReadInstanceData(string counterName) {
#pragma warning disable 618 
            InstanceDataCollection data = new InstanceDataCollection(counterName);
#pragma warning restore 618 
 
            string[] keys = new string[categorySample.InstanceNameTable.Count];
            categorySample.InstanceNameTable.Keys.CopyTo(keys, 0); 
            int[] indexes = new int[categorySample.InstanceNameTable.Count];
            categorySample.InstanceNameTable.Values.CopyTo(indexes, 0);
            for (int index = 0; index < keys.Length; ++ index) {
                long baseValue = 0; 
                if (this.BaseCounterDefinitionSample != null) {
                    CategorySample baseCategorySample = this.BaseCounterDefinitionSample.categorySample; 
                    int baseIndex = (int)baseCategorySample.InstanceNameTable[keys[index]]; 
                    baseValue = this.BaseCounterDefinitionSample.instanceValues[baseIndex];
                } 

                CounterSample sample = new CounterSample(this.instanceValues[indexes[index]],
                                                        baseValue,
                                                        categorySample.CounterFrequency, 
                                                        categorySample.SystemFrequency,
                                                        categorySample.TimeStamp, 
                                                        categorySample.TimeStamp100nSec, 
                                                        (PerformanceCounterType)this.CounterType,
                                                        categorySample.CounterTimeStamp); 

                data.Add(keys[index], new InstanceData(keys[index], sample));
            }
 
            return data;
        } 
 
        internal CounterSample GetSingleValue() {
            long rawValue = this.instanceValues[0]; 
            long baseValue = 0;
            if (this.BaseCounterDefinitionSample != null)
                baseValue = this.BaseCounterDefinitionSample.instanceValues[0];
 
            return new CounterSample(rawValue,
                                                        baseValue, 
                                                        categorySample.CounterFrequency, 
                                                        categorySample.SystemFrequency,
                                                        categorySample.TimeStamp, 
                                                        categorySample.TimeStamp100nSec,
                                                        (PerformanceCounterType)this.CounterType,
                                                        categorySample.CounterTimeStamp);
        } 

        internal void SetInstanceValue(int index, IntPtr dataRef) { 
            long rawValue = ReadValue(dataRef); 
            this.instanceValues[index] = rawValue;
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

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