昨天写好一个驱动后,准备在RING3写GUI进行交互,可是又不想自己再花时间去实现DriverLoader,于是在硬盘里找啊找~就找到了一个方便的用来控制驱动的类。
这 个class来自《Windows程序设计》(第二版)的随书代码(作者王艳平),可以方便地加载驱动、卸载驱动、发送IO控制码,原始代码有些问题我已 经将其修正,在这里贴一下,有需要的同学可以直接拿去用,#include "Driver.h"即可(把函数的实现写在头文件里貌似并不可取,不过我不想再扣出一个.cpp弄成俩文件了…)另外项目使用的字符集必须是 UNICODE
// Driver.h
///////////////////////////////////////////////////
#ifndef __DRIVER_H__
#define __DRIVER_H__
#include <windows.h>
#include <Winsvc.h>
class CDriver
{
public:
// 构造函数和析构函数
// 构造函数,pszDriverPath为驱动所在目录,pszLinkName为符号连接名字
// 在类的构造函数中,将试图创建或打开服务,
CDriver(LPCTSTR pszDriverPath, LPCTSTR pszLinkName);
// 析构函数。在这里,将停止服务,
virtual ~CDriver();
// 属性
// 此驱动是否可用
virtual inline BOOL IsValid() {
return (m_hSCM != NULL && m_hService != NULL);
}
// 操作
// 开启服务。也就是说驱动的DriverEntry函数将被调用
virtual BOOL StartDriver();
// 结束服务。即驱动程序的DriverUnload例程将被调用
virtual BOOL StopDriver();
// 打开设备,即取得到此驱动的一个句柄
virtual BOOL OpenDevice();
// 向设备发送控制代码
virtual DWORD IoControl(DWORD nCode, PVOID pInBuffer, DWORD nInCount, PVOID pOutBuffer, DWORD nOutCount);
// 实现
protected:
wchar_t m_szLinkName[56]; // 符号连接名称
BOOL m_bStarted; // 指定服务是否启动
BOOL m_bCreateService; // 指定是否创建了服务
HANDLE m_hSCM; // SCM数据库句柄
HANDLE m_hService; // 服务句柄
HANDLE m_hDriver; // 设备句柄
};
CDriver::CDriver(LPCTSTR pszDriverPath, LPCTSTR pszLinkName)
{
wcsncpy(m_szLinkName, pszLinkName, 55);
m_bStarted = FALSE;
m_bCreateService = FALSE;
m_hSCM = NULL;
m_hService = NULL;
m_hDriver = INVALID_HANDLE_VALUE;
// 打开SCM管理器
m_hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (m_hSCM == NULL) {
//MessageBox(0, L"打开服务控制管理器失败\n", L"可能是因为您不拥有Administrator权限\n", 0);
return;
}
// 创建或打开服务
m_hService = ::CreateService((SC_HANDLE)m_hSCM, m_szLinkName, m_szLinkName, SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
pszDriverPath, NULL, 0, NULL, NULL, NULL);
if (m_hService == NULL) {
int nError = ::GetLastError();
if(nError == ERROR_SERVICE_EXISTS || nError == ERROR_SERVICE_MARKED_FOR_DELETE)
{
m_hService = ::OpenService((SC_HANDLE)m_hSCM, m_szLinkName, SERVICE_ALL_ACCESS);
}
} else {
m_bCreateService = TRUE;
}
}
CDriver::~CDriver()
{
if (m_hDriver != INVALID_HANDLE_VALUE)
::CloseHandle(m_hDriver);
StopDriver();
if (m_bCreateService)
::DeleteService((SC_HANDLE)m_hService);
if (m_hService != NULL)
::CloseServiceHandle((SC_HANDLE)m_hService);
if (m_hSCM != NULL)
::CloseServiceHandle((SC_HANDLE)m_hSCM);
}
BOOL CDriver::StartDriver()
{
if(m_bStarted)
return TRUE;
if(m_hService == NULL)
return FALSE;
if(!::StartService((SC_HANDLE)m_hService, 0, NULL)) {
int nError = ::GetLastError();
if (nError == ERROR_SERVICE_ALREADY_RUNNING)
m_bStarted = TRUE;
else
::DeleteService((SC_HANDLE)m_hService);
} else {
// 启动成功后,等待服务进入运行状态
int nTry = 0;
SERVICE_STATUS ss;
::QueryServiceStatus((SC_HANDLE)m_hService, &ss);
while (ss.dwCurrentState == SERVICE_START_PENDING && nTry++ < 80) {
::Sleep(50);
::QueryServiceStatus((SC_HANDLE)m_hService, &ss);
}
if (ss.dwCurrentState == SERVICE_RUNNING)
m_bStarted = TRUE;
}
return m_bStarted;
}
BOOL CDriver::StopDriver()
{
if (!m_bStarted)
return TRUE;
if (m_hService == NULL)
return FALSE;
SERVICE_STATUS ss;
if (!::ControlService((SC_HANDLE)m_hService, SERVICE_CONTROL_STOP, &ss))
{
if (::GetLastError() == ERROR_SERVICE_NOT_ACTIVE)
m_bStarted = FALSE;
} else {
// 等待服务完全停止运行
int nTry = 0;
while (ss.dwCurrentState == SERVICE_STOP_PENDING && nTry++ < 80) {
::Sleep(50);
::QueryServiceStatus((SC_HANDLE)m_hService, &ss);
}
if (ss.dwCurrentState == SERVICE_STOPPED)
m_bStarted = FALSE;
}
return !m_bStarted;
}
BOOL CDriver::OpenDevice()
{
if (m_hDriver != INVALID_HANDLE_VALUE)
return TRUE;
wchar_t sz[256] = {0};
wsprintf(sz, L"\\\\.\\%s", m_szLinkName);
// 打开到驱动程序所控制设备的句柄
m_hDriver = ::CreateFile(sz,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
return (m_hDriver != INVALID_HANDLE_VALUE);
}
DWORD CDriver::IoControl(DWORD nCode, PVOID pInBuffer,
DWORD nInCount, PVOID pOutBuffer, DWORD nOutCount)
{
if (m_hDriver == INVALID_HANDLE_VALUE)
return -1;
// 向驱动程序发送控制代码
DWORD nBytesReturn;
BOOL bRet = ::DeviceIoControl(m_hDriver, nCode,
pInBuffer, nInCount, pOutBuffer, nOutCount, &nBytesReturn, NULL);
printf("Error Code: %d %X", GetLastError(), GetLastError());
if (bRet)
return nBytesReturn;
else
return -1;
}
#endif // __DRIVER_H__
调用方法也很简单,贴一个我的示例:
if (pDrvCtl->IsValid() == TRUE) {
pDrvCtl->StartDriver();
pDrvCtl->OpenDevice();
USHORT buf = 77;
pDrvCtl->IoControl(0x1000, &buf, sizeof(USHORT), &buf, sizeof(USHORT));
}
pDrvCtl->StopDriver();
delete pDrvCtl;