Index: /trunk/src/VBox/HostServices/GuestControl/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 45481)
+++ /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 45482)
@@ -103,5 +103,6 @@
     VBOXHGCMSVCPARM *mParms;
     /** The standard constructor. */
-    ClientConnection(void) : mHandle(0), mNumParms(0), mParms(NULL) {}
+    ClientConnection(void)
+        : mHandle(0), mNumParms(0), mParms(NULL) {}
 } ClientConnection;
 
@@ -419,5 +420,5 @@
         }
         else
-            LogFlowFunc(("Client has not (yet) submitted enough parameters (%RU32) to at least peak for the next message\n",
+            LogFlowFunc(("Warning: Client has not (yet) submitted enough parameters (%RU32, must be at least 2) to at least peak for the next message\n",
                          pConnection->mNumParms));
 
@@ -479,5 +480,6 @@
           mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0),
           mHostCmdTS(0),
-          mIsPending(false) { }
+          mIsPending(false),
+          mPeekCount(0) { }
 
     ClientState(PVBOXHGCMSVCHELPERS pSvcHelpers, uint32_t uClientID)
@@ -487,5 +489,6 @@
           mHostCmdRc(VINF_SUCCESS), mHostCmdTries(0),
           mHostCmdTS(0),
-          mIsPending(false) { }
+          mIsPending(false),
+          mPeekCount(0){ }
 
     void DequeueAll(void)
@@ -765,17 +768,31 @@
 
         int rc;
+        /* If the client is in pending mode, always send back
+         * the peek result first. */
         if (mIsPending)
         {
-            /* If the client is in pending mode, always send back
-             * the peek result first. */
             rc = pHostCmd->Peek(pConnection);
+            mPeekCount++;
         }
         else
         {
-            /* Try assigning the host command to the client and store the
-             * result code for later use. */
-            rc = pHostCmd->Assign(pConnection);
-            if (RT_FAILURE(rc)) /* If something failed, let the client peek (again). */
+            if (!mPeekCount)
+            {
                 rc = pHostCmd->Peek(pConnection);
+                mPeekCount++;
+            }
+            else
+            {
+                /* Try assigning the host command to the client and store the
+                 * result code for later use. */
+                rc = pHostCmd->Assign(pConnection);
+                if (RT_FAILURE(rc)) /* If something failed, let the client peek (again). */
+                {
+                    rc = pHostCmd->Peek(pConnection);
+                    mPeekCount++;
+                }
+                else
+                    mPeekCount = 0;
+            }
         }
 
@@ -788,6 +805,6 @@
         mSvcHelpers->pfnCallComplete(pConnection->mHandle, rc);
 
-        LogFlowFunc(("[Client %RU32] pConnection=%p, pHostCmd=%p, replyRc=%Rrc\n",
-                     mID, pConnection, pHostCmd, rc));
+        LogFlowFunc(("[Client %RU32] mPeekCount=%RU32, pConnection=%p, pHostCmd=%p, replyRc=%Rrc\n",
+                     mID, mPeekCount, pConnection, pHostCmd, rc));
         return rc;
     }
@@ -810,6 +827,20 @@
     /** Timestamp (us) of last host command processed. */
     uint64_t mHostCmdTS;
-    /** Flag indicating whether the client currently is pending. */
+    /**
+     * Flag indicating whether the client currently is pending.
+     * This means the client waits for a new host command to reply
+     * and won't return from the waiting call until a new host
+     * command is available.
+     */
     bool mIsPending;
+    /**
+     * This is necessary for being compatible with older
+     * Guest Additions. In case there are commands which only
+     * have two (2) parameters and therefore would fit into the
+     * GUEST_MSG_WAIT reply immediately, we now can make sure
+     * that the client first gets back the GUEST_MSG_WAIT results
+     * first.
+     */
+    uint32_t mPeekCount;
     /** The client's pending connection. */
     ClientConnection mPendingCon;
@@ -1346,5 +1377,7 @@
 
                 /*
-                 * The guest only wants skip the currently assigned messages.
+                 * The guest only wants skip the currently assigned messages. Neded
+                 * for dropping its assigned reference of the current assigned host
+                 * command in queue.
                  * Since VBox 4.3+.
                  */
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 45481)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 45482)
@@ -19928,5 +19928,5 @@
     name="IGuestSessionEvent" extends="IEvent"
     uuid="b9acd33f-647d-45ac-8fe9-f49b3183ba37"
-    wsmap="managed" id="GuestSessionEvent"
+    wsmap="managed"
     >
     <desc>Base abstract interface for all guest session events.</desc>
@@ -19984,6 +19984,6 @@
   <interface
     name="IGuestProcessEvent" extends="IGuestSessionEvent"
-    uuid="ee4be6e7-76c5-4517-a623-d4b1957d4ea4"
-    wsmap="managed" id="GuestProcessEvent"
+    uuid="2405f0e5-6588-40a3-9b0a-68c05ba52c4b"
+    wsmap="managed"
     >
     <desc>Base abstract interface for all guest process events.</desc>
@@ -20042,6 +20042,29 @@
 
   <interface
-    name="IGuestProcessInputNotifyEvent" extends="IGuestProcessEvent"
-    uuid="b3d6bb71-0392-4971-a908-f71c931995fd"
+    name="IGuestProcessIOEvent" extends="IGuestProcessEvent"
+    uuid="9ea9227c-e9bb-49b3-bfc7-c5171e93ef38"
+    wsmap="managed"
+    >
+    <desc>
+      Base abstract interface for all guest process input/output (IO) events.
+    </desc>
+
+    <attribute name="handle" type="unsigned long" readonly="yes">
+      <desc>
+        TODO
+      </desc>
+    </attribute>
+
+    <attribute name="processed" type="unsigned long" readonly="yes">
+      <desc>
+        TODO
+      </desc>
+    </attribute>
+
+  </interface>
+  
+  <interface
+    name="IGuestProcessInputNotifyEvent" extends="IGuestProcessIOEvent"
+    uuid="0de887f2-b7db-4616-aac6-cfb94d89ba78"
     wsmap="managed" autogen="VBoxEvent" id="OnGuestProcessInputNotify"
     >
@@ -20056,21 +20079,9 @@
     </attribute>
 
-    <attribute name="handle" type="unsigned long" readonly="yes">
-      <desc>
-        TODO
-      </desc>
-    </attribute>
-
-    <attribute name="processed" type="unsigned long" readonly="yes">
-      <desc>
-        TODO
-      </desc>
-    </attribute>
-
   </interface>
 
   <interface
-    name="IGuestProcessOutputEvent" extends="IGuestProcessEvent"
-    uuid="a13533b9-4aba-4937-836e-81325859c9d8"
+    name="IGuestProcessOutputEvent" extends="IGuestProcessIOEvent"
+    uuid="d3d5f1ee-bcb2-4905-a7ab-cc85448a742b"
     wsmap="managed" autogen="VBoxEvent" id="OnGuestProcessOutput"
     >
@@ -20079,10 +20090,4 @@
     </desc>
 
-    <attribute name="handle" type="unsigned long" readonly="yes">
-      <desc>
-        TODO
-      </desc>
-    </attribute>
-
     <attribute name="data" type="octet" safearray="yes" readonly="yes">
       <desc>
@@ -20095,6 +20100,6 @@
   <interface
     name="IGuestFileEvent" extends="IGuestSessionEvent"
-    uuid="912f748f-d2f9-4fea-84d2-d36a017cc5f8"
-    wsmap="managed" id="GuestFileEvent"
+    uuid="c8adb7b0-057d-4391-b928-f14b06b710c5"
+    wsmap="managed"
     >
     <desc>Base abstract interface for all guest file events.</desc>
@@ -20153,8 +20158,8 @@
     name="IGuestFileIOEvent" extends="IGuestFileEvent"
     uuid="b5191a7c-9536-4ef8-820e-3b0e17e5bbc8"
-    wsmap="managed" id="OnGuestFileIO"
+    wsmap="managed"
     >
     <desc>
-      TODO
+      Base abstract interface for all guest file input/output (IO) events.
     </desc>
 
Index: /trunk/src/VBox/Main/include/GuestProcessImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 45481)
+++ /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 45482)
@@ -78,5 +78,5 @@
     static Utf8Str guestErrorToString(int guestRc);
     bool isReady(void);
-    int readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, size_t *pcbRead, int *pGuestRc);
+    int readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS, void *pvData, size_t cbData, uint32_t *pcbRead, int *pGuestRc);
     static HRESULT setErrorExternal(VirtualBoxBase *pInterface, int guestRc);
     int startProcess(int *pGuestRc);
@@ -84,6 +84,7 @@
     int terminateProcess(int *pGuestRc);
     int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, ProcessWaitResult_T &waitResult, int *pGuestRc);
-    int waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, size_t *pcbProcessed);
-    int waitForOutput(uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, size_t* pcbRead);
+    int waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents), VBoxEventType_T *pType, IEvent **ppEvent);
+    int waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS, ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed);
+    int waitForOutput(uint32_t uHandle, uint32_t uTimeoutMS, void* pvData, size_t cbData, uint32_t *pcbRead);
     int waitForStatusChange(uint32_t fWaitFlags, uint32_t uTimeoutMS, ProcessStatus_T *pProcessStatus, int *pGuestRc);
     int writeData(uint32_t uHandle, uint32_t uFlags, void *pvData, size_t cbData, uint32_t uTimeoutMS, uint32_t *puWritten, int *pGuestRc);
Index: /trunk/src/VBox/Main/src-client/GuestFileImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestFileImpl.cpp	(revision 45481)
+++ /trunk/src/VBox/Main/src-client/GuestFileImpl.cpp	(revision 45482)
@@ -770,5 +770,5 @@
         arrEventTypes.push_back(VBoxEventType_OnGuestFileStateChanged);
         hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(arrEventTypes),
-                                            TRUE /* Passive listener */);
+                                            FALSE /* Passive listener */);
     }
     else
@@ -847,6 +847,4 @@
                 }
             }
-            else
-                vrc = VERR_COM_UNEXPECTED;
 
         } while (!fSignalled);
Index: /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 45481)
+++ /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 45482)
@@ -593,5 +593,5 @@
     {
         fireGuestProcessInputNotifyEvent(mEventSource, mSession, this,
-                                         mData.mPID, inputStatus, 0 /* StdIn */, dataCb.uProcessed);
+                                         mData.mPID, 0 /* StdIn */, dataCb.uProcessed, inputStatus);
     }
 
@@ -739,5 +739,5 @@
 
     fireGuestProcessOutputEvent(mEventSource, mSession, this,
-                                mData.mPID, dataCb.uHandle, ComSafeArrayAsInParam(data));
+                                mData.mPID, dataCb.uHandle, dataCb.cbData, ComSafeArrayAsInParam(data));
 
     LogFlowFuncLeaveRC(vrc);
@@ -746,5 +746,5 @@
 
 int GuestProcess::readData(uint32_t uHandle, uint32_t uSize, uint32_t uTimeoutMS,
-                           void *pvData, size_t cbData, size_t *pcbRead, int *pGuestRc)
+                           void *pvData, size_t cbData, uint32_t *pcbRead, int *pGuestRc)
 {
     LogFlowThisFunc(("uPID=%RU32, uHandle=%RU32, uSize=%RU32, uTimeoutMS=%RU32, pvData=%p, cbData=%RU32, pGuestRc=%p\n",
@@ -1245,19 +1245,21 @@
 }
 
-int GuestProcess::waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS,
-                                     ProcessInputStatus_T *pInputStatus, size_t *pcbProcessed)
-{
+int GuestProcess::waitForEvents(uint32_t uTimeoutMS, ComSafeArrayIn(VBoxEventType_T, pEvents),
+                                VBoxEventType_T *pType, IEvent **ppEvent)
+{
+    AssertPtrReturn(pType, VERR_INVALID_POINTER);
+    AssertPtrReturn(ppEvent, VERR_INVALID_POINTER);
+
     int vrc;
 
     /** @todo Parameter validation. */
+
+    com::SafeArray <VBoxEventType_T> arrEventTypes(ComSafeArrayInArg(pEvents));
 
     ComPtr<IEventListener> pListener;
     HRESULT hr = mEventSource->CreateListener(pListener.asOutParam());
     if (SUCCEEDED(hr))
-    {
-        com::SafeArray <VBoxEventType_T> eventTypes(1);
-        eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
-        hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), false);
-    }
+        hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(arrEventTypes),
+                                            FALSE /* Passive listener */);
     else
         vrc = VERR_COM_UNEXPECTED;
@@ -1265,6 +1267,6 @@
     if (SUCCEEDED(hr))
     {
-        LogFlowThisFunc(("Waiting for guest process input notify event (timeout=%RU32ms, handle=%RU32) ...\n",
-                         uTimeoutMS, uHandle));
+        LogFlowThisFunc(("Waiting for guest file event(s) (timeout=%RU32ms, %zu events) ...\n",
+                         uTimeoutMS, arrEventTypes.size()));
 
         vrc = VINF_SUCCESS;
@@ -1285,68 +1287,51 @@
             }
 
-            ComPtr<IEvent> pEvent;
-            hr = mEventSource->GetEvent(pListener, cMsWait, pEvent.asOutParam());
+            ComPtr<IEvent> pThisEvent;
+            hr = mEventSource->GetEvent(pListener, cMsWait, pThisEvent.asOutParam());
             if (   SUCCEEDED(hr)
-                && !pEvent.isNull())
+                && !pThisEvent.isNull())
             {
-                VBoxEventType_T aType;
-                hr = pEvent->COMGETTER(Type)(&aType);
+                VBoxEventType_T type;
+                hr = pThisEvent->COMGETTER(Type)(&type);
                 ComAssertComRC(hr);
-                switch (aType)
+
+                for (size_t i = 0; i < arrEventTypes.size() && !fSignalled; i++)
                 {
-                    case VBoxEventType_OnGuestProcessInputNotify:
+                    if (type == arrEventTypes[i])
                     {
-                        ComPtr<IGuestProcessInputNotifyEvent> pOutputEvent = pEvent;
-                        Assert(!pOutputEvent.isNull());
-
-                        ComPtr<IGuestSession> pSession;
-                        pOutputEvent->COMGETTER(Session)(pSession.asOutParam());
-                        Assert(!pSession.isNull());
-                        ULONG uSessionID;
-                        hr = pSession->COMGETTER(Id)(&uSessionID);
-                        ComAssertComRC(hr);
-                        if (uSessionID != mSession->getId())
-                            continue; /* Only the session this process runs in is of interest. */
-
-                        ULONG uPID;
-                        hr = pOutputEvent->COMGETTER(Pid)(&uPID);
-                        ComAssertComRC(hr);
-                        if (uPID != mData.mPID)
-                            continue; /* Only the this process is of interest. */
-
-                        ULONG uHandleEvent;
-                        hr = pOutputEvent->COMGETTER(Handle)(&uHandleEvent);
-                        ComAssertComRC(hr);
-
-                        LogFlowThisFunc(("Got output event for process PID=%RU32, handle=%RU32 (session ID=%RU32)\n",
-                                         mData.mPID, uHandleEvent, mSession->getId()));
-
-                        bool fSignal = uHandleEvent == uHandle;
-                        if (!fSignal)
-                            continue;
-
-                        ProcessInputStatus_T inputStatus;
-                        hr = pOutputEvent->COMGETTER(Status)(&inputStatus);
-                        ComAssertComRC(hr);
-
-                        ULONG uProcessed;
-                        hr = pOutputEvent->COMGETTER(Processed)(&uProcessed);
-                        ComAssertComRC(hr);
-
-                        if (pInputStatus)
-                            *pInputStatus = inputStatus;
-                        if (pcbProcessed)
-                            *pcbProcessed = uProcessed;
-
-                        LogFlowThisFunc(("Input notify event for process PID=%RU32 (session ID=%RU32): %zubytes read\n",
-                                         uPID, mSession->getId(), uProcessed));
-
-                        fSignalled = true;
-                        break;
+                        switch (type)
+                        {
+                            case VBoxEventType_OnGuestProcessStateChanged:
+                            case VBoxEventType_OnGuestProcessInputNotify:
+                            case VBoxEventType_OnGuestProcessOutput:
+                            {
+                                ComPtr<IGuestProcessEvent> pFileEvent = pThisEvent;
+                                Assert(!pFileEvent.isNull());
+
+                                ComPtr<IGuestProcess> pProcess;
+                                pFileEvent->COMGETTER(Process)(pProcess.asOutParam());
+                                Assert(!pProcess.isNull());
+
+                                fSignalled = (pProcess == this);
+                                break;
+                            }
+
+                            default:
+                                AssertMsgFailed(("Unhandled event %ld\n", type));
+                                break;
+                        }
+
+                        if (fSignalled)
+                        {
+                            if (pType)
+                                *pType = type;
+                            if (ppEvent)
+                                pThisEvent.queryInterfaceTo(ppEvent);
+                            if (   type == VBoxEventType_OnGuestProcessStateChanged
+                                && RT_SUCCESS(vrc))
+                                vrc = VWRN_GSTCTL_OBJECTSTATE_CHANGED;
+                            break;
+                        }
                     }
-
-                    default:
-                         AssertMsgFailed(("Unhandled event type %ld\n", aType));
-                         break;
                 }
             }
@@ -1360,5 +1345,6 @@
         }
 
-        mEventSource->UnregisterListener(pListener);
+        hr = mEventSource->UnregisterListener(pListener);
+        ComAssertComRC(hr);
     }
     else
@@ -1369,126 +1355,95 @@
 }
 
+int GuestProcess::waitForInputNotify(uint32_t uHandle, uint32_t uTimeoutMS,
+                                     ProcessInputStatus_T *pInputStatus, uint32_t *pcbProcessed)
+{
+    VBoxEventType_T evtType;
+    ComPtr<IEvent> pEvent;
+    com::SafeArray<VBoxEventType_T> eventTypes;
+    eventTypes.push_back(VBoxEventType_OnGuestProcessInputNotify);
+    int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes),
+                           &evtType, pEvent.asOutParam());
+    if (vrc == VINF_SUCCESS) /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
+    {
+        Assert(evtType == VBoxEventType_OnGuestProcessInputNotify);
+        ComPtr<IGuestProcessInputNotifyEvent> pProcessEvent = pEvent;
+        Assert(!pProcessEvent.isNull());
+
+        if (pInputStatus)
+        {
+            HRESULT hr2 = pProcessEvent->COMGETTER(Status)(pInputStatus);
+            ComAssertComRC(hr2);
+        }
+        if (pcbProcessed)
+        {
+            HRESULT hr2 = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbProcessed);
+            ComAssertComRC(hr2);
+        }
+    }
+
+    LogFlowFuncLeaveRC(vrc);
+    return vrc;
+}
+
 int GuestProcess::waitForOutput(uint32_t uHandle, uint32_t uTimeoutMS,
-                                void *pvData, size_t cbData, size_t *pcbRead)
-{
-    int vrc;
-
-    /** @todo Parameter validation. */
-
-    ComPtr<IEventListener> pListener;
-    HRESULT hr = mEventSource->CreateListener(pListener.asOutParam());
-    if (SUCCEEDED(hr))
-    {
-        com::SafeArray <VBoxEventType_T> eventTypes(1);
+                                void *pvData, size_t cbData, uint32_t *pcbRead)
+{
+    VBoxEventType_T evtType;
+    ComPtr<IEvent> pEvent;
+    com::SafeArray<VBoxEventType_T> eventTypes;
+
+    int vrc = VINF_SUCCESS;
+
+    try
+    {
         eventTypes.push_back(VBoxEventType_OnGuestProcessOutput);
-        hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), false);
-    }
-    else
-        vrc = VERR_COM_UNEXPECTED;
-
-    if (SUCCEEDED(hr))
-    {
-        LogFlowThisFunc(("Waiting for guest process output event (timeout=%RU32ms, handle=%RU32) ...\n",
-                         uTimeoutMS, uHandle));
-
-        vrc = VINF_SUCCESS;
-
-        uint64_t u64Started = RTTimeMilliTS();
-        bool fSignalled = false;
-        do
-        {
-            unsigned cMsWait;
-            if (uTimeoutMS == RT_INDEFINITE_WAIT)
-                cMsWait = 1000;
-            else
+    }
+    catch (std::bad_alloc)
+    {
+        vrc = VERR_NO_MEMORY;
+    }
+
+    if (RT_FAILURE(vrc))
+        return vrc;
+
+    do
+    {
+        vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes),
+                           &evtType, pEvent.asOutParam());
+        if (vrc == VINF_SUCCESS) /* Can also return VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
+        {
+            Assert(evtType == VBoxEventType_OnGuestProcessOutput);
+            ComPtr<IGuestProcessOutputEvent> pProcessEvent = pEvent;
+            Assert(!pProcessEvent.isNull());
+
+            ULONG uHandleEvent;
+            HRESULT hr = pProcessEvent->COMGETTER(Handle)(&uHandleEvent);
+            if (uHandleEvent == uHandle)
             {
-                uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
-                if (cMsElapsed >= uTimeoutMS)
-                    break; /* timed out */
-                cMsWait = RT_MIN(1000, uTimeoutMS - (uint32_t)cMsElapsed);
+                if (pvData)
+                {
+                    com::SafeArray <BYTE> data;
+                    hr = pProcessEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
+                    ComAssertComRC(hr);
+                    size_t cbRead = data.size();
+                    if (   cbRead
+                        && cbRead <= cbData)
+                    {
+                        memcpy(pvData, data.raw(), data.size());
+                    }
+                    else
+                        vrc = VERR_BUFFER_OVERFLOW;
+                }
+                if (pcbRead)
+                {
+                    hr = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbRead);
+                    ComAssertComRC(hr);
+                }
+
+                break;
             }
-
-            ComPtr<IEvent> pEvent;
-            hr = mEventSource->GetEvent(pListener, cMsWait, pEvent.asOutParam());
-            if (   SUCCEEDED(hr)
-                && !pEvent.isNull())
-            {
-                VBoxEventType_T aType;
-                hr = pEvent->COMGETTER(Type)(&aType);
-                ComAssertComRC(hr);
-                switch (aType)
-                {
-                    case VBoxEventType_OnGuestProcessOutput:
-                    {
-                        ComPtr<IGuestProcessOutputEvent> pOutputEvent = pEvent;
-                        Assert(!pOutputEvent.isNull());
-
-                        ComPtr<IGuestSession> pSession;
-                        pOutputEvent->COMGETTER(Session)(pSession.asOutParam());
-                        Assert(!pSession.isNull());
-                        ULONG uSessionID;
-                        hr = pSession->COMGETTER(Id)(&uSessionID);
-                        ComAssertComRC(hr);
-                        if (uSessionID != mSession->getId())
-                            continue; /* Only the session this process runs in is of interest. */
-
-                        ULONG uPID;
-                        hr = pOutputEvent->COMGETTER(Pid)(&uPID);
-                        ComAssertComRC(hr);
-                        if (uPID != mData.mPID)
-                            continue; /* Only the this process is of interest. */
-
-                        ULONG uHandleEvent;
-                        hr = pOutputEvent->COMGETTER(Handle)(&uHandleEvent);
-                        ComAssertComRC(hr);
-
-                        LogFlowThisFunc(("Got output event for process PID=%RU32, handle=%RU32 (session ID=%RU32): %ld\n",
-                                         mData.mPID, uHandleEvent, mSession->getId()));
-
-                        bool fSignal = uHandleEvent == uHandle;
-                        if (!fSignal)
-                            continue;
-
-                        com::SafeArray <BYTE> data;
-                        hr = pOutputEvent->COMGETTER(Data)(ComSafeArrayAsOutParam(data));
-                        ComAssertComRC(hr);
-
-                        size_t cbRead = data.size();
-
-                        if (pvData)
-                        {
-                            if (cbRead < cbData)
-                                cbData = cbRead;
-                            memcpy(pvData, data.raw(), cbData);
-                        }
-
-                        if (pcbRead)
-                            *pcbRead = cbRead;
-
-                        LogFlowThisFunc(("Output event for process PID=%RU32 (session ID=%RU32): %zubytes read\n",
-                                         uPID, mSession->getId(), cbRead));
-
-                        fSignalled = true;
-                        break;
-                    }
-
-                    default:
-                         AssertMsgFailed(("Unhandled event type %ld\n", aType));
-                         break;
-                }
-            }
-
-        } while (!fSignalled);
-
-        if (   RT_SUCCESS(vrc)
-            && !fSignalled)
-        {
-            vrc = VERR_TIMEOUT;
-        }
-
-        mEventSource->UnregisterListener(pListener);
-    }
-    else
-        vrc = VERR_COM_UNEXPECTED;
+        }
+
+    } while (RT_SUCCESS(vrc));
 
     LogFlowFuncLeaveRC(vrc);
@@ -1499,135 +1454,38 @@
                                       ProcessStatus_T *pProcessStatus, int *pGuestRc)
 {
-    int vrc;
-
-    ComPtr<IEventListener> pListener;
-    HRESULT hr = mEventSource->CreateListener(pListener.asOutParam());
-    if (SUCCEEDED(hr))
-    {
-        com::SafeArray <VBoxEventType_T> eventTypes(1);
-        eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
-        hr = mEventSource->RegisterListener(pListener, ComSafeArrayAsInParam(eventTypes), false);
-    }
-    else
-        vrc = VERR_COM_UNEXPECTED;
-
-    if (SUCCEEDED(hr))
-    {
-        LogFlowThisFunc(("Waiting for guest process state changed event (timeout=%RU32ms, flags=%x) ...\n",
-                         uTimeoutMS, fWaitFlags));
-
-        vrc = VINF_SUCCESS;
-
-        uint64_t u64Started = RTTimeMilliTS();
-        bool fSignalled = false;
-        do
-        {
-            unsigned cMsWait;
-            if (uTimeoutMS == RT_INDEFINITE_WAIT)
-                cMsWait = 1000;
-            else
-            {
-                uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
-                if (cMsElapsed >= uTimeoutMS)
-                    break; /* timed out */
-                cMsWait = RT_MIN(1000, uTimeoutMS - (uint32_t)cMsElapsed);
-            }
-
-            ComPtr<IEvent> pEvent;
-            hr = mEventSource->GetEvent(pListener, cMsWait, pEvent.asOutParam());
-            if (   SUCCEEDED(hr)
-                && !pEvent.isNull())
-            {
-                VBoxEventType_T aType;
-                hr = pEvent->COMGETTER(Type)(&aType);
-                ComAssertComRC(hr);
-                switch (aType)
-                {
-                    case VBoxEventType_OnGuestProcessStateChanged:
-                    {
-                        ComPtr<IGuestProcessStateChangedEvent> pChangedEvent = pEvent;
-                        Assert(!pChangedEvent.isNull());
-
-                        ComPtr<IGuestSession> pSession;
-                        pChangedEvent->COMGETTER(Session)(pSession.asOutParam());
-                        Assert(!pSession.isNull());
-                        ULONG uSessionID;
-                        hr = pSession->COMGETTER(Id)(&uSessionID);
-                        ComAssertComRC(hr);
-                        if (uSessionID != mSession->getId())
-                            continue; /* Only the session this process runs in is of interest. */
-
-                        ULONG uPID;
-                        hr = pChangedEvent->COMGETTER(Pid)(&uPID);
-                        ComAssertComRC(hr);
-                        if (uPID != mData.mPID)
-                            continue; /* Only the this process is of interest. */
-
-                        ProcessStatus_T processStatus;
-                        pChangedEvent->COMGETTER(Status)(&processStatus);
-                        if (pProcessStatus)
-                            *pProcessStatus = processStatus;
-
-                        LogFlowThisFunc(("Got status changed event for process PID=%RU32 (session ID=%RU32): %ld\n",
-                                         mData.mPID, mSession->getId(), processStatus));
-
-                        bool fSignal = false;
-                        if (fWaitFlags)
-                        {
-                            switch (processStatus)
-                            {
-                                case ProcessStatus_Started:
-                                    fSignal = (fWaitFlags & ProcessWaitForFlag_Start);
-                                    break;
-
-                                default:
-                                    fSignal = true;
-                                    break;
-                            }
-                        }
-                        else
-                            fSignal = true;
-
-                        if (!fSignal)
-                            continue;
-
-                        ComPtr<IGuestErrorInfo> errorInfo;
-                        hr = pChangedEvent->COMGETTER(Error)(errorInfo.asOutParam());
-                        ComAssertComRC(hr);
-
-                        LONG lGuestRc;
-                        hr = errorInfo->COMGETTER(Result)(&lGuestRc);
-                        ComAssertComRC(hr);
-                        if (RT_FAILURE((int)lGuestRc))
-                            vrc = VERR_GSTCTL_GUEST_ERROR;
-                        if (pGuestRc)
-                            *pGuestRc = (int)lGuestRc;
-
-                        LogFlowThisFunc(("Status changed event for process PID=%RU32 (session ID=%RU32): %ld (%Rrc)\n",
-                                         uPID, mSession->getId(), processStatus,
-                                         RT_SUCCESS((int)lGuestRc) ? VINF_SUCCESS : (int)lGuestRc));
-
-                        fSignalled = true;
-                        break;
-                    }
-
-                    default:
-                         AssertMsgFailed(("Unhandled event type %ld\n", aType));
-                         break;
-                }
-            }
-
-        } while (!fSignalled);
-
-        if (   RT_SUCCESS(vrc)
-            && !fSignalled)
-        {
-            vrc = VERR_TIMEOUT;
-        }
-
-        mEventSource->UnregisterListener(pListener);
-    }
-    else
-        vrc = VERR_COM_UNEXPECTED;
+    /* All pointers are optional. */
+
+    VBoxEventType_T evtType;
+    ComPtr<IEvent> pEvent;
+    com::SafeArray<VBoxEventType_T> eventTypes(1);
+    eventTypes.push_back(VBoxEventType_OnGuestProcessStateChanged);
+    int vrc = waitForEvents(uTimeoutMS, ComSafeArrayAsInParam(eventTypes),
+                            &evtType, pEvent.asOutParam());
+    if (RT_SUCCESS(vrc)) /* Includes VWRN_GSTCTL_OBJECTSTATE_CHANGED. */
+    {
+        Assert(evtType == VBoxEventType_OnGuestProcessStateChanged);
+        ComPtr<IGuestProcessStateChangedEvent> pProcessEvent = pEvent;
+        Assert(!pProcessEvent.isNull());
+
+        HRESULT hr;
+        if (pProcessStatus)
+        {
+            hr = pProcessEvent->COMGETTER(Status)(pProcessStatus);
+            ComAssertComRC(hr);
+        }
+
+        ComPtr<IGuestErrorInfo> errorInfo;
+        hr = pProcessEvent->COMGETTER(Error)(errorInfo.asOutParam());
+        ComAssertComRC(hr);
+
+        LONG lGuestRc;
+        hr = errorInfo->COMGETTER(Result)(&lGuestRc);
+        ComAssertComRC(hr);
+        if (RT_FAILURE((int)lGuestRc))
+            vrc = VERR_GSTCTL_GUEST_ERROR;
+
+        if (pGuestRc)
+            *pGuestRc = (int)lGuestRc;
+    }
 
     LogFlowFuncLeaveRC(vrc);
@@ -1675,5 +1533,5 @@
 
         ProcessInputStatus_T inputStatus;
-        size_t cbProcessed;
+        uint32_t cbProcessed;
         vrc = waitForInputNotify(uHandle, uTimeoutMS, &inputStatus, &cbProcessed);
         if (RT_SUCCESS(vrc))
@@ -1711,5 +1569,5 @@
     HRESULT hr = S_OK;
 
-    size_t cbRead; int guestRc;
+    uint32_t cbRead; int guestRc;
     int vrc = readData(aHandle, aToRead, aTimeoutMS, data.raw(), aToRead, &cbRead, &guestRc);
     if (RT_SUCCESS(vrc))
@@ -2079,5 +1937,5 @@
 
     BYTE byBuf[_64K];
-    size_t cbRead;
+    uint32_t cbRead;
 
     bool fHandleStdOut = false;
Index: /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp	(revision 45481)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImplTasks.cpp	(revision 45482)
@@ -695,5 +695,5 @@
                             RTThreadSleep(1); /* Optional, don't check rc. */
 
-                        size_t cbRead;
+                        uint32_t cbRead;
                         rc = pProcess->readData(OUTPUT_HANDLE_ID_STDOUT, sizeof(byBuf),
                                                 30 * 1000 /* Timeout */, byBuf, sizeof(byBuf),
