Index: /trunk/include/iprt/poll.h
===================================================================
--- /trunk/include/iprt/poll.h	(revision 27508)
+++ /trunk/include/iprt/poll.h	(revision 27509)
@@ -181,5 +181,5 @@
  * @param   hPollSet            The poll set.
  */
-RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet);
+RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet);
 
 /**
@@ -200,4 +200,5 @@
     RTHANDLE Handle;
     Handle.enmType = RTHANDLETYPE_PIPE;
+    Handle.u.uInt  = 0;
     Handle.u.hPipe = hPipe;
     return RTPollSetAdd(hPollSet, &Handle, fEvents, id);
@@ -218,4 +219,5 @@
     RTHANDLE Handle;
     Handle.enmType   = RTHANDLETYPE_SOCKET;
+    Handle.u.uInt    = 0;
     Handle.u.hSocket = hSocket;
     return RTPollSetAdd(hPollSet, &Handle, fEvents, id);
Index: /trunk/include/iprt/types.h
===================================================================
--- /trunk/include/iprt/types.h	(revision 27508)
+++ /trunk/include/iprt/types.h	(revision 27509)
@@ -1404,4 +1404,8 @@
     RTSOCKET        hSocket;            /**< Socket handle. */
     RTTHREAD        hThread;            /**< Thread handle. */
+    /** Generic integer handle value.
+     * Note that RTFILE is not yet pointer sized, so accessing it via this member
+     * isn't necessarily safe or fully portable. */
+    RTHCUINTPTR     uInt;
 } RTHANDLEUNION;
 /** Pointer to a handle union. */
Index: /trunk/src/VBox/Runtime/include/internal/pipe.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/pipe.h	(revision 27508)
+++ /trunk/src/VBox/Runtime/include/internal/pipe.h	(revision 27509)
@@ -33,11 +33,12 @@
 
 #include <iprt/pipe.h>
+/* Requires Windows.h on windows. */
 
 RT_C_DECLS_BEGIN
 
 #ifdef RT_OS_WINDOWS
-int         rtPipePollGetHandles(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph1, PHANDLE ph2);
-uint32_t    rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fNoWait);
-uint32_t    rtPipePollDone(RTPIPE hPipe, uint32_t fEvents);
+int         rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph);
+uint32_t    rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait);
+uint32_t    rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry);
 #endif /* RT_OS_WINDOWS */
 
Index: /trunk/src/VBox/Runtime/include/internal/socket.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/socket.h	(revision 27508)
+++ /trunk/src/VBox/Runtime/include/internal/socket.h	(revision 27509)
@@ -34,15 +34,17 @@
 #include <iprt/cdefs.h>
 #include <iprt/types.h>
+/* Currently requires a bunch of socket headers. */
 
 
 RT_C_DECLS_BEGIN
 
+#ifndef IPRT_INTERNAL_SOCKET_POLLING_ONLY
 int rtSocketResolverError(void);
 int rtSocketCreateForNative(RTSOCKETINT **ppSocket,
-#ifdef RT_OS_WINDOWS
+# ifdef RT_OS_WINDOWS
                             SOCKET hNative
-#else
+# else
                             int hNative
-#endif
+# endif
                             );
 int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol);
@@ -52,4 +54,11 @@
 int rtSocketConnect(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr);
 int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue);
+#endif /* IPRT_INTERNAL_SOCKET_POLLING_ONLY */
+
+#ifdef RT_OS_WINDOWS
+int         rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph);
+uint32_t    rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait);
+uint32_t    rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry);
+#endif /* RT_OS_WINDOWS */
 
 RT_C_DECLS_END
Index: /trunk/src/VBox/Runtime/r3/os2/poll-os2.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/os2/poll-os2.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/r3/os2/poll-os2.cpp	(revision 27509)
@@ -83,5 +83,5 @@
 
 
-RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
+RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
 {
     return UINT32_MAX;
Index: /trunk/src/VBox/Runtime/r3/posix/poll-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/poll-posix.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/r3/posix/poll-posix.cpp	(revision 27509)
@@ -184,5 +184,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int rc;
@@ -224,5 +224,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
@@ -260,5 +260,5 @@
     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
@@ -293,5 +293,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int rc = VINF_SUCCESS;
@@ -407,5 +407,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
@@ -444,5 +444,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
@@ -465,5 +465,5 @@
 
 
-RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
+RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
 {
     /*
Index: /trunk/src/VBox/Runtime/r3/socket.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/socket.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/r3/socket.cpp	(revision 27509)
@@ -60,4 +60,5 @@
 #include <iprt/err.h>
 #include <iprt/mem.h>
+#include <iprt/poll.h>
 #include <iprt/string.h>
 #include <iprt/thread.h>
@@ -134,4 +135,7 @@
     /** The events we're polling for. */
     uint32_t            fPollEvts;
+    /** The events we're currently subscribing to with WSAEventSelect.
+     * This is ZERO if we're currently not subscribing to anything. */
+    uint32_t            fSubscribedEvts;
 #else
     /** The native socket handle. */
@@ -258,11 +262,12 @@
     if (!pThis)
         return VERR_NO_MEMORY;
-    pThis->u32Magic     = RTSOCKET_MAGIC;
-    pThis->cUsers       = 0;
-    pThis->hNative      = hNative;
-#ifdef RT_OS_WINDOWS
-    pThis->hEvent       = WSA_INVALID_EVENT;
-    pThis->hPollSet     = NIL_RTPOLLSET;
-    pThis->fPollEvts    = 0;
+    pThis->u32Magic         = RTSOCKET_MAGIC;
+    pThis->cUsers           = 0;
+    pThis->hNative          = hNative;
+#ifdef RT_OS_WINDOWS
+    pThis->hEvent           = WSA_INVALID_EVENT;
+    pThis->hPollSet         = NIL_RTPOLLSET;
+    pThis->fPollEvts        = 0;
+    pThis->fSubscribedEvts  = 0;
 #endif
     *ppSocket = pThis;
@@ -870,2 +875,222 @@
 }
 
+#ifdef RT_OS_WINDOWS
+
+/**
+ * Internal RTPollSetAdd helper that returns the handle that should be added to
+ * the pollset.
+ *
+ * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
+ * @param   hSocket             The socket handle.
+ * @param   fEvents             The events we're polling for.
+ * @param   ph                  wher to put the primary handle.
+ */
+int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph)
+{
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
+
+    int rc = VINF_SUCCESS;
+    if (pThis->hEvent != WSA_INVALID_EVENT)
+        *ph = pThis->hEvent;
+    else
+    {
+        *ph = pThis->hEvent = WSACreateEvent();
+        if (pThis->hEvent == WSA_INVALID_EVENT)
+            rc = rtSocketError();
+    }
+
+    rtSocketUnlock(pThis);
+    return rc;
+}
+
+
+/**
+ * Updates the mask of events we're subscribing to.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               The socket handle.
+ * @param   fEvents             The events we want to subscribe to.
+ */
+static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
+{
+    LONG fNetworkEvents = 0;
+    if (fEvents & RTPOLL_EVT_READ)
+        fNetworkEvents |= FD_READ;
+    if (fEvents & RTPOLL_EVT_WRITE)
+        fNetworkEvents |= FD_WRITE;
+    if (fEvents & RTPOLL_EVT_ERROR)
+        fNetworkEvents |= FD_CLOSE;
+    if (WSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0)
+    {
+        pThis->fSubscribedEvts = fEvents;
+
+        u_long fNonBlocking = 0;
+        if (ioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking))
+            AssertMsgFailed(("%Rrc\n", rtSocketError()));
+
+        return VINF_SUCCESS;
+    }
+
+    int rc = rtSocketError();
+    AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError()));
+    return rc;
+}
+
+
+/**
+ * Checks for pending events.
+ *
+ * @returns Event mask or 0.
+ * @param   pThis               The socket handle.
+ * @param   fEvents             The desired events.
+ */
+static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
+{
+    int         rc         = VINF_SUCCESS;
+    uint32_t    fRetEvents = 0;
+
+    /* Make sure WSAEnumNetworkEvents returns what we want. */
+    if ((pThis->fSubscribedEvts & fEvents) != fEvents)
+        rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
+
+    /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff.  */
+    WSANETWORKEVENTS NetEvts;
+    RT_ZERO(NetEvts);
+    if (WSAEnumNetworkEvents(pThis->hNative, pThis->hEvent, &NetEvts) == 0)
+    {
+        if (    (NetEvts.lNetworkEvents & FD_READ)
+            &&  (fEvents & RTPOLL_EVT_READ)
+            &&  NetEvts.iErrorCode[FD_READ_BIT] == 0)
+            fRetEvents |= RTPOLL_EVT_READ;
+
+        if (    (NetEvts.lNetworkEvents & FD_WRITE)
+            &&  (fEvents & RTPOLL_EVT_WRITE)
+            &&  NetEvts.iErrorCode[FD_WRITE_BIT] == 0)
+            fRetEvents |= RTPOLL_EVT_WRITE;
+
+        if (fEvents & RTPOLL_EVT_ERROR)
+        {
+            if (NetEvts.lNetworkEvents & FD_CLOSE)
+                fRetEvents |= RTPOLL_EVT_ERROR;
+            else
+                for (uint32_t i = 0; i < FD_MAX_EVENTS; i++)
+                    if (    (NetEvts.lNetworkEvents & (1L << i))
+                        &&  NetEvts.iErrorCode[i] != 0)
+                        fRetEvents |= RTPOLL_EVT_ERROR;
+        }
+    }
+    else
+        rc = rtSocketError();
+
+    /* Fall back on select if we hit an error above. */
+    if (RT_FAILURE(rc))
+    {
+        /** @todo  */
+    }
+
+    return fRetEvents;
+}
+
+
+/**
+ * Internal RTPoll helper that polls the socket handle and, if @a fNoWait is
+ * clear, starts whatever actions we've got running during the poll call.
+ *
+ * @returns 0 if no pending events, actions initiated if @a fNoWait is clear.
+ *          Event mask (in @a fEvents) and no actions if the handle is ready
+ *          already.
+ *          UINT32_MAX (asserted) if the socket handle is busy in I/O or a
+ *          different poll set.
+ *
+ * @param   hSocket             The socket handle.
+ * @param   hPollSet            The poll set handle (for access checks).
+ * @param   fEvents             The events we're polling for.
+ * @param   fFinalEntry         Set if this is the final entry for this handle
+ *                              in this poll set.  This can be used for dealing
+ *                              with duplicate entries.
+ * @param   fNoWait             Set if it's a zero-wait poll call.  Clear if
+ *                              we'll wait for an event to occur.
+ *
+ * @remarks There is a potential race wrt duplicate handles when @a fNoWait is
+ *          @c true, we don't currently care about that oddity...
+ */
+uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
+{
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, UINT32_MAX);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
+    if (rtSocketTryLock(pThis))
+        pThis->hPollSet = hPollSet;
+    else
+    {
+        AssertReturn(pThis->hPollSet == hPollSet, UINT32_MAX);
+        ASMAtomicIncU32(&pThis->cUsers);
+    }
+
+    /* (rtSocketPollCheck will reset the event object). */
+    uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
+    if (   !fRetEvents
+        && !fNoWait)
+    {
+        pThis->fPollEvts |= fEvents;
+        if (   fFinalEntry
+            && pThis->fSubscribedEvts != pThis->fPollEvts)
+        {
+            int rc = rtSocketPollUpdateEvents(pThis, pThis->fPollEvts);
+            if (RT_FAILURE(rc))
+            {
+                pThis->fPollEvts = 0;
+                fRetEvents       = UINT32_MAX;
+            }
+        }
+    }
+
+    if (fRetEvents || fNoWait)
+    {
+        if (pThis->cUsers == 1)
+            pThis->hPollSet = NIL_RTPOLLSET;
+        ASMAtomicDecU32(&pThis->cUsers);
+    }
+
+    return fRetEvents;
+}
+
+
+/**
+ * Called after a WaitForMultipleObjects returned in order to check for pending
+ * events and stop whatever actions that rtSocketPollStart() initiated.
+ *
+ * @returns Event mask or 0.
+ *
+ * @param   hSocket             The socket handle.
+ * @param   fEvents             The events we're polling for.
+ * @param   fFinalEntry         Set if this is the final entry for this handle
+ *                              in this poll set.  This can be used for dealing
+ *                              with duplicate entries.  Only keep in mind that
+ *                              this method is called in reverse order, so the
+ *                              first call will have this set (when the entire
+ *                              set was processed).
+ */
+uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry)
+{
+    RTSOCKETINT *pThis = hSocket;
+    AssertPtrReturn(pThis, 0);
+    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, 0);
+    Assert(pThis->cUsers > 0);
+    Assert(pThis->hPollSet != NIL_RTPOLLSET);
+
+    /* Harvest events and clear the event mask for the next round of polling. */
+    uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
+    pThis->fPollEvts = 0;
+
+    /* unlock the socket. */
+    if (pThis->cUsers == 1)
+        pThis->hPollSet = NIL_RTPOLLSET;
+    ASMAtomicDecU32(&pThis->cUsers);
+    return fRetEvents;
+}
+
+#endif /* RT_OS_WINDOWS */
Index: /trunk/src/VBox/Runtime/r3/win/pipe-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/pipe-win.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/r3/win/pipe-win.cpp	(revision 27509)
@@ -1018,14 +1018,13 @@
 
 /**
- * Internal RTPollSetAdd helper that returns one or two handles that should be
- * added to the pollset.
+ * Internal RTPollSetAdd helper that returns the handle that should be added to
+ * the pollset.
  *
  * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
  * @param   hPipe               The pipe handle.
  * @param   fEvents             The events we're polling for.
- * @param   ph1                 wher to put the primary handle.
- * @param   ph2                 Where to optionally return a 2nd handle.
+ * @param   ph                  wher to put the primary handle.
  */
-int rtPipePollGetHandles(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph1, PHANDLE ph2)
+int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph)
 {
     RTPIPEINTERNAL *pThis = hPipe;
@@ -1036,9 +1035,8 @@
     AssertReturn(!(fEvents & RTPOLL_EVT_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
 
-    *ph1 = pThis->Overlapped.hEvent;
     /* Later: Try register an event handle with the pipe like on OS/2, there is
        a file control for doing this obviously intended for the OS/2 subsys.
        The question is whether this still exists on Vista and W7. */
-    *ph2 = INVALID_HANDLE_VALUE;
+    *ph = pThis->Overlapped.hEvent;
     return VINF_SUCCESS;
 }
@@ -1127,8 +1125,11 @@
  * @param   hPollSet            The poll set handle (for access checks).
  * @param   fEvents             The events we're polling for.
+ * @param   fFinalEntry         Set if this is the final entry for this handle
+ *                              in this poll set.  This can be used for dealing
+ *                              with duplicate entries.
  * @param   fNoWait             Set if it's a zero-wait poll call.  Clear if
  *                              we'll wait for an event to occur.
  */
-uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fNoWait)
+uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
 {
     /** @todo All this polling code could be optimized to make fewer system
@@ -1207,6 +1208,12 @@
  * @param   hPipe               The pipe handle.
  * @param   fEvents             The events we're polling for.
+ * @param   fFinalEntry         Set if this is the final entry for this handle
+ *                              in this poll set.  This can be used for dealing
+ *                              with duplicate entries.  Only keep in mind that
+ *                              this method is called in reverse order, so the
+ *                              first call will have this set (when the entire
+ *                              set was processed).
  */
-uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents)
+uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry)
 {
     RTPIPEINTERNAL *pThis = hPipe;
Index: /trunk/src/VBox/Runtime/r3/win/poll-win.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/win/poll-win.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/r3/win/poll-win.cpp	(revision 27509)
@@ -2,4 +2,6 @@
 /** @file
  * IPRT - Polling I/O Handles, Windows Implementation.
+ *
+ * @todo merge poll-win.cpp and poll-posix.cpp, there is lots of common code.
  */
 
@@ -46,5 +48,8 @@
 #include <iprt/thread.h>
 #include <iprt/time.h>
+
 #include "internal/pipe.h"
+#define IPRT_INTERNAL_SOCKET_POLLING_ONLY
+#include "internal/socket.h"
 #include "internal/magics.h"
 
@@ -64,4 +69,8 @@
     /** The events we're waiting for here. */
     uint32_t        fEvents;
+    /** Set if this is the final entry for this handle.
+     * If the handle is entered more than once, this will be clear for all but
+     * the last entry. */
+    bool            fFinalEntry;
     /** The handle union. */
     RTHANDLEUNION   u;
@@ -123,5 +132,11 @@
         {
             case RTHANDLETYPE_PIPE:
-                fEvents = rtPipePollStart(pThis->aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents, fNoWait);
+                fEvents = rtPipePollStart(pThis->aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents,
+                                          pThis->aHandles[i].fFinalEntry, fNoWait);
+                break;
+
+            case RTHANDLETYPE_SOCKET:
+                fEvents = rtSocketPollStart(pThis->aHandles[i].u.hSocket, pThis, pThis->aHandles[i].fEvents,
+                                            pThis->aHandles[i].fFinalEntry, fNoWait);
                 break;
 
@@ -155,6 +170,13 @@
                 {
                     case RTHANDLETYPE_PIPE:
-                        rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents);
+                        rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
+                                       pThis->aHandles[i].fFinalEntry);
                         break;
+
+                    case RTHANDLETYPE_SOCKET:
+                        rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
+                                         pThis->aHandles[i].fFinalEntry);
+                        break;
+
                     default:
                         AssertFailed();
@@ -198,6 +220,13 @@
         {
             case RTHANDLETYPE_PIPE:
-                fEvents = rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents);
-                break;
+                rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
+                               pThis->aHandles[i].fFinalEntry);
+                break;
+
+            case RTHANDLETYPE_SOCKET:
+                rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
+                                 pThis->aHandles[i].fFinalEntry);
+                break;
+
             default:
                 AssertFailed();
@@ -230,5 +259,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int rc;
@@ -270,5 +299,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
@@ -305,5 +334,5 @@
     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
@@ -334,19 +363,22 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
-
-    int     rc       = VINF_SUCCESS;
-    HANDLE  hNative  = INVALID_HANDLE_VALUE;
-    HANDLE  hNative2 = INVALID_HANDLE_VALUE;
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
+
+    int             rc       = VINF_SUCCESS;
+    HANDLE          hNative  = INVALID_HANDLE_VALUE;
+    RTHANDLEUNION   uh;
+    uh.uInt = 0;
     switch (pHandle->enmType)
     {
         case RTHANDLETYPE_PIPE:
-            if (pHandle->u.hPipe != NIL_RTPIPE)
-                rc = rtPipePollGetHandles(pHandle->u.hPipe, fEvents, &hNative, &hNative2);
+            uh.hPipe = pHandle->u.hPipe;
+            if (uh.hPipe != NIL_RTPIPE)
+                rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative);
             break;
 
         case RTHANDLETYPE_SOCKET:
-            if (pHandle->u.hSocket != NIL_RTSOCKET)
-                rc = VERR_NOT_IMPLEMENTED;
+            uh.hSocket = pHandle->u.hSocket;
+            if (uh.hSocket != NIL_RTSOCKET)
+                rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative);
             break;
 
@@ -372,6 +404,8 @@
 
         /* Check that the handle ID doesn't exist already. */
-        uint32_t j = i;
+        uint32_t iPrev = UINT32_MAX;
+        uint32_t j     = i;
         while (j-- > 0)
+        {
             if (pThis->aHandles[j].id == id)
             {
@@ -379,24 +413,28 @@
                 break;
             }
+            if (   pThis->aHandles[j].enmType == pHandle->enmType
+                && pThis->aHandles[j].u.uInt  == uh.uInt)
+                iPrev = j;
+        }
 
         /* Check that we won't overflow the poll set now. */
         if (    RT_SUCCESS(rc)
-            &&  i + 1 + (hNative2 != INVALID_HANDLE_VALUE) > RT_ELEMENTS(pThis->ahNative))
+            &&  i + 1 > RT_ELEMENTS(pThis->ahNative))
             rc = VERR_POLL_SET_IS_FULL;
         if (RT_SUCCESS(rc))
         {
             /* Add the handles to the two parallel arrays. */
-            pThis->ahNative[i]         = hNative;
-            pThis->aHandles[i].enmType = pHandle->enmType;
-            pThis->aHandles[i].u       = pHandle->u;
-            pThis->aHandles[i].id      = id;
-            pThis->aHandles[i].fEvents = fEvents;
-            if (hNative2 == INVALID_HANDLE_VALUE)
-                pThis->cHandles = i + 1;
-            else
+            pThis->ahNative[i]             = hNative;
+            pThis->aHandles[i].enmType     = pHandle->enmType;
+            pThis->aHandles[i].u           = uh;
+            pThis->aHandles[i].id          = id;
+            pThis->aHandles[i].fEvents     = fEvents;
+            pThis->aHandles[i].fFinalEntry = true;
+            pThis->cHandles = i + 1;
+
+            if (iPrev != UINT32_MAX)
             {
-                pThis->ahNative[i + 1] = hNative2;
-                pThis->aHandles[i + 1] = pThis->aHandles[i];
-                pThis->cHandles = i + 2;
+                Assert(pThis->aHandles[i].fFinalEntry);
+                pThis->aHandles[i].fFinalEntry = false;
             }
 
@@ -423,5 +461,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
@@ -430,4 +468,10 @@
         if (pThis->aHandles[i].id == id)
         {
+            /* Save some details for the duplicate searching. */
+            bool            fFinalEntry = pThis->aHandles[i].fFinalEntry;
+            RTHANDLETYPE    enmType     = pThis->aHandles[i].enmType;
+            RTHANDLEUNION   uh          = pThis->aHandles[i].u;
+
+            /* Remove the entry. */
             pThis->cHandles--;
             size_t const cToMove = pThis->cHandles - i;
@@ -437,5 +481,18 @@
                 memmove(&pThis->ahNative[i], &pThis->ahNative[i + 1], cToMove * sizeof(pThis->ahNative[i]));
             }
+
+            /* Check for duplicate and set the fFinalEntry flag. */
+            if (fFinalEntry)
+                while (i-- > 0)
+                    if (   pThis->aHandles[i].u.uInt  == uh.uInt
+                        && pThis->aHandles[i].enmType == enmType)
+                    {
+                        Assert(!pThis->aHandles[i].fFinalEntry);
+                        pThis->aHandles[i].fFinalEntry = true;
+                        break;
+                    }
+
             rc = VINF_SUCCESS;
+            break;
         }
 
@@ -459,5 +516,5 @@
      * Set the busy flag and do the job.
      */
-    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_WRONG_ORDER);
+    AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true,  false), VERR_CONCURRENT_ACCESS);
 
     int         rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
@@ -480,5 +537,5 @@
 
 
-RTDECL(uint32_t) RTPollSetCount(RTPOLLSET hPollSet)
+RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
 {
     /*
@@ -499,3 +556,2 @@
 }
 
-
Index: /trunk/src/VBox/Runtime/testcase/tstRTPoll.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTPoll.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/testcase/tstRTPoll.cpp	(revision 27509)
@@ -59,5 +59,5 @@
     RTTESTI_CHECK_RC(RTPollSetRemove(hSetInvl, 1), VERR_INVALID_HANDLE);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSetInvl, 1, NULL), VERR_INVALID_HANDLE);
-    RTTESTI_CHECK(RTPollSetCount(hSetInvl) == UINT32_MAX);
+    RTTESTI_CHECK(RTPollSetGetCount(hSetInvl) == UINT32_MAX);
     RTTESTI_CHECK_RC(RTPoll(hSetInvl, 0, NULL, NULL),  VERR_INVALID_HANDLE);
     RTTESTI_CHECK_RC(RTPollNoResume(hSetInvl, 0, NULL, NULL),  VERR_INVALID_HANDLE);
@@ -125,12 +125,12 @@
     RTTESTI_CHECK_RETV(hSet != NIL_RTPOLLSET);
 
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 0);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 0, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND);
 
     RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, NIL_RTPIPE, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 0);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND);
     RTTESTI_CHECK_RC(RTPollSetRemove(hSet, 0), VERR_POLL_HANDLE_ID_NOT_FOUND);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 0);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 0);
 
     RTTESTI_CHECK_RC(RTPollSetDestroy(hSet), VINF_SUCCESS);
@@ -149,5 +149,5 @@
     /* add the read pipe */
     RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 1);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS);
     RTHANDLE Handle;
@@ -162,5 +162,5 @@
     /* add the write pipe */
     RTTESTI_CHECK_RC(RTPollSetAddPipe(hSet, hPipeW, RTPOLL_EVT_WRITE, 10 /*id*/), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 2);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 10 /*id*/, NULL), VINF_SUCCESS);
 
@@ -276,5 +276,5 @@
     /* Remove the read pipe, do a quick poll check. */
     RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 1);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND);
     RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS);
@@ -289,5 +289,5 @@
 
     RTTESTI_CHECK_RC_RETV(RTPollSetAddPipe(hSet, hPipeR, RTPOLL_EVT_READ, 1 /*id*/), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 2);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 2);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VINF_SUCCESS);
 
@@ -308,5 +308,5 @@
     /* Remove it again and break the pipe by closing the read end. */
     RTTESTI_CHECK_RC_RETV(RTPollSetRemove(hSet, 1), VINF_SUCCESS);
-    RTTESTI_CHECK_RETV(RTPollSetCount(hSet) == 1);
+    RTTESTI_CHECK_RETV(RTPollSetGetCount(hSet) == 1);
     RTTESTI_CHECK_RC(RTPollSetQueryHandle(hSet, 1 /*id*/, NULL), VERR_POLL_HANDLE_ID_NOT_FOUND);
     RTTESTI_CHECK_RC_RETV(RTPollSetQueryHandle(hSet, 10 /*id*/, &Handle), VINF_SUCCESS);
Index: /trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp	(revision 27508)
+++ /trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp	(revision 27509)
@@ -118,5 +118,5 @@
         char *pszDomain = (char *)RTMemAlloc(cbDomain); /* Size in TCHAR! */
         AssertPtr(pszDomain);
-    
+
         if (!LookupAccountName(NULL /* Current system */,
                                szUser,
