Introduction
When you develop device drivers you always need to make two projects: first, the device driver and second the application to load and test it. This wrapper class, TDriver
, can help you in the second one. Furthermore I developed an application example that you can use to load any driver you indicate.
Background
Windows allows loading drivers at runtime using the Service Control Manager. Yes, the Service Control Manager in Windows not only can be used to load and manage services. You can use it with device drivers as you use it to load/unload/start/stop windows services.
If you want to send/receive data to the device driver loaded, to allow this, you have to get a handle to the driver. For this purpose you can use the function createFile
, and pass the driver name as the file name. You can see Windows is so abstract in this aspect.
Using the code
Using the TDriver
Class is so easy. Here is the class definition and the explanation follows:
class TDriver
{
public:
TDriver(void);
~TDriver(void);
DWORD InitDriver(LPCTSTR name, LPCTSTR path, LPCTSTR dosName=NULL);
DWORD InitDriver(LPCTSTR path);
DWORD LoadDriver(BOOL start = TRUE);
DWORD LoadDriver(LPCTSTR name, LPCTSTR path,
LPCTSTR dosName=NULL, BOOL start=TRUE);
DWORD LoadDriver(LPCTSTR path, BOOL start=TRUE);
DWORD UnloadDriver(BOOL forceClearData = FALSE);
DWORD StartDriver(void);
DWORD StopDriver(void);
void SetRemovable(BOOL value);
BOOL IsInitialized();
BOOL IsStarted();
BOOL IsLoaded();
HANDLE GetDriverHandle(void);
DWORD WriteIo(DWORD code, PVOID buffer, DWORD count);
DWORD ReadIo(DWORD code, PVOID buffer, DWORD count);
DWORD RawIo(DWORD code, PVOID inBuffer,
DWORD inCount, PVOID outBuffer, DWORD outCount);
private:
HANDLE driverHandle;
LPTSTR driverName;
LPTSTR driverPath;
LPTSTR driverDosName;
BOOL initialized;
BOOL started;
BOOL loaded;
BOOL removable;
DWORD OpenDevice(void);
};
The methods you can use in this class are:
InitDriver(...)
This function is used to initialize the parameters of the driver such as: driver name, driver path and driver dos name. If you only know the driver path, the funtion tries to get the rest of the parameters.
LoadDriver(..)
You can use this function after you call InitDriver
, when you use only one parameter. If start is FALSE
, we need to call StartDriver
function after, to start it. The other two functions, first initialize the driver and then load it as the first function.
UnloadDriver(BOOL forceClearData = FALSE)
This function stops the driver and deregister it in Windows Service Manager. If a problem occurred (while stopping or removing the driver), the class data associated with it(driver name, driver path...) will not be free unless you pass the TRUE
value in forceClearData
.
StartDriver()
You can use this function to start the driver "service".
StopDriver()
Use this function to stop the driver "service"
SetRemovable(BOOL value)
If you set the parameter removable
to FALSE
, in the unload process, the class will not deregister the driver in Windows Service Manager. This parameter is set automatically to FALSE
if the driver was loaded by another application.
IsInitialized();
BOOL IsLoaded();
BOOL IsStarted()
The above are functions to ask the driver about its status.
GetDriverHandle()
You must use this function if you can access to the driver handle directly.
WriteIo(DWORD code, PVOID buffer, DWORD count)
Function to send data to the driver. You must indicate the IOCTL code.
ReadIo(DWORD code, PVOID buffer, DWORD count)
Function to receive data from the driver. You must indicate the IOCTL code. The data will be received in buffer with a maximum length of count.
RawIo(DWORD code, PVOID inBuffer,
DWORD inCount, PVOID outBuffer, DWORD outCount)
You decide what to do, read, write or both.
They are all functions exported by the class to applications. However to make a simple application that manage drivers we need use only two functions. For example, I developed a program to show the functionality of the TDriver
class, that will load/unload any driver you introduce (see screenshot article). The code for this purpose is the next:
if(driver.LoadDriver(m_driverPath, true) == DRV_SUCCESS)
{
}
if(driver.UnloadDriver() == DRV_SUCCESS)
{
}
As you can see that with two lines you can load and unload a driver, making life easy for all :P.
Conclusion
And... That's all. I developed this class because I had to make one application (or modify other) to test each driver I did. So I decided to make the program to load a Driver. And I thought... why don't do a class for this purpose and so I can use it in my other programs? And this is the result of the question. All I want to say, I hope this code can help you.