# HG changeset patch # User moel.mich # Date 1288562927 0 # Node ID 763675f19ff49f53856b0907336d2d732e048050 # Parent 99b6bab765f8f92f3f1e069e27072b4058e6a575 Replaced the non-kernel code of WinRing0 with a managed implementation. The new implementation should fix Issue 32 and simplify further work on Issue 46. diff -r 99b6bab765f8 -r 763675f19ff4 External/WinRing0.dll Binary file External/WinRing0.dll has changed diff -r 99b6bab765f8 -r 763675f19ff4 External/WinRing0.sys Binary file External/WinRing0.sys has changed diff -r 99b6bab765f8 -r 763675f19ff4 External/WinRing0x64.dll Binary file External/WinRing0x64.dll has changed diff -r 99b6bab765f8 -r 763675f19ff4 External/WinRing0x64.sys Binary file External/WinRing0x64.sys has changed diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/AMD0FCPU.cs --- a/Hardware/CPU/AMD0FCPU.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/AMD0FCPU.cs Sun Oct 31 22:08:47 2010 +0000 @@ -118,13 +118,13 @@ public override void Update() { base.Update(); - if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) { + if (miscellaneousControlAddress != Ring0.InvalidPciAddress) { for (uint i = 0; i < coreTemperatures.Length; i++) { - if (WinRing0.WritePciConfigDwordEx( + if (Ring0.WritePciConfig( miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) { uint value; - if (WinRing0.ReadPciConfigDwordEx( + if (Ring0.ReadPciConfig( miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER, out value)) { @@ -145,7 +145,7 @@ Thread.Sleep(1); uint eax, edx; - if (WinRing0.RdmsrTx(FIDVID_STATUS, out eax, out edx, + if (Ring0.RdmsrTx(FIDVID_STATUS, out eax, out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) { // CurrFID can be found in eax bits 0-5, MaxFID in 16-21 // 8-13 hold StartFID, we don't use that here. diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/AMD10CPU.cs --- a/Hardware/CPU/AMD10CPU.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/AMD10CPU.cs Sun Oct 31 22:08:47 2010 +0000 @@ -93,15 +93,15 @@ (UIntPtr)(1L << cpuid[0][0].Thread)); uint ctlEax, ctlEdx; - WinRing0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx); + Ring0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx); uint ctrEax, ctrEdx; - WinRing0.Rdmsr(PERF_CTR_0, out ctrEax, out ctrEdx); + Ring0.Rdmsr(PERF_CTR_0, out ctrEax, out ctrEdx); timeStampCounterMultiplier = estimateTimeStampCounterMultiplier(); // restore the performance counter registers - WinRing0.Wrmsr(PERF_CTL_0, ctlEax, ctlEdx); - WinRing0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx); + Ring0.Wrmsr(PERF_CTL_0, ctlEax, ctlEdx); + Ring0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx); // restore the thread affinity. NativeMethods.SetThreadAffinityMask(thread, mask); @@ -126,14 +126,14 @@ uint eax, edx; // select event "076h CPU Clocks not Halted" and enable the counter - WinRing0.Wrmsr(PERF_CTL_0, + Ring0.Wrmsr(PERF_CTL_0, (1 << 22) | // enable performance counter (1 << 17) | // count events in user mode (1 << 16) | // count events in operating-system mode 0x76, 0x00000000); // set the counter to 0 - WinRing0.Wrmsr(PERF_CTR_0, 0, 0); + Ring0.Wrmsr(PERF_CTR_0, 0, 0); long ticks = (long)(timeWindow * Stopwatch.Frequency); uint lsbBegin, msbBegin, lsbEnd, msbEnd; @@ -142,11 +142,11 @@ (long)Math.Ceiling(0.001 * ticks); long timeEnd = timeBegin + ticks; while (Stopwatch.GetTimestamp() < timeBegin) { } - WinRing0.Rdmsr(PERF_CTR_0, out lsbBegin, out msbBegin); + Ring0.Rdmsr(PERF_CTR_0, out lsbBegin, out msbBegin); while (Stopwatch.GetTimestamp() < timeEnd) { } - WinRing0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd); + Ring0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd); - WinRing0.Rdmsr(COFVID_STATUS, out eax, out edx); + Ring0.Rdmsr(COFVID_STATUS, out eax, out edx); uint cpuDid = (eax >> 6) & 7; uint cpuFid = eax & 0x1F; double coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid); @@ -188,9 +188,9 @@ public override void Update() { base.Update(); - if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) { + if (miscellaneousControlAddress != Ring0.InvalidPciAddress) { uint value; - if (WinRing0.ReadPciConfigDwordEx(miscellaneousControlAddress, + if (Ring0.ReadPciConfig(miscellaneousControlAddress, REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) { coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f + coreTemperature.Parameters[0].Value; @@ -207,7 +207,7 @@ Thread.Sleep(1); uint curEax, curEdx; - if (WinRing0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx, + if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx, (UIntPtr)(1L << cpuid[i][0].Thread))) { // 8:6 CpuDid: current core divisor ID diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/AMDCPU.cs --- a/Hardware/CPU/AMDCPU.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/AMDCPU.cs Sun Oct 31 22:08:47 2010 +0000 @@ -50,17 +50,17 @@ protected uint GetPciAddress(byte function, ushort deviceId) { // assemble the pci address - uint address = WinRing0.GetPciAddress(PCI_BUS, + uint address = Ring0.GetPciAddress(PCI_BUS, (byte)(PCI_BASE_DEVICE + processorIndex), function); // verify that we have the correct bus, device and function uint deviceVendor; - if (!WinRing0.ReadPciConfigDwordEx( + if (!Ring0.ReadPciConfig( address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor)) - return WinRing0.InvalidPciAddress; + return Ring0.InvalidPciAddress; if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID)) - return WinRing0.InvalidPciAddress; + return Ring0.InvalidPciAddress; return address; } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/CPUGroup.cs --- a/Hardware/CPU/CPUGroup.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/CPUGroup.cs Sun Oct 31 22:08:47 2010 +0000 @@ -104,10 +104,7 @@ // No implementation for cpuid on Unix systems int p = (int)Environment.OSVersion.Platform; if ((p == 4) || (p == 128)) - return; - - if (!WinRing0.IsCpuid()) - return; + return; CPUID[][] processorThreads = GetProcessorThreads(); this.threads = new CPUID[processorThreads.Length][][]; diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/CPUID.cs --- a/Hardware/CPU/CPUID.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/CPUID.cs Sun Oct 31 22:08:47 2010 +0000 @@ -107,7 +107,7 @@ throw new ArgumentOutOfRangeException("thread"); UIntPtr mask = (UIntPtr)(1L << thread); - if (WinRing0.CpuidTx(CPUID_0, 0, + if (Opcode.CpuidTx(CPUID_0, 0, out eax, out ebx, out ecx, out edx, mask)) { if (eax > 0) maxCpuid = eax; @@ -131,7 +131,7 @@ break; } eax = ebx = ecx = edx = 0; - if (WinRing0.CpuidTx(CPUID_EXT, 0, + if (Opcode.CpuidTx(CPUID_EXT, 0, out eax, out ebx, out ecx, out edx, mask)) { if (eax > CPUID_EXT) maxCpuidExt = eax - CPUID_EXT; @@ -149,19 +149,19 @@ cpuidData = new uint[maxCpuid + 1, 4]; for (uint i = 0; i < (maxCpuid + 1); i++) - WinRing0.CpuidTx(CPUID_0 + i, 0, + Opcode.CpuidTx(CPUID_0 + i, 0, out cpuidData[i, 0], out cpuidData[i, 1], out cpuidData[i, 2], out cpuidData[i, 3], mask); cpuidExtData = new uint[maxCpuidExt + 1, 4]; for (uint i = 0; i < (maxCpuidExt + 1); i++) - WinRing0.CpuidTx(CPUID_EXT + i, 0, + Opcode.CpuidTx(CPUID_EXT + i, 0, out cpuidExtData[i, 0], out cpuidExtData[i, 1], out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask); StringBuilder nameBuilder = new StringBuilder(); for (uint i = 2; i <= 4; i++) { - if (WinRing0.CpuidTx(CPUID_EXT + i, 0, + if (Opcode.CpuidTx(CPUID_EXT + i, 0, out eax, out ebx, out ecx, out edx, mask)) { AppendRegister(nameBuilder, eax); diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/GenericCPU.cs --- a/Hardware/CPU/GenericCPU.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/GenericCPU.cs Sun Oct 31 22:08:47 2010 +0000 @@ -39,6 +39,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; +using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -55,6 +56,8 @@ protected readonly int coreCount; protected readonly string name; + private readonly bool hasModelSpecificRegisters; + private readonly bool hasTimeStampCounter; private readonly bool isInvariantTimeStampCounter; private readonly double estimatedTimeStampCounterFrequency; @@ -87,7 +90,14 @@ this.processorIndex = processorIndex; this.coreCount = cpuid.Length; - this.name = cpuid[0][0].Name; + this.name = cpuid[0][0].Name; + + // check if processor has MSRs + if (cpuid[0][0].Data.GetLength(0) > 1 + && (cpuid[0][0].Data[1, 3] & 0x20) != 0) + hasModelSpecificRegisters = true; + else + hasModelSpecificRegisters = false; // check if processor has a TSC if (cpuid[0][0].Data.GetLength(0) > 1 @@ -144,28 +154,26 @@ private static double EstimateTimeStampCounterFrequency(double timeWindow) { long ticks = (long)(timeWindow * Stopwatch.Frequency); - uint lsbBegin, msbBegin, lsbEnd, msbEnd; + ulong countBegin, countEnd; Thread.BeginThreadAffinity(); long timeBegin = Stopwatch.GetTimestamp() + (long)Math.Ceiling(0.001 * ticks); long timeEnd = timeBegin + ticks; while (Stopwatch.GetTimestamp() < timeBegin) { } - WinRing0.Rdtsc(out lsbBegin, out msbBegin); + countBegin = Opcode.Rdtsc(); while (Stopwatch.GetTimestamp() < timeEnd) { } - WinRing0.Rdtsc(out lsbEnd, out msbEnd); + countEnd = Opcode.Rdtsc(); Thread.EndThreadAffinity(); - ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin; - ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd; - return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) / (timeEnd - timeBegin); } + private static void AppendMSRData(StringBuilder r, uint msr, int thread) { uint eax, edx; - if (WinRing0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) { + if (Ring0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) { r.Append(" "); r.Append((msr).ToString("X8", CultureInfo.InvariantCulture)); r.Append(" "); @@ -240,6 +248,10 @@ get { return HardwareType.CPU; } } + public bool HasModelSpecificRegisters { + get { return hasModelSpecificRegisters; } + } + public bool HasTimeStampCounter { get { return hasTimeStampCounter; } } @@ -250,14 +262,20 @@ public override void Update() { if (hasTimeStampCounter && isInvariantTimeStampCounter) { - uint lsb, msb; + + // make sure always the same thread is used + IntPtr thread = NativeMethods.GetCurrentThread(); + UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, + (UIntPtr)(1L << cpuid[0][0].Thread)); // read time before and after getting the TSC to estimate the error long firstTime = Stopwatch.GetTimestamp(); - WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1); + ulong timeStampCount = Opcode.Rdtsc(); long time = Stopwatch.GetTimestamp(); - ulong timeStampCount = ((ulong)msb << 32) | lsb; + // restore the thread affinity mask + NativeMethods.SetThreadAffinityMask(thread, mask); + double delta = ((double)(time - lastTime)) / Stopwatch.Frequency; double error = ((double)(time - firstTime)) / Stopwatch.Frequency; @@ -286,5 +304,16 @@ totalLoad.Value = cpuLoad.GetTotalLoad(); } } + + private static class NativeMethods { + private const string KERNEL = "kernel32.dll"; + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern UIntPtr + SetThreadAffinityMask(IntPtr handle, UIntPtr mask); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr GetCurrentThread(); + } } } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/CPU/IntelCPU.cs --- a/Hardware/CPU/IntelCPU.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/CPU/IntelCPU.cs Sun Oct 31 22:08:47 2010 +0000 @@ -117,7 +117,7 @@ uint eax, edx; tjMax = new float[coreCount]; for (int i = 0; i < coreCount; i++) { - if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax, + if (Ring0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax, out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) { tjMax[i] = (eax >> 16) & 0xFF; } else { @@ -142,14 +142,14 @@ case Microarchitecture.Atom: case Microarchitecture.Core: { uint eax, edx; - if (WinRing0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) { + if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) { timeStampCounterMultiplier = ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1); } } break; case Microarchitecture.Nehalem: { uint eax, edx; - if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) { + if (Ring0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) { timeStampCounterMultiplier = (eax >> 8) & 0xff; } } break; @@ -215,7 +215,7 @@ for (int i = 0; i < coreTemperatures.Length; i++) { uint eax, edx; - if (WinRing0.RdmsrTx( + if (Ring0.RdmsrTx( IA32_THERM_STATUS_MSR, out eax, out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) { // if reading is valid @@ -236,7 +236,7 @@ uint eax, edx; for (int i = 0; i < coreClocks.Length; i++) { System.Threading.Thread.Sleep(1); - if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, + if (Ring0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) { newBusClock = diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/Computer.cs --- a/Hardware/Computer.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/Computer.cs Sun Oct 31 22:08:47 2010 +0000 @@ -40,6 +40,7 @@ using System.Globalization; using System.IO; using System.Security.Permissions; +using System.Reflection; namespace OpenHardwareMonitor.Hardware { @@ -86,7 +87,8 @@ if (open) return; - WinRing0.Open(); + Ring0.Open(); + Opcode.Open(); Add(new Mainboard.MainboardGroup(settings)); Add(new CPU.CPUGroup(settings)); @@ -262,7 +264,8 @@ group.Close(); groups.Clear(); - WinRing0.Close(); + Opcode.Close(); + Ring0.Close(); open = false; } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/IOControlCode.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/IOControlCode.cs Sun Oct 31 22:08:47 2010 +0000 @@ -0,0 +1,70 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Runtime.InteropServices; + +namespace OpenHardwareMonitor.Hardware { + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct IOControlCode { + private uint code; + + public IOControlCode(uint deviceType, uint function, Access access) : + this(deviceType, function, Method.Buffered, access) { } + + public IOControlCode(uint deviceType, uint function, Method method, + Access access) + { + code = (deviceType << 16) | + ((uint)access << 14) | (function << 2) | (uint)method; + } + + public enum Method : uint { + Buffered = 0, + InDirect = 1, + OutDirect = 2, + Neither = 3 + } + + public enum Access : uint { + Any = 0, + Read = 1, + Write = 2 + } + } +} diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/KernelDriver.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/KernelDriver.cs Sun Oct 31 22:08:47 2010 +0000 @@ -0,0 +1,300 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +namespace OpenHardwareMonitor.Hardware { + internal class KernelDriver { + + private string id; + + private SafeFileHandle device; + + public KernelDriver(string id) { + this.id = id; + } + + public bool Install(string path) { + IntPtr manager = NativeMethods.OpenSCManager(null, null, + ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS); + + if (manager == IntPtr.Zero) + return false; + + IntPtr service = NativeMethods.CreateService(manager, id, id, + ServiceAccessRights.SERVICE_ALL_ACCESS, + ServiceType.SERVICE_KERNEL_DRIVER, StartType.SERVICE_DEMAND_START, + ErrorControl.SERVICE_ERROR_NORMAL, path, null, null, null, null, + null); + + if (service == IntPtr.Zero) { + if (Marshal.GetHRForLastWin32Error() == ERROR_SERVICE_EXISTS) + service = NativeMethods.OpenService(manager, id, + ServiceAccessRights.SERVICE_ALL_ACCESS); + else + return false; + } + + if (!NativeMethods.StartService(service, 0, null)) { + if (Marshal.GetHRForLastWin32Error() != ERROR_SERVICE_ALREADY_RUNNING) + return false; + } + + NativeMethods.CloseServiceHandle(service); + NativeMethods.CloseServiceHandle(manager); + + return true; + } + + public bool Open() { + device = new SafeFileHandle(NativeMethods.CreateFile(@"\\.\" + id, + FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE, 0, IntPtr.Zero, + CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL, + IntPtr.Zero), true); + + if (device.IsInvalid) { + device.Close(); + device.Dispose(); + device = null; + } + + return device != null; + } + + public bool IsOpen { + get { return device != null; } + } + + public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer) { + if (device == null) + return false; + + uint bytesReturned; + bool b = NativeMethods.DeviceIoControl(device, ioControlCode, + inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer), + null, 0, out bytesReturned, IntPtr.Zero); + return b; + } + + public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer, + ref T outBuffer) + { + if (device == null) + return false; + + object boxedOutBuffer = outBuffer; + uint bytesReturned; + bool b = NativeMethods.DeviceIoControl(device, ioControlCode, + inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer), + boxedOutBuffer, (uint)Marshal.SizeOf(boxedOutBuffer), + out bytesReturned, IntPtr.Zero); + outBuffer = (T)boxedOutBuffer; + return b; + } + + public void Close() { + if (device != null) { + device.Close(); + device.Dispose(); + device = null; + } + } + + public bool Delete() { + IntPtr manager = NativeMethods.OpenSCManager(null, null, + ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS); + + if (manager == IntPtr.Zero) + return false; + + IntPtr service = NativeMethods.OpenService(manager, id, + ServiceAccessRights.SERVICE_ALL_ACCESS); + + if (service == IntPtr.Zero) + return true; + + ServiceStatus status = new ServiceStatus(); + NativeMethods.ControlService(service, ServiceControl.SERVICE_CONTROL_STOP, + ref status); + + NativeMethods.DeleteService(service); + + NativeMethods.CloseServiceHandle(service); + NativeMethods.CloseServiceHandle(manager); + + return true; + } + + private enum ServiceAccessRights : uint { + SERVICE_ALL_ACCESS = 0xF01FF + } + + private enum ServiceControlManagerAccessRights : uint { + SC_MANAGER_ALL_ACCESS = 0xF003F + } + + private enum ServiceType : uint { + SERVICE_KERNEL_DRIVER = 1, + SERVICE_FILE_SYSTEM_DRIVER = 2 + } + + private enum StartType : uint { + SERVICE_BOOT_START = 0, + SERVICE_SYSTEM_START = 1, + SERVICE_AUTO_START = 2, + SERVICE_DEMAND_START = 3, + SERVICE_DISABLED = 4 + } + + private enum ErrorControl : uint { + SERVICE_ERROR_IGNORE = 0, + SERVICE_ERROR_NORMAL = 1, + SERVICE_ERROR_SEVERE = 2, + SERVICE_ERROR_CRITICAL = 3 + } + + private enum ServiceControl : uint { + SERVICE_CONTROL_STOP = 1, + SERVICE_CONTROL_PAUSE = 2, + SERVICE_CONTROL_CONTINUE = 3, + SERVICE_CONTROL_INTERROGATE = 4, + SERVICE_CONTROL_SHUTDOWN = 5, + SERVICE_CONTROL_PARAMCHANGE = 6, + SERVICE_CONTROL_NETBINDADD = 7, + SERVICE_CONTROL_NETBINDREMOVE = 8, + SERVICE_CONTROL_NETBINDENABLE = 9, + SERVICE_CONTROL_NETBINDDISABLE = 10, + SERVICE_CONTROL_DEVICEEVENT = 11, + SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12, + SERVICE_CONTROL_POWEREVENT = 13, + SERVICE_CONTROL_SESSIONCHANGE = 14 + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct ServiceStatus { + public uint dwServiceType; + public uint dwCurrentState; + public uint dwControlsAccepted; + public uint dwWin32ExitCode; + public uint dwServiceSpecificExitCode; + public uint dwCheckPoint; + public uint dwWaitHint; + } + + private enum FileAccess : uint { + GENERIC_READ = 0x80000000, + GENERIC_WRITE = 0x40000000 + } + + private enum CreationDisposition : uint { + CREATE_NEW = 1, + CREATE_ALWAYS = 2, + OPEN_EXISTING = 3, + OPEN_ALWAYS = 4, + TRUNCATE_EXISTING = 5 + } + + private enum FileAttributes : uint { + FILE_ATTRIBUTE_NORMAL = 0x80 + } + + private const int + ERROR_SERVICE_EXISTS = unchecked((int)0x80070431), + ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420); + + private static class NativeMethods { + private const string ADVAPI = "advapi32.dll"; + private const string KERNEL = "kernel32.dll"; + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr OpenSCManager(string machineName, + string databaseName, ServiceControlManagerAccessRights dwAccess); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseServiceHandle(IntPtr hSCObject); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + public static extern IntPtr CreateService(IntPtr hSCManager, + string lpServiceName, string lpDisplayName, + ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType, + StartType dwStartType, ErrorControl dwErrorControl, + string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, + string lpDependencies, string lpServiceStartName, string lpPassword); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + public static extern IntPtr OpenService(IntPtr hSCManager, + string lpServiceName, ServiceAccessRights dwDesiredAccess); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DeleteService(IntPtr hService); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool StartService(IntPtr hService, + uint dwNumServiceArgs, string[] lpServiceArgVectors); + + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ControlService(IntPtr hService, + ServiceControl dwControl, ref ServiceStatus lpServiceStatus); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern bool DeviceIoControl(SafeFileHandle device, + IOControlCode ioControlCode, + [MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer, + uint inBufferSize, + [MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer, + uint nOutBufferSize, out uint bytesReturned, IntPtr overlapped); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi, + SetLastError = true)] + public static extern IntPtr CreateFile(string lpFileName, + FileAccess dwDesiredAccess, uint dwShareMode, + IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition, + FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile); + } + } +} diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/LPC/F718XX.cs --- a/Hardware/LPC/F718XX.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/LPC/F718XX.cs Sun Oct 31 22:08:47 2010 +0000 @@ -60,9 +60,9 @@ new byte[] { 0xA0, 0xB0, 0xC0, 0xD0 }; private byte ReadByte(byte register) { - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + ADDRESS_REGISTER_OFFSET), register); - return WinRing0.ReadIoPortByte((ushort)(address + DATA_REGISTER_OFFSET)); + return Ring0.ReadIoPort((ushort)(address + DATA_REGISTER_OFFSET)); } public byte? ReadGPIO(int index) { @@ -94,7 +94,7 @@ r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture)); r.AppendLine(); - if (!WinRing0.WaitIsaBusMutex(100)) + if (!Ring0.WaitIsaBusMutex(100)) return r.ToString(); r.AppendLine("Hardware Monitor Registers"); @@ -114,13 +114,13 @@ } r.AppendLine(); - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); return r.ToString(); } public void Update() { - if (!WinRing0.WaitIsaBusMutex(10)) + if (!Ring0.WaitIsaBusMutex(10)) return; for (int i = 0; i < voltages.Length; i++) { @@ -173,7 +173,7 @@ fans[i] = null; } - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); } } } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/LPC/IT87XX.cs --- a/Hardware/LPC/IT87XX.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/LPC/IT87XX.cs Sun Oct 31 22:08:47 2010 +0000 @@ -76,9 +76,9 @@ private const byte VOLTAGE_BASE_REG = 0x20; private byte ReadByte(byte register, out bool valid) { - WinRing0.WriteIoPortByte(addressReg, register); - byte value = WinRing0.ReadIoPortByte(dataReg); - valid = register == WinRing0.ReadIoPortByte(addressReg); + Ring0.WriteIoPort(addressReg, register); + byte value = Ring0.ReadIoPort(dataReg); + valid = register == Ring0.ReadIoPort(addressReg); return value; } @@ -86,14 +86,14 @@ if (index >= gpioCount) return null; - return WinRing0.ReadIoPortByte((ushort)(gpioAddress + index)); + return Ring0.ReadIoPort((ushort)(gpioAddress + index)); } public void WriteGPIO(int index, byte value) { if (index >= gpioCount) return; - WinRing0.WriteIoPortByte((ushort)(gpioAddress + index), value); + Ring0.WriteIoPort((ushort)(gpioAddress + index), value); } public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) { @@ -162,7 +162,7 @@ gpioAddress.ToString("X4", CultureInfo.InvariantCulture)); r.AppendLine(); - if (!WinRing0.WaitIsaBusMutex(100)) + if (!Ring0.WaitIsaBusMutex(100)) return r.ToString(); r.AppendLine("Environment Controller Registers"); @@ -194,13 +194,13 @@ r.AppendLine(); r.AppendLine(); - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); return r.ToString(); } public void Update() { - if (!WinRing0.WaitIsaBusMutex(10)) + if (!Ring0.WaitIsaBusMutex(10)) return; for (int i = 0; i < voltages.Length; i++) { @@ -246,7 +246,7 @@ } } - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); } } } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/LPC/LPCIO.cs --- a/Hardware/LPC/LPCIO.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/LPC/LPCIO.cs Sun Oct 31 22:08:47 2010 +0000 @@ -62,8 +62,8 @@ private const byte BASE_ADDRESS_REGISTER = 0x60; private byte ReadByte(byte register) { - WinRing0.WriteIoPortByte(registerPort, register); - return WinRing0.ReadIoPortByte(valuePort); + Ring0.WriteIoPort(registerPort, register); + return Ring0.ReadIoPort(valuePort); } private ushort ReadWord(byte register) { @@ -72,8 +72,8 @@ } private void Select(byte logicalDeviceNumber) { - WinRing0.WriteIoPortByte(registerPort, DEVCIE_SELECT_REGISTER); - WinRing0.WriteIoPortByte(valuePort, logicalDeviceNumber); + Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER); + Ring0.WriteIoPort(valuePort, logicalDeviceNumber); } private void ReportUnknownChip(string type, int chip) { @@ -99,12 +99,12 @@ private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04; private void WinbondFintekEnter() { - WinRing0.WriteIoPortByte(registerPort, 0x87); - WinRing0.WriteIoPortByte(registerPort, 0x87); + Ring0.WriteIoPort(registerPort, 0x87); + Ring0.WriteIoPort(registerPort, 0x87); } private void WinbondFintekExit() { - WinRing0.WriteIoPortByte(registerPort, 0xAA); + Ring0.WriteIoPort(registerPort, 0xAA); } private bool DetectWinbondFintek() { @@ -308,15 +308,15 @@ private const byte IT87_CHIP_VERSION_REGISTER = 0x22; private void IT87Enter() { - WinRing0.WriteIoPortByte(registerPort, 0x87); - WinRing0.WriteIoPortByte(registerPort, 0x01); - WinRing0.WriteIoPortByte(registerPort, 0x55); - WinRing0.WriteIoPortByte(registerPort, 0x55); + Ring0.WriteIoPort(registerPort, 0x87); + Ring0.WriteIoPort(registerPort, 0x01); + Ring0.WriteIoPort(registerPort, 0x55); + Ring0.WriteIoPort(registerPort, 0x55); } private void IT87Exit() { - WinRing0.WriteIoPortByte(registerPort, CONFIGURATION_CONTROL_REGISTER); - WinRing0.WriteIoPortByte(valuePort, 0x02); + Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER); + Ring0.WriteIoPort(valuePort, 0x02); } private bool DetectIT87() { @@ -392,11 +392,11 @@ #region SMSC private void SMSCEnter() { - WinRing0.WriteIoPortByte(registerPort, 0x55); + Ring0.WriteIoPort(registerPort, 0x55); } private void SMSCExit() { - WinRing0.WriteIoPortByte(registerPort, 0xAA); + Ring0.WriteIoPort(registerPort, 0xAA); } private bool DetectSMSC() { @@ -438,15 +438,15 @@ } public LPCIO() { - if (!WinRing0.IsAvailable) + if (!Ring0.IsOpen) return; - if (!WinRing0.WaitIsaBusMutex(100)) + if (!Ring0.WaitIsaBusMutex(100)) return; Detect(); - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); } public ISuperIO[] SuperIO { diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/LPC/W836XX.cs --- a/Hardware/LPC/W836XX.cs Mon Oct 18 07:18:14 2010 +0000 +++ b/Hardware/LPC/W836XX.cs Sun Oct 31 22:08:47 2010 +0000 @@ -84,24 +84,24 @@ private readonly byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 }; private byte ReadByte(byte bank, byte register) { - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER); - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + DATA_REGISTER_OFFSET), bank); - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + ADDRESS_REGISTER_OFFSET), register); - return WinRing0.ReadIoPortByte( + return Ring0.ReadIoPort( (ushort)(address + DATA_REGISTER_OFFSET)); } private void WriteByte(byte bank, byte register, byte value) { - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER); - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + DATA_REGISTER_OFFSET), bank); - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + ADDRESS_REGISTER_OFFSET), register); - WinRing0.WriteIoPortByte( + Ring0.WriteIoPort( (ushort)(address + DATA_REGISTER_OFFSET), value); } @@ -203,7 +203,7 @@ public float?[] Fans { get { return fans; } } public void Update() { - if (!WinRing0.WaitIsaBusMutex(10)) + if (!Ring0.WaitIsaBusMutex(10)) return; for (int i = 0; i < voltages.Length; i++) { @@ -291,7 +291,7 @@ WriteByte(0, FAN_BIT_REG[i], newByte); } - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); } public string GetReport() { @@ -306,7 +306,7 @@ r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture)); r.AppendLine(); - if (!WinRing0.WaitIsaBusMutex(100)) + if (!Ring0.WaitIsaBusMutex(100)) return r.ToString(); r.AppendLine("Hardware Monitor Registers"); @@ -340,7 +340,7 @@ } r.AppendLine(); - WinRing0.ReleaseIsaBusMutex(); + Ring0.ReleaseIsaBusMutex(); return r.ToString(); } diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/Opcode.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/Opcode.cs Sun Oct 31 22:08:47 2010 +0000 @@ -0,0 +1,244 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.Runtime.InteropServices; + +namespace OpenHardwareMonitor.Hardware { + internal static class Opcode { + private static IntPtr codeBuffer; + + public static void Open() { + // No implementation for Unix systems + int p = (int)Environment.OSVersion.Platform; + if ((p == 4) || (p == 128)) + return; + + byte[] rdtscCode; + byte[] cpuidCode; + if (IntPtr.Size == 4) { + rdtscCode = RDTSC_32; + cpuidCode = CPUID_32; + } else { + rdtscCode = RDTSC_64; + cpuidCode = CPUID_64; + } + + codeBuffer = NativeMethods.VirtualAlloc(IntPtr.Zero, + (UIntPtr)(rdtscCode.Length + cpuidCode.Length), + AllocationType.COMMIT | AllocationType.RESERVE, + MemoryProtection.EXECUTE_READWRITE); + + Marshal.Copy(rdtscCode, 0, codeBuffer, rdtscCode.Length); + + Rdtsc = Marshal.GetDelegateForFunctionPointer( + codeBuffer, typeof(RdtscDelegate)) as RdtscDelegate; + + IntPtr cpuidAddress = (IntPtr)((long)codeBuffer + rdtscCode.Length); + Marshal.Copy(cpuidCode, 0, cpuidAddress, cpuidCode.Length); + + Cpuid = Marshal.GetDelegateForFunctionPointer( + cpuidAddress, typeof(CpuidDelegate)) as CpuidDelegate; + } + + public static void Close() { + Rdtsc = null; + Cpuid = null; + + NativeMethods.VirtualFree(codeBuffer, UIntPtr.Zero, + FreeType.RELEASE); + } + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate ulong RdtscDelegate(); + + public static RdtscDelegate Rdtsc; + + // unsigned __int64 __stdcall rdtsc() { + // return __rdtsc(); + // } + + private static readonly byte[] RDTSC_32 = new byte[] { + 0x0F, 0x31, // rdtsc + 0xC3 // ret + }; + + private static readonly byte[] RDTSC_64 = new byte[] { + 0x0F, 0x31, // rdtsc + 0x48, 0xC1, 0xE2, 0x20, // shl rdx,20h + 0x48, 0x0B, 0xC2, // or rax,rdx + 0xC3 // ret + }; + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool CpuidDelegate(uint index, uint ecxValue, + out uint eax, out uint ebx, out uint ecx, out uint edx); + + public static CpuidDelegate Cpuid; + + + // void __stdcall cpuidex(unsigned int index, unsigned int ecxValue, + // unsigned int* eax, unsigned int* ebx, unsigned int* ecx, + // unsigned int* edx) + // { + // int info[4]; + // __cpuidex(info, index, ecxValue); + // *eax = info[0]; + // *ebx = info[1]; + // *ecx = info[2]; + // *edx = info[3]; + // } + + private static readonly byte[] CPUID_32 = new byte[] { + 0x55, // push ebp + 0x8B, 0xEC, // mov ebp,esp + 0x83, 0xEC, 0x10, // sub esp,10h + 0x8B, 0x45, 0x08, // mov eax,dword ptr [ebp+8] + 0x8B, 0x4D, 0x0C, // mov ecx,dword ptr [ebp+0Ch] + 0x53, // push ebx + 0x0F, 0xA2, // cpuid + 0x56, // push esi + 0x8D, 0x75, 0xF0, // lea esi,[info] + 0x89, 0x06, // mov dword ptr [esi],eax + 0x8B, 0x45, 0x10, // mov eax,dword ptr [eax] + 0x89, 0x5E, 0x04, // mov dword ptr [esi+4],ebx + 0x89, 0x4E, 0x08, // mov dword ptr [esi+8],ecx + 0x89, 0x56, 0x0C, // mov dword ptr [esi+0Ch],edx + 0x8B, 0x4D, 0xF0, // mov ecx,dword ptr [info] + 0x89, 0x08, // mov dword ptr [eax],ecx + 0x8B, 0x45, 0x14, // mov eax,dword ptr [ebx] + 0x8B, 0x4D, 0xF4, // mov ecx,dword ptr [ebp-0Ch] + 0x89, 0x08, // mov dword ptr [eax],ecx + 0x8B, 0x45, 0x18, // mov eax,dword ptr [ecx] + 0x8B, 0x4D, 0xF8, // mov ecx,dword ptr [ebp-8] + 0x89, 0x08, // mov dword ptr [eax],ecx + 0x8B, 0x45, 0x1C, // mov eax,dword ptr [edx] + 0x8B, 0x4D, 0xFC, // mov ecx,dword ptr [ebp-4] + 0x5E, // pop esi + 0x89, 0x08, // mov dword ptr [eax],ecx + 0x5B, // pop ebx + 0xC9, // leave + 0xC2, 0x18, 0x00 // ret 18h + }; + + private static readonly byte[] CPUID_64 = new byte[] { + 0x48, 0x89, 0x5C, 0x24, 0x08, // mov qword ptr [rsp+8],rbx + 0x8B, 0xC1, // mov eax,ecx + 0x8B, 0xCA, // mov ecx,edx + 0x0F, 0xA2, // cpuid + 0x41, 0x89, 0x00, // mov dword ptr [r8],eax + 0x48, 0x8B, 0x44, 0x24, 0x28, // mov rax,qword ptr [ecx] + 0x41, 0x89, 0x19, // mov dword ptr [r9],ebx + 0x48, 0x8B, 0x5C, 0x24, 0x08, // mov rbx,qword ptr [rsp+8] + 0x89, 0x08, // mov dword ptr [rax],ecx + 0x48, 0x8B, 0x44, 0x24, 0x30, // mov rax,qword ptr [rsp+30h] + 0x89, 0x10, // mov dword ptr [rax],edx + 0xC3 // ret + }; + + public static bool CpuidTx(uint index, uint ecxValue, + out uint eax, out uint ebx, out uint ecx, out uint edx, + UIntPtr threadAffinityMask) { + + IntPtr thread = NativeMethods.GetCurrentThread(); + UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, + threadAffinityMask); + + if (mask == UIntPtr.Zero) { + eax = ebx = ecx = edx = 0; + return false; + } + + Cpuid(index, ecxValue, out eax, out ebx, out ecx, out edx); + + NativeMethods.SetThreadAffinityMask(thread, mask); + + return true; + } + + [Flags()] + public enum AllocationType : uint { + COMMIT = 0x1000, + RESERVE = 0x2000, + RESET = 0x80000, + LARGE_PAGES = 0x20000000, + PHYSICAL = 0x400000, + TOP_DOWN = 0x100000, + WRITE_WATCH = 0x200000 + } + + [Flags()] + public enum MemoryProtection : uint { + EXECUTE = 0x10, + EXECUTE_READ = 0x20, + EXECUTE_READWRITE = 0x40, + EXECUTE_WRITECOPY = 0x80, + NOACCESS = 0x01, + READONLY = 0x02, + READWRITE = 0x04, + WRITECOPY = 0x08, + GUARD = 0x100, + NOCACHE = 0x200, + WRITECOMBINE = 0x400 + } + + [Flags] + enum FreeType { + DECOMMIT = 0x4000, + RELEASE = 0x8000 + } + + private static class NativeMethods { + private const string KERNEL = "kernel32.dll"; + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, + AllocationType flAllocationType, MemoryProtection flProtect); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern bool VirtualFree(IntPtr lpAddress, UIntPtr dwSize, + FreeType dwFreeType); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern UIntPtr + SetThreadAffinityMask(IntPtr handle, UIntPtr mask); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr GetCurrentThread(); + } + } +} diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/Ring0.cs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hardware/Ring0.cs Sun Oct 31 22:08:47 2010 +0000 @@ -0,0 +1,291 @@ +/* + + Version: MPL 1.1/GPL 2.0/LGPL 2.1 + + The contents of this file are subject to the Mozilla Public License Version + 1.1 (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" basis, + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + for the specific language governing rights and limitations under the License. + + The Original Code is the Open Hardware Monitor code. + + The Initial Developer of the Original Code is + Michael Möller . + Portions created by the Initial Developer are Copyright (C) 2010 + the Initial Developer. All Rights Reserved. + + Contributor(s): + + Alternatively, the contents of this file may be used under the terms of + either the GNU General Public License Version 2 or later (the "GPL"), or + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + in which case the provisions of the GPL or the LGPL are applicable instead + of those above. If you wish to allow use of your version of this file only + under the terms of either the GPL or the LGPL, and not to allow others to + use your version of this file under the terms of the MPL, indicate your + decision by deleting the provisions above and replace them with the notice + and other provisions required by the GPL or the LGPL. If you do not delete + the provisions above, a recipient may use your version of this file under + the terms of any one of the MPL, the GPL or the LGPL. + +*/ + +using System; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +namespace OpenHardwareMonitor.Hardware { + internal static class Ring0 { + + private static KernelDriver driver; + private static Mutex isaBusMutex; + + private const uint OLS_TYPE = 40000; + private static IOControlCode + IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801, + IOControlCode.Access.Any), + IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800, + IOControlCode.Access.Any), + IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821, + IOControlCode.Access.Any), + IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822, + IOControlCode.Access.Any), + IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833, + IOControlCode.Access.Read), + IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836, + IOControlCode.Access.Write), + IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851, + IOControlCode.Access.Read), + IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852, + IOControlCode.Access.Write); + + private static bool ExtractDriver(string fileName) { + string resourceName = "OpenHardwareMonitor.Hardware." + + (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys"); + + string[] names = + Assembly.GetExecutingAssembly().GetManifestResourceNames(); + byte[] buffer = null; + for (int i = 0; i < names.Length; i++) { + if (names[i].Replace('\\', '.') == resourceName) { + using (Stream stream = Assembly.GetExecutingAssembly(). + GetManifestResourceStream(names[i])) + { + buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + } + } + } + + if (buffer == null) + return false; + + using (FileStream target = new FileStream(fileName, FileMode.Create)) { + target.Write(buffer, 0, buffer.Length); + } + + return true; + } + + public static void Open() { + if (driver != null) + return; + + driver = new KernelDriver("WinRing0_1_2_0"); + driver.Open(); + + if (!driver.IsOpen) { + string fileName = Path.GetTempFileName(); + if (ExtractDriver(fileName)) { + + driver.Install(fileName); + File.Delete(fileName); + + driver.Open(); + + if (!driver.IsOpen) + driver.Delete(); + } + } + + if (!driver.IsOpen) + driver = null; + + isaBusMutex = new Mutex(false, "Access_ISABUS.HTP.Method"); + } + + public static bool IsOpen { + get { return driver != null; } + } + + public static void Close() { + if (driver == null) + return; + + uint refCount = 0; + driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount); + + driver.Close(); + + if (refCount <= 1) + driver.Delete(); + + driver = null; + + isaBusMutex.Close(); + } + + public static bool WaitIsaBusMutex(int millisecondsTimeout) { + try { + return isaBusMutex.WaitOne(millisecondsTimeout, false); + } catch (AbandonedMutexException) { return false; } + catch (InvalidOperationException) { return false; } + } + + public static void ReleaseIsaBusMutex() { + isaBusMutex.ReleaseMutex(); + } + + public static bool Rdmsr(uint index, out uint eax, out uint edx) { + if (driver == null) { + eax = 0; + edx = 0; + return false; + } + + ulong buffer = 0; + bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index, + ref buffer); + + edx = (uint)((buffer >> 32) & 0xFFFFFFFF); + eax = (uint)(buffer & 0xFFFFFFFF); + return result; + } + + public static bool RdmsrTx(uint index, out uint eax, out uint edx, + UIntPtr threadAffinityMask) + { + IntPtr thread = NativeMethods.GetCurrentThread(); + UIntPtr mask = NativeMethods.SetThreadAffinityMask(thread, + threadAffinityMask); + + bool result = Rdmsr(index, out eax, out edx); + + NativeMethods.SetThreadAffinityMask(thread, mask); + return result; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct WrmsrInput { + public uint Register; + public ulong Value; + } + + public static bool Wrmsr(uint index, uint eax, uint edx) { + if (driver == null) + return false; + + WrmsrInput input = new WrmsrInput(); + input.Register = index; + input.Value = ((ulong)edx << 32) | eax; + + return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input); + } + + public static byte ReadIoPort(uint port) { + if (driver == null) + return 0; + + uint value = 0; + driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value); + + return (byte)(value & 0xFF); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct WriteIoPortInput { + public uint PortNumber; + public byte Value; + } + + public static void WriteIoPort(uint port, byte value) { + if (driver == null) + return; + + WriteIoPortInput input = new WriteIoPortInput(); + input.PortNumber = port; + input.Value = value; + + driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input); + } + + public const uint InvalidPciAddress = 0xFFFFFFFF; + + public static uint GetPciAddress(byte bus, byte device, byte function) { + return + (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7)); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct ReadPciConfigInput { + public uint PciAddress; + public uint RegAddress; + } + + public static bool ReadPciConfig(uint pciAddress, uint regAddress, + out uint value) + { + if (driver == null || (regAddress & 3) != 0) { + value = 0; + return false; + } + + ReadPciConfigInput input = new ReadPciConfigInput(); + input.PciAddress = pciAddress; + input.RegAddress = regAddress; + + value = 0; + return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input, + ref value); + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct WritePciConfigInput { + public uint PciAddress; + public uint RegAddress; + public uint Value; + } + + public static bool WritePciConfig(uint pciAddress, uint regAddress, + uint value) + { + if (driver == null || (regAddress & 3) != 0) + return false; + + WritePciConfigInput input = new WritePciConfigInput(); + input.PciAddress = pciAddress; + input.RegAddress = regAddress; + input.Value = value; + + return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input); + } + + private static class NativeMethods { + private const string KERNEL = "kernel32.dll"; + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern UIntPtr + SetThreadAffinityMask(IntPtr handle, UIntPtr mask); + + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)] + public static extern IntPtr GetCurrentThread(); + } + } +} diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/WinRing0.cs --- a/Hardware/WinRing0.cs Mon Oct 18 07:18:14 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +0,0 @@ -/* - - Version: MPL 1.1/GPL 2.0/LGPL 2.1 - - The contents of this file are subject to the Mozilla Public License Version - 1.1 (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS IS" basis, - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - for the specific language governing rights and limitations under the License. - - The Original Code is the Open Hardware Monitor code. - - The Initial Developer of the Original Code is - Michael Möller . - Portions created by the Initial Developer are Copyright (C) 2009-2010 - the Initial Developer. All Rights Reserved. - - Contributor(s): - - Alternatively, the contents of this file may be used under the terms of - either the GNU General Public License Version 2 or later (the "GPL"), or - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - in which case the provisions of the GPL or the LGPL are applicable instead - of those above. If you wish to allow use of your version of this file only - under the terms of either the GPL or the LGPL, and not to allow others to - use your version of this file under the terms of the MPL, indicate your - decision by deleting the provisions above and replace them with the notice - and other provisions required by the GPL or the LGPL. If you do not delete - the provisions above, a recipient may use your version of this file under - the terms of any one of the MPL, the GPL or the LGPL. - -*/ - -using System; -using System.Runtime.InteropServices; -using System.Threading; - -namespace OpenHardwareMonitor.Hardware { - - internal class WinRing0 { - - private WinRing0() { } - - public enum OlsDllStatus{ - OLS_DLL_NO_ERROR = 0, - OLS_DLL_UNSUPPORTED_PLATFORM = 1, - OLS_DLL_DRIVER_NOT_LOADED = 2, - OLS_DLL_DRIVER_NOT_FOUND = 3, - OLS_DLL_DRIVER_UNLOADED = 4, - OLS_DLL_DRIVER_NOT_LOADED_ON_NETWORK = 5, - OLS_DLL_UNKNOWN_ERROR = 9 - } - - private static bool available; - private static Mutex isaBusMutex; - - private static string GetDllName() { - int p = (int)Environment.OSVersion.Platform; - if ((p == 4) || (p == 128)) { - if (IntPtr.Size == 4) { - return "libring0.so"; - } else { - return "libring0x64.so"; - } - } else { - if (IntPtr.Size == 4) { - return "WinRing0.dll"; - } else { - return "WinRing0x64.dll"; - } - } - } - - private delegate bool InitializeOlsDelegate(); - private delegate void DeinitializeOlsDelegate(); - - public delegate bool IsCpuidDelegate(); - public delegate bool CpuidTxDelegate(uint index, uint ecxValue, - out uint eax, out uint ebx, out uint ecx, out uint edx, - UIntPtr threadAffinityMask); - public delegate bool RdmsrDelegate(uint index, out uint eax, out uint edx); - public delegate bool RdmsrTxDelegate(uint index, out uint eax, out uint edx, - UIntPtr threadAffinityMask); - public delegate byte ReadIoPortByteDelegate(ushort port); - public delegate void WriteIoPortByteDelegate(ushort port, byte value); - public delegate bool ReadPciConfigDwordExDelegate(uint pciAddress, - uint regAddress, out uint value); - public delegate bool WritePciConfigDwordExDelegate(uint pciAddress, - uint regAddress, uint value); - public delegate bool RdtscDelegate(out uint eax, out uint edx); - public delegate bool RdtscTxDelegate(out uint eax, out uint edx, - UIntPtr threadAffinityMask); - public delegate bool WrmsrDelegate(uint index, uint eax, uint edx); - public delegate bool WrmsrTxDelegate(uint index, uint eax, uint edx, - UIntPtr threadAffinityMask); - - private static readonly InitializeOlsDelegate InitializeOls = - CreateDelegate("InitializeOls"); - private static readonly DeinitializeOlsDelegate DeinitializeOls = - CreateDelegate("DeinitializeOls"); - - public static readonly IsCpuidDelegate IsCpuid = - CreateDelegate("IsCpuid"); - public static readonly CpuidTxDelegate CpuidTx = - CreateDelegate("CpuidTx"); - public static readonly RdmsrDelegate Rdmsr = - CreateDelegate("Rdmsr"); - public static readonly RdmsrTxDelegate RdmsrTx = - CreateDelegate("RdmsrTx"); - public static readonly ReadIoPortByteDelegate ReadIoPortByte = - CreateDelegate("ReadIoPortByte"); - public static readonly WriteIoPortByteDelegate WriteIoPortByte = - CreateDelegate("WriteIoPortByte"); - public static readonly ReadPciConfigDwordExDelegate ReadPciConfigDwordEx = - CreateDelegate("ReadPciConfigDwordEx"); - public static readonly WritePciConfigDwordExDelegate WritePciConfigDwordEx = - CreateDelegate("WritePciConfigDwordEx"); - public static readonly RdtscDelegate Rdtsc = - CreateDelegate("Rdtsc"); - public static readonly RdtscTxDelegate RdtscTx = - CreateDelegate("RdtscTx"); - public static readonly WrmsrDelegate Wrmsr = - CreateDelegate("Wrmsr"); - public static readonly WrmsrTxDelegate WrmsrTx = - CreateDelegate("WrmsrTx"); - - private static T CreateDelegate(string entryPoint) where T : class { - DllImportAttribute attribute = new DllImportAttribute(GetDllName()); - attribute.CallingConvention = CallingConvention.Winapi; - attribute.PreserveSig = true; - attribute.EntryPoint = entryPoint; - attribute.CharSet = CharSet.Auto; - T result; - PInvokeDelegateFactory.CreateDelegate(attribute, out result); - return result; - } - - public static void Open() { - try { - if (InitializeOls != null && InitializeOls()) - available = true; - } catch (DllNotFoundException) { } - - isaBusMutex = new Mutex(false, "Access_ISABUS.HTP.Method"); - } - - public static bool IsAvailable { - get { return available; } - } - - public static void Close() { - if (available) - DeinitializeOls(); - isaBusMutex.Close(); - } - - public static bool WaitIsaBusMutex(int millisecondsTimeout) { - try { - return isaBusMutex.WaitOne(millisecondsTimeout, false); - } catch (AbandonedMutexException) { return false; } - catch (InvalidOperationException) { return false; } - } - - public static void ReleaseIsaBusMutex() { - isaBusMutex.ReleaseMutex(); - } - - public const uint InvalidPciAddress = 0xFFFFFFFF; - - public static uint GetPciAddress(byte bus, byte device, byte function) { - return - (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7)); - } - } -} diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/WinRing0.sys Binary file Hardware/WinRing0.sys has changed diff -r 99b6bab765f8 -r 763675f19ff4 Hardware/WinRing0x64.sys Binary file Hardware/WinRing0x64.sys has changed diff -r 99b6bab765f8 -r 763675f19ff4 OpenHardwareMonitorLib.csproj --- a/OpenHardwareMonitorLib.csproj Mon Oct 18 07:18:14 2010 +0000 +++ b/OpenHardwareMonitorLib.csproj Sun Oct 31 22:08:47 2010 +0000 @@ -60,6 +60,7 @@ + @@ -69,6 +70,9 @@ + + + @@ -105,7 +109,6 @@ - @@ -132,7 +135,10 @@ true - + + + +