Index: /trunk/src/VBox/Main/include/GuestProcessImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 42435)
+++ /trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 42436)
@@ -90,5 +90,4 @@
     inline int callbackRemove(ULONG uContextID);
     inline bool isAlive(void);
-    HRESULT hgcmResultToError(int rc);
     int onGuestDisconnected(GuestCtrlCallback *pCallback, PCALLBACKDATACLIENTDISCONNECTED pData);
     int onProcessInputStatus(GuestCtrlCallback *pCallback, PCALLBACKDATAEXECINSTATUS pData);
@@ -97,5 +96,7 @@
     int prepareExecuteEnv(const char *pszEnv, void **ppvList, ULONG *pcbList, ULONG *pcEnvVars);
     int sendCommand(uint32_t uFunction, uint32_t uParms, PVBOXHGCMSVCPARM paParms);
-    int signalWaiters(ProcessWaitResult_T enmWaitResult, int rc = VINF_SUCCESS);
+    int setErrorInternal(int rc, const Utf8Str &strMessage);
+    int setErrorExternal(void);
+    int signalWaiters(ProcessWaitResult_T enmWaitResult);
     static DECLCALLBACK(int) startProcessThread(RTTHREAD Thread, void *pvUser);
     HRESULT waitResultToErrorEx(const GuestProcessWaitResult &waitResult, bool fLog);
@@ -125,4 +126,9 @@
         /** The current process status. */
         ProcessStatus_T          mStatus;
+        /** The overall rc of the process execution. */
+        int                      mRC;
+        /** The overall error message of the
+         *  process execution. */
+        Utf8Str                  mErrorMsg;
         /** The next upcoming context ID. */
         ULONG                    mNextContextID;
Index: /trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42435)
+++ /trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42436)
@@ -117,6 +117,6 @@
     typedef std::vector <ComObjPtr<GuestFile> > SessionFiles;
     /** Map of guest processes. The key specifies the internal process number.
-     *  To retrieve the process' guest PID use the Id() method of the IProgress interface. */
-    typedef std::map <ULONG, ComObjPtr<GuestProcess> > SessionProcesses;
+     *  To retrieve the process' guest PID use the Id() method of the IProcess interface. */
+    typedef std::map <uint32_t, ComObjPtr<GuestProcess> > SessionProcesses;
 
 public:
Index: /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 42435)
+++ /trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 42436)
@@ -702,5 +702,6 @@
 
 #ifdef DEBUG
-    LogFlowFunc(("uSession=%RU32, uProcess=%RU32, uCount=%RU32\n",
+    LogFlowFunc(("CID=%RU32, uSession=%RU32, uProcess=%RU32, uCount=%RU32\n",
+                 pHeader->u32ContextID,
                  VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(pHeader->u32ContextID),
                  VBOX_GUESTCTRL_CONTEXTID_GET_PROCESS(pHeader->u32ContextID),
@@ -2686,12 +2687,14 @@
     LogFlowFuncEnter();
 
-    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
-    AssertReturn(cbData, VERR_INVALID_PARAMETER);
-
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
+    uint32_t uSessionID = VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID);
+#ifdef DEBUG
+    LogFlowFunc(("uSessionID=%RU32 (%RU32 total)\n",
+                 uSessionID, mData.mGuestSessions.size()));
+#endif
     int rc;
     GuestSessions::const_iterator itSession
-        = mData.mGuestSessions.find(VBOX_GUESTCTRL_CONTEXTID_GET_SESSION(uContextID));
+        = mData.mGuestSessions.find(uSessionID);
     if (itSession != mData.mGuestSessions.end())
     {
@@ -2765,4 +2768,7 @@
 
         mData.mGuestSessions[uNewSessionID] = pGuestSession;
+
+        LogFlowFunc(("Added new session with session ID=%RU32\n",
+                     uNewSessionID));
     }
     catch (int rc2)
@@ -2818,5 +2824,5 @@
             case VERR_MAX_PROCS_REACHED:
                 hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest sessions (%ld) reached"),
-                              VERR_MAX_PROCS_REACHED);
+                              VBOX_GUESTCTRL_MAX_SESSIONS);
                 break;
 
Index: /trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp	(revision 42435)
+++ /trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp	(revision 42436)
@@ -374,6 +374,8 @@
     while (*pszString != '\0' && RT_SUCCESS(rc))
     {
-         if (!RT_C_IS_ALNUM(*pszString++))
+         if (   !RT_C_IS_ALNUM(*pszString)
+             && !RT_C_IS_GRAPH(*pszString))
              rc = VERR_INVALID_PARAMETER;
+         *pszString++;
     }
 
@@ -406,5 +408,9 @@
             strValue = listPair.at(p++);
 
-       rc = Set(strKey, strValue);
+#ifdef DEBUG
+        LogFlowFunc(("strKey=%s, strValue=%s\n",
+                     strKey.c_str(), strValue.c_str()));
+#endif
+        rc = Set(strKey, strValue);
     }
 
Index: /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 42435)
+++ /trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 42436)
@@ -41,10 +41,11 @@
 {
     GuestProcessTask(GuestProcess *pProcess)
-        : mProcess(pProcess) { }
-
-    ~GuestProcessTask(void) { }
-
-    int rc() const { return mRC; }
-    bool isOk() const { return RT_SUCCESS(rc()); }
+        : mProcess(pProcess),
+          mRC(VINF_SUCCESS) { }
+
+    virtual ~GuestProcessTask(void) { }
+
+    int rc(void) const { return mRC; }
+    bool isOk(void) const { return RT_SUCCESS(rc()); }
 
     const ComObjPtr<GuestProcess>    mProcess;
@@ -74,4 +75,5 @@
     mData.mPID = 0;
     mData.mProcessID = 0;
+    mData.mRC = VINF_SUCCESS;
     mData.mStatus = ProcessStatus_Undefined;
 
@@ -97,4 +99,7 @@
 int GuestProcess::init(Console *aConsole, GuestSession *aSession, ULONG aProcessID, const GuestProcessInfo &aProcInfo)
 {
+    LogFlowThisFunc(("aConsole=%p, aSession=%p, aProcessID=%RU32\n",
+                     aConsole, aSession, aProcessID));
+
     AssertPtrReturn(aSession, VERR_INVALID_POINTER);
 
@@ -332,6 +337,6 @@
         /* Create a new context ID ... */
         uNewContextID = VBOX_GUESTCTRL_CONTEXTID_MAKE(uSessionID,
-                                                      mData.mProcessID, mData.mNextContextID++);
-        if (uNewContextID == UINT32_MAX)
+                                                      mData.mProcessID, mData.mNextContextID);
+        if (mData.mNextContextID == VBOX_GUESTCTRL_MAX_CONTEXTS)
             mData.mNextContextID = 0;
         /* Is the context ID already used?  Try next ID ... */
@@ -344,4 +349,5 @@
             break;
         }
+        mData.mNextContextID++;
 
         if (++uTries == UINT32_MAX)
@@ -358,4 +364,7 @@
         if (puContextID)
             *puContextID = uNewContextID;
+
+        LogFlowFunc(("Added new callback (Session: %RU32, Process: %RU32, Count=%RU32) CID=%RU32\n",
+                     uSessionID, mData.mProcessID, mData.mNextContextID, uNewContextID));
     }
 
@@ -500,25 +509,4 @@
 }
 
-HRESULT GuestProcess::hgcmResultToError(int rc)
-{
-    if (RT_SUCCESS(rc))
-        return S_OK;
-
-    HRESULT hr;
-    if (rc == VERR_INVALID_VM_HANDLE)
-        hr = setErrorNoLog(VBOX_E_VM_ERROR,
-                           tr("VMM device is not available (is the VM running?)"));
-    else if (rc == VERR_NOT_FOUND)
-        hr = setErrorNoLog(VBOX_E_IPRT_ERROR,
-                           tr("The guest execution service is not ready (yet)"));
-    else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
-        hr= setErrorNoLog(VBOX_E_IPRT_ERROR,
-                          tr("The guest execution service is not available"));
-    else /* HGCM call went wrong. */
-        hr = setErrorNoLog(E_UNEXPECTED,
-                           tr("The HGCM call failed with error %Rrc"), rc);
-    return hr;
-}
-
 bool GuestProcess::isReady(void)
 {
@@ -546,6 +534,13 @@
     pCallback->Signal();
 
+    /* Do we need to report a termination? */
+    ProcessWaitResult_T waitRes;
+    if (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
+        waitRes = ProcessWaitResult_Status; /* No, just report a status. */
+    else
+        waitRes = ProcessWaitResult_Terminate;
+
     /* Signal in any case. */
-    int rc = signalWaiters(ProcessWaitResult_Status, VERR_CANCELLED);
+    int rc = signalWaiters(waitRes);
     AssertRC(rc);
 
@@ -594,8 +589,6 @@
         Assert(mData.mPID == pData->u32PID);
 
-    int callbackRC = VINF_SUCCESS;
-
     BOOL fSignal = FALSE;
-    ProcessWaitResult_T enmWaitResult;
+    ProcessWaitResult_T waitRes;
     uint32_t uWaitFlags = mData.mWaitEvent
                         ? mData.mWaitEvent->GetWaitFlags() : 0;
@@ -605,5 +598,5 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Start);
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_Started;
@@ -615,5 +608,5 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_TerminatedNormally;
@@ -625,10 +618,8 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_TerminatedSignal;
             mData.mExitCode = pData->u32Flags; /* Contains the signal. */
-
-            callbackRC = VERR_INTERRUPTED;
             break;
         }
@@ -637,9 +628,7 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_TerminatedAbnormally;
-
-            callbackRC = VERR_BROKEN_PIPE;
             break;
         }
@@ -648,9 +637,7 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Timeout;
+            waitRes = ProcessWaitResult_Timeout;
 
             mData.mStatus = ProcessStatus_TimedOutKilled;
-
-            callbackRC = VERR_TIMEOUT;
             break;
         }
@@ -659,9 +646,7 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Timeout;
+            waitRes = ProcessWaitResult_Timeout;
 
             mData.mStatus = ProcessStatus_TimedOutAbnormally;
-
-            callbackRC = VERR_TIMEOUT;
             break;
         }
@@ -670,17 +655,8 @@
         {
             fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = (mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses)
+                    ? ProcessWaitResult_Terminate : ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_Down;
-
-            /*
-             * If mFlags has CreateProcessFlag_IgnoreOrphanedProcesses set, we don't report an error to
-             * our progress object. This is helpful for waiters which rely on the success of our progress object
-             * even if the executed process was killed because the system/VBoxService is shutting down.
-             *
-             * In this case mFlags contains the actual execution flags reached in via Guest::ExecuteProcess().
-             */
-            callbackRC = mData.mProcess.mFlags & ProcessCreateFlag_IgnoreOrphanedProcesses
-                       ? VINF_SUCCESS : VERR_OBJECT_DESTROYED;
             break;
         }
@@ -689,9 +665,64 @@
         {
             fSignal = TRUE; /* Signal in any case. */
-            enmWaitResult = ProcessWaitResult_Error;
+            waitRes = ProcessWaitResult_Error;
 
             mData.mStatus = ProcessStatus_Error;
 
-            callbackRC = pData->u32Flags; /** @todo int vs. uint32 -- IPRT errors are *negative* !!! */
+            Utf8Str strError = Utf8StrFmt(tr("Guest process \"%s\" could not be started: ", mData.mProcess.mCommand.c_str()));
+
+            /* Note: It's not required that the process has been started before. */
+            if (mData.mPID)
+            {
+                strError += Utf8StrFmt(tr("Error rc=%Rrc occured (PID %RU32)"), rc, mData.mPID);
+            }
+            else
+            {
+                /** @todo pData->u32Flags; /** @todo int vs. uint32 -- IPRT errors are *negative* !!! */
+                switch (pData->u32Flags) /* pData->u32Flags contains the IPRT error code from guest side. */
+                {
+                    case VERR_FILE_NOT_FOUND: /* This is the most likely error. */
+                        strError += Utf8StrFmt(tr("The specified file was not found on guest"));
+                        break;
+
+                    case VERR_PATH_NOT_FOUND:
+                        strError += Utf8StrFmt(tr("Could not resolve path to specified file was not found on guest"));
+                        break;
+
+                    case VERR_BAD_EXE_FORMAT:
+                        strError += Utf8StrFmt(tr("The specified file is not an executable format on guest"));
+                        break;
+
+                    case VERR_AUTHENTICATION_FAILURE:
+                        strError += Utf8StrFmt(tr("The specified user was not able to logon on guest"));
+                        break;
+
+                    case VERR_INVALID_NAME:
+                        strError += Utf8StrFmt(tr("The specified file is an invalid name"));
+                        break;
+
+                    case VERR_TIMEOUT:
+                        strError += Utf8StrFmt(tr("The guest did not respond within time"));
+                        break;
+
+                    case VERR_CANCELLED:
+                        strError += Utf8StrFmt(tr("The execution operation was canceled"));
+                        break;
+
+                    case VERR_PERMISSION_DENIED:
+                        strError += Utf8StrFmt(tr("Invalid user/password credentials"));
+                        break;
+
+                    case VERR_MAX_PROCS_REACHED:
+                        strError += Utf8StrFmt(tr("Maximum number of parallel guest processes has been reached"));
+                        break;
+
+                    default:
+                        strError += Utf8StrFmt(tr("Reported error %Rrc"), pData->u32Flags);
+                        break;
+                }
+            }
+
+            rc = setErrorInternal(pData->u32Flags, strError);
+            AssertRC(rc);
             break;
         }
@@ -702,9 +733,7 @@
             /* Silently skip this request. */
             fSignal = TRUE; /* Signal in any case. */
-            enmWaitResult = ProcessWaitResult_Status;
+            waitRes = ProcessWaitResult_Status;
 
             mData.mStatus = ProcessStatus_Undefined;
-
-            callbackRC = VERR_NOT_IMPLEMENTED;
             break;
         }
@@ -712,14 +741,14 @@
 
     LogFlowFunc(("Got rc=%Rrc, waitResult=%d\n",
-                 rc, enmWaitResult));
+                 rc, waitRes));
 
     /*
      * Now do the signalling stuff.
      */
-    rc = pCallback->Signal(callbackRC);
+    rc = pCallback->Signal();
 
     if (fSignal)
     {
-        int rc2 = signalWaiters(enmWaitResult, callbackRC);
+        int rc2 = signalWaiters(waitRes);
         if (RT_SUCCESS(rc))
             rc = rc2;
@@ -814,16 +843,47 @@
 }
 
-int GuestProcess::signalWaiters(ProcessWaitResult_T enmWaitResult, int rc /*= VINF_SUCCESS*/)
-{
-    LogFlowFunc(("enmWaitResult=%d, rc=%Rrc, mWaitCount=%RU32, mWaitEvent=%p\n",
-                 enmWaitResult, rc, mData.mWaitCount, mData.mWaitEvent));
-
-    /* Note: No write locking here -- already done in the callback dispatcher. */
-
-    int rc2 = VINF_SUCCESS;
-    if (mData.mWaitEvent)
-        rc2 = mData.mWaitEvent->Signal(enmWaitResult, rc);
+int GuestProcess::setErrorInternal(int rc, const Utf8Str &strMessage)
+{
+    LogFlowFunc(("rc=%Rrc, strMsg=%s\n", rc, strMessage.c_str()));
+
+    Assert(RT_FAILURE(rc));
+    Assert(!strMessage.isEmpty());
+
+#ifdef DEBUG
+    /* Do not allow overwriting an already set error. If this happens
+     * this means we forgot some error checking/locking somewhere. */
+    Assert(RT_SUCCESS(mData.mRC));
+    Assert(mData.mErrorMsg.isEmpty());
+#endif
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    mData.mStatus = ProcessStatus_Error;
+    mData.mRC = rc;
+    mData.mErrorMsg = strMessage;
+
+    int rc2 = signalWaiters(ProcessWaitResult_Error);
     LogFlowFuncLeaveRC(rc2);
     return rc2;
+}
+
+int GuestProcess::setErrorExternal(void)
+{
+    return RT_SUCCESS(mData.mRC)
+           ? S_OK : setError(VBOX_E_IPRT_ERROR, "%s", mData.mErrorMsg.c_str());
+}
+
+int GuestProcess::signalWaiters(ProcessWaitResult_T enmWaitResult)
+{
+    LogFlowFunc(("enmWaitResult=%d, mWaitCount=%RU32, mWaitEvent=%p\n",
+                 enmWaitResult, mData.mWaitCount, mData.mWaitEvent));
+
+    /* Note: No write locking here -- already done in the caller. */
+
+    int rc = VINF_SUCCESS;
+    if (mData.mWaitEvent)
+        rc = mData.mWaitEvent->Signal(enmWaitResult);
+    LogFlowFuncLeaveRC(rc);
+    return rc;
 }
 
@@ -910,4 +970,17 @@
 
             rc = sendCommand(HOST_EXEC_CMD, i, paParms);
+            if (RT_FAILURE(rc))
+            {
+                int rc2;
+                if (rc == VERR_INVALID_VM_HANDLE)
+                    rc2 = setErrorInternal(rc, tr("VMM device is not available (is the VM running?)"));
+                else if (rc == VERR_NOT_FOUND)
+                    rc2 = setErrorInternal(rc, tr("The guest execution service is not ready (yet)"));
+                else if (rc == VERR_HGCM_SERVICE_NOT_FOUND)
+                    rc2 = setErrorInternal(rc, tr("The guest execution service is not available"));
+                else
+                    rc2 = setErrorInternal(rc, Utf8StrFmt(tr("The HGCM call failed with error %Rrc"), rc));
+                AssertRC(rc2);
+            }
         }
 
@@ -915,7 +988,4 @@
         if (pszArgs)
             RTStrFree(pszArgs);
-
-        if (RT_FAILURE(rc))
-            mData.mStatus = ProcessStatus_Error;
 
         uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;
@@ -1006,5 +1076,5 @@
 }
 
-int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestProcessWaitResult &guestResult)
+int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestProcessWaitResult &waitRes)
 {
     LogFlowThisFuncEnter();
@@ -1019,14 +1089,14 @@
     ProcessStatus_T curStatus = mData.mStatus;
 
-    guestResult.mResult = ProcessWaitResult_None;
-    guestResult.mRC = VINF_SUCCESS;
-
-#if 1
-    if (   (fWaitFlags &  ProcessWaitForFlag_Start)
-        && (curStatus  != ProcessStatus_Undefined))
-    {
-        guestResult.mResult = ProcessWaitResult_Start; /** @todo Fix this. */
-    }
-#else
+    /* Did some error occur before? Then skip waiting and return. */
+    if (curStatus == ProcessStatus_Error)
+    {
+        waitRes.mResult = ProcessWaitResult_Error;
+        return VINF_SUCCESS;
+    }
+
+    waitRes.mResult = ProcessWaitResult_None;
+    waitRes.mRC = VINF_SUCCESS;
+
     if (   (fWaitFlags & ProcessWaitForFlag_Terminate)
         || (fWaitFlags & ProcessWaitForFlag_StdIn)
@@ -1040,14 +1110,20 @@
             case ProcessStatus_TerminatedAbnormally:
             case ProcessStatus_Down:
-                guestResult.mResult = ProcessWaitResult_Terminate;
+                waitRes.mResult = ProcessWaitResult_Terminate;
                 break;
 
             case ProcessStatus_TimedOutKilled:
             case ProcessStatus_TimedOutAbnormally:
-                guestResult.mResult = ProcessWaitResult_Timeout;
+                waitRes.mResult = ProcessWaitResult_Timeout;
                 break;
 
             case ProcessStatus_Error:
-                guestResult.mResult = ProcessWaitResult_Error;
+                waitRes.mResult = ProcessWaitResult_Error;
+                waitRes.mRC = mData.mRC;
+                break;
+
+            case ProcessStatus_Undefined:
+            case ProcessStatus_Starting:
+                /* Do the waiting below. */
                 break;
 
@@ -1064,5 +1140,19 @@
             case ProcessStatus_Paused:
             case ProcessStatus_Terminating:
-                guestResult.mResult = ProcessWaitResult_Start;
+            case ProcessStatus_TerminatedNormally:
+            case ProcessStatus_TerminatedSignal:
+            case ProcessStatus_TerminatedAbnormally:
+            case ProcessStatus_Down:
+                waitRes.mResult = ProcessWaitResult_Start;
+                break;
+
+            case ProcessStatus_Error:
+                waitRes.mResult = ProcessWaitResult_Error;
+                waitRes.mRC = mData.mRC;
+                break;
+
+            case ProcessStatus_Undefined:
+            case ProcessStatus_Starting:
+                /* Do the waiting below. */
                 break;
 
@@ -1072,8 +1162,9 @@
         }
     }
-#endif
+
+    LogFlowFunc(("waitResult=%ld, waitRC=%Rrc\n", waitRes.mResult, waitRes.mRC));
 
     /* No waiting needed? Return immediately. */
-    if (guestResult.mResult != ProcessWaitResult_None)
+    if (waitRes.mResult != ProcessWaitResult_None)
         return VINF_SUCCESS;
 
@@ -1090,5 +1181,5 @@
     int rc = mData.mWaitEvent->Wait(uTimeoutMS);
     if (RT_SUCCESS(rc))
-        guestResult = mData.mWaitEvent->GetResult();
+        waitRes = mData.mWaitEvent->GetResult();
 
     alock.acquire(); /* Get the lock again. */
@@ -1208,7 +1299,4 @@
                         break;
 
-                    case VERR_NOT_AVAILABLE:
-                       strMsg += Utf8StrFmt(tr("Guest control service is not ready"));
-
                     default:
                         strMsg += Utf8StrFmt(tr("Reported error %Rrc"), rc);
@@ -1331,13 +1419,19 @@
     if (RT_SUCCESS(rc))
     {
-        hr = waitResultToErrorEx(waitRes, true /* fLog */);
-        if (SUCCEEDED(hr))
-            *aReason = waitRes.mResult;
+        *aReason = waitRes.mResult;
+        hr = setErrorExternal();
     }
     else
-        hr = setError(VBOX_E_IPRT_ERROR,
-                      tr("Waiting for process \"%s\" (PID %RU32) failed with rc=%Rrc"),
-                      mData.mProcess.mCommand.c_str(), mData.mPID, rc);
-    LogFlowFuncLeaveRC(hr);
+    {
+        if (rc == VERR_TIMEOUT)
+            hr = setError(VBOX_E_IPRT_ERROR,
+                          tr("Process \"%s\" (PID %RU32) did not respond within time (%RU32ms)"),
+                          mData.mProcess.mCommand.c_str(), mData.mPID, aTimeoutMS);
+        else
+            hr = setError(VBOX_E_IPRT_ERROR,
+                          tr("Waiting for process \"%s\" (PID %RU32) failed with rc=%Rrc"),
+                          mData.mProcess.mCommand.c_str(), mData.mPID, rc);
+    }
+    LogFlowFuncLeaveRC(rc);
     return hr;
 #endif /* VBOX_WITH_GUEST_CONTROL */
Index: /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42435)
+++ /trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42436)
@@ -379,12 +379,20 @@
     LogFlowFuncEnter();
 
-    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
-    AssertReturn(cbData, VERR_INVALID_PARAMETER);
-
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
+    uint32_t uProcessID = VBOX_GUESTCTRL_CONTEXTID_GET_PROCESS(uContextID);
+#ifdef DEBUG
+    LogFlowFunc(("uProcessID=%RU32 (%RU32 total)\n",
+                 uProcessID, mData.mProcesses.size()));
+    SessionProcesses::const_iterator i = mData.mProcesses.begin();
+    while (i != mData.mProcesses.end())
+    {
+        LogFlowFunc(("\tproc %RU32\n", i->first));
+        i++;
+    }
+#endif
     int rc;
     SessionProcesses::const_iterator itProc
-        = mData.mProcesses.find(VBOX_GUESTCTRL_CONTEXTID_GET_PROCESS(uContextID));
+        = mData.mProcesses.find(uProcessID);
     if (itProc != mData.mProcesses.end())
     {
@@ -448,4 +456,7 @@
 int GuestSession::processCreateExInteral(GuestProcessInfo &procInfo, ComObjPtr<GuestProcess> &pProcess)
 {
+    LogFlowFunc(("mCmd=%s, mFlags=%x, mTimeoutMS=%RU32\n",
+                 procInfo.mCommand.c_str(), procInfo.mFlags, procInfo.mTimeoutMS));
+
     /* Validate flags. */
     if (procInfo.mFlags)
@@ -469,9 +480,9 @@
     /** @tood Implement process priority + affinity. */
 
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
     int rc = VERR_MAX_PROCS_REACHED;
     if (mData.mProcesses.size() >= VBOX_GUESTCTRL_MAX_PROCESSES)
         return rc;
-
-    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     /* Create a new (host-based) process ID and assign it. */
@@ -504,9 +515,12 @@
 
         rc = pProcess->init(mData.mParent->getConsole() /* Console */, this /* Session */,
-                             uNewProcessID, procInfo);
+                            uNewProcessID, procInfo);
         if (RT_FAILURE(rc)) throw rc;
 
         /* Add the created process to our map. */
         mData.mProcesses[uNewProcessID] = pProcess;
+
+        LogFlowFunc(("Added new process (Session: %RU32) with process ID=%RU32\n",
+                     mData.mId, uNewProcessID));
     }
     catch (int rc2)
@@ -1011,5 +1025,5 @@
         com::SafeArray<IN_BSTR> environment(ComSafeArrayInArg(aEnvironment));
         for (size_t i = 0; i < environment.size() && RT_SUCCESS(rc); i++)
-            rc = mData.mEnvironment.Set(Utf8Str(environment[i]));
+            rc = procInfo.mEnvironment.Set(Utf8Str(environment[i]));
     }
 
@@ -1055,11 +1069,11 @@
         {
             case VERR_MAX_PROCS_REACHED:
-                hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest processes (%ld) reached"),
-                              VERR_MAX_PROCS_REACHED);
+                hr = setError(VBOX_E_IPRT_ERROR, tr("Maximum number of guest processes per session (%ld) reached"),
+                              VBOX_GUESTCTRL_MAX_PROCESSES);
                 break;
 
             /** @todo Add more errors here. */
 
-           default:
+            default:
                 hr = setError(VBOX_E_IPRT_ERROR, tr("Could not create guest process, rc=%Rrc"), rc);
                 break;
