ProcessManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / Services / Monitoring / system / Diagnosticts / ProcessManager.cs / 2 / ProcessManager.cs

                            #if !FEATURE_PAL 
namespace System.Diagnostics {
    using System.Text;
    using System.Threading;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.ComponentModel.Design; 
    using System.Diagnostics; 
    using System;
    using System.Collections; 
    using System.IO;
    using Microsoft.Win32;
    using Microsoft.Win32.SafeHandles;
    using System.Collections.Specialized; 
    using System.Globalization;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Security.Principal;
    using System.Runtime.Versioning; 

    /// 
    ///     This class finds the main window of a process.  It needs to be
    ///     class because we need to store state while searching the set 
    ///     of windows.
    ///  
    ///  
    internal class MainWindowFinder {
        IntPtr bestHandle; 
        int processId;

        public IntPtr FindMainWindow(int processId) {
            bestHandle = (IntPtr)0; 
            this.processId = processId;
 
            NativeMethods.EnumThreadWindowsCallback callback = new NativeMethods.EnumThreadWindowsCallback(this.EnumWindowsCallback); 
            NativeMethods.EnumWindows(callback, IntPtr.Zero);
 
            GC.KeepAlive(callback);
            return bestHandle;
        }
 
        bool IsMainWindow(IntPtr handle) {
 
            if (NativeMethods.GetWindow(new HandleRef(this, handle), NativeMethods.GW_OWNER) != (IntPtr)0 || !NativeMethods.IsWindowVisible(new HandleRef(this, handle))) 
                return false;
 
            // [....]: should we use no window title to mean not a main window? (task man does)

            /*
            int length = NativeMethods.GetWindowTextLength(handle) * 2; 
            StringBuilder builder = new StringBuilder(length);
            if (NativeMethods.GetWindowText(handle, builder, builder.Capacity) == 0) 
                return false; 
            if (builder.ToString() == string.Empty)
                return false; 
            */

            return true;
        } 

        bool EnumWindowsCallback(IntPtr handle, IntPtr extraParameter) { 
            int processId; 
            NativeMethods.GetWindowThreadProcessId(new HandleRef(this, handle), out processId);
            if (processId == this.processId) { 
                if (IsMainWindow(handle)) {
                    bestHandle = handle;
                    return false;
                } 
            }
            return true; 
        } 
    }
 
    /// 
    ///     This static class is a platform independent Api for querying information
    ///     about processes, threads and modules.  It delegates to the platform
    ///     specific classes WinProcessManager for Win9x and NtProcessManager 
    ///     for WinNt.
    ///  
    ///  
    internal static class ProcessManager {
 
        static ProcessManager() {
            // In order to query information (OpenProcess) on some protected processes
            // like csrss, we need SeDebugPrivilege privilege.
            // After removing the depenecy on Performance Counter, we don't have a chance 
            // to run the code in CLR performance counter to ask for this privilege.
            // So we will try to get the privilege here. 
            // We could fail if the user account doesn't have right to do this, but that's fair. 

            NativeMethods.LUID luid = new NativeMethods.LUID(); 
            if (!NativeMethods.LookupPrivilegeValue(null, "SeDebugPrivilege", out luid)) {
                return;
            }
 
            IntPtr tokenHandle = IntPtr.Zero;
            try { 
                if( !NativeMethods.OpenProcessToken( 
                        new HandleRef(null, NativeMethods.GetCurrentProcess()),
                        (int)TokenAccessLevels.AdjustPrivileges, 
                        out tokenHandle)) {
                    return;
                }
 
                NativeMethods.TokenPrivileges tp = new NativeMethods.TokenPrivileges();
                tp.PrivilegeCount = 1; 
                tp.Luid = luid; 
                tp.Attributes = NativeMethods.SE_PRIVILEGE_ENABLED;
 
                // AdjustTokenPrivileges can return true even if it didn't succeed (when ERROR_NOT_ALL_ASSIGNED is returned).
                NativeMethods.AdjustTokenPrivileges(new HandleRef(null,tokenHandle), false, tp, 0, IntPtr.Zero, IntPtr.Zero);
            }
            finally { 
                if( tokenHandle != IntPtr.Zero) {
                    SafeNativeMethods.CloseHandle(new HandleRef(null,tokenHandle)); 
                } 
            }
        } 



        public static bool IsNt { 
            get {
                return Environment.OSVersion.Platform == PlatformID.Win32NT; 
            } 
        }
 
       public static bool IsOSOlderThanXP  {
            get {
                return Environment.OSVersion.Version.Major < 5 ||
                            (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0); 
            }
       } 
 
        public static ProcessInfo[] GetProcessInfos(string machineName) {
            bool isRemoteMachine = IsRemoteMachine(machineName); 
            if (IsNt) {
                // Do not use performance counter for local machine with Win2000 and above
                if( !isRemoteMachine &&
                    (Environment.OSVersion.Version.Major >= 5 ))   { 
                    return NtProcessInfoHelper.GetProcessInfos();
                } 
                return NtProcessManager.GetProcessInfos(machineName, isRemoteMachine); 
            }
 
            else {
                if (isRemoteMachine)
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequiredForRemote));
                return WinProcessManager.GetProcessInfos(); 
            }
        } 
 
        public static int[] GetProcessIds() {
            if (IsNt) 
                return NtProcessManager.GetProcessIds();
            else {
                return WinProcessManager.GetProcessIds();
            } 
        }
 
        public static int[] GetProcessIds(string machineName) { 
            if (IsRemoteMachine(machineName)) {
                if (IsNt) { 
                    return NtProcessManager.GetProcessIds(machineName, true);
                }
                else {
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequiredForRemote)); 
                }
            } 
            else { 
                return GetProcessIds();
            } 
        }

        public static bool IsProcessRunning(int processId, string machineName) {
            return IsProcessRunning(processId, GetProcessIds(machineName)); 
        }
 
        public static bool IsProcessRunning(int processId) { 
            return IsProcessRunning(processId, GetProcessIds());
        } 

        static bool IsProcessRunning(int processId, int[] processIds) {
            for (int i = 0; i < processIds.Length; i++)
                if (processIds[i] == processId) 
                    return true;
            return false; 
        } 

        public static int GetProcessIdFromHandle(SafeProcessHandle processHandle) { 
            if (IsNt)
                return NtProcessManager.GetProcessIdFromHandle(processHandle);
            else
                throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired)); 
        }
 
        public static IntPtr GetMainWindowHandle(ProcessInfo processInfo) { 
            MainWindowFinder finder = new MainWindowFinder();
            return finder.FindMainWindow(processInfo.processId); 
        }

        public static ModuleInfo[] GetModuleInfos(int processId) {
            if (IsNt) 
                return NtProcessManager.GetModuleInfos(processId);
            else 
                return WinProcessManager.GetModuleInfos(processId); 
        }
 
        public static SafeProcessHandle OpenProcess(int processId, int access, bool throwIfExited) {
            SafeProcessHandle processHandle = NativeMethods.OpenProcess(access, false, processId);
            int result = Marshal.GetLastWin32Error();
            if (!processHandle.IsInvalid) { 
                return processHandle;
            } 
 
            if (processId == 0) {
                throw new Win32Exception(5); 
            }

            // If the handle is invalid because the process has exited, only throw an exception if throwIfExited is true.
            if (!IsProcessRunning(processId)) { 
                if (throwIfExited) {
                    throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture))); 
                } 
                else {
                    return SafeProcessHandle.InvalidHandle; 
                }
            }
            throw new Win32Exception(result);
        } 

        public static SafeThreadHandle OpenThread(int threadId, int access) { 
            try { 
                SafeThreadHandle threadHandle = NativeMethods.OpenThread(access, false, threadId);
                int result = Marshal.GetLastWin32Error(); 
                if (threadHandle.IsInvalid) {
                    if (result == NativeMethods.ERROR_INVALID_PARAMETER)
                        throw new InvalidOperationException(SR.GetString(SR.ThreadExited, threadId.ToString(CultureInfo.CurrentCulture)));
                    throw new Win32Exception(result); 
                }
                return threadHandle; 
            } 
            catch (EntryPointNotFoundException x) {
                throw new PlatformNotSupportedException(SR.GetString(SR.Win2000Required), x); 
            }
        }

 

        public static bool IsRemoteMachine(string machineName) { 
            if (machineName == null) 
                throw new ArgumentNullException("machineName");
 
            if (machineName.Length == 0)
                throw new ArgumentException(SR.GetString(SR.InvalidParameter, "machineName", machineName));

            string baseName; 

            if (machineName.StartsWith("\\", StringComparison.Ordinal)) 
                baseName = machineName.Substring(2); 
            else
                baseName = machineName; 
            if (baseName.Equals(".")) return false;

            StringBuilder sb = new StringBuilder(256);
            SafeNativeMethods.GetComputerName(sb, new int[] {sb.Capacity}); 
            string computerName = sb.ToString();
            if (String.Compare(computerName, baseName, StringComparison.OrdinalIgnoreCase) == 0) return false; 
            return true; 
        }
    } 

    /// 
    ///     This static class provides the process api for the Win9x platform.
    ///     We use the toolhelp32 api to query process, thread and module information. 
    /// 
    ///  
    internal static class WinProcessManager { 

        // This is expensive.  We should specialize getprocessinfos and only get 
        // the ids instead of getting all the info and then copying the ids out.
        public static int[] GetProcessIds() {
            ProcessInfo[] infos = GetProcessInfos();
            int[] ids = new int[infos.Length]; 
            for (int i = 0; i < infos.Length; i++) {
                ids[i] = infos[i].processId; 
            } 
            return ids;
        } 

        public static ProcessInfo[] GetProcessInfos() {
            IntPtr handle = (IntPtr)(-1);
            GCHandle bufferHandle = new GCHandle(); 
            ArrayList threadInfos = new ArrayList();
            Hashtable processInfos = new Hashtable(); 
 
            try {
                handle = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPPROCESS | NativeMethods.TH32CS_SNAPTHREAD, 0); 
                if (handle == (IntPtr)(-1)) throw new Win32Exception();
                int entrySize = (int)Marshal.SizeOf(typeof(NativeMethods.WinProcessEntry));
                int bufferSize = entrySize + NativeMethods.WinProcessEntry.sizeofFileName;
                int[] buffer = new int[bufferSize / 4]; 
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject(); 
                Marshal.WriteInt32(bufferPtr, bufferSize); 

                HandleRef handleRef = new HandleRef(null, handle); 

                if (NativeMethods.Process32First(handleRef, bufferPtr)) {
                    do {
                        NativeMethods.WinProcessEntry process = new NativeMethods.WinProcessEntry(); 
                        Marshal.PtrToStructure(bufferPtr, process);
                        ProcessInfo processInfo = new ProcessInfo(); 
                        String name = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize)); 
                        processInfo.processName = Path.ChangeExtension(Path.GetFileName(name), null);
                        processInfo.handleCount = process.cntUsage; 
                        processInfo.processId = process.th32ProcessID;
                        processInfo.basePriority = process.pcPriClassBase;
                        processInfo.mainModuleId = process.th32ModuleID;
                        processInfos.Add(processInfo.processId, processInfo); 
                        Marshal.WriteInt32(bufferPtr, bufferSize);
                    } 
                    while (NativeMethods.Process32Next(handleRef, bufferPtr)); 
                }
 
                NativeMethods.WinThreadEntry thread = new NativeMethods.WinThreadEntry();
                thread.dwSize = Marshal.SizeOf(thread);
                if (NativeMethods.Thread32First(handleRef, thread)) {
                    do { 
                        ThreadInfo threadInfo = new ThreadInfo();
                        threadInfo.threadId = thread.th32ThreadID; 
                        threadInfo.processId = thread.th32OwnerProcessID; 
                        threadInfo.basePriority = thread.tpBasePri;
                        threadInfo.currentPriority = thread.tpBasePri + thread.tpDeltaPri; 
                        threadInfos.Add(threadInfo);
                    }
                    while (NativeMethods.Thread32Next(handleRef, thread));
                } 

                for (int i = 0; i < threadInfos.Count; i++) { 
                    ThreadInfo threadInfo = (ThreadInfo)threadInfos[i]; 
                    ProcessInfo processInfo = (ProcessInfo)processInfos[threadInfo.processId];
                    if (processInfo != null) 
                        processInfo.threadInfoList.Add(threadInfo);
                    //else
                    //    throw new InvalidOperationException(SR.GetString(SR.ProcessNotFound, threadInfo.threadId.ToString(), threadInfo.processId.ToString()));
                } 
            }
            finally { 
                if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(toolhelp32 snapshot handle)");
                if (handle != (IntPtr)(-1)) SafeNativeMethods.CloseHandle(new HandleRef(null, handle)); 
            }

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0); 
            return temp;
        } 
 
        public static ModuleInfo[] GetModuleInfos(int processId) {
            IntPtr handle = (IntPtr)(-1); 
            GCHandle bufferHandle = new GCHandle();
            ArrayList moduleInfos = new ArrayList();

            try { 
                handle = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPMODULE, processId);
                if (handle == (IntPtr)(-1)) throw new Win32Exception(); 
                int entrySize = Marshal.SizeOf(typeof(NativeMethods.WinModuleEntry)); 
                int bufferSize = entrySize + NativeMethods.WinModuleEntry.sizeofFileName + NativeMethods.WinModuleEntry.sizeofModuleName;
                int[] buffer = new int[bufferSize / 4]; 
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject();
                Marshal.WriteInt32(bufferPtr, bufferSize);
 
                HandleRef handleRef = new HandleRef(null, handle);
 
                if (NativeMethods.Module32First(handleRef, bufferPtr)) { 
                    do {
                        NativeMethods.WinModuleEntry module = new NativeMethods.WinModuleEntry(); 
                        Marshal.PtrToStructure(bufferPtr, module);
                        ModuleInfo moduleInfo = new ModuleInfo();
                        moduleInfo.baseName = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize));
                        moduleInfo.fileName = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize + NativeMethods.WinModuleEntry.sizeofModuleName)); 
                        moduleInfo.baseOfDll = module.modBaseAddr;
                        moduleInfo.sizeOfImage = module.modBaseSize; 
                        moduleInfo.Id = module.th32ModuleID; 
                        moduleInfos.Add(moduleInfo);
                        Marshal.WriteInt32(bufferPtr, bufferSize); 
                    }
                    while (NativeMethods.Module32Next(handleRef, bufferPtr));
                }
            } 
            finally {
                if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(toolhelp32 snapshot handle)"); 
                if (handle != (IntPtr)(-1)) SafeNativeMethods.CloseHandle(new HandleRef(null, handle));
            } 

            ModuleInfo[] temp = new ModuleInfo[moduleInfos.Count];
            moduleInfos.CopyTo(temp, 0);
            return temp; 
        }
 
    } 

 
    /// 
    ///     This static class provides the process api for the WinNt platform.
    ///     We use the performance counter api to query process and thread
    ///     information.  Module information is obtained using PSAPI. 
    /// 
    ///  
    internal static class NtProcessManager { 
        private const int ProcessPerfCounterId = 230;
        private const int ThreadPerfCounterId = 232; 
        private const string PerfCounterQueryString = "230 232";
        internal const int IdleProcessID = 0;

        static Hashtable valueIds; 

        static NtProcessManager() { 
            valueIds = new Hashtable(); 
            valueIds.Add("Handle Count", ValueId.HandleCount);
            valueIds.Add("Pool Paged Bytes", ValueId.PoolPagedBytes); 
            valueIds.Add("Pool Nonpaged Bytes", ValueId.PoolNonpagedBytes);
            valueIds.Add("Elapsed Time", ValueId.ElapsedTime);
            valueIds.Add("Virtual Bytes Peak", ValueId.VirtualBytesPeak);
            valueIds.Add("Virtual Bytes", ValueId.VirtualBytes); 
            valueIds.Add("Private Bytes", ValueId.PrivateBytes);
            valueIds.Add("Page File Bytes", ValueId.PageFileBytes); 
            valueIds.Add("Page File Bytes Peak", ValueId.PageFileBytesPeak); 
            valueIds.Add("Working Set Peak", ValueId.WorkingSetPeak);
            valueIds.Add("Working Set", ValueId.WorkingSet); 
            valueIds.Add("ID Thread", ValueId.ThreadId);
            valueIds.Add("ID Process", ValueId.ProcessId);
            valueIds.Add("Priority Base", ValueId.BasePriority);
            valueIds.Add("Priority Current", ValueId.CurrentPriority); 
            valueIds.Add("% User Time", ValueId.UserTime);
            valueIds.Add("% Privileged Time", ValueId.PrivilegedTime); 
            valueIds.Add("Start Address", ValueId.StartAddress); 
            valueIds.Add("Thread State", ValueId.ThreadState);
            valueIds.Add("Thread Wait Reason", ValueId.ThreadWaitReason); 
        }

        internal static int SystemProcessID {
            get { 
                const int systemProcessIDOnXP = 4;
                const int systemProcessIDOn2K = 8; 
 
                if( ProcessManager.IsOSOlderThanXP) {
                    return systemProcessIDOn2K; 
                }
                else {
                    return systemProcessIDOnXP;
                } 
            }
        } 
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static int[] GetProcessIds(string machineName, bool isRemoteMachine) {
            ProcessInfo[] infos = GetProcessInfos(machineName, isRemoteMachine);
            int[] ids = new int[infos.Length];
            for (int i = 0; i < infos.Length; i++) 
                ids[i] = infos[i].processId;
            return ids; 
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static int[] GetProcessIds() {
            int[] processIds = new int[256];
            int size; 
            for (;;) {
                if (!NativeMethods.EnumProcesses(processIds, processIds.Length * 4, out size)) 
                    throw new Win32Exception(); 
                if (size == processIds.Length * 4) {
                    processIds = new int[processIds.Length * 2]; 
                    continue;
                }
                break;
            } 
            int[] ids = new int[size / 4];
            Array.Copy(processIds, ids, ids.Length); 
            return ids; 
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static ModuleInfo[] GetModuleInfos(int processId) {
            return GetModuleInfos(processId, false); 
        }
 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static ModuleInfo GetFirstModuleInfo(int processId) { 
            ModuleInfo[] moduleInfos = GetModuleInfos(processId, true);
            if( moduleInfos.Length == 0) {
                return null;
            } 
            else {
                return moduleInfos[0]; 
            } 
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        private static ModuleInfo[] GetModuleInfos(int processId, bool firstModuleOnly) {
            // preserving Everett behavior. 
            if( processId == SystemProcessID || processId == IdleProcessID) {
                // system process and idle process doesn't have any modules 
                throw new Win32Exception(HResults.EFail,SR.GetString(SR.EnumProcessModuleFailed)); 
            }
 
            SafeProcessHandle processHandle = SafeProcessHandle.InvalidHandle;
            try {
                processHandle = ProcessManager.OpenProcess(processId, NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_VM_READ, true);
                IntPtr[] moduleHandles = new IntPtr[64]; 
                GCHandle moduleHandlesArrayHandle = new GCHandle();
                int moduleCount = 0; 
                for (;;) { 
                    bool enumResult = false;
                    try { 
                        moduleHandlesArrayHandle = GCHandle.Alloc(moduleHandles, GCHandleType.Pinned);
                        //
                        // EnumProcessModules is not a reliable method to get the modules for a process.
                        // If OS loader is touching module information, this method might fail and copy part of the data. 
                        // This is no easy solution to this problem. The only reliable way to fix this is to
                        // suspend all the threads in target process. Of course we don't want to do this in Process class. 
                        // So we just to try avoid the ---- by calling the same method 10 (an arbitary number) times. 
                        //
                        for( int i = 0; i < 10; i++) { 
                            enumResult = NativeMethods.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);
                            if( enumResult) {
                                break;
                            } 
                            Thread.Sleep(1);
                        } 
                    } 
                    finally {
                        moduleHandlesArrayHandle.Free(); 
                    }

                    if (!enumResult) {
                        throw new Win32Exception(); 
                    }
 
                    moduleCount /= IntPtr.Size; 
                    if (moduleCount <= moduleHandles.Length) break;
                    moduleHandles = new IntPtr[moduleHandles.Length * 2]; 
                }
                ArrayList moduleInfos = new ArrayList();

                int ret; 
                for (int i = 0; i < moduleCount; i++) {
                    ModuleInfo moduleInfo = new ModuleInfo(); 
                    IntPtr moduleHandle = moduleHandles[i]; 
                    NativeMethods.NtModuleInfo ntModuleInfo = new NativeMethods.NtModuleInfo();
                    if (!NativeMethods.GetModuleInformation(processHandle, new HandleRef(null, moduleHandle), ntModuleInfo, Marshal.SizeOf(ntModuleInfo))) 
                        throw new Win32Exception();
                    moduleInfo.sizeOfImage = ntModuleInfo.SizeOfImage;
                    moduleInfo.entryPoint = ntModuleInfo.EntryPoint;
                    moduleInfo.baseOfDll = ntModuleInfo.BaseOfDll; 

                    StringBuilder baseName = new StringBuilder(1024); 
                    ret = NativeMethods.GetModuleBaseName(processHandle, new HandleRef(null, moduleHandle), baseName, baseName.Capacity * 2); 
                    if (ret == 0) throw new Win32Exception();
                    moduleInfo.baseName = baseName.ToString(); 

                    StringBuilder fileName = new StringBuilder(1024);
                    ret = NativeMethods.GetModuleFileNameEx(processHandle, new HandleRef(null, moduleHandle), fileName, fileName.Capacity * 2);
                    if (ret == 0) throw new Win32Exception(); 
                    moduleInfo.fileName = fileName.ToString();
 
                    // smss.exe is started before the win32 subsystem so it get this funny "\systemroot\.." path. 
                    // We change this to the actual path by appending "smss.exe" to GetSystemDirectory()
                    if (string.Compare(moduleInfo.fileName, "\\SystemRoot\\System32\\smss.exe", StringComparison.OrdinalIgnoreCase) == 0) { 
                        moduleInfo.fileName = Path.Combine(Environment.SystemDirectory, "smss.exe");
                    }
                    // Avoid returning Unicode-style long string paths.  IO methods cannot handle them.
                    if (moduleInfo.fileName != null 
                        && moduleInfo.fileName.Length >= 4
                        && moduleInfo.fileName.StartsWith(@"\\?\", StringComparison.Ordinal)) { 
 
                            moduleInfo.fileName = moduleInfo.fileName.Substring(4);
                    } 

                    moduleInfos.Add(moduleInfo);
                    //
                    // If the user is only interested in the main module, break now. 
                    // This avoid some waste of time. In addition, if the application unloads a DLL
                    // we will not get an exception. 
                    // 
                    if( firstModuleOnly) { break; }
                } 
                ModuleInfo[] temp = new ModuleInfo[moduleInfos.Count];
                moduleInfos.CopyTo(temp, 0);
                return temp;
            } 
            finally {
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(process)"); 
                if (!processHandle.IsInvalid ) { 
                    processHandle.Close();
                } 
            }
        }

        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static int GetProcessIdFromHandle(SafeProcessHandle processHandle) { 
            NativeMethods.NtProcessBasicInfo info = new NativeMethods.NtProcessBasicInfo(); 
            int status = NativeMethods.NtQueryInformationProcess(processHandle, NativeMethods.NtQueryProcessBasicInfo, info, (int)Marshal.SizeOf(info), null);
            if (status != 0) { 
                throw new InvalidOperationException(SR.GetString(SR.CantGetProcessId), new Win32Exception(status));
            }
            // We should change the signature of this function and ID property in process class.
            return info.UniqueProcessId.ToInt32(); 
        }
 
        public static ProcessInfo[] GetProcessInfos(string machineName, bool isRemoteMachine) { 
            // We demand unmanaged code here because PerformanceCounterLib doesn't demand
            // anything.  This is the only place we do GetPerformanceCounterLib, and it isn't cached. 
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
            PerformanceCounterLib library = null;
            try {
                library = PerformanceCounterLib.GetPerformanceCounterLib(machineName, new CultureInfo(0x009)); 
                return GetProcessInfos(library);
            } 
            catch(Exception e) { 
                if( isRemoteMachine) {
                    throw new InvalidOperationException(SR.GetString(SR.CouldntConnectToRemoteMachine), e); 
                }
                else {
                    throw e;
                } 
            }
            catch { 
                if(isRemoteMachine) { 
                    throw new InvalidOperationException(SR.GetString(SR.CouldntConnectToRemoteMachine));
                } 
                else {
                    throw;
                }
            } 
            // We don't want to call library.Close() here because that would cause us to unload all of the perflibs.
            // On the next call to GetProcessInfos, we'd have to load them all up again, which is SLOW! 
        } 

        static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library) { 
            ProcessInfo[] processInfos = new ProcessInfo[0] ;
            byte[] dataPtr = null;

            int retryCount = 5; 
            while (processInfos.Length == 0 && retryCount != 0) {
                try { 
                    dataPtr = library.GetPerformanceData(PerfCounterQueryString); 
                    processInfos = GetProcessInfos(library, ProcessPerfCounterId, ThreadPerfCounterId, dataPtr);
                } 
                catch (Exception e) {
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos), e);
                }
                catch { 
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos));
                } 
 
                --retryCount;
            } 

            if (processInfos.Length == 0)
                throw new InvalidOperationException(SR.GetString(SR.ProcessDisabled));
 
            return processInfos;
 
        } 

        unsafe static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library, int processIndex, int threadIndex, byte[] data) { 
            Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos()");
            Hashtable processInfos = new Hashtable();
            ArrayList threadInfos = new ArrayList();
 
            fixed (byte* dataPtr = data) {
                IntPtr dataBlockPtr = new IntPtr( (void*) dataPtr); 
                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK(); 
                Marshal.PtrToStructure(dataBlockPtr, dataBlock);
                IntPtr typePtr = (IntPtr)((long)dataBlockPtr + dataBlock.HeaderLength); 
                NativeMethods.PERF_INSTANCE_DEFINITION instance = new NativeMethods.PERF_INSTANCE_DEFINITION();
                NativeMethods.PERF_COUNTER_BLOCK counterBlock = new NativeMethods.PERF_COUNTER_BLOCK();
                for (int i = 0; i < dataBlock.NumObjectTypes; i++) {
                    NativeMethods.PERF_OBJECT_TYPE type = new NativeMethods.PERF_OBJECT_TYPE(); 
                    Marshal.PtrToStructure(typePtr, type);
                    IntPtr instancePtr = (IntPtr)((long)typePtr + type.DefinitionLength); 
                    IntPtr counterPtr = (IntPtr)((long)typePtr + type.HeaderLength); 
                    ArrayList counterList = new ArrayList();
 
                    for (int j = 0; j < type.NumCounters; j++) {
                        NativeMethods.PERF_COUNTER_DEFINITION counter = new NativeMethods.PERF_COUNTER_DEFINITION();
                        Marshal.PtrToStructure(counterPtr, counter);
                        string counterName = library.GetCounterName(counter.CounterNameTitleIndex); 

                        if (type.ObjectNameTitleIndex == processIndex) 
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName); 
                        else if (type.ObjectNameTitleIndex == threadIndex)
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName); 
                        counterList.Add(counter);
                        counterPtr = (IntPtr)((long)counterPtr + counter.ByteLength);
                    }
                    NativeMethods.PERF_COUNTER_DEFINITION[] counters = new NativeMethods.PERF_COUNTER_DEFINITION[counterList.Count]; 
                    counterList.CopyTo(counters, 0);
                    for (int j = 0; j < type.NumInstances; j++) { 
                        Marshal.PtrToStructure(instancePtr, instance); 
                        IntPtr namePtr = (IntPtr)((long)instancePtr + instance.NameOffset);
                        string instanceName = Marshal.PtrToStringUni(namePtr); 
                        if (instanceName.Equals("_Total")) continue;
                        IntPtr counterBlockPtr = (IntPtr)((long)instancePtr + instance.ByteLength);
                        Marshal.PtrToStructure(counterBlockPtr, counterBlock);
                        if (type.ObjectNameTitleIndex == processIndex) { 
                            ProcessInfo processInfo = GetProcessInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (processInfo.processId == 0 && string.Compare(instanceName, "Idle", StringComparison.OrdinalIgnoreCase) != 0) { 
                                // Sometimes we'll get a process structure that is not completely filled in. 
                                // We can catch some of these by looking for non-"idle" processes that have id 0
                                // and ignoring those. 
                                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos() - found a non-idle process with id 0; ignoring.");
                            }
                            else {
                                if (processInfos[processInfo.processId] != null) { 
                                    // We've found two entries in the perfcounters that claim to be the
                                    // same process.  We throw an exception.  Is this really going to be 
                                    // helpfull to the user?  Should we just ignore? 
                                    Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos() - found a duplicate process id");
                                } 
                                else {
                                    // the performance counters keep a 15 character prefix of the exe name, and then delete the ".exe",
                                    // if it's in the first 15.  The problem is that sometimes that will leave us with part of ".exe"
                                    // at the end.  If instanceName ends in ".", ".e", or ".ex" we remove it. 
                                    string processName = instanceName;
                                    if (processName.Length == 15) { 
                                        if      (instanceName.EndsWith(".", StringComparison.Ordinal  )) processName = instanceName.Substring(0, 14); 
                                        else if (instanceName.EndsWith(".e", StringComparison.Ordinal )) processName = instanceName.Substring(0, 13);
                                        else if (instanceName.EndsWith(".ex", StringComparison.Ordinal)) processName = instanceName.Substring(0, 12); 
                                    }
                                    processInfo.processName = processName;
                                    processInfos.Add(processInfo.processId, processInfo);
                                } 
                            }
                        } 
                        else if (type.ObjectNameTitleIndex == threadIndex) { 
                            ThreadInfo threadInfo = GetThreadInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (threadInfo.threadId != 0) threadInfos.Add(threadInfo); 
                        }
                        instancePtr = (IntPtr)((long)instancePtr + instance.ByteLength + counterBlock.ByteLength);
                    }
 
                    typePtr = (IntPtr)((long)typePtr + type.TotalByteLength);
                } 
            } 

            for (int i = 0; i < threadInfos.Count; i++) { 
                ThreadInfo threadInfo = (ThreadInfo)threadInfos[i];
                ProcessInfo processInfo = (ProcessInfo)processInfos[threadInfo.processId];
                if (processInfo != null) {
                    processInfo.threadInfoList.Add(threadInfo); 
                }
                //else { 
                //    throw new InvalidOperationException(SR.GetString(SR.ProcessNotFound, threadInfo.threadId.ToString(), threadInfo.processId.ToString())); 
                //}
            } 

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return temp; 
        }
 
        static ThreadInfo GetThreadInfo(NativeMethods.PERF_OBJECT_TYPE type, IntPtr instancePtr, NativeMethods.PERF_COUNTER_DEFINITION[] counters) { 
            ThreadInfo threadInfo = new ThreadInfo();
            for (int i = 0; i < counters.Length; i++) { 
                NativeMethods.PERF_COUNTER_DEFINITION counter = counters[i];
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset));
                switch ((ValueId)counter.CounterNameTitlePtr) {
                    case ValueId.ProcessId: 
                        threadInfo.processId = (int)value;
                        break; 
                    case ValueId.ThreadId: 
                        threadInfo.threadId = (int)value;
                        break; 
                    case ValueId.BasePriority:
                        threadInfo.basePriority = (int)value;
                        break;
                    case ValueId.CurrentPriority: 
                        threadInfo.currentPriority = (int)value;
                        break; 
                    case ValueId.StartAddress: 
                        threadInfo.startAddress = (IntPtr)value;
                        break; 
                    case ValueId.ThreadState:
                        threadInfo.threadState = (ThreadState)value;
                        break;
                    case ValueId.ThreadWaitReason: 
                        threadInfo.threadWaitReason = GetThreadWaitReason((int)value);
                        break; 
                } 
            }
 
            return threadInfo;
        }

        internal static ThreadWaitReason GetThreadWaitReason(int value) { 
            switch (value) {
                case 0: 
                case 7: return ThreadWaitReason.Executive; 
                case 1:
                case 8: return ThreadWaitReason.FreePage; 
                case 2:
                case 9: return ThreadWaitReason.PageIn;
                case 3:
                case 10: return ThreadWaitReason.SystemAllocation; 
                case 4:
                case 11: return ThreadWaitReason.ExecutionDelay; 
                case 5: 
                case 12: return ThreadWaitReason.Suspended;
                case 6: 
                case 13: return ThreadWaitReason.UserRequest;
                case 14: return ThreadWaitReason.EventPairHigh;;
                case 15: return ThreadWaitReason.EventPairLow;
                case 16: return ThreadWaitReason.LpcReceive; 
                case 17: return ThreadWaitReason.LpcReply;
                case 18: return ThreadWaitReason.VirtualMemory; 
                case 19: return ThreadWaitReason.PageOut; 
                default: return ThreadWaitReason.Unknown;
            } 
        }

        static ProcessInfo GetProcessInfo(NativeMethods.PERF_OBJECT_TYPE type, IntPtr instancePtr, NativeMethods.PERF_COUNTER_DEFINITION[] counters) {
            ProcessInfo processInfo = new ProcessInfo(); 
            for (int i = 0; i < counters.Length; i++) {
                NativeMethods.PERF_COUNTER_DEFINITION counter = counters[i]; 
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset)); 
                switch ((ValueId)counter.CounterNameTitlePtr) {
                    case ValueId.ProcessId: 
                        processInfo.processId = (int)value;
                        break;
                    case ValueId.HandleCount:
                        processInfo.handleCount = (int)value; 
                        break;
                    case ValueId.PoolPagedBytes: 
                        processInfo.poolPagedBytes = (int)value; 
                        break;
                    case ValueId.PoolNonpagedBytes: 
                        processInfo.poolNonpagedBytes = (int)value;
                        break;
                    case ValueId.VirtualBytes:
                        processInfo.virtualBytes = (int)value; 
                        break;
                    case ValueId.VirtualBytesPeak: 
                        processInfo.virtualBytesPeak = (int)value; 
                        break;
                    case ValueId.WorkingSetPeak: 
                        processInfo.workingSetPeak = (int)value;
                        break;
                    case ValueId.WorkingSet:
                        processInfo.workingSet = (int)value; 
                        break;
                    case ValueId.PageFileBytesPeak: 
                        processInfo.pageFileBytesPeak = (int)value; 
                        break;
                    case ValueId.PageFileBytes: 
                        processInfo.pageFileBytes = (int)value;
                        break;
                    case ValueId.PrivateBytes:
                        processInfo.privateBytes = (int)value; 
                        break;
                    case ValueId.BasePriority: 
                        processInfo.basePriority = (int)value; 
                        break;
                } 
            }
            return processInfo;
        }
 
        static ValueId GetValueId(string counterName) {
            if (counterName != null) { 
                object id = valueIds[counterName]; 
                if (id != null)
                    return(ValueId)id; 
            }
            return ValueId.Unknown;
        }
 
        static long ReadCounterValue(int counterType, IntPtr dataPtr) {
            if ((counterType & NativeMethods.NtPerfCounterSizeLarge) != 0) 
                return Marshal.ReadInt64(dataPtr); 
            else
                return(long)Marshal.ReadInt32(dataPtr); 
        }

        enum ValueId {
            Unknown = -1, 
            HandleCount,
            PoolPagedBytes, 
            PoolNonpagedBytes, 
            ElapsedTime,
            VirtualBytesPeak, 
            VirtualBytes,
            PrivateBytes,
            PageFileBytes,
            PageFileBytesPeak, 
            WorkingSetPeak,
            WorkingSet, 
            ThreadId, 
            ProcessId,
            BasePriority, 
            CurrentPriority,
            UserTime,
            PrivilegedTime,
            StartAddress, 
            ThreadState,
            ThreadWaitReason 
        } 
    }
 
    internal static class NtProcessInfoHelper {
        private static int GetNewBufferSize(int existingBufferSize, int requiredSize) {
            if( requiredSize == 0) {
                // 
                // On some old OS like win2000, requiredSize will not be set if the buffer
                // passed to NtQuerySystemInformation is not enough. 
                // 
                int newSize = existingBufferSize * 2;
                if ( newSize < existingBufferSize ) { 
                    // In reality, we should never overflow.
                    // Adding the code here just in case it happens.
                    throw new OutOfMemoryException();
                } 
                return newSize;
            } 
            else { 
                // allocating a few more kilo bytes just in case there are some new process
                // kicked in since new call to NtQuerySystemInformation 
                return requiredSize + 1024 * 10;
            }
        }
 
        #pragma warning disable 169
        public static ProcessInfo[] GetProcessInfos() { 
            // On a normal machine, 30k to 40K will be enough. 
            // We use 128K here to tolerate mutilple connections to a machine.
            int bufferSize = 128 * 1024; 
#if DEBUG
            // on debug build, use a smaller buffer size to make sure we hit the retrying code path
           bufferSize = 1024;
#endif 
            int requiredSize = 0;
            int status; 
 
            ProcessInfo[] processInfos;
            GCHandle bufferHandle = new GCHandle(); 

            try {
                // Retry until we get all the data
                do { 
                    Byte[] buffer = new Byte[bufferSize];
                    bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
 
                    status = NativeMethods.NtQuerySystemInformation(
                        NativeMethods.NtQuerySystemProcessInformation, 
                        bufferHandle.AddrOfPinnedObject(),
                        bufferSize,
                        out requiredSize);
 
                    if ((uint)status == NativeMethods.STATUS_INFO_LENGTH_MISMATCH) {
                        if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                        bufferSize = GetNewBufferSize(bufferSize, requiredSize); 
                    }
                } while ((uint)status == NativeMethods.STATUS_INFO_LENGTH_MISMATCH); 

                if (status < 0) { // see definition of NT_SUCCESS(Status) in SDK
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos), new Win32Exception(status));
                } 

                // Parse the data block to get process information 
                processInfos = GetProcessInfos(bufferHandle.AddrOfPinnedObject()); 
            }
            finally { 
                if (bufferHandle.IsAllocated) bufferHandle.Free();
            }
            return processInfos;
        } 

        unsafe static ProcessInfo[] GetProcessInfos(IntPtr dataPtr) { 
            // 60 is a reasonable number for processes on a normal machine. 
            Hashtable processInfos = new Hashtable(60);
 
            long totalOffset = 0;

            while(true) {
                IntPtr currentPtr = (IntPtr)((long)dataPtr + totalOffset); 
                SystemProcessInformation pi = new SystemProcessInformation();
 
                Marshal.PtrToStructure(currentPtr, pi); 

                // get information for a process 
                ProcessInfo processInfo = new ProcessInfo();
                // Process ID shouldn't overflow. OS API GetCurrentProcessID returns DWORD.
                processInfo.processId = pi.UniqueProcessId.ToInt32();
                processInfo.handleCount = (int)pi.HandleCount; 
                processInfo.sessionId = (int)pi.SessionId;
                processInfo.poolPagedBytes = (long)pi.QuotaPagedPoolUsage;; 
                processInfo.poolNonpagedBytes = (long)pi.QuotaNonPagedPoolUsage; 
                processInfo.virtualBytes = (long)pi.VirtualSize;
                processInfo.virtualBytesPeak = (long)pi.PeakVirtualSize; 
                processInfo.workingSetPeak = (long)pi.PeakWorkingSetSize;
                processInfo.workingSet = (long)pi.WorkingSetSize;
                processInfo.pageFileBytesPeak = (long)pi.PeakPagefileUsage;
                processInfo.pageFileBytes = (long)pi.PagefileUsage; 
                processInfo.privateBytes = (long)pi.PrivatePageCount;
                processInfo.basePriority = pi.BasePriority; 
 

                if( pi.NamePtr == IntPtr.Zero) { 
                    if( processInfo.processId == NtProcessManager.SystemProcessID) {
                        processInfo.processName = "System";
                    }
                    else if( processInfo.processId == NtProcessManager.IdleProcessID) { 
                        processInfo.processName = "Idle";
                    } 
                    else { 
                        // for normal process without name, using the process ID.
                        processInfo.processName = processInfo.processId.ToString(CultureInfo.InvariantCulture); 
                    }
                }
                else {
                    string processName = GetProcessShortName((char *)pi.NamePtr.ToPointer(), pi.NameLength/2); 
                    //
                    // On old operating system (NT4 and windows 2000), the process name might be truncated to 15 
                    // characters. For example, aspnet_admin.exe will show up in performance counter as aspnet_admin.ex. 
                    // Process class try to return a nicer name. We used to get the main module name for a process and
                    // use that as the process name. However normal user doesn't have access to module information, 
                    // so normal user will see an exception when we try to get a truncated process name.
                    //
                    if (ProcessManager.IsOSOlderThanXP && (processName.Length == 15)) {
                        if (processName.EndsWith(".", StringComparison.OrdinalIgnoreCase)) { 
                            processName = processName.Substring(0, 14);
                        } 
                        else if (processName.EndsWith(".e", StringComparison.OrdinalIgnoreCase)) { 
                            processName = processName.Substring(0, 13);
                        } 
                        else if (processName.EndsWith(".ex", StringComparison.OrdinalIgnoreCase)) {
                            processName = processName.Substring(0, 12);
                        }
                    } 
                    processInfo.processName = processName;
                } 
 
                // get the threads for current process
                processInfos[processInfo.processId] =  processInfo; 

                currentPtr = (IntPtr)((long)currentPtr + Marshal.SizeOf(pi));
                int i = 0;
                while( i < pi.NumberOfThreads) { 
                    SystemThreadInformation ti = new SystemThreadInformation();
                    Marshal.PtrToStructure(currentPtr, ti); 
                    ThreadInfo threadInfo = new ThreadInfo(); 

                    threadInfo.processId = (int)ti.UniqueProcess; 
                    threadInfo.threadId = (int)ti.UniqueThread;
                    threadInfo.basePriority = ti.BasePriority;
                    threadInfo.currentPriority = ti.Priority;
                    threadInfo.startAddress = ti.StartAddress; 
                    threadInfo.threadState = (ThreadState)ti.ThreadState;
                    threadInfo.threadWaitReason = NtProcessManager.GetThreadWaitReason((int)ti.WaitReason); 
 
                    processInfo.threadInfoList.Add(threadInfo);
                    currentPtr = (IntPtr)((long)currentPtr + Marshal.SizeOf(ti)); 
                    i++;
                }

                if (pi.NextEntryOffset == 0) { 
                    break;
                } 
                totalOffset += pi.NextEntryOffset; 
            }
 
            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return temp;
        } 

        // This function generates the short form of process name. 
        // 
        // This is from GetProcessShortName in NT code base.
        // Check base\screg\winreg\perfdlls\process\perfsprc.c for details. 
        internal unsafe static string GetProcessShortName(char* name, int length)  {
            char* pSlash = name;
            char* pPeriod = name;
            char* pThisChar = name; 
            int wThisChar = 0;
 
            while (*pThisChar != 0) { // go until null 
                if (*pThisChar == '\\') {
                    pSlash = pThisChar; 
                } else if (*pThisChar == '.') {
                    pPeriod = pThisChar;
                }
                pThisChar++;    // point to next char 
                wThisChar++;
                if (wThisChar >= length) { 
                    break; 
                }
            } 

            // if pPeriod is still pointing to the beginning of the
            // string, then no period was found
 
            if (pPeriod == name) {
                pPeriod = pThisChar; // set to end of string; 
            } else { 
                // if a period was found, then see if the extension is
                // .EXE, if so drop it, if not, then use end of string 
                // (i.e. include extension in name)
                String extension = new String(pPeriod);

                if(!String.Equals(".exe", extension, StringComparison.OrdinalIgnoreCase) ) { 
                    pPeriod = pThisChar;
                } 
            } 

            if (*pSlash == '\\') { // if pSlash is pointing to a slash, then 
                pSlash++;   // point to character next to slash
            }

            // copy characters between period (or end of string) and 
            // slash (or start of string) to make image name
            int wStringSize = (int)(pPeriod - pSlash); // size in bytes 
            return new String(pSlash, 0, wStringSize); 
        }
 

        [StructLayout(LayoutKind.Sequential)]
        internal class SystemProcessInformation {
            internal int NextEntryOffset; 
            internal uint NumberOfThreads;
            long SpareLi1; 
            long SpareLi2; 
            long SpareLi3;
            long CreateTime; 
            long UserTime;
            long KernelTime;

            internal ushort NameLength;   // UNICODE_STRING 
            internal ushort MaximumNameLength;
            internal IntPtr NamePtr;     // This will point into the data block returned by NtQuerySystemInformation 
 
            internal int BasePriority;
            internal IntPtr UniqueProcessId; 
            internal IntPtr InheritedFromUniqueProcessId;
            internal uint HandleCount;
            internal uint SessionId;
            internal IntPtr PageDirectoryBase; 
            internal IntPtr PeakVirtualSize;
            internal IntPtr VirtualSize; 
            internal uint   PageFaultCount; 

            internal IntPtr PeakWorkingSetSize; 
            internal IntPtr WorkingSetSize;
            internal IntPtr QuotaPeakPagedPoolUsage;
            internal IntPtr QuotaPagedPoolUsage;
            internal IntPtr QuotaPeakNonPagedPoolUsage; 
            internal IntPtr QuotaNonPagedPoolUsage;
            internal IntPtr PagefileUsage; 
            internal IntPtr PeakPagefileUsage; 
            internal IntPtr PrivatePageCount;
 
            long ReadOperationCount;
            long WriteOperationCount;
            long OtherOperationCount;
            long ReadTransferCount; 
            long WriteTransferCount;
            long OtherTransferCount; 
        } 

        [StructLayout(LayoutKind.Sequential)] 
        internal class SystemThreadInformation {
            long KernelTime;
            long UserTime;
            long CreateTime; 

            uint WaitTime; 
            internal IntPtr StartAddress; 
            internal IntPtr UniqueProcess;
            internal IntPtr UniqueThread; 
            internal int Priority;
            internal int BasePriority;
            internal uint ContextSwitches;
            internal uint ThreadState; 
            internal uint WaitReason;
        } 
        #pragma warning restore 169 
    }
} 
#endif // !FEATURE_PAL

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
#if !FEATURE_PAL 
namespace System.Diagnostics {
    using System.Text;
    using System.Threading;
    using System.Runtime.InteropServices; 
    using System.ComponentModel;
    using System.ComponentModel.Design; 
    using System.Diagnostics; 
    using System;
    using System.Collections; 
    using System.IO;
    using Microsoft.Win32;
    using Microsoft.Win32.SafeHandles;
    using System.Collections.Specialized; 
    using System.Globalization;
    using System.Security; 
    using System.Security.Permissions; 
    using System.Security.Principal;
    using System.Runtime.Versioning; 

    /// 
    ///     This class finds the main window of a process.  It needs to be
    ///     class because we need to store state while searching the set 
    ///     of windows.
    ///  
    ///  
    internal class MainWindowFinder {
        IntPtr bestHandle; 
        int processId;

        public IntPtr FindMainWindow(int processId) {
            bestHandle = (IntPtr)0; 
            this.processId = processId;
 
            NativeMethods.EnumThreadWindowsCallback callback = new NativeMethods.EnumThreadWindowsCallback(this.EnumWindowsCallback); 
            NativeMethods.EnumWindows(callback, IntPtr.Zero);
 
            GC.KeepAlive(callback);
            return bestHandle;
        }
 
        bool IsMainWindow(IntPtr handle) {
 
            if (NativeMethods.GetWindow(new HandleRef(this, handle), NativeMethods.GW_OWNER) != (IntPtr)0 || !NativeMethods.IsWindowVisible(new HandleRef(this, handle))) 
                return false;
 
            // [....]: should we use no window title to mean not a main window? (task man does)

            /*
            int length = NativeMethods.GetWindowTextLength(handle) * 2; 
            StringBuilder builder = new StringBuilder(length);
            if (NativeMethods.GetWindowText(handle, builder, builder.Capacity) == 0) 
                return false; 
            if (builder.ToString() == string.Empty)
                return false; 
            */

            return true;
        } 

        bool EnumWindowsCallback(IntPtr handle, IntPtr extraParameter) { 
            int processId; 
            NativeMethods.GetWindowThreadProcessId(new HandleRef(this, handle), out processId);
            if (processId == this.processId) { 
                if (IsMainWindow(handle)) {
                    bestHandle = handle;
                    return false;
                } 
            }
            return true; 
        } 
    }
 
    /// 
    ///     This static class is a platform independent Api for querying information
    ///     about processes, threads and modules.  It delegates to the platform
    ///     specific classes WinProcessManager for Win9x and NtProcessManager 
    ///     for WinNt.
    ///  
    ///  
    internal static class ProcessManager {
 
        static ProcessManager() {
            // In order to query information (OpenProcess) on some protected processes
            // like csrss, we need SeDebugPrivilege privilege.
            // After removing the depenecy on Performance Counter, we don't have a chance 
            // to run the code in CLR performance counter to ask for this privilege.
            // So we will try to get the privilege here. 
            // We could fail if the user account doesn't have right to do this, but that's fair. 

            NativeMethods.LUID luid = new NativeMethods.LUID(); 
            if (!NativeMethods.LookupPrivilegeValue(null, "SeDebugPrivilege", out luid)) {
                return;
            }
 
            IntPtr tokenHandle = IntPtr.Zero;
            try { 
                if( !NativeMethods.OpenProcessToken( 
                        new HandleRef(null, NativeMethods.GetCurrentProcess()),
                        (int)TokenAccessLevels.AdjustPrivileges, 
                        out tokenHandle)) {
                    return;
                }
 
                NativeMethods.TokenPrivileges tp = new NativeMethods.TokenPrivileges();
                tp.PrivilegeCount = 1; 
                tp.Luid = luid; 
                tp.Attributes = NativeMethods.SE_PRIVILEGE_ENABLED;
 
                // AdjustTokenPrivileges can return true even if it didn't succeed (when ERROR_NOT_ALL_ASSIGNED is returned).
                NativeMethods.AdjustTokenPrivileges(new HandleRef(null,tokenHandle), false, tp, 0, IntPtr.Zero, IntPtr.Zero);
            }
            finally { 
                if( tokenHandle != IntPtr.Zero) {
                    SafeNativeMethods.CloseHandle(new HandleRef(null,tokenHandle)); 
                } 
            }
        } 



        public static bool IsNt { 
            get {
                return Environment.OSVersion.Platform == PlatformID.Win32NT; 
            } 
        }
 
       public static bool IsOSOlderThanXP  {
            get {
                return Environment.OSVersion.Version.Major < 5 ||
                            (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 0); 
            }
       } 
 
        public static ProcessInfo[] GetProcessInfos(string machineName) {
            bool isRemoteMachine = IsRemoteMachine(machineName); 
            if (IsNt) {
                // Do not use performance counter for local machine with Win2000 and above
                if( !isRemoteMachine &&
                    (Environment.OSVersion.Version.Major >= 5 ))   { 
                    return NtProcessInfoHelper.GetProcessInfos();
                } 
                return NtProcessManager.GetProcessInfos(machineName, isRemoteMachine); 
            }
 
            else {
                if (isRemoteMachine)
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequiredForRemote));
                return WinProcessManager.GetProcessInfos(); 
            }
        } 
 
        public static int[] GetProcessIds() {
            if (IsNt) 
                return NtProcessManager.GetProcessIds();
            else {
                return WinProcessManager.GetProcessIds();
            } 
        }
 
        public static int[] GetProcessIds(string machineName) { 
            if (IsRemoteMachine(machineName)) {
                if (IsNt) { 
                    return NtProcessManager.GetProcessIds(machineName, true);
                }
                else {
                    throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequiredForRemote)); 
                }
            } 
            else { 
                return GetProcessIds();
            } 
        }

        public static bool IsProcessRunning(int processId, string machineName) {
            return IsProcessRunning(processId, GetProcessIds(machineName)); 
        }
 
        public static bool IsProcessRunning(int processId) { 
            return IsProcessRunning(processId, GetProcessIds());
        } 

        static bool IsProcessRunning(int processId, int[] processIds) {
            for (int i = 0; i < processIds.Length; i++)
                if (processIds[i] == processId) 
                    return true;
            return false; 
        } 

        public static int GetProcessIdFromHandle(SafeProcessHandle processHandle) { 
            if (IsNt)
                return NtProcessManager.GetProcessIdFromHandle(processHandle);
            else
                throw new PlatformNotSupportedException(SR.GetString(SR.WinNTRequired)); 
        }
 
        public static IntPtr GetMainWindowHandle(ProcessInfo processInfo) { 
            MainWindowFinder finder = new MainWindowFinder();
            return finder.FindMainWindow(processInfo.processId); 
        }

        public static ModuleInfo[] GetModuleInfos(int processId) {
            if (IsNt) 
                return NtProcessManager.GetModuleInfos(processId);
            else 
                return WinProcessManager.GetModuleInfos(processId); 
        }
 
        public static SafeProcessHandle OpenProcess(int processId, int access, bool throwIfExited) {
            SafeProcessHandle processHandle = NativeMethods.OpenProcess(access, false, processId);
            int result = Marshal.GetLastWin32Error();
            if (!processHandle.IsInvalid) { 
                return processHandle;
            } 
 
            if (processId == 0) {
                throw new Win32Exception(5); 
            }

            // If the handle is invalid because the process has exited, only throw an exception if throwIfExited is true.
            if (!IsProcessRunning(processId)) { 
                if (throwIfExited) {
                    throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture))); 
                } 
                else {
                    return SafeProcessHandle.InvalidHandle; 
                }
            }
            throw new Win32Exception(result);
        } 

        public static SafeThreadHandle OpenThread(int threadId, int access) { 
            try { 
                SafeThreadHandle threadHandle = NativeMethods.OpenThread(access, false, threadId);
                int result = Marshal.GetLastWin32Error(); 
                if (threadHandle.IsInvalid) {
                    if (result == NativeMethods.ERROR_INVALID_PARAMETER)
                        throw new InvalidOperationException(SR.GetString(SR.ThreadExited, threadId.ToString(CultureInfo.CurrentCulture)));
                    throw new Win32Exception(result); 
                }
                return threadHandle; 
            } 
            catch (EntryPointNotFoundException x) {
                throw new PlatformNotSupportedException(SR.GetString(SR.Win2000Required), x); 
            }
        }

 

        public static bool IsRemoteMachine(string machineName) { 
            if (machineName == null) 
                throw new ArgumentNullException("machineName");
 
            if (machineName.Length == 0)
                throw new ArgumentException(SR.GetString(SR.InvalidParameter, "machineName", machineName));

            string baseName; 

            if (machineName.StartsWith("\\", StringComparison.Ordinal)) 
                baseName = machineName.Substring(2); 
            else
                baseName = machineName; 
            if (baseName.Equals(".")) return false;

            StringBuilder sb = new StringBuilder(256);
            SafeNativeMethods.GetComputerName(sb, new int[] {sb.Capacity}); 
            string computerName = sb.ToString();
            if (String.Compare(computerName, baseName, StringComparison.OrdinalIgnoreCase) == 0) return false; 
            return true; 
        }
    } 

    /// 
    ///     This static class provides the process api for the Win9x platform.
    ///     We use the toolhelp32 api to query process, thread and module information. 
    /// 
    ///  
    internal static class WinProcessManager { 

        // This is expensive.  We should specialize getprocessinfos and only get 
        // the ids instead of getting all the info and then copying the ids out.
        public static int[] GetProcessIds() {
            ProcessInfo[] infos = GetProcessInfos();
            int[] ids = new int[infos.Length]; 
            for (int i = 0; i < infos.Length; i++) {
                ids[i] = infos[i].processId; 
            } 
            return ids;
        } 

        public static ProcessInfo[] GetProcessInfos() {
            IntPtr handle = (IntPtr)(-1);
            GCHandle bufferHandle = new GCHandle(); 
            ArrayList threadInfos = new ArrayList();
            Hashtable processInfos = new Hashtable(); 
 
            try {
                handle = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPPROCESS | NativeMethods.TH32CS_SNAPTHREAD, 0); 
                if (handle == (IntPtr)(-1)) throw new Win32Exception();
                int entrySize = (int)Marshal.SizeOf(typeof(NativeMethods.WinProcessEntry));
                int bufferSize = entrySize + NativeMethods.WinProcessEntry.sizeofFileName;
                int[] buffer = new int[bufferSize / 4]; 
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject(); 
                Marshal.WriteInt32(bufferPtr, bufferSize); 

                HandleRef handleRef = new HandleRef(null, handle); 

                if (NativeMethods.Process32First(handleRef, bufferPtr)) {
                    do {
                        NativeMethods.WinProcessEntry process = new NativeMethods.WinProcessEntry(); 
                        Marshal.PtrToStructure(bufferPtr, process);
                        ProcessInfo processInfo = new ProcessInfo(); 
                        String name = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize)); 
                        processInfo.processName = Path.ChangeExtension(Path.GetFileName(name), null);
                        processInfo.handleCount = process.cntUsage; 
                        processInfo.processId = process.th32ProcessID;
                        processInfo.basePriority = process.pcPriClassBase;
                        processInfo.mainModuleId = process.th32ModuleID;
                        processInfos.Add(processInfo.processId, processInfo); 
                        Marshal.WriteInt32(bufferPtr, bufferSize);
                    } 
                    while (NativeMethods.Process32Next(handleRef, bufferPtr)); 
                }
 
                NativeMethods.WinThreadEntry thread = new NativeMethods.WinThreadEntry();
                thread.dwSize = Marshal.SizeOf(thread);
                if (NativeMethods.Thread32First(handleRef, thread)) {
                    do { 
                        ThreadInfo threadInfo = new ThreadInfo();
                        threadInfo.threadId = thread.th32ThreadID; 
                        threadInfo.processId = thread.th32OwnerProcessID; 
                        threadInfo.basePriority = thread.tpBasePri;
                        threadInfo.currentPriority = thread.tpBasePri + thread.tpDeltaPri; 
                        threadInfos.Add(threadInfo);
                    }
                    while (NativeMethods.Thread32Next(handleRef, thread));
                } 

                for (int i = 0; i < threadInfos.Count; i++) { 
                    ThreadInfo threadInfo = (ThreadInfo)threadInfos[i]; 
                    ProcessInfo processInfo = (ProcessInfo)processInfos[threadInfo.processId];
                    if (processInfo != null) 
                        processInfo.threadInfoList.Add(threadInfo);
                    //else
                    //    throw new InvalidOperationException(SR.GetString(SR.ProcessNotFound, threadInfo.threadId.ToString(), threadInfo.processId.ToString()));
                } 
            }
            finally { 
                if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(toolhelp32 snapshot handle)");
                if (handle != (IntPtr)(-1)) SafeNativeMethods.CloseHandle(new HandleRef(null, handle)); 
            }

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0); 
            return temp;
        } 
 
        public static ModuleInfo[] GetModuleInfos(int processId) {
            IntPtr handle = (IntPtr)(-1); 
            GCHandle bufferHandle = new GCHandle();
            ArrayList moduleInfos = new ArrayList();

            try { 
                handle = NativeMethods.CreateToolhelp32Snapshot(NativeMethods.TH32CS_SNAPMODULE, processId);
                if (handle == (IntPtr)(-1)) throw new Win32Exception(); 
                int entrySize = Marshal.SizeOf(typeof(NativeMethods.WinModuleEntry)); 
                int bufferSize = entrySize + NativeMethods.WinModuleEntry.sizeofFileName + NativeMethods.WinModuleEntry.sizeofModuleName;
                int[] buffer = new int[bufferSize / 4]; 
                bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr bufferPtr = bufferHandle.AddrOfPinnedObject();
                Marshal.WriteInt32(bufferPtr, bufferSize);
 
                HandleRef handleRef = new HandleRef(null, handle);
 
                if (NativeMethods.Module32First(handleRef, bufferPtr)) { 
                    do {
                        NativeMethods.WinModuleEntry module = new NativeMethods.WinModuleEntry(); 
                        Marshal.PtrToStructure(bufferPtr, module);
                        ModuleInfo moduleInfo = new ModuleInfo();
                        moduleInfo.baseName = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize));
                        moduleInfo.fileName = Marshal.PtrToStringAnsi((IntPtr)((long)bufferPtr + entrySize + NativeMethods.WinModuleEntry.sizeofModuleName)); 
                        moduleInfo.baseOfDll = module.modBaseAddr;
                        moduleInfo.sizeOfImage = module.modBaseSize; 
                        moduleInfo.Id = module.th32ModuleID; 
                        moduleInfos.Add(moduleInfo);
                        Marshal.WriteInt32(bufferPtr, bufferSize); 
                    }
                    while (NativeMethods.Module32Next(handleRef, bufferPtr));
                }
            } 
            finally {
                if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(toolhelp32 snapshot handle)"); 
                if (handle != (IntPtr)(-1)) SafeNativeMethods.CloseHandle(new HandleRef(null, handle));
            } 

            ModuleInfo[] temp = new ModuleInfo[moduleInfos.Count];
            moduleInfos.CopyTo(temp, 0);
            return temp; 
        }
 
    } 

 
    /// 
    ///     This static class provides the process api for the WinNt platform.
    ///     We use the performance counter api to query process and thread
    ///     information.  Module information is obtained using PSAPI. 
    /// 
    ///  
    internal static class NtProcessManager { 
        private const int ProcessPerfCounterId = 230;
        private const int ThreadPerfCounterId = 232; 
        private const string PerfCounterQueryString = "230 232";
        internal const int IdleProcessID = 0;

        static Hashtable valueIds; 

        static NtProcessManager() { 
            valueIds = new Hashtable(); 
            valueIds.Add("Handle Count", ValueId.HandleCount);
            valueIds.Add("Pool Paged Bytes", ValueId.PoolPagedBytes); 
            valueIds.Add("Pool Nonpaged Bytes", ValueId.PoolNonpagedBytes);
            valueIds.Add("Elapsed Time", ValueId.ElapsedTime);
            valueIds.Add("Virtual Bytes Peak", ValueId.VirtualBytesPeak);
            valueIds.Add("Virtual Bytes", ValueId.VirtualBytes); 
            valueIds.Add("Private Bytes", ValueId.PrivateBytes);
            valueIds.Add("Page File Bytes", ValueId.PageFileBytes); 
            valueIds.Add("Page File Bytes Peak", ValueId.PageFileBytesPeak); 
            valueIds.Add("Working Set Peak", ValueId.WorkingSetPeak);
            valueIds.Add("Working Set", ValueId.WorkingSet); 
            valueIds.Add("ID Thread", ValueId.ThreadId);
            valueIds.Add("ID Process", ValueId.ProcessId);
            valueIds.Add("Priority Base", ValueId.BasePriority);
            valueIds.Add("Priority Current", ValueId.CurrentPriority); 
            valueIds.Add("% User Time", ValueId.UserTime);
            valueIds.Add("% Privileged Time", ValueId.PrivilegedTime); 
            valueIds.Add("Start Address", ValueId.StartAddress); 
            valueIds.Add("Thread State", ValueId.ThreadState);
            valueIds.Add("Thread Wait Reason", ValueId.ThreadWaitReason); 
        }

        internal static int SystemProcessID {
            get { 
                const int systemProcessIDOnXP = 4;
                const int systemProcessIDOn2K = 8; 
 
                if( ProcessManager.IsOSOlderThanXP) {
                    return systemProcessIDOn2K; 
                }
                else {
                    return systemProcessIDOnXP;
                } 
            }
        } 
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        public static int[] GetProcessIds(string machineName, bool isRemoteMachine) {
            ProcessInfo[] infos = GetProcessInfos(machineName, isRemoteMachine);
            int[] ids = new int[infos.Length];
            for (int i = 0; i < infos.Length; i++) 
                ids[i] = infos[i].processId;
            return ids; 
        } 

        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static int[] GetProcessIds() {
            int[] processIds = new int[256];
            int size; 
            for (;;) {
                if (!NativeMethods.EnumProcesses(processIds, processIds.Length * 4, out size)) 
                    throw new Win32Exception(); 
                if (size == processIds.Length * 4) {
                    processIds = new int[processIds.Length * 2]; 
                    continue;
                }
                break;
            } 
            int[] ids = new int[size / 4];
            Array.Copy(processIds, ids, ids.Length); 
            return ids; 
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static ModuleInfo[] GetModuleInfos(int processId) {
            return GetModuleInfos(processId, false); 
        }
 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static ModuleInfo GetFirstModuleInfo(int processId) { 
            ModuleInfo[] moduleInfos = GetModuleInfos(processId, true);
            if( moduleInfos.Length == 0) {
                return null;
            } 
            else {
                return moduleInfos[0]; 
            } 
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        private static ModuleInfo[] GetModuleInfos(int processId, bool firstModuleOnly) {
            // preserving Everett behavior. 
            if( processId == SystemProcessID || processId == IdleProcessID) {
                // system process and idle process doesn't have any modules 
                throw new Win32Exception(HResults.EFail,SR.GetString(SR.EnumProcessModuleFailed)); 
            }
 
            SafeProcessHandle processHandle = SafeProcessHandle.InvalidHandle;
            try {
                processHandle = ProcessManager.OpenProcess(processId, NativeMethods.PROCESS_QUERY_INFORMATION | NativeMethods.PROCESS_VM_READ, true);
                IntPtr[] moduleHandles = new IntPtr[64]; 
                GCHandle moduleHandlesArrayHandle = new GCHandle();
                int moduleCount = 0; 
                for (;;) { 
                    bool enumResult = false;
                    try { 
                        moduleHandlesArrayHandle = GCHandle.Alloc(moduleHandles, GCHandleType.Pinned);
                        //
                        // EnumProcessModules is not a reliable method to get the modules for a process.
                        // If OS loader is touching module information, this method might fail and copy part of the data. 
                        // This is no easy solution to this problem. The only reliable way to fix this is to
                        // suspend all the threads in target process. Of course we don't want to do this in Process class. 
                        // So we just to try avoid the ---- by calling the same method 10 (an arbitary number) times. 
                        //
                        for( int i = 0; i < 10; i++) { 
                            enumResult = NativeMethods.EnumProcessModules(processHandle, moduleHandlesArrayHandle.AddrOfPinnedObject(), moduleHandles.Length * IntPtr.Size, ref moduleCount);
                            if( enumResult) {
                                break;
                            } 
                            Thread.Sleep(1);
                        } 
                    } 
                    finally {
                        moduleHandlesArrayHandle.Free(); 
                    }

                    if (!enumResult) {
                        throw new Win32Exception(); 
                    }
 
                    moduleCount /= IntPtr.Size; 
                    if (moduleCount <= moduleHandles.Length) break;
                    moduleHandles = new IntPtr[moduleHandles.Length * 2]; 
                }
                ArrayList moduleInfos = new ArrayList();

                int ret; 
                for (int i = 0; i < moduleCount; i++) {
                    ModuleInfo moduleInfo = new ModuleInfo(); 
                    IntPtr moduleHandle = moduleHandles[i]; 
                    NativeMethods.NtModuleInfo ntModuleInfo = new NativeMethods.NtModuleInfo();
                    if (!NativeMethods.GetModuleInformation(processHandle, new HandleRef(null, moduleHandle), ntModuleInfo, Marshal.SizeOf(ntModuleInfo))) 
                        throw new Win32Exception();
                    moduleInfo.sizeOfImage = ntModuleInfo.SizeOfImage;
                    moduleInfo.entryPoint = ntModuleInfo.EntryPoint;
                    moduleInfo.baseOfDll = ntModuleInfo.BaseOfDll; 

                    StringBuilder baseName = new StringBuilder(1024); 
                    ret = NativeMethods.GetModuleBaseName(processHandle, new HandleRef(null, moduleHandle), baseName, baseName.Capacity * 2); 
                    if (ret == 0) throw new Win32Exception();
                    moduleInfo.baseName = baseName.ToString(); 

                    StringBuilder fileName = new StringBuilder(1024);
                    ret = NativeMethods.GetModuleFileNameEx(processHandle, new HandleRef(null, moduleHandle), fileName, fileName.Capacity * 2);
                    if (ret == 0) throw new Win32Exception(); 
                    moduleInfo.fileName = fileName.ToString();
 
                    // smss.exe is started before the win32 subsystem so it get this funny "\systemroot\.." path. 
                    // We change this to the actual path by appending "smss.exe" to GetSystemDirectory()
                    if (string.Compare(moduleInfo.fileName, "\\SystemRoot\\System32\\smss.exe", StringComparison.OrdinalIgnoreCase) == 0) { 
                        moduleInfo.fileName = Path.Combine(Environment.SystemDirectory, "smss.exe");
                    }
                    // Avoid returning Unicode-style long string paths.  IO methods cannot handle them.
                    if (moduleInfo.fileName != null 
                        && moduleInfo.fileName.Length >= 4
                        && moduleInfo.fileName.StartsWith(@"\\?\", StringComparison.Ordinal)) { 
 
                            moduleInfo.fileName = moduleInfo.fileName.Substring(4);
                    } 

                    moduleInfos.Add(moduleInfo);
                    //
                    // If the user is only interested in the main module, break now. 
                    // This avoid some waste of time. In addition, if the application unloads a DLL
                    // we will not get an exception. 
                    // 
                    if( firstModuleOnly) { break; }
                } 
                ModuleInfo[] temp = new ModuleInfo[moduleInfos.Count];
                moduleInfos.CopyTo(temp, 0);
                return temp;
            } 
            finally {
                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "Process - CloseHandle(process)"); 
                if (!processHandle.IsInvalid ) { 
                    processHandle.Close();
                } 
            }
        }

        [ResourceExposure(ResourceScope.Process)] 
        [ResourceConsumption(ResourceScope.Process)]
        public static int GetProcessIdFromHandle(SafeProcessHandle processHandle) { 
            NativeMethods.NtProcessBasicInfo info = new NativeMethods.NtProcessBasicInfo(); 
            int status = NativeMethods.NtQueryInformationProcess(processHandle, NativeMethods.NtQueryProcessBasicInfo, info, (int)Marshal.SizeOf(info), null);
            if (status != 0) { 
                throw new InvalidOperationException(SR.GetString(SR.CantGetProcessId), new Win32Exception(status));
            }
            // We should change the signature of this function and ID property in process class.
            return info.UniqueProcessId.ToInt32(); 
        }
 
        public static ProcessInfo[] GetProcessInfos(string machineName, bool isRemoteMachine) { 
            // We demand unmanaged code here because PerformanceCounterLib doesn't demand
            // anything.  This is the only place we do GetPerformanceCounterLib, and it isn't cached. 
            new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
            PerformanceCounterLib library = null;
            try {
                library = PerformanceCounterLib.GetPerformanceCounterLib(machineName, new CultureInfo(0x009)); 
                return GetProcessInfos(library);
            } 
            catch(Exception e) { 
                if( isRemoteMachine) {
                    throw new InvalidOperationException(SR.GetString(SR.CouldntConnectToRemoteMachine), e); 
                }
                else {
                    throw e;
                } 
            }
            catch { 
                if(isRemoteMachine) { 
                    throw new InvalidOperationException(SR.GetString(SR.CouldntConnectToRemoteMachine));
                } 
                else {
                    throw;
                }
            } 
            // We don't want to call library.Close() here because that would cause us to unload all of the perflibs.
            // On the next call to GetProcessInfos, we'd have to load them all up again, which is SLOW! 
        } 

        static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library) { 
            ProcessInfo[] processInfos = new ProcessInfo[0] ;
            byte[] dataPtr = null;

            int retryCount = 5; 
            while (processInfos.Length == 0 && retryCount != 0) {
                try { 
                    dataPtr = library.GetPerformanceData(PerfCounterQueryString); 
                    processInfos = GetProcessInfos(library, ProcessPerfCounterId, ThreadPerfCounterId, dataPtr);
                } 
                catch (Exception e) {
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos), e);
                }
                catch { 
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos));
                } 
 
                --retryCount;
            } 

            if (processInfos.Length == 0)
                throw new InvalidOperationException(SR.GetString(SR.ProcessDisabled));
 
            return processInfos;
 
        } 

        unsafe static ProcessInfo[] GetProcessInfos(PerformanceCounterLib library, int processIndex, int threadIndex, byte[] data) { 
            Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos()");
            Hashtable processInfos = new Hashtable();
            ArrayList threadInfos = new ArrayList();
 
            fixed (byte* dataPtr = data) {
                IntPtr dataBlockPtr = new IntPtr( (void*) dataPtr); 
                NativeMethods.PERF_DATA_BLOCK dataBlock = new NativeMethods.PERF_DATA_BLOCK(); 
                Marshal.PtrToStructure(dataBlockPtr, dataBlock);
                IntPtr typePtr = (IntPtr)((long)dataBlockPtr + dataBlock.HeaderLength); 
                NativeMethods.PERF_INSTANCE_DEFINITION instance = new NativeMethods.PERF_INSTANCE_DEFINITION();
                NativeMethods.PERF_COUNTER_BLOCK counterBlock = new NativeMethods.PERF_COUNTER_BLOCK();
                for (int i = 0; i < dataBlock.NumObjectTypes; i++) {
                    NativeMethods.PERF_OBJECT_TYPE type = new NativeMethods.PERF_OBJECT_TYPE(); 
                    Marshal.PtrToStructure(typePtr, type);
                    IntPtr instancePtr = (IntPtr)((long)typePtr + type.DefinitionLength); 
                    IntPtr counterPtr = (IntPtr)((long)typePtr + type.HeaderLength); 
                    ArrayList counterList = new ArrayList();
 
                    for (int j = 0; j < type.NumCounters; j++) {
                        NativeMethods.PERF_COUNTER_DEFINITION counter = new NativeMethods.PERF_COUNTER_DEFINITION();
                        Marshal.PtrToStructure(counterPtr, counter);
                        string counterName = library.GetCounterName(counter.CounterNameTitleIndex); 

                        if (type.ObjectNameTitleIndex == processIndex) 
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName); 
                        else if (type.ObjectNameTitleIndex == threadIndex)
                            counter.CounterNameTitlePtr = (int)GetValueId(counterName); 
                        counterList.Add(counter);
                        counterPtr = (IntPtr)((long)counterPtr + counter.ByteLength);
                    }
                    NativeMethods.PERF_COUNTER_DEFINITION[] counters = new NativeMethods.PERF_COUNTER_DEFINITION[counterList.Count]; 
                    counterList.CopyTo(counters, 0);
                    for (int j = 0; j < type.NumInstances; j++) { 
                        Marshal.PtrToStructure(instancePtr, instance); 
                        IntPtr namePtr = (IntPtr)((long)instancePtr + instance.NameOffset);
                        string instanceName = Marshal.PtrToStringUni(namePtr); 
                        if (instanceName.Equals("_Total")) continue;
                        IntPtr counterBlockPtr = (IntPtr)((long)instancePtr + instance.ByteLength);
                        Marshal.PtrToStructure(counterBlockPtr, counterBlock);
                        if (type.ObjectNameTitleIndex == processIndex) { 
                            ProcessInfo processInfo = GetProcessInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (processInfo.processId == 0 && string.Compare(instanceName, "Idle", StringComparison.OrdinalIgnoreCase) != 0) { 
                                // Sometimes we'll get a process structure that is not completely filled in. 
                                // We can catch some of these by looking for non-"idle" processes that have id 0
                                // and ignoring those. 
                                Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos() - found a non-idle process with id 0; ignoring.");
                            }
                            else {
                                if (processInfos[processInfo.processId] != null) { 
                                    // We've found two entries in the perfcounters that claim to be the
                                    // same process.  We throw an exception.  Is this really going to be 
                                    // helpfull to the user?  Should we just ignore? 
                                    Debug.WriteLineIf(Process.processTracing.TraceVerbose, "GetProcessInfos() - found a duplicate process id");
                                } 
                                else {
                                    // the performance counters keep a 15 character prefix of the exe name, and then delete the ".exe",
                                    // if it's in the first 15.  The problem is that sometimes that will leave us with part of ".exe"
                                    // at the end.  If instanceName ends in ".", ".e", or ".ex" we remove it. 
                                    string processName = instanceName;
                                    if (processName.Length == 15) { 
                                        if      (instanceName.EndsWith(".", StringComparison.Ordinal  )) processName = instanceName.Substring(0, 14); 
                                        else if (instanceName.EndsWith(".e", StringComparison.Ordinal )) processName = instanceName.Substring(0, 13);
                                        else if (instanceName.EndsWith(".ex", StringComparison.Ordinal)) processName = instanceName.Substring(0, 12); 
                                    }
                                    processInfo.processName = processName;
                                    processInfos.Add(processInfo.processId, processInfo);
                                } 
                            }
                        } 
                        else if (type.ObjectNameTitleIndex == threadIndex) { 
                            ThreadInfo threadInfo = GetThreadInfo(type, (IntPtr)((long)instancePtr + instance.ByteLength), counters);
                            if (threadInfo.threadId != 0) threadInfos.Add(threadInfo); 
                        }
                        instancePtr = (IntPtr)((long)instancePtr + instance.ByteLength + counterBlock.ByteLength);
                    }
 
                    typePtr = (IntPtr)((long)typePtr + type.TotalByteLength);
                } 
            } 

            for (int i = 0; i < threadInfos.Count; i++) { 
                ThreadInfo threadInfo = (ThreadInfo)threadInfos[i];
                ProcessInfo processInfo = (ProcessInfo)processInfos[threadInfo.processId];
                if (processInfo != null) {
                    processInfo.threadInfoList.Add(threadInfo); 
                }
                //else { 
                //    throw new InvalidOperationException(SR.GetString(SR.ProcessNotFound, threadInfo.threadId.ToString(), threadInfo.processId.ToString())); 
                //}
            } 

            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return temp; 
        }
 
        static ThreadInfo GetThreadInfo(NativeMethods.PERF_OBJECT_TYPE type, IntPtr instancePtr, NativeMethods.PERF_COUNTER_DEFINITION[] counters) { 
            ThreadInfo threadInfo = new ThreadInfo();
            for (int i = 0; i < counters.Length; i++) { 
                NativeMethods.PERF_COUNTER_DEFINITION counter = counters[i];
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset));
                switch ((ValueId)counter.CounterNameTitlePtr) {
                    case ValueId.ProcessId: 
                        threadInfo.processId = (int)value;
                        break; 
                    case ValueId.ThreadId: 
                        threadInfo.threadId = (int)value;
                        break; 
                    case ValueId.BasePriority:
                        threadInfo.basePriority = (int)value;
                        break;
                    case ValueId.CurrentPriority: 
                        threadInfo.currentPriority = (int)value;
                        break; 
                    case ValueId.StartAddress: 
                        threadInfo.startAddress = (IntPtr)value;
                        break; 
                    case ValueId.ThreadState:
                        threadInfo.threadState = (ThreadState)value;
                        break;
                    case ValueId.ThreadWaitReason: 
                        threadInfo.threadWaitReason = GetThreadWaitReason((int)value);
                        break; 
                } 
            }
 
            return threadInfo;
        }

        internal static ThreadWaitReason GetThreadWaitReason(int value) { 
            switch (value) {
                case 0: 
                case 7: return ThreadWaitReason.Executive; 
                case 1:
                case 8: return ThreadWaitReason.FreePage; 
                case 2:
                case 9: return ThreadWaitReason.PageIn;
                case 3:
                case 10: return ThreadWaitReason.SystemAllocation; 
                case 4:
                case 11: return ThreadWaitReason.ExecutionDelay; 
                case 5: 
                case 12: return ThreadWaitReason.Suspended;
                case 6: 
                case 13: return ThreadWaitReason.UserRequest;
                case 14: return ThreadWaitReason.EventPairHigh;;
                case 15: return ThreadWaitReason.EventPairLow;
                case 16: return ThreadWaitReason.LpcReceive; 
                case 17: return ThreadWaitReason.LpcReply;
                case 18: return ThreadWaitReason.VirtualMemory; 
                case 19: return ThreadWaitReason.PageOut; 
                default: return ThreadWaitReason.Unknown;
            } 
        }

        static ProcessInfo GetProcessInfo(NativeMethods.PERF_OBJECT_TYPE type, IntPtr instancePtr, NativeMethods.PERF_COUNTER_DEFINITION[] counters) {
            ProcessInfo processInfo = new ProcessInfo(); 
            for (int i = 0; i < counters.Length; i++) {
                NativeMethods.PERF_COUNTER_DEFINITION counter = counters[i]; 
                long value = ReadCounterValue(counter.CounterType, (IntPtr)((long)instancePtr + counter.CounterOffset)); 
                switch ((ValueId)counter.CounterNameTitlePtr) {
                    case ValueId.ProcessId: 
                        processInfo.processId = (int)value;
                        break;
                    case ValueId.HandleCount:
                        processInfo.handleCount = (int)value; 
                        break;
                    case ValueId.PoolPagedBytes: 
                        processInfo.poolPagedBytes = (int)value; 
                        break;
                    case ValueId.PoolNonpagedBytes: 
                        processInfo.poolNonpagedBytes = (int)value;
                        break;
                    case ValueId.VirtualBytes:
                        processInfo.virtualBytes = (int)value; 
                        break;
                    case ValueId.VirtualBytesPeak: 
                        processInfo.virtualBytesPeak = (int)value; 
                        break;
                    case ValueId.WorkingSetPeak: 
                        processInfo.workingSetPeak = (int)value;
                        break;
                    case ValueId.WorkingSet:
                        processInfo.workingSet = (int)value; 
                        break;
                    case ValueId.PageFileBytesPeak: 
                        processInfo.pageFileBytesPeak = (int)value; 
                        break;
                    case ValueId.PageFileBytes: 
                        processInfo.pageFileBytes = (int)value;
                        break;
                    case ValueId.PrivateBytes:
                        processInfo.privateBytes = (int)value; 
                        break;
                    case ValueId.BasePriority: 
                        processInfo.basePriority = (int)value; 
                        break;
                } 
            }
            return processInfo;
        }
 
        static ValueId GetValueId(string counterName) {
            if (counterName != null) { 
                object id = valueIds[counterName]; 
                if (id != null)
                    return(ValueId)id; 
            }
            return ValueId.Unknown;
        }
 
        static long ReadCounterValue(int counterType, IntPtr dataPtr) {
            if ((counterType & NativeMethods.NtPerfCounterSizeLarge) != 0) 
                return Marshal.ReadInt64(dataPtr); 
            else
                return(long)Marshal.ReadInt32(dataPtr); 
        }

        enum ValueId {
            Unknown = -1, 
            HandleCount,
            PoolPagedBytes, 
            PoolNonpagedBytes, 
            ElapsedTime,
            VirtualBytesPeak, 
            VirtualBytes,
            PrivateBytes,
            PageFileBytes,
            PageFileBytesPeak, 
            WorkingSetPeak,
            WorkingSet, 
            ThreadId, 
            ProcessId,
            BasePriority, 
            CurrentPriority,
            UserTime,
            PrivilegedTime,
            StartAddress, 
            ThreadState,
            ThreadWaitReason 
        } 
    }
 
    internal static class NtProcessInfoHelper {
        private static int GetNewBufferSize(int existingBufferSize, int requiredSize) {
            if( requiredSize == 0) {
                // 
                // On some old OS like win2000, requiredSize will not be set if the buffer
                // passed to NtQuerySystemInformation is not enough. 
                // 
                int newSize = existingBufferSize * 2;
                if ( newSize < existingBufferSize ) { 
                    // In reality, we should never overflow.
                    // Adding the code here just in case it happens.
                    throw new OutOfMemoryException();
                } 
                return newSize;
            } 
            else { 
                // allocating a few more kilo bytes just in case there are some new process
                // kicked in since new call to NtQuerySystemInformation 
                return requiredSize + 1024 * 10;
            }
        }
 
        #pragma warning disable 169
        public static ProcessInfo[] GetProcessInfos() { 
            // On a normal machine, 30k to 40K will be enough. 
            // We use 128K here to tolerate mutilple connections to a machine.
            int bufferSize = 128 * 1024; 
#if DEBUG
            // on debug build, use a smaller buffer size to make sure we hit the retrying code path
           bufferSize = 1024;
#endif 
            int requiredSize = 0;
            int status; 
 
            ProcessInfo[] processInfos;
            GCHandle bufferHandle = new GCHandle(); 

            try {
                // Retry until we get all the data
                do { 
                    Byte[] buffer = new Byte[bufferSize];
                    bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned); 
 
                    status = NativeMethods.NtQuerySystemInformation(
                        NativeMethods.NtQuerySystemProcessInformation, 
                        bufferHandle.AddrOfPinnedObject(),
                        bufferSize,
                        out requiredSize);
 
                    if ((uint)status == NativeMethods.STATUS_INFO_LENGTH_MISMATCH) {
                        if (bufferHandle.IsAllocated) bufferHandle.Free(); 
                        bufferSize = GetNewBufferSize(bufferSize, requiredSize); 
                    }
                } while ((uint)status == NativeMethods.STATUS_INFO_LENGTH_MISMATCH); 

                if (status < 0) { // see definition of NT_SUCCESS(Status) in SDK
                    throw new InvalidOperationException(SR.GetString(SR.CouldntGetProcessInfos), new Win32Exception(status));
                } 

                // Parse the data block to get process information 
                processInfos = GetProcessInfos(bufferHandle.AddrOfPinnedObject()); 
            }
            finally { 
                if (bufferHandle.IsAllocated) bufferHandle.Free();
            }
            return processInfos;
        } 

        unsafe static ProcessInfo[] GetProcessInfos(IntPtr dataPtr) { 
            // 60 is a reasonable number for processes on a normal machine. 
            Hashtable processInfos = new Hashtable(60);
 
            long totalOffset = 0;

            while(true) {
                IntPtr currentPtr = (IntPtr)((long)dataPtr + totalOffset); 
                SystemProcessInformation pi = new SystemProcessInformation();
 
                Marshal.PtrToStructure(currentPtr, pi); 

                // get information for a process 
                ProcessInfo processInfo = new ProcessInfo();
                // Process ID shouldn't overflow. OS API GetCurrentProcessID returns DWORD.
                processInfo.processId = pi.UniqueProcessId.ToInt32();
                processInfo.handleCount = (int)pi.HandleCount; 
                processInfo.sessionId = (int)pi.SessionId;
                processInfo.poolPagedBytes = (long)pi.QuotaPagedPoolUsage;; 
                processInfo.poolNonpagedBytes = (long)pi.QuotaNonPagedPoolUsage; 
                processInfo.virtualBytes = (long)pi.VirtualSize;
                processInfo.virtualBytesPeak = (long)pi.PeakVirtualSize; 
                processInfo.workingSetPeak = (long)pi.PeakWorkingSetSize;
                processInfo.workingSet = (long)pi.WorkingSetSize;
                processInfo.pageFileBytesPeak = (long)pi.PeakPagefileUsage;
                processInfo.pageFileBytes = (long)pi.PagefileUsage; 
                processInfo.privateBytes = (long)pi.PrivatePageCount;
                processInfo.basePriority = pi.BasePriority; 
 

                if( pi.NamePtr == IntPtr.Zero) { 
                    if( processInfo.processId == NtProcessManager.SystemProcessID) {
                        processInfo.processName = "System";
                    }
                    else if( processInfo.processId == NtProcessManager.IdleProcessID) { 
                        processInfo.processName = "Idle";
                    } 
                    else { 
                        // for normal process without name, using the process ID.
                        processInfo.processName = processInfo.processId.ToString(CultureInfo.InvariantCulture); 
                    }
                }
                else {
                    string processName = GetProcessShortName((char *)pi.NamePtr.ToPointer(), pi.NameLength/2); 
                    //
                    // On old operating system (NT4 and windows 2000), the process name might be truncated to 15 
                    // characters. For example, aspnet_admin.exe will show up in performance counter as aspnet_admin.ex. 
                    // Process class try to return a nicer name. We used to get the main module name for a process and
                    // use that as the process name. However normal user doesn't have access to module information, 
                    // so normal user will see an exception when we try to get a truncated process name.
                    //
                    if (ProcessManager.IsOSOlderThanXP && (processName.Length == 15)) {
                        if (processName.EndsWith(".", StringComparison.OrdinalIgnoreCase)) { 
                            processName = processName.Substring(0, 14);
                        } 
                        else if (processName.EndsWith(".e", StringComparison.OrdinalIgnoreCase)) { 
                            processName = processName.Substring(0, 13);
                        } 
                        else if (processName.EndsWith(".ex", StringComparison.OrdinalIgnoreCase)) {
                            processName = processName.Substring(0, 12);
                        }
                    } 
                    processInfo.processName = processName;
                } 
 
                // get the threads for current process
                processInfos[processInfo.processId] =  processInfo; 

                currentPtr = (IntPtr)((long)currentPtr + Marshal.SizeOf(pi));
                int i = 0;
                while( i < pi.NumberOfThreads) { 
                    SystemThreadInformation ti = new SystemThreadInformation();
                    Marshal.PtrToStructure(currentPtr, ti); 
                    ThreadInfo threadInfo = new ThreadInfo(); 

                    threadInfo.processId = (int)ti.UniqueProcess; 
                    threadInfo.threadId = (int)ti.UniqueThread;
                    threadInfo.basePriority = ti.BasePriority;
                    threadInfo.currentPriority = ti.Priority;
                    threadInfo.startAddress = ti.StartAddress; 
                    threadInfo.threadState = (ThreadState)ti.ThreadState;
                    threadInfo.threadWaitReason = NtProcessManager.GetThreadWaitReason((int)ti.WaitReason); 
 
                    processInfo.threadInfoList.Add(threadInfo);
                    currentPtr = (IntPtr)((long)currentPtr + Marshal.SizeOf(ti)); 
                    i++;
                }

                if (pi.NextEntryOffset == 0) { 
                    break;
                } 
                totalOffset += pi.NextEntryOffset; 
            }
 
            ProcessInfo[] temp = new ProcessInfo[processInfos.Values.Count];
            processInfos.Values.CopyTo(temp, 0);
            return temp;
        } 

        // This function generates the short form of process name. 
        // 
        // This is from GetProcessShortName in NT code base.
        // Check base\screg\winreg\perfdlls\process\perfsprc.c for details. 
        internal unsafe static string GetProcessShortName(char* name, int length)  {
            char* pSlash = name;
            char* pPeriod = name;
            char* pThisChar = name; 
            int wThisChar = 0;
 
            while (*pThisChar != 0) { // go until null 
                if (*pThisChar == '\\') {
                    pSlash = pThisChar; 
                } else if (*pThisChar == '.') {
                    pPeriod = pThisChar;
                }
                pThisChar++;    // point to next char 
                wThisChar++;
                if (wThisChar >= length) { 
                    break; 
                }
            } 

            // if pPeriod is still pointing to the beginning of the
            // string, then no period was found
 
            if (pPeriod == name) {
                pPeriod = pThisChar; // set to end of string; 
            } else { 
                // if a period was found, then see if the extension is
                // .EXE, if so drop it, if not, then use end of string 
                // (i.e. include extension in name)
                String extension = new String(pPeriod);

                if(!String.Equals(".exe", extension, StringComparison.OrdinalIgnoreCase) ) { 
                    pPeriod = pThisChar;
                } 
            } 

            if (*pSlash == '\\') { // if pSlash is pointing to a slash, then 
                pSlash++;   // point to character next to slash
            }

            // copy characters between period (or end of string) and 
            // slash (or start of string) to make image name
            int wStringSize = (int)(pPeriod - pSlash); // size in bytes 
            return new String(pSlash, 0, wStringSize); 
        }
 

        [StructLayout(LayoutKind.Sequential)]
        internal class SystemProcessInformation {
            internal int NextEntryOffset; 
            internal uint NumberOfThreads;
            long SpareLi1; 
            long SpareLi2; 
            long SpareLi3;
            long CreateTime; 
            long UserTime;
            long KernelTime;

            internal ushort NameLength;   // UNICODE_STRING 
            internal ushort MaximumNameLength;
            internal IntPtr NamePtr;     // This will point into the data block returned by NtQuerySystemInformation 
 
            internal int BasePriority;
            internal IntPtr UniqueProcessId; 
            internal IntPtr InheritedFromUniqueProcessId;
            internal uint HandleCount;
            internal uint SessionId;
            internal IntPtr PageDirectoryBase; 
            internal IntPtr PeakVirtualSize;
            internal IntPtr VirtualSize; 
            internal uint   PageFaultCount; 

            internal IntPtr PeakWorkingSetSize; 
            internal IntPtr WorkingSetSize;
            internal IntPtr QuotaPeakPagedPoolUsage;
            internal IntPtr QuotaPagedPoolUsage;
            internal IntPtr QuotaPeakNonPagedPoolUsage; 
            internal IntPtr QuotaNonPagedPoolUsage;
            internal IntPtr PagefileUsage; 
            internal IntPtr PeakPagefileUsage; 
            internal IntPtr PrivatePageCount;
 
            long ReadOperationCount;
            long WriteOperationCount;
            long OtherOperationCount;
            long ReadTransferCount; 
            long WriteTransferCount;
            long OtherTransferCount; 
        } 

        [StructLayout(LayoutKind.Sequential)] 
        internal class SystemThreadInformation {
            long KernelTime;
            long UserTime;
            long CreateTime; 

            uint WaitTime; 
            internal IntPtr StartAddress; 
            internal IntPtr UniqueProcess;
            internal IntPtr UniqueThread; 
            internal int Priority;
            internal int BasePriority;
            internal uint ContextSwitches;
            internal uint ThreadState; 
            internal uint WaitReason;
        } 
        #pragma warning restore 169 
    }
} 
#endif // !FEATURE_PAL

// 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