ImageVerifierCode 换一换
格式:DOCX , 页数:67 ,大小:49.25KB ,
资源ID:7915549      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7915549.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(实战DeviceIoControl.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

实战DeviceIoControl.docx

1、实战DeviceIoControl实战DeviceIoControl 之一:通过API访问设备驱动程序Q 在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数、读写绝对扇区数据、测试光驱实际速度等,该从哪里入手呢? A 在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就可以达到我们的目的。 DeviceIoControl的函数原型为 BOOL DeviceIoControl( HANDLE hDevice, / 设备

2、句柄 DWORD dwIoControlCode, / 控制码 LPVOID lpInBuffer, / 输入数据缓冲区指针 DWORD nInBufferSize, / 输入数据缓冲区长度 LPVOID lpOutBuffer, / 输出数据缓冲区指针 DWORD nOutBufferSize, / 输出数据缓冲区长度 LPDWORD lpBytesReturned, / 输出数据实际长度单元长度 LPOVERLAPPED lpOverlapped / 重叠操作结构指针);设备句柄用来标识你所访问的设备。 发送不同的控制码,可以调用设备驱动程序的不同类型的功能。在头文件winioctl.h中

3、,预定义的标准设备控制码,都以IOCTL或FSCTL开头。例如,IOCTL_DISK_GET_DRIVE_GEOMETRY是对物理驱动器取结构参数(介质类型、柱面数、每柱面磁道数、每磁道扇区数等)的控制码,FSCTL_LOCK_VOLUME是对逻辑驱动器的卷加锁的控制码。 输入输出数据缓冲区是否需要,是何种结构,以及占多少字节空间,完全由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备预定义了一些输入输出数据结构。重叠操作结构指针设置为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计。 Q 设备句柄是从哪里获得的? A 设备句柄可

4、以用API函数CreateFile获得。它的原型为 HANDLE CreateFile( LPCTSTR lpFileName, / 文件名/设备路径 DWORD dwDesiredAccess, / 访问方式 DWORD dwShareMode, / 共享方式 LPSECURITY_ATTRIBUTES lpSecurityAttributes, / 安全描述符指针 DWORD dwCreationDisposition, / 创建方式 DWORD dwFlagsAndAttributes, / 文件属性及标志 HANDLE hTemplateFile / 模板文件的句柄);CreateFi

5、le这个函数用处很多,这里我们用它“打开”设备驱动程序,得到设备的句柄。操作完成后用CloseHandle关闭设备句柄。 与普通文件名有所不同,设备驱动的“文件名”(常称为“设备路径”)形式固定为“.DeviceName”(注意在C程序中该字符串写法为“.DeviceName”),DeviceName必须与设备驱动程序内定义的设备名称一致。 一般地,调用CreateFile获得设备句柄时,访问方式参数设置为0或GENERIC_READ|GENERIC_WRITE,共享方式参数设置为FILE_SHARE_READ|FILE_SHARE_WRITE,创建方式参数设置为OPEN_EXISTING,其

6、它参数设置为0或NULL。 Q 可是,我怎么知道设备名称是什么呢? A 一些存储设备的名称是微软定义好的,不可能有什么变化。大体列出如下 软盘驱动器 A:, B: 硬盘逻辑分区 C:, D:, E:, . 物理驱动器 PHYSICALDRIVEx CD-ROM, DVD/ROM CDROMx 磁带机 TAPEx 其中,物理驱动器不包括软驱和光驱。逻辑驱动器可以是IDE/SCSI/PCMCIA/USB接口的硬盘分区(卷)、光驱、MO、CF卡等,甚至是虚拟盘。x=0,1,2 其它的设备名称需通过驱动接口的GUID调用设备管理函数族取得,这里暂不讨论。 Q 请举一个简单的例子说明如何通过Device

7、IoControl访问设备驱动程序。 A 这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中如何通过DeviceIoControl获取硬盘的基本参数。 /* The code of interest is in the subroutine GetDriveGeometry. The code in main shows how to interpret the results of the IOCTL call. */ #include #include BOOL GetDriveGeometry(DISK_GEOMETRY *pdg) HANDLE hDevice;

8、/ handle to the drive to be examined BOOL bResult; / results flag DWORD junk; / discard results hDevice = CreateFile(.PhysicalDrive0, / drive to open 0, / no access to the drive FILE_SHARE_READ | / share mode FILE_SHARE_WRITE, NULL, / default security attributes OPEN_EXISTING, / disposition 0, / fil

9、e attributes NULL); / do not copy file attributes if (hDevice = INVALID_HANDLE_VALUE) / cannot open the drive return (FALSE); bResult = DeviceIoControl(hDevice, / device to be queried IOCTL_DISK_GET_DRIVE_GEOMETRY, / operation to perform NULL, 0, / no input buffer pdg, sizeof(*pdg), / output buffer

10、&junk, / # bytes returned (LPOVERLAPPED) NULL); / synchronous I/O CloseHandle(hDevice); return (bResult); int main(int argc, char *argv) DISK_GEOMETRY pdg; / disk drive geometry structure BOOL bResult; / generic results flag ULONGLONG DiskSize; / size of the drive, in bytes bResult = GetDriveGeometr

11、y (&pdg); if (bResult) printf(Cylinders = %I64dn, pdg.Cylinders); printf(Tracks per cylinder = %ldn, (ULONG) pdg.TracksPerCylinder); printf(Sectors per track = %ldn, (ULONG) pdg.SectorsPerTrack); printf(Bytes per sector = %ldn, (ULONG) pdg.BytesPerSector); DiskSize = * (ULONG)pdg.TracksPerCylinder *

12、 (ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector; printf(Disk size = %I64d (Bytes) = %I64d (Mb)n, DiskSize, DiskSize / (1024 * 1024); else printf(GetDriveGeometry failed. Error %ld.n, GetLastError(); return (int)bResult);Q 如果将设备名换成“A:”就可以取A盘参数,换成“CDROM0”就可以取CDROM参数,是这样吗? A 这个问题暂不做回答。请动手试一下。 现

13、在我们总结一下通过DeviceIoControl访问设备驱动程序的“三步曲”:首先用CreateFile取得设备句柄,然后用DeviceIoControl与设备进行I/O,最后别忘记用CloseHandle关闭设备句柄。实战DeviceIoControl 之二:获取软盘/硬盘/光盘的参数Q 在MSDN的那个demo中,将设备名换成“A:”取A盘参数,先用资源管理器读一下盘,再运行这个程序可以成功,但换一张盘后就失败;换成“CDROM0”取CDROM参数,无论如何都不行。这个问题如何解决呢? A 取软盘参数是从软盘上读取格式化后的信息,也就是必须执行读操作,这一点与硬盘不同。将CreateFil

14、e中的访问方式改为GENERIC_READ就行了。 IOCTL_DISK_GET_DRIVE_GEOMETRY这个I/O控制码,对软盘和硬盘有效,但对一些可移动媒介如CD/DVD-ROM、TAPE等就不管用了。要取CDROM参数,还得另辟蹊径。IOCTL_STORAGE_GET_MEDIA_TYPES_EX能够帮我们解决问题。 Q 使用这些I/O控制码,需要什么样的输入输出数据格式呢? A DeviceIoControl使用这两个控制码时,都不需要输入数据。 IOCTL_DISK_GET_DRIVE_GEOMETRY直接输出一个DISK_GEOMETRY结构: typedef struct _

15、DISK_GEOMETRY LARGE_INTEGER Cylinders; / 柱面数 MEDIA_TYPE MediaType; / 介质类型 DWORD TracksPerCylinder; / 每柱面的磁道数 DWORD SectorsPerTrack; / 每磁道的扇区数 DWORD BytesPerSector; / 每扇区的字节数 DISK_GEOMETRY;IOCTL_STORAGE_GET_MEDIA_TYPES_EX输出一个GET_MEDIA_TYPES结构: typedef struct _GET_MEDIA_TYPES DWORD DeviceType; / 设备类型

16、DWORD MediaInfoCount; / 介质信息条数 DEVICE_MEDIA_INFO MediaInfo1; / 介质信息 GET_MEDIA_TYPES;让我们来看一下DEVICE_MEDIA_INFO结构的定义: typedef struct _DEVICE_MEDIA_INFO union struct LARGE_INTEGER Cylinders; / 柱面数 STORAGE_MEDIA_TYPE MediaType; / 介质类型 DWORD TracksPerCylinder; / 每柱面的磁道数 DWORD SectorsPerTrack; / 每磁道的扇区数 DW

17、ORD BytesPerSector; / 每扇区的字节数 DWORD NumberMediaSides; / 介质面数 DWORD MediaCharacteristics; / 介质特性 DiskInfo; / 硬盘信息 struct LARGE_INTEGER Cylinders; / 柱面数 STORAGE_MEDIA_TYPE MediaType; / 介质类型 DWORD TracksPerCylinder; / 每柱面的磁道数 DWORD SectorsPerTrack; / 每磁道的扇区数 DWORD BytesPerSector; / 每扇区的字节数 DWORD Number

18、MediaSides; / 介质面数 DWORD MediaCharacteristics; / 介质特性 RemovableDiskInfo; / “可移动盘”信息 struct STORAGE_MEDIA_TYPE MediaType; / 介质类型 DWORD MediaCharacteristics; / 介质特性 DWORD CurrentBlockSize; / 块的大小 TapeInfo; / 磁带信息 DeviceSpecific; DEVICE_MEDIA_INFO;其中CD-ROM属于“可移动盘”的范围。请注意,GET_MEDIA_TYPES结构本身只定义了一条DEVICE

19、_MEDIA_INFO,额外的DEVICE_MEDIA_INFO需要紧接此结构的另外的空间。 Q 调用方法我了解了,请用VC举个例子来实现我所期待已久的功能吧? A 好,现在就演示一下如何取软盘/硬盘/光盘的参数。测试时,记得要有软盘/光盘插在驱动器里喔! 首先,用MFC AppWizard生成一个单文档的应用程序,取名为DiskGeometry,让它的View基于CEditView。 然后,添加以下的.h和.cpp文件。 / GetDiskGeometry.h/ #if !defined(GET_DISK_GEOMETRY_H_)#define GET_DISK_GEOMETRY_H_ #i

20、f _MSC_VER 1000#pragma once#endif / _MSC_VER 1000 #include BOOL GetDriveGeometry(const char* filename, DISK_GEOMETRY *pdg); #endif / !defined(GET_DISK_GEOMETRY_H_) / GetDiskGeometry.cpp/ #include stdafx.h#include GetDiskGeometry.h / IOCTL_STORAGE_GET_MEDIA_TYPES_EX可能返回不止一条DEVICE_MEDIA_INFO,故定义足够的空间#

21、define MEDIA_INFO_SIZE sizeof(GET_MEDIA_TYPES)+15*sizeof(DEVICE_MEDIA_INFO) / filename - 用于设备的文件名/ pdg - 参数缓冲区指针BOOL GetDriveGeometry(const char* filename, DISK_GEOMETRY *pdg) HANDLE hDevice; / 设备句柄 BOOL bResult; / DeviceIoControl的返回结果 GET_MEDIA_TYPES *pmt; / 内部用的输出缓冲区 DWORD dwOutBytes; / 输出数据长度 / 打

22、开设备 hDevice = :CreateFile(filename, / 文件名 GENERIC_READ, / 软驱需要读盘 FILE_SHARE_READ | FILE_SHARE_WRITE, / 共享方式 NULL, / 默认的安全描述符 OPEN_EXISTING, / 创建方式 0, / 不需设置文件属性 NULL); / 不需参照模板文件 if (hDevice = INVALID_HANDLE_VALUE) / 设备无法打开. return FALSE; / 用IOCTL_DISK_GET_DRIVE_GEOMETRY取磁盘参数 bResult = :DeviceIoCont

23、rol(hDevice, / 设备句柄 IOCTL_DISK_GET_DRIVE_GEOMETRY, / 取磁盘参数 NULL, 0, / 不需要输入数据 pdg, sizeof(DISK_GEOMETRY), / 输出数据缓冲区 &dwOutBytes, / 输出数据长度 (LPOVERLAPPED)NULL); / 用同步I/O / 如果失败,再用IOCTL_STORAGE_GET_MEDIA_TYPES_EX取介质类型参数 if (!bResult) pmt = (GET_MEDIA_TYPES *)new BYTEMEDIA_INFO_SIZE; bResult = :DeviceIo

24、Control(hDevice, / 设备句柄 IOCTL_STORAGE_GET_MEDIA_TYPES_EX, / 取介质类型参数 NULL, 0, / 不需要输入数据 pmt, MEDIA_INFO_SIZE, / 输出数据缓冲区 &dwOutBytes, / 输出数据长度 (LPOVERLAPPED)NULL); / 用同步I/O if (bResult) / 注意到结构DEVICE_MEDIA_INFO是在结构DISK_GEOMETRY的基础上扩充的 / 为简化程序,用memcpy代替如下多条赋值语句: / pdg-MediaType = (MEDIA_TYPE)pmt-MediaI

25、nfo0.; / pdg-Cylinders = pmt-MediaInfo0.; / pdg-TracksPerCylinder = pmt-MediaInfo0.; / . . :memcpy(pdg, pmt-MediaInfo, sizeof(DISK_GEOMETRY); delete pmt; / 关闭设备句柄 :CloseHandle(hDevice); return (bResult);然后,在Toolbar的IDR_MAINFRAME上添加一个按钮,ID为ID_GET_DISK_GEOMETRY。打开ClassWizard,在DiskGeometryView中 添加ID_GET_DISK_GEOMETRY的映射函数OnGetDiskGeometry。打开DiskGeometryView.cpp,包含头文件GetDiskGeometry.h。 在OnGetDiskGeometry中,添加以下代码 const char *szDevName= .A:, .B:, .PhysicalDrive0, .PhysicalDrive1, .PhysicalDrive2, .PhysicalDrive3,

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1