Fixed Issue 224.
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.Security.AccessControl;
43 using System.Threading;
46 namespace OpenHardwareMonitor.Hardware {
47 internal static class Ring0 {
49 private static KernelDriver driver;
50 private static string fileName;
51 private static Mutex isaBusMutex;
52 private static readonly StringBuilder report = new StringBuilder();
54 private const uint OLS_TYPE = 40000;
55 private static IOControlCode
56 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
57 IOControlCode.Access.Any),
58 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
59 IOControlCode.Access.Any),
60 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
61 IOControlCode.Access.Any),
62 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
63 IOControlCode.Access.Any),
64 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
65 IOControlCode.Access.Read),
66 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
67 IOControlCode.Access.Write),
68 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
69 IOControlCode.Access.Read),
70 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
71 IOControlCode.Access.Write),
72 IOCTL_OLS_READ_MEMORY = new IOControlCode(OLS_TYPE, 0x841,
73 IOControlCode.Access.Read);
75 private static string GetTempFileName() {
77 // try to get a file in the temporary folder
79 return Path.GetTempFileName();
80 } catch (IOException) {
83 catch (UnauthorizedAccessException) {
84 // we do not have the right to create a file in the temp folder
86 catch (NotSupportedException) {
87 // invalid path format of the TMP system environment variable
90 // if this failed, we try to create one in the application folder
91 string fileName = Path.ChangeExtension(
92 Assembly.GetExecutingAssembly().Location, ".sys");
94 using (FileStream stream = File.Create(fileName)) {
97 } catch (IOException) { }
98 catch (UnauthorizedAccessException) { }
103 private static bool ExtractDriver(string fileName) {
104 string resourceName = "OpenHardwareMonitor.Hardware." +
105 (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
108 Assembly.GetExecutingAssembly().GetManifestResourceNames();
109 byte[] buffer = null;
110 for (int i = 0; i < names.Length; i++) {
111 if (names[i].Replace('\\', '.') == resourceName) {
112 using (Stream stream = Assembly.GetExecutingAssembly().
113 GetManifestResourceStream(names[i]))
115 buffer = new byte[stream.Length];
116 stream.Read(buffer, 0, buffer.Length);
124 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
125 target.Write(buffer, 0, buffer.Length);
131 public static void Open() {
132 // no implementation for unix systems
133 int p = (int)Environment.OSVersion.Platform;
134 if ((p == 4) || (p == 128))
140 // clear the current report
143 driver = new KernelDriver("WinRing0_1_2_0");
146 if (!driver.IsOpen) {
147 // driver is not loaded, try to reinstall and open
150 fileName = GetTempFileName();
151 if (fileName != null && ExtractDriver(fileName)) {
152 if (driver.Install(fileName)) {
155 if (!driver.IsOpen) {
157 report.AppendLine("Status: Opening driver failed");
160 report.AppendLine("Status: Installing driver \"" +
161 fileName + "\" failed" +
162 (File.Exists(fileName) ? " and file exists" : ""));
164 report.Append("Exception: " + Marshal.GetExceptionForHR(
165 Marshal.GetHRForLastWin32Error()).Message);
168 report.AppendLine("Status: Extracting driver failed");
172 // try to delte the driver file
173 if (File.Exists(fileName))
174 File.Delete(fileName);
176 } catch (IOException) { }
177 catch (UnauthorizedAccessException) { }
183 string mutexName = "Global\\Access_ISABUS.HTP.Method";
185 isaBusMutex = new Mutex(false, mutexName);
186 } catch (UnauthorizedAccessException) {
188 isaBusMutex = Mutex.OpenExisting(mutexName, MutexRights.Synchronize);
193 public static bool IsOpen {
194 get { return driver != null; }
197 public static void Close() {
202 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
211 if (isaBusMutex != null) {
216 // try to delete temporary driver file again if failed during open
217 if (fileName != null && File.Exists(fileName)) {
219 File.Delete(fileName);
221 } catch (IOException) { }
222 catch (UnauthorizedAccessException) { }
226 public static string GetReport() {
227 if (report.Length > 0) {
228 StringBuilder r = new StringBuilder();
229 r.AppendLine("Ring0");
238 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
239 if (isaBusMutex == null)
242 return isaBusMutex.WaitOne(millisecondsTimeout, false);
243 } catch (AbandonedMutexException) { return false; }
244 catch (InvalidOperationException) { return false; }
247 public static void ReleaseIsaBusMutex() {
248 if (isaBusMutex == null)
250 isaBusMutex.ReleaseMutex();
253 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
254 if (driver == null) {
261 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
264 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
265 eax = (uint)(buffer & 0xFFFFFFFF);
269 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
270 ulong threadAffinityMask)
272 ulong mask = ThreadAffinity.Set(threadAffinityMask);
274 bool result = Rdmsr(index, out eax, out edx);
276 ThreadAffinity.Set(mask);
280 [StructLayout(LayoutKind.Sequential, Pack = 1)]
281 private struct WrmsrInput {
282 public uint Register;
286 public static bool Wrmsr(uint index, uint eax, uint edx) {
290 WrmsrInput input = new WrmsrInput();
291 input.Register = index;
292 input.Value = ((ulong)edx << 32) | eax;
294 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
297 public static byte ReadIoPort(uint port) {
302 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
304 return (byte)(value & 0xFF);
307 [StructLayout(LayoutKind.Sequential, Pack = 1)]
308 private struct WriteIoPortInput {
309 public uint PortNumber;
313 public static void WriteIoPort(uint port, byte value) {
317 WriteIoPortInput input = new WriteIoPortInput();
318 input.PortNumber = port;
321 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
324 public const uint InvalidPciAddress = 0xFFFFFFFF;
326 public static uint GetPciAddress(byte bus, byte device, byte function) {
328 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
331 [StructLayout(LayoutKind.Sequential, Pack = 1)]
332 private struct ReadPciConfigInput {
333 public uint PciAddress;
334 public uint RegAddress;
337 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
340 if (driver == null || (regAddress & 3) != 0) {
345 ReadPciConfigInput input = new ReadPciConfigInput();
346 input.PciAddress = pciAddress;
347 input.RegAddress = regAddress;
350 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
354 [StructLayout(LayoutKind.Sequential, Pack = 1)]
355 private struct WritePciConfigInput {
356 public uint PciAddress;
357 public uint RegAddress;
361 public static bool WritePciConfig(uint pciAddress, uint regAddress,
364 if (driver == null || (regAddress & 3) != 0)
367 WritePciConfigInput input = new WritePciConfigInput();
368 input.PciAddress = pciAddress;
369 input.RegAddress = regAddress;
372 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
375 [StructLayout(LayoutKind.Sequential, Pack = 1)]
376 private struct ReadMemoryInput {
377 public ulong address;
378 public uint unitSize;
382 public static bool ReadMemory<T>(ulong address, ref T buffer) {
383 if (driver == null) {
387 ReadMemoryInput input = new ReadMemoryInput();
388 input.address = address;
390 input.count = (uint)Marshal.SizeOf(buffer);
392 return driver.DeviceIOControl(IOCTL_OLS_READ_MEMORY, input,