Added some error reporting to the Ring0 driver loading code.
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 Mutex isaBusMutex;
50 private static readonly StringBuilder report = new StringBuilder();
52 private const uint OLS_TYPE = 40000;
53 private static IOControlCode
54 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
55 IOControlCode.Access.Any),
56 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
57 IOControlCode.Access.Any),
58 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
59 IOControlCode.Access.Any),
60 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
61 IOControlCode.Access.Any),
62 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
63 IOControlCode.Access.Read),
64 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
65 IOControlCode.Access.Write),
66 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
67 IOControlCode.Access.Read),
68 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
69 IOControlCode.Access.Write);
71 private static bool ExtractDriver(string fileName) {
72 string resourceName = "OpenHardwareMonitor.Hardware." +
73 (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
76 Assembly.GetExecutingAssembly().GetManifestResourceNames();
78 for (int i = 0; i < names.Length; i++) {
79 if (names[i].Replace('\\', '.') == resourceName) {
80 using (Stream stream = Assembly.GetExecutingAssembly().
81 GetManifestResourceStream(names[i]))
83 buffer = new byte[stream.Length];
84 stream.Read(buffer, 0, buffer.Length);
92 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
93 target.Write(buffer, 0, buffer.Length);
99 public static void Open() {
100 // no implementation for unix systems
101 int p = (int)Environment.OSVersion.Platform;
102 if ((p == 4) || (p == 128))
108 // clear the current report
111 driver = new KernelDriver("WinRing0_1_2_0");
114 if (!driver.IsOpen) {
115 // driver is not loaded, try to install and open
116 string fileName = Path.GetTempFileName();
117 if (ExtractDriver(fileName)) {
118 if (driver.Install(fileName)) {
119 File.Delete(fileName);
122 if (!driver.IsOpen) {
124 report.AppendLine("Status: Opening driver failed");
127 report.AppendLine("Status: Installing driver failed");
129 report.Append("Exception: " + Marshal.GetExceptionForHR(
130 Marshal.GetHRForLastWin32Error()).Message);
134 "Status: Extracting driver to \"" + fileName + "\" failed");
141 isaBusMutex = new Mutex(false, "Access_ISABUS.HTP.Method");
144 public static bool IsOpen {
145 get { return driver != null; }
148 public static void Close() {
153 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
165 public static string GetReport() {
166 if (report.Length > 0) {
167 report.Insert(0, "Ring0" + Environment.NewLine +
168 Environment.NewLine);
170 return report.ToString();
175 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
177 return isaBusMutex.WaitOne(millisecondsTimeout, false);
178 } catch (AbandonedMutexException) { return false; }
179 catch (InvalidOperationException) { return false; }
182 public static void ReleaseIsaBusMutex() {
183 isaBusMutex.ReleaseMutex();
186 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
187 if (driver == null) {
194 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
197 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
198 eax = (uint)(buffer & 0xFFFFFFFF);
202 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
203 ulong threadAffinityMask)
205 ulong mask = ThreadAffinity.Set(threadAffinityMask);
207 bool result = Rdmsr(index, out eax, out edx);
209 ThreadAffinity.Set(mask);
213 [StructLayout(LayoutKind.Sequential, Pack = 1)]
214 private struct WrmsrInput {
215 public uint Register;
219 public static bool Wrmsr(uint index, uint eax, uint edx) {
223 WrmsrInput input = new WrmsrInput();
224 input.Register = index;
225 input.Value = ((ulong)edx << 32) | eax;
227 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
230 public static byte ReadIoPort(uint port) {
235 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
237 return (byte)(value & 0xFF);
240 [StructLayout(LayoutKind.Sequential, Pack = 1)]
241 private struct WriteIoPortInput {
242 public uint PortNumber;
246 public static void WriteIoPort(uint port, byte value) {
250 WriteIoPortInput input = new WriteIoPortInput();
251 input.PortNumber = port;
254 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
257 public const uint InvalidPciAddress = 0xFFFFFFFF;
259 public static uint GetPciAddress(byte bus, byte device, byte function) {
261 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
264 [StructLayout(LayoutKind.Sequential, Pack = 1)]
265 private struct ReadPciConfigInput {
266 public uint PciAddress;
267 public uint RegAddress;
270 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
273 if (driver == null || (regAddress & 3) != 0) {
278 ReadPciConfigInput input = new ReadPciConfigInput();
279 input.PciAddress = pciAddress;
280 input.RegAddress = regAddress;
283 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
287 [StructLayout(LayoutKind.Sequential, Pack = 1)]
288 private struct WritePciConfigInput {
289 public uint PciAddress;
290 public uint RegAddress;
294 public static bool WritePciConfig(uint pciAddress, uint regAddress,
297 if (driver == null || (regAddress & 3) != 0)
300 WritePciConfigInput input = new WritePciConfigInput();
301 input.PciAddress = pciAddress;
302 input.RegAddress = regAddress;
305 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);