When using FILE_FLAG_NO_BUFFERING documented requirement is that the memory address to read or write must be a multiple of the size of the physical sector. In your code, you selected a random selection of the address of the byte array (therefore, it is unlikely to be a multiple of the size of the physical sector), and then you add an offset.
The behavior you observe is that the call works if the offset is a multiple of 4. Probably the byte array is aligned at the 4-byte boundary, so the call works if the memory address is a multiple of 4.
Therefore, your question can be rewritten as follows: why does reading work when the memory address is a multiple of 4, when the documentation says that it should be a multiple of 512?
The answer is that the documentation does not give any specific guarantees as to what will happen if you break the rules. It may happen that the call is all the same. It may happen that the call works anyway, but only in September in even years. It may happen that the call works in any case, but only if the memory address is a multiple of 4. (It probably depends on the specific hardware and device drivers involved in the read operation. Just because it works on your machine, t means that it will work for someone else's.)
It is probably not recommended to use FILE_FLAG_NO_BUFFERING with a FileStream in the first place, because I doubt that the FileStream actually guarantees that it will pass the address that you give it unmodified to the underlying ReadFile call. Instead, use P / Invoke to directly invoke the core API functions. You may also need to allocate your memory this way because I don't know if .NET provides any way to allocate memory with a specific alignment or not.
source share