Index: /trunk/include/VBox/HostServices/GuestControlSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 28771)
+++ /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 28772)
@@ -124,4 +124,11 @@
 };
 
+enum eVBoxGuestCtrlCallbackType
+{
+    VBOXGUESTCTRLCALLBACKTYPE_UNKNOWN = 0,
+    VBOXGUESTCTRLCALLBACKTYPE_EXEC_START = 1,
+    VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT = 2
+};
+
 /**
  * The service functions which are callable by host.
Index: /trunk/src/VBox/Main/GuestImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/GuestImpl.cpp	(revision 28771)
+++ /trunk/src/VBox/Main/GuestImpl.cpp	(revision 28772)
@@ -117,4 +117,7 @@
     for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
         removeCtrlCallbackContext(it);
+
+    /* Clear process list. */
+    mGuestProcessList.clear();
 #endif
 
@@ -518,4 +521,26 @@
         }
 
+        /* Handle process list. */
+        /** @todo What happens on/deal with PID reuse? */
+        /** @todo How to deal with multiple updates at once? */
+        GuestProcessIter it_proc = getProcessByPID(pCBData->u32PID);
+        if (it_proc == mGuestProcessList.end())
+        {
+            /* Not found, add to list. */
+            GuestProcess p;
+            p.mPID = pCBData->u32PID;
+            p.mStatus = pCBData->u32Status;
+            //p.mReason = pCBData->u32Reason;
+            p.mExitCode = pCBData->u32Flags; /* Contains exit code. */
+            
+            mGuestProcessList.push_back(p);
+        }
+        else /* Update list. */
+        {
+            it_proc->mStatus = pCBData->u32Status;
+            //it_proc->mReason = pCBData->u32Reason;
+            it_proc->mExitCode = pCBData->u32Flags; /* Contains exit code. */
+        }
+
         if (   !it->pProgress.isNull()
             && errMsg.length())
@@ -591,14 +616,13 @@
 }
 
-Guest::CallbackListIter Guest::getCtrlCallbackContextByPID(uint32_t u32PID)
+Guest::GuestProcessIter Guest::getProcessByPID(uint32_t u32PID)
 {
     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     /** @todo Maybe use a map instead of list for fast context lookup. */
-    CallbackListIter it;
-    for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
-    {
-        PHOSTEXECCALLBACKDATA pCBData = (HOSTEXECCALLBACKDATA*)it->pvData;
-        if (pCBData && pCBData->u32PID == u32PID)
+    GuestProcessIter it;
+    for (it = mGuestProcessList.begin(); it != mGuestProcessList.end(); it++)
+    {
+        if (it->mPID == u32PID)
             return (it);
     }
@@ -630,5 +654,5 @@
  * to the callback list. A callback is identified by a unique context ID which is used
  * to identify a callback from the guest side. */
-uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress *pProgress)
+uint32_t Guest::addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress *pProgress)
 {
     LogFlowFuncEnter();
@@ -640,4 +664,5 @@
     CallbackContext context;
     context.mContextID = uNewContext;
+    context.mType = enmType;
     context.bCalled = false;
     context.pvData = pvData;
@@ -755,5 +780,6 @@
                     PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA));
                     AssertPtr(pData);
-                    uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA), progress);
+                    uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_START, 
+                                                        pData, sizeof(HOSTEXECCALLBACKDATA), progress);
                     Assert(uContextID > 0);
 
@@ -952,5 +978,6 @@
     /* Search for existing PID. */
     PHOSTEXECOUTCALLBACKDATA pData = (HOSTEXECOUTCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECOUTCALLBACKDATA));
-    uint32_t uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECOUTCALLBACKDATA), NULL /* pProgress */);
+    uint32_t uContextID = addCtrlCallbackContext(VBOXGUESTCTRLCALLBACKTYPE_EXEC_OUTPUT,
+                                                 pData, sizeof(HOSTEXECOUTCALLBACKDATA), NULL /* pProgress */);
     Assert(uContextID > 0);
 
@@ -1041,4 +1068,35 @@
 }
 
+STDMETHODIMP Guest::GetProcessStatus(ULONG aPID, ULONG *aReason, ULONG *aExitCode, ULONG *aStatus)
+{
+#ifndef VBOX_WITH_GUEST_CONTROL
+    ReturnComNotImplemented();
+#else  /* VBOX_WITH_GUEST_CONTROL */
+    using namespace guestControl;
+
+    HRESULT rc = S_OK;
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    GuestProcessIterConst it;
+    for (it = mGuestProcessList.begin(); it != mGuestProcessList.end(); it++)
+    {
+        if (it->mPID == aPID)
+            break;
+    }
+
+    if (it != mGuestProcessList.end())
+    {
+        *aReason = it->mReason;
+        *aExitCode = it->mExitCode;
+        *aStatus = it->mStatus;
+    }
+    else
+        rc = setError(VBOX_E_IPRT_ERROR,
+                      tr("Process (PID %u) not found!"), aPID);
+    return rc;
+#endif
+}
+
 // public methods only for internal purposes
 /////////////////////////////////////////////////////////////////////////////
Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 28771)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 28772)
@@ -8379,5 +8379,5 @@
   <interface
      name="IGuest" extends="$unknown"
-     uuid="4b8f90ce-e8ef-4f07-af1b-b0b85bc07e37"
+     uuid="a772d41d-8f60-4247-9a0e-fea7ebec2151"
      wsmap="managed"
      >
@@ -8634,4 +8634,35 @@
         </desc>
       </param>
+    </method>
+
+    <method name="getProcessStatus">
+      <desc>
+        Retrieves status, exit code and the exit reason of a formerly started process.
+
+        <result name="VBOX_E_IPRT_ERROR">
+          Process with specified PID was not found.
+        </result>
+
+      </desc>
+      <param name="pid" type="unsigned long" dir="in">
+        <desc>
+          Process id returned by earlier executeProcess() call.
+        </desc>
+      </param>
+      <param name="reason" type="unsigned long" dir="out">
+        <desc>
+          The reason of exit.
+        </desc>
+      </param>
+      <param name="exitcode" type="unsigned long" dir="out">
+        <desc>
+          The actual exit code.
+        </desc>
+      </param>
+      <param name="status" type="unsigned long" dir="return">
+        <desc>
+          The current process status.
+        </desc>
+      </param>      
     </method>
 
Index: /trunk/src/VBox/Main/include/GuestImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/GuestImpl.h	(revision 28771)
+++ /trunk/src/VBox/Main/include/GuestImpl.h	(revision 28772)
@@ -96,6 +96,7 @@
                               IN_BSTR aStdIn, IN_BSTR aStdOut, IN_BSTR aStdErr,
                               IN_BSTR aUserName, IN_BSTR aPassword,
-                              ULONG aTimeoutMS, ULONG* aPID, IProgress **aProgress);
+                              ULONG aTimeoutMS, ULONG *aPID, IProgress **aProgress);
     STDMETHOD(GetProcessOutput)(ULONG aPID, ULONG aFlags, ULONG aTimeoutMS, ULONG64 aSize, ComSafeArrayOut(BYTE, aData));
+    STDMETHOD(GetProcessStatus)(ULONG aPID, ULONG *aReason, ULONG *aExitCode, ULONG *aStatus);
     STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
                                      ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemCache,
@@ -124,15 +125,27 @@
     struct CallbackContext
     {
-        uint32_t            mContextID;
-        void               *pvData;
-        uint32_t            cbData;
+        uint32_t                    mContextID;
+        eVBoxGuestCtrlCallbackType  mType;
+        void                       *pvData;
+        uint32_t                    cbData;
         /** Atomic flag whether callback was called. */
-        volatile bool       bCalled;
+        volatile bool               bCalled;
         /** Pointer to user-supplied IProgress. */
-        ComObjPtr<Progress> pProgress;
+        ComObjPtr<Progress>         pProgress;
     };
     typedef std::list< CallbackContext > CallbackList;
     typedef std::list< CallbackContext >::iterator CallbackListIter;
     typedef std::list< CallbackContext >::const_iterator CallbackListIterConst;
+
+    struct GuestProcess
+    {
+        uint32_t                 mPID;
+        uint32_t                 mStatus;
+        uint32_t                 mReason;
+        uint32_t                 mExitCode;
+    };
+    typedef std::list< GuestProcess > GuestProcessList;
+    typedef std::list< GuestProcess >::iterator GuestProcessIter;
+    typedef std::list< GuestProcess >::const_iterator GuestProcessIterConst;
 
     int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
@@ -141,7 +154,7 @@
     int notifyCtrlExecOut(uint32_t u32Function, PHOSTEXECOUTCALLBACKDATA pData);
     CallbackListIter getCtrlCallbackContextByID(uint32_t u32ContextID);
-    CallbackListIter getCtrlCallbackContextByPID(uint32_t u32PID);
+    GuestProcessIter getProcessByPID(uint32_t u32PID);
     void removeCtrlCallbackContext(CallbackListIter it);
-    uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress* pProgress);
+    uint32_t addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress* pProgress);
 # endif
 
@@ -171,4 +184,5 @@
     volatile uint32_t mNextContextID;
     CallbackList mCallbackList;
+    GuestProcessList mGuestProcessList;
 # endif
 };
