1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Hardware/KernelDriver.cs Sun Oct 31 22:08:47 2010 +0000
1.3 @@ -0,0 +1,300 @@
1.4 +/*
1.5 +
1.6 + Version: MPL 1.1/GPL 2.0/LGPL 2.1
1.7 +
1.8 + The contents of this file are subject to the Mozilla Public License Version
1.9 + 1.1 (the "License"); you may not use this file except in compliance with
1.10 + the License. You may obtain a copy of the License at
1.11 +
1.12 + http://www.mozilla.org/MPL/
1.13 +
1.14 + Software distributed under the License is distributed on an "AS IS" basis,
1.15 + WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1.16 + for the specific language governing rights and limitations under the License.
1.17 +
1.18 + The Original Code is the Open Hardware Monitor code.
1.19 +
1.20 + The Initial Developer of the Original Code is
1.21 + Michael Möller <m.moeller@gmx.ch>.
1.22 + Portions created by the Initial Developer are Copyright (C) 2010
1.23 + the Initial Developer. All Rights Reserved.
1.24 +
1.25 + Contributor(s):
1.26 +
1.27 + Alternatively, the contents of this file may be used under the terms of
1.28 + either the GNU General Public License Version 2 or later (the "GPL"), or
1.29 + the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
1.30 + in which case the provisions of the GPL or the LGPL are applicable instead
1.31 + of those above. If you wish to allow use of your version of this file only
1.32 + under the terms of either the GPL or the LGPL, and not to allow others to
1.33 + use your version of this file under the terms of the MPL, indicate your
1.34 + decision by deleting the provisions above and replace them with the notice
1.35 + and other provisions required by the GPL or the LGPL. If you do not delete
1.36 + the provisions above, a recipient may use your version of this file under
1.37 + the terms of any one of the MPL, the GPL or the LGPL.
1.38 +
1.39 +*/
1.40 +
1.41 +using System;
1.42 +using System.Runtime.InteropServices;
1.43 +using Microsoft.Win32.SafeHandles;
1.44 +
1.45 +namespace OpenHardwareMonitor.Hardware {
1.46 + internal class KernelDriver {
1.47 +
1.48 + private string id;
1.49 +
1.50 + private SafeFileHandle device;
1.51 +
1.52 + public KernelDriver(string id) {
1.53 + this.id = id;
1.54 + }
1.55 +
1.56 + public bool Install(string path) {
1.57 + IntPtr manager = NativeMethods.OpenSCManager(null, null,
1.58 + ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
1.59 +
1.60 + if (manager == IntPtr.Zero)
1.61 + return false;
1.62 +
1.63 + IntPtr service = NativeMethods.CreateService(manager, id, id,
1.64 + ServiceAccessRights.SERVICE_ALL_ACCESS,
1.65 + ServiceType.SERVICE_KERNEL_DRIVER, StartType.SERVICE_DEMAND_START,
1.66 + ErrorControl.SERVICE_ERROR_NORMAL, path, null, null, null, null,
1.67 + null);
1.68 +
1.69 + if (service == IntPtr.Zero) {
1.70 + if (Marshal.GetHRForLastWin32Error() == ERROR_SERVICE_EXISTS)
1.71 + service = NativeMethods.OpenService(manager, id,
1.72 + ServiceAccessRights.SERVICE_ALL_ACCESS);
1.73 + else
1.74 + return false;
1.75 + }
1.76 +
1.77 + if (!NativeMethods.StartService(service, 0, null)) {
1.78 + if (Marshal.GetHRForLastWin32Error() != ERROR_SERVICE_ALREADY_RUNNING)
1.79 + return false;
1.80 + }
1.81 +
1.82 + NativeMethods.CloseServiceHandle(service);
1.83 + NativeMethods.CloseServiceHandle(manager);
1.84 +
1.85 + return true;
1.86 + }
1.87 +
1.88 + public bool Open() {
1.89 + device = new SafeFileHandle(NativeMethods.CreateFile(@"\\.\" + id,
1.90 + FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE, 0, IntPtr.Zero,
1.91 + CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL,
1.92 + IntPtr.Zero), true);
1.93 +
1.94 + if (device.IsInvalid) {
1.95 + device.Close();
1.96 + device.Dispose();
1.97 + device = null;
1.98 + }
1.99 +
1.100 + return device != null;
1.101 + }
1.102 +
1.103 + public bool IsOpen {
1.104 + get { return device != null; }
1.105 + }
1.106 +
1.107 + public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer) {
1.108 + if (device == null)
1.109 + return false;
1.110 +
1.111 + uint bytesReturned;
1.112 + bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
1.113 + inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
1.114 + null, 0, out bytesReturned, IntPtr.Zero);
1.115 + return b;
1.116 + }
1.117 +
1.118 + public bool DeviceIOControl<T>(IOControlCode ioControlCode, object inBuffer,
1.119 + ref T outBuffer)
1.120 + {
1.121 + if (device == null)
1.122 + return false;
1.123 +
1.124 + object boxedOutBuffer = outBuffer;
1.125 + uint bytesReturned;
1.126 + bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
1.127 + inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
1.128 + boxedOutBuffer, (uint)Marshal.SizeOf(boxedOutBuffer),
1.129 + out bytesReturned, IntPtr.Zero);
1.130 + outBuffer = (T)boxedOutBuffer;
1.131 + return b;
1.132 + }
1.133 +
1.134 + public void Close() {
1.135 + if (device != null) {
1.136 + device.Close();
1.137 + device.Dispose();
1.138 + device = null;
1.139 + }
1.140 + }
1.141 +
1.142 + public bool Delete() {
1.143 + IntPtr manager = NativeMethods.OpenSCManager(null, null,
1.144 + ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
1.145 +
1.146 + if (manager == IntPtr.Zero)
1.147 + return false;
1.148 +
1.149 + IntPtr service = NativeMethods.OpenService(manager, id,
1.150 + ServiceAccessRights.SERVICE_ALL_ACCESS);
1.151 +
1.152 + if (service == IntPtr.Zero)
1.153 + return true;
1.154 +
1.155 + ServiceStatus status = new ServiceStatus();
1.156 + NativeMethods.ControlService(service, ServiceControl.SERVICE_CONTROL_STOP,
1.157 + ref status);
1.158 +
1.159 + NativeMethods.DeleteService(service);
1.160 +
1.161 + NativeMethods.CloseServiceHandle(service);
1.162 + NativeMethods.CloseServiceHandle(manager);
1.163 +
1.164 + return true;
1.165 + }
1.166 +
1.167 + private enum ServiceAccessRights : uint {
1.168 + SERVICE_ALL_ACCESS = 0xF01FF
1.169 + }
1.170 +
1.171 + private enum ServiceControlManagerAccessRights : uint {
1.172 + SC_MANAGER_ALL_ACCESS = 0xF003F
1.173 + }
1.174 +
1.175 + private enum ServiceType : uint {
1.176 + SERVICE_KERNEL_DRIVER = 1,
1.177 + SERVICE_FILE_SYSTEM_DRIVER = 2
1.178 + }
1.179 +
1.180 + private enum StartType : uint {
1.181 + SERVICE_BOOT_START = 0,
1.182 + SERVICE_SYSTEM_START = 1,
1.183 + SERVICE_AUTO_START = 2,
1.184 + SERVICE_DEMAND_START = 3,
1.185 + SERVICE_DISABLED = 4
1.186 + }
1.187 +
1.188 + private enum ErrorControl : uint {
1.189 + SERVICE_ERROR_IGNORE = 0,
1.190 + SERVICE_ERROR_NORMAL = 1,
1.191 + SERVICE_ERROR_SEVERE = 2,
1.192 + SERVICE_ERROR_CRITICAL = 3
1.193 + }
1.194 +
1.195 + private enum ServiceControl : uint {
1.196 + SERVICE_CONTROL_STOP = 1,
1.197 + SERVICE_CONTROL_PAUSE = 2,
1.198 + SERVICE_CONTROL_CONTINUE = 3,
1.199 + SERVICE_CONTROL_INTERROGATE = 4,
1.200 + SERVICE_CONTROL_SHUTDOWN = 5,
1.201 + SERVICE_CONTROL_PARAMCHANGE = 6,
1.202 + SERVICE_CONTROL_NETBINDADD = 7,
1.203 + SERVICE_CONTROL_NETBINDREMOVE = 8,
1.204 + SERVICE_CONTROL_NETBINDENABLE = 9,
1.205 + SERVICE_CONTROL_NETBINDDISABLE = 10,
1.206 + SERVICE_CONTROL_DEVICEEVENT = 11,
1.207 + SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12,
1.208 + SERVICE_CONTROL_POWEREVENT = 13,
1.209 + SERVICE_CONTROL_SESSIONCHANGE = 14
1.210 + }
1.211 +
1.212 + [StructLayout(LayoutKind.Sequential, Pack = 1)]
1.213 + private struct ServiceStatus {
1.214 + public uint dwServiceType;
1.215 + public uint dwCurrentState;
1.216 + public uint dwControlsAccepted;
1.217 + public uint dwWin32ExitCode;
1.218 + public uint dwServiceSpecificExitCode;
1.219 + public uint dwCheckPoint;
1.220 + public uint dwWaitHint;
1.221 + }
1.222 +
1.223 + private enum FileAccess : uint {
1.224 + GENERIC_READ = 0x80000000,
1.225 + GENERIC_WRITE = 0x40000000
1.226 + }
1.227 +
1.228 + private enum CreationDisposition : uint {
1.229 + CREATE_NEW = 1,
1.230 + CREATE_ALWAYS = 2,
1.231 + OPEN_EXISTING = 3,
1.232 + OPEN_ALWAYS = 4,
1.233 + TRUNCATE_EXISTING = 5
1.234 + }
1.235 +
1.236 + private enum FileAttributes : uint {
1.237 + FILE_ATTRIBUTE_NORMAL = 0x80
1.238 + }
1.239 +
1.240 + private const int
1.241 + ERROR_SERVICE_EXISTS = unchecked((int)0x80070431),
1.242 + ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420);
1.243 +
1.244 + private static class NativeMethods {
1.245 + private const string ADVAPI = "advapi32.dll";
1.246 + private const string KERNEL = "kernel32.dll";
1.247 +
1.248 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
1.249 + public static extern IntPtr OpenSCManager(string machineName,
1.250 + string databaseName, ServiceControlManagerAccessRights dwAccess);
1.251 +
1.252 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
1.253 + [return: MarshalAs(UnmanagedType.Bool)]
1.254 + public static extern bool CloseServiceHandle(IntPtr hSCObject);
1.255 +
1.256 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
1.257 + SetLastError = true)]
1.258 + public static extern IntPtr CreateService(IntPtr hSCManager,
1.259 + string lpServiceName, string lpDisplayName,
1.260 + ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType,
1.261 + StartType dwStartType, ErrorControl dwErrorControl,
1.262 + string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId,
1.263 + string lpDependencies, string lpServiceStartName, string lpPassword);
1.264 +
1.265 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
1.266 + SetLastError = true)]
1.267 + public static extern IntPtr OpenService(IntPtr hSCManager,
1.268 + string lpServiceName, ServiceAccessRights dwDesiredAccess);
1.269 +
1.270 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
1.271 + SetLastError = true)]
1.272 + [return: MarshalAs(UnmanagedType.Bool)]
1.273 + public static extern bool DeleteService(IntPtr hService);
1.274 +
1.275 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
1.276 + SetLastError = true)]
1.277 + [return: MarshalAs(UnmanagedType.Bool)]
1.278 + public static extern bool StartService(IntPtr hService,
1.279 + uint dwNumServiceArgs, string[] lpServiceArgVectors);
1.280 +
1.281 + [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
1.282 + SetLastError = true)]
1.283 + [return: MarshalAs(UnmanagedType.Bool)]
1.284 + public static extern bool ControlService(IntPtr hService,
1.285 + ServiceControl dwControl, ref ServiceStatus lpServiceStatus);
1.286 +
1.287 + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
1.288 + public static extern bool DeviceIoControl(SafeFileHandle device,
1.289 + IOControlCode ioControlCode,
1.290 + [MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer,
1.291 + uint inBufferSize,
1.292 + [MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer,
1.293 + uint nOutBufferSize, out uint bytesReturned, IntPtr overlapped);
1.294 +
1.295 + [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi,
1.296 + SetLastError = true)]
1.297 + public static extern IntPtr CreateFile(string lpFileName,
1.298 + FileAccess dwDesiredAccess, uint dwShareMode,
1.299 + IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
1.300 + FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
1.301 + }
1.302 + }
1.303 +}