I am writing myself a COM port driver for my Arduino projects. For that, I performed a comprehensive searching to COM port driver writing. I begins with whatever COM port driver source code available on the internet. After two whole days of digesting those source code, I finally got a COM driver project compiled and working, in a way that every lines of code understood. The first thing I do after testing it with the terminal software is to connect it to the Arduino IDE and try to send/receive data from the serial monitor window. And, I got ...
"java.io.IOException: No error in nativeDrain".
Fascinating error message. How can "no error" become an "IOException"?? So, I began another searching, tracing the source code line by line. It turns out Arduino IDE uses a java package RXTX http://rxtx.qbang.org to do the serial connection, RXTX translate it to a native call called tcdrain() which is a function ported from UNIX, and tcdrain() is calling a Microsoft function FlushFileBuffers() to flush the output stream. (... and so... and so... too long now, I know)
The fascinating error message happens because the driver programmers did not implement the driver callback function for flushing stream (i.e. IRP_MJ_FLUSH_BUFFERS). The driver programmers do that probably because they are thinking of a direct IO device, such that every IO operation is carried out immediately and so no buffer to flush. Microsoft substitute a fail return value to any unimplemented callback functions. So, flushing stream will always fail in this case. The catch is Microsoft also think that it is okay to call an unimplemented callback function. As a result, tcdrain() fails to flush the stream, but GetLastError() said "no error". Eventually, when all these pieces of error messages put together at the front end, it becomes "java.io.IOException: No error in nativeDrain".
At the end of the story, there is still a question to be answered. What can you do if you meet the same problem? Here is the answer. If you are a driver programmer implementing a direct IO device, you can implement the callback function IRP_MJ_FLUSH_BUFFERS and always return ok. If you are an unlucky programmer who need to deal with some less elaborated drivers, you can take away the calls to flush function on a per driver basis. And... if you are just an ordinary end user, you can pray.
PS: I did reproduced the error, and solved it by implementing the flushing callback function with my own driver source code. A solid confirmation.