DeviceIoControl的使用说明

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

BOOL DeviceIoControl(
  HANDLE hDevice,
  DWORD dwIoControlCode,
  LPVOID lpInBuffer,
  DWORD nInBufferSize,
  LPVOID lpOutBuffer,
  DWORD nOutBufferSize,
  LPDWORD lpBytesReturned,
  LPOVERLAPPED lpOverlapped
);Parameters(参数)
hDevice (CreateFile返回的设备句柄)
[in] Handle to the device that is to perform the operation. To obtain a device handle, call the CreateFile function.
dwIoControlCode (应用程序调用驱动程序的控制命令,就是IOCTL_XXX IOCTLs )
[in] IOCTL for the operation. This value identifies the specific operation to perform and the type of device on which to perform the operation. There are no specific values defined for the dwIoControlCode parameter. However, you can define custom IOCTL_XXX IOCTLs with the CTL_CODE macro. You can then advertise these IOCTLs and an application can use these IOCTLs with DeviceIoControl to perform the driver-specific functions.
lpInBuffer (应用程序传递给驱动程序的数据缓冲区地址)
[in] Long pointer to a buffer that contains the data required to perform the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not require input data.
nInBufferSize (应用程序传递给驱动程序的数据缓冲区大小,字节数)
[in] Size, in bytes, of the buffer pointed to by lpInBuffer.
lpOutBuffer (驱动程序返回给应用程序的数据缓冲区地址)
[out] Long pointer to a buffer that receives the output data for the operation. Set to NULL if the dwIoControlCode parameter specifies an operation that does not produce output data.
nOutBufferSize (驱动程序返回给应用程序的数据缓冲区大小,字节数)
[out] Size, in bytes, of the buffer pointed to by lpOutBuffer.
lpBytesReturned (驱动程序实际返回给应用程序的数据字节数地址)
[out] Long pointer to a variable that receives the size, in bytes, of the data stored in lpOutBuffer. The DeviceIoControl function may unnecessarily use this parameter. For example, if an operation does not produce data for lpOutBuffer and lpOutBuffer is NULL, the value of lpBytesReturned is meaningless.
lpOverlapped (重叠操作结构)
[in] Ignored; set to NULL.
Return Values(返回值)
Nonzero indicates success. Zero indicates failure. To obtain extended error information, call the GetLastError function. (非0成功,0失败)

具体使用我们看看列子:

1,向设备传递数据,我们定义一个函数来实现

bool CDeviceOperDlg::SendKeyData(HANDLE handle, BYTE *bData, int iSize)
{
 ULONG nOutput;
 BYTE bTemp[512];

//将数据放置到发送数组
 memset(bTemp,0,sizeof(bTemp));
 memcpy(bTemp,&bData[0],iSize);
 //向设备发送
 if (!DeviceIoControl(handle,        
       ATST2004_IOCTL_WRITE,     //根据具体的设备有相关的定义
       bTemp,                                        //向设备传递的数据地址
       iSize,                                            //数据大小,字节数
       NULL,                                          //没有返回的数据,置为NULL
       0,                                                  //没有返回的数据,置为0

&nOutput,
       NULL)
    )
 {
  return false;
 }

return true;
}

2,从设备读取数据

bool CDeviceOperDlg::ReviceKeyData(HANDLE handle, BYTE *bData, int iSize)
{

ULONG nOutput;
 BYTE bTemp[512];
 //数组清零
 memset(bTemp,0,sizeof(bTemp));
 //向设备发送
 if (!DeviceIoControl(handle,
       ATST2004_IOCTL_READ,           //根据具体的设备有相关的定义
       NULL,                                              //没有向设备传递的数据,置为NULL
       0,                                                      //没有向设备传递的数据,置为NULL
       bTemp,                                           //读取设备的数据返回地址
       iSize,                                               //读取数据的字节数
       &nOutput,
       NULL)
    )
 {
  return false;
 }
 //放置到公用数组
 memcpy(&bData[0],&bTemp[0],iSize);
 return true;
}

---------------------------------------------------------------------------------

CTL_CODE说明

我们在说DeviceIoControl函数时其第二个参数dwIoControlCode就是由CTL_CODE宏定义的,下边我们可以了解一下CTL_CODE的内容。
CTL_CODE:用于创建一个唯一的32位系统I/O控制代码,这个控制代码包括4部分组成:DeviceType(设备类型,高16位(16-31位)),Access(访问限制,14-15位),Function(功能2-13位),Method(I/O访问内存使用方式)。

This macro creates a unique system I/O control code (IOCTL).

#define CTL_CODE(DeviceType, Function, Method, Access) (
  ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)
)Parameters(参数)
DeviceType
Defines the type of device for the given IOCTL.
This parameter can be no bigger than a WORD value.

The values used by Microsoft are in the range 0-32767; the values 32768-65535 are reserved for use by OEMs and IHVs.

The following device types are defined by the system:

FILE_DEVICE_BEEP
FILE_DEVICE_CD_ROM
FILE_DEVICE_CD_ROM_FILE_SYSTEM
FILE_DEVICE_CONTROLLER
FILE_DEVICE_DATALINK
FILE_DEVICE_DFS
FILE_DEVICE_DISK
FILE_DEVICE_DISK_FILE_SYSTEM
FILE_DEVICE_FILE_SYSTEM
FILE_DEVICE_INPORT_PORT
FILE_DEVICE_KEYBOARD
FILE_DEVICE_MAILSLOT
FILE_DEVICE_MIDI_IN
FILE_DEVICE_MIDI_OUT
FILE_DEVICE_MOUSE
FILE_DEVICE_MULTI_UNC_PROVIDER
FILE_DEVICE_NAMED_PIPE
FILE_DEVICE_NETWORK
FILE_DEVICE_NETWORK_BROWSER
FILE_DEVICE_NETWORK_FILE_SYSTEM
FILE_DEVICE_NULL
FILE_DEVICE_PARALLEL_PORT
FILE_DEVICE_PHYSICAL_NETCARD
FILE_DEVICE_PRINTER
FILE_DEVICE_SCANNER
FILE_DEVICE_SERIAL_MOUSE_PORT
FILE_DEVICE_SERIAL_PORT
FILE_DEVICE_SCREEN
FILE_DEVICE_SOUND
FILE_DEVICE_DEVICE_STREAMS
FILE_DEVICE_TAPE
FILE_DEVICE_TAPE_FILE_SYSTEM
FILE_DEVICE_TRANSPORT
FILE_DEVICE_UNKNOWN
FILE_DEVICE_VIDEO
FILE_DEVICE_VIRTUAL_DISK
FILE_DEVICE_WAVE_IN
FILE_DEVICE_WAVE_OUT
FILE_DEVICE_8042_PORT
FILE_DEVICE_NETWORK_REDIRECTOR
FILE_DEVICE_BATTERY
FILE_DEVICE_BUS_EXTENDER
FILE_DEVICE_MODEM
FILE_DEVICE_VDM
FILE_DEVICE_MASS_STORAGE
FILE_DEVICE_SMB
FILE_DEVICE_KS
FILE_DEVICE_CHANGER
FILE_DEVICE_SMARTCARD
FILE_DEVICE_ACPI
FILE_DEVICE_DVD
FILE_DEVICE_FULLSCREEN_VIDEO
FILE_DEVICE_DFS_FILE_SYSTEM
FILE_DEVICE_DFS_VOLUME
The following device types are specific to Windows CE:

FILE_DEVICE_HAL
FILE_DEVICE_CONSOLE
FILE_DEVICE_PSL
FILE_DEVICE_SERVICE
Function
Defines an action within the device category.
Function codes 0-2047 are reserved for Microsoft; codes 2048-4095 are reserved for OEMs and IHVs.

A function code can be no larger then 4095.

Method
Defines the method codes for how buffers are passed for I/O and file system controls.
The following values are possible for this parameter:

METHOD_BUFFERED
METHOD_IN_DIRECT
METHOD_OUT_DIRECT
METHOD_NEITHER
This field is ignored by Windows CE. You should always use the METHOD_BUFFERED value unless compatibility with Windows-based desktop platforms is required using a different Method value.

Access
Defines the access check value for any access.
The following table shows the possible flags for this parameter. The FILE_ACCESS_ANY is generally the correct value.

Flag Description
FILE_ANY_ACCESS Request all access.
FILE_READ_ACCESS Request read access. Can be used with FILE_WRITE_ACCESS.
FILE_WRITE_ACCESS Request write access. Can be used with FILE_READ_ACCESS.

Return Values(返回值)
None.

Remarks(备注)
The macro can be used for defining IOCTL and FSCTL function control codes. All IOCTLs must be defined this way to ensure that values used by Microsoft, OEMs, and IHVs do not overlap.

The following illustration shows the format of the resulting IOCTL.

---------------------------------
|             |         |         |    |
31         16 15 14       2    1
---------------------------------
              |         |         |    |
DeviceType Access Function Method
---------------------------------

举例说明一下:

我定义两个IOCTL,一个用于对设备的读,一个用于对设备的写

#define ATST2004_IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_DATA)
#define ATST2004_IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_WRITE_DATA)

在VC中使用不需要进行处理,假如我要在VB中使用这两个IOCTL,就需要进行查值计算了,计算后定义如下:

Private Const ATST2004_IOCTL_READ = &H226000
Private Const ATST2004_IOCTL_WRITE = &H22A004

关于Method(I/O访问内存使用方式),我们下篇在说。

------------------------------------------------------------------------------------

CTL_CODE定义中Method的说明

我在上一篇中说明CTL_CODE的时候,其中CTL_CODE定义中有一个Method域,该域的功能意义是定义用于与在驱动程序中获取应用程序数据缓冲区的地址方式。如果你看了我前边的文章,你可以看到在DeviceIoControl的使用说明中对DeviceIoControl参数进行描述中关于lpInBuffer 和lpOutBuffer 的描述。简单的说,Method域就是定义了lpInBuffer 和lpOutBuffer 缓冲区在驱动程序中对这两个缓冲区地址的获取和数据的操作方式。我们分别进行描述:

•METHOD_BUFFERED
系统分配一个缓冲区用于输入和输出,该缓冲区的字节数应该为应用程序的输入和输出缓冲区中较大的字节数。驱动程序中通过KIrp::IoctlBuffer获得缓冲区的地址。对于输出,驱动程序必须将输出字节数返回给I.Information(),然后由I/O管理器将数据从系统缓冲区复制到应用程序的缓冲区中。

•METHOD_IN_DIRECT
•METHOD_OUT_DIRECT
在这两种方式下,输入缓冲区数据被复制到一个系统缓冲区中,驱动程序可以用KIrp::IoctlBuffer访问这个缓冲区。输出缓冲区被类KMemory对象映射,驱动程序可以通过KIrp::Mdl来访问这个缓冲区。

•METHOD_NEITHER
这个比较特殊,一般不使用。

typedef   struct_OVERLAPPED
{
      DWORD   Internal;
      DWORD   InternalHigh;
      DWORD   offset;
      DWORD   offsetHigh;
      HANDLE   hEvent;
}OVERLAPPED;
Internal   指定与系统相关的状态,为操作系统的使用而保留;
InternalHigh   指定传送数据的长度,为操作系统的使用而保留;
offset   指定文件的位置,从该位置传送数据,文件位置是相对文件开始处的字节偏移量。调用ReadFile或WriteFile函数之前调用进程设置这个成员,读写命名管道及通信设备时调用进程忽略这个成员;
offsetHigh   指定开始传送数据的字节偏移量的高位字,读写命名管道及通信设备时调用进程忽略这个成员;
hEvent   标识事件,数据传送完成时把它设为信号状态,调用ReadFile   WriteFile   ConnectNamedPipe   TransactNamedPipe函数前,调用进程设置这个成员.
相关函数   CreateEvent     ResetEvent   GetOverlappedResult   WaitForSingleObject   CWinThread   GetLastErro

DeviceIoControl详解相关推荐

  1. DeviceIOControl详解-各个击破

    DeviceIoControl这个api我们用的不多,但是很重要,有时会帮助我们实现一些特别的需求, 如获取硬件设备信息.与硬件设备通信(读写数据)等,对照msdn,下面我们详细解释一下这个api的用 ...

  2. 应用程序与驱动程序交互函数DeviceIoControl详解

    这种通信方式,就是驱动程序和应用程序自定义一种IO控制码,然后调用DeviceIoControl函数,IO管理器会产生一个MajorFunction 为IRP_MJ_DEVICE_CONTROL(De ...

  3. 《Windows驱动开发技术详解》学习笔记

    Abstract   如果推荐 Windows 驱动开发的入门书,我强烈推荐<Windows驱动开发技术详解>.但是由于成书的时间较早,该书中提到的很多工具和环境都已不可用或找不到,而本文 ...

  4. Windows API函数大全---附:windows运行命令详解

    1. API之网络函数             WNetAddConnection 创建同一个网络资源的永久性连接             WNetAddConnection2 创建同一个网络资源的连 ...

  5. windows USB读卡器驱动详解

    目标 在windows 2000及以上版本的操作系统中,开发usb读卡器驱动.实现数据批量传输功能,同时需要根据特定的协议(协议可自定义)进行通信.实现一个基于此usb驱动的动态库(统一接口),供上层 ...

  6. c语言windows驱动编程入门,Windows驱动开发技术详解 PDF扫描版[175MB]

    Windows驱动开发技术详解由浅入深.循序渐进地介绍了windows驱动程序的开发方法与调试技巧.本书共分23章,内容涵盖了windows操作系统的基本原理.nt驱动程序与wdm驱动程序的构造.驱动 ...

  7. 从命令行到IDE,版本管理工具Git详解(远程仓库创建+命令行讲解+IDEA集成使用)

    首先,Git已经并不只是GitHub,而是所有基于Git的平台,只要在你的电脑上面下载了Git,你就可以通过Git去管理"基于Git的平台"上的代码,常用的平台有GitHub.Gi ...

  8. JVM年轻代,老年代,永久代详解​​​​​​​

    秉承不重复造轮子的原则,查看印象笔记分享连接↓↓↓↓ 传送门:JVM年轻代,老年代,永久代详解 速读摘要 最近被问到了这个问题,解释的不是很清晰,有一些概念略微模糊,在此进行整理和记录,分享给大家.在 ...

  9. docker常用命令详解

    docker常用命令详解 本文只记录docker命令在大部分情境下的使用,如果想了解每一个选项的细节,请参考官方文档,这里只作为自己以后的备忘记录下来. 根据自己的理解,总的来说分为以下几种: Doc ...

最新文章

  1. 自然语言处理(NLP)历史中的6个主要时期你知道吗?
  2. 8086 汇编指令手册查询(转)
  3. 相比 App,Web 开发竟更适合初创公司?
  4. gets函数会读取回车吗_会做二次函数吗?用6种方法教你做二次函数(初中生不要错过)...
  5. cello 有关trigger
  6. vue-cli的webpack模版,相关配置文件dev-server.js与webpack.config.js配置解析
  7. 《Python Cookbook 3rd》笔记(5.18):将文件描述符包装成文件对象
  8. 快速接入阿里云应用配置管理工具 轻松开启企业效率新时代
  9. 小心编译器的隐式声明
  10. 四年级下册英语计算机房和教师办公室的图片,人教版四年级英语下册Unit 1单元知识梳理卷...
  11. [leetcode] @python 113. Path Sum II
  12. 微信公众号分销商城(源码+数据库+文档)
  13. 【C/C++】使用PDFLIB创建一个带中文的pdf文件
  14. Object-C 介绍
  15. python每天定时执行任务_Python设置定时任务
  16. PHP毕业设计——艺术品展示网站
  17. 小程序流量主怎么赚钱?
  18. ArrayList的add方法详解——让我们好好看看一个元素是如何插入到ArrayList集合当中(源码级别)
  19. 基于Aforge的物体运动识别-入门篇
  20. java 连接Linux服务器并执行指令

热门文章

  1. Java网络编程UDP协议--模拟英雄联盟游戏聊天骂人变*--优化网络环境从你我做起
  2. 人一生要经历多少次“灵魂深处的革命”,才能达到一个成功者需要的精神特质?...
  3. hive load data inpath ‘‘ overwrite into 坑
  4. 很早之前申请过域名,现在想做一个网站,如何来操作
  5. NSString使用stringWithFormat
  6. 用向导制作FLI30602封装
  7. MFC函数之BitBlt
  8. 聚类算法评价指标python实现_[ML] 聚类评价指标
  9. android之简单手电筒
  10. 用Arduino自制钢琴实现录音和重放,陈老师教你弹