"Steve" <St***@discussi ons.microsoft.c om> wrote in message
news:82******** *************** ***********@mic rosoft.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(dri verName,
@"c:\\folder\\m ydriver.sys");
if (driver.LoadDev iceDriver()){
IntPtr handle = driver.OpenDevi ce();
// use device using ....DeviceIoCon trol(handle,... .) see class code for
signature
}
//unload when done
driver.UnloadDe viceDriver();
// the class file
public sealed class Win32Driver : IDisposable
{
string driverName;
string execPath;
IntPtr fileHandle;
public Win32Driver(str ing 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(fil eHandle);
}
}
public void Dispose()
{
CloseStuff();
GC.SuppressFina lize(this);
}
private readonly static IntPtr INVALID_HANDLE_ VALUE = new IntPtr(-1);
private const int STANDARD_RIGHTS _REQUIRED = 0x000F0000;
private const int SC_MANAGER_CONN ECT = 0x0001;
private const int SC_MANAGER_CREA TE_SERVICE = 0x0002;
private const int SC_MANAGER_ENUM ERATE_SERVICE = 0x0004;
private const int SC_MANAGER_LOCK = 0x0008;
private const int SC_MANAGER_QUER Y_LOCK_STATUS = 0x0010;
private const int SC_MANAGER_MODI FY_BOOT_CONFIG =0x0020;
private const int SC_MANAGER_ALL_ ACCESS = STANDARD_RIGHTS _REQUIRED |
SC_MANAGER_CONN ECT |
SC_MANAGER_CREA TE_SERVICE |
SC_MANAGER_ENUM ERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUER Y_LOCK_STATUS |
SC_MANAGER_MODI FY_BOOT_CONFIG;
private const int SERVICE_QUERY_C ONFIG = 0x0001;
private const int SERVICE_CHANGE_ CONFIG = 0x0002;
private const int SERVICE_QUERY_S TATUS = 0x0004;
private const int SERVICE_ENUMERA TE_DEPENDENTS = 0x0008;
private const int SERVICE_START = 0x0010;
private const int SERVICE_STOP = 0x0020;
private const int SERVICE_PAUSE_C ONTINUE = 0x0040;
private const int SERVICE_INTERRO GATE = 0x0080;
private const int SERVICE_USER_DE FINED_CONTROL = 0x0100;
private const int SERVICE_ALL_ACC ESS = STANDARD_RIGHTS _REQUIRED
|
SERVICE_QUERY_C ONFIG |
SERVICE_CHANGE_ CONFIG |
SERVICE_QUERY_S TATUS |
SERVICE_ENUMERA TE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_C ONTINUE |
SERVICE_INTERRO GATE |
SERVICE_USER_DE FINED_CONTROL;
private const int SERVICE_DEMAND_ START = 0x00000003;
private const int SERVICE_KERNEL_ DRIVER = 0x00000001;
private const int SERVICE_ERROR_N ORMAL = 0x00000001;
private const uint GENERIC_READ = 0x80000000;
private const uint FILE_SHARE_READ = 1;
private const uint FILE_SHARE_WRIT E = 2;
private const uint OPEN_EXISTING = 3;
private const uint IOCTL_SHOCKMGR_ READ_ACCELEROME TER_DATA = 0x733fc;
private const int FACILITY_WIN32 = unchecked((int) 0x80070000);
private IntPtr handle = INVALID_HANDLE_ VALUE;
[DllImport("adva pi32", SetLastError = true)]
internal static extern IntPtr OpenSCManager(s tring machineName, string
databaseName, uint dwDesiredAccess );
[DllImport("adva pi32", SetLastError = true)]
internal static extern IntPtr CreateService(I ntPtr hSCManager, string
serviceName, string displayName,
uint dwDesiredAccess , uint serviceType, uint startType, uint
errorControl,
string lpBinaryPathNam e, string lpLoadOrderGrou p, string lpdwTagId,
string lpDependencies,
string lpServiceStartN ame, string lpPassword);
[DllImport("adva pi32")]
internal static extern bool CloseServiceHan dle(IntPtr handle);
[DllImport("kern el32", SetLastError = true)]
internal static extern IntPtr CreateFile(stri ng lpFileName, uint
dwDesiredAccess , uint dwShareMode, IntPtr lpSecurityAttri butes, uint
dwCreationDispo sition, uint dwFlagsAndAttri butes, IntPtr hTemplateFile);
[DllImport("kern el32")]
internal static extern void CloseHandle(Int Ptr handle);
[DllImport("kern el32", 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 LoadDeviceDrive r()
{
IntPtr scHandle = OpenSCManager(n ull, null, SC_MANAGER_ALL_ ACCESS);
if (scHandle != INVALID_HANDLE_ VALUE)
{
IntPtr hService = CreateService(s cHandle, this.driverName ,
this.driverName , SERVICE_ALL_ACC ESS
, SERVICE_KERNEL_ DRIVER, SERVICE_DEMAND_ START,SERVICE_E RROR_NORMAL
,execPath, null, null, null, null, null);
if (hService != IntPtr.Zero)
{
CloseServiceHan dle(hService); // close both handles
CloseServiceHan dle(scHandle);
// Start the driver using System.Manageme nt (WMI)
if (ExecuteSCMOper ationOnDriver(t his.driverName, "StartServi ce") == 0)
return true;
}
else
if (Marshal.GetLas tWin32Error()== 1073) // Driver/Service already in DB
{
CloseServiceHan dle(scHandle);
// Start the driver using System.Manageme nt (WMI)
if (ExecuteSCMOper ationOnDriver(t his.driverName, "StartServi ce") == 0)
return true;
}
Marshal.ThrowEx ceptionForHR(HR ESULT_FROM_WIN3 2(Marshal.GetLa stWin32Error()) );
}
return false;
}
internal bool UnloadDeviceDri ver()
{
int ret = 0;
if (fileHandle != IntPtr.Zero && fileHandle != INVALID_HANDLE_ VALUE)
{
CloseHandle(fil eHandle);
}
if ((ret = ExecuteSCMOpera tionOnDriver(dr iverName, "StopServic e")) == 0)
{
ret = ExecuteSCMOpera tionOnDriver(dr iverName, "Delete");
}
if (ret != 0)
{
return false;
}
return true;
}
private static int ExecuteSCMOpera tionOnDriver(st ring driverName, string
operation)
{
ManagementPath path = new ManagementPath( );
path.Server = ".";
path.NamespaceP ath = @"root\CIMV2 ";
path.RelativePa th = @"Win32_BaseSer vice.Name='" + driverName +"'";
using(Managemen tObject o = new ManagementObjec t(path))
{
ManagementBaseO bject outParams = o.InvokeMethod( operation,
null, null);
return Convert.ToInt32 (outParams.Prop erties["ReturnValu e"].Value);
}
}
internal IntPtr OpenDevice()
{
fileHandle = CreateFile("\\\ \.\\" + driverName, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRIT E, IntPtr.Zero, OPEN_EXISTING, 0,
IntPtr.Zero);
if(handle == INVALID_HANDLE_ VALUE)
{
Marshal.ThrowEx ceptionForHR(HR ESULT_FROM_WIN3 2(Marshal.GetLa stWin32Error()) );
}
return fileHandle;
}
private static int HRESULT_FROM_WI N32(int x)
{
return x <= 0 ? x : ((x & 0x0000FFFF) | FACILITY_WIN32) ;
}
}