Fixed Issue 215.
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
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.Runtime.InteropServices;
41 using System.Security.AccessControl;
42 using Microsoft.Win32.SafeHandles;
44 namespace OpenHardwareMonitor.Hardware {
45 internal class KernelDriver {
49 private SafeFileHandle device;
51 public KernelDriver(string id) {
55 public bool Install(string path) {
56 IntPtr manager = NativeMethods.OpenSCManager(null, null,
57 ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
59 if (manager == IntPtr.Zero)
62 IntPtr service = NativeMethods.CreateService(manager, id, id,
63 ServiceAccessRights.SERVICE_ALL_ACCESS,
64 ServiceType.SERVICE_KERNEL_DRIVER, StartType.SERVICE_DEMAND_START,
65 ErrorControl.SERVICE_ERROR_NORMAL, path, null, null, null, null,
68 if (service == IntPtr.Zero) {
69 if (Marshal.GetHRForLastWin32Error() == ERROR_SERVICE_EXISTS)
70 service = NativeMethods.OpenService(manager, id,
71 ServiceAccessRights.SERVICE_ALL_ACCESS);
76 if (!NativeMethods.StartService(service, 0, null)) {
77 if (Marshal.GetHRForLastWin32Error() != ERROR_SERVICE_ALREADY_RUNNING)
81 NativeMethods.CloseServiceHandle(service);
82 NativeMethods.CloseServiceHandle(manager);
85 // restrict the driver access to system (SY) and builtin admins (BA)
86 // TODO: replace with a call to IoCreateDeviceSecure in the driver
87 FileSecurity fileSecurity = File.GetAccessControl(@"\\.\" + id);
88 fileSecurity.SetSecurityDescriptorSddlForm(
89 "O:BAG:SYD:(A;;FA;;;SY)(A;;FA;;;BA)");
90 File.SetAccessControl(@"\\.\" + id, fileSecurity);
97 device = new SafeFileHandle(NativeMethods.CreateFile(@"\\.\" + id,
98 FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE, 0, IntPtr.Zero,
99 CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL,
102 if (device.IsInvalid) {
108 return device != null;
112 get { return device != null; }
115 public bool DeviceIOControl(IOControlCode ioControlCode, object inBuffer) {
120 bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
121 inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
122 null, 0, out bytesReturned, IntPtr.Zero);
126 public bool DeviceIOControl<T>(IOControlCode ioControlCode, object inBuffer,
132 object boxedOutBuffer = outBuffer;
134 bool b = NativeMethods.DeviceIoControl(device, ioControlCode,
135 inBuffer, inBuffer == null ? 0 : (uint)Marshal.SizeOf(inBuffer),
136 boxedOutBuffer, (uint)Marshal.SizeOf(boxedOutBuffer),
137 out bytesReturned, IntPtr.Zero);
138 outBuffer = (T)boxedOutBuffer;
142 public void Close() {
143 if (device != null) {
150 public bool Delete() {
151 IntPtr manager = NativeMethods.OpenSCManager(null, null,
152 ServiceControlManagerAccessRights.SC_MANAGER_ALL_ACCESS);
154 if (manager == IntPtr.Zero)
157 IntPtr service = NativeMethods.OpenService(manager, id,
158 ServiceAccessRights.SERVICE_ALL_ACCESS);
160 if (service == IntPtr.Zero)
163 ServiceStatus status = new ServiceStatus();
164 NativeMethods.ControlService(service, ServiceControl.SERVICE_CONTROL_STOP,
167 NativeMethods.DeleteService(service);
169 NativeMethods.CloseServiceHandle(service);
170 NativeMethods.CloseServiceHandle(manager);
175 private enum ServiceAccessRights : uint {
176 SERVICE_ALL_ACCESS = 0xF01FF
179 private enum ServiceControlManagerAccessRights : uint {
180 SC_MANAGER_ALL_ACCESS = 0xF003F
183 private enum ServiceType : uint {
184 SERVICE_KERNEL_DRIVER = 1,
185 SERVICE_FILE_SYSTEM_DRIVER = 2
188 private enum StartType : uint {
189 SERVICE_BOOT_START = 0,
190 SERVICE_SYSTEM_START = 1,
191 SERVICE_AUTO_START = 2,
192 SERVICE_DEMAND_START = 3,
196 private enum ErrorControl : uint {
197 SERVICE_ERROR_IGNORE = 0,
198 SERVICE_ERROR_NORMAL = 1,
199 SERVICE_ERROR_SEVERE = 2,
200 SERVICE_ERROR_CRITICAL = 3
203 private enum ServiceControl : uint {
204 SERVICE_CONTROL_STOP = 1,
205 SERVICE_CONTROL_PAUSE = 2,
206 SERVICE_CONTROL_CONTINUE = 3,
207 SERVICE_CONTROL_INTERROGATE = 4,
208 SERVICE_CONTROL_SHUTDOWN = 5,
209 SERVICE_CONTROL_PARAMCHANGE = 6,
210 SERVICE_CONTROL_NETBINDADD = 7,
211 SERVICE_CONTROL_NETBINDREMOVE = 8,
212 SERVICE_CONTROL_NETBINDENABLE = 9,
213 SERVICE_CONTROL_NETBINDDISABLE = 10,
214 SERVICE_CONTROL_DEVICEEVENT = 11,
215 SERVICE_CONTROL_HARDWAREPROFILECHANGE = 12,
216 SERVICE_CONTROL_POWEREVENT = 13,
217 SERVICE_CONTROL_SESSIONCHANGE = 14
220 [StructLayout(LayoutKind.Sequential, Pack = 1)]
221 private struct ServiceStatus {
222 public uint dwServiceType;
223 public uint dwCurrentState;
224 public uint dwControlsAccepted;
225 public uint dwWin32ExitCode;
226 public uint dwServiceSpecificExitCode;
227 public uint dwCheckPoint;
228 public uint dwWaitHint;
231 private enum FileAccess : uint {
232 GENERIC_READ = 0x80000000,
233 GENERIC_WRITE = 0x40000000
236 private enum CreationDisposition : uint {
241 TRUNCATE_EXISTING = 5
244 private enum FileAttributes : uint {
245 FILE_ATTRIBUTE_NORMAL = 0x80
249 ERROR_SERVICE_EXISTS = unchecked((int)0x80070431),
250 ERROR_SERVICE_ALREADY_RUNNING = unchecked((int)0x80070420);
252 private static class NativeMethods {
253 private const string ADVAPI = "advapi32.dll";
254 private const string KERNEL = "kernel32.dll";
256 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
257 public static extern IntPtr OpenSCManager(string machineName,
258 string databaseName, ServiceControlManagerAccessRights dwAccess);
260 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi)]
261 [return: MarshalAs(UnmanagedType.Bool)]
262 public static extern bool CloseServiceHandle(IntPtr hSCObject);
264 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
265 SetLastError = true)]
266 public static extern IntPtr CreateService(IntPtr hSCManager,
267 string lpServiceName, string lpDisplayName,
268 ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType,
269 StartType dwStartType, ErrorControl dwErrorControl,
270 string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId,
271 string lpDependencies, string lpServiceStartName, string lpPassword);
273 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
274 SetLastError = true)]
275 public static extern IntPtr OpenService(IntPtr hSCManager,
276 string lpServiceName, ServiceAccessRights dwDesiredAccess);
278 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
279 SetLastError = true)]
280 [return: MarshalAs(UnmanagedType.Bool)]
281 public static extern bool DeleteService(IntPtr hService);
283 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
284 SetLastError = true)]
285 [return: MarshalAs(UnmanagedType.Bool)]
286 public static extern bool StartService(IntPtr hService,
287 uint dwNumServiceArgs, string[] lpServiceArgVectors);
289 [DllImport(ADVAPI, CallingConvention = CallingConvention.Winapi,
290 SetLastError = true)]
291 [return: MarshalAs(UnmanagedType.Bool)]
292 public static extern bool ControlService(IntPtr hService,
293 ServiceControl dwControl, ref ServiceStatus lpServiceStatus);
295 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
296 public static extern bool DeviceIoControl(SafeFileHandle device,
297 IOControlCode ioControlCode,
298 [MarshalAs(UnmanagedType.AsAny)] [In] object inBuffer,
300 [MarshalAs(UnmanagedType.AsAny)] [Out] object outBuffer,
301 uint nOutBufferSize, out uint bytesReturned, IntPtr overlapped);
303 [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi,
304 SetLastError = true)]
305 public static extern IntPtr CreateFile(string lpFileName,
306 FileAccess dwDesiredAccess, uint dwShareMode,
307 IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
308 FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);