DeviceIoControl使用教程

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

实战DeviceIoControl之一:通过API访问设备驱动程序Q在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数、读写绝对扇区数据、测试光驱实际速度等,该从哪里入手呢?A在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问—获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就可以达到我们的目的。DeviceIoControl的函数原型为BOOLDeviceIoControl(HANDLEhDevice,//设备句柄DWORDdwIoControlCode,//控制码LPVOIDlpInBuffer,//输入数据缓冲区指针DWORDnInBufferSize,//输入数据缓冲区长度LPVOIDlpOutBuffer,//输出数据缓冲区指针DWORDnOutBufferSize,//输出数据缓冲区长度LPDWORDlpBytesReturned,//输出数据实际长度单元长度LPOVERLAPPEDlpOverlapped//重叠操作结构指针);设备句柄用来标识你所访问的设备。发送不同的控制码,可以调用设备驱动程序的不同类型的功能。在头文件winioctl.h中,预定义的标准设备控制码,都以IOCTL或FSCTL开头。例如,IOCTL_DISK_GET_DRIVE_GEOMETRY是对物理驱动器取结构参数(介质类型、柱面数、每柱面磁道数、每磁道扇区数等)的控制码,FSCTL_LOCK_VOLUME是对逻辑驱动器的卷加锁的控制码。输入输出数据缓冲区是否需要,是何种结构,以及占多少字节空间,完全由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备预定义了一些输入输出数据结构。重叠操作结构指针设置为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计。Q设备句柄是从哪里获得的?A设备句柄可以用API函数CreateFile获得。它的原型为HANDLECreateFile(LPCTSTRlpFileName,//文件名/设备路径DWORDdwDesiredAccess,//访问方式DWORDdwShareMode,//共享方式LPSECURITY_ATTRIBUTESlpSecurityAttributes,//安全描述符指针DWORDdwCreationDisposition,//创建方式DWORDdwFlagsAndAttributes,//文件属性及标志HANDLEhTemplateFile//模板文件的句柄);CreateFile这个函数用处很多,这里我们用它“打开”设备驱动程序,得到设备的句柄。操作完成后用CloseHandle关闭设备句柄。与普通文件名有所不同,设备驱动的“文件名”(常称为“设备路径”)形式固定为“//./DeviceName”(注意在C程序中该字符串写法为“////.//DeviceName”),DeviceName必须与设备驱动程序内定义的设备名称一致。一般地,调用CreateFile获得设备句柄时,访问方式参数设置为0或GENERIC_READ|GENERIC_WRITE,共享方式参数设置为FILE_SHARE_READ|FILE_SHARE_WRITE,创建方式参数设置为OPEN_EXISTING,其它参数设置为0或NULL。Q可是,我怎么知道设备名称是什么呢?A一些存储设备的名称是微软定义好的,不可能有什么变化。大体列出如下软盘驱动器A:,B:硬盘逻辑分区C:,D:,E:,...物理驱动器PHYSICALDRIVExCD-ROM,DVD/ROMCDROMx磁带机TAPEx其中,物理驱动器不包括软驱和光驱。逻辑驱动器可以是IDE/SCSI/PCMCIA/USB接口的硬盘分区(卷)、光驱、MO、CF卡等,甚至是虚拟盘。x=0,1,2……其它的设备名称需通过驱动接口的GUID调用设备管理函数族取得,这里暂不讨论。Q请举一个简单的例子说明如何通过DeviceIoControl访问设备驱动程序。A这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中如何通过DeviceIoControl获取硬盘的基本参数。/*ThecodeofinterestisinthesubroutineGetDriveGeometry.ThecodeinmainshowshowtointerprettheresultsoftheIOCTLcall.*/#includewindows.h#includewinioctl.hBOOLGetDriveGeometry(DISK_GEOMETRY*pdg){HANDLEhDevice;//handletothedrivetobeexaminedBOOLbResult;//resultsflagDWORDjunk;//discardresultshDevice=CreateFile(////.//PhysicalDrive0,//drivetoopen0,//noaccesstothedriveFILE_SHARE_READ|//sharemodeFILE_SHARE_WRITE,NULL,//defaultsecurityattributesOPEN_EXISTING,//disposition0,//fileattributesNULL);//donotcopyfileattributesif(hDevice==INVALID_HANDLE_VALUE)//cannotopenthedrive{return(FALSE);}bResult=DeviceIoControl(hDevice,//devicetobequeriedIOCTL_DISK_GET_DRIVE_GEOMETRY,//operationtoperformNULL,0,//noinputbufferpdg,sizeof(*pdg),//outputbuffer&junk,//#bytesreturned(LPOVERLAPPED)NULL);//synchronousI/OCloseHandle(hDevice);return(bResult);}intmain(intargc,char*argv[]){DISK_GEOMETRYpdg;//diskdrivegeometrystructureBOOLbResult;//genericresultsflagULONGLONGDiskSize;//sizeofthedrive,inbytesbResult=GetDriveGeometry(&pdg);if(bResult){printf(Cylinders=%I64d/n,pdg.Cylinders);printf(Trackspercylinder=%ld/n,(ULONG)pdg.TracksPerCylinder);printf(Sectorspertrack=%ld/n,(ULONG)pdg.SectorsPerTrack);printf(Bytespersector=%ld/n,(ULONG)pdg.BytesPerSector);DiskSize=pdg.Cylinders.QuadPart*(ULONG)pdg.TracksPerCylinder*(ULONG)pdg.SectorsPerTrack*(ULONG)pdg.BytesPerSector;printf(Disksize=%I64d(Bytes)=%I64d(Mb)/n,DiskSize,DiskSize/(1024*1024));}else{printf(GetDriveGeometryfailed.Error%ld./n,GetLastError());}return((int)bResult);}Q如果将设备名换成“A:”就可以取A盘参数,换成“CDROM0”就可以取CDROM参数,是这样吗?A这个问题暂不做回答。请动手试一下。现在我们总结一下通过DeviceIoControl访问设备驱动程序的“三步曲”:首先用CreateFile取得设备句柄,然后用DeviceIoControl与设备进行I/O,最后别忘记用CloseHandle关闭设备句柄。实战DeviceIoControl之二:获取软盘/硬盘/光盘的参数Q在MSDN的那个demo中,将设备名换成“A:”取A盘参数,先用资源管理器读一下盘,再运行这个程序可以成功,但换一张盘后就失败;换成“CDROM0”取CDROM参数,无论如何都不行。这个问题如何解决呢?A取软盘参数是从软盘上读取格式化后的信息,也就是必须执行读操作,这一点与硬盘不同。将CreateFile中的访问方式改为GENERIC_READ就行了。IOCTL_DISK_GET_DRIVE_GEOMETRY这个I/O控制码,对软盘和硬盘有效,但对一些可移动媒介如CD/DVD-ROM、TAPE等就不管用了。要取CDROM参数,还得另辟蹊径。IOCTL_STORAGE_GET_MEDIA_TYPES_EX能够帮我们解决问题。Q使用这些I/O控制码,需要什么样的输入输出数据格式呢?ADeviceIoControl使用这两个控制码时,都不需要输入数据。IOCTL_DISK_GET_DRIVE_GEOMETRY直接输出一个DISK_GEOMETRY结构:typedefstruct_DISK_GEOMETRY{LARGE_INTEGERCylinders;//柱面数MEDIA_TYPEMediaType;//介质类型DWORDTracksPerCylinder;//每柱面的磁道数DWORDSectorsPerTrack;//每磁道的扇区数DWORDBytesPerSector;//每扇区的字节数}DISK_GEOMETRY;IOCTL_STORAGE_GET_MEDIA_TYPES_EX输出一个GET_MEDIA_TYPES结构:typedefstruct_GET_MEDIA_TYPES{DWORDDeviceType;//设备类型DWORDMediaInfoCount;//介质信息条数DEVICE_MEDIA_INFOMediaInfo[1];//介质信息}GET_MEDIA_TYPES;让我们来看一下DEVICE_MEDIA_INFO结构的定义:typedefstruct_DEVICE_MEDIA_INFO{union{struct{LARGE_INTEGERCylinders;//柱面数STORAGE_MEDIA_TYPEMediaType;//介质类型DWORDTracksPerCylinder;//每柱面的磁道数DWORDSectorsPerTrack;//每磁道的扇区数DWORDBytesPerSector;//每扇区的字节数DWORDNumberMediaSides;//介质面数DWORDMediaCharacteristics;//介质特性}DiskInfo;//硬盘信息struct{LARGE_INTEGERCylinders;//柱面数STORAGE_MEDIA_TYPEMediaType;//介质类型DWORDTracksPerCylinder;//每柱面的磁道数DWORDSectorsPerTrack;//每磁道的扇区数DWORDBytesPerSector;//每扇区的字节数DWORDNumberMediaSides;//介质面数DWORDMediaCharacteristics;//介质特性}RemovableDiskInfo;//“可移动盘”信息struct{STORAGE_MEDIA_TYPEMediaType;//介质类型DWORDMediaCharacteristics;//介质特性DWORDCurrentBlockSize;//块的大小}TapeInfo;//磁带信息}DeviceS

1 / 46
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功