Index: /trunk/src/VBox/Main/HostPower.cpp
===================================================================
--- /trunk/src/VBox/Main/HostPower.cpp	(revision 13712)
+++ /trunk/src/VBox/Main/HostPower.cpp	(revision 13713)
@@ -29,6 +29,7 @@
 #include "Logging.h"
 
-HostPowerService::HostPowerService(VirtualBox *aVirtualBox) : aMachineSuspended(NULL), cbMachineSuspended(0)
+HostPowerService::HostPowerService (VirtualBox *aVirtualBox)
 {
+    Assert (aVirtualBox != NULL);
     mVirtualBox = aVirtualBox;
 }
@@ -38,129 +39,113 @@
 }
 
-
-void HostPowerService::notify(HostPowerEvent event)
+void HostPowerService::notify (HostPowerEvent aEvent)
 {
     VirtualBox::SessionMachineVector machines;
-    mVirtualBox->getOpenedMachines (machines);
+    VirtualBox::InternalControlVector controls;
 
-    switch (event)
+    HRESULT rc = S_OK;
+
+    switch (aEvent)
     {
-    case HostPowerEvent_Suspend:
-        if (machines.size())
-            aMachineSuspended = (BOOL *)RTMemAllocZ(sizeof(BOOL) * machines.size());
+        case HostPowerEvent_Suspend:
+        {
+            LogFunc (("SUSPEND\n"));
 
-        cbMachineSuspended = machines.size();
+            mVirtualBox->getOpenedMachinesAndControls (machines, controls);
 
-        for (size_t i = 0; i < machines.size(); i++)
-            processEvent(machines[i], HostPowerEvent_Suspend, (aMachineSuspended) ? &aMachineSuspended[i] : NULL);
+            /* pause running VMs */
+            for (size_t i = 0; i < controls.size(); ++ i)
+            {
+                /* get the remote console */
+                ComPtr <IConsole> console;
+                rc = controls [i]->GetRemoteConsole (console.asOutParam());
+                /* the VM could have been powered down and closed or whatever */
+                if (FAILED (rc))
+                    continue;
 
-        Log(("HostPowerService::notify SUSPEND\n"));
-        break;
+                /* note that Pause() will simply return a failure if the VM is
+                 * in an inappropriate state */
+                rc = console->Pause();
+                if (FAILED (rc))
+                    continue;
 
-    case HostPowerEvent_Resume:
-        Log(("HostPowerService::notify RESUME\n"));
+                /* save the control to un-pause the VM later */
+                mConsoles.push_back (console);
+            }
 
-        if (aMachineSuspended)
-        {
-            /* It's possible (in theory) that machines are created or destroyed between the suspend notification and the actual host suspend.
-             * Ignore this edge case and just make sure not to access invalid data.
-             */
-            cbMachineSuspended = RT_MIN(machines.size(), cbMachineSuspended);
+            LogFunc (("Suspended %d VMs\n", mConsoles.size()));
 
-            for (size_t i = 0; i < cbMachineSuspended; i++)
-                processEvent(machines[i], HostPowerEvent_Resume, &aMachineSuspended[i]);
-
-            RTMemFree(aMachineSuspended);
-            cbMachineSuspended = 0;
-            aMachineSuspended  = NULL;
-        }
-        break;
-
-    case HostPowerEvent_BatteryLow:
-        Log(("HostPowerService::notify BATTERY LOW\n"));
-        for (size_t i = 0; i < machines.size(); i++)
-            processEvent(machines[i], HostPowerEvent_BatteryLow, NULL);
-        break;
-    }
-
-    machines.clear();
-}
-
-HRESULT HostPowerService::processEvent(SessionMachine *machine, HostPowerEvent event, BOOL *pMachineSuspended)
-{
-    MachineState_T state;
-    HRESULT        rc;
-
-    rc = machine->COMGETTER(State)(&state);
-    CheckComRCReturnRC (rc);
-
-    /* Power event handling:
-     * - pause running machines for HostPowerEvent_Suspend
-     * - resume paused machines for HostPowerEvent_Resume
-     * - save the state of running and paused machine for HostPowerEvent_BatteryLow
-     */
-    if (    (state == MachineState_Running && event != HostPowerEvent_Resume)
-        ||  (state == MachineState_Paused  && event != HostPowerEvent_Suspend))
-    {
-        ComPtr <ISession> session;
-
-        rc = session.createInprocObject (CLSID_Session);
-        if (FAILED (rc))
-            return rc;
-
-        /* get the IInternalSessionControl interface */
-        ComPtr <IInternalSessionControl> control = session;
-        if (!control)
-        {
-            rc = E_INVALIDARG;
-            goto fail;
+            break;
         }
 
-        rc = machine->openExistingSession (control);
-        if (SUCCEEDED (rc))
+        case HostPowerEvent_Resume:
         {
-            /* get the associated console */
-            ComPtr<IConsole> console;
-            rc = session->COMGETTER(Console)(console.asOutParam());
-            if (SUCCEEDED (rc))
+            LogFunc (("RESUME\n"));
+
+            size_t resumed = 0;
+
+            /* go through VMs we paused on Suspend */
+            for (size_t i = 0; i < mConsoles.size(); ++ i)
             {
-                switch (event)
-                {
-                case HostPowerEvent_Suspend:
-                    rc = console->Pause();
-                    if (    SUCCEEDED(rc)
-                        &&  pMachineSuspended)
-                        *pMachineSuspended = TRUE;
-                    break;
+                /* note that Resume() will simply return a failure if the VM is
+                 * in an inappropriate state (it will also fail if the VM has
+                 * been somehow closed by this time already so that the
+                 * console reference we have is dead) */
+                rc = mConsoles [i]->Resume();
+                if (FAILED (rc))
+                    continue;
 
-                case HostPowerEvent_Resume:
-                    Assert(pMachineSuspended);
-                    if (*pMachineSuspended == TRUE)
-                        rc = console->Resume();
-                    break;
+                ++ resumed;
+            }
 
-                case HostPowerEvent_BatteryLow:
-                {
-                    ComPtr<IProgress> progress;
+            LogFunc (("Resumed %d VMs\n", resumed));
 
-                    rc = console->SaveState(progress.asOutParam());
-                    if (SUCCEEDED(rc))
-                    {
-                        /* Wait until the operation has been completed. */
-                        progress->WaitForCompletion(-1); 
+            mConsoles.clear();
 
-                        progress->COMGETTER(ResultCode)(&rc);
-                        AssertMsg(SUCCEEDED(rc), ("SaveState WaitForCompletion failed with %x\n", rc));
-                    }
+            break;
+        }
 
-                    break;
-                }
+        case HostPowerEvent_BatteryLow:
+        {
+            LogFunc (("BATTERY LOW\n"));
 
-                } /* switch (event) */
+            mVirtualBox->getOpenedMachinesAndControls (machines, controls);
+
+            size_t saved = 0;
+
+            /* save running VMs */
+            for (size_t i = 0; i < controls.size(); ++ i)
+            {
+                /* get the remote console */
+                ComPtr <IConsole> console;
+                rc = controls [i]->GetRemoteConsole (console.asOutParam());
+                /* the VM could have been powered down and closed or whatever */
+                if (FAILED (rc))
+                    continue;
+
+                ComPtr<IProgress> progress;
+
+                /* note that SaveState() will simply return a failure if the VM
+                 * is in an inappropriate state */
+                rc = console->SaveState (progress.asOutParam());
+                if (FAILED (rc))
+                    continue;
+
+                /* Wait until the operation has been completed. */
+                rc = progress->WaitForCompletion(-1);
+                if (SUCCEEDED (rc))
+                    progress->COMGETTER(ResultCode) (&rc);
+
+                AssertMsg (SUCCEEDED (rc), ("SaveState WaitForCompletion "
+                                            "failed with %Rhrc (%#08X)\n", rc, rc));
+
+                if (SUCCEEDED (rc))
+                    ++ saved;
             }
+
+            LogFunc (("Saved %d VMs\n", saved));
+
+            break;
         }
-fail:
-        session->Close();
     }
-    return rc;
 }
Index: /trunk/src/VBox/Main/MachineImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MachineImpl.cpp	(revision 13712)
+++ /trunk/src/VBox/Main/MachineImpl.cpp	(revision 13713)
@@ -3828,5 +3828,6 @@
  *
  * @param aMachine  Session machine object.
- * @param aIPCSem   Mutex IPC semaphore handle for this machine.
+ * @param aControl  Direct session control object (optional).
+ * @param aIPCSem   Mutex IPC semaphore handle for this machine (optional).
  *
  * @note locks this object for reading.
@@ -3834,12 +3835,15 @@
 #if defined (RT_OS_WINDOWS)
 bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
                              HANDLE *aIPCSem /*= NULL*/,
                              bool aAllowClosing /*= false*/)
 #elif defined (RT_OS_OS2)
 bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
                              HMTX *aIPCSem /*= NULL*/,
                              bool aAllowClosing /*= false*/);
 #else
 bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                             ComPtr <IInternalSessionControl> *aControl /*= NULL*/,
                              bool aAllowClosing /*= false*/)
 #endif
@@ -3860,4 +3864,7 @@
 
         aMachine = mData->mSession.mMachine;
+
+        if (aControl != NULL)
+            *aControl = mData->mSession.mDirectControl;
 
 #if defined (RT_OS_WINDOWS) || defined (RT_OS_OS2)
Index: /trunk/src/VBox/Main/VirtualBoxImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 13712)
+++ /trunk/src/VBox/Main/VirtualBoxImpl.cpp	(revision 13713)
@@ -2499,8 +2499,11 @@
 
 /**
- * Returns the list of opened machines (machines having direct sessionsopened by
- * client processes).
- *
- * @note The returned list contains smart pointers. So, clear it as soon as
+ * Returns the list of opened machines (machines having direct sessions opened
+ * by client processes) and optionally the list of direct session controls.
+ *
+ * @param aMachines     Where to put opened machines (will be empty if none).
+ * @param aControls     Where to put direct session controls (optional).
+ *
+ * @note The returned lists contain smart pointers. So, clear it as soon as
  * it becomes no more necessary to release instances.
  *
@@ -2511,10 +2514,13 @@
  * @note Locks objects for reading.
  */
-void VirtualBox::getOpenedMachines (SessionMachineVector &aVector)
+void VirtualBox::getOpenedMachines (SessionMachineVector &aMachines,
+                                    InternalControlVector *aControls /*= NULL*/)
 {
     AutoCaller autoCaller (this);
     AssertComRCReturnVoid (autoCaller.rc());
 
-    aVector.clear();
+    aMachines.clear();
+    if (aControls)
+        aControls->clear();
 
     AutoReadLock alock (this);
@@ -2525,6 +2531,11 @@
     {
         ComObjPtr <SessionMachine> sm;
-        if ((*it)->isSessionOpen (sm))
-            aVector.push_back (sm);
+        ComPtr <IInternalSessionControl> ctl;
+        if ((*it)->isSessionOpen (sm, &ctl))
+        {
+            aMachines.push_back (sm);
+            if (aControls)
+                aControls->push_back (ctl);
+        }
     }
 }
@@ -4071,5 +4082,5 @@
                     ComObjPtr <SessionMachine> sm;
                     HANDLE ipcSem;
-                    if ((*it)->isSessionOpenOrClosing (sm, &ipcSem))
+                    if ((*it)->isSessionOpenOrClosing (sm, NULL, &ipcSem))
                     {
                         machines.push_back (sm);
@@ -4263,5 +4274,5 @@
                         ComObjPtr <SessionMachine> sm;
                         HMTX ipcSem;
-                        if ((*it)->isSessionOpenOrClosing (sm, &ipcSem))
+                        if ((*it)->isSessionOpenOrClosing (sm, NULL, &ipcSem))
                         {
                             machines.push_back (sm);
Index: /trunk/src/VBox/Main/include/HostImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/HostImpl.h	(revision 13712)
+++ /trunk/src/VBox/Main/include/HostImpl.h	(revision 13713)
@@ -126,6 +126,4 @@
 #endif
 
-    HostPowerService *mHostPowerService;
-
     // for VirtualBoxSupportErrorInfoImpl
     static const wchar_t *getComponentName() { return L"Host"; }
@@ -179,4 +177,5 @@
 #endif /* VBOX_WITH_USB */
 
+    HostPowerService *mHostPowerService;
 };
 
Index: /trunk/src/VBox/Main/include/HostPower.h
===================================================================
--- /trunk/src/VBox/Main/include/HostPower.h	(revision 13712)
+++ /trunk/src/VBox/Main/include/HostPower.h	(revision 13713)
@@ -26,4 +26,6 @@
 #include "MachineImpl.h"
 
+#include <vector>
+
 class VirtualBox;
 
@@ -38,15 +40,15 @@
 {
 public:
-    HostPowerService(VirtualBox *aVirtualBox);
+
+    HostPowerService (VirtualBox *aVirtualBox);
     virtual ~HostPowerService();
 
-    void    notify(HostPowerEvent event);
-    HRESULT processEvent(SessionMachine *machine, HostPowerEvent event, BOOL *paMachineSuspended);
+    void    notify (HostPowerEvent aEvent);
 
 protected:
+
     ComObjPtr <VirtualBox, ComWeakRef> mVirtualBox;
 
-    BOOL    *aMachineSuspended;
-    size_t   cbMachineSuspended;
+    std::vector <ComPtr <IConsole> > mConsoles;
 };
 
@@ -58,8 +60,10 @@
 {
 public:
+
     HostPowerServiceWin(VirtualBox *aVirtualBox);
     virtual ~HostPowerServiceWin();
 
 private:
+
     static DECLCALLBACK(int) NotificationThread (RTTHREAD ThreadSelf, void *pInstance);
     static LRESULT CALLBACK  WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
Index: /trunk/src/VBox/Main/include/MachineImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/MachineImpl.h	(revision 13712)
+++ /trunk/src/VBox/Main/include/MachineImpl.h	(revision 13713)
@@ -636,14 +636,17 @@
 
     bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                        ComPtr <IInternalSessionControl> *aControl = NULL,
                         HANDLE *aIPCSem = NULL, bool aAllowClosing = false);
     bool isSessionSpawning (RTPROCESS *aPID = NULL);
 
     bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
+                                 ComPtr <IInternalSessionControl> *aControl = NULL,
                                  HANDLE *aIPCSem = NULL)
-    { return isSessionOpen (aMachine, aIPCSem, true /* aAllowClosing */); }
+    { return isSessionOpen (aMachine, aControl, aIPCSem, true /* aAllowClosing */); }
 
 #elif defined (RT_OS_OS2)
 
     bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                        ComPtr <IInternalSessionControl> *aControl = NULL,
                         HMTX *aIPCSem = NULL, bool aAllowClosing = false);
 
@@ -651,15 +654,18 @@
 
     bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
+                                 ComPtr <IInternalSessionControl> *aControl = NULL,
                                  HMTX *aIPCSem = NULL)
-    { return isSessionOpen (aMachine, aIPCSem, true /* aAllowClosing */); }
+    { return isSessionOpen (aMachine, aControl, aIPCSem, true /* aAllowClosing */); }
 
 #else
 
     bool isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                        ComPtr <IInternalSessionControl> *aControl = NULL,
                         bool aAllowClosing = false);
     bool isSessionSpawning();
 
-    bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine)
-    { return isSessionOpen (aMachine, true /* aAllowClosing */); }
+    bool isSessionOpenOrClosing (ComObjPtr <SessionMachine> &aMachine,
+                                 ComPtr <IInternalSessionControl> *aControl = NULL)
+    { return isSessionOpen (aMachine, aControl, true /* aAllowClosing */); }
 
 #endif
@@ -961,4 +967,5 @@
     Bstr mIPCSemName;
     friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                                        ComPtr <IInternalSessionControl> *aControl,
                                         HANDLE *aIPCSem, bool aAllowClosing);
 #elif defined (RT_OS_OS2)
@@ -966,4 +973,5 @@
     Bstr mIPCSemName;
     friend bool Machine::isSessionOpen (ComObjPtr <SessionMachine> &aMachine,
+                                        ComPtr <IInternalSessionControl> *aControl,
                                         HMTX *aIPCSem, bool aAllowClosing);
 #elif defined (VBOX_WITH_SYS_V_IPC_SESSION_WATCHER)
Index: /trunk/src/VBox/Main/include/VirtualBoxImpl.h
===================================================================
--- /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 13712)
+++ /trunk/src/VBox/Main/include/VirtualBoxImpl.h	(revision 13713)
@@ -82,4 +82,6 @@
     typedef std::vector <ComObjPtr <SessionMachine> > SessionMachineVector;
     typedef std::vector <ComObjPtr <Machine> > MachineVector;
+
+    typedef std::vector <ComPtr <IInternalSessionControl> > InternalControlVector;
 
     class CallbackEvent;
@@ -216,5 +218,11 @@
     ComObjPtr <GuestOSType> getUnknownOSType();
 
-    void getOpenedMachines (SessionMachineVector &aVector);
+    void getOpenedMachines (SessionMachineVector &aMachines,
+                            InternalControlVector *aControls = NULL);
+
+    /** Shortcut to #getOpenedMachines (aMachines, &aControls). */
+    void getOpenedMachinesAndControls (SessionMachineVector &aMachines,
+                                       InternalControlVector &aControls)
+    { getOpenedMachines (aMachines, &aControls); }
 
     bool isMachineIdValid (const Guid &aId)
