wine and asyncronous file i/o

Martin Fuchs martin-fuchs at
Mon Nov 25 16:19:50 CST 2002

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

> This is against what MSDN says: According to
> 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
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
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
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 at

More information about the wine-devel mailing list