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.

This commit is contained in:
Michael Möller 2010-10-31 22:08:47 +00:00
parent fcf4876985
commit f238f35eff
23 changed files with 1034 additions and 284 deletions

BIN
External/WinRing0.dll vendored

Binary file not shown.

Binary file not shown.

View File

@ -118,13 +118,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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.

View File

@ -93,15 +93,15 @@ namespace OpenHardwareMonitor.Hardware.CPU {
(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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
(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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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

View File

@ -50,17 +50,17 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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;
}

View File

@ -104,10 +104,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
// 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][][];

View File

@ -107,7 +107,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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);

View File

@ -39,6 +39,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@ -55,6 +56,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
get { return HardwareType.CPU; }
}
public bool HasModelSpecificRegisters {
get { return hasModelSpecificRegisters; }
}
public bool HasTimeStampCounter {
get { return hasTimeStampCounter; }
}
@ -250,14 +262,20 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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();
}
}
}

View File

@ -117,7 +117,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 @@ namespace OpenHardwareMonitor.Hardware.CPU {
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 =

View File

@ -40,6 +40,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security.Permissions;
using System.Reflection;
namespace OpenHardwareMonitor.Hardware {
@ -86,7 +87,8 @@ namespace OpenHardwareMonitor.Hardware {
if (open)
return;
WinRing0.Open();
Ring0.Open();
Opcode.Open();
Add(new Mainboard.MainboardGroup(settings));
Add(new CPU.CPUGroup(settings));
@ -262,7 +264,8 @@ namespace OpenHardwareMonitor.Hardware {
group.Close();
groups.Clear();
WinRing0.Close();
Opcode.Close();
Ring0.Close();
open = false;
}

70
Hardware/IOControlCode.cs Normal file
View File

@ -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 <m.moeller@gmx.ch>.
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
}
}
}

300
Hardware/KernelDriver.cs Normal file
View File

@ -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 <m.moeller@gmx.ch>.
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<T>(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);
}
}
}

View File

@ -60,9 +60,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
fans[i] = null;
}
WinRing0.ReleaseIsaBusMutex();
Ring0.ReleaseIsaBusMutex();
}
}
}

View File

@ -76,9 +76,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
}
WinRing0.ReleaseIsaBusMutex();
Ring0.ReleaseIsaBusMutex();
}
}
}

View File

@ -62,8 +62,8 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
#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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
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 {

View File

@ -84,24 +84,24 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
WriteByte(0, FAN_BIT_REG[i], newByte);
}
WinRing0.ReleaseIsaBusMutex();
Ring0.ReleaseIsaBusMutex();
}
public string GetReport() {
@ -306,7 +306,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
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 @@ namespace OpenHardwareMonitor.Hardware.LPC {
}
r.AppendLine();
WinRing0.ReleaseIsaBusMutex();
Ring0.ReleaseIsaBusMutex();
return r.ToString();
}

244
Hardware/Opcode.cs Normal file
View File

@ -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 <m.moeller@gmx.ch>.
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();
}
}
}

291
Hardware/Ring0.cs Normal file
View File

@ -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 <m.moeller@gmx.ch>.
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();
}
}
}

View File

@ -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 <m.moeller@gmx.ch>.
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<InitializeOlsDelegate>("InitializeOls");
private static readonly DeinitializeOlsDelegate DeinitializeOls =
CreateDelegate<DeinitializeOlsDelegate>("DeinitializeOls");
public static readonly IsCpuidDelegate IsCpuid =
CreateDelegate<IsCpuidDelegate>("IsCpuid");
public static readonly CpuidTxDelegate CpuidTx =
CreateDelegate<CpuidTxDelegate>("CpuidTx");
public static readonly RdmsrDelegate Rdmsr =
CreateDelegate<RdmsrDelegate>("Rdmsr");
public static readonly RdmsrTxDelegate RdmsrTx =
CreateDelegate<RdmsrTxDelegate>("RdmsrTx");
public static readonly ReadIoPortByteDelegate ReadIoPortByte =
CreateDelegate<ReadIoPortByteDelegate>("ReadIoPortByte");
public static readonly WriteIoPortByteDelegate WriteIoPortByte =
CreateDelegate<WriteIoPortByteDelegate>("WriteIoPortByte");
public static readonly ReadPciConfigDwordExDelegate ReadPciConfigDwordEx =
CreateDelegate<ReadPciConfigDwordExDelegate>("ReadPciConfigDwordEx");
public static readonly WritePciConfigDwordExDelegate WritePciConfigDwordEx =
CreateDelegate<WritePciConfigDwordExDelegate>("WritePciConfigDwordEx");
public static readonly RdtscDelegate Rdtsc =
CreateDelegate<RdtscDelegate>("Rdtsc");
public static readonly RdtscTxDelegate RdtscTx =
CreateDelegate<RdtscTxDelegate>("RdtscTx");
public static readonly WrmsrDelegate Wrmsr =
CreateDelegate<WrmsrDelegate>("Wrmsr");
public static readonly WrmsrTxDelegate WrmsrTx =
CreateDelegate<WrmsrTxDelegate>("WrmsrTx");
private static T CreateDelegate<T>(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));
}
}
}

View File

@ -60,6 +60,7 @@
<Compile Include="Hardware\ATI\ADL.cs" />
<Compile Include="Hardware\ATI\ATIGPU.cs" />
<Compile Include="Hardware\ATI\ATIGroup.cs" />
<Compile Include="Hardware\IOControlCode.cs" />
<Compile Include="Hardware\Computer.cs" />
<Compile Include="Hardware\CPU\AMDCPU.cs" />
<Compile Include="Hardware\CPU\GenericCPU.cs" />
@ -69,6 +70,9 @@
<Compile Include="Hardware\CPU\CPUID.cs" />
<Compile Include="Hardware\CPU\CPULoad.cs" />
<Compile Include="Hardware\CPU\IntelCPU.cs" />
<Compile Include="Hardware\Opcode.cs" />
<Compile Include="Hardware\Ring0.cs" />
<Compile Include="Hardware\KernelDriver.cs" />
<Compile Include="Hardware\Hardware.cs" />
<Compile Include="Hardware\HDD\HDD.cs" />
<Compile Include="Hardware\HDD\HDDGroup.cs" />
@ -105,7 +109,6 @@
<Compile Include="Hardware\TBalancer\FTD2XX.cs" />
<Compile Include="Hardware\TBalancer\TBalancer.cs" />
<Compile Include="Hardware\TBalancer\TBalancerGroup.cs" />
<Compile Include="Hardware\WinRing0.cs" />
<Compile Include="Hardware\ISettings.cs" />
<Compile Include="Hardware\HexStringArray.cs" />
<Compile Include="Collections\IReadOnlyArray.cs" />
@ -132,7 +135,10 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Hardware\WinRing0.sys" />
<EmbeddedResource Include="Hardware\WinRing0x64.sys" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -87,17 +87,6 @@ namespace OpenHardwareMonitor {
if (!IsFileAvailable("Aga.Controls.dll"))
return false;
if (IntPtr.Size == 4) {
if (!IsFileAvailable("WinRing0.dll"))
return false;
if (!IsFileAvailable("WinRing0.sys"))
return false;
} else {
if (!IsFileAvailable("WinRing0x64.dll"))
return false;
if (!IsFileAvailable("WinRing0x64.sys"))
return false;
}
return true;
}