- /* Returns non-zero upon success, 0 upon failure. */
- if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
- RETURN_FAIL("WriteFile() failed");
+ if (port->nonblocking) {
+ /* Non-blocking write. */
+
+ /* Check whether previous write is complete. */
+ if (port->writing) {
+ if (HasOverlappedIoCompleted(&port->write_ovl)) {
+ DEBUG("Previous write completed");
+ port->writing = 0;
+ free(port->write_buf);
+ port->write_buf = NULL;
+ } else {
+ DEBUG("Previous write not complete");
+ /* Can't take a new write until the previous one finishes. */
+ RETURN_VALUE("0", 0);
+ }
+ }
+
+ /* Copy user buffer. */
+ if (!(port->write_buf = malloc(count)))
+ RETURN_ERROR(SP_ERR_MEM, "buffer copy malloc failed");
+ memcpy(port->write_buf, buf, count);
+
+ /* Start asynchronous write. */
+ if (WriteFile(port->hdl, buf, count, NULL, &port->write_ovl) == 0) {
+ if (GetLastError() == ERROR_IO_PENDING) {
+ DEBUG("Asynchronous write started");
+ port->writing = 1;
+ RETURN_VALUE("%d", count);
+ } else {
+ free(port->write_buf);
+ port->write_buf = NULL;
+ /* Actual failure of some kind. */
+ RETURN_FAIL("WriteFile() failed");
+ }
+ } else {
+ DEBUG("Write completed immediately");
+ free(port->write_buf);
+ port->write_buf = NULL;
+ RETURN_VALUE("%d", count);
+ }
+ } else {
+ /* Blocking write. */
+ if (WriteFile(port->hdl, buf, count, &written, NULL) == 0) {
+ RETURN_FAIL("WriteFile() failed");
+ }
+ }
+