当前位置: 首页 > article >正文

DeviceIoControl的使用说明

    应用程序和驱动程序的通信过程是:应用程序使用CreateFile函数打开设备,然后用DeviceIoControl与驱动程序进行通信,包括读和写两种操作。还可以用ReadFile读数据用WriteFile写数据。操作完毕时用CloseHandle关闭设备。我们比较常用的就是用DeviceIoControl对设备进行读写操作。

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


参数说明

hDevice

要进行操作的设备句柄。

dwIoControlCode

要进行操作的控制码。驱动程序可以通过CTL_CODE宏来组合定义一个控制码,并在IRP_MJ_DEVICE_CONTROL的实现中进行控制码的操作。在驱动层,irpStack->Parameters.DeviceIoControl.IoControlCode表示了这个控制码。

lpInBuffer

由用户层发送的缓冲区数据。在驱动层,依传输类型的不同,输入缓冲区的位置亦不同,见下表。

传输类型           位置
METHOD_IN_DIRECT   irp->AssociatedIrp.SystemBuffer
METHOD_OUT_DIRECT  irp->AssociatedIrp.SystemBuffer
METHOD_BUFFERED    irp->AssociatedIrp.SystemBuffer
METHOD_NEITHER     irpStack->Parameters.DeviceIoControl.Type3InputBuffer


nInBufferSize

由用户层发送的缓冲区大小。在驱动层,这个值是irpStack->Parameters.DeviceIoControl.InputBufferLength。

lpOutBuffer

由用户层指定,用于接收驱动层返回数据的缓冲区。在驱动层,依传输类型的不同,输出缓冲区的位置亦不同,见下表。

传输类型            位置
METHOD_IN_DIRECT    irp->MdlAddress
METHOD_OUT_DIRECT   irp->MdlAddress
METHOD_BUFFERED     irp->UserBuffer
METHOD_NEITHER      irp->AssociatedIrp.SystemBuffer

"缓冲"方法(METHOD_BUFFERED)
备注:在下面的讨论中,"输入"表示数据从用户模式的应用程序到驱动程序,"输出"表示数据从驱动程序到应用程序。

对于读取请求,I/O 管理器分配一个与用户模式的缓冲区大小相同的系统缓冲区。IRP 中的 SystemBuffer 字段包含系统地址。UserBuffer 字段包含初始的用户缓冲区地址。当完成请求时,I/O 管理器将驱动程序已经提供的数据从系统缓冲区复制到用户缓冲区。对于写入请求,会分配一个系统缓冲区并将 SystemBuffer 设置为地址。用户缓冲区的内容会被复制到系统缓冲区,但是不设置 UserBuffer。对于 IOCTL 请求,会分配一个容量大小足以包含输入缓冲区或输出缓冲区的系统缓冲区,并将 SystemBuffer 设置为分配的缓冲区地址。输入缓冲区中的数据复制到系统缓冲区。UserBuffer 字段设置为用户模式输出缓冲区地址。内核模式驱动程序应当只使用系统缓冲区,且不应使用 UserBuffer 中存储的地址。

对于 IOCTL,驱动程序应当从系统缓冲区获取输入并将输出写入到系统缓冲区。当完成请求时,I/O 系统将输出数据从系统缓冲区复制到用户缓冲区。

"直接"方法(METHOD_IN/OUT_DIRECT)
对于读取和写入请求,用户模式缓冲区会被锁定,并且会创建一个内存描述符列表 (MDL)。MDL 地址会存储在 IRP 的 MdlAddress 字段中。SystemBuffer 和 UserBuffer 均没有任何含义。但是,驱动程序不应当更改这些字段的值。

对于 IOCTL 请求,如果在 METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT 中同时有一个输出缓冲区,则分配一个系统缓冲区(SystemBuffer 又有了地址)并将输入数据复制到其中。如果有一个输出缓冲区,且它被锁定,则会创建 MDL 并设置 MdlAddress。UserBuffer 字段没有任何含义。

"两者都不"方法(METHOD_NEITHER)
对于读取和写入请求,UserBuffer 字段被设置为指向初始的用户缓冲区。不执行任何其他操作。SystemAddress 和 MdlAddress 没有任何含义。对于 IOCTL 请求,I/O 管理器将 UserBuffer 设置为初始的用户输出缓冲区,而且,它将当前 I/O 栈位置的 Parameters.DeviceIoControl.Type3InputBuffer 设置为用户输入缓冲区。利用该 I/O 方法,由驱动程序来确定如何处理缓冲区:分配系统缓冲区或创建 MDL。

通常,驱动程序在访问用户数据时不应当将 UserBuffer 字段用作地址,即使当用户缓冲区被锁定时也是如此。这是由于在调用驱动程序时,在系统中可能看不到调用用户的地址空间。(对于该规则的一个例外是,在最高层驱动程序将 IRP 向下传递到较低层的驱动程序之前,它可能需要使用 UserBuffer 来复制数据。)如果使用"直接"或"两者都不"方法,在创建 MDL 之后,驱动程序可以使用 MmGetSystemAddressForMdl 函数来获取有效的系统地址以访问用户缓冲区。


nOutBufferSize

由用户层指定,用于接收驱动层返回数据的缓冲区大小。在驱动层,这个值是irpStack->Parameters.DeviceIoControl.OutputBufferLength。

lpBytesReturned

由用户层指定,用于接收驱动层实际返回数据大小。在驱动层,这个值是irp->IoStatus->Information。

lpOverlapped

用于异步操作。

————————————————————————————————————

irp为PIRP类型,即PDRIVER_DISPATCH的入口参数。
irpStack为PIO_STACK_LOCATION类型,即IoGetCurrentIrpStackLocation的返回值。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mbalium/archive/2009/06/30/4310802.aspx

http://www.lryc.cn/news/2419520.html

相关文章:

  • fcfs调度算法_王道操作系统学习笔记(四)进程调度
  • 对偶问题的理解
  • java 通过远程URL实现文件下载几种方式
  • 《工程电磁场》学习笔记1-静电场
  • 研究生们都在推荐哪些好用的论文在线翻译软件?
  • 【STM32学习笔记】(9)——串口通讯(USART)详解
  • 机器学习(四)—— 多项式回归
  • 如何解决IDEA中输入sout,psvm后没有自动联想功能的问题。
  • Linux-UGO用户权限
  • HTML Help Workshop(chm生成工具)的使用
  • 汉字转Unicode编码
  • Java 性能优化实战工具实践:基准测试 JMH,精确测量方法性能
  • 网络通信基础(入门知识总结)
  • 实现动态数组
  • 四大主流云平台对比--CloudStack, Eucalyptus, vCloud Director和OpenStack。
  • 37.绘制文本DrawText、DrawTextEx、DRAWTEXTPARAMS 使用
  • SQL语法——触发器
  • 卷!推荐11个做PPT的神仙网站
  • xshell安装错误:-1605这个操作只对当前安装的产品有效
  • 系统架构图
  • Python 三个拆分函数(split、rsplit、splitlines)不同的用法
  • PUBG介绍
  • 网页星号密码查看器_四大密码查看器 星号、浏览器保存密码、连接过的WIFI账号密码...
  • Java中慎用e.printStackTrace()
  • 2022年诺贝尔物理学奖背后的故事——贝尔不等式诞生之后
  • SurfaceView 基本使用
  • 硬件测试需要什么软件是什么原因,什么硬件软件检测温度准啊
  • zeros什么意思_什么是张量?
  • Ubuntu Touch的小确幸(Linux系统手机Ubports)
  • 数据结构(C语言版)--速成笔记【持续更新中。。】