驱动开发入门总结

1.简单的驱动框架

开发环境为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(("驱动已卸载"));
}

2.创建驱动设备与绑定符号链接

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);
	}
}

3.IRP派遣函数

关于派遣函数的解释
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;
}

4.应用层与驱动层通信

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);
}

5.驱动的加载与卸载

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;
}

驱动开发方面我是个刚刚入门的萌新,如果我写的有问题望多多指教,谢谢!

你可能感兴趣的:(Windows内核研究)