开发环境为VS2019,新建项目选择Kernel Model Driver,Empty(KMDF).
为项目添加一个DriverEntry.c文件.注意!是.c文件
项目属性:
1.C\C++:警告等级设置为3级,警告视为错误设置为否,SDL检查设置为否;
2.Driver Setting:Target OS Version设置为要开发的Windows系统平台的版本
(这里Windows 7),Target Platform设置为Desktop;
3.Stamplnf:Enable Architectrue设置为否;
4.Inf2Cat:Run Inf2Cat暂时不需要,设置为否;
5.删除Driver Files下面的inf文件
定义驱动的入口函数和卸载函数:
#include
//声明卸载函数(卸载前要做什么)
void DriverUnload(PDRIVER_OBJECT driver);
//入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, UNICODE_STRING path)
{
driver->DriverUnload = DriverUnload;
return STATUS_SUCCESS;
}
void DriverUnload(PDRIVER_OBJECT driver)
{
KdPrint(("驱动已卸载"));
}
1.调用IoCreateDevice()创建IO设备
2.通过IoCreateSymbolicLink创建符号链接并绑定IO设备
注意:UNICODE_STRING类型的变量声明后需要用RtlInitUnicodeString()初始化
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING DeviceName;
PDEVICE_OBJECT MyDevice=NULL;
//初始化DeviceName
RtlInitUnicodeString(&DeviceName, L"\\Device\\MyDevice");
status = IoCreateDevice(
driver,
sizeof(driver->DriverExtension),
&DeviceName,
FILE_DEVICE_UNKNOWN,//设备类型
FILE_DEVICE_SECURE_OPEN,//设备特性
FALSE,//这个设备是否是独占的
&MyDevice
);
if (status == STATUS_SUCCESS)
{
KdPrint(("设备已创建:%xZ",DeviceName));
UNICODE_STRING SymbolName;
RtlInitUnicodeString(&SymbolName, L"\\??\\MySymbol");
//创建符号链接
status = IoCreateSymbolicLink(&SymbolName, &DeviceName);
if (status == STATUS_SUCCESS)
{
KdPrint(("创建符号链接失败!"));
}
else
{
KdPrint(("符号链接已创建: %xZ",SymbolName));
}
}
else
{
KdPrint(("设备创建失败!"));
IoDeleteDevice(MyDevice);
}
}
关于派遣函数的解释
1.用IoGetCurrentIrpStackLocation来获取应用层传来的消息
2.使用switch语句调用对应的消息处理函数
3.用IoCompleteRequest返回数据给应用层
4.绑定消息处理函数
NTSTATUS DriverIrpCtrl(PDEVICE_OBJECT devoce, PIRP pirp)
{
PIO_STACK_LOCATION IrpStack=NULL;
ULONG CtrlCode = 0;//控制码
ULONG InputBuffSize=0;//接收输入的缓冲区长度
//获取应用层传来的消息
IrpStack = IoGetCurrentIrpStackLocation(pirp);
switch (IrpStack->MajorFunction)
{
//设备读写消息
case IRP_MJ_DEVICE_CONTROL:
{
KdPrint(("设备读写消息"));
//处理设备读写的函数
DoMessage_RW(pirp);
break;
}
//设备打开消息
case IRP_MJ_CREATE:
{
KdPrint(("设备打开消息"));
break;
}
//设备关闭消息
case IRP_MJ_CLOSE:
{
KdPrint(("设备关闭消息"));
break;
}
}
pirp->IoStatus.Status = STATUS_SUCCESS;
//返回数据给应用层
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
绑定消息处理函数,需要在DriverEntry中调用
void BindingDriverIrpCtrl(PDRIVER_OBJECT driver)
{
driver->MajorFunction[IRP_MJ_CREATE] = DriverIrpCtrl;
driver->MajorFunction[IRP_MJ_CLOSE] = DriverIrpCtrl;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIrpCtrl;
}
1.应用层:
a.新建一个MFC工程(其他的也可以)
b.用CreateFileW获取驱动IO设备的句柄
c.用DeviceIoControl向驱动发送数据
d.不再需要读写操作时,用CloseHandle关闭设备句柄
2.驱动层:
//获取传入的数据
int *pInBuff = pirp->AssociatedIrp.SystemBuffer;
KdPrint(("传入参数: %d", pInBuff));
//处理传入的数据
*pInBuff = *pInBuff + 1234567;
//返回数据(pInBuff也可以是其他)
pirp->IoStatus.Information = sizeof(pInBuff);//返回数据给DeviceIoControl倒数第二个参数(返回字节数)
打开设备:
bool OpenDriverDevice(LPCWSTR SymbolName)
{
DeviceHandle = CreateFileW(SymbolName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (DeviceHandle == NULL)
{
return false;
}
else
{
return true;
}
}
输入数据:
int InputDevice(void* InBuff, DWORD InBuffSize,void* OutBuff, DWORD OutBuffSize,HANDLE DeviceHandle, DWORD CtrlCode)
{
DWORD dwRetSize;
bool bRet = DeviceIoControl(DeviceHandle,
CtrlCode,//控制码
InBuff,//输入参数指针
InBuffSize,//输入参数大小
OutBuff,//返回缓冲器指针
OutBuffSize,//返回缓冲区大小
&dwRetSize,//返回缓冲区字节数
NULL
);
if (bRet)
return dwRetSize;
else
return -1;
}
关闭设备:
void CloseDriverDevice(HANDLE DeviceHandle)
{
CloseHandle(DeviceHandle);
}
1.加载驱动:
a.用GetFullPathNameA获取驱动的完整路径
b.用OpenSCManager打开服务控制管理器
c.用CreateServiceA创建服务
d.如果服务创建已存在,直接用OpenServiceA打开服务,否则用StartServiceA开启服务
2.卸载驱动:
a.用OpenSCManager打开服务控制管理器
b.用OpenServiceA打开服务
c.用ControlService停止驱动服务
加载驱动:
bool LoadDriver(const char* DriverName, const char* DriverFileName)
{
char DriverImagePath[256] = { 0 };//用于保存驱动文件的全路径名
//获取驱动文件全路径名
GetFullPathNameA(DriverFileName, 256, DriverImagePath, NULL);
bool bRet = false;
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDX = NULL;//NT驱动服务的服务句柄
//打开SCM管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hServiceMgr != NULL)
{
//创建驱动服务
hServiceDDX = CreateServiceA(hServiceMgr,
DriverName,//驱动程序注册表中的名字
DriverName,//注册表中驱动程序的 DisPlayName 的值
SERVICE_START,//加载驱动的访问权限 SERVICE_START 或 SERVICE_ALL_ACCESS
SERVICE_KERNEL_DRIVER,//表示加载服务是驱动程序
SERVICE_DEMAND_START,//注册表驱动程序的 Start 值
SERVICE_ERROR_NORMAL,//注册表程序的 ErrorControl 值
DriverImagePath,
NULL, NULL, NULL, NULL, NULL
);
}
else
{
return false;
}
if (hServiceDDX==NULL)
{
DWORD errorCode = GetLastError();
if (errorCode == ERROR_SERVICE_EXISTS)
{
hServiceDDX = OpenServiceA(hServiceMgr, DriverName, SERVICE_ALL_ACCESS);
if (!hServiceDDX)
{
if (hServiceMgr)CloseServiceHandle(hServiceMgr);
return false;
}
}
else
{
CString str;
str.Format(L"错误代码:%d",errorCode);
MessageBox(NULL,str,L"",MB_OK);
return false;
}
}
bRet = StartService(hServiceDDX, NULL, NULL);
if (hServiceDDX)
{
CloseServiceHandle(hServiceDDX);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}
卸载驱动:
bool UnLoadDriver(const char* DriverName)
{
bool bRet = false;
SC_HANDLE hServiceMgr = NULL;//SCM管理器的句柄
SC_HANDLE hServiceDDX = NULL;//NT驱动程序的服务句柄
SERVICE_STATUS Svrsta;
//先关闭设备
if (DeviceHandle) CloseHandle(DeviceHandle);
//打开SCM管理器
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hServiceMgr == NULL)
{
bRet = FALSE;
goto BeforeLeave;
}
//打开驱动所有对应服务
hServiceDDX = OpenServiceA(hServiceMgr, DriverName, SERVICE_ALL_ACCESS);
if (hServiceDDX == NULL)
{
bRet = false;
goto BeforeLeave;
}
//停止驱动程序
ControlService(hServiceDDX, SERVICE_CONTROL_STOP, &Svrsta);
//动态卸载驱动程序
bRet = DeleteService(hServiceDDX);
BeforeLeave:
if (hServiceDDX)
{
CloseServiceHandle(hServiceDDX);
}
if (hServiceMgr)
{
CloseServiceHandle(hServiceMgr);
}
return bRet;
}