The first issue is that buffered writes of course still go through the page cache like I described previously. There's no way to specify that a cache page is being completely stomped, so they are validated automatically by the page manager when they are touched.
Even on an empty file that you just created they get touched. In order to do an async write, you had to do a SetFileSize to reserve room for yourself (extending file size is always synchronous, so you have to bump the file size up in advance). Windows won't let you just extend the file size without validating the data in the new file. In particular, it stomps zeros in there. What this means is the first time you write to a page it gets zeroed before your data goes in. The reason they do this is for security. If you could just extend your file size and they didn't stomp zeros, you could see sectors on disk that had been marked as deleted but not wiped, so you could look at someone else's data.
To avoid this hit, they nicely tell you that you can use this handy function SetFileValidData() which marks the data up to some length as valid so it won't get zeroed. Unfortunately, only administrators are allowed to use this function so you can't put it in an application at all.
Sigh. The result is that non-buffered writes are way faster than buffered writes, and also that overlapped writes are almost never actually asynchronous (when writing to portions of the file you haven't previously touched, they are synchronous, if you write back over something you touched it is async).
Of course, like most Windows security measures, this is all pretty retarded. Anybody who actually wants to install a malicious app that peeks at your deleted sectors can still easily do so by installing something at the device layer. The only actual consequence of this security measure is that normal apps that just want to write data are slower.