the problem is in this line of code:
if not Windows.WriteFile(file_hdl, buffer, Length(buffer), written, nil) then
what that line of code does is pass @buffer to Windows.WriteFile because the parameter is untyped. That's what causes the address to be passed instead of the value.
if you change that line of code to read:
if not Windows.WriteFile(file_hdl, buffer^, Length(buffer), written, nil) then
(note that buffer is dereferenced, i.e, buffer^, that should work.
The reason it works with "MyWriteFile" is because your definition is _correct_, i.e, the parameter "buffer" is of type pointer (as it should be) instead of untyped. That causes the value of buffer (which is a pointer) to be passed to MyWriteFile instead of a pointer to the buffer pointer which is what's passed with Windows.WriteFile.
ETA:
But I don't understand the difference between 'buf' and 'buf^'.
in the call to Windows.WriteFile, buf^ dereferences buf but since the parameter is untyped what ends up being passed is buf, i.e, @buf^ = buf, which is what should have been passed without all these binary contortions.
In the call to MyWriteFile you can simply pass buf because buf is already a pointer to the buffer and, since your definition is correct (buf is a pointer, not an untyped var), it works.
In the call to Windows.WriteFile, because the definition automatically takes the address of the variable you are passing, you need to dereference the variable you're passing so that when the address is taken, you end up with the value of the variable, in this case, buf.