现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

对DeviceIoControl()函数的整理

2020-05-10 21:59 工业·编程 ⁄ 共 8858字 ⁄ 字号 暂无评论

一、DeviceIoControl()各参数的简单说明

    利用DeviceIoControl()函数可以实现对系统硬件的操作,该函数通过向指定设备的驱动程序发送控制码从而让该设备执行相应的操作。函数原型为:

BOOL DeviceIoControl(

HANDLE hDevice,

DWORD dwIoControlCode,

LPVOID lpInBuffer,

DWORD nInBufferSize,

LPVOID lpOutBuffer,

DWORD nOutBufferSize,

LPDWORD lpBytesReturned,

LPOVERLAPPED lpOverlapped

);

    参数说明

    ● hDevice

    [in] 通过CreateFile()打开的设备句柄。注意CreateFile()函数在打开设备时设备名称必须使用“\\.\DeviceName”格式。

    ● dwIoControlCode

    [in] 操作的控制码。该参数的有效取值列表将会在后面重点介绍。

    ● lpInBuffer

    [in] 指向包含有执行当前操作所需数据缓冲区的指针。该参数格式依赖于dwIoControlCode所取的值,详见后面dwIoControlCode参数的说明部分。

    当dwIoControlCode所指定的操作不要求传入数据时,该参数可以为NULL。

    ● nInBufferSize

    [in] lpInBuffer所包含的字节数。

    ● lpOutBuffer

    [out] 指向接收当前操作返回数据缓冲区的指针。该参数格式依赖于dwIoControlCode所取的值,详见后面dwIoControlCode参数的说明部分。

    当dwIoControlCode所指定的操作不返回数据时,该参数可以为NULL。

    ● nOutBufferSize

    [in] lpOutBuffer最大可接收的字节数。

    ● lpBytesReturned

    [out] 用于存储 lpOutBuffer 中有效数据的字节数。

    如果 lpOutBuffer 由于空间过于小而无法接收任何数据,函数的调用将会失败。调用GetLastError()会得到ERROR_INSUFFICIENT_BUFFER 的错误值。此时 lpBytesReturned 值为0。

    如果 lpOutBuffer 由于空间过于小而无法接收所有数据,但可以容纳部分数据,有些设备将会返回部分数据以填充 lpOutBuffer。在这种情况下,函数的调用还是失败的,调用GetLastError()将会得到 ERROR_MORE_DATA 的错误值。此时 lpBytesReturned 值为 lpOutBuffer 中所接收的字节数。

    如果 lpOverlapped 为NULL,lpBytesReturned 必须不为NULL。甚至当当前操作并不需要返回数据、lpOutBuffer也为NULL时DeviceIoControl还是会使用lpBytesReturned。在这种情况下,函数完成后lpBytesReturned 的值没有意义。

    如果 lpOverlapped 不为NULL,lpBytesReturned 可以为NULL。如果这个参数不为NULL并且当前操作会返回数据时,lpBytesReturned 在异步操作完成之前是没有意义的。要得到返回的字节数,可调用GetOverlappedResult()函数。如果当前关联的设备是一个完成端口,可以通过调用 GetQueuedCompletionStatus() 函数来获取返回的字节数。

    ● lpOverlapped

    [in] 指向一个OVERLAPPED 结构。

    如果hDevice所指向的设备在打开时没有指定 FILE_FLAG_OVERLAPPED,该参数将被忽略。

    如果hDevice所指向的设备在打开时指定了 FILE_FLAG_OVERLAPPED,当前的操作将会以异步操作的方式执行,在这种情况下,lpOverlapped指向的必须是一个包含有有效事件对象(Event object :忘记行话怎么翻译了,以后再纠正)的OVERLAPPED 结构,否则将会发生不可预知的错误。

    对于异步操作,当事件对象有信号时DeviceIoControl 会立即返回,否则,函数将会一直阻塞直到操作完成或者发生错误。

二、dwIoControlCode各取值的意义

1、通信控制码

    ● IOCTL_SERIAL_LSRMST_INSERT

    该控制码允许/禁止线路状态和调制解调器状态发送到数据流中。应用程序可以通过ReadFile函数从数据流中获取这些状态。

    当允许线路状态和调制解调器状态发送时,数据流中的状态值之前将会有一个转义字符。转义字符是可以自定义的。状态值一般由1—3个字节组成。

    注意: 一个应用程序使用这种模式时必须检查数据流中的每个字符以确保调制解调器状态和线路状态确实存在于数据流中。如果打开 LSRMST_INSERT 模式,转义字符之后将会跟随以下数值:

    SERIAL_LSRMST_ESCAPE 表示接收转义字符进入数据流中。

    SERIAL_LSRMST_LSR_DATA 表示一个线路状态发生了改变,并且硬件缓冲区中的值已经被置为有效值。

    SERIAL_LSRMST_LSR_NODATA 表示一个线路状态发生了改变,但在硬件缓冲区中没有有效值可用。

    SERIAL_LSRMST_MST 表示一个调制解调器状态发生了改变。

    lpInBuffer 指向一个有符号的字节变量。

    如果该值不为0,则他表示转义字符。当前操作将会把线路状态和调制解调器状态的LSRMST_INSERT模式打开。

    如果该值为0,当前操作将会把线路状态和调制解调器状态的LSRMST_INSERT模式关闭。

    转义字符不能为XON/XOFF字符。

    lpOutBuffer 无意义,设为NULL。

2、设备管理控制码

    ● 以下控制码用于修改设备

    IOCTL_CHANGER_EXCHANGE_MEDIUM

    暂缺

    IOCTL_CHANGER_GET_ELEMENT_STATUS

    暂缺

    IOCTL_CHANGER_GET_PARAMETERS

    该控制码用于返回指定设备的参数信息。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个 GET_CHANGER_PARAMETERS 结构的指针。

    IOCTL_CHANGER_GET_PRODUCT_DATA

    该控制码用于返回指定设备的产品信息。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个 CHANGER_PRODUCT_DATA 结构的指针。

    IOCTL_CHANGER_GET_STATUS

    该控制码用于返回指定设备当前状态。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_CHANGER_INITIALIZE_ELEMENT_STATUS

    暂缺

    IOCTL_CHANGER_MOVE_MEDIUM

    暂缺

    IOCTL_CHANGER_QUERY_VOLUME_TAGS

    该控制码用于返回指定元件的卷标信息。

    lpInBuffer 指向一个CHANGER_SEND_VOLUME_TAG_INFORMATION 结构的指针。

    lpOutBuffer 指向一个READ_ELEMENT_ADDRESS_INFO 结构的指针。

    IOCTL_CHANGER_REINITIALIZE_TRANSPORT

    暂缺

    IOCTL_CHANGER_SET_ACCESS

    该控制码用于设置设备的输入/输出端口、键区等的状态。

    lpInBuffer 指向一个 CHANGER_SET_ACCESS 结构的指针。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_CHANGER_SET_POSITION

    暂缺

    ● 以下控制码用于设备管理

    IOCTL_STORAGE_CHECK_VERIFY

    该控制码用于确定设备是否是可存取的。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_STORAGE_EJECT_MEDIA

    暂缺

    IOCTL_STORAGE_EJECTION_CONTROL

    暂缺

    IOCTL_STORAGE_GET_HOTPLUG_INFO

    该控制码用于返回指定设备插塞配置。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个 STORAGE_HOTPLUG_INFO 结构的指针。

    IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER

    该控制码用于返回USB设备的序列号。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个 MEDIA_SERIAL_NUMBER_DATA 结构的指针。

    IOCTL_STORAGE_GET_MEDIA_TYPES

    该控制码用于返回设备的几何信息。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个 DISK_GEOMETRY 结构数组的指针。

    IOCTL_STORAGE_GET_MEDIA_TYPES_EX

    该控制码用于返回设备所支持的媒介类型

    lpOutBuffer  无意义,设为NULL。

    lpOutBuffer 指向一个GET_MEDIA_TYPES 结构的指针。

    IOCTL_STORAGE_LOAD_MEDIA

    该控制码用于向设备中载入指定媒介。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_STORAGE_MCN_CONTROL

    该控制码用于打开/关闭媒体改变通知功能,关闭该功能将会阻止GUID_IO_MEDIA_ARRIVAL和GUID_IO_MEDIA_REMOVAL事件。

    lpInBuffer 指向一个Boolean变量的指针,如果为该值为TRUE,则关闭改变通知功能,否则则打开改变通知功能。

    lpOutBuffer  无意义,设为NULL。

    IOCTL_STORAGE_MEDIA_REMOVAL

    暂缺

    IOCTL_STORAGE_SET_HOTPLUG_INFO

    该控制码用设置指定设备的插塞配置。

    lpInBuffer 指向 STORAGE_HOTPLUG_INFO 结构的指针。

    lpOutBuffer  无意义,设为NULL。

3、目录管理控制码

    ● 以下控制码用于文件压缩/解压缩

    FSCTL_GET_COMPRESSION

    获取文件/文件夹的压缩状态(注意目标卷的文件系统是否支持压缩)

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个USHORT变量的指针。该参数可以为以下各值之一:

    COMPRESSION_FORMAT_NONE 文件/文件夹未被压缩

    COMPRESSION_FORMAT_LZNT1 文件/文件夹使用LZNT1f进行了压缩

    all other values 保留

    FSCTL_SET_COMPRESSION

    设置文件/文件夹的压缩状态(注意目标卷的文件系统是否支持压缩)

    lpInBuffer 指向一个USHORT变量的指针。该参数可以为以下各值之一:

    COMPRESSION_FORMAT_NONE 解压缩文件/文件夹

    COMPRESSION_FORMAT_DEFAULT 使用默认压缩算法压缩文件/文件夹

    COMPRESSION_FORMAT_LZNT1 使用LZNT1f压缩算法压缩文件/文件夹

    all other values 保留

    lpOutBuffer 无意义,设为NULL。

    ● 以下控制码用于重解析点(Reparse Point)

    FSCTL_DELETE_REPARSE_POINT

    删除指定文件/文件夹的重解析点,该操作不会将文件/文件夹删除

    lpInBuffer 指向一个REPARSE_GUID_DATA_BUFFER结构的指针。该结构中ReparseTag成员必须是要删除的重解析点的标识、ReparseGuid成员必须是要删除的重解析点的GUID,同时ReparseDataLength成员必须为0。

    lpOutBuffer 无意义,设为NULL。

    FSCTL_GET_REPARSE_POINT

    获取指定文件/文件夹的重解析点

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个用于接收重解析点数据的指针。如果重解析标识是微软的重解析标识,该指针指向一个REPARSE_DATA_BUFFER结构,否则,该指针指向一个 REPARSE_GUID_DATA_BUFFER结构

    FSCTL_SET_REPARSE_POINT

    设置指定文件/文件夹重解析点

    lpInBuffer 指向一个包含有重解析点信息的REPARSE_GUID_DATA_BUFFER结构的指针。

    lpOutBuffer 无意义,设为NULL。

4、磁盘管理控制码

    ● 以下控制码用于磁盘管理

    IOCTL_DISK_CREATE_DISK

    利用CREATE_DISK结构中的信息对指定磁盘和磁盘分区进行初始化。

    lpInBuffer 指向 CREATE_DISK 结构的指针。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_DELETE_DRIVE_LAYOUT

    从主引导记录中删除引导信息,所以磁盘将会被从头到尾的格式化。扇区0中的分区信息也就不复存在了。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_FORMAT_TRACKS

    格式化指定的、连续的软盘磁道。如果需要更多的功能请使用IOCTL_DISK_FORMAT_TRACKS_EX。

    lpInBuffer 指向一个FORMAT_PARAMETERS结构的指针。

    lpOutBuffer 指向一系列BAD_TRACK_NUMBER类型的变量。每个变量都包含有该坏磁道中的磁道数。

    IOCTL_DISK_FORMAT_TRACKS_EX

    格式化指定的、连续的软盘磁道。

    lpInBuffer 指向一个 FORMAT_EX_PARAMETERS结构的指针。

    lpOutBuffer 指向一系列BAD_TRACK_NUMBER类型的变量。每个变量都包含有该坏磁道中的磁道数。

    IOCTL_DISK_GET_CACHE_INFORMATION

    返回磁盘的高速缓存配置数据

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个用于接收高速缓存配置数据的DISK_CACHE_INFORMATION结构。

    IOCTL_DISK_GET_DRIVE_GEOMETRY_EX

    返回物理磁盘的扩展信息。包括:类型、柱面数量、每柱面磁道数、每磁道扇区数和每扇区字节数等。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个用于接收磁盘信息的DISK_GEOMETRY_EX结构。

    IOCTL_DISK_GET_DRIVE_LAYOUT_EX

    返回各分区的扩展信息以及这些分区的特性。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个用于接收磁盘分区信息的缓冲区。更多信息请参照DRIVE_LAYOUT_INFORMATION_EX结构。

    IOCTL_DISK_GET_LENGTH_INFO

    返回指定磁盘/卷/分区的大小信息

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个GET_LENGTH_INFORMATION结构。

    IOCTL_DISK_GET_PARTITION_INFO_EX

    返回指定分区的扩展信息。包括:分区类型、大小和种类。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个用于接收该分区信息的缓冲区。更多信息请参照PARTITION_INFORMATION_EX结构。

    IOCTL_DISK_GROW_PARTITION

    扩大指定分区。

    lpInBuffer 指向一个DISK_GROW_PARTITION结构。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_IS_WRITABLE

    确定指定磁盘是否可写。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_PERFORMANCE

    启用并获取磁盘性能统计

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 指向一个DISK_PERFORMANCE结构。

    IOCTL_DISK_PERFORMANCE_OFF

    关闭磁盘性能统计

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_REASSIGN_BLOCKS

    使磁盘设备影射一块区域做为它的备用存储块公用池(spare block pool)。

    lpInBuffer 指向一个REASSIGN_BLOCKS结构。该结包含有重新分配存储块公用池所需的信息。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_SET_CACHE_INFORMATION

    设置磁盘的配置信息

    lpInBuffer 指向一个DISK_CACHE_INFORMATION结构的指针。

    lpOutBuffer 指向一个DISK_CACHE_INFORMATION结构的指针。

    IOCTL_DISK_SET_DRIVE_LAYOUT_EX

    根据给定的磁盘信息对磁盘进行分区。

    lpInBuffer 指向一个包含有磁盘分区信息的DRIVE_LAYOUT_INFORMATION_EX结构。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_SET_PARTITION_INFO_EX

    设置指定分区的分区信息。包括AT和EFI (Extensible Firmware Interface)分区的布局信息。

    lpInBuffer 指向一个包含有分区信息的PARTITION_INFORMATION_EX结构。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_UPDATE_PROPERTIES

    使缓冲的分区表无效并重新获取一份。

    lpInBuffer 无意义,设为NULL。

    lpOutBuffer 无意义,设为NULL。

    IOCTL_DISK_VERIFY

    对指定磁盘进行逻辑格式化

    lpInBuffer 指向一个VERIFY_INFORMATION结构。

    lpOutBuffer 无意义,设为NULL。

    ● 以下控制码用于磁盘碎片整理

    FSCTL_GET_RETRIEVAL_POINTERS

    获取指定文件磁盘上被分配的存储单元以及其位置。

    lpInBuffer 指向一个STARTING_VCN_INPUT_BUFFER结构。

    lpOutBuffer 指向一个RETRIEVAL_POINTERS_BUFFER结构。注意该结构大小是可变的。

    FSCTL_GET_VOLUME_BITMAP

    返回一个用于描述指定卷的已用空间和可用空间的位图。

    lpInBuffer 指向一个STARTING_LCN_INPUT_BUFFER结构。开始的LCN在输出缓冲区中有可能会被四舍五入。

    lpOutBuffer 指向一个VOLUME_BITMAP_BUFFER结构。注意该结构大小是可变的。

    FSCTL_MOVE_FILE

    在同一卷内移动、整理指定文件。该操作在整理碎片时使用。

    lpInBuffer 指向一个MOVE_FILE_DATA结构。

    lpOutBuffer 无意义,设为NULL。

    以下是已经废弃的控制码,忽略

    IOCTL_DISK_CONTROLLER_NUMBER

    IOCTL_DISK_GET_DRIVE_GEOMETRY

    IOCTL_DISK_GET_DRIVE_LAYOUT

    IOCTL_DISK_GET_PARTITION_INFO

    IOCTL_DISK_HISTOGRAM_DATA

    IOCTL_DISK_HISTOGRAM_RESET

    IOCTL_DISK_HISTOGRAM_STRUCTURE

    IOCTL_DISK_LOGGING

    IOCTL_DISK_REQUEST_DATA

    IOCTL_DISK_REQUEST_STRUCTURE

    IOCTL_DISK_SET_DRIVE_LAYOUT

    IOCTL_DISK_SET_PARTITION_INFO

给我留言

留言无头像?