Êíèãà: Writing Windows WDM Device Drivers
Conclusion
Conclusion
This chapter first looked at how to install WDM device drivers using INF files. It then described the installation process for NT style kernel mode drivers. The device driver management tools were discussed. The Servicer program can start and stop NT style drivers.
Our tour of the core device driver functionality continues in the next chapter by looking at how to interact with the Windows Management Instrumentation system.
Listing 11.2 NTMnstall.Cpp
// install.Inf – NT driver install program
// Copyright © 1998 Chris Cant, PHD Computer Consultants Ltd
// This is not a complete program
void InstallDriver(CString DriverName, CString DriverFromPath) {
//////////////////////////////////////////////////////////////////
// Get System32 directory
_TCHAR System32Directory[_MAX_PATH];
if (0==GetSystemDirectory(System32Directory,_MAX_PATH)) {
AfxMessageBox("Could not find Windows system directory");
return;
}
///////////////////////////////////////////////////////////////////
// Copy driver.sys file across
CString DriverFullPath = System32Directory+"Drivers"+DriverName+".sys";
if (0==CopyFile( DriverFromPath, DriverFullPath, FALSE)) // Overwrite OK
{
CString Msg;
Msg.Format("Could not copy %s to %s", DriverFullPath, Drivers);
AfxMessageBox(Msg);
return;
}
///////////////////////////////////////////////////////////////////
// Create driver (or stop existing driver)
if (!CreateDriver(DriverName, DriverFullPath)) return;
///////////////////////////////////////////////////////////////////
// Create/Open driver registry key and set its values
//Overwrite registry values written in driver creation
HKEY mru;
DWORD disposition;
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEMCurrentControlSetServices"+DriverName,
0, "", 0, KEY_ALL_ACCESS, NULL, &mru, &disposition) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry key");
return;
}
// Delete ImagePath
RegDeleteValue(mru,"ImagePath");
// Delete DisplayName
RegDeleteValue(mru, "DisplayName");
// ErrorControl
DWORD dwRegValue = SERVICE_ERROR_NORMAL;
if (RegSetValueEx(mru, "ErrorControl", 0, REG_DWORD, (CONST BYTE*)&dwRegValue, sizeof(DWORD)) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value ErrorControl");
return;
}
// Start
dwRegValue = SERVICE_AUTO_START;
if (RegSetValueEx(mru, "Start" , 0, REG_DWORD, (CONST BYTE*)&dwRegValue, sizeof(DWORD)) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value Start");
return;
}
// Type
dwRegValue = SERVICE_KERNEL_DRIVER;
if (RegSetValueEx(mru, "Type", 0, REG_DWORD, (CONST BYTE*)&dwRegValue, sizeof(DWORD)) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value Type");
return;
}
// DependOnGroup
_TCHAR DependOnGroup[] = "Parallel arbitrator";
if (RegSetValueEx(mru, "DependOnGroup", 0, REG_MULTI_SZ,
(CONST BYTE*)&DependOnGroup, strlen(DependOnGroup)+2) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value DependOnGroup");
return;
}
// DependOnService
_TCHAR DependOnService[] = "parport";
if (RegSetValueEx(mru, "DependOnService", 0, REG_MULTI_SZ,
(CONST BYTE*) &DependOnService, strlen(DependOnService)+2) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value DependOnService");
return;
}
RegCloseKey(mru);
//////////////////////////////////////////////////////////////////
// Create/Open driverParameters registry key and set its values
if (RegCreateKeyEx(HKEY_LOCAL_MACHIME, "SYSTEMCurrentControlSetServices'+DriverName+'Parameters',
0, "", 0, KEY_ALL_ACCESS, NULL, &mru, &disposition) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driverParameters registry key");
return;
}
// EventLogLevel
dwRegValue = 1;
if (RegSetValueEx(mru, "EventLogLevel", 0, REG_DWORD, (CONST BYTE*)&dwRegValue, sizeof(DWORD)) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driverParameters registry value EventLogLevel");
return;
}
// Default or No Name
CString DefaultName = DriverName;
int DeviceNameLen = DefaultName.GetLength()+1;
LPTSTR lpDefaultName = DefaultName.GetBuffer(DeviceNameLen);
if (RegSetValueEx(mru, "", 0, REG_SZ, (CONST BYTE*)lpDefaultName, DeviceNameLen) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driverParameters default registry value");
return;
}
DefaultName.ReleaseBuffer(0);
RegCloseKey(mru);
//////////////////////////////////////////////////////////////////
// Open EventLogSystem registry key and set its values
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEMCurrentControlSetServicesEventLogSystem",
0, "", 0, KEY_ALL_ACCESS, NULL, &mru, &disposition) != ERROR SUCCESS) {
AfxMessageBox("Could not open EventLogSystem registry key");
return;
}
// get Sources size
DWORD DataSize = 0;
DWORD Type;
if (RegQueryValueEx(mru, "Sources", NULL, &Type, NULL, &DataSize) ! = ERROR_SUCCESS) {
AfxMessageBox("Could not read size of EventLogSystem registry value Sources");
return;
}
// read Sources
int DriverNameLen = strlen(DriverName);
DataSize += DriverNameLen+1;
LPTSTR Sources = new _TCHAR[DataSize];
if (RegQueryValueEx(mru, "Sources", NULL, &Type, (LPBYTE)Sources, &DataSize) != ERROR_SUCCESS) {
AfxMessageBox("Could not read EventLogSystem registry value Sources");
return;
}
// If driver not there, add and write
if (FindInMultiSz(Sources, DataSize, DriverName )==-1) {
strcpy(Sources+DataSize-1,DriverName);
DataSize += DriverNameLen;
*(Sources+DataSize) = '';
if (RegSetValueEx(mru, "Sources", 0, REG_MULTI_SZ, (CONST BYTE*)Sources.DataSize) != ERROR_SUCCESS) {
AfxMessageBox("Could not create driver registry value Sources");
return;
}
}
///////////////////////////////////////////////////////////////////
// Create/Open EventLogSystemdriver registry key and set its values
if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEMCurrentControlSetServicesEventLogSystem"+DriverName,
0, "", 0, KEY_ALL_ACCESS, NULL, &mru, &disposition) != ERROR_SUCCESS) {
AfxMessageBox("Could not create EventLogSystemdriver registry key");
return;
}
// TypesSupported dwRegValue = 7;
if (RegSetValueEx(mru,"TypesSupported", 0, REG_DWORD, (CONST BYTE*)&dwRegValue, sizeof(DWORD)) != ERROR_SUCCESS) {
AfxMessageBox("Could not create EventLogSystemdriver registry value TypesSupported");
return;
}
// EventMessageFile
LPTSTR EventMessageFile = "%SystemRoot%System32IoLogMsg.dll;%SystemRoot%System32Drivers"+DriverName+".sys";
if (RegSetValueEx(mru, "EventMessageFile", 0, REG_EXPAND_SZ,
(CONST BYTE*)EventMessageFile, strlen(EventMessageFile)+1) != ERROR_SUCCESS) {
AfxMessageBox("Could not create EventLogSystemdriver registry value EventMessageFile");
return;
}
RegCloseKey(mru);
////////////////////////////////////////////////////////////////////
// Start driver service
if (!StartDriver(DriverName)) return;
}
////////////////////////////////////////////////////////////////
BOOL CreateDriver( CString DriverName, CString FullDriver) {
///////////////////////////////////////////////////////////////
// Open service control manager
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager=NULL) {
AfxMessageBox("Could not open Service Control Manager");
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// If driver is running, stop it
SC_HANDLE hDriver = OpenService(hSCManager, DriverName, SERVICE_ALL_ACCESS);
if (hDriver!=NULL) {
SERVICE_STATUS ss;
if (ControlService(hDriver, SERVICE_CONTROL_INTERROGATE, &ss)) {
if (ss.dwCurrentState != SERVICE_STOPPED) {
if (!ControlService(hDriver, SERVICE_CONTROL_STOP, &ss)) {
AfxMessageBox("Could not stop driver");
CloseServiceHandle(hSCManager);
CloseServiceHandle(hDriver);
return FALSE;
}
// Give it 10 seconds to stop
BOOL Stopped = FALSE;
for (int seconds=0; seconds<10; seconds++) {
Sleep(1000);
if (ControlService(hDriver, SERVICE_CONTROL_INTERROGATE, &ss) && ss.dwCurrentState==SERVICE_STOPPED) {
Stopped = TRUE;
break;
}
}
if (!Stopped) {
AfxMessageBox("Could not stop driver");
CloseServiceHandle(hSCManager);
CloseServiceHandle(hDriver);
return FALSE;
}
}
CloseServiceHandle(hDriver);
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// Create driver service
hDriver = CreateService(hSCManager, DriverName.DriverName, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL, Drivers, NULL, NULL,"parport", NULL, NULL);
if (hDriver==NULL) {
AfxMessageBox("Could not install driver with Service Control Manager");
CloseServiceHandle(hSCManager);
return FALSE;
}
//////////////////////////////////////////////////////////////////////
CloseServiceHandle(hSCManager);
return TRUE;
}
///////////////////////////////////////////////////////////////////////
BOOL StartDriver(CString DriverName) {
//////////////////////////////////////////////////////////////////////
// Open service control manager
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager==NULL) {
AfxMessageBox("Could not open Service Control Manager");
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// Driver isn't there
SC_HANDLE hDriver = OpenService(hSCManager,DriverName,SERVICE_ALL_ACCESS);
if (hDriver==NULL) {
AfxMessageBox("Could not open driver service");
CloseServiceHandle(hSCManager);
return FALSE;
}
SERVICE_STATUS ss;
if (!ControlService(hDriver, SERVICE_CONTROL_INTERROGATE, &ss) ss.dwCurrentState!=SERVICE_STOPPED) {
AfxMessageBox("Could not interrogate driver service");
CloseServiceHandle(hSCManager);
CloseServiceHandle(hDriver);
return FALSE;
}
if (!StartService(hDriver, 0, NULL)) {
AfxMessageBox("Could not start driver");
CloseServiceHandle(hSCManager);
CloseServiceHandle(hDriver);
return FALSE;
}
// Give it 10 seconds to start
BOOL Started = FALSE;
for (int seconds=0; seconds<10; seconds++) {
Sleep(1000);
if (ControlService(hDriver, SERVICE_CONTROL_INTERROGATE, &ss) & ss.dwCurrentState==SERVICE_RUNNING) {
Started = TRUE;
break;
}
}
if (!Started) {
AfxMessageBox("Could not start driver");
CloseServiceHandle(hSCManager);
CloseServiceHandle(hDriver);
return FALSE;
}
CloseServiceHandle(hDriver);
CloseServiceHandle(hSCManager);
return TRUE;
}
///////////////////////////////////////////////////////////////////////
//Try to find Match in MultiSz, including Match's terminating
int FindInMultiSz(LPTSTR MultiSz, int MultiSzLen, LPTSTR Match) {
int MatchLen = strlen(Match);
_TCHAR FirstChar = *Match;
for (int i=0; i<MultiSzLen-MatchLen; i++) {
if (*MultiSz++ == FirstChar) {
BOOL Found = TRUE;
LPTSTR Try = MultiSz;
for (int j=1; j<=MatchLen; j++)
if (*Try++ != Match[j]) {
Found = FALSE;
break;
}
if (Found) return i;
}
}
return –1;
}
///////////////////////////////////////////////////////////////////////
Note: A revised version of NTNinstall.cpp is available on the book's web site, www.phdcc.com/wdmbook. This updated version fixes a problem to make it work in W2000.