Hardware/Ring0.cs
author moel.mich
Thu, 11 Nov 2010 21:22:24 +0000
changeset 241 52007c404f32
parent 236 763675f19ff4
child 254 d8079800a888
permissions -rw-r--r--
Fixed a problem, where the MainForm location and size was lost when the application is started minimized and exited without ever showing the form. This caused MainForm_Load to be never called (location and size was not loaded), but the default size and location were still saved. The new implementation only saves the location and size when one of the two is changed.
moel@236
     1
/*
moel@236
     2
  
moel@236
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@236
     4
moel@236
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@236
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@236
     7
  the License. You may obtain a copy of the License at
moel@236
     8
 
moel@236
     9
  http://www.mozilla.org/MPL/
moel@236
    10
moel@236
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@236
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@236
    13
  for the specific language governing rights and limitations under the License.
moel@236
    14
moel@236
    15
  The Original Code is the Open Hardware Monitor code.
moel@236
    16
moel@236
    17
  The Initial Developer of the Original Code is 
moel@236
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@236
    19
  Portions created by the Initial Developer are Copyright (C) 2010
moel@236
    20
  the Initial Developer. All Rights Reserved.
moel@236
    21
moel@236
    22
  Contributor(s):
moel@236
    23
moel@236
    24
  Alternatively, the contents of this file may be used under the terms of
moel@236
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@236
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@236
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@236
    28
  of those above. If you wish to allow use of your version of this file only
moel@236
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@236
    30
  use your version of this file under the terms of the MPL, indicate your
moel@236
    31
  decision by deleting the provisions above and replace them with the notice
moel@236
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@236
    33
  the provisions above, a recipient may use your version of this file under
moel@236
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@236
    35
 
moel@236
    36
*/
moel@236
    37
moel@236
    38
using System;
moel@236
    39
using System.IO;
moel@236
    40
using System.Reflection;
moel@236
    41
using System.Runtime.InteropServices;
moel@236
    42
using System.Threading;
moel@236
    43
moel@236
    44
namespace OpenHardwareMonitor.Hardware {
moel@236
    45
  internal static class Ring0 {
moel@236
    46
moel@236
    47
    private static KernelDriver driver;
moel@236
    48
    private static Mutex isaBusMutex;
moel@236
    49
moel@236
    50
    private const uint OLS_TYPE = 40000;
moel@236
    51
    private static IOControlCode
moel@236
    52
      IOCTL_OLS_GET_REFCOUNT = new IOControlCode(OLS_TYPE, 0x801,
moel@236
    53
        IOControlCode.Access.Any),
moel@236
    54
      IOCTL_OLS_GET_DRIVER_VERSION = new IOControlCode(OLS_TYPE, 0x800,
moel@236
    55
        IOControlCode.Access.Any),
moel@236
    56
      IOCTL_OLS_READ_MSR = new IOControlCode(OLS_TYPE, 0x821,
moel@236
    57
        IOControlCode.Access.Any),
moel@236
    58
      IOCTL_OLS_WRITE_MSR = new IOControlCode(OLS_TYPE, 0x822, 
moel@236
    59
        IOControlCode.Access.Any),
moel@236
    60
      IOCTL_OLS_READ_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x833,
moel@236
    61
        IOControlCode.Access.Read),
moel@236
    62
      IOCTL_OLS_WRITE_IO_PORT_BYTE = new IOControlCode(OLS_TYPE, 0x836, 
moel@236
    63
        IOControlCode.Access.Write),
moel@236
    64
      IOCTL_OLS_READ_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x851, 
moel@236
    65
        IOControlCode.Access.Read),
moel@236
    66
      IOCTL_OLS_WRITE_PCI_CONFIG = new IOControlCode(OLS_TYPE, 0x852,
moel@236
    67
        IOControlCode.Access.Write);
moel@236
    68
moel@236
    69
    private static bool ExtractDriver(string fileName) {
moel@236
    70
      string resourceName = "OpenHardwareMonitor.Hardware." +
moel@236
    71
        (IntPtr.Size == 4 ? "WinRing0.sys" : "WinRing0x64.sys");
moel@236
    72
moel@236
    73
      string[] names =
moel@236
    74
        Assembly.GetExecutingAssembly().GetManifestResourceNames();
moel@236
    75
      byte[] buffer = null;
moel@236
    76
      for (int i = 0; i < names.Length; i++) {
moel@236
    77
        if (names[i].Replace('\\', '.') == resourceName) {
moel@236
    78
          using (Stream stream = Assembly.GetExecutingAssembly().
moel@236
    79
            GetManifestResourceStream(names[i])) 
moel@236
    80
          {
moel@236
    81
              buffer = new byte[stream.Length];
moel@236
    82
              stream.Read(buffer, 0, buffer.Length);
moel@236
    83
          }
moel@236
    84
        }
moel@236
    85
      }
moel@236
    86
moel@236
    87
      if (buffer == null)
moel@236
    88
        return false;
moel@236
    89
moel@236
    90
      using (FileStream target = new FileStream(fileName, FileMode.Create)) {
moel@236
    91
        target.Write(buffer, 0, buffer.Length);
moel@236
    92
      }
moel@236
    93
moel@236
    94
      return true;
moel@236
    95
    }
moel@236
    96
moel@236
    97
    public static void Open() {
moel@238
    98
      // No implementation for Unix systems
moel@238
    99
      int p = (int)Environment.OSVersion.Platform;
moel@238
   100
      if ((p == 4) || (p == 128))
moel@238
   101
        return;  
moel@238
   102
      
moel@236
   103
      if (driver != null)
moel@236
   104
        return;
moel@236
   105
     
moel@236
   106
      driver = new KernelDriver("WinRing0_1_2_0");
moel@236
   107
      driver.Open();
moel@236
   108
moel@236
   109
      if (!driver.IsOpen) {
moel@236
   110
        string fileName = Path.GetTempFileName();
moel@236
   111
        if (ExtractDriver(fileName)) {
moel@236
   112
moel@236
   113
          driver.Install(fileName);
moel@236
   114
          File.Delete(fileName);
moel@236
   115
moel@236
   116
          driver.Open();
moel@236
   117
moel@236
   118
          if (!driver.IsOpen)
moel@236
   119
            driver.Delete();
moel@236
   120
        }
moel@236
   121
      }
moel@236
   122
moel@236
   123
      if (!driver.IsOpen) 
moel@236
   124
        driver = null;
moel@236
   125
moel@236
   126
      isaBusMutex = new Mutex(false, "Access_ISABUS.HTP.Method");
moel@236
   127
    }
moel@236
   128
moel@236
   129
    public static bool IsOpen {
moel@236
   130
      get { return driver != null; }
moel@236
   131
    }
moel@236
   132
moel@236
   133
    public static void Close() {
moel@236
   134
      if (driver == null)
moel@236
   135
        return;
moel@236
   136
moel@236
   137
      uint refCount = 0;
moel@236
   138
      driver.DeviceIOControl(IOCTL_OLS_GET_REFCOUNT, null, ref refCount);
moel@236
   139
moel@236
   140
      driver.Close();
moel@236
   141
moel@236
   142
      if (refCount <= 1)
moel@236
   143
        driver.Delete();
moel@236
   144
moel@236
   145
      driver = null;
moel@236
   146
moel@236
   147
      isaBusMutex.Close(); 
moel@236
   148
    }
moel@236
   149
moel@236
   150
    public static bool WaitIsaBusMutex(int millisecondsTimeout) {
moel@236
   151
      try {
moel@236
   152
        return isaBusMutex.WaitOne(millisecondsTimeout, false);
moel@236
   153
      } catch (AbandonedMutexException) { return false; } 
moel@236
   154
        catch (InvalidOperationException) { return false; }
moel@236
   155
    }
moel@236
   156
moel@236
   157
    public static void ReleaseIsaBusMutex() {
moel@236
   158
      isaBusMutex.ReleaseMutex();
moel@236
   159
    }
moel@236
   160
moel@236
   161
    public static bool Rdmsr(uint index, out uint eax, out uint edx) {
moel@236
   162
      if (driver == null) {
moel@236
   163
        eax = 0;
moel@236
   164
        edx = 0;
moel@236
   165
        return false;
moel@236
   166
      }
moel@236
   167
moel@236
   168
      ulong buffer = 0;
moel@236
   169
      bool result = driver.DeviceIOControl(IOCTL_OLS_READ_MSR, index,
moel@236
   170
        ref buffer);
moel@236
   171
moel@236
   172
      edx = (uint)((buffer >> 32) & 0xFFFFFFFF);
moel@236
   173
      eax = (uint)(buffer & 0xFFFFFFFF);
moel@236
   174
      return result;
moel@236
   175
    }
moel@236
   176
moel@236
   177
    public static bool RdmsrTx(uint index, out uint eax, out uint edx,
moel@238
   178
      ulong threadAffinityMask) 
moel@236
   179
    {
moel@238
   180
      ulong mask = ThreadAffinity.Set(threadAffinityMask);
moel@236
   181
moel@236
   182
      bool result = Rdmsr(index, out eax, out edx);
moel@236
   183
moel@238
   184
      ThreadAffinity.Set(mask);
moel@236
   185
      return result;
moel@236
   186
    }
moel@236
   187
moel@236
   188
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@236
   189
    private struct WrmsrInput {
moel@236
   190
      public uint Register;
moel@236
   191
      public ulong Value;
moel@236
   192
    }
moel@236
   193
moel@236
   194
    public static bool Wrmsr(uint index, uint eax, uint edx) {
moel@236
   195
      if (driver == null)
moel@236
   196
        return false;
moel@236
   197
moel@236
   198
      WrmsrInput input = new WrmsrInput();
moel@236
   199
      input.Register = index;
moel@236
   200
      input.Value = ((ulong)edx << 32) | eax;
moel@236
   201
moel@236
   202
      return driver.DeviceIOControl(IOCTL_OLS_WRITE_MSR, input);
moel@236
   203
    }
moel@236
   204
moel@236
   205
    public static byte ReadIoPort(uint port) {
moel@236
   206
      if (driver == null)
moel@236
   207
        return 0;
moel@236
   208
moel@236
   209
      uint value = 0;
moel@236
   210
      driver.DeviceIOControl(IOCTL_OLS_READ_IO_PORT_BYTE, port, ref value);
moel@236
   211
moel@236
   212
      return (byte)(value & 0xFF);
moel@236
   213
    }
moel@236
   214
moel@236
   215
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@236
   216
    private struct WriteIoPortInput {
moel@236
   217
      public uint PortNumber;
moel@236
   218
      public byte Value;
moel@236
   219
    }
moel@236
   220
moel@236
   221
    public static void WriteIoPort(uint port, byte value) {
moel@236
   222
      if (driver == null)
moel@236
   223
        return;
moel@236
   224
moel@236
   225
      WriteIoPortInput input = new WriteIoPortInput();
moel@236
   226
      input.PortNumber = port;
moel@236
   227
      input.Value = value;
moel@236
   228
moel@236
   229
      driver.DeviceIOControl(IOCTL_OLS_WRITE_IO_PORT_BYTE, input);
moel@236
   230
    }
moel@236
   231
moel@236
   232
    public const uint InvalidPciAddress = 0xFFFFFFFF;
moel@236
   233
moel@236
   234
    public static uint GetPciAddress(byte bus, byte device, byte function) {
moel@236
   235
      return
moel@236
   236
        (uint)(((bus & 0xFF) << 8) | ((device & 0x1F) << 3) | (function & 7));
moel@236
   237
    }
moel@236
   238
moel@236
   239
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@236
   240
    private struct ReadPciConfigInput {
moel@236
   241
      public uint PciAddress;
moel@236
   242
      public uint RegAddress;
moel@236
   243
    }
moel@236
   244
moel@236
   245
    public static bool ReadPciConfig(uint pciAddress, uint regAddress, 
moel@236
   246
      out uint value) 
moel@236
   247
    {
moel@236
   248
      if (driver == null || (regAddress & 3) != 0) {
moel@236
   249
        value = 0;
moel@236
   250
        return false;
moel@236
   251
      }
moel@236
   252
moel@236
   253
      ReadPciConfigInput input = new ReadPciConfigInput();
moel@236
   254
      input.PciAddress = pciAddress;
moel@236
   255
      input.RegAddress = regAddress;
moel@236
   256
moel@236
   257
      value = 0;
moel@236
   258
      return driver.DeviceIOControl(IOCTL_OLS_READ_PCI_CONFIG, input, 
moel@236
   259
        ref value);
moel@236
   260
    }
moel@236
   261
moel@236
   262
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
moel@236
   263
    private struct WritePciConfigInput {
moel@236
   264
      public uint PciAddress;
moel@236
   265
      public uint RegAddress;
moel@236
   266
      public uint Value;
moel@236
   267
    }
moel@236
   268
moel@236
   269
    public static bool WritePciConfig(uint pciAddress, uint regAddress, 
moel@236
   270
      uint value) 
moel@236
   271
    {
moel@236
   272
      if (driver == null || (regAddress & 3) != 0)
moel@236
   273
        return false;
moel@236
   274
moel@236
   275
      WritePciConfigInput input = new WritePciConfigInput();
moel@236
   276
      input.PciAddress = pciAddress;
moel@236
   277
      input.RegAddress = regAddress;
moel@236
   278
      input.Value = value;
moel@236
   279
moel@236
   280
      return driver.DeviceIOControl(IOCTL_OLS_WRITE_PCI_CONFIG, input);
moel@236
   281
    }
moel@236
   282
  }
moel@236
   283
}