Fixed Issue 216.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 The contents of this file are subject to the Mozilla Public License Version
6 1.1 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 for the specific language governing rights and limitations under the License.
15 The Original Code is the Open Hardware Monitor code.
17 The Initial Developer of the Original Code is
18 Michael Möller <m.moeller@gmx.ch>.
19 Portions created by the Initial Developer are Copyright (C) 2010-2011
20 the Initial Developer. All Rights Reserved.
24 Alternatively, the contents of this file may be used under the terms of
25 either the GNU General Public License Version 2 or later (the "GPL"), or
26 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 in which case the provisions of the GPL or the LGPL are applicable instead
28 of those above. If you wish to allow use of your version of this file only
29 under the terms of either the GPL or the LGPL, and not to allow others to
30 use your version of this file under the terms of the MPL, indicate your
31 decision by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL or the LGPL. If you do not delete
33 the provisions above, a recipient may use your version of this file under
34 the terms of any one of the MPL, the GPL or the LGPL.
40 using System.Reflection;
41 using System.Runtime.InteropServices;
42 using System.Threading;
45 namespace OpenHardwareMonitor.Hardware {
46 internal static class Ring0 {
48 private static KernelDriver driver;
49 private static string fileName;
50 private static Mutex isaBusMutex;
51 private static readonly StringBuilder report = new StringBuilder();
53 private const uint OLS_TYPE = 40000;
54 private static IOControlCode
55 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
56 IOControlCode.Access.Any),
57 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
58 IOControlCode.Access.Any),
59 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
60 IOControlCode.Access.Any),
61 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
62 IOControlCode.Access.Any),
63 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
64 IOControlCode.Access.Read),
65 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
66 IOControlCode.Access.Write),
67 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
68 IOControlCode.Access.Read),
69 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
70 IOControlCode.Access.Write),
71 IOCTL_OLS_READ_MEMORY = new IOControlCode(OLS_TYPE, 0x841,
72 IOControlCode.Access.Read);
74 private static bool ExtractDriver(string fileName) {
75 string resourceName = "OpenHardwareMonitor.Hardware." +
76 (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
79 Assembly.GetExecutingAssembly().GetManifestResourceNames();
81 for (int i = 0; i < names.Length; i++) {
82 if (names[i].Replace('\\', '.') == resourceName) {
83 using (Stream stream = Assembly.GetExecutingAssembly().
84 GetManifestResourceStream(names[i]))
86 buffer = new byte[stream.Length];
87 stream.Read(buffer, 0, buffer.Length);
95 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
96 target.Write(buffer, 0, buffer.Length);
102 public static void Open() {
103 // no implementation for unix systems
104 int p = (int)Environment.OSVersion.Platform;
105 if ((p == 4) || (p == 128))
111 // clear the current report
114 driver = new KernelDriver("WinRing0_1_2_0");
117 if (!driver.IsOpen) {
118 // driver is not loaded, try to reinstall and open
121 fileName = Path.GetTempFileName();
122 if (ExtractDriver(fileName)) {
123 if (driver.Install(fileName)) {
126 if (!driver.IsOpen) {
128 report.AppendLine("Status: Opening driver failed");
131 report.AppendLine("Status: Installing driver \"" +
132 fileName + "\" failed" +
133 (File.Exists(fileName) ? " and file exists" : ""));
135 report.Append("Exception: " + Marshal.GetExceptionForHR(
136 Marshal.GetHRForLastWin32Error()).Message);
141 "Status: Extracting driver to \"" + fileName + "\" failed");
145 // try to delte the driver file
146 if (File.Exists(fileName))
147 File.Delete(fileName);
149 } catch (IOException) { }
150 catch (UnauthorizedAccessException) { }
156 isaBusMutex = new Mutex(false, "Global\\Access_ISABUS.HTP.Method");
159 public static bool IsOpen {
160 get { return driver != null; }
163 public static void Close() {
168 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
179 // try to delete temporary driver file again if failed during open
180 if (fileName != null && File.Exists(fileName)) {
182 File.Delete(fileName);
184 } catch (IOException) { }
185 catch (UnauthorizedAccessException) { }
189 public static string GetReport() {
190 if (report.Length > 0) {
191 StringBuilder r = new StringBuilder();
192 r.AppendLine("Ring0");
201 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
203 return isaBusMutex.WaitOne(millisecondsTimeout, false);
204 } catch (AbandonedMutexException) { return false; }
205 catch (InvalidOperationException) { return false; }
208 public static void ReleaseIsaBusMutex() {
209 isaBusMutex.ReleaseMutex();
212 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
213 if (driver == null) {
220 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
223 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
224 eax = (uint)(buffer & 0xFFFFFFFF);
228 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
229 ulong threadAffinityMask)
231 ulong mask = ThreadAffinity.Set(threadAffinityMask);
233 bool result = Rdmsr(index, out eax, out edx);
235 ThreadAffinity.Set(mask);
239 [StructLayout(LayoutKind.Sequential, Pack = 1)]
240 private struct WrmsrInput {
241 public uint Register;
245 public static bool Wrmsr(uint index, uint eax, uint edx) {
249 WrmsrInput input = new WrmsrInput();
250 input.Register = index;
251 input.Value = ((ulong)edx << 32) | eax;
253 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
256 public static byte ReadIoPort(uint port) {
261 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
263 return (byte)(value & 0xFF);
266 [StructLayout(LayoutKind.Sequential, Pack = 1)]
267 private struct WriteIoPortInput {
268 public uint PortNumber;
272 public static void WriteIoPort(uint port, byte value) {
276 WriteIoPortInput input = new WriteIoPortInput();
277 input.PortNumber = port;
280 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
283 public const uint InvalidPciAddress = 0xFFFFFFFF;
285 public static uint GetPciAddress(byte bus, byte device, byte function) {
287 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
290 [StructLayout(LayoutKind.Sequential, Pack = 1)]
291 private struct ReadPciConfigInput {
292 public uint PciAddress;
293 public uint RegAddress;
296 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
299 if (driver == null || (regAddress & 3) != 0) {
304 ReadPciConfigInput input = new ReadPciConfigInput();
305 input.PciAddress = pciAddress;
306 input.RegAddress = regAddress;
309 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
313 [StructLayout(LayoutKind.Sequential, Pack = 1)]
314 private struct WritePciConfigInput {
315 public uint PciAddress;
316 public uint RegAddress;
320 public static bool WritePciConfig(uint pciAddress, uint regAddress,
323 if (driver == null || (regAddress & 3) != 0)
326 WritePciConfigInput input = new WritePciConfigInput();
327 input.PciAddress = pciAddress;
328 input.RegAddress = regAddress;
331 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
334 [StructLayout(LayoutKind.Sequential, Pack = 1)]
335 private struct ReadMemoryInput {
336 public ulong address;
337 public uint unitSize;
341 public static bool ReadMemory<T>(ulong address, ref T buffer) {
342 if (driver == null) {
346 ReadMemoryInput input = new ReadMemoryInput();
347 input.address = address;
349 input.count = (uint)Marshal.SizeOf(buffer);
351 return driver.DeviceIOControl(IOCTL_OLS_READ_MEMORY, input,