Index: /trunk/src/VBox/Runtime/r3/win/localipc-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/localipc-win.cpp	(revision 58298)
+++ /trunk/src/VBox/Runtime/r3/win/localipc-win.cpp	(revision 58299)
@@ -29,5 +29,4 @@
 *   Header Files                                                                                                                 *
 *********************************************************************************************************************************/
-#define RTMEM_WRAP_TO_EF_APIS
 #define LOG_GROUP RTLOGGROUP_LOCALIPC
 /*
@@ -1082,5 +1081,4 @@
         {
             pThis->Read.hActiveThread = RTThreadSelf();
-            Assert(!pThis->fZeroByteRead);
 
             size_t cbTotalRead = 0;
@@ -1128,6 +1126,5 @@
 
                         RTCritSectEnter(&pThis->CritSect);
-                        if (GetOverlappedResult(pThis->hNmPipe, &pThis->Read.OverlappedIO, &cbRead,
-                                                rcWait == WAIT_OBJECT_0 && !pThis->fCancelled /*fWait*/))
+                        if (GetOverlappedResult(pThis->hNmPipe, &pThis->Read.OverlappedIO, &cbRead, TRUE /*fWait*/))
                             rc = VINF_SUCCESS;
                         else
@@ -1165,4 +1162,123 @@
                     && rc != VERR_INVALID_POINTER)
                     rc = VINF_SUCCESS;
+            }
+
+            pThis->Read.hActiveThread = NIL_RTTHREAD;
+        }
+        else
+            rc = VERR_WRONG_ORDER;
+        rtLocalIpcSessionReleaseAndUnlock(pThis);
+    }
+
+    return rc;
+}
+
+
+RTDECL(int) RTLocalIpcSessionReadNB(RTLOCALIPCSESSION hSession, void *pvBuf, size_t cbToRead, size_t *pcbRead)
+{
+    PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE);
+    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcbRead, VERR_INVALID_POINTER);
+    *pcbRead = 0;
+
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        rtLocalIpcSessionRetain(pThis);
+        if (pThis->Read.hActiveThread == NIL_RTTHREAD)
+        {
+            pThis->Read.hActiveThread = RTThreadSelf();
+
+            for (;;)
+            {
+                DWORD cbRead = 0;
+                if (!pThis->fCancelled)
+                {
+                    /*
+                     * Wait for pending zero byte read, if necessary.
+                     * Note! It cannot easily be cancelled due to concurrent current writes.
+                     */
+                    if (!pThis->fZeroByteRead)
+                    { /* likely */ }
+                    else
+                    {
+                        RTCritSectLeave(&pThis->CritSect);
+                        DWORD rcWait = WaitForSingleObject(pThis->Read.OverlappedIO.hEvent, 0);
+                        RTCritSectEnter(&pThis->CritSect);
+
+                        rc = rtLocalIpcWinGetZeroReadResult(pThis, rcWait);
+                        if (RT_SUCCESS(rc))
+                            continue;
+
+                        if (rc == VERR_TIMEOUT)
+                            rc = VINF_TRY_AGAIN;
+                        break;
+                    }
+
+                    /*
+                     * Figure out how much we can read (cannot try and cancel here
+                     * like in the anonymous pipe code).
+                     */
+                    DWORD cbAvailable;
+                    if (PeekNamedPipe(pThis->hNmPipe, NULL, 0, NULL, &cbAvailable, NULL))
+                    {
+                        if (cbAvailable == 0 || cbToRead == 0)
+                        {
+                            *pcbRead = 0;
+                            rc = VINF_TRY_AGAIN;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        rc = RTErrConvertFromWin32(GetLastError());
+                        break;
+                    }
+                    if (cbAvailable > cbToRead)
+                        cbAvailable = (DWORD)cbToRead;
+
+                    /*
+                     * Kick of a an overlapped read.  It should return immediately, so we
+                     * don't really need to leave the critsect here.
+                     */
+                    rc = ResetEvent(pThis->Read.OverlappedIO.hEvent); Assert(rc == TRUE);
+                    if (ReadFile(pThis->hNmPipe, pvBuf, cbAvailable, &cbRead, &pThis->Read.OverlappedIO))
+                    {
+                        *pcbRead = cbRead;
+                        rc = VINF_SUCCESS;
+                    }
+                    else if (GetLastError() == ERROR_IO_PENDING)
+                    {
+                        DWORD rcWait = WaitForSingleObject(pThis->Read.OverlappedIO.hEvent, 0);
+                        if (rcWait == WAIT_TIMEOUT)
+                        {
+                            RTCritSectLeave(&pThis->CritSect);
+                            rcWait = WaitForSingleObject(pThis->Read.OverlappedIO.hEvent, INFINITE);
+                            RTCritSectEnter(&pThis->CritSect);
+                        }
+                        if (GetOverlappedResult(pThis->hNmPipe, &pThis->Read.OverlappedIO, &cbRead, TRUE /*fWait*/))
+                        {
+                            *pcbRead = cbRead;
+                            rc = VINF_SUCCESS;
+                        }
+                        else
+                        {
+                            if (pThis->fCancelled)
+                                rc = VERR_CANCELLED;
+                            else
+                                rc = RTErrConvertFromWin32(GetLastError());
+                        }
+                    }
+                    else
+                    {
+                        rc = RTErrConvertFromWin32(GetLastError());
+                        AssertMsgFailedBreak(("%Rrc\n", rc));
+                    }
+                }
+                else
+                    rc = VERR_CANCELLED;
+                break;
             }
 
Index: /trunk/src/VBox/Runtime/testcase/tstRTLocalIpc.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTLocalIpc.cpp	(revision 58298)
+++ /trunk/src/VBox/Runtime/testcase/tstRTLocalIpc.cpp	(revision 58299)
@@ -242,5 +242,4 @@
             RTTESTI_CHECK_RC(RTLocalIpcSessionWaitForData(hIpcSession, RT_MS_1MIN), VINF_SUCCESS);
 
-#ifndef RT_OS_WINDOWS
             size_t cbRead;
             char szCmd[64];
@@ -250,5 +249,4 @@
                 RTTestIFailed("cbRead=%zu, expected %zu; szCmd='%s', expected 'disconnect'\n",
                               cbRead, sizeof("disconnect") - 1, szCmd);
-#endif
 
             RTTESTI_CHECK_RC(RTLocalIpcSessionClose(hIpcSession), VINF_OBJECT_DESTROYED);
@@ -285,8 +283,6 @@
     uint8_t abBuf[4];
     size_t cbRead = _4M-1;
-#ifndef RT_OS_WINDOWS
     RTTESTI_CHECK_RC(RTLocalIpcSessionReadNB(hClientSession, abBuf, sizeof(abBuf), &cbRead), VINF_TRY_AGAIN);
     RTTESTI_CHECK(cbRead == 0);
-#endif
 
     /* Trigger server disconnect. */
@@ -310,8 +306,6 @@
         cbRead = _4M-1;
         RTTESTI_CHECK_RC(RTLocalIpcSessionRead(hClientSession, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE);
-#ifndef RT_OS_WINDOWS
         cbRead = _1G/2;
         RTTESTI_CHECK_RC(RTLocalIpcSessionReadNB(hClientSession, abBuf, sizeof(abBuf), &cbRead), VERR_BROKEN_PIPE);
-#endif
 
         RTAssertSetMayPanic(fMayPanic);
