Index: trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 34837)
+++ trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp	(revision 34839)
@@ -76,5 +76,4 @@
 
 /* global weak references (for event handlers) */
-static ISession *gSession = NULL;
 static IConsole *gConsole = NULL;
 static EventQueue *gEventQ = NULL;
@@ -88,4 +87,45 @@
 
 ////////////////////////////////////////////////////////////////////////////////
+
+/**
+ *  Handler for VirtualBoxClient events.
+ */
+class VirtualBoxClientEventListener
+{
+public:
+    VirtualBoxClientEventListener()
+    {
+    }
+
+    virtual ~VirtualBoxClientEventListener()
+    {
+    }
+
+    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent * aEvent)
+    {
+        switch (aType)
+        {
+            case VBoxEventType_OnVBoxSVCUnavailable:
+            {
+                ComPtr<IVBoxSVCUnavailableEvent> pVSUEv = aEvent;
+                Assert(pVSUEv);
+
+                LogRel(("VBoxHeadless: VBoxSVC became unavailable, exiting.\n"));
+                RTPrintf("VBoxSVC became unavailable, exiting.\n");
+                /* Terminate the VM as cleanly as possible given that VBoxSVC
+                 * is no longer present. */
+                g_fTerminateFE = true;
+                gEventQ->interruptEventQueueProcessing();
+                break;
+            }
+            default:
+                AssertFailed();
+        }
+
+        return S_OK;
+    }
+
+private:
+};
 
 /**
@@ -201,7 +241,8 @@
 {
 public:
-    ConsoleEventListener()
-    {
-        mLastVRDEPort = -1;
+    ConsoleEventListener() :
+        mLastVRDEPort(-1),
+        m_fIgnorePowerOffEvents(false)
+    {
     }
 
@@ -249,5 +290,5 @@
                 /* Terminate any event wait operation if the machine has been
                  * PoweredDown/Saved/Aborted. */
-                if (machineState < MachineState_Running)
+                if (machineState < MachineState_Running && !m_fIgnorePowerOffEvents)
                 {
                     g_fTerminateFE = true;
@@ -305,12 +346,20 @@
     }
 
+    void ignorePowerOffEvents(bool fIgnore)
+    {
+        m_fIgnorePowerOffEvents = fIgnore;
+    }
+
 private:
 
     long mLastVRDEPort;
+    bool m_fIgnorePowerOffEvents;
 };
 
+typedef ListenerImpl<VirtualBoxClientEventListener> VirtualBoxClientEventListenerImpl;
 typedef ListenerImpl<VirtualBoxEventListener> VirtualBoxEventListenerImpl;
 typedef ListenerImpl<ConsoleEventListener> ConsoleEventListenerImpl;
 
+VBOX_LISTENER_DECLARE(VirtualBoxClientEventListenerImpl)
 VBOX_LISTENER_DECLARE(VirtualBoxEventListenerImpl)
 VBOX_LISTENER_DECLARE(ConsoleEventListenerImpl)
@@ -705,23 +754,19 @@
     }
 
+    ComPtr<IVirtualBoxClient> pVirtualBoxClient;
     ComPtr<IVirtualBox> virtualBox;
     ComPtr<ISession> session;
+    ComPtr<IMachine> machine;
     bool fSessionOpened = false;
-    IEventListener *vboxListener = NULL, *consoleListener = NULL;
+    IEventListener *vboxClientListener = NULL;
+    IEventListener *vboxListener = NULL;
+    ConsoleEventListenerImpl *consoleListener = NULL;
 
     do
     {
-        rc = virtualBox.createLocalObject(CLSID_VirtualBox);
+        rc = pVirtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
         if (FAILED(rc))
-            RTPrintf("VBoxHeadless: ERROR: failed to create the VirtualBox object!\n");
-        else
-        {
-            rc = session.createInprocObject(CLSID_Session);
-            if (FAILED(rc))
-                RTPrintf("VBoxHeadless: ERROR: failed to create a session object!\n");
-        }
-
-        if (FAILED(rc))
-        {
+        {
+            RTPrintf("VBoxHeadless: ERROR: failed to create the VirtualBoxClient object!\n");
             com::ErrorInfo info;
             if (!info.isFullAvailable() && !info.isBasicAvailable())
@@ -732,4 +777,17 @@
             else
                 GluePrintErrorInfo(info);
+            break;
+        }
+
+        rc = pVirtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam());
+        if (FAILED(rc))
+        {
+            RTPrintf("Failed to get VirtualBox object (rc=%Rhrc)!\n", rc);
+            break;
+        }
+        rc = pVirtualBoxClient->COMGETTER(Session)(session.asOutParam());
+        if (FAILED(rc))
+        {
+            RTPrintf("Failed to get session object (rc=%Rhrc)!\n", rc);
             break;
         }
@@ -761,5 +819,4 @@
 
         /* get the mutable machine */
-        ComPtr<IMachine> machine;
         CHECK_ERROR_BREAK(console, COMGETTER(Machine)(machine.asOutParam()));
 
@@ -930,7 +987,16 @@
 
         /* initialize global references */
-        gSession = session;
         gConsole = console;
         gEventQ = com::EventQueue::getMainEventQueue();
+
+        /* VirtualBoxClient events registration. */
+        {
+            ComPtr<IEventSource> pES;
+            CHECK_ERROR(pVirtualBoxClient, COMGETTER(EventSource)(pES.asOutParam()));
+            vboxClientListener = new VirtualBoxClientEventListenerImpl();
+            com::SafeArray <VBoxEventType_T> eventTypes;
+            eventTypes.push_back(VBoxEventType_OnVBoxSVCUnavailable);
+            CHECK_ERROR(pES, RegisterListener(vboxClientListener, ComSafeArrayAsInParam(eventTypes), true));
+        }
 
         /* Console events registration. */
@@ -1125,4 +1191,44 @@
     while (0);
 
+    /*
+     * Get the machine state.
+     */
+    MachineState_T machineState = MachineState_Aborted;
+    if (!machine.isNull())
+        machine->COMGETTER(State)(&machineState);
+
+    /*
+     * Turn off the VM if it's running
+     */
+    if (   gConsole
+        && (   machineState == MachineState_Running
+            || machineState == MachineState_Teleporting
+            || machineState == MachineState_LiveSnapshotting
+            /** @todo power off paused VMs too? */
+           )
+       )
+    do
+    {
+        consoleListener->getWrapped()->ignorePowerOffEvents(true);
+        ComPtr<IProgress> pProgress;
+        CHECK_ERROR_BREAK(gConsole, PowerDown(pProgress.asOutParam()));
+        CHECK_ERROR_BREAK(pProgress, WaitForCompletion(-1));
+        BOOL completed;
+        CHECK_ERROR_BREAK(pProgress, COMGETTER(Completed)(&completed));
+        ASSERT(completed);
+        LONG hrc;
+        CHECK_ERROR_BREAK(pProgress, COMGETTER(ResultCode)(&hrc));
+        if (FAILED(hrc))
+        {
+            RTPrintf("VBoxHeadless: ERROR: Failed to power down VM!");
+            com::ErrorInfo info;
+            if (!info.isFullAvailable() && !info.isBasicAvailable())
+                com::GluePrintRCMessage(hrc);
+            else
+                GluePrintErrorInfo(info);
+            break;
+        }
+    } while (0);
+
     /* VirtualBox callback unregistration. */
     if (vboxListener)
@@ -1130,5 +1236,6 @@
         ComPtr<IEventSource> es;
         CHECK_ERROR(virtualBox, COMGETTER(EventSource)(es.asOutParam()));
-        CHECK_ERROR(es, UnregisterListener(vboxListener));
+        if (!es.isNull())
+            CHECK_ERROR(es, UnregisterListener(vboxListener));
         vboxListener->Release();
     }
@@ -1139,6 +1246,17 @@
         ComPtr<IEventSource> es;
         CHECK_ERROR(gConsole, COMGETTER(EventSource)(es.asOutParam()));
-        CHECK_ERROR(es, UnregisterListener(consoleListener));
+        if (!es.isNull())
+            CHECK_ERROR(es, UnregisterListener(consoleListener));
         consoleListener->Release();
+    }
+
+    /* VirtualBoxClient callback unregistration. */
+    if (consoleListener)
+    {
+        ComPtr<IEventSource> pES;
+        CHECK_ERROR(pVirtualBoxClient, COMGETTER(EventSource)(pES.asOutParam()));
+        if (!pES.isNull())
+            CHECK_ERROR(pES, UnregisterListener(vboxClientListener));
+        vboxClientListener->Release();
     }
 
@@ -1159,4 +1277,5 @@
     session.setNull();
     virtualBox.setNull();
+    pVirtualBoxClient.setNull();
 
     com::Shutdown();
