My results in Windows XP showed the following results: (The same would be true for Windows NT or 2000)
We must distinguish 2 cases:
a) The file pointer in the overlapped structure is already beyond EOF. This condition is one where ReadFileEx() should arguably react as you are describing.
If the file pointer is exactly at or after EOF, ReadFileEx() returns FALSE. GetLastError() reports ERROR_HANDLE_EOF. The completition function is not called in this case.
If you call ReadFileEx() at EOF, or even beyond, but specify to read 0 bytes, it reports success by returning TRUE.
b) The file pointer in the overlapped structure is below eof, but the App wants to read more than available (file pointer + number of bytes to read is beyond EOF). If I understand you right, in this case ReadFileEx() returns TRUE, sets the last error to ERROR_HANDLE_EOF, reads as much as it can and calls the completion function with an Error code of 0. Right?
No. Don't take my work around, which called the callback function with 0, as the correct behaviour. I merely searched for a way, which would allow my programs to run under wine. They run pretty, when calling the completition function with 0. But maybe some other program doesn't expect this behaviour and will complain about that. Calling the function this additional time without incrementing the file pointer leads to an additional call of the wine ReadFileEx() function, which now can simply report the EOF error, because we stored the state internally in the OVERLAPPED structure.
The behaving of Windows in this case b.) is: If the file pointer is below EOF, ReadFileEx() returns TRUE. SetLastError() is not called, so GetLastError() would return 0. The completition function will be called, when SleepEx(), WaitForMultipleObjectsEx() etc. is called some time later with the parameter bAlertable=TRUE.
This is against what MSDN says: According to http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/bas
e/fileiocompletionroutine.asp
the error code for the completion function is set to ERROR_HANDLE_EOF if "the application tried to read past the end of file", which is case b) to my understanding.
MSDN says it this way:
dwErrorCode [in] Specifies the I/O completion status. This parameter CAN be one of the following values.
Value Meaning 0 The I/O was successful. ERROR_HANDLE_EOF The ReadFileEx function tried to read past the end of the file
So, the "can" allows to call the completition function with ERROR_HANDLE_EOF, but it does not say, it would be called in all cases, for all types of file handles, and so on... As described above, it is not called with ERROR_HANDLE_EOF, at least for regular files with my test program. If you take it exactly, MSDN is correct. But it doesn't specify exactly, what will happen in every situation with every type of file.
So, what should be changed in wine?
To do it exactly like Windows, ReadFileEx() should check for a end-of-file condition. It there are any bytes to read from the file, it should return TRUE. After that, when the thread goes into the alertable state, the completition function should be called. In the other case, if ReadFileEx() finds EOF, it should call SetLastError(ERROR_HANDLE_EOF), and return FALSE. This is, what wine currently doesn't do.
That's all. At least for regular files located on the hard disc.
-- Martin Fuchs martin-fuchs@gmx.net