Created
February 5, 2020 13:49
-
-
Save Konctantin/2cf939962e489024381e33e74506f769 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Collections; | |
using System.Runtime.InteropServices; | |
using System.Management; | |
using System.ServiceProcess; | |
namespace ConsoleApplication2 | |
{ | |
public sealed class Win32Driver : IDisposable | |
{ | |
string driverName; | |
string execPath; | |
IntPtr fileHandle; | |
public Win32Driver(string driver, string driverExecPath) | |
{ | |
this.driverName = driver; | |
this.execPath = driverExecPath; | |
} | |
~Win32Driver() | |
{ | |
// BUG - should never rely on finalizer to clean-up unmanaged resources | |
Dispose(); | |
} | |
private void CloseStuff() | |
{ | |
if (fileHandle != INVALID_HANDLE_VALUE) | |
{ | |
fileHandle = INVALID_HANDLE_VALUE; | |
CloseHandle(fileHandle); | |
} | |
} | |
public void Dispose() | |
{ | |
CloseStuff(); | |
GC.SuppressFinalize(this); | |
} | |
private readonly static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); | |
private const int STANDARD_RIGHTS_REQUIRED = 0x000F0000; | |
private const int SC_MANAGER_CONNECT = 0x0001; | |
private const int SC_MANAGER_CREATE_SERVICE = 0x0002; | |
private const int SC_MANAGER_ENUMERATE_SERVICE = 0x0004; | |
private const int SC_MANAGER_LOCK = 0x0008; | |
private const int SC_MANAGER_QUERY_LOCK_STATUS = 0x0010; | |
private const int SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020; | |
private const int SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | | |
SC_MANAGER_CONNECT | | |
SC_MANAGER_CREATE_SERVICE | | |
SC_MANAGER_ENUMERATE_SERVICE | | |
SC_MANAGER_LOCK | | |
SC_MANAGER_QUERY_LOCK_STATUS | | |
SC_MANAGER_MODIFY_BOOT_CONFIG; | |
private const int SERVICE_QUERY_CONFIG = 0x0001; | |
private const int SERVICE_CHANGE_CONFIG = 0x0002; | |
private const int SERVICE_QUERY_STATUS = 0x0004; | |
private const int SERVICE_ENUMERATE_DEPENDENTS = 0x0008; | |
private const int SERVICE_START = 0x0010; | |
private const int SERVICE_STOP = 0x0020; | |
private const int SERVICE_PAUSE_CONTINUE = 0x0040; | |
private const int SERVICE_INTERROGATE = 0x0080; | |
private const int SERVICE_USER_DEFINED_CONTROL = 0x0100; | |
private const int SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | |
| | |
SERVICE_QUERY_CONFIG | | |
SERVICE_CHANGE_CONFIG | | |
SERVICE_QUERY_STATUS | | |
SERVICE_ENUMERATE_DEPENDENTS | | |
SERVICE_START | | |
SERVICE_STOP | | |
SERVICE_PAUSE_CONTINUE | | |
SERVICE_INTERROGATE | | |
SERVICE_USER_DEFINED_CONTROL; | |
private const int SERVICE_DEMAND_START = 0x00000003; | |
private const int SERVICE_KERNEL_DRIVER = 0x00000001; | |
private const int SERVICE_ERROR_NORMAL = 0x00000001; | |
private const uint GENERIC_READ = 0x80000000; | |
private const uint FILE_SHARE_READ = 1; | |
private const uint FILE_SHARE_WRITE = 2; | |
private const uint OPEN_EXISTING = 3; | |
private const uint IOCTL_SHOCKMGR_READ_ACCELEROMETER_DATA = 0x733fc; | |
private const int FACILITY_WIN32 = unchecked((int)0x80070000); | |
private IntPtr handle = INVALID_HANDLE_VALUE; | |
[DllImport("advapi32", SetLastError = true)] | |
internal static extern IntPtr OpenSCManager(string machineName, string | |
databaseName, uint dwDesiredAccess); | |
[DllImport("advapi32", SetLastError = true)] | |
internal static extern IntPtr CreateService(IntPtr hSCManager, string | |
serviceName, string displayName, | |
uint dwDesiredAccess, uint serviceType, uint startType, uint | |
errorControl, | |
string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, | |
string lpDependencies, | |
string lpServiceStartName, string lpPassword); | |
[DllImport("advapi32")] | |
internal static extern bool CloseServiceHandle(IntPtr handle); | |
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] | |
static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess); | |
[DllImport("kernel32", SetLastError = true)] | |
internal static extern IntPtr CreateFile(string lpFileName, uint | |
dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint | |
dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); | |
[DllImport("kernel32")] | |
internal static extern void CloseHandle(IntPtr handle); | |
[DllImport("kernel32", SetLastError = true)] | |
private static extern bool DeviceIoControl(IntPtr hDevice, uint | |
dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, | |
uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped); | |
internal bool LoadDeviceDriver() | |
{ | |
IntPtr scHandle = OpenSCManager(null, null, SC_MANAGER_ALL_ACCESS); | |
Console.WriteLine("OpenSCManager: " + scHandle); | |
if (scHandle != INVALID_HANDLE_VALUE) | |
{ | |
IntPtr hService = CreateService(scHandle, this.driverName, | |
this.driverName, SERVICE_ALL_ACCESS | |
, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL | |
,execPath, null, null, null, null, null); | |
Console.WriteLine("CreateService: " + hService); | |
hService = OpenService(scHandle, this.driverName, | |
SERVICE_START | SERVICE_STOP); | |
Console.WriteLine("OpenService: "+hService); | |
if (hService != IntPtr.Zero) | |
{ | |
CloseServiceHandle(hService); // close both handles | |
CloseServiceHandle(scHandle); | |
// Start the driver using System.Management (WMI) | |
if (ExecuteSCMOperationOnDriver(this.driverName, "StartService") == 0) | |
{ | |
return true; | |
} | |
} | |
else | |
if (Marshal.GetLastWin32Error()== 1073) // Driver/Service already in DB | |
{ | |
Console.WriteLine("Marshal=1073"); | |
CloseServiceHandle(scHandle); | |
// Start the driver using System.Management (WMI) | |
if (ExecuteSCMOperationOnDriver(this.driverName, "StartService") == 0) | |
{ | |
return true; | |
} | |
} | |
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error())); | |
} | |
return false; | |
} | |
internal bool UnloadDeviceDriver() | |
{ | |
int ret = 0; | |
Console.WriteLine("Unloading now..."); | |
if (fileHandle != IntPtr.Zero && fileHandle != INVALID_HANDLE_VALUE) | |
{ | |
CloseHandle(fileHandle); | |
} | |
if ((ret = ExecuteSCMOperationOnDriver(driverName, "StopService")) == 0) | |
{ | |
ret = ExecuteSCMOperationOnDriver(driverName, "Delete"); | |
} | |
if (ret != 0) | |
{ | |
return false; | |
} | |
return true; | |
} | |
private static int ExecuteSCMOperationOnDriver(string driverName, string operation) | |
{ | |
ManagementPath path = new ManagementPath(); | |
path.Server = "."; | |
path.NamespacePath = @"root\CIMV2"; | |
path.RelativePath = @"Win32_BaseService.Name='" + driverName + "'"; | |
using (ManagementObject o = new ManagementObject(path)) | |
{ | |
ManagementBaseObject outParams = o.InvokeMethod(operation,null, null); | |
return Convert.ToInt32(outParams.Properties["ReturnValue"].Value); | |
} | |
} | |
internal IntPtr OpenDevice() | |
{ | |
Console.WriteLine(driverName); | |
fileHandle = CreateFile("\\\\.\\"+driverName, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); | |
Console.WriteLine("CreateFile: "+fileHandle); | |
//Console.WriteLine(Marshal.GetLastWin32Error()); | |
if(fileHandle == INVALID_HANDLE_VALUE) | |
{ | |
Console.WriteLine("Throw exception"); | |
Console.WriteLine((Marshal.GetLastWin32Error()).ToString()+"\n\n\n"); | |
//Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error())); | |
} | |
return fileHandle; | |
} | |
internal IntPtr DevControl() | |
{ | |
Console.WriteLine("DevControl started"); | |
//long DeviceBuffer = 0; | |
IntPtr dwState = new IntPtr(100); | |
uint dwRet=0; | |
bool dc = DeviceIoControl(fileHandle, FSConstants.IO_SET_EVENT, IntPtr.Zero, 0, dwState, (uint)Marshal.SizeOf(dwRet), ref dwRet, IntPtr.Zero); | |
Console.WriteLine("Operation: "+dc); | |
Console.WriteLine("Return Value: "+dwRet); | |
Console.WriteLine("Error: "+(Marshal.GetLastWin32Error()).ToString() + "\n\n\n"); | |
if (fileHandle == INVALID_HANDLE_VALUE) | |
{ | |
//Console.WriteLine("Throw exception"); | |
//Console.WriteLine((Marshal.GetLastWin32Error()).ToString()+"\n\n\n"); | |
//Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(Marshal.GetLastWin32Error())); | |
} | |
return fileHandle; | |
} | |
private static int HRESULT_FROM_WIN32(int x) | |
{ | |
return x <= 0 ? x : ((x & 0x0000FFFF) | FACILITY_WIN32); | |
} | |
} | |
internal class FSConstants | |
{ | |
private const int FILE_DEVICE_COMM_DRIVER = 0x00008810; | |
const uint METHOD_NEITHER = 3; | |
const uint METHOD_BUFFERED = 0; | |
const uint FILE_ANY_ACCESS = 0; | |
const uint FILE_SPECIAL_ACCESS = FILE_ANY_ACCESS; | |
public static uint IO_SET_EVENT = CTL_CODE(FILE_DEVICE_COMM_DRIVER, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS); | |
static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access) | |
{ | |
return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment