Re: Is C# support load device driver?

From: Willy Denoyette [MVP] (willy.denoyette_at_pandora.be)
Date: 09/25/04


Date: Sat, 25 Sep 2004 19:04:06 +0200


"Steve" <Steve@discussions.microsoft.com> wrote in message
news:82758F85-EFBE-4A78-A10B-5E3177AB354E@microsoft.com...
> All,
>
> Thanks for the help about this issue.
>
> Willy,
>
> I think you answer my question, for I am new in C#, I will try figure out
> how to implement based on your suggestion, really appreciated.
>
> "Willy Denoyette [MVP]" wrote:
>

Steve,

I would never use C# for this, but here's a sample class that illustrates
how to manage driver loading/unloading using both PInvoke interop and WMI.

Note this is no production code, it's only meant to illustrate how to:
- load a driver.
- start the driver
- open the device
- stop the driver
- unload the driver
using C#.

usage:
 Win32Driver driver = new Win32Driver(driverName,
@"c:\\folder\\mydriver.sys");
  if (driver.LoadDeviceDriver()){
      IntPtr handle = driver.OpenDevice();
    // use device using ....DeviceIoControl(handle,....) see class code for
signature
    }
   //unload when done
  driver.UnloadDeviceDriver();

// the class file
 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("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);
   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);
    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
     {
      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;
   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()
  {
   fileHandle = CreateFile("\\\\.\\" + driverName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0,
IntPtr.Zero);
   if(handle == INVALID_HANDLE_VALUE)
   {
    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);
  }
 }



Relevant Pages

  • Re: Is C# support load device driver?
    ... I can see my driver is loaded. ... > string driverName; ... > internal static extern IntPtr OpenSCManager(string machineName, ... > uint dwDesiredAccess, uint serviceType, uint startType, uint ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: P/Invoking FormatMessage
    ... public static extern int FormatMessage(int dwFlags, IntPtr lpSource, ... int dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, ... static extern uint FormatMessage(uint dwFlags, IntPtr lpSource, ... public static string GetErrorMessage2 ...
    (microsoft.public.dotnet.framework.compactframework)
  • Re: Issue with pinvoking DeviceIoControl: switching USB function driver at run time
    ... Looks like the string needed to exactly match the WinCE data type _TCHAR ... Marshal.StringToBSTRto get me a IntPtr after allocating a COM-style ... UInt32 dwDesiredAccess, ... uint dwIoControlCode, ...
    (microsoft.public.pocketpc.developer)
  • Re: ask about CeRapiInvoke in C#
    ... which is invalid and CeRapiInitEx failed when calling. ... Also you'll find it easier to pass pcbOutput as out uint ... (rather than IntPtr) ... public static extern Int32 CeRapiInvoke(string pDllPath, ...
    (microsoft.public.pocketpc.developer)
  • Re: Listening for event call from device driver using WaitForMultipleObjects
    ... I use overlapped I/O from C# to the PCAUSA Rawether NDIS protocol driver. ... public static IntPtr OpenGrantedPacketEvent() ... i immediately thought that it was the string used for the event name .. ... although ive tried every different possible combination of declaring ...
    (microsoft.public.development.device.drivers)