| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 | using Microsoft.Win32;using System;using System.ComponentModel;using System.Runtime.InteropServices;namespace PaintDotNet.SystemLayer{    /// <summary>    /// Provides static methods and properties related to the CPU.    /// </summary>    public static class Processor    {        private static int logicalCpuCount;        private static string cpuName;        static Processor()        {            logicalCpuCount = ConcreteLogicalCpuCount;        }        private static ProcessorArchitecture Convert(ushort wProcessorArchitecture)        {            ProcessorArchitecture platform;            switch (wProcessorArchitecture)            {                case NativeConstants.PROCESSOR_ARCHITECTURE_AMD64:                    platform = ProcessorArchitecture.X64;                    break;                case NativeConstants.PROCESSOR_ARCHITECTURE_INTEL:                    platform = ProcessorArchitecture.X86;                    break;                default:                case NativeConstants.PROCESSOR_ARCHITECTURE_UNKNOWN:                    platform = ProcessorArchitecture.Unknown;                    break;            }            return platform;        }        /// <summary>        /// Returns the processor architecture that the current process is using.        /// </summary>        /// <remarks>        /// Note that if the current process is 32-bit, but the OS is 64-bit, this        /// property will still return X86 and not X64.        /// </remarks>        public static ProcessorArchitecture Architecture        {            get            {                NativeStructs.SYSTEM_INFO sysInfo = new NativeStructs.SYSTEM_INFO();                NativeMethods.GetSystemInfo(ref sysInfo);                ProcessorArchitecture architecture = Convert(sysInfo.wProcessorArchitecture);                return architecture;            }        }        /// <summary>        /// Returns the processor architecture of the installed operating system.        /// </summary>        /// <remarks>        /// Note that this may differ from the Architecture property if, for instance,        /// this is a 32-bit process on a 64-bit OS.        /// </remarks>        public static ProcessorArchitecture NativeArchitecture        {            get            {                NativeStructs.SYSTEM_INFO sysInfo = new NativeStructs.SYSTEM_INFO();                NativeMethods.GetNativeSystemInfo(ref sysInfo);                ProcessorArchitecture architecture = Convert(sysInfo.wProcessorArchitecture);                return architecture;            }        }        private static string GetCpuName()        {            Guid processorClassGuid = new Guid("{50127DC3-0F36-415E-A6CC-4CB3BE910B65}");            IntPtr hDiSet = IntPtr.Zero;            string cpuName = null;            try            {                hDiSet = NativeMethods.SetupDiGetClassDevsW(ref processorClassGuid, null, IntPtr.Zero, NativeConstants.DIGCF_PRESENT);                if (hDiSet == NativeConstants.INVALID_HANDLE_VALUE)                {                    NativeMethods.ThrowOnWin32Error("SetupDiGetClassDevsW returned INVALID_HANDLE_VALUE");                }                bool bResult = false;                uint memberIndex = 0;                while (true)                {                    NativeStructs.SP_DEVINFO_DATA spDevinfoData = new NativeStructs.SP_DEVINFO_DATA();                    spDevinfoData.cbSize = (uint)Marshal.SizeOf(typeof(NativeStructs.SP_DEVINFO_DATA));                    bResult = NativeMethods.SetupDiEnumDeviceInfo(hDiSet, memberIndex, ref spDevinfoData);                    if (!bResult)                    {                        int error = Marshal.GetLastWin32Error();                        if (error == NativeConstants.ERROR_NO_MORE_ITEMS)                        {                            break;                        }                        else                        {                            throw new Win32Exception("SetupDiEnumDeviceInfo returned false, GetLastError() = " + error.ToString());                        }                    }                    uint lengthReq = 0;                    bResult = NativeMethods.SetupDiGetDeviceInstanceIdW(hDiSet, ref spDevinfoData, IntPtr.Zero, 0, out lengthReq);                    if (bResult)                    {                        NativeMethods.ThrowOnWin32Error("SetupDiGetDeviceInstanceIdW(1) returned true");                    }                    if (lengthReq == 0)                    {                        NativeMethods.ThrowOnWin32Error("SetupDiGetDeviceInstanceIdW(1) returned false, but also 0 for lengthReq");                    }                    IntPtr str = IntPtr.Zero;                    string regPath = null;                    try                    {                        // Note: We cannot use Memory.Allocate() here because this property is                        // usually retrieved during app shutdown, during which the heap may not                        // be available.                        str = Marshal.AllocHGlobal(checked((int)(sizeof(char) * (1 + lengthReq))));                        bResult = NativeMethods.SetupDiGetDeviceInstanceIdW(hDiSet, ref spDevinfoData, str, lengthReq, out lengthReq);                        if (!bResult)                        {                            NativeMethods.ThrowOnWin32Error("SetupDiGetDeviceInstanceIdW(2) returned false");                        }                        regPath = Marshal.PtrToStringUni(str);                    }                    finally                    {                        if (str != IntPtr.Zero)                        {                            Marshal.FreeHGlobal(str);                            str = IntPtr.Zero;                        }                    }                    string keyName = @"SYSTEM\CurrentControlSet\Enum\" + regPath;                    using (RegistryKey procKey = Registry.LocalMachine.OpenSubKey(keyName, false))                    {                        const string friendlyName = "FriendlyName";                        if (procKey != null)                        {                            object valueObj = procKey.GetValue(friendlyName);                            string value = valueObj as string;                            if (value != null)                            {                                cpuName = value;                            }                        }                    }                    if (cpuName != null)                    {                        break;                    }                    ++memberIndex;                }            }            finally            {                if (hDiSet != IntPtr.Zero)                {                    NativeMethods.SetupDiDestroyDeviceInfoList(hDiSet);                    hDiSet = IntPtr.Zero;                }            }            return cpuName;        }        /// <summary>        /// Returns the name of the CPU that is installed. If more than 1 CPU is installed,        /// then the name of the first one is retrieved.        /// </summary>        /// <remarks>        /// This is the name that shows up in Windows Device Manager in the "Processors" node.        /// Note to implementors: This is only ever used for diagnostics (e.g., crash log).        /// </remarks>        public static string CpuName        {            get            {                if (cpuName == null)                {                    cpuName = GetCpuName();                }                return cpuName;            }        }        /// <summary>        /// Gets the number of logical or "virtual" processors installed in the computer.        /// </summary>        /// <remarks>        /// This value may not return the actual number of processors installed in the system.        /// It may be set to another number for testing and benchmarking purposes. It is        /// recommended that you use this property instead of ConcreteLogicalCpuCount for the        /// purposes of optimizing thread usage.        /// The maximum value for this property is 32 when running as a 32-bit process, or        /// 64 for a 64-bit process. Note that this implies the maximum is 32 for a 32-bit process        /// even when running on a 64-bit system.        /// </remarks>        public static int LogicalCpuCount        {            get            {                return logicalCpuCount;            }            set            {                if (value < 1 || value > (IntPtr.Size * 8))                {                    throw new ArgumentOutOfRangeException("value", value, "must be in the range [0, " + (IntPtr.Size * 8).ToString() + "]");                }                logicalCpuCount = value;            }        }        /// <summary>        /// Gets the number of logical or "virtual" processors installed in the computer.        /// </summary>        /// <remarks>        /// This property will always return the actual number of logical processors installed        /// in the system. Note that processors such as Intel Xeons and Pentium 4's with        /// HyperThreading will result in values that are twice the number of physical processor        /// packages that have been installed (i.e. 2 Xeons w/ HT => ConcreteLogicalCpuCount = 4).        /// </remarks>        public static int ConcreteLogicalCpuCount        {            get            {                return Environment.ProcessorCount;            }        }        /// <summary>        /// Gets the approximate speed of the processor, in megahurtz.        /// </summary>        /// <remarks>        /// No accuracy is guaranteed, and precision is dependent on the operating system.        /// If there is an error determining the CPU speed, then 0 will be returned.        /// </remarks>        public static int ApproximateSpeedMhz        {            get            {                const string keyName = @"HARDWARE\DESCRIPTION\System\CentralProcessor\0";                const string valueName = @"~MHz";                int mhz = 0;                try                {                    using (RegistryKey key = Registry.LocalMachine.OpenSubKey(keyName, false))                    {                        if (key != null)                        {                            object value = key.GetValue(valueName);                            mhz = (int)value;                        }                    }                }                catch (Exception)                {                    mhz = 0;                }                return mhz;            }        }        private static ProcessorFeature features = (ProcessorFeature)0;        public static ProcessorFeature Features        {            get            {                if (features == (ProcessorFeature)0)                {                    ProcessorFeature newFeatures = (ProcessorFeature)0;                    // DEP                    if (SafeNativeMethods.IsProcessorFeaturePresent(NativeConstants.PF_NX_ENABLED))                    {                        newFeatures |= ProcessorFeature.DEP;                    }                    // SSE                    if (SafeNativeMethods.IsProcessorFeaturePresent(NativeConstants.PF_XMMI_INSTRUCTIONS_AVAILABLE))                    {                        newFeatures |= ProcessorFeature.SSE;                    }                    // SSE2                    if (SafeNativeMethods.IsProcessorFeaturePresent(NativeConstants.PF_XMMI64_INSTRUCTIONS_AVAILABLE))                    {                        newFeatures |= ProcessorFeature.SSE2;                    }                    // SSE3                    if (SafeNativeMethods.IsProcessorFeaturePresent(NativeConstants.PF_SSE3_INSTRUCTIONS_AVAILABLE))                    {                        newFeatures |= ProcessorFeature.SSE3;                    }                    features = newFeatures;                }                return features;            }        }        public static bool IsFeaturePresent(ProcessorFeature feature)        {            return ((Features & feature) == feature);        }    }}
 |