Index: /trunk/src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35459)
+++ /trunk/src/VBox/Main/idl/VirtualBox.xidl	(revision 35460)
@@ -3,5 +3,5 @@
 <!--
 
-    Copyright (C) 2006-2010 Oracle Corporation
+    Copyright (C) 2006-2011 Oracle Corporation
 
     This file is part of VirtualBox Open Source Edition (OSE), as
@@ -2907,5 +2907,5 @@
   <interface
     name="IInternalMachineControl" extends="$unknown"
-    uuid="476126af-e223-4490-a8a0-b1f1575be013"
+    uuid="8e723ab0-812c-5662-dd8e-7ebc89637acf"
     internal="yes"
     wsmap="suppress"
@@ -2957,4 +2957,42 @@
       </desc>
       <param name="result" type="long" dir="in"/>
+    </method>
+
+    <method name="beginPoweringDown">
+      <desc>
+        Called by the VM process to inform the server it wants to
+        stop the VM execution and power down.
+      </desc>
+      <param name="progress" type="IProgress" dir="out">
+        <desc>
+          Progress object created by VBoxSVC to wait until
+          the VM is powered down.
+        </desc>
+      </param>
+    </method>
+
+    <method name="endPoweringDown">
+      <desc>
+        Called by the VM process to inform the server that powering
+        down previously requested by #beginPoweringDown is either
+        successfully finished or there was a failure.
+
+        <result name="VBOX_E_FILE_ERROR">
+          Settings file not accessible.
+        </result>
+        <result name="VBOX_E_XML_ERROR">
+          Could not parse the settings file.
+        </result>
+
+      </desc>
+
+      <param name="result" type="long" dir="in">
+        <desc>@c S_OK to indicate success.
+        </desc>
+      </param>
+      <param name="errMsg" type="wstring" dir="in">
+        <desc>@c human readable error message in case of failure.
+        </desc>
+      </param>
     </method>
 
Index: /trunk/src/VBox/Main/include/ConsoleImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 35459)
+++ /trunk/src/VBox/Main/include/ConsoleImpl.h	(revision 35460)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -435,5 +435,5 @@
 
     HRESULT powerUp(IProgress **aProgress, bool aPaused);
-    HRESULT powerDown(Progress *aProgress = NULL);
+    HRESULT powerDown(IProgress *aProgress = NULL);
 
     HRESULT callTapSetupApplication(bool isStatic, RTFILE tapFD, Bstr &tapDevice,
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 35459)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 35460)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -927,4 +927,6 @@
     STDMETHOD(BeginPowerUp)(IProgress *aProgress);
     STDMETHOD(EndPowerUp)(LONG iResult);
+    STDMETHOD(BeginPoweringDown)(IProgress **aProgress);
+    STDMETHOD(EndPoweringDown)(LONG aResult, IN_BSTR aErrMsg);
     STDMETHOD(RunUSBDeviceFilters)(IUSBDevice *aUSBDevice, BOOL *aMatched, ULONG *aMaskedIfs);
     STDMETHOD(CaptureUSBDevice)(IN_BSTR aId);
Index: /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 35459)
+++ /trunk/src/VBox/Main/src-client/ConsoleImpl.cpp	(revision 35460)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -142,7 +142,12 @@
 struct VMTask
 {
-    VMTask(Console *aConsole, bool aUsesVMPtr)
+    VMTask(Console *aConsole,
+           Progress *aProgress,
+           const ComPtr<IProgress> &aServerProgress,
+           bool aUsesVMPtr)
         : mConsole(aConsole),
           mConsoleCaller(aConsole),
+          mProgress(aProgress),
+          mServerProgress(aServerProgress),
           mVMCallerAdded(false)
     {
@@ -178,4 +183,7 @@
     const ComObjPtr<Console> mConsole;
     AutoCaller mConsoleCaller;
+    const ComObjPtr<Progress> mProgress;
+    Utf8Str mErrorMsg;
+    const ComPtr<IProgress> mServerProgress;
 
 private:
@@ -185,19 +193,5 @@
 };
 
-struct VMProgressTask : public VMTask
-{
-    VMProgressTask(Console *aConsole,
-                   Progress *aProgress,
-                   bool aUsesVMPtr)
-        : VMTask(aConsole, aUsesVMPtr),
-          mProgress(aProgress)
-    {}
-
-    const ComObjPtr<Progress> mProgress;
-
-    Utf8Str mErrorMsg;
-};
-
-struct VMTakeSnapshotTask : public VMProgressTask
+struct VMTakeSnapshotTask : public VMTask
 {
     VMTakeSnapshotTask(Console *aConsole,
@@ -205,5 +199,6 @@
                        IN_BSTR aName,
                        IN_BSTR aDescription)
-        : VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
+        : VMTask(aConsole, aProgress, NULL /* aServerProgress */,
+                 false /* aUsesVMPtr */),
           bstrName(aName),
           bstrDescription(aDescription),
@@ -219,9 +214,10 @@
 };
 
-struct VMPowerUpTask : public VMProgressTask
+struct VMPowerUpTask : public VMTask
 {
     VMPowerUpTask(Console *aConsole,
                   Progress *aProgress)
-        : VMProgressTask(aConsole, aProgress, false /* aUsesVMPtr */),
+        : VMTask(aConsole, aProgress, NULL /* aServerProgress */,
+                 false /* aUsesVMPtr */),
           mConfigConstructor(NULL),
           mStartPaused(false),
@@ -242,15 +238,31 @@
 };
 
-struct VMSaveTask : public VMProgressTask
-{
-    VMSaveTask(Console *aConsole, Progress *aProgress, const ComPtr<IProgress> &aServerProgress)
-        : VMProgressTask(aConsole, aProgress, true /* aUsesVMPtr */),
-          mLastMachineState(MachineState_Null),
-          mServerProgress(aServerProgress)
+struct VMPowerDownTask : public VMTask
+{
+    VMPowerDownTask(Console *aConsole,
+                    const ComPtr<IProgress> &aServerProgress,
+                    MachineState_T aLastMachineState)
+        : VMTask(aConsole, NULL /* aProgress */, aServerProgress,
+                 true /* aUsesVMPtr */),
+          mLastMachineState(aLastMachineState)
+    {}
+
+    MachineState_T mLastMachineState;
+};
+
+struct VMSaveTask : public VMTask
+{
+    VMSaveTask(Console *aConsole,
+               const ComPtr<IProgress> &aServerProgress,
+               const Utf8Str &aSavedStateFile,
+               MachineState_T aLastMachineState)
+        : VMTask(aConsole, NULL /* aProgress */, aServerProgress,
+                 true /* aUsesVMPtr */),
+          mSavedStateFile(aSavedStateFile),
+          mLastMachineState(aLastMachineState)
     {}
 
     Utf8Str mSavedStateFile;
     MachineState_T mLastMachineState;
-    ComPtr<IProgress> mServerProgress;
 };
 
@@ -1398,5 +1410,5 @@
     {
         LogFunc(("Console::doGuestPropNotification: hrc=%Rhrc pCBData={.pcszName=%s, .pcszValue=%s, .pcszFlags=%s}\n",
-                 pCBData->pcszName, pCBData->pcszValue, pCBData->pcszFlags));
+                 hrc, pCBData->pcszName, pCBData->pcszValue, pCBData->pcszFlags));
         rc = Global::vboxStatusCodeFromCOM(hrc);
     }
@@ -1723,9 +1735,8 @@
 STDMETHODIMP Console::PowerDown(IProgress **aProgress)
 {
-    if (aProgress == NULL)
-        return E_POINTER;
-
     LogFlowThisFuncEnter();
     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
+
+    CheckComArgOutPointerValid(aProgress);
 
     AutoCaller autoCaller(this);
@@ -1785,34 +1796,72 @@
     LogFlowThisFunc(("Initiating SHUTDOWN request...\n"));
 
-    /* create an IProgress object to track progress of this operation */
-    ComObjPtr<Progress> pProgress;
-    pProgress.createObject();
-    pProgress->init(static_cast<IConsole *>(this),
-                    Bstr(tr("Stopping virtual machine")).raw(),
-                    FALSE /* aCancelable */);
-
-    /* setup task object and thread to carry out the operation asynchronously */
-    std::auto_ptr<VMProgressTask> task(new VMProgressTask(this, pProgress, true /* aUsesVMPtr */));
-    AssertReturn(task->isOk(), E_FAIL);
-
-    int vrc = RTThreadCreate(NULL, Console::powerDownThread,
-                             (void *) task.get(), 0,
-                             RTTHREADTYPE_MAIN_WORKER, 0,
-                             "VMPowerDown");
-    if (RT_FAILURE(vrc))
-        return setError(E_FAIL, "Could not create VMPowerDown thread (%Rrc)", vrc);
-
-    /* task is now owned by powerDownThread(), so release it */
-    task.release();
-
-    /* go to Stopping state to forbid state-dependent operations */
-    setMachineState(MachineState_Stopping);
-
-    /* pass the progress to the caller */
-    pProgress.queryInterfaceTo(aProgress);
-
+    /* memorize the current machine state */
+    MachineState_T lastMachineState = mMachineState;
+
+    HRESULT rc = S_OK;
+    bool fBeganPowerDown = false;
+
+    do
+    {
+        ComPtr<IProgress> pProgress;
+
+        /*
+         * request a progress object from the server
+         * (this will set the machine state to Stopping on the server to block
+         * others from accessing this machine)
+         */
+        rc = mControl->BeginPoweringDown(pProgress.asOutParam());
+        if (FAILED(rc))
+            break;
+
+        fBeganPowerDown = true;
+
+        /* sync the state with the server */
+        setMachineStateLocally(MachineState_Stopping);
+
+        /* setup task object and thread to carry out the operation asynchronously */
+        std::auto_ptr<VMPowerDownTask> task(new VMPowerDownTask(this, pProgress,
+                                                                lastMachineState));
+        AssertBreakStmt(task->isOk(), rc = E_FAIL);
+
+        int vrc = RTThreadCreate(NULL, Console::powerDownThread,
+                                 (void *) task.get(), 0,
+                                 RTTHREADTYPE_MAIN_WORKER, 0,
+                                 "VMPowerDown");
+        if (RT_FAILURE(vrc))
+        {
+            rc = setError(E_FAIL, "Could not create VMPowerDown thread (%Rrc)", vrc);
+            break;
+        }
+
+        /* task is now owned by powerDownThread(), so release it */
+        task.release();
+
+        /* pass the progress to the caller */
+        pProgress.queryInterfaceTo(aProgress);
+    }
+    while (0);
+
+    if (FAILED(rc))
+    {
+        /* preserve existing error info */
+        ErrorInfoKeeper eik;
+
+        if (fBeganPowerDown)
+        {
+            /*
+             * cancel the requested power down procedure.
+             * This will reset the machine state to the state it had right
+             * before calling mControl->BeginPoweringDown().
+             */
+            mControl->EndPoweringDown(eik.getResultCode(), eik.getText().raw());        }
+
+        setMachineStateLocally(lastMachineState);
+    }
+
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
 
-    return S_OK;
+    return rc;
 }
 
@@ -1848,5 +1897,5 @@
                  vrc);
 
-    LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc));
+    LogFlowThisFunc(("mMachineState=%d, rc=%Rhrc\n", mMachineState, rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -1978,5 +2027,5 @@
                       tr("Hot-Remove was aborted because the CPU may still be used by the guest"), VERR_RESOURCE_BUSY);
 
-    LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc));
+    LogFlowThisFunc(("mMachineState=%d, rc=%Rhrc\n", mMachineState, rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2095,5 +2144,5 @@
     }
 
-    LogFlowThisFunc(("mMachineState=%d, rc=%08X\n", mMachineState, rc));
+    LogFlowThisFunc(("mMachineState=%d, rc=%Rhrc\n", mMachineState, rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2186,5 +2235,5 @@
                  vrc);
 
-    LogFlowThisFunc(("rc=%08X\n", rc));
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2224,5 +2273,5 @@
                  vrc);
 
-    LogFlowThisFunc(("rc=%08X\n", rc));
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2268,5 +2317,5 @@
     *aHandled = handled;
 
-    LogFlowThisFunc(("rc=%08X\n", rc));
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2343,5 +2392,5 @@
             vrc);
 
-    LogFlowThisFunc(("rc=%08X\n", rc));
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2399,19 +2448,4 @@
         /* sync the state with the server */
         setMachineStateLocally(MachineState_Saving);
-
-        /* create a task object early to ensure mpVM protection is successful */
-        std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, NULL, pProgress));
-        rc = task->rc();
-        /*
-         * If we fail here it means a PowerDown() call happened on another
-         * thread while we were doing Pause() (which leaves the Console lock).
-         * We assign PowerDown() a higher precedence than SaveState(),
-         * therefore just return the error to the caller.
-         */
-        if (FAILED(rc))
-        {
-            fTaskCreationFailed = true;
-            break;
-        }
 
         /* ensure the directory for the saved state file exists */
@@ -2432,8 +2466,20 @@
         }
 
-        /* setup task object and thread to carry out the operation asynchronously */
-        task->mSavedStateFile = stateFilePath;
-        /* set the state the operation thread will restore when it is finished */
-        task->mLastMachineState = lastMachineState;
+        /* create a task object early to ensure mpVM protection is successful */
+        std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, pProgress,
+                                                      stateFilePath,
+                                                      lastMachineState));
+        rc = task->rc();
+        /*
+         * If we fail here it means a PowerDown() call happened on another
+         * thread while we were doing Pause() (which leaves the Console lock).
+         * We assign PowerDown() a higher precedence than SaveState(),
+         * therefore just return the error to the caller.
+         */
+        if (FAILED(rc))
+        {
+            fTaskCreationFailed = true;
+            break;
+        }
 
         /* create a thread to wait until the VM state is saved */
@@ -2480,5 +2526,5 @@
     }
 
-    LogFlowThisFunc(("rc=%08X\n", rc));
+    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     LogFlowThisFuncLeave();
     return rc;
@@ -2917,5 +2963,5 @@
 {
     LogFlowThisFuncEnter();
-    LogFlowThisFunc(("aName='%ls' mMachineState=%08X\n", aName, mMachineState));
+    LogFlowThisFunc(("aName='%ls' mMachineState=%d\n", aName, mMachineState));
 
     CheckComArgStrNotEmptyOrNull(aName);
@@ -3037,5 +3083,5 @@
     {
         delete pTask;
-        NOREF(erc);
+        rc = erc;
         mptrCancelableProgress.setNull();
     }
@@ -5307,14 +5353,11 @@
  * @param   aProgress       Where to return the progress object.
  * @param   aPaused         true if PowerUpPaused called.
- *
- * @todo move down to powerDown();
  */
 HRESULT Console::powerUp(IProgress **aProgress, bool aPaused)
 {
-    if (aProgress == NULL)
-        return E_POINTER;
-
     LogFlowThisFuncEnter();
     LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
+
+    CheckComArgOutPointerValid(aProgress);
 
     AutoCaller autoCaller(this);
@@ -5705,5 +5748,5 @@
  *       release(). Otherwise it will deadlock.
  */
-HRESULT Console::powerDown(Progress *aProgress /*= NULL*/)
+HRESULT Console::powerDown(IProgress *aProgress /*= NULL*/)
 {
     LogFlowThisFuncEnter();
@@ -5848,11 +5891,4 @@
         alock.enter();
     }
-    else
-    {
-        /** @todo r=bird: Doesn't make sense. Please remove after 3.1 has been branched
-         *        off. */
-        /* reset the flag for future re-use */
-        mVMPoweredOff = false;
-    }
 
     /* advance percent count */
@@ -5969,8 +6005,4 @@
     if (SUCCEEDED(rc))
         mCallbackData.clear();
-
-    /* complete the progress */
-    if (aProgress)
-        aProgress->notifyComplete(rc);
 
     LogFlowThisFuncLeave();
@@ -6025,5 +6057,5 @@
             LogFlowThisFunc(("Doing mControl->UpdateState()...\n"));
             rc = mControl->UpdateState(aMachineState);
-            LogFlowThisFunc(("mControl->UpdateState()=%08X\n", rc));
+            LogFlowThisFunc(("mControl->UpdateState()=%Rhrc\n", rc));
         }
     }
@@ -6422,6 +6454,7 @@
                  * deadlock).
                  */
-                std::auto_ptr<VMProgressTask> task(new VMProgressTask(that, NULL /* aProgress */,
-                                                                      true /* aUsesVMPtr */));
+                std::auto_ptr<VMPowerDownTask> task(new VMPowerDownTask(that,
+                                                                        NULL /* aServerProgress */,
+                                                                        MachineState_Null));
 
                  /* If creating a task failed, this can currently mean one of
@@ -6659,5 +6692,4 @@
 
 #ifdef VBOX_WITH_USB
-
 /**
  * Sends a request to VMM to attach the given host device.
@@ -6892,8 +6924,7 @@
     return vrc;
 }
-
 #endif /* VBOX_WITH_USB */
-#if ((defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)) || defined(RT_OS_FREEBSD))
-
+
+#if ((defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)) && !defined(VBOX_WITH_NETFLT))
 /**
  * Helper function to handle host interface device creation and attachment.
@@ -7130,5 +7161,4 @@
     return rc;
 }
-
 #endif /* (RT_OS_LINUX || RT_OS_FREEBSD) && !VBOX_WITH_NETFLT */
 
@@ -7164,9 +7194,9 @@
         if (attachment == NetworkAttachmentType_Bridged)
         {
-#if defined(RT_OS_LINUX) && !defined(VBOX_WITH_NETFLT)
+#if ((defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)) && !defined(VBOX_WITH_NETFLT))
             HRESULT rc2 = detachFromTapInterface(pNetworkAdapter);
             if (FAILED(rc2) && SUCCEEDED(rc))
                 rc = rc2;
-#endif
+#endif /* (RT_OS_LINUX || RT_OS_FREEBSD) && !VBOX_WITH_NETFLT */
         }
     }
@@ -7520,5 +7550,5 @@
                                      COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE |
                                      COINIT_SPEED_OVER_MEMORY);
-        LogFlowFunc(("CoInitializeEx()=%08X\n", hrc));
+        LogFlowFunc(("CoInitializeEx()=%Rhrc\n", hrc));
     }
 #endif
@@ -8438,8 +8468,10 @@
     LogFlowFuncEnter();
 
-    std::auto_ptr<VMProgressTask> task(static_cast<VMProgressTask *>(pvUser));
+    std::auto_ptr<VMPowerDownTask> task(static_cast<VMPowerDownTask *>(pvUser));
     AssertReturn(task.get(), VERR_INVALID_PARAMETER);
 
     AssertReturn(task->isOk(), VERR_GENERAL_FAILURE);
+
+    Assert(task->mProgress.isNull());
 
     const ComObjPtr<Console> &that = task->mConsole;
@@ -8454,5 +8486,8 @@
     task->releaseVMCaller();
 
-    that->powerDown(task->mProgress);
+    that->powerDown(task->mServerProgress);
+
+    /* complete the operation */
+    that->mControl->EndPoweringDown(S_OK, Bstr().raw());
 
     LogFlowFuncLeave();
Index: /trunk/src/VBox/Main/src-server/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 35459)
+++ /trunk/src/VBox/Main/src-server/MachineImpl.cpp	(revision 35460)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -10479,5 +10479,4 @@
 }
 
-
 /**
  *  @note Locks this object for writing.
@@ -10513,4 +10512,92 @@
     return S_OK;
 }
+
+/**
+ *  @note Locks this object for writing.
+ */
+STDMETHODIMP SessionMachine::BeginPoweringDown(IProgress **aProgress)
+{
+    LogFlowThisFuncEnter();
+
+    CheckComArgOutPointerValid(aProgress);
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    AssertReturn(mConsoleTaskData.mLastState == MachineState_Null,
+                 E_FAIL);
+
+    /* create a progress object to track operation completion */
+    ComObjPtr<Progress> pProgress;
+    pProgress.createObject();
+    pProgress->init(getVirtualBox(),
+                    static_cast<IMachine *>(this) /* aInitiator */,
+                    Bstr(tr("Stopping the virtual machine")).raw(),
+                    FALSE /* aCancelable */);
+
+    /* fill in the console task data */
+    mConsoleTaskData.mLastState = mData->mMachineState;
+    mConsoleTaskData.mProgress = pProgress;
+
+    /* set the state to Stopping (this is expected by Console::PowerDown()) */
+    setMachineState(MachineState_Stopping);
+
+    pProgress.queryInterfaceTo(aProgress);
+
+    return S_OK;
+}
+
+/**
+ *  @note Locks this object for writing.
+ */
+STDMETHODIMP SessionMachine::EndPoweringDown(LONG iResult, IN_BSTR aErrMsg)
+{
+    LogFlowThisFuncEnter();
+
+    AutoCaller autoCaller(this);
+    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    AssertReturn(    (   (SUCCEEDED(iResult) && mData->mMachineState == MachineState_PoweredOff)
+                      || (FAILED(iResult) && mData->mMachineState == MachineState_Stopping))
+                  && mConsoleTaskData.mLastState != MachineState_Null,
+                 E_FAIL);
+
+    /*
+     * On failure, set the state to the state we had when BeginPoweringDown()
+     * was called (this is expected by Console::PowerDown() and the associated
+     * task). On success the VM process already changed the state to
+     * MachineState_PoweredOff, so no need to do anything.
+     */
+    if (FAILED(iResult))
+        setMachineState(mConsoleTaskData.mLastState);
+
+    /* notify the progress object about operation completion */
+    Assert(mConsoleTaskData.mProgress);
+    if (SUCCEEDED(iResult))
+        mConsoleTaskData.mProgress->notifyComplete(S_OK);
+    else
+    {
+        Utf8Str strErrMsg(aErrMsg);
+        if (strErrMsg.length())
+            mConsoleTaskData.mProgress->notifyComplete(iResult,
+                                                       COM_IIDOF(ISession),
+                                                       getComponentName(),
+                                                       strErrMsg.c_str());
+        else
+            mConsoleTaskData.mProgress->notifyComplete(iResult);
+    }
+
+    /* clear out the temporary saved state data */
+    mConsoleTaskData.mLastState = MachineState_Null;
+    mConsoleTaskData.mProgress.setNull();
+
+    LogFlowThisFuncLeave();
+    return S_OK;
+}
+
 
 /**
@@ -10779,5 +10866,5 @@
     }
 
-    /* fill in the snapshot data */
+    /* fill in the console task data */
     mConsoleTaskData.mLastState = mData->mMachineState;
     mConsoleTaskData.mStateFilePath = stateFilePath;
@@ -11541,7 +11628,7 @@
         if (aErrMsg.length())
             mConsoleTaskData.mProgress->notifyComplete(aRc,
-                                                    COM_IIDOF(ISession),
-                                                    getComponentName(),
-                                                    aErrMsg.c_str());
+                                                       COM_IIDOF(ISession),
+                                                       getComponentName(),
+                                                       aErrMsg.c_str());
         else
             mConsoleTaskData.mProgress->notifyComplete(aRc);
