private static unsafe int WriteFileNative(IntPtr hFile, byte[] bytes, int offset, int count, bool useFileAPIs)
{
Debug.Assert(offset >= 0, "offset >= 0");
Debug.Assert(count >= 0, "count >= 0");
Debug.Assert(bytes != null, "bytes != null");
Debug.Assert(bytes.Length >= offset + count, "bytes.Length >= offset + count");
// You can't use the fixed statement on an array of length 0.
if (bytes.Length == 0)
return Interop.Errors.ERROR_SUCCESS;
bool writeSuccess;
fixed (byte* p = bytes)
{
if (useFileAPIs)
{
int numBytesWritten;
writeSuccess = (0 != Interop.Kernel32.WriteFile(hFile, p + offset, count, out numBytesWritten, IntPtr.Zero));
Debug.Assert(!writeSuccess || count == numBytesWritten);
}
else
{
// If the code page could be Unicode, we should use ReadConsole instead, e.g.
// Note that WriteConsoleW has a max limit on num of chars to write (64K)
// [http://msdn.microsoft.com/en-us/library/ms687401.aspx]
// However, we do not need to worry about that because the StreamWriter in Console has
// a much shorter buffer size anyway.
int charsWritten;
writeSuccess = Interop.Kernel32.WriteConsole(hFile, p + offset, count / BytesPerWChar, out charsWritten, IntPtr.Zero);
Debug.Assert(!writeSuccess || count / BytesPerWChar == charsWritten);
}
}
if (writeSuccess)
return Interop.Errors.ERROR_SUCCESS;
// For pipes that are closing or broken, just stop.
// (E.g. ERROR_NO_DATA ("pipe is being closed") is returned when we write to a console that is closing;
// ERROR_BROKEN_PIPE ("pipe was closed") is returned when stdin was closed, which is mot an error, but EOF.)
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == Interop.Errors.ERROR_NO_DATA || errorCode == Interop.Errors.ERROR_BROKEN_PIPE)
return Interop.Errors.ERROR_SUCCESS;
return errorCode;
}
}