Changed the license to the Mozilla Public License 2.0 and update the licensing information.
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 Michael Möller <mmoeller@openhardwaremonitor.org>
13 using System.Runtime.InteropServices;
14 using System.Security.AccessControl;
15 using Microsoft.Win32.SafeHandles;
17 namespace OpenHardwareMonitor.Hardware {
18 internal class KernelDriver {
22 private SafeFileHandle device;
24 public KernelDriver(string id) {
28 public bool Install(string path) {
29 IntPtr manager = NativeMethods.OpenSCManager(null, null,
30 ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
32 if (manager == IntPtr.Zero)
35 IntPtr service = NativeMethods.CreateService(manager, id, id,
36 ServiceAccessRights.SERVICE_ALL_ACCESS,
37 ServiceType.SERVICE_KERNEL_DRIVER, StartType.SERVICE_DEMAND_START,
38 ErrorControl.SERVICE_ERROR_NORMAL, path, null, null, null, null,
41 if (service == IntPtr.Zero) {
42 if (Marshal.GetHRForLastWin32Error() == ERROR_SERVICE_EXISTS)
43 service = NativeMethods.OpenService(manager, id,
44 ServiceAccessRights.SERVICE_ALL_ACCESS);
49 if (!NativeMethods.StartService(service, 0, null)) {
50 if (Marshal.GetHRForLastWin32Error() != ERROR_SERVICE_ALREADY_RUNNING)
54 NativeMethods.CloseServiceHandle(service);
55 NativeMethods.CloseServiceHandle(manager);
58 // restrict the driver access to system (SY) and builtin admins (BA)
59 // TODO: replace with a call to IoCreateDeviceSecure in the driver
60 FileSecurity fileSecurity = File.GetAccessControl(@"\\.\" + id);
61 fileSecurity.SetSecurityDescriptorSddlForm(
62 "O:BAG:SYD:(A;;FA;;;SY)(A;;FA;;;BA)");
63 File.SetAccessControl(@"\\.\" + id, fileSecurity);
70 device = new SafeFileHandle(NativeMethods.CreateFile(@"\\.\" + id,
71 FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE, 0, IntPtr.Zero,
72 CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL,
75 if (device.IsInvalid) {
81 return device != null;
85 get { return device != null; }
88 public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer) {
93 bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
94 inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
95 null, 0, out bytesReturned, IntPtr.Zero);
99 public bool DeviceIOControl<T>(IOControlCode ioControlCode, object inBuffer,
105 object boxedOutBuffer = outBuffer;
107 bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
108 inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
109 boxedOutBuffer, (uint)Marshal.SizeOf(boxedOutBuffer),
110 out bytesReturned, IntPtr.Zero);
111 outBuffer = (T)boxedOutBuffer;
115 public void Close() {
116 if (device != null) {
123 public bool Delete() {
124 IntPtr manager = NativeMethods.OpenSCManager(null, null,
125 ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
127 if (manager == IntPtr.Zero)
130 IntPtr service = NativeMethods.OpenService(manager, id,
131 ServiceAccessRights.SERVICE_ALL_ACCESS);
133 if (service == IntPtr.Zero)
136 ServiceStatus status = new ServiceStatus();
137 NativeMethods.ControlService(service, ServiceControl.SERVICE_CONTROL_STOP,
140 NativeMethods.DeleteService(service);
142 NativeMethods.CloseServiceHandle(service);
143 NativeMethods.CloseServiceHandle(manager);
148 private enum ServiceAccessRights : uint {
149 SERVICE_ALL_ACCESS = 0xF01FF
152 private enum ServiceControlManagerAccessRights : uint {
153 SC_MANAGER_ALL_ACCESS = 0xF003F
156 private enum ServiceType : uint {
157 SERVICE_KERNEL_DRIVER = 1,
158 SERVICE_FILE_SYSTEM_DRIVER = 2
161 private enum StartType : uint {
162 SERVICE_BOOT_START = 0,
163 SERVICE_SYSTEM_START = 1,
164 SERVICE_AUTO_START = 2,
165 SERVICE_DEMAND_START = 3,
169 private enum ErrorControl : uint {
170 SERVICE_ERROR_IGNORE = 0,
171 SERVICE_ERROR_NORMAL = 1,
172 SERVICE_ERROR_SEVERE = 2,
173 SERVICE_ERROR_CRITICAL = 3
176 private enum ServiceControl : uint {
177 SERVICE_CONTROL_STOP = 1,
178 SERVICE_CONTROL_PAUSE = 2,
179 SERVICE_CONTROL_CONTINUE = 3,
180 SERVICE_CONTROL_INTERROGATE = 4,
181 SERVICE_CONTROL_SHUTDOWN = 5,
182 SERVICE_CONTROL_PARAMCHANGE = 6,
183 SERVICE_CONTROL_NETBINDADD = 7,
184 SERVICE_CONTROL_NETBINDREMOVE = 8,
185 SERVICE_CONTROL_NETBINDENABLE = 9,
186 SERVICE_CONTROL_NETBINDDISABLE = 10,
187 SERVICE_CONTROL_DEVICEEVENT = 11,
188 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12,
189 SERVICE_CONTROL_POWEREVENT = 13,
190 SERVICE_CONTROL_SESSIONCHANGE = 14
193 [StructLayout(LayoutKind.Sequential, Pack = 1)]
194 private struct ServiceStatus {
195 public uint dwServiceType;
196 public uint dwCurrentState;
197 public uint dwControlsAccepted;
198 public uint dwWin32ExitCode;
199 public uint dwServiceSpecificExitCode;
200 public uint dwCheckPoint;
201 public uint dwWaitHint;
204 private enum FileAccess : uint {
205 GENERIC_READ = 0x80000000,
206 GENERIC_WRITE = 0x40000000
209 private enum CreationDisposition : uint {
214 TRUNCATE_EXISTING = 5
217 private enum FileAttributes : uint {
218 FILE_ATTRIBUTE_NORMAL = 0x80
222 ERROR_SERVICE_EXISTS = unchecked((int)0x80070431),
223 ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420);
225 private static class NativeMethods {
226 private const string ADVAPI = "advapi32.dll";
227 private const string KERNEL = "kernel32.dll";
229 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
230 public static extern IntPtr OpenSCManager(string machineName,
231 string databaseName, ServiceControlManagerAccessRights dwAccess);
233 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
234 [return: MarshalAs(UnmanagedType.Bool)]
235 public static extern bool CloseServiceHandle(IntPtr hSCObject);
237 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
238 SetLastError = true)]
239 public static extern IntPtr CreateService(IntPtr hSCManager,
240 string lpServiceName, string lpDisplayName,
241 ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType,
242 StartType dwStartType, ErrorControl dwErrorControl,
243 string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId,
244 string lpDependencies, string lpServiceStartName, string lpPassword);
246 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
247 SetLastError = true)]
248 public static extern IntPtr OpenService(IntPtr hSCManager,
249 string lpServiceName, ServiceAccessRights dwDesiredAccess);
251 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
252 SetLastError = true)]
253 [return: MarshalAs(UnmanagedType.Bool)]
254 public static extern bool DeleteService(IntPtr hService);
256 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
257 SetLastError = true)]
258 [return: MarshalAs(UnmanagedType.Bool)]
259 public static extern bool StartService(IntPtr hService,
260 uint dwNumServiceArgs, string[] lpServiceArgVectors);
262 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
263 SetLastError = true)]
264 [return: MarshalAs(UnmanagedType.Bool)]
265 public static extern bool ControlService(IntPtr hService,
266 ServiceControl dwControl, ref ServiceStatus lpServiceStatus);
268 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
269 public static extern bool DeviceIoControl(SafeFileHandle device,
270 IOControlCode ioControlCode,
271 [MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer,
273 [MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer,
274 uint nOutBufferSize, out uint bytesReturned, IntPtr overlapped);
276 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi,
277 SetLastError = true)]
278 public static extern IntPtr CreateFile(string lpFileName,
279 FileAccess dwDesiredAccess, uint dwShareMode,
280 IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
281 FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);