mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-29 05:18:14 +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:
parent
fcf4876985
commit
f238f35eff
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() {
|
||||
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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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][][];
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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
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 };
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
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\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.
|
||||
|
11
Program.cs
11
Program.cs
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user