mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-09-01 14:55:13 +00:00
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:
BIN
External/WinRing0.dll
vendored
BIN
External/WinRing0.dll
vendored
Binary file not shown.
BIN
External/WinRing0x64.dll
vendored
BIN
External/WinRing0x64.dll
vendored
Binary file not shown.
@@ -118,13 +118,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
public override void Update() {
|
public override void Update() {
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
|
if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
|
||||||
for (uint i = 0; i < coreTemperatures.Length; i++) {
|
for (uint i = 0; i < coreTemperatures.Length; i++) {
|
||||||
if (WinRing0.WritePciConfigDwordEx(
|
if (Ring0.WritePciConfig(
|
||||||
miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
|
miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
|
||||||
i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) {
|
i > 0 ? THERM_SENSE_CORE_SEL_CPU1 : THERM_SENSE_CORE_SEL_CPU0)) {
|
||||||
uint value;
|
uint value;
|
||||||
if (WinRing0.ReadPciConfigDwordEx(
|
if (Ring0.ReadPciConfig(
|
||||||
miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
|
miscellaneousControlAddress, THERMTRIP_STATUS_REGISTER,
|
||||||
out value))
|
out value))
|
||||||
{
|
{
|
||||||
@@ -145,7 +145,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
|
||||||
uint eax, edx;
|
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))) {
|
(UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||||
// CurrFID can be found in eax bits 0-5, MaxFID in 16-21
|
// CurrFID can be found in eax bits 0-5, MaxFID in 16-21
|
||||||
// 8-13 hold StartFID, we don't use that here.
|
// 8-13 hold StartFID, we don't use that here.
|
||||||
|
@@ -93,15 +93,15 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
(UIntPtr)(1L << cpuid[0][0].Thread));
|
(UIntPtr)(1L << cpuid[0][0].Thread));
|
||||||
|
|
||||||
uint ctlEax, ctlEdx;
|
uint ctlEax, ctlEdx;
|
||||||
WinRing0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx);
|
Ring0.Rdmsr(PERF_CTL_0, out ctlEax, out ctlEdx);
|
||||||
uint ctrEax, ctrEdx;
|
uint ctrEax, ctrEdx;
|
||||||
WinRing0.Rdmsr(PERF_CTR_0, out ctrEax, out ctrEdx);
|
Ring0.Rdmsr(PERF_CTR_0, out ctrEax, out ctrEdx);
|
||||||
|
|
||||||
timeStampCounterMultiplier = estimateTimeStampCounterMultiplier();
|
timeStampCounterMultiplier = estimateTimeStampCounterMultiplier();
|
||||||
|
|
||||||
// restore the performance counter registers
|
// restore the performance counter registers
|
||||||
WinRing0.Wrmsr(PERF_CTL_0, ctlEax, ctlEdx);
|
Ring0.Wrmsr(PERF_CTL_0, ctlEax, ctlEdx);
|
||||||
WinRing0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx);
|
Ring0.Wrmsr(PERF_CTR_0, ctrEax, ctrEdx);
|
||||||
|
|
||||||
// restore the thread affinity.
|
// restore the thread affinity.
|
||||||
NativeMethods.SetThreadAffinityMask(thread, mask);
|
NativeMethods.SetThreadAffinityMask(thread, mask);
|
||||||
@@ -126,14 +126,14 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
|
|
||||||
// select event "076h CPU Clocks not Halted" and enable the counter
|
// 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 << 22) | // enable performance counter
|
||||||
(1 << 17) | // count events in user mode
|
(1 << 17) | // count events in user mode
|
||||||
(1 << 16) | // count events in operating-system mode
|
(1 << 16) | // count events in operating-system mode
|
||||||
0x76, 0x00000000);
|
0x76, 0x00000000);
|
||||||
|
|
||||||
// set the counter to 0
|
// 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);
|
long ticks = (long)(timeWindow * Stopwatch.Frequency);
|
||||||
uint lsbBegin, msbBegin, lsbEnd, msbEnd;
|
uint lsbBegin, msbBegin, lsbEnd, msbEnd;
|
||||||
@@ -142,11 +142,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
(long)Math.Ceiling(0.001 * ticks);
|
(long)Math.Ceiling(0.001 * ticks);
|
||||||
long timeEnd = timeBegin + ticks;
|
long timeEnd = timeBegin + ticks;
|
||||||
while (Stopwatch.GetTimestamp() < timeBegin) { }
|
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) { }
|
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 cpuDid = (eax >> 6) & 7;
|
||||||
uint cpuFid = eax & 0x1F;
|
uint cpuFid = eax & 0x1F;
|
||||||
double coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
|
double coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
|
||||||
@@ -188,9 +188,9 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
public override void Update() {
|
public override void Update() {
|
||||||
base.Update();
|
base.Update();
|
||||||
|
|
||||||
if (miscellaneousControlAddress != WinRing0.InvalidPciAddress) {
|
if (miscellaneousControlAddress != Ring0.InvalidPciAddress) {
|
||||||
uint value;
|
uint value;
|
||||||
if (WinRing0.ReadPciConfigDwordEx(miscellaneousControlAddress,
|
if (Ring0.ReadPciConfig(miscellaneousControlAddress,
|
||||||
REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
|
REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
|
||||||
coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
|
coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
|
||||||
coreTemperature.Parameters[0].Value;
|
coreTemperature.Parameters[0].Value;
|
||||||
@@ -207,7 +207,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
|
|
||||||
uint curEax, curEdx;
|
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)))
|
(UIntPtr)(1L << cpuid[i][0].Thread)))
|
||||||
{
|
{
|
||||||
// 8:6 CpuDid: current core divisor ID
|
// 8:6 CpuDid: current core divisor ID
|
||||||
|
@@ -50,17 +50,17 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
protected uint GetPciAddress(byte function, ushort deviceId) {
|
protected uint GetPciAddress(byte function, ushort deviceId) {
|
||||||
|
|
||||||
// assemble the pci address
|
// assemble the pci address
|
||||||
uint address = WinRing0.GetPciAddress(PCI_BUS,
|
uint address = Ring0.GetPciAddress(PCI_BUS,
|
||||||
(byte)(PCI_BASE_DEVICE + processorIndex), function);
|
(byte)(PCI_BASE_DEVICE + processorIndex), function);
|
||||||
|
|
||||||
// verify that we have the correct bus, device and function
|
// verify that we have the correct bus, device and function
|
||||||
uint deviceVendor;
|
uint deviceVendor;
|
||||||
if (!WinRing0.ReadPciConfigDwordEx(
|
if (!Ring0.ReadPciConfig(
|
||||||
address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
|
address, DEVICE_VENDOR_ID_REGISTER, out deviceVendor))
|
||||||
return WinRing0.InvalidPciAddress;
|
return Ring0.InvalidPciAddress;
|
||||||
|
|
||||||
if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
|
if (deviceVendor != (deviceId << 16 | AMD_VENDOR_ID))
|
||||||
return WinRing0.InvalidPciAddress;
|
return Ring0.InvalidPciAddress;
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
@@ -106,9 +106,6 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
if ((p == 4) || (p == 128))
|
if ((p == 4) || (p == 128))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!WinRing0.IsCpuid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
CPUID[][] processorThreads = GetProcessorThreads();
|
CPUID[][] processorThreads = GetProcessorThreads();
|
||||||
this.threads = new CPUID[processorThreads.Length][][];
|
this.threads = new CPUID[processorThreads.Length][][];
|
||||||
|
|
||||||
|
@@ -107,7 +107,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
throw new ArgumentOutOfRangeException("thread");
|
throw new ArgumentOutOfRangeException("thread");
|
||||||
UIntPtr mask = (UIntPtr)(1L << 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)) {
|
out eax, out ebx, out ecx, out edx, mask)) {
|
||||||
if (eax > 0)
|
if (eax > 0)
|
||||||
maxCpuid = eax;
|
maxCpuid = eax;
|
||||||
@@ -131,7 +131,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
eax = ebx = ecx = edx = 0;
|
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)) {
|
out eax, out ebx, out ecx, out edx, mask)) {
|
||||||
if (eax > CPUID_EXT)
|
if (eax > CPUID_EXT)
|
||||||
maxCpuidExt = eax - CPUID_EXT;
|
maxCpuidExt = eax - CPUID_EXT;
|
||||||
@@ -149,19 +149,19 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
cpuidData = new uint[maxCpuid + 1, 4];
|
cpuidData = new uint[maxCpuid + 1, 4];
|
||||||
for (uint i = 0; i < (maxCpuid + 1); i++)
|
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, 0], out cpuidData[i, 1],
|
||||||
out cpuidData[i, 2], out cpuidData[i, 3], mask);
|
out cpuidData[i, 2], out cpuidData[i, 3], mask);
|
||||||
|
|
||||||
cpuidExtData = new uint[maxCpuidExt + 1, 4];
|
cpuidExtData = new uint[maxCpuidExt + 1, 4];
|
||||||
for (uint i = 0; i < (maxCpuidExt + 1); i++)
|
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, 0], out cpuidExtData[i, 1],
|
||||||
out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask);
|
out cpuidExtData[i, 2], out cpuidExtData[i, 3], mask);
|
||||||
|
|
||||||
StringBuilder nameBuilder = new StringBuilder();
|
StringBuilder nameBuilder = new StringBuilder();
|
||||||
for (uint i = 2; i <= 4; i++) {
|
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))
|
out eax, out ebx, out ecx, out edx, mask))
|
||||||
{
|
{
|
||||||
AppendRegister(nameBuilder, eax);
|
AppendRegister(nameBuilder, eax);
|
||||||
|
@@ -39,6 +39,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
@@ -55,6 +56,8 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
protected readonly int coreCount;
|
protected readonly int coreCount;
|
||||||
protected readonly string name;
|
protected readonly string name;
|
||||||
|
|
||||||
|
private readonly bool hasModelSpecificRegisters;
|
||||||
|
|
||||||
private readonly bool hasTimeStampCounter;
|
private readonly bool hasTimeStampCounter;
|
||||||
private readonly bool isInvariantTimeStampCounter;
|
private readonly bool isInvariantTimeStampCounter;
|
||||||
private readonly double estimatedTimeStampCounterFrequency;
|
private readonly double estimatedTimeStampCounterFrequency;
|
||||||
@@ -89,6 +92,13 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
this.coreCount = cpuid.Length;
|
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
|
// check if processor has a TSC
|
||||||
if (cpuid[0][0].Data.GetLength(0) > 1
|
if (cpuid[0][0].Data.GetLength(0) > 1
|
||||||
&& (cpuid[0][0].Data[1, 3] & 0x10) != 0)
|
&& (cpuid[0][0].Data[1, 3] & 0x10) != 0)
|
||||||
@@ -144,28 +154,26 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
private static double EstimateTimeStampCounterFrequency(double timeWindow) {
|
private static double EstimateTimeStampCounterFrequency(double timeWindow) {
|
||||||
long ticks = (long)(timeWindow * Stopwatch.Frequency);
|
long ticks = (long)(timeWindow * Stopwatch.Frequency);
|
||||||
uint lsbBegin, msbBegin, lsbEnd, msbEnd;
|
ulong countBegin, countEnd;
|
||||||
|
|
||||||
Thread.BeginThreadAffinity();
|
Thread.BeginThreadAffinity();
|
||||||
long timeBegin = Stopwatch.GetTimestamp() +
|
long timeBegin = Stopwatch.GetTimestamp() +
|
||||||
(long)Math.Ceiling(0.001 * ticks);
|
(long)Math.Ceiling(0.001 * ticks);
|
||||||
long timeEnd = timeBegin + ticks;
|
long timeEnd = timeBegin + ticks;
|
||||||
while (Stopwatch.GetTimestamp() < timeBegin) { }
|
while (Stopwatch.GetTimestamp() < timeBegin) { }
|
||||||
WinRing0.Rdtsc(out lsbBegin, out msbBegin);
|
countBegin = Opcode.Rdtsc();
|
||||||
while (Stopwatch.GetTimestamp() < timeEnd) { }
|
while (Stopwatch.GetTimestamp() < timeEnd) { }
|
||||||
WinRing0.Rdtsc(out lsbEnd, out msbEnd);
|
countEnd = Opcode.Rdtsc();
|
||||||
Thread.EndThreadAffinity();
|
Thread.EndThreadAffinity();
|
||||||
|
|
||||||
ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
|
|
||||||
ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
|
|
||||||
|
|
||||||
return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
|
return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
|
||||||
(timeEnd - timeBegin);
|
(timeEnd - timeBegin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
|
private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
|
||||||
uint eax, edx;
|
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(" ");
|
||||||
r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
|
r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
|
||||||
r.Append(" ");
|
r.Append(" ");
|
||||||
@@ -240,6 +248,10 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
get { return HardwareType.CPU; }
|
get { return HardwareType.CPU; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasModelSpecificRegisters {
|
||||||
|
get { return hasModelSpecificRegisters; }
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasTimeStampCounter {
|
public bool HasTimeStampCounter {
|
||||||
get { return hasTimeStampCounter; }
|
get { return hasTimeStampCounter; }
|
||||||
}
|
}
|
||||||
@@ -250,14 +262,20 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
public override void Update() {
|
public override void Update() {
|
||||||
if (hasTimeStampCounter && isInvariantTimeStampCounter) {
|
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
|
// read time before and after getting the TSC to estimate the error
|
||||||
long firstTime = Stopwatch.GetTimestamp();
|
long firstTime = Stopwatch.GetTimestamp();
|
||||||
WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
|
ulong timeStampCount = Opcode.Rdtsc();
|
||||||
long time = Stopwatch.GetTimestamp();
|
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 delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
|
||||||
double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
|
double error = ((double)(time - firstTime)) / Stopwatch.Frequency;
|
||||||
|
|
||||||
@@ -286,5 +304,16 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
totalLoad.Value = cpuLoad.GetTotalLoad();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -117,7 +117,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
tjMax = new float[coreCount];
|
tjMax = new float[coreCount];
|
||||||
for (int i = 0; i < coreCount; i++) {
|
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))) {
|
out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||||
tjMax[i] = (eax >> 16) & 0xFF;
|
tjMax[i] = (eax >> 16) & 0xFF;
|
||||||
} else {
|
} else {
|
||||||
@@ -142,14 +142,14 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
case Microarchitecture.Atom:
|
case Microarchitecture.Atom:
|
||||||
case Microarchitecture.Core: {
|
case Microarchitecture.Core: {
|
||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
if (WinRing0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
|
if (Ring0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
|
||||||
timeStampCounterMultiplier =
|
timeStampCounterMultiplier =
|
||||||
((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
|
((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case Microarchitecture.Nehalem: {
|
case Microarchitecture.Nehalem: {
|
||||||
uint eax, edx;
|
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;
|
timeStampCounterMultiplier = (eax >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -215,7 +215,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
|
|
||||||
for (int i = 0; i < coreTemperatures.Length; i++) {
|
for (int i = 0; i < coreTemperatures.Length; i++) {
|
||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
if (WinRing0.RdmsrTx(
|
if (Ring0.RdmsrTx(
|
||||||
IA32_THERM_STATUS_MSR, out eax, out edx,
|
IA32_THERM_STATUS_MSR, out eax, out edx,
|
||||||
(UIntPtr)(1L << cpuid[i][0].Thread))) {
|
(UIntPtr)(1L << cpuid[i][0].Thread))) {
|
||||||
// if reading is valid
|
// if reading is valid
|
||||||
@@ -236,7 +236,7 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
|||||||
uint eax, edx;
|
uint eax, edx;
|
||||||
for (int i = 0; i < coreClocks.Length; i++) {
|
for (int i = 0; i < coreClocks.Length; i++) {
|
||||||
System.Threading.Thread.Sleep(1);
|
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)))
|
(UIntPtr)(1L << cpuid[i][0].Thread)))
|
||||||
{
|
{
|
||||||
newBusClock =
|
newBusClock =
|
||||||
|
@@ -40,6 +40,7 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Permissions;
|
using System.Security.Permissions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace OpenHardwareMonitor.Hardware {
|
namespace OpenHardwareMonitor.Hardware {
|
||||||
|
|
||||||
@@ -86,7 +87,8 @@ namespace OpenHardwareMonitor.Hardware {
|
|||||||
if (open)
|
if (open)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WinRing0.Open();
|
Ring0.Open();
|
||||||
|
Opcode.Open();
|
||||||
|
|
||||||
Add(new Mainboard.MainboardGroup(settings));
|
Add(new Mainboard.MainboardGroup(settings));
|
||||||
Add(new CPU.CPUGroup(settings));
|
Add(new CPU.CPUGroup(settings));
|
||||||
@@ -262,7 +264,8 @@ namespace OpenHardwareMonitor.Hardware {
|
|||||||
group.Close();
|
group.Close();
|
||||||
groups.Clear();
|
groups.Clear();
|
||||||
|
|
||||||
WinRing0.Close();
|
Opcode.Close();
|
||||||
|
Ring0.Close();
|
||||||
|
|
||||||
open = false;
|
open = false;
|
||||||
}
|
}
|
||||||
|
70
Hardware/IOControlCode.cs
Normal file
70
Hardware/IOControlCode.cs
Normal 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
300
Hardware/KernelDriver.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -60,9 +60,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
new byte[] { 0xA0, 0xB0, 0xC0, 0xD0 };
|
new byte[] { 0xA0, 0xB0, 0xC0, 0xD0 };
|
||||||
|
|
||||||
private byte ReadByte(byte register) {
|
private byte ReadByte(byte register) {
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
|
(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) {
|
public byte? ReadGPIO(int index) {
|
||||||
@@ -94,7 +94,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
|
r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
if (!WinRing0.WaitIsaBusMutex(100))
|
if (!Ring0.WaitIsaBusMutex(100))
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
|
|
||||||
r.AppendLine("Hardware Monitor Registers");
|
r.AppendLine("Hardware Monitor Registers");
|
||||||
@@ -114,13 +114,13 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
}
|
}
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
|
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
if (!WinRing0.WaitIsaBusMutex(10))
|
if (!Ring0.WaitIsaBusMutex(10))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < voltages.Length; i++) {
|
for (int i = 0; i < voltages.Length; i++) {
|
||||||
@@ -173,7 +173,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
fans[i] = null;
|
fans[i] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -76,9 +76,9 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
private const byte VOLTAGE_BASE_REG = 0x20;
|
private const byte VOLTAGE_BASE_REG = 0x20;
|
||||||
|
|
||||||
private byte ReadByte(byte register, out bool valid) {
|
private byte ReadByte(byte register, out bool valid) {
|
||||||
WinRing0.WriteIoPortByte(addressReg, register);
|
Ring0.WriteIoPort(addressReg, register);
|
||||||
byte value = WinRing0.ReadIoPortByte(dataReg);
|
byte value = Ring0.ReadIoPort(dataReg);
|
||||||
valid = register == WinRing0.ReadIoPortByte(addressReg);
|
valid = register == Ring0.ReadIoPort(addressReg);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,14 +86,14 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
if (index >= gpioCount)
|
if (index >= gpioCount)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return WinRing0.ReadIoPortByte((ushort)(gpioAddress + index));
|
return Ring0.ReadIoPort((ushort)(gpioAddress + index));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteGPIO(int index, byte value) {
|
public void WriteGPIO(int index, byte value) {
|
||||||
if (index >= gpioCount)
|
if (index >= gpioCount)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WinRing0.WriteIoPortByte((ushort)(gpioAddress + index), value);
|
Ring0.WriteIoPort((ushort)(gpioAddress + index), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
|
public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
|
||||||
@@ -162,7 +162,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
|
gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
if (!WinRing0.WaitIsaBusMutex(100))
|
if (!Ring0.WaitIsaBusMutex(100))
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
|
|
||||||
r.AppendLine("Environment Controller Registers");
|
r.AppendLine("Environment Controller Registers");
|
||||||
@@ -194,13 +194,13 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
|
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
if (!WinRing0.WaitIsaBusMutex(10))
|
if (!Ring0.WaitIsaBusMutex(10))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < voltages.Length; i++) {
|
for (int i = 0; i < voltages.Length; i++) {
|
||||||
@@ -246,7 +246,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,8 +62,8 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
private const byte BASE_ADDRESS_REGISTER = 0x60;
|
private const byte BASE_ADDRESS_REGISTER = 0x60;
|
||||||
|
|
||||||
private byte ReadByte(byte register) {
|
private byte ReadByte(byte register) {
|
||||||
WinRing0.WriteIoPortByte(registerPort, register);
|
Ring0.WriteIoPort(registerPort, register);
|
||||||
return WinRing0.ReadIoPortByte(valuePort);
|
return Ring0.ReadIoPort(valuePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ushort ReadWord(byte register) {
|
private ushort ReadWord(byte register) {
|
||||||
@@ -72,8 +72,8 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void Select(byte logicalDeviceNumber) {
|
private void Select(byte logicalDeviceNumber) {
|
||||||
WinRing0.WriteIoPortByte(registerPort, DEVCIE_SELECT_REGISTER);
|
Ring0.WriteIoPort(registerPort, DEVCIE_SELECT_REGISTER);
|
||||||
WinRing0.WriteIoPortByte(valuePort, logicalDeviceNumber);
|
Ring0.WriteIoPort(valuePort, logicalDeviceNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReportUnknownChip(string type, int chip) {
|
private void ReportUnknownChip(string type, int chip) {
|
||||||
@@ -99,12 +99,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
|
private const byte FINTEK_HARDWARE_MONITOR_LDN = 0x04;
|
||||||
|
|
||||||
private void WinbondFintekEnter() {
|
private void WinbondFintekEnter() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x87);
|
Ring0.WriteIoPort(registerPort, 0x87);
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x87);
|
Ring0.WriteIoPort(registerPort, 0x87);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WinbondFintekExit() {
|
private void WinbondFintekExit() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0xAA);
|
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DetectWinbondFintek() {
|
private bool DetectWinbondFintek() {
|
||||||
@@ -308,15 +308,15 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
|
private const byte IT87_CHIP_VERSION_REGISTER = 0x22;
|
||||||
|
|
||||||
private void IT87Enter() {
|
private void IT87Enter() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x87);
|
Ring0.WriteIoPort(registerPort, 0x87);
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x01);
|
Ring0.WriteIoPort(registerPort, 0x01);
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x55);
|
Ring0.WriteIoPort(registerPort, 0x55);
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x55);
|
Ring0.WriteIoPort(registerPort, 0x55);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void IT87Exit() {
|
private void IT87Exit() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, CONFIGURATION_CONTROL_REGISTER);
|
Ring0.WriteIoPort(registerPort, CONFIGURATION_CONTROL_REGISTER);
|
||||||
WinRing0.WriteIoPortByte(valuePort, 0x02);
|
Ring0.WriteIoPort(valuePort, 0x02);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DetectIT87() {
|
private bool DetectIT87() {
|
||||||
@@ -392,11 +392,11 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
#region SMSC
|
#region SMSC
|
||||||
|
|
||||||
private void SMSCEnter() {
|
private void SMSCEnter() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0x55);
|
Ring0.WriteIoPort(registerPort, 0x55);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SMSCExit() {
|
private void SMSCExit() {
|
||||||
WinRing0.WriteIoPortByte(registerPort, 0xAA);
|
Ring0.WriteIoPort(registerPort, 0xAA);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool DetectSMSC() {
|
private bool DetectSMSC() {
|
||||||
@@ -438,15 +438,15 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LPCIO() {
|
public LPCIO() {
|
||||||
if (!WinRing0.IsAvailable)
|
if (!Ring0.IsOpen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!WinRing0.WaitIsaBusMutex(100))
|
if (!Ring0.WaitIsaBusMutex(100))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Detect();
|
Detect();
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISuperIO[] SuperIO {
|
public ISuperIO[] SuperIO {
|
||||||
|
@@ -84,24 +84,24 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
private readonly byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
|
private readonly byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
|
||||||
|
|
||||||
private byte ReadByte(byte bank, byte register) {
|
private byte ReadByte(byte bank, byte register) {
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
|
(ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + DATA_REGISTER_OFFSET), bank);
|
(ushort)(address + DATA_REGISTER_OFFSET), bank);
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
|
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
|
||||||
return WinRing0.ReadIoPortByte(
|
return Ring0.ReadIoPort(
|
||||||
(ushort)(address + DATA_REGISTER_OFFSET));
|
(ushort)(address + DATA_REGISTER_OFFSET));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteByte(byte bank, byte register, byte value) {
|
private void WriteByte(byte bank, byte register, byte value) {
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
|
(ushort)(address + ADDRESS_REGISTER_OFFSET), BANK_SELECT_REGISTER);
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + DATA_REGISTER_OFFSET), bank);
|
(ushort)(address + DATA_REGISTER_OFFSET), bank);
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
|
(ushort)(address + ADDRESS_REGISTER_OFFSET), register);
|
||||||
WinRing0.WriteIoPortByte(
|
Ring0.WriteIoPort(
|
||||||
(ushort)(address + DATA_REGISTER_OFFSET), value);
|
(ushort)(address + DATA_REGISTER_OFFSET), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
public float?[] Fans { get { return fans; } }
|
public float?[] Fans { get { return fans; } }
|
||||||
|
|
||||||
public void Update() {
|
public void Update() {
|
||||||
if (!WinRing0.WaitIsaBusMutex(10))
|
if (!Ring0.WaitIsaBusMutex(10))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < voltages.Length; i++) {
|
for (int i = 0; i < voltages.Length; i++) {
|
||||||
@@ -291,7 +291,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
WriteByte(0, FAN_BIT_REG[i], newByte);
|
WriteByte(0, FAN_BIT_REG[i], newByte);
|
||||||
}
|
}
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetReport() {
|
public string GetReport() {
|
||||||
@@ -306,7 +306,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
|
r.AppendLine(address.ToString("X4", CultureInfo.InvariantCulture));
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
if (!WinRing0.WaitIsaBusMutex(100))
|
if (!Ring0.WaitIsaBusMutex(100))
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
|
|
||||||
r.AppendLine("Hardware Monitor Registers");
|
r.AppendLine("Hardware Monitor Registers");
|
||||||
@@ -340,7 +340,7 @@ namespace OpenHardwareMonitor.Hardware.LPC {
|
|||||||
}
|
}
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
|
|
||||||
WinRing0.ReleaseIsaBusMutex();
|
Ring0.ReleaseIsaBusMutex();
|
||||||
|
|
||||||
return r.ToString();
|
return r.ToString();
|
||||||
}
|
}
|
||||||
|
244
Hardware/Opcode.cs
Normal file
244
Hardware/Opcode.cs
Normal 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
291
Hardware/Ring0.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -60,6 +60,7 @@
|
|||||||
<Compile Include="Hardware\ATI\ADL.cs" />
|
<Compile Include="Hardware\ATI\ADL.cs" />
|
||||||
<Compile Include="Hardware\ATI\ATIGPU.cs" />
|
<Compile Include="Hardware\ATI\ATIGPU.cs" />
|
||||||
<Compile Include="Hardware\ATI\ATIGroup.cs" />
|
<Compile Include="Hardware\ATI\ATIGroup.cs" />
|
||||||
|
<Compile Include="Hardware\IOControlCode.cs" />
|
||||||
<Compile Include="Hardware\Computer.cs" />
|
<Compile Include="Hardware\Computer.cs" />
|
||||||
<Compile Include="Hardware\CPU\AMDCPU.cs" />
|
<Compile Include="Hardware\CPU\AMDCPU.cs" />
|
||||||
<Compile Include="Hardware\CPU\GenericCPU.cs" />
|
<Compile Include="Hardware\CPU\GenericCPU.cs" />
|
||||||
@@ -69,6 +70,9 @@
|
|||||||
<Compile Include="Hardware\CPU\CPUID.cs" />
|
<Compile Include="Hardware\CPU\CPUID.cs" />
|
||||||
<Compile Include="Hardware\CPU\CPULoad.cs" />
|
<Compile Include="Hardware\CPU\CPULoad.cs" />
|
||||||
<Compile Include="Hardware\CPU\IntelCPU.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\Hardware.cs" />
|
||||||
<Compile Include="Hardware\HDD\HDD.cs" />
|
<Compile Include="Hardware\HDD\HDD.cs" />
|
||||||
<Compile Include="Hardware\HDD\HDDGroup.cs" />
|
<Compile Include="Hardware\HDD\HDDGroup.cs" />
|
||||||
@@ -105,7 +109,6 @@
|
|||||||
<Compile Include="Hardware\TBalancer\FTD2XX.cs" />
|
<Compile Include="Hardware\TBalancer\FTD2XX.cs" />
|
||||||
<Compile Include="Hardware\TBalancer\TBalancer.cs" />
|
<Compile Include="Hardware\TBalancer\TBalancer.cs" />
|
||||||
<Compile Include="Hardware\TBalancer\TBalancerGroup.cs" />
|
<Compile Include="Hardware\TBalancer\TBalancerGroup.cs" />
|
||||||
<Compile Include="Hardware\WinRing0.cs" />
|
|
||||||
<Compile Include="Hardware\ISettings.cs" />
|
<Compile Include="Hardware\ISettings.cs" />
|
||||||
<Compile Include="Hardware\HexStringArray.cs" />
|
<Compile Include="Hardware\HexStringArray.cs" />
|
||||||
<Compile Include="Collections\IReadOnlyArray.cs" />
|
<Compile Include="Collections\IReadOnlyArray.cs" />
|
||||||
@@ -132,7 +135,10 @@
|
|||||||
<Install>true</Install>
|
<Install>true</Install>
|
||||||
</BootstrapperPackage>
|
</BootstrapperPackage>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Hardware\WinRing0.sys" />
|
||||||
|
<EmbeddedResource Include="Hardware\WinRing0x64.sys" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- 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.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
11
Program.cs
11
Program.cs
@@ -87,17 +87,6 @@ namespace OpenHardwareMonitor {
|
|||||||
if (!IsFileAvailable("Aga.Controls.dll"))
|
if (!IsFileAvailable("Aga.Controls.dll"))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user