Index: trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 42410)
+++ trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 42411)
@@ -8804,5 +8804,5 @@
   <enum
     name="ProcessWaitForFlag"
-    uuid="858a99aa-4b3c-4863-9726-87386671f408"
+    uuid="23b550c7-78e1-437e-98f0-65fd9757bcd2"
     >
     <desc>
@@ -8812,28 +8812,25 @@
     <const name="None"                    value="0">
       <desc>TODO</desc>
-    </const>    
-    <const name="Exit"                    value="1">
+    </const>
+    <const name="Start"                   value="1">
+      <desc>TODO</desc>
+    </const>
+    <const name="Terminate"               value="2">
+      <desc>TODO</desc>
+    </const>        
+    <const name="StdIn"                   value="4">
       <desc>TODO</desc>
     </const>    
-    <const name="StdIn"                   value="2">
+    <const name="StdOut"                  value="8">
       <desc>TODO</desc>
     </const>    
-    <const name="StdOut"                  value="4">
+    <const name="StdErr"                  value="16">
       <desc>TODO</desc>
-    </const>    
-    <const name="StdErr"                  value="8">
-      <desc>TODO</desc>
-    </const>    
-    <const name="Start"                   value="16">
-      <desc>TODO</desc>
-    </const>    
-    <const name="Status"                  value="32">
-      <desc>TODO</desc>
-    </const>    
+    </const>            
   </enum>
   
   <enum
     name="ProcessWaitResult"
-    uuid="b03af138-c812-45eb-939d-5d564bd0b89a"
+    uuid="c593a234-21ee-4a67-85ef-ba0cc9b9b86a"
     >
     <desc>
@@ -8841,23 +8838,29 @@
     </desc>
 
-    <const name="None"                   value="0">
+    <const name="None"                    value="0">
       <desc>TODO</desc>
     </const>
-    <const name="Status"                 value="1">
+    <const name="Start"                   value="1">
+      <desc>TODO</desc>
+    </const>
+    <const name="Terminate"               value="2">
+      <desc>TODO</desc>
+    </const>
+    <const name="Status"                  value="3">
       <desc>TODO</desc>
     </const>    
-    <const name="Error"                  value="10">
+    <const name="Error"                   value="4">
       <desc>TODO</desc>
     </const>    
-    <const name="Timeout"                value="50">
+    <const name="Timeout"                 value="5">
       <desc>TODO</desc>
     </const>    
-    <const name="StdIn"                  value="100">
+    <const name="StdIn"                   value="6">
       <desc>TODO</desc>
     </const>    
-    <const name="StdOut"                 value="150">
+    <const name="StdOut"                  value="7">
       <desc>TODO</desc>
     </const>    
-    <const name="StdErr"                 value="200">
+    <const name="StdErr"                  value="8">
       <desc>TODO</desc>
     </const>    
@@ -8944,5 +8947,5 @@
   <enum
     name="ProcessCreateFlag"
-    uuid="1497c881-70b4-42dd-8b42-2ad76f004e3f"
+    uuid="91c8aba8-2e62-4fe5-b744-fcbd607971e2"
     >
     <desc>
@@ -8965,4 +8968,10 @@
     <const name="NoProfile"               value="8">
       <desc>Do not use the user's profile data when exeuting a process. Only available for Windows guests.</desc>
+    </const>
+    <const name="WaitForStdOut"           value="16">
+      <desc>The guest process waits until all data from stdout is read out.</desc>
+    </const>
+    <const name="WaitForStdErr"           value="32">
+      <desc>The guest process waits until all data from stderr is read out.</desc>
     </const>
   </enum>
@@ -9181,5 +9190,5 @@
   <interface
     name="IGuestSession" extends="$unknown"
-    uuid="530aef35-6a48-455c-960c-aac5792abc38"
+    uuid="47a344ec-8495-49ad-bfab-8cd0ff8eb3cf"
     wsmap="managed"
     >
@@ -9221,5 +9230,5 @@
     </attribute>
     
-    <attribute name="timeout" type="unsigned long" readonly="yes">
+    <attribute name="timeout" type="unsigned long" readonly="no">
       <desc>
         TODO
@@ -9752,5 +9761,5 @@
     </method>
     
-    <method name="SetTimeout">
+    <method name="SymlinkCreate">
       <desc>
         TODO
@@ -9760,10 +9769,16 @@
         </result>
       </desc>
-      <param name="timeoutMS" type="unsigned long" dir="in">
+      <param name="source" type="wstring" dir="in">
         <desc>TODO</desc>
       </param>
+      <param name="target" type="wstring" dir="in">
+        <desc>TODO</desc>
+      </param>
+      <param name="type" type="SymlinkType" dir="in">
+        <desc>TODO</desc>
+      </param>
     </method>
     
-    <method name="SymlinkCreate">
+    <method name="SymlinkExists">
       <desc>
         TODO
@@ -9773,16 +9788,13 @@
         </result>
       </desc>
-      <param name="source" type="wstring" dir="in">
+      <param name="symlink" type="wstring" dir="in">
         <desc>TODO</desc>
       </param>
-      <param name="target" type="wstring" dir="in">
+      <param name="exists" type="boolean" dir="return">
         <desc>TODO</desc>
       </param>
-      <param name="type" type="SymlinkType" dir="in">
-        <desc>TODO</desc>
-      </param>
     </method>
     
-    <method name="SymlinkExists">
+    <method name="SymlinkRead">
       <desc>
         TODO
@@ -9795,10 +9807,13 @@
         <desc>TODO</desc>
       </param>
-      <param name="exists" type="boolean" dir="return">
+      <param name="flags" type="SymlinkReadFlag" dir="in" safearray="yes">
         <desc>TODO</desc>
       </param>
+      <param name="target" type="wstring" dir="return">
+        <desc>TODO</desc>
+      </param>
     </method>
     
-    <method name="SymlinkRead">
+    <method name="SymlinkRemoveDirectory">
       <desc>
         TODO
@@ -9808,16 +9823,10 @@
         </result>
       </desc>
-      <param name="symlink" type="wstring" dir="in">
+      <param name="path" type="wstring" dir="in">
         <desc>TODO</desc>
       </param>
-      <param name="flags" type="SymlinkReadFlag" dir="in" safearray="yes">
-        <desc>TODO</desc>
-      </param>
-      <param name="target" type="wstring" dir="return">
-        <desc>TODO</desc>
-      </param>
     </method>
     
-    <method name="SymlinkRemoveDirectory">
+    <method name="SymlinkRemoveFile">
       <desc>
         TODO
@@ -9827,17 +9836,4 @@
         </result>
       </desc>
-      <param name="path" type="wstring" dir="in">
-        <desc>TODO</desc>
-      </param>
-    </method>
-    
-    <method name="SymlinkRemoveFile">
-      <desc>
-        TODO
-
-        <result name="VBOX_E_NOT_SUPPORTED">
-          TODO
-        </result>
-      </desc>
       <param name="file" type="wstring" dir="in">
         <desc>TODO</desc>
@@ -9849,5 +9845,5 @@
   <interface
     name="IProcess" extends="$unknown"
-    uuid="8a308a2f-bea6-4786-80a0-4d07cd4bacaa"
+    uuid="f55af4a1-e280-40ac-83e1-921c0abcaf18"
     wsmap="managed"
     >
@@ -9903,8 +9899,35 @@
       </desc>
     </attribute>
+    <attribute name="name" type="wstring" readonly="yes">
+      <desc>
+        TODO
+        <note>
+          TODO
+        </note>
+      </desc>
+    </attribute>
     
     <method name="WaitFor">
       <desc>
         TODO
+
+        <result name="VBOX_E_NOT_SUPPORTED">
+          TODO
+        </result>
+      </desc>
+      <param name="waitFor" type="unsigned long" dir="in">
+        <desc>TODO</desc>
+      </param>
+      <param name="timeoutMS" type="unsigned long" dir="in">
+        <desc>TODO</desc>
+      </param>
+      <param name="reason" type="ProcessWaitResult" dir="return">
+        <desc>TODO</desc>
+      </param>
+    </method>
+    
+    <method name="WaitForArray">
+      <desc>
+        Scriptable version of <link to="#waitFor" />.
 
         <result name="VBOX_E_NOT_SUPPORTED">
@@ -10388,5 +10411,5 @@
   <interface
     name="IGuest" extends="$unknown"
-    uuid="1413d910-e533-47af-a71b-919c106d2472"
+    uuid="9e0b07b1-490f-4413-8955-0a16515aac12"
     wsmap="managed"
     >
@@ -10805,5 +10828,21 @@
         </desc>
       </param>
-    </method>    
+    </method>
+    
+    <method name="findSession">
+      <desc>
+        TODO
+      </desc>      
+      <param name="sessionName" type="wstring" dir="in">
+        <desc>
+          TODO
+        </desc>
+      </param>
+      <param name="sessions" type="IGuestSession" safearray="yes" dir="return">
+        <desc>
+          TODO
+        </desc>
+      </param>
+    </method>
     
     <method name="executeProcess">
Index: trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
===================================================================
--- trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 42410)
+++ trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h	(revision 42411)
@@ -127,4 +127,6 @@
     void Destroy(void);
 
+    int FillData(const void *pData, size_t cbData);
+
     int Init(eVBoxGuestCtrlCallbackType enmType);
 
Index: trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestImpl.h	(revision 42410)
+++ trunk/src/VBox/Main/include/GuestImpl.h	(revision 42411)
@@ -134,4 +134,5 @@
     STDMETHOD(UpdateGuestAdditions)(IN_BSTR aSource, ULONG aFlags, IProgress **aProgress);
     STDMETHOD(CreateSession)(IN_BSTR aUser, IN_BSTR aPassword, IN_BSTR aDomain, IN_BSTR aSessionName, IGuestSession **aGuestSession);
+    STDMETHOD(FindSession)(IN_BSTR aSessionName, ComSafeArrayOut(IGuestSession *, aSessions));
 
     // Public methods that are not in IDL (only called internally).
Index: trunk/src/VBox/Main/include/GuestProcessImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 42410)
+++ trunk/src/VBox/Main/include/GuestProcessImpl.h	(revision 42411)
@@ -57,4 +57,5 @@
     STDMETHOD(COMGETTER(ExecutablePath))(BSTR *aExecutablePath);
     STDMETHOD(COMGETTER(ExitCode))(LONG *aExitCode);
+    STDMETHOD(COMGETTER(Name))(BSTR *aName);
     STDMETHOD(COMGETTER(Pid))(ULONG *aPID);
     STDMETHOD(COMGETTER(Status))(ProcessStatus_T *aStatus);
@@ -62,5 +63,6 @@
     STDMETHOD(Read)(ULONG aHandle, ULONG aSize, ULONG aTimeoutMS, ComSafeArrayOut(BYTE, aData));
     STDMETHOD(Terminate)(void);
-    STDMETHOD(WaitFor)(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
+    STDMETHOD(WaitFor)(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
+    STDMETHOD(WaitForArray)(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason);
     STDMETHOD(Write)(ULONG aHandle, ComSafeArrayIn(BYTE, aData), ULONG aTimeoutMS, ULONG *aWritten);
     /** @}  */
@@ -79,5 +81,4 @@
     int terminateProcess(void);
     int waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestProcessWaitResult &guestResult);
-    HRESULT waitResultToErrorEx(const GuestProcessWaitResult &waitResult, bool fLog);
     int writeData(ULONG uHandle, BYTE const *pbData, size_t cbData, ULONG uTimeoutMS, ULONG *puWritten);
     /** @}  */
@@ -88,4 +89,6 @@
     inline int callbackAdd(GuestCtrlCallback *pCallback, ULONG *puContextID);
     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);
@@ -96,4 +99,5 @@
     int signalWaiters(ProcessWaitResult_T enmWaitResult, int rc = VINF_SUCCESS);
     static DECLCALLBACK(int) startProcessThread(RTTHREAD Thread, void *pvUser);
+    HRESULT waitResultToErrorEx(const GuestProcessWaitResult &waitResult, bool fLog);
     /** @}  */
 
@@ -109,4 +113,6 @@
         /** All related callbacks to this process. */
         GuestCtrlCallbacks       mCallbacks;
+        /** The process' name. */
+        Utf8Str                  mName;
         /** The process start information. */
         GuestProcessInfo         mProcess;
@@ -119,9 +125,8 @@
         /** The current process status. */
         ProcessStatus_T          mStatus;
-        /** Flag indicating whether the process has been started
-         *  so that it can't be started a second time. */
-        bool                     mStarted;
         /** The next upcoming context ID. */
         ULONG                    mNextContextID;
+        /** The mutex for protecting the waiter(s). */
+        RTSEMMUTEX               mWaitMutex;
         /** How many waiters? At the moment there can only
          *  be one. */
Index: trunk/src/VBox/Main/include/GuestSessionImpl.h
===================================================================
--- trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42410)
+++ trunk/src/VBox/Main/include/GuestSessionImpl.h	(revision 42411)
@@ -61,4 +61,5 @@
     STDMETHOD(COMGETTER(Id))(ULONG *aId);
     STDMETHOD(COMGETTER(Timeout))(ULONG *aTimeout);
+    STDMETHOD(COMSETTER(Timeout))(ULONG aTimeout);
     STDMETHOD(COMGETTER(Environment))(ComSafeArrayOut(BSTR, aEnvironment));
     STDMETHOD(COMGETTER(Processes))(ComSafeArrayOut(IGuestProcess *, aProcesses));
Index: trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 42410)
+++ trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp	(revision 42411)
@@ -2834,2 +2834,7 @@
 }
 
+STDMETHODIMP Guest::FindSession(IN_BSTR aSessionName, ComSafeArrayOut(IGuestSession *, aSessions))
+{
+    ReturnComNotImplemented();
+}
+
Index: trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp	(revision 42410)
+++ trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp	(revision 42411)
@@ -206,4 +206,20 @@
     }
     cbData = 0;
+}
+
+int GuestCtrlCallback::FillData(const void *pData, size_t cbData)
+{
+    if (!cbData)
+        return VINF_SUCCESS;
+    AssertPtr(pData);
+
+    Assert(pvData == NULL); /* Can't reuse callbacks! */
+    pvData = RTMemAlloc(cbData);
+    if (!pvData)
+        return VERR_NO_MEMORY;
+
+    memcpy(pvData, pData, cbData);
+
+    return VINF_SUCCESS;
 }
 
Index: trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 42410)
+++ trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp	(revision 42411)
@@ -75,8 +75,7 @@
     mData.mProcessID = 0;
     mData.mStatus = ProcessStatus_Undefined;
-    mData.mStarted = false;
 
     mData.mWaitCount = 0;
-    mData.mWaitEvent = NIL_RTSEMEVENT;
+    mData.mWaitEvent = NULL;
 
     HRESULT hr = BaseFinalConstruct();
@@ -148,8 +147,8 @@
     LogFlowThisFuncEnter();
 
+    CheckComArgOutSafeArrayPointerValid(aArguments);
+
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    CheckComArgOutSafeArrayPointerValid(aArguments);
 
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -179,8 +178,8 @@
     LogFlowThisFuncEnter();
 
+    CheckComArgOutSafeArrayPointerValid(aEnvironment);
+
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
-
-    CheckComArgOutSafeArrayPointerValid(aEnvironment);
 
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
@@ -206,4 +205,6 @@
     LogFlowThisFuncEnter();
 
+    CheckComArgOutPointerValid(aExecutablePath);
+
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -225,4 +226,6 @@
     LogFlowThisFuncEnter();
 
+    CheckComArgOutPointerValid(aExitCode);
+
     AutoCaller autoCaller(this);
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
@@ -237,5 +240,5 @@
 }
 
-STDMETHODIMP GuestProcess::COMGETTER(Pid)(ULONG *aPID)
+STDMETHODIMP GuestProcess::COMGETTER(Name)(BSTR *aName)
 {
 #ifndef VBOX_WITH_GUEST_CONTROL
@@ -243,4 +246,27 @@
 #else
     LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aName);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    mData.mName.cloneTo(aName);
+
+    LogFlowFuncLeaveRC(S_OK);
+    return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::COMGETTER(Pid)(ULONG *aPID)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+    ReturnComNotImplemented();
+#else
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aPID);
 
     AutoCaller autoCaller(this);
@@ -436,4 +462,11 @@
 }
 
+inline bool GuestProcess::isAlive(void)
+{
+    return (   mData.mStatus == ProcessStatus_Started
+            || mData.mStatus == ProcessStatus_Paused
+            || mData.mStatus == ProcessStatus_Terminating);
+}
+
 void GuestProcess::close(void)
 {
@@ -467,4 +500,25 @@
 }
 
+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)
 {
@@ -518,6 +572,5 @@
     uint32_t uWaitFlags = mData.mWaitEvent
                         ? mData.mWaitEvent->GetWaitFlags() : 0;
-    if (   (uWaitFlags & ProcessWaitForFlag_Status)
-        || (uWaitFlags & ProcessWaitForFlag_StdIn))
+    if (uWaitFlags & ProcessWaitForFlag_StdIn)
         rc = signalWaiters(ProcessWaitResult_StdIn);
     AssertRC(rc);
@@ -556,5 +609,4 @@
             mData.mStatus = ProcessStatus_Started;
             mData.mPID = pData->u32PID;
-            mData.mStarted = true;
             break;
         }
@@ -562,5 +614,5 @@
         case PROC_STS_TEN:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Status;
 
@@ -572,5 +624,5 @@
         case PROC_STS_TES:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Status;
 
@@ -584,5 +636,5 @@
         case PROC_STS_TEA:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Status;
 
@@ -595,5 +647,5 @@
         case PROC_STS_TOK:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Timeout;
 
@@ -606,5 +658,5 @@
         case PROC_STS_TOA:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Timeout;
 
@@ -617,5 +669,5 @@
         case PROC_STS_DWN:
         {
-            fSignal = (uWaitFlags & ProcessWaitForFlag_Exit);
+            fSignal = (uWaitFlags & ProcessWaitForFlag_Terminate);
             enmWaitResult = ProcessWaitResult_Status;
 
@@ -667,6 +719,4 @@
     rc = pCallback->Signal(callbackRC);
 
-    if (!fSignal)
-        fSignal = (uWaitFlags & ProcessWaitForFlag_Status);
     if (fSignal)
     {
@@ -688,10 +738,11 @@
                  mData.mPID, pData->u32HandleId, pData->u32Flags, pData->pvData, pData->cbData, pCallback, pData));
 
-    int rc = VINF_SUCCESS;
-
-    /** @todo Fill data into callback. */
+    /* Copy data into callback. */
+    int rc = pCallback->FillData(pData->pvData, pData->cbData);
 
     /* First, signal callback in every case. */
-    pCallback->Signal();
+    int rc2 = pCallback->Signal();
+    if (RT_SUCCESS(rc))
+        rc = rc2;
 
     /* Then do the WaitFor signalling stuff. */
@@ -716,10 +767,11 @@
     }
 
-    if (!fSignal)
-        fSignal = (uWaitFlags & ProcessWaitForFlag_Status);
-
     if (fSignal)
-        rc = signalWaiters(  pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT
-                           ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr);
+    {
+        rc2 = signalWaiters(  pData->u32HandleId == OUTPUT_HANDLE_ID_STDOUT
+                            ? ProcessWaitResult_StdOut : ProcessWaitResult_StdErr);
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
     AssertRC(rc);
 
@@ -767,8 +819,9 @@
                  enmWaitResult, rc, mData.mWaitCount, mData.mWaitEvent));
 
-    /* Note: No locking here -- already done in the callback dispatcher. */
-
-    AssertPtr(mData.mWaitEvent);
-    int rc2 = mData.mWaitEvent->Signal(enmWaitResult, rc);
+    /* Note: No write locking here -- already done in the callback dispatcher. */
+
+    int rc2 = VINF_SUCCESS;
+    if (mData.mWaitEvent)
+        rc2 = mData.mWaitEvent->Signal(enmWaitResult, rc);
     LogFlowFuncLeaveRC(rc2);
     return rc2;
@@ -780,5 +833,7 @@
                  mData.mProcess.mCommand.c_str(), mData.mProcess.mTimeoutMS, mData.mProcess.mFlags));
 
-    AssertReturn(!mData.mStarted, VERR_ALREADY_EXISTS);
+    /* Wait until the caller function (if kicked off by a thread)
+     * has returned and continue operation. */
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     int rc;
@@ -788,20 +843,14 @@
         return VERR_NO_MEMORY;
 
-    {
-        /* Wait until the caller function (if kicked off by a thread)
-         * has returned and continue operation. */
-        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
-
-        mData.mStatus = ProcessStatus_Starting;
-
-        /* Create callback and add it to the map. */
-        rc = pCallbackStart->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START);
-        if (RT_SUCCESS(rc))
-            rc = callbackAdd(pCallbackStart, &uContextID);
-    }
-
+    mData.mStatus = ProcessStatus_Starting;
+
+    /* Create callback and add it to the map. */
+    rc = pCallbackStart->Init(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START);
     if (RT_SUCCESS(rc))
-    {
-        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+        rc = callbackAdd(pCallbackStart, &uContextID);
+
+    if (RT_SUCCESS(rc))
+    {
+      //  AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
         GuestSession *pSession = mData.mParent;
@@ -867,4 +916,7 @@
             RTStrFree(pszArgs);
 
+        if (RT_FAILURE(rc))
+            mData.mStatus = ProcessStatus_Error;
+
         uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;
 
@@ -877,10 +929,10 @@
              * Note: Be sure not keeping a AutoRead/WriteLock here.
              */
-            LogFlowFunc((tr("Waiting for callback (%RU32ms) ...\n"), uTimeoutMS));
+            LogFlowFunc(("Waiting for callback (%RU32ms) ...\n", uTimeoutMS));
             rc = pCallbackStart->Wait(uTimeoutMS);
             if (RT_SUCCESS(rc)) /* Wait was successful, check for supplied information. */
             {
                 rc = pCallbackStart->GetResultCode();
-                LogFlowFunc((tr("Callback returned rc=%Rrc\n"), rc));
+                LogFlowFunc(("Callback returned rc=%Rrc\n", rc));
             }
             else
@@ -936,6 +988,11 @@
     if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
-    int rcIgnored = pProcess->startProcess();
-    LogFlowFuncLeaveRC(rcIgnored);
+    int rc = pProcess->startProcess();
+    if (RT_FAILURE(rc))
+    {
+        /** @todo What now? */
+    }
+
+    LogFlowFuncLeaveRC(rc);
     return VINF_SUCCESS;
 }
@@ -951,10 +1008,73 @@
 int GuestProcess::waitFor(uint32_t fWaitFlags, ULONG uTimeoutMS, GuestProcessWaitResult &guestResult)
 {
-    LogFlowFunc(("fWaitFlags=%x, uTimeoutMS=%RU32, mWaitCount=%RU32, mWaitEvent=%p\n",
-                 fWaitFlags, uTimeoutMS, mData.mWaitCount, mData.mWaitEvent));
+    LogFlowThisFuncEnter();
 
     AssertReturn(fWaitFlags, VERR_INVALID_PARAMETER);
 
     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    LogFlowFunc(("fWaitFlags=%x, uTimeoutMS=%RU32, mStatus=%RU32, mWaitCount=%RU32, mWaitEvent=%p\n",
+                 fWaitFlags, uTimeoutMS, mData.mStatus, mData.mWaitCount, mData.mWaitEvent));
+
+    ProcessStatus 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
+    if (   (fWaitFlags & ProcessWaitForFlag_Terminate)
+        || (fWaitFlags & ProcessWaitForFlag_StdIn)
+        || (fWaitFlags & ProcessWaitForFlag_StdOut)
+        || (fWaitFlags & ProcessWaitForFlag_StdErr))
+    {
+        switch (mData.mStatus)
+        {
+            case ProcessStatus_TerminatedNormally:
+            case ProcessStatus_TerminatedSignal:
+            case ProcessStatus_TerminatedAbnormally:
+            case ProcessStatus_Down:
+                guestResult.mResult = ProcessWaitResult_Terminate;
+                break;
+
+            case ProcessStatus_TimedOutKilled:
+            case ProcessStatus_TimedOutAbnormally:
+                guestResult.mResult = ProcessWaitResult_Timeout;
+                break;
+
+            case ProcessStatus_Error:
+                guestResult.mResult = ProcessWaitResult_Error;
+                break;
+
+            default:
+                AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
+                return VERR_NOT_IMPLEMENTED;
+        }
+    }
+    else if (fWaitFlags & ProcessWaitForFlag_Start)
+    {
+        switch (mData.mStatus)
+        {
+            case ProcessStatus_Started:
+            case ProcessStatus_Paused:
+            case ProcessStatus_Terminating:
+                guestResult.mResult = ProcessWaitResult_Start;
+                break;
+
+            default:
+                AssertMsgFailed(("Unhandled process status %ld\n", mData.mStatus));
+                return VERR_NOT_IMPLEMENTED;
+        }
+    }
+#endif
+
+    /* No waiting needed? Return immediately. */
+    if (guestResult.mResult != ProcessWaitResult_None)
+        return VINF_SUCCESS;
 
     if (mData.mWaitCount > 0)
@@ -962,5 +1082,5 @@
     mData.mWaitCount++;
 
-    Assert(mData.mWaitEvent == NIL_RTSEMEVENT);
+    Assert(mData.mWaitEvent == NULL);
     mData.mWaitEvent = new GuestProcessEvent(fWaitFlags);
     AssertPtrReturn(mData.mWaitEvent, VERR_NO_MEMORY);
@@ -971,4 +1091,6 @@
     if (RT_SUCCESS(rc))
         guestResult = mData.mWaitEvent->GetResult();
+
+    alock.acquire(); /* Get the lock again. */
 
     /* Note: The caller always is responsible of deleting the
@@ -977,4 +1099,6 @@
     mData.mWaitEvent = NULL;
 
+    mData.mWaitCount--;
+
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -996,5 +1120,5 @@
 
         case ProcessStatus_TerminatedNormally:
-            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated normally (exit code: %d)"),
+            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated normally (exit code: %ld)"),
                                 mData.mProcess.mCommand.c_str(), mData.mPID, mData.mExitCode);
             break;
@@ -1002,5 +1126,5 @@
         case ProcessStatus_TerminatedSignal:
         {
-            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated through signal (signal: %d)"),
+            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated through signal (signal: %ld)"),
                                 mData.mProcess.mCommand.c_str(), mData.mPID, mData.mExitCode);
             break;
@@ -1009,5 +1133,5 @@
         case ProcessStatus_TerminatedAbnormally:
         {
-            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated abnormally (exit code: %d)"),
+            strMsg = Utf8StrFmt(tr("Guest process \"%s\" (PID %RU32) terminated abnormally (exit code: %ld)"),
                                 mData.mProcess.mCommand.c_str(), mData.mPID, mData.mExitCode);
             break;
@@ -1084,4 +1208,7 @@
                         break;
 
+                    case VERR_NOT_AVAILABLE:
+                       strMsg += Utf8StrFmt(tr("Guest control service is not ready"));
+
                     default:
                         strMsg += Utf8StrFmt(tr("Reported error %Rrc"), rc);
@@ -1183,5 +1310,39 @@
 }
 
-STDMETHODIMP GuestProcess::WaitFor(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
+STDMETHODIMP GuestProcess::WaitFor(ULONG aWaitFlags, ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+    ReturnComNotImplemented();
+#else
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aReason);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /*
+     * Note: Do not hold any locks here while waiting!
+     */
+    HRESULT hr;
+
+    GuestProcessWaitResult waitRes;
+    int rc = waitFor(aWaitFlags, aTimeoutMS, waitRes);
+    if (RT_SUCCESS(rc))
+    {
+        hr = waitResultToErrorEx(waitRes, true /* fLog */);
+        if (SUCCEEDED(hr))
+            *aReason = waitRes.mResult;
+    }
+    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);
+    return hr;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
+STDMETHODIMP GuestProcess::WaitForArray(ComSafeArrayIn(ProcessWaitForFlag_T, aFlags), ULONG aTimeoutMS, ProcessWaitResult_T *aReason)
 {
 #ifndef VBOX_WITH_GUEST_CONTROL
@@ -1203,18 +1364,6 @@
         fWaitFor |= flags[i];
 
-    HRESULT hr;
-
-    GuestProcessWaitResult guestResult;
-    int rc = waitFor(fWaitFor, aTimeoutMS, guestResult);
-    if (RT_SUCCESS(rc))
-    {
-        hr = waitResultToErrorEx(guestResult, true /* fLog */);
-        if (SUCCEEDED(hr))
-            *aReason = guestResult.mResult;
-    }
-    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);
+    HRESULT hr = WaitFor(fWaitFor, aTimeoutMS, aReason);
+
     LogFlowFuncLeaveRC(hr);
     return hr;
Index: trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
===================================================================
--- trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42410)
+++ trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp	(revision 42411)
@@ -240,4 +240,23 @@
 }
 
+STDMETHODIMP GuestSession::COMSETTER(Timeout)(ULONG aTimeout)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+    ReturnComNotImplemented();
+#else
+    LogFlowThisFuncEnter();
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    mData.mTimeout = aTimeout;
+
+    LogFlowFuncLeaveRC(S_OK);
+    return S_OK;
+#endif /* VBOX_WITH_GUEST_CONTROL */
+}
+
 STDMETHODIMP GuestSession::COMGETTER(Environment)(ComSafeArrayOut(BSTR, aEnvironment))
 {
@@ -435,5 +454,7 @@
             && !(procInfo.mFlags & ProcessCreateFlag_WaitForProcessStartOnly)
             && !(procInfo.mFlags & ProcessCreateFlag_Hidden)
-            && !(procInfo.mFlags & ProcessCreateFlag_NoProfile))
+            && !(procInfo.mFlags & ProcessCreateFlag_NoProfile)
+            && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdOut)
+            && !(procInfo.mFlags & ProcessCreateFlag_WaitForStdErr))
         {
             return VERR_INVALID_PARAMETER;
