Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/Makefile.kmk
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/Makefile.kmk	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/Makefile.kmk	(revision 39986)
@@ -22,5 +22,5 @@
  VBoxBalloonCtrl_TEMPLATE   = VBOXMAINCLIENTEXE
  VBoxBalloonCtrl_DEFS      += \
-	VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\"
+	VBOX_WATCHDOG_GLOBAL_PERFCOL VBOX_BUILD_TARGET=\"$(KBUILD_TARGET).$(KBUILD_TARGET_ARCH)\"
  VBoxBalloonCtrl_DEFS.win   = _WIN32_WINNT=0x0500
  VBoxBalloonCtrl_SOURCES    = \
Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp	(revision 39986)
@@ -0,0 +1,190 @@
+
+/* $Id$ */
+/** @file
+ * VBoxModAPIMonitor - API monitor module for detecting host isolation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#ifndef VBOX_ONLY_DOCS
+# include <VBox/com/com.h>
+# include <VBox/com/string.h>
+# include <VBox/com/Guid.h>
+# include <VBox/com/array.h>
+# include <VBox/com/ErrorInfo.h>
+# include <VBox/com/errorprint.h>
+
+# include <VBox/com/EventQueue.h>
+# include <VBox/com/listeners.h>
+# include <VBox/com/VirtualBox.h>
+#endif /* !VBOX_ONLY_DOCS */
+
+#include <VBox/err.h>
+#include <VBox/log.h>
+#include <VBox/version.h>
+
+#include <package-generated.h>
+
+#include <iprt/asm.h>
+#include <iprt/buildconfig.h>
+#include <iprt/critsect.h>
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/path.h>
+#include <iprt/process.h>
+#include <iprt/semaphore.h>
+#include <iprt/stream.h>
+#include <iprt/string.h>
+#include <iprt/system.h>
+
+#include <map>
+#include <string>
+#include <signal.h>
+
+#include "VBoxWatchdogInternal.h"
+
+using namespace com;
+
+#define VBOX_MOD_APIMONITOR_NAME "apimonitor"
+
+/**
+ * The module's RTGetOpt-IDs for the command line.
+ */
+enum GETOPTDEF_APIMONITOR
+{
+    GETOPTDEF_APIMONITOR_GROUPS = 1000,
+};
+
+/**
+ * The module's command line arguments.
+ */
+static const RTGETOPTDEF g_aAPIMonitorOpts[] = {
+    { "--apimonitor-groups",         GETOPTDEF_APIMONITOR_GROUPS,         RTGETOPT_REQ_STRING }
+};
+
+/* Callbacks. */
+static DECLCALLBACK(int) VBoxModAPIMonitorPreInit(void)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorOption(int argc, char **argv)
+{
+    if (!argc) /* Take a shortcut. */
+        return -1;
+
+    AssertPtrReturn(argv, VERR_INVALID_PARAMETER);
+
+    RTGETOPTSTATE GetState;
+    int rc = RTGetOptInit(&GetState, argc, argv,
+                          g_aAPIMonitorOpts, RT_ELEMENTS(g_aAPIMonitorOpts),
+                          0 /* First */, 0 /*fFlags*/);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = 0; /* Set default parsing result to valid. */
+
+    int c;
+    RTGETOPTUNION ValueUnion;
+    while ((c = RTGetOpt(&GetState, &ValueUnion)))
+    {
+        switch (c)
+        {
+            case GETOPTDEF_APIMONITOR_GROUPS:
+                break;
+
+            default:
+                rc = -1; /* We don't handle this option, skip. */
+                break;
+        }
+    }
+
+    return rc;
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorInit(void)
+{
+    return VINF_SUCCESS; /* Nothing to do here right now. */
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorMain(void)
+{
+    return VINF_SUCCESS; /* Nothing to do here right now. */
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorStop(void)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(void) VBoxModAPIMonitorTerm(void)
+{
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorOnMachineRegistered(const Bstr &strUuid)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorOnMachineUnregistered(const Bstr &strUuid)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorOnMachineStateChanged(const Bstr &strUuid,
+                                                                MachineState_T enmState)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) VBoxModAPIMonitorOnServiceStateChanged(bool fAvailable)
+{
+    return VINF_SUCCESS;
+}
+
+/**
+ * The 'apimonitor' module description.
+ */
+VBOXMODULE g_ModAPIMonitor =
+{
+    /* pszName. */
+    VBOX_MOD_APIMONITOR_NAME,
+    /* pszDescription. */
+    "API monitor for host isolation detection",
+    /* pszDepends. */
+    NULL,
+    /* uPriority. */
+    0 /* Not used */,
+    /* pszUsage. */
+    " [--apimonitor-groups <string>]\n"
+    ,
+    /* pszOptions. */
+    "--apimonitor-groups    Sets the VM groups for monitoring (none).\n",
+    /* methods. */
+    VBoxModAPIMonitorPreInit,
+    VBoxModAPIMonitorOption,
+    VBoxModAPIMonitorInit,
+    VBoxModAPIMonitorMain,
+    VBoxModAPIMonitorStop,
+    VBoxModAPIMonitorTerm,
+    /* callbacks. */
+    VBoxModAPIMonitorOnMachineRegistered,
+    VBoxModAPIMonitorOnMachineUnregistered,
+    VBoxModAPIMonitorOnMachineStateChanged,
+    VBoxModAPIMonitorOnServiceStateChanged
+};
+
Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp	(revision 39986)
@@ -199,4 +199,30 @@
 
 /**
+ * Indicates whether ballooning on the specified machine state is
+ * possible -- this only is true if the machine is up and running.
+ *
+ * @return  bool            Flag indicating whether the VM is running or not.
+ * @param   enmState        The VM's machine state to judge whether it's running or not.
+ */
+static bool balloonIsPossible(MachineState_T enmState)
+{
+    switch (enmState)
+    {
+        case MachineState_Running:
+#if 0
+        /* Not required for ballooning. */
+        case MachineState_Teleporting:
+        case MachineState_LiveSnapshotting:
+        case MachineState_Paused:
+        case MachineState_TeleportingPausedVM:
+#endif
+            return true;
+        default:
+            break;
+    }
+    return false;
+}
+
+/**
  * Determines whether ballooning is required to the specified machine.
  *
@@ -207,6 +233,4 @@
 {
     AssertPtrReturn(pMachine, false);
-
-    /** @todo Add grouping! */
 
     /* Only do ballooning if we have a maximum balloon size set. */
@@ -217,5 +241,54 @@
                               ? 0 : balloonGetMaxSize(pMachine->machine);
 
+    /** @todo Add grouping as a criteria! */
+
     return pData->ulBalloonSizeMax ? true : false;
+}
+
+int balloonMachineSetup(const Bstr& strUuid)
+{
+    int vrc = VINF_SUCCESS;
+
+    do
+    {
+        PVBOXWATCHDOG_MACHINE pMachine = getMachine(strUuid);
+        AssertPtrBreakStmt(pMachine, vrc=VERR_INVALID_PARAMETER);
+
+        ComPtr<IMachine> m = pMachine->machine;
+
+        /*
+         * Setup metrics required for ballooning.
+         */
+        com::SafeArray<BSTR> metricNames(1);
+        com::SafeIfaceArray<IUnknown> metricObjects(1);
+        com::SafeIfaceArray<IPerformanceMetric> metricAffected;
+
+        Bstr strMetricNames(L"Guest/RAM/Usage");
+        strMetricNames.cloneTo(&metricNames[0]);
+
+        HRESULT rc = m.queryInterfaceTo(&metricObjects[0]);
+
+#ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
+        CHECK_ERROR_BREAK(g_pPerfCollector, SetupMetrics(ComSafeArrayAsInParam(metricNames),
+                                                         ComSafeArrayAsInParam(metricObjects),
+                                                         5 /* 5 seconds */,
+                                                         1 /* One sample is enough */,
+                                                         ComSafeArrayAsOutParam(metricAffected)));
+#else
+        ComPtr<IPerformanceCollector> coll = pMachine->collector;
+
+        CHECK_ERROR_BREAK(g_pVirtualBox, COMGETTER(PerformanceCollector)(coll.asOutParam()));
+        CHECK_ERROR_BREAK(coll, SetupMetrics(ComSafeArrayAsInParam(metricNames),
+                                             ComSafeArrayAsInParam(metricObjects),
+                                             5 /* 5 seconds */,
+                                             1 /* One sample is enough */,
+                                             ComSafeArrayAsOutParam(metricAffected)));
+#endif
+        if (FAILED(rc))
+            vrc = VERR_COM_IPRT_ERROR; /* @todo Find better rc! */
+
+    } while (0);
+
+    return vrc;
 }
 
@@ -228,5 +301,5 @@
  * @param   pMachine                Pointer to the machine's internal structure.
  */
-static int balloonUpdate(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine)
+static int balloonMachineUpdate(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine)
 {
     AssertPtrReturn(pMachine, VERR_INVALID_POINTER);
@@ -304,9 +377,8 @@
 }
 
+/* Callbacks. */
 static DECLCALLBACK(int) VBoxModBallooningPreInit(void)
 {
-    int rc = -1;
-    /* Not yet implemented. */
-    return rc;
+    return VINF_SUCCESS;
 }
 
@@ -373,7 +445,5 @@
 static DECLCALLBACK(int) VBoxModBallooningInit(void)
 {
-    int rc = -1;
-    /* Not yet implemented. */
-    return rc;
+    return VINF_SUCCESS; /* Nothing to do here right now. */
 }
 
@@ -385,49 +455,61 @@
         return VINF_SUCCESS;
     uLast = uNow;
-#if 0
-    int rc = RTCritSectEnter(&g_MapCritSect);
+
+    int rc = VINF_SUCCESS;
+
+    /** @todo Provide API for enumerating/working w/ machines inside a module! */
+    mapVMIter it = g_mapVM.begin();
+    while (it != g_mapVM.end())
+    {
+        MachineState_T state = getMachineState(&it->second);
+
+        /* Our actual ballooning criteria. */
+        if (   balloonIsPossible(state)
+            && balloonIsRequired(&it->second))
+        {
+            rc = balloonMachineUpdate(it->first /* UUID */,
+                                      &it->second /* Machine */);
+            AssertRC(rc);
+        }
+        if (RT_FAILURE(rc))
+            break;
+
+        it++;
+    }
+
+    return rc;
+}
+
+static DECLCALLBACK(int) VBoxModBallooningStop(void)
+{
+    return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(void) VBoxModBallooningTerm(void)
+{
+}
+
+static DECLCALLBACK(int) VBoxModBallooningOnMachineRegistered(const Bstr &strUuid)
+{
+    PVBOXWATCHDOG_MACHINE pMachine = getMachine(strUuid);
+    AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER);
+
+    PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD pData;
+    int rc = payloadAlloc(pMachine, VBOX_MOD_BALLOONING_NAME,
+                          sizeof(VBOXWATCHDOG_BALLOONCTRL_PAYLOAD), (void**)&pData);
     if (RT_SUCCESS(rc))
-    {
-        mapVMIter it = g_mapVM.begin();
-        while (it != g_mapVM.end())
-        {
-            MachineState_T machineState;
-            HRESULT hrc = it->second.machine->COMGETTER(State)(&machineState);
-            if (SUCCEEDED(hrc))
-            {
-                rc = machineUpdate(it->first /* UUID */, machineState);
-                if (RT_FAILURE(rc))
-                    break;
-            }
-            it++;
-        }
-
-        int rc2 = RTCritSectLeave(&g_MapCritSect);
-        if (RT_SUCCESS(rc))
-            rc = rc2;
-    }
+        rc = balloonMachineUpdate(strUuid, pMachine);
 
     return rc;
-#endif
-    return 0;
-}
-
-static DECLCALLBACK(int) VBoxModBallooningStop(void)
-{
-    return 0;
-}
-
-static DECLCALLBACK(void) VBoxModBallooningTerm(void)
-{
-}
-
-static DECLCALLBACK(int) VBoxModBallooningOnMachineRegistered(const Bstr &strUuid)
-{
-    return 0;
 }
 
 static DECLCALLBACK(int) VBoxModBallooningOnMachineUnregistered(const Bstr &strUuid)
 {
-    return 0;
+    PVBOXWATCHDOG_MACHINE pMachine = getMachine(strUuid);
+    AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER);
+
+    payloadFree(pMachine, VBOX_MOD_BALLOONING_NAME);
+
+    return VINF_SUCCESS;
 }
 
@@ -435,10 +517,13 @@
                                                                 MachineState_T enmState)
 {
-    return 0;
+    PVBOXWATCHDOG_MACHINE pMachine = getMachine(strUuid);
+    AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER);
+
+    return balloonMachineUpdate(strUuid, pMachine);
 }
 
 static DECLCALLBACK(int) VBoxModBallooningOnServiceStateChanged(bool fAvailable)
 {
-    return 0;
+    return VINF_SUCCESS;
 }
 
@@ -457,10 +542,10 @@
     0 /* Not used */,
     /* pszUsage. */
-    "              [--balloon-dec <MB>] [--balloon-inc <MB>]\n"
-    "              [--balloon-interval <ms>] [--balloon-lower-limit <MB>]\n"
-    "              [--balloon-max <MB>]",
+    " [--balloon-dec <MB>] [--balloon-groups <string>] [--balloon-inc <MB>]\n"
+    " [--balloon-interval <ms>] [--balloon-lower-limit <MB>]\n"
+    " [--balloon-max <MB>]\n",
     /* pszOptions. */
     "--balloon-dec          Sets the ballooning decrement in MB (128 MB).\n"
-    "--balloon-groups       Sets the VM groups for ballooning (All).\n"
+    "--balloon-groups       Sets the VM groups for ballooning (all).\n"
     "--balloon-inc          Sets the ballooning increment in MB (256 MB).\n"
     "--balloon-interval     Sets the check interval in ms (30 seconds).\n"
Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp	(revision 39986)
@@ -66,7 +66,11 @@
 
 /** External globals. */
-bool                 g_fVerbose    = false;
-ComPtr<IVirtualBox>  g_pVirtualBox = NULL;
-ComPtr<ISession>     g_pSession    = NULL;
+bool                                g_fVerbose    = false;
+ComPtr<IVirtualBox>                 g_pVirtualBox = NULL;
+ComPtr<ISession>                    g_pSession    = NULL;
+mapVM                               g_mapVM;
+# ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
+ComPtr<IPerformanceCollector>       g_pPerfCollector = NULL;
+# endif
 
 /** The critical section for the machines map. */
@@ -99,5 +103,6 @@
 } g_aModules[] =
 {
-    { &g_ModBallooning, false /* Pre-inited */, true /* Enabled */ }
+    { &g_ModBallooning, false /* Pre-inited */, true /* Enabled */ },
+    { &g_ModAPIMonitor, false /* Pre-inited */, true /* Enabled */ }
 };
 
@@ -119,5 +124,5 @@
 };
 
-static unsigned long g_ulTimeoutMS = 30 * 1000; /* Default is 30 seconds timeout. */
+static unsigned long g_ulTimeoutMS = 500; /* Default is 500ms timeout. */
 static unsigned long g_ulMemoryBalloonIncrementMB = 256;
 static unsigned long g_ulMemoryBalloonDecrementMB = 128;
@@ -132,18 +137,12 @@
 static ComPtr<IEventSource> g_pEventSourceClient = NULL;
 static ComPtr<IEventListener> g_pVBoxEventListener = NULL;
-# ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
-static ComPtr<IPerformanceCollector> g_pPerfCollector = NULL;
-# endif
 static EventQueue *g_pEventQ = NULL;
-static mapVM g_mapVM;
 
 /* Prototypes. */
-static bool machineIsRunning(MachineState_T enmState);
-static bool machineHandled(const Bstr &strUuid);
 static int machineAdd(const Bstr &strUuid);
 static int machineRemove(const Bstr &strUuid);
 //static int machineUpdate(const Bstr &strUuid, MachineState_T enmState);
 static HRESULT watchdogSetup();
-static void watchdogTeardown();
+static void watchdogShutdown();
 
 #ifdef RT_OS_WINDOWS
@@ -195,22 +194,7 @@
                         if (RT_SUCCESS(rc))
                         {
-                            for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
-                                if (g_aModules[j].fEnabled)
-                                {
-                                    int rc2 = fRegistered
-                                            ? g_aModules[j].pDesc->pfnOnMachineRegistered(uuid)
-                                            : g_aModules[j].pDesc->pfnOnMachineUnregistered(uuid);
-                                    if (RT_FAILURE(rc2))
-                                        serviceLog("Module '%s' reported an error: %Rrc\n",
-                                                   g_aModules[j].pDesc->pszName, rc);
-                                    /* Keep going. */
-                                }
-
-                            #if 0
-                            if (fRegistered && machineHandled(uuid))
-                                rc = machineAdd(uuid);
-                            else if (!fRegistered)
-                                 rc = machineRemove(uuid);
-                            #endif
+                            rc = fRegistered
+                               ? machineAdd(uuid)
+                               : machineRemove(uuid);
                             int rc2 = RTCritSectLeave(&g_csMachines);
                             if (RT_SUCCESS(rc))
@@ -250,5 +234,4 @@
                                 }
 
-                            //rc = machineUpdate(uuid, machineState);
                             int rc2 = RTCritSectLeave(&g_csMachines);
                             if (RT_SUCCESS(rc))
@@ -282,5 +265,5 @@
                     {
                         serviceLog("VBoxSVC became unavailable\n");
-                        watchdogTeardown();
+                        watchdogShutdown();
                     }
                     else
@@ -352,65 +335,4 @@
 
 /**
- * Indicates whether a VM is up and running (regardless of its running
- * state, could be paused as well).
- *
- * @return  bool            Flag indicating whether the VM is running or not.
- * @param   enmState        The VM's machine state to judge whether it's running or not.
- */
-static bool machineIsRunning(MachineState_T enmState)
-{
-    switch (enmState)
-    {
-        case MachineState_Running:
-#if 0
-        /* Not required for ballooning. */
-        case MachineState_Teleporting:
-        case MachineState_LiveSnapshotting:
-        case MachineState_Paused:
-        case MachineState_TeleportingPausedVM:
-#endif
-            return true;
-        default:
-            break;
-    }
-    return false;
-}
-
-/**
- * Determines whether the specified machine needs to be handled
- * by this service.
- *
- * @return  bool                    True if the machine needs handling, false if not.
- * @param   strUuid                 UUID of the specified machine.
- */
-static bool machineHandled(const Bstr &strUuid)
-{
-    bool fHandled = false;
-
-    do
-    {
-        HRESULT rc;
-
-        ComPtr <IMachine> machine;
-        CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine(strUuid.raw(), machine.asOutParam()));
-
-        MachineState_T machineState;
-        CHECK_ERROR_BREAK(machine, COMGETTER(State)(&machineState));
-
-    #if 0
-        if (   balloonGetMaxSize(machine)
-            && machineIsRunning(machineState))
-        {
-            serviceLogVerbose(("Handling machine \"%ls\"\n", strUuid.raw()));
-            fHandled = true;
-        }
-    #endif
-    }
-    while (0);
-
-    return fHandled;
-}
-
-/**
  * Adds a specified machine to the list (map) of handled machines.
  * Does not do locking -- needs to be done by caller!
@@ -431,46 +353,6 @@
         CHECK_ERROR_BREAK(machine, COMGETTER(State)(&machineState));
 
-    #if 0
-        if (   !balloonGetMaxSize(machine)
-            || !machineIsRunning(machineState))
-        {
-            /* This machine does not need to be added, just skip it! */
-            break;
-        }
-    #endif
-
         VBOXWATCHDOG_MACHINE m;
         m.machine = machine;
-
-////// TODO: Put this in module!
-
-        /*
-         * Setup metrics.
-         */
-        com::SafeArray<BSTR> metricNames(1);
-        com::SafeIfaceArray<IUnknown> metricObjects(1);
-        com::SafeIfaceArray<IPerformanceMetric> metricAffected;
-
-        Bstr strMetricNames(L"Guest/RAM/Usage");
-        strMetricNames.cloneTo(&metricNames[0]);
-
-        m.machine.queryInterfaceTo(&metricObjects[0]);
-
-#ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
-        CHECK_ERROR_BREAK(g_pPerfCollector, SetupMetrics(ComSafeArrayAsInParam(metricNames),
-                                                         ComSafeArrayAsInParam(metricObjects),
-                                                         5 /* 5 seconds */,
-                                                         1 /* One sample is enough */,
-                                                         ComSafeArrayAsOutParam(metricAffected)));
-#else
-        CHECK_ERROR_BREAK(g_pVirtualBox, COMGETTER(PerformanceCollector)(m.collector.asOutParam()));
-        CHECK_ERROR_BREAK(m.collector, SetupMetrics(ComSafeArrayAsInParam(metricNames),
-                                                    ComSafeArrayAsInParam(metricObjects),
-                                                    5 /* 5 seconds */,
-                                                    1 /* One sample is enough */,
-                                                    ComSafeArrayAsOutParam(metricAffected)));
-#endif
-
-///////////////// TODO END
 
         /*
@@ -479,15 +361,18 @@
         mapVMIter it = g_mapVM.find(strUuid);
         Assert(it == g_mapVM.end());
-
-        /* Register all module payloads. */
+        g_mapVM.insert(std::make_pair(strUuid, m));
+
+        serviceLogVerbose(("Added machine \"%ls\"\n", strUuid.raw()));
+
+        /* Let all modules know. */
         for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
-        {
-            if (g_aModules[j].pDesc->pszOptions)
-                RTPrintf("%s", g_aModules[j].pDesc->pszOptions);
-        }
-
-        g_mapVM.insert(std::make_pair(strUuid, m));
-
-        serviceLogVerbose(("Added machine \"%ls\"\n", strUuid.raw()));
+            if (g_aModules[j].fEnabled)
+            {
+                int rc2 = g_aModules[j].pDesc->pfnOnMachineRegistered(strUuid);
+                if (RT_FAILURE(rc2))
+                    serviceLog("OnMachineRegistered: Module '%s' reported an error: %Rrc\n",
+                               g_aModules[j].pDesc->pszName, rc);
+                /* Keep going. */
+            }
 
     } while (0);
@@ -496,4 +381,39 @@
 
     return SUCCEEDED(rc) ? VINF_SUCCESS : VERR_COM_IPRT_ERROR; /* @todo Find a better error! */
+}
+
+static int machineDestroy(const Bstr &strUuid)
+{
+    AssertReturn(!strUuid.isEmpty(), VERR_INVALID_PARAMETER);
+    int rc = VINF_SUCCESS;
+
+    /* Let all modules know. */
+    for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
+        if (g_aModules[j].fEnabled)
+        {
+            int rc2 = g_aModules[j].pDesc->pfnOnMachineUnregistered(strUuid);
+            if (RT_FAILURE(rc2))
+                serviceLog("OnMachineUnregistered: Module '%s' reported an error: %Rrc\n",
+                           g_aModules[j].pDesc->pszName, rc);
+            /* Keep going. */
+        }
+
+    mapVMIter it = g_mapVM.find(strUuid);
+    Assert(it != g_mapVM.end());
+
+#ifndef VBOX_WATCHDOG_GLOBAL_PERFCOL
+    it->second.collector.setNull();
+#endif
+    it->second.machine.setNull();
+
+    /* Must log before erasing the iterator because of the UUID ref! */
+    serviceLogVerbose(("Removing machine \"%ls\"\n", strUuid.raw()));
+
+    /*
+     * Remove machine from map.
+     */
+    g_mapVM.erase(it);
+
+    return rc;
 }
 
@@ -507,4 +427,5 @@
 static int machineRemove(const Bstr &strUuid)
 {
+    AssertReturn(!strUuid.isEmpty(), VERR_INVALID_PARAMETER);
     int rc = VINF_SUCCESS;
 
@@ -512,11 +433,12 @@
     if (it != g_mapVM.end())
     {
-        /* Must log before erasing the iterator because of the UUID ref! */
-        serviceLogVerbose(("Removing machine \"%ls\"\n", strUuid.raw()));
-
-        /*
-         * Remove machine from map.
-         */
-        g_mapVM.erase(it);
+        int rc2 = machineDestroy(strUuid);
+        if (RT_FAILURE(rc))
+        {
+            serviceLog(("Machine \"%ls\" failed to destroy, rc=%Rc\n"));
+            if (RT_SUCCESS(rc))
+                rc = rc2;
+        }
+
     }
     else
@@ -529,66 +451,4 @@
 }
 
-#if 0
-/**
- * Updates a specified machine according to its current machine state.
- * That currently also could mean that a machine gets removed if it doesn't
- * fit in our criteria anymore or a machine gets added if we need to handle
- * it now (and didn't before).
- * Does not do locking -- needs to be done by caller!
- *
- * @return  IPRT status code.
- * @param   strUuid                 UUID of the specified machine.
- * @param   enmState                The machine's current state.
- */
-static int machineUpdate(const Bstr &strUuid, MachineState_T enmState)
-{
-    int rc = VINF_SUCCESS;
-
-    mapVMIter it = g_mapVM.find(strUuid);
-    if (it == g_mapVM.end())
-    {
-        if (machineHandled(strUuid))
-        {
-            rc  = machineAdd(strUuid);
-            if (RT_SUCCESS(rc))
-                it = g_mapVM.find(strUuid);
-        }
-        else
-        {
-            serviceLogVerbose(("Machine \"%ls\" (state: %u) does not need to be updated\n",
-                               strUuid.raw(), enmState));
-        }
-    }
-
-    if (it != g_mapVM.end())
-    {
-        /*
-         * Ballooning stuff - start.
-         */
-#if 0
-        /* Our actual ballooning criteria. */
-        if (   !balloonIsRequired(&it->second)
-            || !machineIsRunning(enmState))
-        {
-            /* Current machine is not suited for ballooning anymore -
-             * remove it from our map. */
-            rc = machineRemove(strUuid);
-        }
-        else
-        {
-            rc = balloonUpdate(strUuid, &it->second);
-            AssertRC(rc);
-        }
-#endif
-    }
-
-    /*
-     * Ballooning stuff - end.
-     */
-
-    return rc;
-}
-#endif
-
 static void vmListDestroy()
 {
@@ -601,9 +461,6 @@
         while (it != g_mapVM.end())
         {
-#ifndef VBOX_WATCHDOG_GLOBAL_PERFCOL
-            it->second.collector.setNull();
-#endif
-            it->second.machine.setNull();
-            it++;
+            machineDestroy(it->first);
+            it = g_mapVM.begin();
         }
 
@@ -763,6 +620,4 @@
         g_pEventQ = com::EventQueue::getMainEventQueue();
 
-        RTCritSectInit(&g_csMachines);
-
         /*
          * Install signal handlers.
@@ -806,20 +661,23 @@
              * Do the actual work.
              */
-            /*
-            vrc = balloonCtrlCheck();
-            if (RT_FAILURE(vrc))
+
+            int rc = RTCritSectEnter(&g_csMachines);
+            if (RT_SUCCESS(rc))
             {
-                serviceLog("Error while doing ballooning control; rc=%Rrc\n", vrc);
-                break;
-            }*/
-            for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
-                if (g_aModules[j].fEnabled)
-                {
-                    int rc2 = g_aModules[j].pDesc->pfnMain();
-                    if (RT_FAILURE(rc2))
-                        serviceLog("Module '%s' reported an error: %Rrc\n",
-                                   g_aModules[j].pDesc->pszName, rc);
-                    /* Keep going. */
-                }
+                for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
+                    if (g_aModules[j].fEnabled)
+                    {
+                        int rc2 = g_aModules[j].pDesc->pfnMain();
+                        if (RT_FAILURE(rc2))
+                            serviceLog("Module '%s' reported an error: %Rrc\n",
+                                       g_aModules[j].pDesc->pszName, rc);
+                        /* Keep going. */
+                    }
+
+                int rc2 = RTCritSectLeave(&g_csMachines);
+                if (RT_SUCCESS(rc))
+                    rc = rc2;
+                AssertRC(rc);
+            }
 
             /*
@@ -854,6 +712,4 @@
         vrc = watchdogShutdownModules();
         AssertRC(vrc);
-
-        RTCritSectDelete(&g_csMachines);
 
         if (RT_FAILURE(vrc))
@@ -964,6 +820,16 @@
     displayHeader();
 
-    RTStrmPrintf(g_pStdErr, "Usage: %s [options]\n\nSupported options (default values in brackets):\n",
-                 pszImage);
+    RTStrmPrintf(g_pStdErr,
+                 "Usage:\n"
+                 " %s [-v|--verbose] [-h|-?|--help] [-P|--pidfile]\n"
+                 " [-F|--logfile=<file>] [-R|--logrotate=<num>] [-S|--logsize=<bytes>]\n"
+                 " [-I|--loginterval=<seconds>]\n", pszImage);
+    for (unsigned j = 0; j < RT_ELEMENTS(g_aModules); j++)
+        if (g_aModules[j].pDesc->pszUsage)
+            RTStrmPrintf(g_pStdErr, "%s\n", g_aModules[j].pDesc->pszUsage);
+
+    RTStrmPrintf(g_pStdErr, "\n"
+                 "Options:\n");
+
     for (unsigned i = 0;
          i < RT_ELEMENTS(g_aOptions);
@@ -1032,5 +898,5 @@
 static HRESULT watchdogSetup()
 {
-    serviceLogVerbose(("Creating local objects ...\n"));
+    serviceLogVerbose(("Setting up ...\n"));
 
     HRESULT rc = g_pVirtualBoxClient->COMGETTER(VirtualBox)(g_pVirtualBox.asOutParam());
@@ -1055,8 +921,15 @@
 #endif
 
+        int vrc = RTCritSectInit(&g_csMachines);
+        if (RT_FAILURE(vrc))
+        {
+            rc = VBOX_E_IPRT_ERROR;
+            break;
+        }
+
         /*
          * Build up initial VM list.
          */
-        int vrc = vmListBuild();
+        vrc = vmListBuild();
         if (RT_FAILURE(vrc))
         {
@@ -1070,9 +943,12 @@
 }
 
-static void watchdogTeardown()
-{
-    serviceLogVerbose(("Deleting local objects ...\n"));
+static void watchdogShutdown()
+{
+    serviceLogVerbose(("Shutting down ...\n"));
 
     vmListDestroy();
+
+    int rc = RTCritSectDelete(&g_csMachines);
+    AssertRC(rc);
 
 #ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
@@ -1276,5 +1152,5 @@
     EventQueue::getMainEventQueue()->processEventQueue(0);
 
-    watchdogTeardown();
+    watchdogShutdown();
 
     g_pVirtualBoxClient.setNull();
Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogInternal.h
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogInternal.h	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogInternal.h	(revision 39986)
@@ -21,4 +21,5 @@
 #ifndef VBOX_ONLY_DOCS
 #include <VBox/com/com.h>
+#include <VBox/com/assert.h>
 #include <VBox/com/string.h>
 #include <VBox/com/VirtualBox.h>
@@ -55,7 +56,7 @@
     /* Pointer to allocated payload. Can be NULL if
      * a module doesn't have an own payload. */
-    void *pvPayload;
+    void *pvData;
     /* Size of payload (in bytes). */
-    size_t cbPayload;
+    size_t cbData;
     /** @todo Add mutex for locking + getPayloadLocked(). */
 } VBOXWATCHDOG_MODULE_PAYLOAD, *PVBOXWATCHDOG_MODULE_PAYLOAD;
@@ -195,8 +196,13 @@
 
 extern bool g_fVerbose;
-extern ComPtr<IVirtualBox> g_pVirtualBox;
-extern ComPtr<ISession> g_pSession;
+extern ComPtr<IVirtualBox>              g_pVirtualBox;
+extern ComPtr<ISession>                 g_pSession;
+extern mapVM                            g_mapVM;
+# ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
+extern ComPtr<IPerformanceCollector>    g_pPerfCollector;
+# endif
 
 extern VBOXMODULE g_ModBallooning;
+extern VBOXMODULE g_ModAPIMonitor;
 
 extern void serviceLog(const char *pszFormat, ...);
@@ -205,4 +211,8 @@
 extern int getMetric(PVBOXWATCHDOG_MACHINE pMachine, const Bstr& strName, LONG *pulData);
 void* getPayload(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);
+int payloadAlloc(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule, size_t cbSize, void **ppszPayload);
+void payloadFree(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);
+PVBOXWATCHDOG_MACHINE getMachine(const Bstr& strUuid);
+MachineState_T getMachineState(const PVBOXWATCHDOG_MACHINE pMachine);
 
 RT_C_DECLS_END
Index: trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogUtils.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogUtils.cpp	(revision 39943)
+++ trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogUtils.cpp	(revision 39986)
@@ -54,5 +54,5 @@
     /* Query current memory free. */
     strName.cloneTo(&metricNames[0]);
-#ifdef VBOX_BALLOONCTRL_GLOBAL_PERFCOL
+#ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
     Assert(!g_pPerfCollector.isNull());
     HRESULT hrc = g_pPerfCollector->QueryMetricsData(
@@ -112,6 +112,63 @@
     if (it == pMachine->payload.end())
         return NULL;
-    Assert(it->second.cbPayload);
-    return it->second.pvPayload;
+    Assert(it->second.cbData);
+    return it->second.pvData;
 }
 
+int payloadAlloc(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule,
+                 size_t cbSize, void **ppszPayload)
+{
+    AssertPtrReturn(pMachine, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
+    AssertReturn(cbSize, VERR_INVALID_PARAMETER);
+
+    void *pvData = RTMemAlloc(cbSize);
+    AssertPtrReturn(pvData, VERR_NO_MEMORY);
+
+    mapPayloadIter it = pMachine->payload.find(pszModule);
+    AssertReturn(it == pMachine->payload.end(), VERR_INVALID_PARAMETER);
+
+    VBOXWATCHDOG_MODULE_PAYLOAD p;
+    p.pvData = pvData;
+    p.cbData = cbSize;
+
+    if (ppszPayload)
+        *ppszPayload = p.pvData;
+
+    pMachine->payload.insert(std::make_pair(pszModule, p));
+
+    return VINF_SUCCESS;
+}
+
+void payloadFree(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule)
+{
+    AssertPtrReturnVoid(pMachine);
+    AssertPtrReturnVoid(pszModule);
+
+    mapPayloadIter it = pMachine->payload.find(pszModule);
+    if (it != pMachine->payload.end())
+    {
+        RTMemFree(it->second.pvData);
+        pMachine->payload.erase(it);
+    }
+}
+
+PVBOXWATCHDOG_MACHINE getMachine(const Bstr& strUuid)
+{
+    mapVMIter it = g_mapVM.find(strUuid);
+    if (it != g_mapVM.end())
+        return &it->second;
+    return NULL;
+}
+
+MachineState_T getMachineState(const PVBOXWATCHDOG_MACHINE pMachine)
+{
+    AssertPtrReturn(pMachine, MachineState_Null);
+    MachineState_T machineState;
+    Assert(!pMachine->machine.isNull());
+    HRESULT rc = pMachine->machine->COMGETTER(State)(&machineState);
+    if (SUCCEEDED(rc))
+        return machineState;
+    return MachineState_Null;
+}
+
