As far as I can tell disk file case works a bit differently on Windows. It's using dwBytesTransferred, and probably some of OVERLAPPED fields, e.g. EndRead()/EndWrite() will return precisely what's in dwByteTransferred. Unfortunately it's not that straightforward, and some internal bookkeeping is still happening and End* methods can't solely rely on result data. Buy let's ignore that for now, it's not clear of bringing async IO to already async MF reads is worth it.