DeviceIoControl参数各个击破~!

DeviceIoControl这个api我们用的不多,但是很重要,有时会帮助我们实现一些特别的需求, 如获取硬件设备信息、与硬件设备通信(读写数据)等,对照msdn,下面我们详细解释一下这个api的用法(有什么错误再所难免,各位不吝指教啊)。

DeviceIoControl是用来控制我们指定设备的输入输出操作,使设备按照我们发的指令去工作。

DeviceIoControl是kernel32中的函数,需要包含的头文件是winbase.h,先看函数原型

<strong>BOOL DeviceIoControl(
  HANDLE</strong> <em sizcache="28" sizset="62"><a target=_blank class="synParam" href="">hDevice</a></em><strong>,
  DWORD</strong> <em sizcache="28" sizset="63"><a target=_blank class="synParam" href="">dwIoControlCode</a></em><strong>,
  LPVOID</strong> <em sizcache="28" sizset="64"><a target=_blank class="synParam" href="">lpInBuffer</a></em><strong>,
  DWORD</strong> <em sizcache="28" sizset="65"><a target=_blank class="synParam" href="">nInBufferSize</a></em><strong>,
  LPVOID </strong><em sizcache="28" sizset="66"><a target=_blank class="synParam" href="">lpOutBuffer</a></em><strong>,
  DWORD</strong> <em sizcache="28" sizset="67"><a target=_blank class="synParam" href="">nOutBufferSize</a></em><strong>,
  LPDWORD</strong> <em sizcache="28" sizset="68"><a target=_blank class="synParam" href="">lpBytesReturned</a></em><strong>,
  LPOVERLAPPED</strong> <em sizcache="28" sizset="69"><a target=_blank class="synParam" href="">lpOverlapped</a></em>
<strong>);</strong>

哈哈,参数不少,而且还都很抽象,没关系,我们一个一个击破它

来到第一个参数,hDevice,当然是要操作的设备的句柄了,这个句柄需要通过CreateFile的返回值中获取,对于createfile这里只做一个粗略的解释:

  • <strong>HANDLE CreateFile(
      LPCTSTR</strong> <em sizcache="28" sizset="70"><a target=_blank class="synParam" href="">lpFileName</a></em><strong>,
      DWORD</strong> <em sizcache="28" sizset="71"><a target=_blank class="synParam" href="">dwDesiredAccess</a></em><strong>,
      DWORD</strong> <em sizcache="28" sizset="72"><a target=_blank class="synParam" href="">dwShareMode</a></em><strong>,
      LPSECURITY_ATTRIBUTES</strong> <em sizcache="28" sizset="73"><a target=_blank class="synParam" href="">lpSecurityAttributes</a></em><strong>,
      DWORD</strong> <em sizcache="28" sizset="74"><a target=_blank class="synParam" href="">dwCreationDisposition</a></em><strong>,
      DWORD</strong> <em sizcache="28" sizset="75"><a target=_blank class="synParam" href="">dwFlagsAndAttributes</a></em><strong>,
      HANDLE</strong> <em sizcache="28" sizset="76"><a target=_blank class="synParam" href="">hTemplateFile</a></em>
    <strong>);</strong> 

参数:要打开的文件名,访问权限,共享模式,安全属性,文件存在与不存在时的文件创建模式,文件属性设定(隐藏、只读、压缩、指定为系统文件等),文件副本句柄。要说明的是第一个参数lpFileName,是设备的名称或者是和设备关连的驱动的名称,一般用\\.\DeviceName的形式,比如要打开逻辑驱动盘A就用\\.\a,也可以用\\.\PhysicalDevice0,\\.\PhsycalDebive1来指定物理驱动器,\\.\PhysicalDevice0表示本机的物理驱动器0(一般是主硬盘),从而来获取硬盘的序列号、模块名、扇区数、磁头数等相关信息

搞定hDevice!

dwIoControlCode: 当然就是控制设备的指令了,指令怎么来是个问题,微软已经定义好了很多种操作,在winioctl.h文件中,但最终都是通过CTL_CODE宏来实现的,其实这就是一种通信协议。CTL_CODE的具体用法在最后来介绍。

lpInBuffer:
设备操控请求数据的缓冲区基址,如果dwIoControlCode 指定了一个操作,该操作不需要输入数据,那么这个参数设为NULL

nInBufferSizelplnBuffer的size

lpOutBuffer:存放输出数据的buffer,同样,如果dwIoControlCode 指定了一个操作,该操作不需要处理输出数据,那么这个参数设为NULL

nOutBufferSizehaha,别说你不知道什么什么意思,pass

lpBytesReturned实际输出数据的bytes

lpOverlappedIgnored; set to NULL.(Are you understand?)

下面来到第二个参数的详解,CTL_CODE的定义与应用:

CTL_CODE原型:

<strong>#define CTL_CODE(</strong><em sizcache="28" sizset="88"><a target=_blank class="synParam" href="">DeviceType</a></em>, <em sizcache="28" sizset="89"><a target=_blank class="synParam" href="">Function</a></em>, <em sizcache="28" sizset="90"><a target=_blank class="synParam" href="">Method</a></em>, <em sizcache="28" sizset="91"><a target=_blank class="synParam" href="">Access</a></em><strong>) (
  ((</strong><em sizcache="28" sizset="92"><a target=_blank class="synParam" href="">DeviceType</a></em><strong>) << 16) | ((</strong><em sizcache="28" sizset="93"><a target=_blank class="synParam" href="">Access</a></em><strong>) << 14) | ((</strong><em sizcache="28" sizset="94"><a target=_blank class="synParam" href="">Function</a></em><strong>) << 2) | (</strong><em sizcache="28" sizset="95"><a target=_blank class="synParam" href="">Method</a></em><strong>)
)</strong>

可以看到,这个宏四个参数,自然是一个32位分成了4部分,高16位存储设备类型( 这里不列举了,看msdn哦),14~15位访问权限,2~13位操作功能,最后一个就是确定缓冲区(别忘记上面DeviceIOControl中缓冲区的定义哦)是如何与I/O和文件系统数据缓冲区进行数据传递的方式(具体取值查看msdn)我们最常用的就是METHOD_BUFFERED

Function codes 0-2047 are reserved for Microsoft; codes 2048-4095 are reserved for OEMs and IHVs. (我们能用的是2048~4095)

看以下一段:

这个宏经常用来定义IOCTL(I/O控制)和FSCTL(文件系统控制)功能控制代码,所有的IOCTLs必须通过这种方式定义,以确保这些指令能被Microsoft,以及其他的硬件厂商通信接口所识别

The following illustration shows the format of the resulting IOCTL.

援引微软定义的一个指令:锁卷

#define FSCTL_LOCK_VOLUME               CTL_CODE(FILE_DEVICE_FILE_SYSTEM,  6, METHOD_BUFFERED, FILE_ANY_ACCESS)

DeviceIoControl参数各个击破~!

时间: 2024-11-05 16:07:27

DeviceIoControl参数各个击破~!的相关文章

WinCE 驱动开发问题精华集锦

如何让系统加载自己写的驱动程序? 两种办法: 1.在[HKEY_LOCAL_MACHINE/Drivers/BuiltIn]下添加注册键. 2.在应用程序中调用ActivateDeviceEx. 在一些文件中用分号来表示注释,例如下面的内容 ; @CESYSGEN IF SERVERS_MODULES_HTTPD ; @CESYSGEN ENDIF 在“CESYSGEN...”前加了“@”,有没有什么特别的含义? 在WINCE的一些文件中,用“;”作为注释并在注释文字中用@CESYSGEN作为标

转:WinCE驱动开发问题精华集锦

1.在应用程序中,如何向修改本机的ip 地址等网络参数,并使之立即生效?          网络设置保存在注册表中,位置[HKEY_LOCAL_MACHINE\Comm\网卡名称\Parms\TcpIp],例如常见的CS8900网卡设置:   [HKEY_LOCAL_MACHINE\Comm\CS89001\Parms\TcpIp]      "EnableDHCP"=dword:0      "DefaultGateway"="192.168.0.1&q

C/C++刁钻问题各个击破之细说sizeof(转)

今天在编程的时候,简单地用下边的程序求vector容器内的元素个数: vector<int> vec; for (int i = 0; i < 100; i++) { vec.push_back(i); } int size = sizeof(vec) / sizeof(int); 程序的运行结果是size=4(sizeof(vec)=16,sizeof(int)=4)而不是size=100.这让我很惊讶,因此我又进行了下边的实验: vector<int> vec_int;

CreateFile DeviceIoControl dwIoControlCode——应用程序与驱动程序通信

在"进程内存管理器中"的一个Ring0,Ring3层通信问题,之前也见过这样的代码,这次拆分出来详细总结一下. 先通过CreateFile函数得到设备句柄,CreateFile函数原型: HANDLE CreateFile( LPCTSTR lpFileName, // 文件名/设备路径 设备的名称 DWORD dwDesiredAccess, // 访问方式 DWORD dwShareMode, // 共享方式 LPSECURITY_ATTRIBUTES lpSecurityAttr

实战DeviceIoControl系列之四:获取硬盘的详细信息

Q 用IOCTL_DISK_GET_DRIVE_GEOMETRY IOCTL_STORAGE_GET_MEDIA_TYPES_EX只能得到很少的磁盘参数,我想获得包括硬盘序列号在内的更加详细的信息,有什么办法呀? A 确实,用你所说的I/O控 制码,只能得到最基本的磁盘参数.获取磁盘出厂信息的I/O控制码,微软在VC/MFC环境中没有开放,在DDK中可以发现一些线索.早先,Lynn McGuire写了一个很出名的获取IDE硬盘详细信息的程序DiskID32 ,下面的例子是在其基础上经过增删和改进

DeviceIoControl:通过API访问设备驱动程序;并获取window文件/文件夹id

1.设备句柄可以用API函数CreateFile获得.它的原型为 HANDLE CreateFile( LPCTSTR lpFileName,                         // 文件名/设备路径 DWORD dwDesiredAccess,                      // 访问方式 DWORD dwShareMode,                          // 共享方式 LPSECURITY_ATTRIBUTES lpSecurityAttrib

webpack4.0各个击破(4)—— Javascript &amp; splitChunk

目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 代码混淆压缩 四. 细说splitChunks技术 4.1 参数说明 4.2 参数配置 4.3 代码分割实例 五. 参考及附件说明 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建

webpack4.0各个击破(5)—— Module篇

webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法.(本篇中的参数配置及使用方式均基于webpack4.0版本) 使用webpack对脚本进行合并是非常方便的,因为webpack实现了对各种不同模块规范的兼容处理,对前端开发者来说,理解这种实现方式比学习如何配置w

webpack4.0各个击破(10)—— Integration篇

webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法.(本篇中的参数配置及使用方式均基于webpack4.0版本) 一. Integration 下文摘自webpack中文网: 首先我们要消除一个常见的误解,webpack是一个模块打包工具(module bundler),它不是一个任务执行工具,任务执行器是用来自动化处