Index: trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMisc.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMisc.cpp	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibMisc.cpp	(revision 26326)
@@ -158,15 +158,8 @@
 VBGLR3DECL(int) VbglR3CtlFilterMask(uint32_t fOr, uint32_t fNot)
 {
-#if defined(RT_OS_WINDOWS)
-    /** @todo Not yet implemented. */
-    return VERR_NOT_SUPPORTED;
-
-#else
-
     VBoxGuestFilterMaskInfo Info;
     Info.u32OrMask = fOr;
     Info.u32NotMask = fNot;
     return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CTL_FILTER_MASK, &Info, sizeof(Info));
-#endif
 }
 
@@ -196,4 +189,47 @@
 #endif
     return rc;
+}
+
+/**
+ * Query the current statistics update interval
+ *
+ * @returns IPRT status code
+ * @param   pu32Interval    Update interval in ms (out)
+ */
+VBGLR3DECL(int) VbglR3StatQueryInterval(uint32_t *pu32Interval)
+{
+    VMMDevGetStatisticsChangeRequest Req;
+
+    vmmdevInitRequest(&Req.header, VMMDevReq_GetStatisticsChangeRequest);
+    Req.eventAck = VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST;
+    int rc = vbglR3GRPerform(&Req.header);
+    if (RT_SUCCESS(rc))
+        *pu32Interval = Req.u32StatInterval * 1000;
+    return rc;
+}
+
+
+/**
+ * Report guest statistics
+ *
+ * @returns IPRT status code
+ * @param   pReq        Request packet with statistics
+ */
+VBGLR3DECL(int) VbglR3StatReport(VMMDevReportGuestStats *pReq)
+{
+    vmmdevInitRequest(&pReq->header, VMMDevReq_ReportGuestStats);
+    return vbglR3GRPerform(&pReq->header);
+}
+
+
+/**
+ * Refresh the memory balloon after a change
+ *
+ * @returns IPRT status code
+ * @param   pu32Size    Memory balloon size in MBs (out)
+ */
+VBGLR3DECL(int) VbglR3MemBalloonRefresh(uint32_t *pu32Size)
+{
+    return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK, pu32Size, sizeof(*pu32Size));
 }
 
Index: trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk	(revision 26326)
@@ -34,6 +34,5 @@
 VBoxService_TEMPLATE      = VBOXGUESTR3EXE
 VBoxService_DEFS          = VBOXSERVICE_TIMESYNC
-VBoxService_DEFS.win     += _WIN32_WINNT=0x0501 
-##VBOXSERVICE_MANAGEMENT
+VBoxService_DEFS.win     += _WIN32_WINNT=0x0501 VBOXSERVICE_MANAGEMENT
 VBoxService_DEFS.os2      = VBOX_WITH_HGCM VBOXSERVICE_CLIPBOARD
 ifdef VBOX_WITH_GUEST_PROPS
@@ -67,8 +66,7 @@
 VBoxService_SOURCES.win  += \
 	VBoxService-win.rc \
-	VBoxService-win.cpp
-
-##	VBoxServiceStats.cpp \
-##	VBoxServiceBalloon.cpp
+	VBoxService-win.cpp \
+	VBoxServiceBalloon.cpp \
+	VBoxServiceStats.cpp
 
 VBoxService_SOURCES.os2   = \
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceBalloon.cpp	(revision 26326)
@@ -19,144 +19,168 @@
  * additional information or have any questions.
  */
-#define _WIN32_WINNT 0x0500
-#include <windows.h>
-#include <psapi.h>
-#include "VBoxTray.h"
-#include "VBoxMemBalloon.h"
-#include <VBoxDisplay.h>
-#include <VBox/VMMDev.h>
-#include <VBoxGuestInternal.h>
 #include <iprt/assert.h>
-#include "helpers.h"
-#include <winternl.h>
-
-typedef struct _VBOXMEMBALLOONCONTEXT
-{
-    const VBOXSERVICEENV *pEnv;
-    uint32_t              uMemBalloonSize;
-} VBOXMEMBALLOONCONTEXT;
+#include <iprt/mem.h>
+#include <iprt/thread.h>
+#include <iprt/string.h>
+#include <iprt/semaphore.h>
+#include <iprt/system.h>
+#include <iprt/time.h>
+#include <VBox/VBoxGuestLib.h>
+#include "VBoxServiceInternal.h"
+#include "VBoxServiceUtils.h"
 
 
-static VBOXMEMBALLOONCONTEXT gCtx = {0};
 
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+static uint32_t g_MemBalloonSize = 0;
 
-int VBoxMemBalloonInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
+/** The semaphore we're blocking on. */
+static RTSEMEVENTMULTI  g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
+
+/** @copydoc VBOXSERVICE::pfnPreInit */
+static DECLCALLBACK(int) VBoxServiceBalloonPreInit(void)
 {
-    HANDLE gVBoxDriver = pEnv->hDriver;
-    DWORD  cbReturned;
-
-    Log(("VBoxMemBalloonInit: Init\n"));
-
-    gCtx.pEnv                   = pEnv;
-    gCtx.uMemBalloonSize        = 0;
-
-    /* Check balloon size */
-    DWORD dwMemBalloonSize;
-    if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK, NULL, 0, &dwMemBalloonSize, sizeof(dwMemBalloonSize), &cbReturned, NULL))
-    {
-        Log(("VBoxMemBalloonInit: new balloon size %d MB\n", dwMemBalloonSize));
-        gCtx.uMemBalloonSize = dwMemBalloonSize;
-    }
-    else
-        Log(("VBoxMemBalloonInit: DeviceIoControl (balloon) failed with %d\n", GetLastError()));
-
-    *pfStartThread = true;
-    *ppInstance = &gCtx;
     return VINF_SUCCESS;
 }
 
 
-void VBoxMemBalloonDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
+/** @copydoc VBOXSERVICE::pfnOption */
+static DECLCALLBACK(int) VBoxServiceBalloonOption(const char **ppszShort, int argc, char **argv, int *pi)
 {
-    Log(("VBoxMemBalloonDestroy\n"));
+    return VINF_SUCCESS;
+}
+
+
+/** @copydoc VBOXSERVICE::pfnInit */
+static DECLCALLBACK(int) VBoxServiceBalloonInit(void)
+{
+    VBoxServiceVerbose(3, "VBoxServiceBalloonInit\n");
+
+    int rc = RTSemEventMultiCreate(&g_MemBalloonEvent);
+    AssertRCReturn(rc, rc);
+
+    g_MemBalloonSize = 0;
+
+    /* Check balloon size */
+    rc = VbglR3MemBalloonRefresh(&g_MemBalloonSize);
+    if (RT_SUCCESS(rc))
+        VBoxServiceVerbose(3, "VBoxMemBalloonInit: new balloon size %d MB\n", g_MemBalloonSize);
+    else
+        VBoxServiceVerbose(3, "VBoxMemBalloonInit: VbglR3MemBalloonRefresh failed with %d\n", rc);
+
+    return rc;
+}
+
+
+uint32_t VBoxServiceBalloonQuerySize()
+{
+    return g_MemBalloonSize;
+}
+
+/** @copydoc VBOXSERVICE::pfnWorker */
+DECLCALLBACK(int) VBoxServiceBalloonWorker(bool volatile *pfShutdown)
+{
+    int rc = VINF_SUCCESS;
+
+    /* Start monitoring of the stat event change event. */
+    rc = VbglR3CtlFilterMask(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0);
+    if (RT_FAILURE(rc))
+    {
+        VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %d\n", rc);
+        return rc;
+    }
+
+    /*
+     * Tell the control thread that it can continue
+     * spawning services.
+     */
+    RTThreadUserSignal(RTThreadSelf());
+
+    /*
+     * Now enter the loop retrieving runtime data continuously.
+     */
+    for (;;)
+    {
+        uint32_t fEvents = 0;
+
+        /* Check if an update interval change is pending. */
+        rc = VbglR3WaitEvent(VMMDEV_EVENT_BALLOON_CHANGE_REQUEST, 0 /* no wait */, &fEvents);
+        if (    RT_SUCCESS(rc)
+            &&  (fEvents & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST))
+        {
+            rc = VbglR3MemBalloonRefresh(&g_MemBalloonSize);
+            if (RT_SUCCESS(rc))
+                VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: new balloon size %d MB\n", g_MemBalloonSize);
+            else
+                VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3MemBalloonRefresh failed with %d\n", rc);
+        }
+
+        /*
+         * Block for a while.
+         *
+         * The event semaphore takes care of ignoring interruptions and it
+         * allows us to implement service wakeup later.
+         */
+        if (*pfShutdown)
+            break;
+        int rc2 = RTSemEventMultiWait(g_MemBalloonEvent, 5000);
+        if (*pfShutdown)
+            break;
+        if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
+        {
+            VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
+            rc = rc2;
+            break;
+        }
+    }
+
+    /* Cancel monitoring of the memory balloon change event. */
+    rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_BALLOON_CHANGE_REQUEST);
+    if (RT_FAILURE(rc))
+        VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: VbglR3CtlFilterMask failed with %d\n", rc);
+
+    RTSemEventMultiDestroy(g_MemBalloonEvent);
+    g_MemBalloonEvent = NIL_RTSEMEVENTMULTI;
+
+    VBoxServiceVerbose(3, "VBoxServiceBalloonWorker: finished mem balloon change request thread\n");
+    return 0;
+}
+
+/** @copydoc VBOXSERVICE::pfnTerm */
+static DECLCALLBACK(void) VBoxServiceBalloonTerm(void)
+{
+    VBoxServiceVerbose(3, "VBoxServiceBalloonTerm\n");
     return;
 }
 
-uint32_t VBoxMemBalloonQuerySize()
+
+/** @copydoc VBOXSERVICE::pfnStop */
+static DECLCALLBACK(void) VBoxServiceBalloonStop(void)
 {
-    return gCtx.uMemBalloonSize;
-}
-
-/**
- * Thread function to wait for and process seamless mode change
- * requests
- */
-unsigned __stdcall VBoxMemBalloonThread(void *pInstance)
-{
-    VBOXMEMBALLOONCONTEXT *pCtx = (VBOXMEMBALLOONCONTEXT *)pInstance;
-    HANDLE gVBoxDriver = pCtx->pEnv->hDriver;
-    bool fTerminate = false;
-    VBoxGuestFilterMaskInfo maskInfo;
-    DWORD cbReturned;
-
-    maskInfo.u32OrMask = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;
-    maskInfo.u32NotMask = 0;
-    if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
-    {
-        Log(("VBoxMemBalloonThread: DeviceIOControl(CtlMask - or) succeeded\n"));
-    }
-    else
-    {
-        Log(("VBoxMemBalloonThread: DeviceIOControl(CtlMask) failed, SeamlessChangeThread exited\n"));
-        return 0;
-    }
-
-    do
-    {
-        /* wait for a seamless change event */
-        VBoxGuestWaitEventInfo waitEvent;
-        waitEvent.u32TimeoutIn = 5000;
-        waitEvent.u32EventMaskIn = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;
-        if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL))
-        {
-            Log(("VBoxMemBalloonThread: DeviceIOControl succeded\n"));
-
-            /* are we supposed to stop? */
-            if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0)
-                break;
-
-            Log(("VBoxMemBalloonThread: checking event\n"));
-
-            /* did we get the right event? */
-            if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_BALLOON_CHANGE_REQUEST)
-            {
-                DWORD dwMemBalloonSize;
-                if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_CHECK_BALLOON_MASK, NULL, 0, &dwMemBalloonSize, sizeof(dwMemBalloonSize), &cbReturned, NULL))
-                {
-                    Log(("VBoxMemBalloonThread: new balloon size % MB\n", dwMemBalloonSize));
-                    pCtx->uMemBalloonSize = dwMemBalloonSize;
-                }
-                else
-                    Log(("VBoxMemBalloonThread: DeviceIoControl (balloon) failed with %d\n", GetLastError()));
-            }
-        }
-        else
-        {
-            Log(("VBoxMemBalloonThread: error 0 from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n"));
-
-            /* sleep a bit to not eat too much CPU in case the above call always fails */
-            if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0)
-            {
-                fTerminate = true;
-                break;
-            }
-        }
-    }
-    while (!fTerminate);
-
-    maskInfo.u32OrMask = 0;
-    maskInfo.u32NotMask = VMMDEV_EVENT_BALLOON_CHANGE_REQUEST;
-    if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
-    {
-        Log(("VBoxMemBalloonThread: DeviceIOControl(CtlMask - not) succeeded\n"));
-    }
-    else
-    {
-        Log(("VBoxMemBalloonThread: DeviceIOControl(CtlMask) failed\n"));
-    }
-
-    Log(("VBoxMemBalloonThread: finished mem balloon change request thread\n"));
-    return 0;
+    RTSemEventMultiSignal(g_MemBalloonEvent);
 }
 
 
+/**
+ * The 'memballoon' service description.
+ */
+VBOXSERVICE g_MemBalloon =
+{
+    /* pszName. */
+    "memballoon",
+    /* pszDescription. */
+    "Memory Ballooning",
+    /* pszUsage. */
+    NULL,
+    /* pszOptions. */
+    NULL,
+    /* methods */
+    VBoxServiceBalloonPreInit,
+    VBoxServiceBalloonOption,
+    VBoxServiceBalloonInit,
+    VBoxServiceBalloonWorker,
+    VBoxServiceBalloonStop,
+    VBoxServiceBalloonTerm
+};
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 26326)
@@ -27,5 +27,4 @@
 # include <Windows.h>
 # include <process.h> /* Needed for file version information. */
-# include <Ntsecapi.h> /* Needed for process security information. */
 #endif
 
@@ -153,5 +152,4 @@
 #ifdef RT_OS_WINDOWS
 extern DWORD g_rcWinService;
-extern SERVICE_STATUS_HANDLE g_hWinServiceStatus;
 extern SERVICE_TABLE_ENTRY const g_aServiceTable[];     /** @todo generate on the fly, see comment in main() from the enabled sub services. */
 extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */
@@ -169,4 +167,8 @@
 #endif /* RT_OS_WINDOWS */
 
+#ifdef VBOXSERVICE_MANAGEMENT
+extern uint32_t VBoxServiceBalloonQuerySize();
+#endif
+
 RT_C_DECLS_END
 
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceStats.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceStats.cpp	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceStats.cpp	(revision 26326)
@@ -19,15 +19,18 @@
  * additional information or have any questions.
  */
-#define _WIN32_WINNT 0x0500
 #include <windows.h>
 #include <psapi.h>
-#include "VBoxTray.h"
-#include <VBoxDisplay.h>
-#include <VBox/VMMDev.h>
-#include <VBox/VBoxGuest.h>
-#include <VBoxGuestInternal.h>
+#include <winternl.h>
+
 #include <iprt/assert.h>
-#include "helpers.h"
-#include <winternl.h>
+#include <iprt/mem.h>
+#include <iprt/thread.h>
+#include <iprt/string.h>
+#include <iprt/semaphore.h>
+#include <iprt/system.h>
+#include <iprt/time.h>
+#include <VBox/VBoxGuestLib.h>
+#include "VBoxServiceInternal.h"
+#include "VBoxServiceUtils.h"
 
 typedef struct _VBOXSTATSCONTEXT
@@ -77,21 +80,14 @@
     AssertRCReturn(rc, rc);
 
-    gCtx.pEnv                   = pEnv;
-    gCtx.uStatInterval          = 0;     /* default */
+    gCtx.uStatInterval          = 0;     /* default; update disabled */
     gCtx.ullLastCpuLoad_Idle    = 0;
     gCtx.ullLastCpuLoad_Kernel  = 0;
     gCtx.ullLastCpuLoad_User    = 0;
 
-    VMMDevGetStatisticsChangeRequest req;
-    vmmdevInitRequest(&req.header, VMMDevReq_GetStatisticsChangeRequest);
-    req.eventAck = 0;
-
-    if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(req.header.size), &req, req.header.size, &req, req.header.size, &cbReturned, NULL))
-    {
-        VBoxServiceVerbose(3, "VBoxStatsInit: new statistics interval %d seconds\n", req.u32StatInterval);
-        gCtx.uStatInterval = req.u32StatInterval * 1000;
-    }
+    rc = VbglR3StatQueryInterval(&gCtx.uStatInterval);
+    if (RT_SUCCESS(rc))
+        VBoxServiceVerbose(3, "VBoxStatsInit: new statistics interval %d seconds\n", gCtx.uStatInterval);
     else
-        VBoxServiceVerbose(3, ("VBoxStatsInit: DeviceIoControl failed with %d\n", GetLastError());
+        VBoxServiceVerbose(3, "VBoxStatsInit: DeviceIoControl failed with %d\n", rc);
 
 #ifdef RT_OS_WINDOWS
@@ -139,5 +135,5 @@
 
 
-static void VBoxServiceVMStatsReport(VBOXSTATSCONTEXT *pCtx)
+static void VBoxServiceVMStatsReport()
 {
 #ifdef RT_OS_WINDOWS
@@ -148,5 +144,4 @@
     uint32_t cbStruct;
     DWORD    cbReturned;
-    HANDLE   gVBoxDriver = pCtx->pEnv->hDriver;
 
     Assert(gCtx.pfnGlobalMemoryStatusEx && gCtx.pfnNtQuerySystemInformation);
@@ -154,6 +149,4 @@
         ||  !gCtx.pfnNtQuerySystemInformation)
         return;
-
-    vmmdevInitRequest(&req.header, VMMDevReq_ReportGuestStats);
 
     /* Query and report guest statistics */
@@ -169,5 +162,5 @@
     req.guestStats.u32PageFileSize      = (uint32_t)(memStatus.ullTotalPageFile / systemInfo.dwPageSize) - req.guestStats.u32PhysMemTotal;
     req.guestStats.u32MemoryLoad        = memStatus.dwMemoryLoad;
-    req.guestStats.u32PhysMemBalloon    = VBoxMemBalloonQuerySize() * (_1M/systemInfo.dwPageSize);    /* was in megabytes */
+    req.guestStats.u32PhysMemBalloon    = VBoxServiceBalloonQuerySize() * (_1M/systemInfo.dwPageSize);    /* was in megabytes */
     req.guestStats.u32StatCaps          = VBOX_GUEST_STAT_PHYS_MEM_TOTAL | VBOX_GUEST_STAT_PHYS_MEM_AVAIL | VBOX_GUEST_STAT_PAGE_FILE_SIZE | VBOX_GUEST_STAT_MEMORY_LOAD | VBOX_GUEST_STAT_PHYS_MEM_BALLOON;
 
@@ -189,5 +182,5 @@
         }
         else
-            Log(("GetPerformanceInfo failed with %d\n", GetLastError()));
+            VBoxServiceVerbose(3, "GetPerformanceInfo failed with %d\n", GetLastError());
     }
 
@@ -238,10 +231,11 @@
         req.guestStats.u32CpuId = i;
 
-        if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(req.header.size), &req, req.header.size, &req, req.header.size, &cbReturned, NULL))
-        {
-            Log(("VBoxStatsReportStatistics: new statistics reported successfully!\n"));
-        }
-        else
-            Log(("VBoxStatsReportStatistics: DeviceIoControl (stats report) failed with %d\n", GetLastError()));
+        rc = VbglR3StatReport(&req);
+        if (RT_SUCCESS(rc))
+        {
+            VBoxServiceVerbose(3, "VBoxStatsReportStatistics: new statistics reported successfully!\n");
+        }
+        else
+            VBoxServiceVerbose(3, "VBoxStatsReportStatistics: DeviceIoControl (stats report) failed with %d\n", GetLastError());
     }
 
@@ -256,9 +250,13 @@
 DECLCALLBACK(int) VBoxServiceVMStatsWorker(bool volatile *pfShutdown)
 {
-    VBOXSTATSCONTEXT *pCtx = (VBOXSTATSCONTEXT *)pInstance;
-    HANDLE gVBoxDriver = pCtx->pEnv->hDriver;
-    bool fTerminate = false;
-
     int rc = VINF_SUCCESS;
+
+    /* Start monitoring of the stat event change event. */
+    rc = VbglR3CtlFilterMask(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 0);
+    if (RT_FAILURE(rc))
+    {
+        VBoxServiceVerbose(3, "VBoxServiceVMStatsWorker: VbglR3CtlFilterMask failed with %d\n", rc);
+        return rc;
+    }
 
     /*
@@ -268,11 +266,4 @@
     RTThreadUserSignal(RTThreadSelf());
 
-    rc = VbglR3CtlFilterMask(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 0);
-    if (RT_FAILED(rc))
-    {
-        VBoxServiceVerbose(3, ("VBoxStatsThread: DeviceIOControl(CtlMask) failed, SeamlessChangeThread exited\n");
-        return 0;
-    }
-
     /*
      * Now enter the loop retrieving runtime data continuously.
@@ -281,12 +272,21 @@
     {
         uint32_t fEvents = 0;
-
-        rc = VbglR3WaitEvent(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 1000, &fEvents);
+        uint32_t u32WaitMillies;
+
+        /* Check if an update interval change is pending. */
+        rc = VbglR3WaitEvent(VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST, 0 /* no wait */, &fEvents);
         if (    RT_SUCCESS(rc)
             &&  (fEvents & VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST))
         {
-        }
-
-        VBoxServiceVMStatsReport();
+            VbglR3StatQueryInterval(&gCtx.uStatInterval);
+        }
+
+        if (gCtx.uStatInterval)
+        {
+            VBoxServiceVMStatsReport();
+            u32WaitMillies = gCtx.uStatInterval;
+        }
+        else
+            u32WaitMillies = 3000;
 
         /*
@@ -298,5 +298,5 @@
         if (*pfShutdown)
             break;
-        int rc2 = RTSemEventMultiWait(g_VMStatEvent, g_VMStatsInterval);
+        int rc2 = RTSemEventMultiWait(g_VMStatEvent, u32WaitMillies);
         if (*pfShutdown)
             break;
@@ -309,16 +309,13 @@
     }
 
+    /* Cancel monitoring of the stat event change event. */
     rc = VbglR3CtlFilterMask(0, VMMDEV_EVENT_STATISTICS_INTERVAL_CHANGE_REQUEST);
-    if (RT_FAILED(rc))
-    {
-        VBoxServiceVerbose(3, ("VBoxStatsThread: DeviceIOControl(CtlMask) failed, SeamlessChangeThread exited\n");
-        return 0;
-    }
-
-
-    RTSemEventMultiDestroy(g_VMStatsEvent);
-    g_VMStatsEvent = NIL_RTSEMEVENTMULTI;
-
-    Log(("VBoxStatsThread: finished statistics change request thread\n"));
+    if (RT_FAILURE(rc))
+        VBoxServiceVerbose(3, "VBoxServiceVMStatsWorker: VbglR3CtlFilterMask failed with %d\n", rc);
+
+    RTSemEventMultiDestroy(g_VMStatEvent);
+    g_VMStatEvent = NIL_RTSEMEVENTMULTI;
+
+    VBoxServiceVerbose(3, "VBoxStatsThread: finished statistics change request thread\n");
     return 0;
 }
@@ -336,5 +333,5 @@
 static DECLCALLBACK(void) VBoxServiceVMStatsStop(void)
 {
-    RTSemEventMultiSignal(g_VMStatsEvent);
+    RTSemEventMultiSignal(g_VMStatEvent);
 }
 
Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 26324)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceVMInfo-win.cpp	(revision 26326)
@@ -27,4 +27,5 @@
 #include <wtsapi32.h>       /* For WTS* calls. */
 #include <psapi.h>          /* EnumProcesses. */
+#include <Ntsecapi.h>       /* Needed for process security information. */
 
 #include <iprt/assert.h>
