diff --git a/code/Native/Windows/CommOverlappedIo.cs b/code/Native/Windows/CommOverlappedIo.cs
index 97f08bd..3b037ff 100644
--- a/code/Native/Windows/CommOverlappedIo.cs
+++ b/code/Native/Windows/CommOverlappedIo.cs
@@ -1,4 +1,4 @@
-// Copyright © Jason Curl 2012-2023
+// Copyright © Jason Curl 2012-2024
// Sources at https://github.com/jcurl/SerialPortStream
// Licensed under the Microsoft Public License (Ms-PL)
@@ -457,20 +457,7 @@ private void OverlappedIoThreadMainLoop()
} else if (whandles[ev] == m_ReadEvent) {
result = Kernel32.GetOverlappedResult(m_ComPortHandle, ref readOverlapped, out bytes, true);
if (!result) {
- int win32Error = Marshal.GetLastWin32Error();
- int hr = Marshal.GetHRForLastWin32Error();
- // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered.
- if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0) {
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
- "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
- Marshal.ThrowExceptionForHR(hr);
- } else {
- // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
- "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
- }
+ ProcessReadEventError(bytes);
} else {
ProcessReadEvent(bytes);
}
@@ -481,19 +468,7 @@ private void OverlappedIoThreadMainLoop()
} else if (whandles[ev] == m_WriteEvent) {
result = Kernel32.GetOverlappedResult(m_ComPortHandle, ref writeOverlapped, out bytes, true);
if (!result) {
- int win32Error = Marshal.GetLastWin32Error();
- int hr = Marshal.GetHRForLastWin32Error();
- // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered.
- if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0) {
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
- "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
- Marshal.ThrowExceptionForHR(hr);
- } else {
- // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
- }
+ ProcessWriteEventError(bytes);
} else {
ProcessWriteEvent(bytes);
}
@@ -508,20 +483,7 @@ private void OverlappedIoThreadMainLoop()
m_PurgePending = true;
result = Kernel32.PurgeComm(m_ComPortHandle,
Kernel32.PurgeFlags.PURGE_TXABORT | Kernel32.PurgeFlags.PURGE_TXCLEAR);
- if (!result) {
- int win32Error = Marshal.GetLastWin32Error();
- int hr = Marshal.GetHRForLastWin32Error();
- if (win32Error != WinError.ERROR_OPERATION_ABORTED) {
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
- "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
- Marshal.ThrowExceptionForHR(hr);
- } else {
- if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
- m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
- "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
- }
- }
+ if (!result) ProcessPurgeCommError();
} else {
lock (m_Buffer.WriteLock) {
if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
@@ -737,6 +699,33 @@ private void ProcessReadEvent(uint bytes)
}
}
+ private void ProcessReadEventError(uint bytes)
+ {
+ int win32Error = Marshal.GetLastWin32Error();
+ int hr = Marshal.GetHRForLastWin32Error();
+
+ // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered.
+ if (bytes == 0) {
+ switch (win32Error) {
+ case WinError.ERROR_OPERATION_ABORTED:
+ // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
+ "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
+ return;
+ case WinError.ERROR_HANDLE_EOF:
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Information))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Information,
+ "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
+ return;
+ }
+ }
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
+ "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes);
+ Marshal.ThrowExceptionForHR(hr);
+ }
+
///
/// Check if we should WriteFile() and update buffers if serial data is immediately cached by driver.
///
@@ -826,6 +815,47 @@ private void ProcessWriteEvent(uint bytes)
}
}
+ private void ProcessWriteEventError(uint bytes)
+ {
+ int win32Error = Marshal.GetLastWin32Error();
+ int hr = Marshal.GetHRForLastWin32Error();
+
+ if (bytes == 0) {
+ switch (win32Error) {
+ case WinError.ERROR_OPERATION_ABORTED:
+ // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
+ "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
+ return;
+ }
+ }
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
+ "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
+ Marshal.ThrowExceptionForHR(hr);
+ }
+
+ private void ProcessPurgeCommError()
+ {
+ int win32Error = Marshal.GetLastWin32Error();
+ int hr = Marshal.GetHRForLastWin32Error();
+
+ switch (win32Error) {
+ case WinError.ERROR_OPERATION_ABORTED:
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose,
+ "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
+ return;
+ default:
+ if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error))
+ m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error,
+ "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error);
+ Marshal.ThrowExceptionForHR(hr);
+ break;
+ }
+ }
+
#region Event Handling
public event EventHandler CommEvent;