Index: /trunk/src/VBox/Runtime/r3/win/serialport-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/serialport-win.cpp	(revision 73634)
+++ /trunk/src/VBox/Runtime/r3/win/serialport-win.cpp	(revision 73635)
@@ -60,8 +60,16 @@
     /** The device handle. */
     HANDLE              hDev;
-    /** The overlapped I/O structure. */
-    OVERLAPPED          Overlapped;
-    /** The event handle to wait on for the overlapped I/O operations of the device. */
+    /** The overlapped write structure. */
+    OVERLAPPED          OverlappedWrite;
+    /** The overlapped read structure. */
+    OVERLAPPED          OverlappedRead;
+    /** The overlapped I/O structure when waiting on events. */
+    OVERLAPPED          OverlappedEvt;
+    /** The event handle to wait on for the overlapped event operations of the device. */
     HANDLE              hEvtDev;
+    /** The event handle to wait on for the overlapped write operations of the device. */
+    HANDLE              hEvtWrite;
+    /** The event handle to wait on for the overlapped read operations of the device. */
+    HANDLE              hEvtRead;
     /** The event handle to wait on for waking up waiting threads externally. */
     HANDLE              hEvtIntr;
@@ -111,5 +119,5 @@
 static int rtSerialPortWinUpdateEvtMask(PRTSERIALPORTINTERNAL pThis, uint32_t fEvtMask)
 {
-    DWORD dwEvtMask = 0;
+    DWORD dwEvtMask = EV_ERR;
 
     if (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)
@@ -173,9 +181,9 @@
 {
     int rc = VINF_SUCCESS;
-    DWORD dwRc = WaitForSingleObject(pThis->Overlapped.hEvent, 0);
+    DWORD dwRc = WaitForSingleObject(pThis->OverlappedWrite.hEvent, 0);
     if (dwRc == WAIT_OBJECT_0)
     {
         DWORD cbWritten = 0;
-        if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbWritten, TRUE))
+        if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedWrite, &cbWritten, TRUE))
         {
             for (;;)
@@ -190,7 +198,7 @@
                 /* resubmit the remainder of the buffer - can this actually happen? */
                 memmove(&pThis->pbBounceBuf[0], &pThis->pbBounceBuf[cbWritten], pThis->cbBounceBufUsed - cbWritten);
-                rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE);
+                rc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(rc == TRUE);
                 if (!WriteFile(pThis->hDev, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed,
-                               &cbWritten, &pThis->Overlapped))
+                               &cbWritten, &pThis->OverlappedWrite))
                 {
                     if (GetLastError() == ERROR_IO_PENDING)
@@ -245,36 +253,53 @@
         pThis->cbBounceBufUsed  = 0;
         pThis->cbBounceBufAlloc = 0;
-        pThis->hEvtDev          = CreateEvent(NULL, FALSE, FALSE, NULL);
+        RT_ZERO(pThis->OverlappedEvt);
+        RT_ZERO(pThis->OverlappedWrite);
+        RT_ZERO(pThis->OverlappedRead);
+        pThis->hEvtDev          = CreateEvent(NULL, TRUE, FALSE, NULL);
         if (pThis->hEvtDev)
         {
-            pThis->Overlapped.hEvent = pThis->hEvtDev,
+            pThis->OverlappedEvt.hEvent = pThis->hEvtDev,
             pThis->hEvtIntr = CreateEvent(NULL, FALSE, FALSE, NULL);
             if (pThis->hEvtIntr)
             {
-                DWORD fWinFlags = 0;
-
-                if (fFlags & RTSERIALPORT_OPEN_F_WRITE)
-                    fWinFlags |= GENERIC_WRITE;
-                if (fFlags & RTSERIALPORT_OPEN_F_READ)
-                    fWinFlags |= GENERIC_READ;
-
-                pThis->hDev = CreateFile(pszPortAddress,
-                                         fWinFlags,
-                                         0, /* Must be opened with exclusive access. */
-                                         NULL, /* No SECURITY_ATTRIBUTES structure. */
-                                         OPEN_EXISTING, /* Must use OPEN_EXISTING. */
-                                         FILE_FLAG_OVERLAPPED, /* Overlapped I/O. */
-                                         NULL);
-                if (pThis->hDev)
+                pThis->hEvtWrite = CreateEvent(NULL, TRUE, TRUE, NULL);
+                if (pThis->hEvtWrite)
                 {
-                    rc = rtSerialPortSetDefaultCfg(pThis);
-                    if (RT_SUCCESS(rc))
+                    pThis->OverlappedWrite.hEvent = pThis->hEvtWrite;
+                    pThis->hEvtRead = CreateEvent(NULL, TRUE, TRUE, NULL);
+                    if (pThis->hEvtRead)
                     {
-                        *phSerialPort = pThis;
-                        return rc;
+                        pThis->OverlappedRead.hEvent = pThis->hEvtRead;
+                        DWORD fWinFlags = 0;
+
+                        if (fFlags & RTSERIALPORT_OPEN_F_WRITE)
+                            fWinFlags |= GENERIC_WRITE;
+                        if (fFlags & RTSERIALPORT_OPEN_F_READ)
+                            fWinFlags |= GENERIC_READ;
+
+                        pThis->hDev = CreateFile(pszPortAddress,
+                                                 fWinFlags,
+                                                 0, /* Must be opened with exclusive access. */
+                                                 NULL, /* No SECURITY_ATTRIBUTES structure. */
+                                                 OPEN_EXISTING, /* Must use OPEN_EXISTING. */
+                                                 FILE_FLAG_OVERLAPPED, /* Overlapped I/O. */
+                                                 NULL);
+                        if (pThis->hDev)
+                        {
+                            rc = rtSerialPortSetDefaultCfg(pThis);
+                            if (RT_SUCCESS(rc))
+                            {
+                                *phSerialPort = pThis;
+                                return rc;
+                            }
+                        }
+                        else
+                            rc = RTErrConvertFromWin32(GetLastError());
+
+                        CloseHandle(pThis->hEvtRead);
                     }
+
+                    CloseHandle(pThis->hEvtWrite);
                 }
-                else
-                    rc = RTErrConvertFromWin32(GetLastError());
 
                 CloseHandle(pThis->hEvtIntr);
@@ -315,8 +340,12 @@
     CloseHandle(pThis->hDev);
     CloseHandle(pThis->hEvtDev);
+    CloseHandle(pThis->hEvtWrite);
+    CloseHandle(pThis->hEvtRead);
     CloseHandle(pThis->hEvtIntr);
-    pThis->hDev     = NULL;
-    pThis->hEvtDev  = NULL;
-    pThis->hEvtIntr = NULL;
+    pThis->hDev      = NULL;
+    pThis->hEvtDev   = NULL;
+    pThis->hEvtWrite = NULL;
+    pThis->hEvtRead  = NULL;
+    pThis->hEvtIntr  = NULL;
     RTMemFree(pThis);
     return VINF_SUCCESS;
@@ -351,9 +380,9 @@
            && RT_SUCCESS(rc))
     {
-        BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
+        BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
         DWORD cbRead = 0;
         if (ReadFile(pThis->hDev, pbBuf,
                      cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
-                     &cbRead, &pThis->Overlapped))
+                     &cbRead, &pThis->OverlappedRead))
         {
             if (pcbRead)
@@ -366,8 +395,8 @@
         else if (GetLastError() == ERROR_IO_PENDING)
         {
-            DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
+            DWORD dwWait = WaitForSingleObject(pThis->OverlappedRead.hEvent, INFINITE);
             if (dwWait == WAIT_OBJECT_0)
             {
-                if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbRead, TRUE /*fWait*/))
+                if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
                 {
                     if (pcbRead)
@@ -418,10 +447,10 @@
      */
     int rc = VINF_SUCCESS;
-    BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
+    BOOL fSucc = ResetEvent(pThis->OverlappedRead.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
     DWORD cbRead = 0;
     if (   cbToRead == 0
         || ReadFile(pThis->hDev, pvBuf,
                     cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
-                    &cbRead, &pThis->Overlapped))
+                    &cbRead, &pThis->OverlappedRead))
     {
         *pcbRead = cbRead;
@@ -431,6 +460,6 @@
     {
         if (!CancelIo(pThis->hDev))
-            WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
-        if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbRead, TRUE /*fWait*/))
+            WaitForSingleObject(pThis->OverlappedRead.hEvent, INFINITE);
+        if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedRead, &cbRead, TRUE /*fWait*/))
         {
             *pcbRead = cbRead;
@@ -471,9 +500,9 @@
                && RT_SUCCESS(rc))
         {
-            BOOL fSucc = ResetEvent(pThis->Overlapped.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
+            BOOL fSucc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(fSucc == TRUE); RT_NOREF(fSucc);
             DWORD cbWritten = 0;
             if (WriteFile(pThis->hDev, pbBuf,
                           cbToWrite <= ~(DWORD)0 ? (DWORD)cbToWrite : ~(DWORD)0,
-                          &cbWritten, &pThis->Overlapped))
+                          &cbWritten, &pThis->OverlappedWrite))
             {
                 if (pcbWritten)
@@ -486,8 +515,8 @@
             else if (GetLastError() == ERROR_IO_PENDING)
             {
-                DWORD dwWait = WaitForSingleObject(pThis->Overlapped.hEvent, INFINITE);
+                DWORD dwWait = WaitForSingleObject(pThis->OverlappedWrite.hEvent, INFINITE);
                 if (dwWait == WAIT_OBJECT_0)
                 {
-                    if (GetOverlappedResult(pThis->hDev, &pThis->Overlapped, &cbWritten, TRUE /*fWait*/))
+                    if (GetOverlappedResult(pThis->hDev, &pThis->OverlappedWrite, &cbWritten, TRUE /*fWait*/))
                     {
                         if (pcbWritten)
@@ -562,8 +591,8 @@
 
             /* Submit the write. */
-            rc = ResetEvent(pThis->Overlapped.hEvent); Assert(rc == TRUE);
+            rc = ResetEvent(pThis->OverlappedWrite.hEvent); Assert(rc == TRUE);
             DWORD cbWritten = 0;
             if (WriteFile(pThis->hDev, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed,
-                          &cbWritten, &pThis->Overlapped))
+                          &cbWritten, &pThis->OverlappedWrite))
             {
                 *pcbWritten = RT_MIN(cbWritten, cbToWrite); /* paranoia^3 */
@@ -750,4 +779,31 @@
         rc = rtSerialPortWinUpdateEvtMask(pThis, fEvtMask);
 
+    /*
+     * EV_RXCHAR is triggered only if a byte is received after the event mask is set,
+     * not if there is already something in the input buffer. Thatswhy we check the input
+     * buffer for any stored data and the output buffer whether it is empty and return
+     * the appropriate flags.
+     */
+    if (RT_SUCCESS(rc))
+    {
+        COMSTAT ComStat; RT_ZERO(ComStat);
+        if (!ClearCommError(pThis->hDev, NULL, &ComStat))
+            return RTErrConvertFromWin32(GetLastError());
+
+        /* Check whether data is already waiting in the input buffer. */
+        if (   (fEvtMask & RTSERIALPORT_EVT_F_DATA_RX)
+            && ComStat.cbInQue > 0)
+            *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_RX;
+
+        /* Check whether the output buffer is empty. */
+        if (   (fEvtMask & RTSERIALPORT_EVT_F_DATA_TX)
+            && ComStat.cbOutQue == 0)
+            *pfEvtsRecv |= RTSERIALPORT_EVT_F_DATA_TX;
+
+        /* Return if there is at least one event. */
+        if (*pfEvtsRecv != 0)
+            return VINF_SUCCESS;
+    }
+
     if (RT_SUCCESS(rc))
     {
@@ -757,8 +813,8 @@
         ahWait[1] = pThis->hEvtIntr;
 
-        RT_ZERO(pThis->Overlapped);
-        pThis->Overlapped.hEvent = pThis->hEvtDev;
-
-        if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->Overlapped))
+        RT_ZERO(pThis->OverlappedEvt);
+        pThis->OverlappedEvt.hEvent = pThis->hEvtDev;
+
+        if (!WaitCommEvent(pThis->hDev, &dwEventMask, &pThis->OverlappedEvt))
         {
             DWORD dwRet = GetLastError();
