Index: /trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk	(revision 42526)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk	(revision 42527)
@@ -22,5 +22,8 @@
  VBoxAutostart_TEMPLATE   = VBOXMAINCLIENTEXE
  VBoxAutostart_SOURCES    = \
-	VBoxAutostart.cpp
+	VBoxAutostart.cpp \
+	VBoxAutostartCfg.cpp \
+	VBoxAutostartStart.cpp \
+	VBoxAutostartStop.cpp
 
 include $(FILE_KBUILD_SUB_FOOTER)
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.cpp	(revision 42526)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.cpp	(revision 42527)
@@ -58,38 +58,16 @@
 #include <signal.h>
 
+#include "VBoxAutostart.h"
+
 using namespace com;
 
-/**
- * Tokenizer instance data for the config data.
- */
-typedef struct CFGTOKENIZER
-{
-    /** Config file handle. */
-    PRTSTREAM hStrmConfig;
-    /** String buffer for the current line we are operating in. */
-    char      *pszLine;
-    /** Size of the string buffer. */
-    size_t     cbLine;
-    /** Current position in the line. */
-    char      *pszLineCurr;
-    /** Current line in the config file. */
-    unsigned   iLine;
-} CFGTOKENIZER, *PCFGTOKENIZER;
-
-/**
- * VM list entry.
- */
-typedef struct AUTOSTARTVM
-{
-    /** ID of the VM to start. */
-    Bstr  strId;
-    /** Startup delay of the VM. */
-    ULONG uStartupDelay;
-} AUTOSTARTVM;
-
-static ComPtr<IVirtualBoxClient> g_pVirtualBoxClient = NULL;
-static bool                      g_fVerbose    = false;
-static ComPtr<IVirtualBox>       g_pVirtualBox = NULL;
-static ComPtr<ISession>          g_pSession    = NULL;
+#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
+# define VBOXAUTOSTART_DAEMONIZE
+#endif
+
+ComPtr<IVirtualBoxClient> g_pVirtualBoxClient = NULL;
+bool                      g_fVerbose    = false;
+ComPtr<IVirtualBox>       g_pVirtualBox = NULL;
+ComPtr<ISession>          g_pSession    = NULL;
 
 /** Logging parameters. */
@@ -105,5 +83,5 @@
  */
 static const RTGETOPTDEF g_aOptions[] = {
-#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
+#ifdef VBOXAUTOSTART_DAEMONIZE
     { "--background",           'b',                                       RTGETOPT_REQ_NOTHING },
 #endif
@@ -122,5 +100,5 @@
 
 
-static void serviceLog(const char *pszFormat, ...)
+DECLHIDDEN(void) serviceLog(const char *pszFormat, ...)
 {
     va_list args;
@@ -133,524 +111,4 @@
 
     RTStrFree(psz);
-}
-
-#define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; }
-
-/**
- * Reads the next line from the config stream.
- *
- * @returns VBox status code.
- * @param   pCfgTokenizer    The config tokenizer.
- */
-static int autostartConfigTokenizerReadNextLine(PCFGTOKENIZER pCfgTokenizer)
-{
-    int rc = VINF_SUCCESS;
-
-    do
-    {
-        rc = RTStrmGetLine(pCfgTokenizer->hStrmConfig, pCfgTokenizer->pszLine,
-                           pCfgTokenizer->cbLine);
-        if (rc == VERR_BUFFER_OVERFLOW)
-        {
-            char *pszTmp;
-
-            pCfgTokenizer->cbLine += 128;
-            pszTmp = (char *)RTMemRealloc(pCfgTokenizer->pszLine, pCfgTokenizer->cbLine);
-            if (pszTmp)
-                pCfgTokenizer->pszLine = pszTmp;
-            else
-                rc = VERR_NO_MEMORY;
-        }
-    } while (rc == VERR_BUFFER_OVERFLOW);
-
-    if (RT_SUCCESS(rc))
-    {
-        pCfgTokenizer->iLine++;
-        pCfgTokenizer->pszLineCurr = pCfgTokenizer->pszLine;
-    }
-
-    return rc;
-}
-
-/**
- * Creates the config tokenizer from the given filename.
- *
- * @returns VBox status code.
- * @param   pszFilename    Config filename.
- * @param   ppCfgTokenizer Where to store the pointer to the config tokenizer on
- *                         success.
- */
-static int autostartConfigTokenizerCreate(const char *pszFilename, PCFGTOKENIZER *ppCfgTokenizer)
-{
-    int rc = VINF_SUCCESS;
-    PCFGTOKENIZER pCfgTokenizer = (PCFGTOKENIZER)RTMemAllocZ(sizeof(CFGTOKENIZER));
-
-    if (pCfgTokenizer)
-    {
-        pCfgTokenizer->iLine = 1;
-        pCfgTokenizer->cbLine = 128;
-        pCfgTokenizer->pszLine = (char *)RTMemAllocZ(pCfgTokenizer->cbLine);
-        if (pCfgTokenizer->pszLine)
-        {
-            rc = RTStrmOpen(pszFilename, "r", &pCfgTokenizer->hStrmConfig);
-            if (RT_SUCCESS(rc))
-                rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
-        }
-        else
-            rc = VERR_NO_MEMORY;
-    }
-    else
-        rc = VERR_NO_MEMORY;
-
-    if (RT_SUCCESS(rc))
-        *ppCfgTokenizer = pCfgTokenizer;
-    else if (   RT_FAILURE(rc)
-             && pCfgTokenizer)
-    {
-        if (pCfgTokenizer->pszLine)
-            RTMemFree(pCfgTokenizer->pszLine);
-        if (pCfgTokenizer->hStrmConfig)
-            RTStrmClose(pCfgTokenizer->hStrmConfig);
-        RTMemFree(pCfgTokenizer);
-    }
-
-    return rc;
-}
-
-/**
- * Destroys the given config tokenizer.
- *
- * @returns nothing.
- * @param   pCfgTokenizer    The config tokenizer to destroy.
- */
-static void autostartConfigTokenizerDestroy(PCFGTOKENIZER pCfgTokenizer)
-{
-    if (pCfgTokenizer->pszLine)
-        RTMemFree(pCfgTokenizer->pszLine);
-    if (pCfgTokenizer->hStrmConfig)
-        RTStrmClose(pCfgTokenizer->hStrmConfig);
-    RTMemFree(pCfgTokenizer);
-}
-
-/**
- * Read the next token from the config file.
- *
- * @returns VBox status code.
- * @param   pCfgTokenizer    The config tokenizer data.
- * @param   ppszToken        Where to store the start to the next token on success.
- * @param   pcchToken        Where to store the number of characters of the next token
- *                           excluding the \0 terminator on success.
- */
-static int autostartConfigTokenizerReadNext(PCFGTOKENIZER pCfgTokenizer, const char **ppszToken,
-                                            size_t *pcchToken)
-{
-    if (!pCfgTokenizer->pszLineCurr)
-        return VERR_EOF;
-
-    int rc = VINF_SUCCESS;
-
-    for (;;)
-    {
-        char *pszTok = pCfgTokenizer->pszLineCurr;
-
-        /* Skip all spaces. */
-        while (RT_C_IS_BLANK(*pszTok))
-            pszTok++;
-
-        /* Check if we have to read a new line. */
-        if (   *pszTok == '\0'
-            || *pszTok == '#')
-        {
-            rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
-            if (RT_FAILURE(rc))
-                break;
-            /* start from the beginning. */
-        }
-        else if (   *pszTok == '='
-                 || *pszTok == ',')
-        {
-            *ppszToken = pszTok;
-            *pcchToken = 1;
-            pCfgTokenizer->pszLineCurr = pszTok + 1;
-            break;
-        }
-        else
-        {
-            /* Get the complete token. */
-            size_t cchToken = 1;
-            char *pszTmp = pszTok + 1;
-
-            while (   RT_C_IS_ALNUM(*pszTmp)
-                   || *pszTmp == '_')
-            {
-                pszTmp++;
-                cchToken++;
-            }
-
-            *ppszToken = pszTok;
-            *pcchToken = cchToken;
-            pCfgTokenizer->pszLineCurr = pszTmp;
-            break;
-        }
-    }
-
-    return rc;
-}
-
-static int autostartConfigTokenizerCheckAndConsume(PCFGTOKENIZER pCfgTokenizer, const char *pszTokCheck)
-{
-    int rc = VINF_SUCCESS;
-    const char *pszToken = NULL;
-    size_t cchToken = 0;
-
-    rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken, &cchToken);
-    if (RT_SUCCESS(rc))
-    {
-        if (RTStrNCmp(pszToken, pszTokCheck, cchToken))
-        {
-            RTMsgError("Unexpected token at line %d, expected '%s'",
-                       pCfgTokenizer->iLine, pszTokCheck);
-            rc = VERR_INVALID_PARAMETER;
-        }
-    }
-    return rc;
-}
-
-/**
- * Returns the start of the next token without consuming it.
- *
- * @returns VBox status code.
- * @param   pCfgTokenizer    Tokenizer instance data.
- * @param   ppszTok          Where to store the start of the next token on success.
- */
-static int autostartConfigTokenizerPeek(PCFGTOKENIZER pCfgTokenizer, const char **ppszTok)
-{
-    int rc = VINF_SUCCESS;
-
-    for (;;)
-    {
-        char *pszTok = pCfgTokenizer->pszLineCurr;
-
-        /* Skip all spaces. */
-        while (RT_C_IS_BLANK(*pszTok))
-            pszTok++;
-
-        /* Check if we have to read a new line. */
-        if (   *pszTok == '\0'
-            || *pszTok == '#')
-        {
-            rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
-            if (RT_FAILURE(rc))
-                break;
-            /* start from the beginning. */
-        }
-        else
-        {
-            *ppszTok = pszTok;
-            break;
-        }
-    }
-
-    return rc;
-}
-
-/**
- * Check whether the given token is a reserved token.
- *
- * @returns true if the token is reserved or false otherwise.
- * @param   pszToken    The token to check.
- * @param   cchToken    Size of the token in characters.
- */
-static bool autostartConfigTokenizerIsReservedToken(const char *pszToken, size_t cchToken)
-{
-    if (   cchToken == 1
-        && (   *pszToken == ','
-            || *pszToken == '='))
-        return true;
-    else if (   cchToken > 1
-             && (   !RTStrNCmp(pszToken, "default_policy", cchToken)
-                 || !RTStrNCmp(pszToken, "exception_list", cchToken)))
-        return true;
-
-    return false;
-}
-
-/**
- * Parse the given configuration file and return the interesting config parameters.
- *
- * @returns VBox status code.
- * @param   pszFilename    The config file to parse.
- * @param   pfAllowed      Where to store the flag whether the user of this process
- *                         is allowed to start VMs automatically during system startup.
- * @param   puStartupDelay Where to store the startup delay for the user.
- */
-static int autostartParseConfig(const char *pszFilename, bool *pfAllowed, uint32_t *puStartupDelay)
-{
-    int rc = VINF_SUCCESS;
-    char *pszUserProcess = NULL;
-    bool fDefaultAllow = false;
-    bool fInExceptionList = false;
-
-    AssertPtrReturn(pfAllowed, VERR_INVALID_POINTER);
-    AssertPtrReturn(puStartupDelay, VERR_INVALID_POINTER);
-
-    *pfAllowed = false;
-    *puStartupDelay = 0;
-
-    rc = RTProcQueryUsernameA(RTProcSelf(), &pszUserProcess);
-    if (RT_SUCCESS(rc))
-    {
-        PCFGTOKENIZER pCfgTokenizer = NULL;
-
-        rc = autostartConfigTokenizerCreate(pszFilename, &pCfgTokenizer);
-        if (RT_SUCCESS(rc))
-        {
-            do
-            {
-                size_t cchToken = 0;
-                const char *pszToken = NULL;
-
-                rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
-                                                      &cchToken);
-                if (RT_SUCCESS(rc))
-                {
-                    if (!RTStrNCmp(pszToken, "default_policy", strlen("default_policy")))
-                    {
-                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
-                        if (RT_SUCCESS(rc))
-                        {
-                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
-                                                                  &cchToken);
-                            if (RT_SUCCESS(rc))
-                            {
-                                if (!RTStrNCmp(pszToken, "allow", strlen("allow")))
-                                    fDefaultAllow = true;
-                                else if (!RTStrNCmp(pszToken, "deny", strlen("deny")))
-                                    fDefaultAllow = false;
-                                else
-                                {
-                                    RTMsgError("Unexpected token at line %d, expected either 'allow' or 'deny'",
-                                               pCfgTokenizer->iLine);
-                                    rc = VERR_INVALID_PARAMETER;
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                    else if (!RTStrNCmp(pszToken, "exception_list", strlen("exception_list")))
-                    {
-                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
-                        if (RT_SUCCESS(rc))
-                        {
-                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
-                                                                  &cchToken);
-
-                            while (RT_SUCCESS(rc))
-                            {
-                                if (autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
-                                {
-                                    RTMsgError("Unexpected token at line %d, expected a username",
-                                               pCfgTokenizer->iLine);
-                                    rc = VERR_INVALID_PARAMETER;
-                                    break;
-                                }
-                                else if (!RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
-                                    fInExceptionList = true;
-
-                                /* Skip , */
-                                rc = autostartConfigTokenizerPeek(pCfgTokenizer, &pszToken);
-                                if (   RT_SUCCESS(rc)
-                                    && *pszToken == ',')
-                                {
-                                    rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, ",");
-                                    AssertRC(rc);
-                                }
-                                else if (RT_SUCCESS(rc))
-                                    break;
-
-                                rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
-                                                                      &cchToken);
-                            }
-
-                            if (rc == VERR_EOF)
-                                rc = VINF_SUCCESS;
-                        }
-                    }
-                    else if (!autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
-                    {
-                        /* Treat as 'username = <base delay in seconds>. */
-                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
-                        if (RT_SUCCESS(rc))
-                        {
-                            size_t cchDelay = 0;
-                            const char *pszDelay = NULL;
-
-                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszDelay,
-                                                                  &cchDelay);
-                            if (RT_SUCCESS(rc))
-                            {
-                                uint32_t uDelay = 0;
-
-                                rc = RTStrToUInt32Ex(pszDelay, NULL, 10, &uDelay);
-                                if (rc == VWRN_TRAILING_SPACES)
-                                    rc = VINF_SUCCESS;
-
-                                if (   RT_SUCCESS(rc)
-                                    && !RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
-                                        *puStartupDelay = uDelay;
-
-                                if (RT_FAILURE(rc))
-                                    RTMsgError("Unexpected token at line %d, expected a number",
-                                               pCfgTokenizer->iLine);
-                            }
-                        }
-                    }
-                    else
-                    {
-                        RTMsgError("Unexpected token at line %d, expected a username",
-                                   pCfgTokenizer->iLine);
-                        rc = VERR_INVALID_PARAMETER;
-                    }
-                }
-                else if (rc == VERR_EOF)
-                {
-                    rc = VINF_SUCCESS;
-                    break;
-                }
-            } while (RT_SUCCESS(rc));
-
-            if (   RT_SUCCESS(rc)
-                && (   (fDefaultAllow && !fInExceptionList)
-                    || (!fDefaultAllow && fInExceptionList)))
-                *pfAllowed= true;
-
-            autostartConfigTokenizerDestroy(pCfgTokenizer);
-        }
-
-        RTStrFree(pszUserProcess);
-    }
-
-    return rc;
-}
-
-static DECLCALLBACK(bool) autostartVMCmp(const AUTOSTARTVM &vm1, const AUTOSTARTVM &vm2)
-{
-    return vm1.uStartupDelay <= vm2.uStartupDelay;
-}
-
-/**
- * Main routine for the autostart daemon.
- *
- * @returns exit status code.
- */
-static RTEXITCODE autostartMain(uint32_t uStartupDelay)
-{
-    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
-    int vrc = VINF_SUCCESS;
-    std::list<AUTOSTARTVM> listVM;
-
-    if (uStartupDelay)
-    {
-        serviceLogVerbose(("Delay starting for %d seconds ...\n", uStartupDelay));
-        vrc = RTThreadSleep(uStartupDelay * 1000);
-    }
-
-    if (vrc == VERR_INTERRUPTED)
-        return RTEXITCODE_SUCCESS;
-
-    /*
-     * Build a list of all VMs we need to autostart first, apply the overrides
-     * from the configuration and start the VMs afterwards.
-     */
-    com::SafeIfaceArray<IMachine> machines;
-    HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
-    if (SUCCEEDED(rc))
-    {
-        /*
-         * Iterate through the collection
-         */
-        for (size_t i = 0; i < machines.size(); ++i)
-        {
-            if (machines[i])
-            {
-                BOOL fAccessible;
-                CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
-                if (!fAccessible)
-                    continue;
-
-                BOOL fAutostart;
-                CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartEnabled)(&fAutostart));
-                if (fAutostart)
-                {
-                    AUTOSTARTVM autostartVM;
-
-                    CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostartVM.strId.asOutParam()));
-                    CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartDelay)(&autostartVM.uStartupDelay));
-
-                    listVM.push_back(autostartVM);
-                }
-            }
-        }
-
-        if (   SUCCEEDED(rc)
-            && listVM.size())
-        {
-            ULONG uDelayCurr = 0;
-
-            /* Sort by startup delay and apply base override. */
-            listVM.sort(autostartVMCmp);
-
-            std::list<AUTOSTARTVM>::iterator it;
-            for (it = listVM.begin(); it != listVM.end(); it++)
-            {
-                ComPtr<IMachine> machine;
-                ComPtr<IProgress> progress;
-
-                if ((*it).uStartupDelay > uDelayCurr)
-                {
-                    serviceLogVerbose(("Delay starting of the next VMs for %d seconds ...\n",
-                                       (*it).uStartupDelay - uDelayCurr));
-                    RTThreadSleep(((*it).uStartupDelay - uDelayCurr) * 1000);
-                    uDelayCurr = (*it).uStartupDelay;
-                }
-
-                CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
-                                                             machine.asOutParam()));
-
-                CHECK_ERROR_BREAK(machine, LaunchVMProcess(g_pSession, Bstr("headless").raw(),
-                                                           Bstr("").raw(), progress.asOutParam()));
-                if (SUCCEEDED(rc) && !progress.isNull())
-                {
-                    serviceLogVerbose(("Waiting for VM \"%ls\" to power on...\n", (*it).strId.raw()));
-                    CHECK_ERROR(progress, WaitForCompletion(-1));
-                    if (SUCCEEDED(rc))
-                    {
-                        BOOL completed = true;
-                        CHECK_ERROR(progress, COMGETTER(Completed)(&completed));
-                        if (SUCCEEDED(rc))
-                        {
-                            ASSERT(completed);
-
-                            LONG iRc;
-                            CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc));
-                            if (SUCCEEDED(rc))
-                            {
-                                if (FAILED(iRc))
-                                {
-                                    ProgressErrorInfo info(progress);
-                                    com::GluePrintErrorInfo(info);
-                                }
-                                else
-                                    serviceLogVerbose(("VM \"%ls\" has been successfully started.\n", (*it).strId.raw()));
-                            }
-                        }
-                    }
-                }
-                g_pSession->UnlockMachine();
-            }
-        }
-    }
-
-    return rcExit;
 }
 
@@ -703,5 +161,5 @@
                 break;
 
-#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
+#ifdef VBOXAUTOSTART_DAEMONIZE
             case 'b':
                 pcszDescr = "Run in background (daemon mode).";
@@ -807,5 +265,5 @@
                 break;
 
-#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
+#ifdef VBOXAUTOSTART_DAEMONIZE
             case 'b':
                 g_fDaemonize = true;
@@ -901,5 +359,5 @@
         return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
 
-#if defined(RT_OS_LINUX) || defined (RT_OS_SOLARIS) || defined(RT_OS_FREEBSD) || defined(RT_OS_DARWIN)
+#ifdef VBOXAUTOSTART_DAEMONIZE
     if (g_fDaemonize)
     {
@@ -969,5 +427,12 @@
         return RTEXITCODE_FAILURE;
 
-    RTEXITCODE rcExit = autostartMain(uStartupDelay);
+    RTEXITCODE rcExit;
+    if (fStart)
+        rcExit = autostartStartMain(uStartupDelay);
+    else
+    {
+        Assert(fStop);
+        rcExit = autostartStopMain(uStartupDelay);
+    }
 
     EventQueue::getMainEventQueue()->processEventQueue(0);
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h	(revision 42527)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h	(revision 42527)
@@ -0,0 +1,79 @@
+/* $Id$ */
+/** @file
+ * VBoxAutostart - VirtualBox Autostart service.
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef __VBoxAutostart_h__
+#define __VBoxAutostart_h__
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+
+#include <VBox/com/com.h>
+#include <VBox/com/VirtualBox.h>
+
+/** Flag whether we are in verbose logging mode. */
+extern bool                g_fVerbose;
+/** Handle to the VirtualBox interface. */
+extern ComPtr<IVirtualBox> g_pVirtualBox;
+/** Handle to the session interface. */
+extern ComPtr<ISession>    g_pSession;
+
+/**
+ * Log information in verbose mode.
+ */
+#define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; }
+
+/**
+ * Log messages to the release log.
+ *
+ * @returns nothing.
+ * @param   pszFormat    Format string.
+ */
+DECLHIDDEN(void) serviceLog(const char *pszFormat, ...);
+
+/**
+ * Parse the given configuration file and return the interesting config parameters.
+ *
+ * @returns VBox status code.
+ * @param   pszFilename    The config file to parse.
+ * @param   pfAllowed      Where to store the flag whether the user of this process
+ *                         is allowed to start VMs automatically during system startup.
+ * @param   puStartupDelay Where to store the startup delay for the user.
+ */
+DECLHIDDEN(int) autostartParseConfig(const char *pszFilename, bool *pfAllowed, uint32_t *puStartupDelay);
+
+/**
+ * Main routine for the autostart daemon.
+ *
+ * @returns exit status code.
+ * @param   uStartupDelay    Base startup for the user.
+ */
+DECLHIDDEN(RTEXITCODE) autostartStartMain(uint32_t uStartupDelay);
+
+/**
+ * Main routine for the autostart daemon when stopping virtual machines
+ * during system shutdown.
+ *
+ * @returns exit status code.
+ * @param   uStartupDelay    Base stop delay for the user.
+ */
+DECLHIDDEN(RTEXITCODE) autostartStopMain(uint32_t uStopDelay);
+
+#endif /* __VBoxAutostart_h__ */
+
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartCfg.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartCfg.cpp	(revision 42527)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartCfg.cpp	(revision 42527)
@@ -0,0 +1,443 @@
+/* $Id$ */
+/** @file
+ * VBoxAutostart - VirtualBox Autostart service, configuration parser.
+ */
+
+/*
+ * 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                                                               *
+*******************************************************************************/
+
+#include <iprt/stream.h>
+#include <iprt/process.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/ctype.h>
+#include <iprt/message.h>
+
+#include "VBoxAutostart.h"
+
+/*******************************************************************************
+*   Constants And Macros, Structures and Typedefs                              *
+*******************************************************************************/
+
+/**
+ * Tokenizer instance data for the config data.
+ */
+typedef struct CFGTOKENIZER
+{
+    /** Config file handle. */
+    PRTSTREAM hStrmConfig;
+    /** String buffer for the current line we are operating in. */
+    char      *pszLine;
+    /** Size of the string buffer. */
+    size_t     cbLine;
+    /** Current position in the line. */
+    char      *pszLineCurr;
+    /** Current line in the config file. */
+    unsigned   iLine;
+} CFGTOKENIZER, *PCFGTOKENIZER;
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+
+/**
+ * Reads the next line from the config stream.
+ *
+ * @returns VBox status code.
+ * @param   pCfgTokenizer    The config tokenizer.
+ */
+static int autostartConfigTokenizerReadNextLine(PCFGTOKENIZER pCfgTokenizer)
+{
+    int rc = VINF_SUCCESS;
+
+    do
+    {
+        rc = RTStrmGetLine(pCfgTokenizer->hStrmConfig, pCfgTokenizer->pszLine,
+                           pCfgTokenizer->cbLine);
+        if (rc == VERR_BUFFER_OVERFLOW)
+        {
+            char *pszTmp;
+
+            pCfgTokenizer->cbLine += 128;
+            pszTmp = (char *)RTMemRealloc(pCfgTokenizer->pszLine, pCfgTokenizer->cbLine);
+            if (pszTmp)
+                pCfgTokenizer->pszLine = pszTmp;
+            else
+                rc = VERR_NO_MEMORY;
+        }
+    } while (rc == VERR_BUFFER_OVERFLOW);
+
+    if (RT_SUCCESS(rc))
+    {
+        pCfgTokenizer->iLine++;
+        pCfgTokenizer->pszLineCurr = pCfgTokenizer->pszLine;
+    }
+
+    return rc;
+}
+
+/**
+ * Creates the config tokenizer from the given filename.
+ *
+ * @returns VBox status code.
+ * @param   pszFilename    Config filename.
+ * @param   ppCfgTokenizer Where to store the pointer to the config tokenizer on
+ *                         success.
+ */
+static int autostartConfigTokenizerCreate(const char *pszFilename, PCFGTOKENIZER *ppCfgTokenizer)
+{
+    int rc = VINF_SUCCESS;
+    PCFGTOKENIZER pCfgTokenizer = (PCFGTOKENIZER)RTMemAllocZ(sizeof(CFGTOKENIZER));
+
+    if (pCfgTokenizer)
+    {
+        pCfgTokenizer->iLine = 1;
+        pCfgTokenizer->cbLine = 128;
+        pCfgTokenizer->pszLine = (char *)RTMemAllocZ(pCfgTokenizer->cbLine);
+        if (pCfgTokenizer->pszLine)
+        {
+            rc = RTStrmOpen(pszFilename, "r", &pCfgTokenizer->hStrmConfig);
+            if (RT_SUCCESS(rc))
+                rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
+        }
+        else
+            rc = VERR_NO_MEMORY;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    if (RT_SUCCESS(rc))
+        *ppCfgTokenizer = pCfgTokenizer;
+    else if (   RT_FAILURE(rc)
+             && pCfgTokenizer)
+    {
+        if (pCfgTokenizer->pszLine)
+            RTMemFree(pCfgTokenizer->pszLine);
+        if (pCfgTokenizer->hStrmConfig)
+            RTStrmClose(pCfgTokenizer->hStrmConfig);
+        RTMemFree(pCfgTokenizer);
+    }
+
+    return rc;
+}
+
+/**
+ * Destroys the given config tokenizer.
+ *
+ * @returns nothing.
+ * @param   pCfgTokenizer    The config tokenizer to destroy.
+ */
+static void autostartConfigTokenizerDestroy(PCFGTOKENIZER pCfgTokenizer)
+{
+    if (pCfgTokenizer->pszLine)
+        RTMemFree(pCfgTokenizer->pszLine);
+    if (pCfgTokenizer->hStrmConfig)
+        RTStrmClose(pCfgTokenizer->hStrmConfig);
+    RTMemFree(pCfgTokenizer);
+}
+
+/**
+ * Read the next token from the config file.
+ *
+ * @returns VBox status code.
+ * @param   pCfgTokenizer    The config tokenizer data.
+ * @param   ppszToken        Where to store the start to the next token on success.
+ * @param   pcchToken        Where to store the number of characters of the next token
+ *                           excluding the \0 terminator on success.
+ */
+static int autostartConfigTokenizerReadNext(PCFGTOKENIZER pCfgTokenizer, const char **ppszToken,
+                                            size_t *pcchToken)
+{
+    if (!pCfgTokenizer->pszLineCurr)
+        return VERR_EOF;
+
+    int rc = VINF_SUCCESS;
+
+    for (;;)
+    {
+        char *pszTok = pCfgTokenizer->pszLineCurr;
+
+        /* Skip all spaces. */
+        while (RT_C_IS_BLANK(*pszTok))
+            pszTok++;
+
+        /* Check if we have to read a new line. */
+        if (   *pszTok == '\0'
+            || *pszTok == '#')
+        {
+            rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
+            if (RT_FAILURE(rc))
+                break;
+            /* start from the beginning. */
+        }
+        else if (   *pszTok == '='
+                 || *pszTok == ',')
+        {
+            *ppszToken = pszTok;
+            *pcchToken = 1;
+            pCfgTokenizer->pszLineCurr = pszTok + 1;
+            break;
+        }
+        else
+        {
+            /* Get the complete token. */
+            size_t cchToken = 1;
+            char *pszTmp = pszTok + 1;
+
+            while (   RT_C_IS_ALNUM(*pszTmp)
+                   || *pszTmp == '_')
+            {
+                pszTmp++;
+                cchToken++;
+            }
+
+            *ppszToken = pszTok;
+            *pcchToken = cchToken;
+            pCfgTokenizer->pszLineCurr = pszTmp;
+            break;
+        }
+    }
+
+    return rc;
+}
+
+static int autostartConfigTokenizerCheckAndConsume(PCFGTOKENIZER pCfgTokenizer, const char *pszTokCheck)
+{
+    int rc = VINF_SUCCESS;
+    const char *pszToken = NULL;
+    size_t cchToken = 0;
+
+    rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken, &cchToken);
+    if (RT_SUCCESS(rc))
+    {
+        if (RTStrNCmp(pszToken, pszTokCheck, cchToken))
+        {
+            RTMsgError("Unexpected token at line %d, expected '%s'",
+                       pCfgTokenizer->iLine, pszTokCheck);
+            rc = VERR_INVALID_PARAMETER;
+        }
+    }
+    return rc;
+}
+
+/**
+ * Returns the start of the next token without consuming it.
+ *
+ * @returns VBox status code.
+ * @param   pCfgTokenizer    Tokenizer instance data.
+ * @param   ppszTok          Where to store the start of the next token on success.
+ */
+static int autostartConfigTokenizerPeek(PCFGTOKENIZER pCfgTokenizer, const char **ppszTok)
+{
+    int rc = VINF_SUCCESS;
+
+    for (;;)
+    {
+        char *pszTok = pCfgTokenizer->pszLineCurr;
+
+        /* Skip all spaces. */
+        while (RT_C_IS_BLANK(*pszTok))
+            pszTok++;
+
+        /* Check if we have to read a new line. */
+        if (   *pszTok == '\0'
+            || *pszTok == '#')
+        {
+            rc = autostartConfigTokenizerReadNextLine(pCfgTokenizer);
+            if (RT_FAILURE(rc))
+                break;
+            /* start from the beginning. */
+        }
+        else
+        {
+            *ppszTok = pszTok;
+            break;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Check whether the given token is a reserved token.
+ *
+ * @returns true if the token is reserved or false otherwise.
+ * @param   pszToken    The token to check.
+ * @param   cchToken    Size of the token in characters.
+ */
+static bool autostartConfigTokenizerIsReservedToken(const char *pszToken, size_t cchToken)
+{
+    if (   cchToken == 1
+        && (   *pszToken == ','
+            || *pszToken == '='))
+        return true;
+    else if (   cchToken > 1
+             && (   !RTStrNCmp(pszToken, "default_policy", cchToken)
+                 || !RTStrNCmp(pszToken, "exception_list", cchToken)))
+        return true;
+
+    return false;
+}
+
+DECLHIDDEN(int) autostartParseConfig(const char *pszFilename, bool *pfAllowed, uint32_t *puStartupDelay)
+{
+    int rc = VINF_SUCCESS;
+    char *pszUserProcess = NULL;
+    bool fDefaultAllow = false;
+    bool fInExceptionList = false;
+
+    AssertPtrReturn(pfAllowed, VERR_INVALID_POINTER);
+    AssertPtrReturn(puStartupDelay, VERR_INVALID_POINTER);
+
+    *pfAllowed = false;
+    *puStartupDelay = 0;
+
+    rc = RTProcQueryUsernameA(RTProcSelf(), &pszUserProcess);
+    if (RT_SUCCESS(rc))
+    {
+        PCFGTOKENIZER pCfgTokenizer = NULL;
+
+        rc = autostartConfigTokenizerCreate(pszFilename, &pCfgTokenizer);
+        if (RT_SUCCESS(rc))
+        {
+            do
+            {
+                size_t cchToken = 0;
+                const char *pszToken = NULL;
+
+                rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
+                                                      &cchToken);
+                if (RT_SUCCESS(rc))
+                {
+                    if (!RTStrNCmp(pszToken, "default_policy", strlen("default_policy")))
+                    {
+                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
+                        if (RT_SUCCESS(rc))
+                        {
+                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
+                                                                  &cchToken);
+                            if (RT_SUCCESS(rc))
+                            {
+                                if (!RTStrNCmp(pszToken, "allow", strlen("allow")))
+                                    fDefaultAllow = true;
+                                else if (!RTStrNCmp(pszToken, "deny", strlen("deny")))
+                                    fDefaultAllow = false;
+                                else
+                                {
+                                    RTMsgError("Unexpected token at line %d, expected either 'allow' or 'deny'",
+                                               pCfgTokenizer->iLine);
+                                    rc = VERR_INVALID_PARAMETER;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else if (!RTStrNCmp(pszToken, "exception_list", strlen("exception_list")))
+                    {
+                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
+                        if (RT_SUCCESS(rc))
+                        {
+                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
+                                                                  &cchToken);
+
+                            while (RT_SUCCESS(rc))
+                            {
+                                if (autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
+                                {
+                                    RTMsgError("Unexpected token at line %d, expected a username",
+                                               pCfgTokenizer->iLine);
+                                    rc = VERR_INVALID_PARAMETER;
+                                    break;
+                                }
+                                else if (!RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
+                                    fInExceptionList = true;
+
+                                /* Skip , */
+                                rc = autostartConfigTokenizerPeek(pCfgTokenizer, &pszToken);
+                                if (   RT_SUCCESS(rc)
+                                    && *pszToken == ',')
+                                {
+                                    rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, ",");
+                                    AssertRC(rc);
+                                }
+                                else if (RT_SUCCESS(rc))
+                                    break;
+
+                                rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszToken,
+                                                                      &cchToken);
+                            }
+
+                            if (rc == VERR_EOF)
+                                rc = VINF_SUCCESS;
+                        }
+                    }
+                    else if (!autostartConfigTokenizerIsReservedToken(pszToken, cchToken))
+                    {
+                        /* Treat as 'username = <base delay in seconds>. */
+                        rc = autostartConfigTokenizerCheckAndConsume(pCfgTokenizer, "=");
+                        if (RT_SUCCESS(rc))
+                        {
+                            size_t cchDelay = 0;
+                            const char *pszDelay = NULL;
+
+                            rc = autostartConfigTokenizerReadNext(pCfgTokenizer, &pszDelay,
+                                                                  &cchDelay);
+                            if (RT_SUCCESS(rc))
+                            {
+                                uint32_t uDelay = 0;
+
+                                rc = RTStrToUInt32Ex(pszDelay, NULL, 10, &uDelay);
+                                if (rc == VWRN_TRAILING_SPACES)
+                                    rc = VINF_SUCCESS;
+
+                                if (   RT_SUCCESS(rc)
+                                    && !RTStrNCmp(pszUserProcess, pszToken, strlen(pszUserProcess)))
+                                        *puStartupDelay = uDelay;
+
+                                if (RT_FAILURE(rc))
+                                    RTMsgError("Unexpected token at line %d, expected a number",
+                                               pCfgTokenizer->iLine);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        RTMsgError("Unexpected token at line %d, expected a username",
+                                   pCfgTokenizer->iLine);
+                        rc = VERR_INVALID_PARAMETER;
+                    }
+                }
+                else if (rc == VERR_EOF)
+                {
+                    rc = VINF_SUCCESS;
+                    break;
+                }
+            } while (RT_SUCCESS(rc));
+
+            if (   RT_SUCCESS(rc)
+                && (   (fDefaultAllow && !fInExceptionList)
+                    || (!fDefaultAllow && fInExceptionList)))
+                *pfAllowed= true;
+
+            autostartConfigTokenizerDestroy(pCfgTokenizer);
+        }
+
+        RTStrFree(pszUserProcess);
+    }
+
+    return rc;
+}
+
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStart.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStart.cpp	(revision 42527)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStart.cpp	(revision 42527)
@@ -0,0 +1,163 @@
+/* $Id$ */
+/** @file
+ * VBoxAutostart - VirtualBox Autostart service, start machines during system boot.
+ */
+
+/*
+ * 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.
+ */
+
+#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 <iprt/thread.h>
+#include <iprt/stream.h>
+#include <iprt/log.h>
+
+#include <algorithm>
+#include <list>
+#include <string>
+
+#include "VBoxAutostart.h"
+
+using namespace com;
+
+/**
+ * VM list entry.
+ */
+typedef struct AUTOSTARTVM
+{
+    /** ID of the VM to start. */
+    Bstr  strId;
+    /** Startup delay of the VM. */
+    ULONG uStartupDelay;
+} AUTOSTARTVM;
+
+static DECLCALLBACK(bool) autostartVMCmp(const AUTOSTARTVM &vm1, const AUTOSTARTVM &vm2)
+{
+    return vm1.uStartupDelay <= vm2.uStartupDelay;
+}
+
+DECLHIDDEN(RTEXITCODE) autostartStartMain(uint32_t uStartupDelay)
+{
+    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+    int vrc = VINF_SUCCESS;
+    std::list<AUTOSTARTVM> listVM;
+
+    if (uStartupDelay)
+    {
+        serviceLogVerbose(("Delay starting for %d seconds ...\n", uStartupDelay));
+        vrc = RTThreadSleep(uStartupDelay * 1000);
+    }
+
+    if (vrc == VERR_INTERRUPTED)
+        return RTEXITCODE_SUCCESS;
+
+    /*
+     * Build a list of all VMs we need to autostart first, apply the overrides
+     * from the configuration and start the VMs afterwards.
+     */
+    com::SafeIfaceArray<IMachine> machines;
+    HRESULT rc = g_pVirtualBox->COMGETTER(Machines)(ComSafeArrayAsOutParam(machines));
+    if (SUCCEEDED(rc))
+    {
+        /*
+         * Iterate through the collection
+         */
+        for (size_t i = 0; i < machines.size(); ++i)
+        {
+            if (machines[i])
+            {
+                BOOL fAccessible;
+                CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible)(&fAccessible));
+                if (!fAccessible)
+                    continue;
+
+                BOOL fAutostart;
+                CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartEnabled)(&fAutostart));
+                if (fAutostart)
+                {
+                    AUTOSTARTVM autostartVM;
+
+                    CHECK_ERROR_BREAK(machines[i], COMGETTER(Id)(autostartVM.strId.asOutParam()));
+                    CHECK_ERROR_BREAK(machines[i], COMGETTER(AutostartDelay)(&autostartVM.uStartupDelay));
+
+                    listVM.push_back(autostartVM);
+                }
+            }
+        }
+
+        if (   SUCCEEDED(rc)
+            && listVM.size())
+        {
+            ULONG uDelayCurr = 0;
+
+            /* Sort by startup delay and apply base override. */
+            listVM.sort(autostartVMCmp);
+
+            std::list<AUTOSTARTVM>::iterator it;
+            for (it = listVM.begin(); it != listVM.end(); it++)
+            {
+                ComPtr<IMachine> machine;
+                ComPtr<IProgress> progress;
+
+                if ((*it).uStartupDelay > uDelayCurr)
+                {
+                    serviceLogVerbose(("Delay starting of the next VMs for %d seconds ...\n",
+                                       (*it).uStartupDelay - uDelayCurr));
+                    RTThreadSleep(((*it).uStartupDelay - uDelayCurr) * 1000);
+                    uDelayCurr = (*it).uStartupDelay;
+                }
+
+                CHECK_ERROR_BREAK(g_pVirtualBox, FindMachine((*it).strId.raw(),
+                                                             machine.asOutParam()));
+
+                CHECK_ERROR_BREAK(machine, LaunchVMProcess(g_pSession, Bstr("headless").raw(),
+                                                           Bstr("").raw(), progress.asOutParam()));
+                if (SUCCEEDED(rc) && !progress.isNull())
+                {
+                    serviceLogVerbose(("Waiting for VM \"%ls\" to power on...\n", (*it).strId.raw()));
+                    CHECK_ERROR(progress, WaitForCompletion(-1));
+                    if (SUCCEEDED(rc))
+                    {
+                        BOOL completed = true;
+                        CHECK_ERROR(progress, COMGETTER(Completed)(&completed));
+                        if (SUCCEEDED(rc))
+                        {
+                            ASSERT(completed);
+
+                            LONG iRc;
+                            CHECK_ERROR(progress, COMGETTER(ResultCode)(&iRc));
+                            if (SUCCEEDED(rc))
+                            {
+                                if (FAILED(iRc))
+                                {
+                                    ProgressErrorInfo info(progress);
+                                    com::GluePrintErrorInfo(info);
+                                }
+                                else
+                                    serviceLogVerbose(("VM \"%ls\" has been successfully started.\n", (*it).strId.raw()));
+                            }
+                        }
+                    }
+                }
+                g_pSession->UnlockMachine();
+            }
+        }
+    }
+
+    return rcExit;
+}
+
Index: /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp	(revision 42527)
+++ /trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp	(revision 42527)
@@ -0,0 +1,46 @@
+/* $Id$ */
+/** @file
+ * VBoxAutostart - VirtualBox Autostart service, stop machines during system shutdown.
+ */
+
+/*
+ * 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.
+ */
+
+#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 <iprt/thread.h>
+#include <iprt/stream.h>
+#include <iprt/log.h>
+#include <iprt/assert.h>
+
+#include <algorithm>
+#include <list>
+#include <string>
+
+#include "VBoxAutostart.h"
+
+using namespace com;
+
+DECLHIDDEN(RTEXITCODE) autostartStopMain(uint32_t uStartupDelay)
+{
+    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+
+    AssertMsgFailed(("Not implemented yet!\n"));
+
+    return rcExit;
+}
+
