If you want to do IO really robustly in Windows, you can't just assume that your ReadFile / WriteFile will succeed under normal usage. There are lots of nasty cases where you need to retry (perhaps with smaller IO sizes, or just after waiting a bit).
In particular you can see these errors in normal runs :
ERROR_NOT_ENOUGH_MEMORY = too many AsyncIO 's pending
ERROR_NOT_ENOUGH_QUOTA = single IO call too large
not enough process space pages available
failure to alloc pages in the kernel address space for the IO
try again with smaller IOs
normal async IO return value
sometimes normal EOF return value
anyway, this post is not about the specifics of IO errors. (random aside : I believe that some of these annoying errors were much
more common in 32-bit windows; the failure to get address space to map IO pages was a bigger problem in
32-bit (I saw it most often when running with the /3GB option which makes the kernel page space a scarce commodity),
I don't think I've seen it in the field in 64-bit windows)
I discovered a while ago that ReadFile and WriteFile can fail (return false) but not set last error to anything.
That is, you have something like :
SetLastError(77); // something bogus
if ( ! ReadFile(....) )
// failure, get code :
DWORD new_error = GetLastError();
// new_error should be the error info about ReadFile failing
// but sometimes it's still 77
and *sometimes* new_error is still 77 (or whatever; that is, it wasn't actually set when ReadFile failed).
I have no idea exactly what situations make the error get set or not. I have no idea how many other Win32 APIs are affected by this flaw, I only have empirical proof of ReadFile and WriteFile.
Anyhoo, the conclusion is that best practice on Win32 is to call SetLastError(0) before invoking any
API where you need to know for sure that the error code you get was in fact set by that call. eg.
if ( ! SomeWin32API(...) )
DWORD hey_I_know_this_error_is_legit = GetLastError();
That is, Win32 APIs returning failure does *not* guarantee that they set LastError.
ADD : while I'm at it :
in the VC watch window is pretty sweet.
GetLastError is :
or *(DWORD *)(FS:[0x34]) on x86