Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2010-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
13 using System.Reflection;
14 using System.Runtime.InteropServices;
15 using System.Security.AccessControl;
16 using System.Threading;
19 namespace OpenHardwareMonitor.Hardware {
20 internal static class Ring0 {
22 private static KernelDriver driver;
23 private static string fileName;
24 private static Mutex isaBusMutex;
25 private static readonly StringBuilder report = new StringBuilder();
27 private const uint OLS_TYPE = 40000;
28 private static IOControlCode
29 IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
30 IOControlCode.Access.Any),
31 IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
32 IOControlCode.Access.Any),
33 IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
34 IOControlCode.Access.Any),
35 IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822,
36 IOControlCode.Access.Any),
37 IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
38 IOControlCode.Access.Read),
39 IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836,
40 IOControlCode.Access.Write),
41 IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851,
42 IOControlCode.Access.Read),
43 IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
44 IOControlCode.Access.Write),
45 IOCTL_OLS_READ_MEMORY = new IOControlCode(OLS_TYPE, 0x841,
46 IOControlCode.Access.Read);
48 private static string GetTempFileName() {
50 // try to create one in the application folder
51 string fileName = Path.ChangeExtension(
52 Assembly.GetEntryAssembly().Location, ".sys");
54 using (FileStream stream = File.Create(fileName)) {
57 } catch (IOException) { }
58 catch (UnauthorizedAccessException) { }
60 // if this failed, try to get a file in the temporary folder
62 return Path.GetTempFileName();
63 } catch (IOException) {
66 catch (UnauthorizedAccessException) {
67 // we do not have the right to create a file in the temp folder
69 catch (NotSupportedException) {
70 // invalid path format of the TMP system environment variable
76 private static bool ExtractDriver(string fileName) {
77 string resourceName = "OpenHardwareMonitor.Hardware." +
78 (OperatingSystem.Is64BitOperatingSystem() ? "WinRing0x64.sys" :
82 Assembly.GetExecutingAssembly().GetManifestResourceNames();
84 for (int i = 0; i < names.Length; i++) {
85 if (names[i].Replace('\\', '.') == resourceName) {
86 using (Stream stream = Assembly.GetExecutingAssembly().
87 GetManifestResourceStream(names[i]))
89 buffer = new byte[stream.Length];
90 stream.Read(buffer, 0, buffer.Length);
99 using (FileStream target = new FileStream(fileName, FileMode.Create)) {
100 target.Write(buffer, 0, buffer.Length);
103 } catch (IOException) {
104 // for example there is not enough space on the disk
108 // make sure the file is actually writen to the file system
109 for (int i = 0; i < 20; i++) {
111 if (File.Exists(fileName) &&
112 new FileInfo(fileName).Length == buffer.Length)
117 } catch (IOException) {
122 // file still has not the right size, something is wrong
126 public static void Open() {
127 // no implementation for unix systems
128 int p = (int)Environment.OSVersion.Platform;
129 if ((p == 4) || (p == 128))
135 // clear the current report
138 driver = new KernelDriver("WinRing0_1_2_0");
141 if (!driver.IsOpen) {
142 // driver is not loaded, try to install and open
144 fileName = GetTempFileName();
145 if (fileName != null && ExtractDriver(fileName)) {
147 if (driver.Install(fileName, out installError)) {
150 if (!driver.IsOpen) {
152 report.AppendLine("Status: Opening driver failed after install");
155 string errorFirstInstall = installError;
157 // install failed, try to delete and reinstall
160 // wait a short moment to give the OS a chance to remove the driver
163 string errorSecondInstall;
164 if (driver.Install(fileName, out errorSecondInstall)) {
167 if (!driver.IsOpen) {
170 "Status: Opening driver failed after reinstall");
173 report.AppendLine("Status: Installing driver \"" +
174 fileName + "\" failed" +
175 (File.Exists(fileName) ? " and file exists" : ""));
176 report.AppendLine("First Exception: " + errorFirstInstall);
177 report.AppendLine("Second Exception: " + errorSecondInstall);
181 report.AppendLine("Status: Extracting driver failed");
185 // try to delte the driver file
186 if (File.Exists(fileName))
187 File.Delete(fileName);
189 } catch (IOException) { }
190 catch (UnauthorizedAccessException) { }
196 string mutexName = "Global\\Access_ISABUS.HTP.Method";
198 isaBusMutex = new Mutex(false, mutexName);
199 } catch (UnauthorizedAccessException) {
201 isaBusMutex = Mutex.OpenExisting(mutexName, MutexRights.Synchronize);
206 public static bool IsOpen {
207 get { return driver != null; }
210 public static void Close() {
215 driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
224 if (isaBusMutex != null) {
229 // try to delete temporary driver file again if failed during open
230 if (fileName != null && File.Exists(fileName)) {
232 File.Delete(fileName);
234 } catch (IOException) { }
235 catch (UnauthorizedAccessException) { }
239 public static string GetReport() {
240 if (report.Length > 0) {
241 StringBuilder r = new StringBuilder();
242 r.AppendLine("Ring0");
251 public static bool WaitIsaBusMutex(int millisecondsTimeout) {
252 if (isaBusMutex == null)
255 return isaBusMutex.WaitOne(millisecondsTimeout, false);
256 } catch (AbandonedMutexException) { return false; }
257 catch (InvalidOperationException) { return false; }
260 public static void ReleaseIsaBusMutex() {
261 if (isaBusMutex == null)
263 isaBusMutex.ReleaseMutex();
266 public static bool Rdmsr(uint index, out uint eax, out uint edx) {
267 if (driver == null) {
274 bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
277 edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
278 eax = (uint)(buffer & 0xFFFFFFFF);
282 public static bool RdmsrTx(uint index, out uint eax, out uint edx,
283 ulong threadAffinityMask)
285 ulong mask = ThreadAffinity.Set(threadAffinityMask);
287 bool result = Rdmsr(index, out eax, out edx);
289 ThreadAffinity.Set(mask);
293 [StructLayout(LayoutKind.Sequential, Pack = 1)]
294 private struct WrmsrInput {
295 public uint Register;
299 public static bool Wrmsr(uint index, uint eax, uint edx) {
303 WrmsrInput input = new WrmsrInput();
304 input.Register = index;
305 input.Value = ((ulong)edx << 32) | eax;
307 return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
310 public static byte ReadIoPort(uint port) {
315 driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
317 return (byte)(value & 0xFF);
320 [StructLayout(LayoutKind.Sequential, Pack = 1)]
321 private struct WriteIoPortInput {
322 public uint PortNumber;
326 public static void WriteIoPort(uint port, byte value) {
330 WriteIoPortInput input = new WriteIoPortInput();
331 input.PortNumber = port;
334 driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
337 public const uint InvalidPciAddress = 0xFFFFFFFF;
339 public static uint GetPciAddress(byte bus, byte device, byte function) {
341 (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
344 [StructLayout(LayoutKind.Sequential, Pack = 1)]
345 private struct ReadPciConfigInput {
346 public uint PciAddress;
347 public uint RegAddress;
350 public static bool ReadPciConfig(uint pciAddress, uint regAddress,
353 if (driver == null || (regAddress & 3) != 0) {
358 ReadPciConfigInput input = new ReadPciConfigInput();
359 input.PciAddress = pciAddress;
360 input.RegAddress = regAddress;
363 return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input,
367 [StructLayout(LayoutKind.Sequential, Pack = 1)]
368 private struct WritePciConfigInput {
369 public uint PciAddress;
370 public uint RegAddress;
374 public static bool WritePciConfig(uint pciAddress, uint regAddress,
377 if (driver == null || (regAddress & 3) != 0)
380 WritePciConfigInput input = new WritePciConfigInput();
381 input.PciAddress = pciAddress;
382 input.RegAddress = regAddress;
385 return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
388 [StructLayout(LayoutKind.Sequential, Pack = 1)]
389 private struct ReadMemoryInput {
390 public ulong address;
391 public uint unitSize;
395 public static bool ReadMemory<T>(ulong address, ref T buffer) {
396 if (driver == null) {
400 ReadMemoryInput input = new ReadMemoryInput();
401 input.address = address;
403 input.count = (uint)Marshal.SizeOf(buffer);
405 return driver.DeviceIOControl(IOCTL_OLS_READ_MEMORY, input,