Index: trunk/src/VBox/Runtime/r3/os2/pipe-os2.cpp
===================================================================
--- trunk/src/VBox/Runtime/r3/os2/pipe-os2.cpp	(revision 39657)
+++ trunk/src/VBox/Runtime/r3/os2/pipe-os2.cpp	(revision 39690)
@@ -95,2 +95,8 @@
 }
 
+
+RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
+{
+    return VERR_NOT_IMPLEMENTED;
+}
+
Index: trunk/src/VBox/Runtime/r3/posix/pipe-posix.cpp
===================================================================
--- trunk/src/VBox/Runtime/r3/posix/pipe-posix.cpp	(revision 39657)
+++ trunk/src/VBox/Runtime/r3/posix/pipe-posix.cpp	(revision 39690)
@@ -44,4 +44,5 @@
 #include <limits.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
 #include <sys/poll.h>
 #include <sys/stat.h>
@@ -638,2 +639,28 @@
 }
 
+
+RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
+{
+    RTPIPEINTERNAL *pThis = hPipe;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->fRead, VERR_PIPE_NOT_READ);
+    AssertPtrReturn(pcbReadable, VERR_INVALID_POINTER);
+
+    int cb = 0;
+    int rc = ioctl(pThis->fd, FIONREAD, &cb);
+    if (rc != -1)
+    {
+        AssertStmt(cb >= 0, cb = 0);
+        *pcbReadable = cb;
+        return VINF_SUCCESS;
+    }
+
+    rc = errno;
+    if (rc == ENOTTY)
+        rc = VERR_NOT_SUPPORTED;
+    else
+        rc = RTErrConvertFromErrno(rc);
+    return rc;
+}
+
Index: trunk/src/VBox/Runtime/r3/win/pipe-win.cpp
===================================================================
--- trunk/src/VBox/Runtime/r3/win/pipe-win.cpp	(revision 39657)
+++ trunk/src/VBox/Runtime/r3/win/pipe-win.cpp	(revision 39690)
@@ -1148,4 +1148,27 @@
 
 
+RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
+{
+    RTPIPEINTERNAL *pThis = hPipe;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->fRead, VERR_PIPE_NOT_READ);
+    AssertPtrReturn(pcbReadable, VERR_INVALID_POINTER);
+
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    DWORD cbAvailable = 0;
+    if (PeekNamedPipe(pThis->hPipe, NULL, 0, NULL, &cbAvailable, NULL)
+        *pcbReadable = cbAvailable;
+    else
+        rc = RTErrConvertFromWin32(GetLastError());
+
+    RTCritSectLeave(&pThis->CritSect);
+    return rc;
+}
+
+
 /**
  * Internal RTPollSetAdd helper that returns the handle that should be added to
Index: trunk/src/VBox/Runtime/testcase/tstRTPipe.cpp
===================================================================
--- trunk/src/VBox/Runtime/testcase/tstRTPipe.cpp	(revision 39657)
+++ trunk/src/VBox/Runtime/testcase/tstRTPipe.cpp	(revision 39690)
@@ -351,7 +351,10 @@
     RTTESTI_CHECK_RC_RETV(RTPipeWrite(hPipeW, "BigQ", 4, &cbWritten), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbWritten == 4);
-    cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 0), VINF_SUCCESS);
     RTTESTI_CHECK_RC_RETV(RTPipeSelectOne(hPipeR, 1), VINF_SUCCESS);
+    cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
+    cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, abBuf, sizeof(abBuf), &cbRead), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbRead == 4);
@@ -362,16 +365,31 @@
     RTTESTI_CHECK_RETV(cbWritten == 4);
     cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
+    cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[0], 1, &cbRead), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbRead == 1);
     cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten - 1, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
+    cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[1], 1, &cbRead), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbRead == 1);
     cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten - 2, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
+    cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[2], 1, &cbRead), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbRead == 1);
+    cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten - 3, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
     cbRead = ~(size_t)0;
     RTTESTI_CHECK_RC_RETV(RTPipeRead(hPipeR, &abBuf[3], 1, &cbRead), VINF_SUCCESS);
     RTTESTI_CHECK_RETV(cbRead == 1);
     RTTESTI_CHECK_RETV(!memcmp(abBuf, "H2G2", 4));
+    cbRead = ~(size_t)0;
+    RTTESTI_CHECK_RC_RETV(RTPipeQueryReadable(hPipeR, &cbRead), VINF_SUCCESS);
+    RTTESTI_CHECK_MSG(cbRead == cbWritten - 4, ("cbRead=%zu cbWritten=%zu\n", cbRead, cbWritten));
 
     RTTESTI_CHECK_RC_RETV(RTPipeClose(hPipeR), VINF_SUCCESS);
