Yes.
When an I/O completes (whether synchronously or asynchronously),
the event is signaled and completion status notifications are queued.
The GetOverlappedResult/
function can be used
to wait on an I/O that has already completed;
it will merely return immediately.
If you ask
HasOverlappedIoCompleted
whether the I/O
has completed, and the I/O completed synchronously,
it will correctly report,
"Yeah, of course it completed. Heck, it completed a long time ago!"
In other words, you can logically treat the case of an asynchronous I/O request completing synchronously as if it had completed asynchronously. It just completes asynchronously before you even blinked.