驱动开发:应用DeviceIoContro开发模板

article/2025/10/14 18:25:41

内核中执行代码后需要将结果动态显示给应用层的用户,DeviceIoControl 是直接发送控制代码到指定的设备驱动程序,使相应的移动设备以执行相应的操作的函数,如下代码是一个经典的驱动开发模板框架,在开发经典驱动时会用到的一个通用案例。

一般要实现驱动程与应用层通信有多种方法,最简单的一种方式则是通过IO派遣实现,应用层通过DeviceIoControl函数与内核建立联系,DeviceIoControl 是 Windows 操作系统提供的一个函数,用于与设备驱动程序进行通信。它允许应用程序发送控制代码(IOCTL)给设备驱动程序,并传递相应的输入和输出缓冲区。

该函数的原型如下:

BOOL DeviceIoControl(HANDLE       hDevice,DWORD        dwIoControlCode,LPVOID       lpInBuffer,DWORD        nInBufferSize,LPVOID       lpOutBuffer,DWORD        nOutBufferSize,LPDWORD      lpBytesReturned,LPOVERLAPPED lpOverlapped
);

参数说明:

  • hDevice:设备句柄,用于标识要进行操作的设备。
  • dwIoControlCode:控制代码,用于指定要执行的设备操作。
  • lpInBuffer:输入缓冲区,包含要传递给设备的输入数据。
  • nInBufferSize:输入缓冲区大小,以字节为单位。
  • lpOutBuffer:输出缓冲区,用于接收设备返回的输出数据。
  • nOutBufferSize:输出缓冲区大小,以字节为单位。
  • lpBytesReturned:用于接收实际传输的字节数。
  • lpOverlapped:用于异步操作的指针。

通过调用 DeviceIoControl 函数,应用程序可以向设备发送各种类型的请求,例如读取设备状态、执行设备操作、获取设备信息等。具体的操作和使用方式取决于所操作的设备驱动程序提供的功能。

驱动程序开发通用模板代码如下:

#include <ntifs.h>
#include <windef.h>// 控制器
#define IOCTL_IO_LyShark CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)// 卸载驱动执行
VOID UnDriver(PDRIVER_OBJECT pDriver)
{PDEVICE_OBJECT pDev;                                        // 用来取得要删除设备对象UNICODE_STRING SymLinkName;                                 // 局部变量symLinkNamepDev = pDriver->DeviceObject;IoDeleteDevice(pDev);                                       // 调用IoDeleteDevice用于删除设备RtlInitUnicodeString(&SymLinkName, L"\\??\\LySharkDriver");     // 初始化字符串将symLinkName定义成需要删除的符号链接名称IoDeleteSymbolicLink(&SymLinkName);                         // 调用IoDeleteSymbolicLink删除符号链接DbgPrint("驱动卸载完毕...");
}// 创建设备连接
NTSTATUS 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);        // 指示完成此IRPreturn STATUS_SUCCESS;                           // 返回成功
}// 关闭回调函数
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功DbgPrint("派遣函数 IRP_MJ_CLOSE 执行 \n");IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRPreturn STATUS_SUCCESS;                           // 返回成功
}// 主控制器,用于判断R3发送的控制信号
// lyshark.com
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;PIO_STACK_LOCATION pIrpStack;ULONG uIoControlCode;PVOID pIoBuffer;ULONG uInSize;ULONG uOutSize;// 获得IRP里的关键数据pIrpStack = IoGetCurrentIrpStackLocation(pIrp);// 获取控制码uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;// 输入和输出的缓冲区(DeviceIoControl的InBuffer和OutBuffer都是它)pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;// EXE发送传入数据的BUFFER长度(DeviceIoControl的nInBufferSize)uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;// EXE接收传出数据的BUFFER长度(DeviceIoControl的nOutBufferSize)uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;// 对不同控制信号的处理流程switch (uIoControlCode){// 接收或发送case IOCTL_IO_LyShark:{DWORD dw = 0;// 得到输入参数memcpy(&dw, pIoBuffer, sizeof(DWORD));DbgPrint("[+] hello lyshark \n");// 对输入参数进行处理dw++;// 设置输出参数memcpy(pIoBuffer, &dw, sizeof(DWORD));// 返回通信状态status = STATUS_SUCCESS;break;}pIrp->IoStatus.Status = status;pIrp->IoStatus.Information = uOutSize;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return status;}// 设定DeviceIoControl的*lpBytesReturned的值(如果通信失败则返回0长度)if (status == STATUS_SUCCESS)pIrp->IoStatus.Information = uOutSize;elsepIrp->IoStatus.Information = 0;// 设定DeviceIoControl的返回值是成功还是失败pIrp->IoStatus.Status = status;IoCompleteRequest(pIrp, IO_NO_INCREMENT);return status;
}// 入口函数
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{// 调用创建设备CreateDriverObject(pDriver);pDriver->DriverUnload = UnDriver;                               // 卸载函数pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;         // 创建派遣函数pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;           // 关闭派遣函数pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;  // 分发函数DbgPrint("By:LyShark ...");return STATUS_SUCCESS;
}

应用层通用测试模板代码如下:

#include <iostream>
#include <Windows.h>
#include <winioctl.h>#define IOCTL_IO_LyShark CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)int main(int argc, char *argv[])
{HANDLE hDevice = CreateFileA("\\\\.\\LySharkDriver", GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hDevice == INVALID_HANDLE_VALUE){CloseHandle(hDevice);return 0;}// 发送控制信号// input = 发送数据 output = 接受数据 ref_len = 数据长度DWORD input = 100, output = 0, ref_len = 0;DeviceIoControl(hDevice, IOCTL_IO_LyShark, &input, sizeof(input), &output, sizeof(output), &ref_len, 0);printf("输出: %d \n", output);system("pause");CloseHandle(hDevice);return 0;
}

输出效果如下:


http://chatgpt.dhexx.cn/article/7iuKHkhi.shtml

相关文章

deviceiocontrol(deviceiocontrol函数)

如何用DeviceIOControl读取并口信息 应用程序和驱动程序的通信过程是&#xff1a;应用程序使用CreateFile函数打开设备&#xff0c;然后用DeviceIoControl与驱动程序进行通信&#xff0c;包括读和写两种操作。还可以用ReadFile读数据用WriteFile写数据。操作完毕时用CloseHandl…

DeviceIOControl详解-各个击破

DeviceIoControl这个api我们用的不多&#xff0c;但是很重要&#xff0c;有时会帮助我们实现一些特别的需求, 如获取硬件设备信息、与硬件设备通信&#xff08;读写数据&#xff09;等&#xff0c;对照msdn&#xff0c;下面我们详细解释一下这个api的用法&#xff08;有什么错误…

DeviceIoControl 函数详细解析

前言&#xff1a; 最近需要对Windows中的设备进行编程操作&#xff0c;其中涉及到非常重要的函数DeviceIoControl&#xff0c;在使用的时候也比较的复杂&#xff0c;国内这一块中文资料比较少&#xff0c;在学习之余顺便将其翻译出来&#xff0c;以供参考&#xff0c;如有错误&…

操作系统原理(一)——自举过程

操作系统&#xff0c;这个名词每个人都不会陌生&#xff0c;但又总觉得似乎没有了解很深&#xff0c;这一系列博客将会从零开始强化你对操作系统的认知。 1. 什么是操作系统&#xff1f; 答&#xff1a;操作系统是介于硬件与用户&#xff08;也就是程序和人&#xff09;之间的…

【操作系统基础知识 一】操作系统基本原理

学生时代没有好好学习操作系统&#xff0c;悔不当初&#xff0c;现在重新捡起来看看&#xff0c;才发现日常有很多事情都可以解释了&#xff0c;例如为什么Linux快&#xff01;并发是什么&#xff1f;操作系统到底干啥活&#xff0c;这篇blog是王道的学习笔记&#xff1a; 操作…

操作系统原理,进程的基本状态,运行态,就绪态,等待态与转换模型,进程的其他状态,创建,终止,挂起与转换模型,Linux进程状态模型示例

操作系统原理&#xff0c;进程的基本状态&#xff0c;运行态&#xff0c;就绪态&#xff0c;等待态与转换模型&#xff0c;进程的其他状态&#xff0c;创建&#xff0c;终止&#xff0c;挂起与转换模型&#xff0c;Linux进程状态模型示例 一、进程的三种基本状态&#xff1a; …

Linux操作系统基础原理

计算机系统 1.计算机体系层次 计算机自身是由众多电子元器件构成&#xff0c;硬件本身提供给用户的接口十分底层复杂&#xff0c;使用很不方便。在硬件之上的操作系统将硬件接口抽象封装为比较直观&#xff0c;用户容易调用的接口&#xff1b;用户开发应用程序&#xff0c;通过…

操作系统原理实验——实验一 Linux基本操作

1、实验目的 &#xff08;1&#xff09;熟悉Linux下的基本操作&#xff0c;学会使用各种Shell命令去操作Linux&#xff0c;对Linux有一个感性认识。 &#xff08;2&#xff09;学会使用vi编辑器编辑简单的C语言程序&#xff0c;并能对其编译和调试。 2、实验预备内容 &#…

Linux 操作系统原理 — 操作系统的本质

目录 文章目录 目录操作系统的起源操作系统和高级编程语言使硬件抽象化操作系统的起源 在操作系统尚不存在的年代,人们通过各种按钮来控制计算机,这一过程非常麻烦。于是,有人开发出了仅仅具有加载和运行功能的监控程序(Supervisor),这就是操作系统的原型。 通过监控程…

操作系统原理之多进程、多线程与并发

文章目录 (1)什么是进程&#xff1f;(2)进程的状态(3)OS何时介入进程调度&#xff1f;(4)多进程的意义(5)并行和并发(6)进程间通信(7)死锁(8)什么是线程&#xff1f;(9)多线程的意义(10)进程和线程的区别(11)Java线程和OS线程的关系 提示&#xff1a;以下是本篇文章正文内容&am…

【考研复习】《操作系统原理》孟庆昌等编著课后习题+答案——第二章

前言 此书在最后的附录B中&#xff0c;有给出部分重难点部分的参考答案。会在最后放上图片。如果想要此书习题答案&#xff0c;可点以下链接&#xff1a;为一个压缩包&#xff0c;以图片形式&#xff0c;习题图片按章节排序&#xff0c;答案图片按书页排序。 《操作系统原理…

操作系统原理——第六章:页面置换算法

文章目录 1. 功能与目标2. 实验设置与评价方法3. 局部页面置换算法3.1 最优页面置换算法&#xff08;OPT&#xff0c;optimal&#xff09;3.2 先进先出算法&#xff08;FIFO&#xff09;3.3 最近最久未使用算法&#xff08;LRU&#xff0c;Least Recently Used&#xff09;3.4 …

操作系统原理模拟实验(基于C/C++模拟处理机调度、存储管理和文件系统)

目录 引言一、处理机调度模拟1、下载链接2、目的与要求3、截图示例 二、存储管理模拟动态分区分配1、下载链接2、目的与要求3、截图示例 分页存储地址转换1、下载链接2、目的与要求3、截图示例 三、文件系统模拟1、下载链接2、目的与要求3、截图示例 引言 包含多个实验的完整源…

操作系统原理总结

转载&#xff1a;https://blog.csdn.net/yanglingwell/article/details/53745758 操作系统原理总结 made by 杨领well (yanglingwellsina.com) 一、基础知识点 1. 操作系统的资源管理技术 资源管理解决物理资源数量不足和合理分配资源这两个问题。 操作系统虚拟机为用户提供…

操作系统原理:覆盖技术、交换技术、虚拟内存概要

随着时间的推移&#xff0c;程序不断地更新&#xff0c;规模不断增长&#xff0c;运行的时候可能会发现内存会越来越不够用。所以希望一个容量大&#xff0c;更快&#xff0c;更便宜&#xff0c;数据不易丢失的存储器。 首先想到的就是硬盘&#xff0c;所以在硬盘的基础上建立了…

操作系统原理、实现与实践课后习题参考答案(已完结)

习题二–系统接口 通向操作系统内核的大门 1.调用fork()的父子进程执行“同样”的代码&#xff0c;如何理解”同样“&#xff1f; 答&#xff1a; fork()函数为系统调用&#xff0c;用于创建进程。创建的进程与原来进程几乎完全相同. 一个进程调用fork&#xff08;&#xff09…

操作系统原理1-3章答案 黑新宏 胡元义主编

第1章引论 一、单项选择题 1.A 2. C 3. D 4. A 5.A 6. C 7. C 8. D 9. C 10.C 11. D 12.A 13.C 14.D 15.D 16.C 17.D 18.C 19.B 20.C 21.D 22.D 23.C 24.B 25.C 26.B 二、判断题 1.错误 2. 错误 3.错误 4. 错误 5.错误 6.错误 7.正确 8.错误 9.错误 10.错误 11.正确 12.错误 1…

操作系统原理:文件系统、磁盘调度

目录 一、相关概念 二、文件的分配 三、空闲空间列表 四、多磁盘管理-RAID 五、磁盘调度 一、相关概念 文件系统是一种用于持久性存储的系统抽象。硬盘属于持久性存储介质的一种。管理文件系统例如硬盘&#xff0c;需要管理文件块&#xff0c;哪一块属于哪一…

Linux的操作系统原理详解

Linux的操作系统原理详解 ///插播一条&#xff1a;我自己在今年年初录制了一套还比较系统的入门单片机教程&#xff0c;想要的同学找我拿/// 1.操作系统基本概念 操作系统是一个基本程序的集合&#xff0c;在这个集合中&#xff0c;最重要的程序称为内核&#xff08;Kernel&a…