驱动与应用程序的通信是非常有必要的 , 内核中执行代码后需要将其动态显示给应用层,但驱动程序与应用层毕竟不在一个地址空间内,为了实现内核与应用层数据交互则必须有通信的方法,微软为我们提供了三种通信方式 , 如下先来介绍通过ReadFile系列函数实现的通信模式 。
长话短说,不说没用的概念,首先系统中支持的通信模式可以总结为三种 。
- 缓冲区方式读写(DO_BUFFERED_IO)
- 直接方式读写(DO_DIRECT_IO)
- 其他方式读写
首先需要实现初始化各类派遣函数这么一个案例,如下代码则是通用的一种初始化派遣函数的基本框架,分别处理了IRP_MJ_CREATE创建派遣,以及IRP_MJ_CLOSE关闭的派遣,此外函数DriverDefaultHandle的作用时初始化其他派遣用的,也就是将除去CREATE/CLOSE这两个派遣之外,其他的全部赋值成初始值的意思,当然不增加此段代码也是无妨,并不影响代码的实际执行 。
#include <ntifs.h>// 卸载驱动执行VOID UnDriver(PDRIVER_OBJECT pDriver){ PDEVICE_OBJECT pDev; // 用来取得要删除设备对象 UNICODE_STRING SymLinkName; // 局部变量symLinkName pDev = pDriver->DeviceObject; IoDeleteDevice(pDev); // 调用IoDeleteDevice用于删除设备 RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver"); // 初始化字符串将symLinkName定义成需要删除的符号链接名称 IoDeleteSymbolicLink(&SymLinkName); // 调用IoDeleteSymbolicLink删除符号链接 DbgPrint("驱动卸载完毕...");}// 创建设备连接// LyShark.comNTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver){ NTSTATUS Status; PDEVICE_OBJECT pDevObj; UNICODE_STRING DriverName; UNICODE_STRING SymLinkName; // 创建设备名称字符串 RtlInitUnicodeString(&DriverName, L"\\Device\\LySharkDriver"); Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj); // 指定通信方式为缓冲区 pDevObj->Flags |= DO_BUFFERED_IO; // 创建符号链接 RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver"); Status = IoCreateSymbolicLink(&SymLinkName, &DriverName); return STATUS_SUCCESS;}// 创建回调函数NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp){ pIrp->IoStatus.Status = STATUS_SUCCESS; // 返回成功 DbgPrint("派遣函数 IRP_MJ_CREATE 执行 \n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // 指示完成此IRP return STATUS_SUCCESS; // 返回成功}// 关闭回调函数NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp){ pIrp->IoStatus.Status = STATUS_SUCCESS; // 返回成功 DbgPrint("派遣函数 IRP_MJ_CLOSE 执行 \n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // 指示完成此IRP return STATUS_SUCCESS; // 返回成功}// 默认派遣函数NTSTATUS DriverDefaultHandle(PDEVICE_OBJECT pDevObj, PIRP pIrp){ NTSTATUS status = STATUS_SUCCESS; pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status;}// 入口函数// By: LySharkNTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath){ DbgPrint("hello lyshark \n"); // 调用创建设备 CreateDriverObject(pDriver); pDriver->DriverUnload = UnDriver; // 卸载函数 pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; // 创建派遣函数 pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; // 关闭派遣函数 // 初始化其他派遣 for (ULONG i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {DbgPrint("初始化派遣: %d \n", i);pDriver->MajorFunction[i] = DriverDefaultHandle; } DbgPrint("驱动加载完成..."); return STATUS_SUCCESS;}
推荐阅读
- 三十六 Java开发学习----SpringBoot三种配置文件解析
- aardio + Python 可视化快速开发桌面程序,一键生成独立 EXE
- Windows esp-idf 安装
- aardio + PHP 可视化快速开发独立 EXE 桌面程序
- 制造企业有可能自行开发ERP系统吗?
- aardio + VBScript 混合开发
- 通过Thread Pool Executor类解析线程池执行任务的核心流程
- 14 基于SqlSugar的开发框架循序渐进介绍-- 基于Vue3+TypeScript的全局对象的注入和使用
- 【Python+C#】手把手搭建基于Hugging Face模型的离线翻译系统,并通过C#代码进行访问
- 基于Qt Designer和PyQt5的桌面软件开发--环境搭建和入门例子