全部博文(584)
分类: WINDOWS
2011-03-29 16:30:25
WDM驱动程序开发之应用程序测试篇CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle.
时间 : 2008-03-24 作者:佚名 编辑:本站 点击: 4813 [ 评论 ]
【Return Values】
调用如果成功,返回值时一个打开文件的句柄。
如果调用之前文件已存在,且dwCreationDisposetion 为CREATE_ALWAYS或OPEN_ALWAYS,用GetLastError返回ERROR_ALREADY_EXISTS。
(即使调用成功也会返回这个值)。如果调用之前不存在,GetLastError返回0。
调用如果失败,返回值是INVALID_HANDLE_VALUE。要进一步了解出错原因,调用GetLastError。
【Remarks】
在Windows 2000/XP平台上:
如果你企图打开一个远程机器上的文件或目录,dwDesiredAccess设置为DELETE或者任一其他的控制标志,
而这时远程文件或目录还没有以FILE_SHARE_DELETE的方式打开的话,你的函数调用就会发生共享错误了。
为了避免共享错误,一种办法是单独用DELETE方式打开远程文件或目录,另一种方法是在打开文件或目录之前先调用DeleteFile函数。
如果dwCreationDisposition 参数指定为CREATE_ALWAYS 并且dwFlagsAndAttributes
参数指定为FILE_ATTRIBUTE_NORMAL
的话,CreateFile调用将失败,GetLastError报告的错误是ACCESS_DENIED。这时,把
dwFlagsAndAttributes
参数设置为FILE_ATTRIBUTE_HIDDEN和FILE_ATTRIBUTE_NORMAL的联合值,将避免这个问题。
二、*****CloseHandle*****
用于关掉一个打开的对象句柄。
函数原型:
BOOL CloseHandle(
HANDLE hObject // handle to object
);
【Return Values】
函数调用成功返回非零,失败返回0。获得更多错误信息,需要调用GetLastError函数。
在Windows NT/2000/XP平台上:当应用程序在调试器下运行时,关闭一个不合法的句柄将产生一个异常(Exception)。包括两次关闭同一个句柄,或者试图关闭一个由FindFirstFile函数返回的句柄,都会产生异常。
【Remarks】
CloseHandle使指定的句柄无效,减少对象的句柄计数,进行对象保持检验。当对象的最后一个句柄关闭时,对象将从系统中删除。关闭一个线程句柄并
不会终止一个线程,要释放一个线程对象,必须terminate线程,然后关闭所有的线程句柄。用CloseHandle只能关闭由CreateFile
函数返回的句柄。用FindClose来关闭由FindFirstFile返回的句柄。
三、*****ReadFile*****
ReadFile函数从文件指针指定的位置读取数据。读操作完成后,文件指针将根据实际读出的数据自动进行调整,除非文件句柄是以OVERLAPPED属性值打开的。如果是以OVERLAPPED打开的I/O,应用程序就需要自己手动调整文件指针。
这个函数被设计成兼有同步和异步操作。ReadFileEx函数则设计成只支持异步操作,异步操作允许应用程序在读文件期间可以同时进行其他的操作。
函数原型:
BOOL ReadFile(
HANDLE hFile, // handle to file
LPVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // number of bytes read
LPOVERLAPPED lpOverlapped // overlapped buffer
);
【Parameters】
1、hFile
文件句柄(必须具有GENERIC_READ访问权限)。
在Windows NT/2000/XP平台上:对于异步读操作,hFile可以是由CreateFile函数以FILE_FLAG_OVERLAPPED方式打开的任何句柄,或者一个由socket或accept函数返回的socket句柄。
在Windows 95/98/Me平台上:对于邮槽、命名管道和磁盘文件不能使用异步读操作。
2、lpBuffer
用来接收从文件中读出的数据的缓冲区指针。
3、nNumberOfBytesToRead
指明要读的字节总数。
4、lpNumberOfBytesRead
一个变量指针,用来存储实际传输的字节总数。ReadFile在做所有事情(包括错误检查)之前,先将这个值赋为0。当ReadFile从一个命名管道上
返回TRUE时这个参数为0,说明消息管道另一端调用WriteFile时设置的nNumberOfBytesToWrite 参数为0。
在Windows NT/2000/XP平台上:如果lpOverlapped
为NULL,则lpNumberOfBytesRead不能为NULL。如果lpOverlapped
不是NULL,lpNumberOfBytesRead可以设为NULL。如果是一个overlapped形式的读操作,我们可以动用
GetOverlappedResult函数来获得传输的实际字节数。如果hFile关联的是一个完成端口(I/O completion
port),那么可以调用GetQueuedCompletionStatus函数来获得传输的实际字节数。
如果完成端口(I/O
completion
port)被占用,而你用的是一个用于释放内存的回调例程,对于lpOverlapped参数指向的OVERLAPPED结构体来说,为这个参数指定
NULL可以避免重新分配内存时发生内存泄漏。内存泄漏会导致返回这个参数值时是一个非法值。
Windows 95/98/Me平台上:这个参数不允许为NULL。
5、lpOverlapped
一个指向OVERLAPPED结构体的指针。如果hFile是以FILE_FLAG_OVERLAPPED方式获得的句柄,这个结构是必须的,不能为
NULL。(否则函数会在错误的时刻报告读操作已经完成了)。这时,读操作在由OVERLAPPED中Offset成员指定的偏移地址开始读,并且在实际
完成读操作之前就返回了。在这种情况下,ReadFile返回FALSE,GerLastError报告从错误类型是ERROR_IO_PENDING。
这允许调用进程继续其他工作直到读操作完成。OVERLAPPED结构中的事件将会在读操作完成时被使能。
如果hFile不是以FILE_FLAG_OVERLAPPED方式获得的句柄,并且lpOverlapped为NULL,读操作就从当前文件的开始位置读起,直到读操作完成ReadFile函数才能返回。
在Windows
NT/2000/XP平台上:如果hFile不是以FILE_FLAG_OVERLAPPED方式获得的句柄,并且lpOverlapped不为
NULL,则读操作在由OVERLAPPED中Offset成员指定的偏移地址开始读,直到读操作完成ReadFile函数才能返回。
在Windows 95/98/Me平台上:对于文件、磁盘、管道和邮槽的操作,这个参数必须为NULL。一个不为空的OVERLAPPED结构体指针将导致调用失败。Windows 95/98/Me平台只支持串行口和并行口的overlapped 读写。
【Return Values】
有如下任一种情况发生都会导致函数返回:(1)在管道另一端的写操作完成后(2)请求的字节数传输完毕(3)发生错误。
如果函数正确,返回非零。
如果返回值是非零,但接收的字节数是0,那么可能是文件指针在读操作期间超出了文件的end位置。然而,如果文件以FILE_FLAG_OVERLAPPED方式打开,lpOverlappe
WDM驱动程序开发之应用程序测试篇CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle.
时间 : 2008-03-24 作者:佚名 编辑:本站 点击: 4814 [ 评论 ]
【Remarks】
如果文件的一部分被另一个进程锁定,而当前进程试图重复锁定,那将会失败。
一个应用程序在读以FILE_FLAG_NO_BUFFERING方式打开的文件时要符合一定的条件。
(1)文件读的开始地址必须是扇区大小的整数倍。GetDiskFreeSpace函数可以取得扇区的大小。
(2)请求读的字节数也必须是扇区大小的整数倍。
(3)用于读写操作的Buffer地址必须按照扇区大小进行边界对齐。可以通过用VirtualAlloc 函数申请内存来做到。
在读操作期间试图访问相应的输入缓冲区,会导致读入到缓冲区的数据损坏。读操作完成之前,应用程序不能对这段输入缓冲区做任何操作(包括读、写、重新分配内存,释放内存等)。
ReadFile可以通过指向控制台输入对象的句柄将控制台的输入字符读出来。控制台的模式决定了ReadFile的具体行为。
如果一个命名管道正在以消息模式被读取,并且下一条消息比nNumberOfBytesToRead参数指定的长度还大,那么ReadFile将返回
FALSE并且GetLastError返回错误为ERROR_MORE_DATA。剩下没读完的消息可能会被随后的ReadFile或
PeckNamedPipe函数读出。
读取一个通信设备时,ReadFile的行为被当前的通信延时所支配,延时属性的设置和取得使用SetCommTimeouts和GetCommTimeouts函数。如果你设置延时属性失败,就会得到不可预知的结果。
如果ReadFile试图读取一个buffer太小的邮槽,将会返回FALSE并且GetLastError返回错误为ERROR_INSUFFICIENT_BUFFER 。
如果一个匿名的写管道句柄已经关闭,而ReadFile试图用响应的匿名权限读这个管道句柄,将返回FALSE并且
GetLastError返回错误为ERROR_BROKEN_PIPE。
每当有太多的异步I/O请求得不到响应,ReadFile就会失败,并返回ERROR_INVALID_USER_BUFFER或ERROR_NOT_ENOUGH_MEMORY的错误。
在同步和异步两种情况下,ReadFile中检测EOF(文件结尾边界)的代码是不同的。当一个同步读操作到达文件结尾时,ReadFile返回
TRUE,并设置*lpNumberOfBytesRead 为0
。异步读操作会在开始调用的读操作中或者随后的其他异步操作中突然遇到文件结尾。(1)如果EOF在ReadFile期间被检测到,将会返回FALSE,
且 GetLastError返回错误描述
ERROR_HANDLE_EOF。(2)如果EOF在随后的其他异步操作中被检测到,则类似GetOverlappedResult
等试图获取操作结果的函数返回FALSE,且 GetLastError返回错误描述ERROR_HANDLE_EOF。
为了取消未响应的异步I/O操作,用CancelIo函数。这个函数只能取消由调用进程对特定句柄进行的操作。被取消的I/O操作将被描述为ERROR_OPERATION_ABORTED。
如果你正试图从并不存在的软驱中读数据,系统会弹出消息框提示你重新操作。为了阻止系统的消息框,调用函数SetErrorMode,参数设置为SEM_NOOPENFILEERRORBOX。
四、*****WriteFile*****
可以以同步或异步方式向一个对象句柄中写数据
函数原型:
BOOL WriteFile(
HANDLE hFile, // handle to file
LPCVOID lpBuffer, // data buffer
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // number of bytes written
LPOVERLAPPED lpOverlapped // overlapped buffer
);
其他信息与ReadFile极其相似,可参考上文ReadFile的翻译。
五、*****DeviceIoControl*****
这个函数直接向指定的设备驱动程序发送控制码,使响应的设备产生响应的操作。
函数原型:
BOOL DeviceIoControl(
HANDLE hDevice, // handle to device
DWORD dwIoControlCode, // operation
LPVOID lpInBuffer, // input data buffer
DWORD nInBufferSize, // size of input data buffer
LPVOID lpOutBuffer, // output data buffer
DWORD nOutBufferSize, // size of output data buffer
LPDWORD lpBytesReturned, // byte count
LPOVERLAPPED lpOverlapped // overlapped information
);
【Parameters】
(1)hDevice(输入)
用CreateFile获得的设备句柄,典型的设备对象有卷、目录、文件、交替的流等。
(2)dwIoControlCode(输入)
指定操作码。这个值区别特定的操作和设备对象的类型。
IOCTL_DISK_CREATE_DISK 用特定的信息初始化指定的磁盘和磁盘分区表
IOCTL_DISK_FORMAT_TRACKS 格式化一组连续的磁道
IOCTL_DISK_GET_DRIVE_GEOMETRY 获取关于物理磁盘几何属性的信息
IOCTL_DISK_GET_DRIVE_GEOMETRY_EX 获取关于物理磁盘几何属性的信息
IOCTL_DISK_GET_DRIVE_LAYOUT_EX 获取一个磁盘的分区数量和每个分区的特征信息
IOCTL_DISK_GET_LENGTH_INFO 获得指定磁盘、卷、分区的长度
IOCTL_DISK_GET_PARTITION_INFO_EX 获取自动变速(AT)分区和可扩展固件接口(EFI)分区的分区信息
IOCTL_DISK_PERFORMANCE 提供磁盘性能信息
IOCTL_DISK_REASSIGN_BLOCKS 将磁盘块映射到空闲块池
IOCTL_DISK_SET_DRIVE_LAYOUT_EX 将磁盘分区
IOCTL_DISK_SET_PARTITION_INFO_EX 设置分区类型
IOCTL_DISK_UPDATE_PROPERTIES 使特定磁盘的cache分区表无效并重新枚举磁盘
IOCTL_DISK_VERIFY 对磁盘大小进行逻辑检测
IOCTL_SERIAL_LSRMST_INSERT (不)使电话线和Modem的连接状态信息发送到数据流中
IOCTL_STORAGE_CHECK_VERIFY 检测可移动媒体设备的改变
IOCTL_STORAGE_EJECT_MEDIA 弹出SCSI设备中的媒体(比如光盘)
IOCTL_STORAGE_GET_HOTPLUG_INFO 获取指定设备的热插拔配置
IOCTL_STORAGE_GET_MEDIA_TYPES 获取媒体支持信息
IOCTL_STORAGE_LOAD_MEDIA 将媒体装入设备
IOCTL_STORAGE_MEDIA_REMOVAL (不)使能媒体弹出装置
IOCTL_STORAGE_SET_HOTPLUG_INFO 设置指定设备的热插拔配置
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 获取一个或多个磁盘上指定卷的物理单元
IOCTL_VOLUME_IS_CLUSTERED 决定是否为一个卷作索引
(3)lpInBuffer(输入)
一个指针,指向存放操作所需数据的缓冲区。如果dwIoControlCode指定一个不需要输入数据的操作,那么这个参数可以为NULL。
(4)nInBufferSize(输入)
以字节为单位,指定输入缓冲区的大小。
(5)lpOutBuffer(输出)
一个指针,指向用来存放输出数据的缓冲区。如果dwIoControlCode指定一个没有输出数据的操作,那么这个参数可以为NULL。
(6)nOutBufferSize(输入)
以字节为单位,指定输出缓冲区的大小。
(7)lpBytesReturned(输出)
一个指针,指向一个存放输出数据长度的变量。
如果输出缓冲区太小不足以接收任何数据,那么函数调用失败,GetLastError错误描述为ERROR_INSUFFICIENT_BUFFER,输出数据长度为0。
如果输出缓冲区太小不足以接收所有数据但是可以放一部分,那么操作系统就返回可以放下的那部分数据,函数调用失败,
GetLastError错误描述为ERROR_MORE_DATA,输出数据长度是返回来的那部分数据的长度。你的应用程序应该调用DeviceIoControl 进行相同的操作,重新传输(指定那个没传完的地方作为开始点进行续传)。
如果lpOverlapped 为NULL,那么lpBytesReturned
决不能为NULL。即使是一个没有输出数据的操作,lpOutBuffer为NULL,DeviceIoControl也将会用到
lpBytesReturned指向的那个变量。这样的操作返回后,这个参数的返回值是无意义的。
如果lpOverlapped
不为NULL,那么lpBytesReturned
可以为NULL。如果是一次异步操作,我们可以通道函数GetOverlappedResult来获得返回的数据长度。如果hDevice
指向的是一个完成端口对象,我们可以用函数GetQueuedCompletionStatus获得返回数据的长度。
(8)lpOverlapped
一个指向OVERLAPPED结构体的指针。
如果hDevice用FILE_FLAG_OVERLAPPED 形式打开,lpOverlapped 必须指向一个合法的OVERLAPPED结构体。在这种情况下,进行异步操作。
如果hDevice用FILE_FLAG_OVERLAPPED 形式打开,而lpOverlapped为NULL,函数会返回不可预知的错误。
如果hDevice打开时没有指定FILE_FLAG_OVERLAP
WDM驱动程序开发之应用程序测试篇CreateFile,ReadFile,WriteFile,DeviceIoControl,CloseHandle.
时间 : 2008-03-24 作者:佚名 编辑:本站 点击: 4815 [ 评论 ]
PED 标志,lpOverlapped参数将被忽略,进行同步操作,函数直到操作完成或出现错误时才返回。
【Parameters】
成功返回非零,失败返回0,错误描述用GetLastError取得。
【Remarks】
如果hDevice用FILE_FLAG_OVERLAPPED 形式打开,lpOverlapped
指向一个合法的OVERLAPPED结构体,这是进行异步操作。在这种情况下,OVERLAPPED结构体必须包含一个手动设置的事件对象(用
CreateEvent函数创建)。