Index: trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk
===================================================================
--- trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk	(revision 76582)
+++ trunk/src/VBox/Frontends/VBoxAutostart/Makefile.kmk	(revision 80569)
@@ -22,4 +22,5 @@
  PROGRAMS += VBoxAutostartSvc
  VBoxAutostartSvc_TEMPLATE   = VBOXMAINCLIENTEXE
+ VBoxAutostartSvc_INCS       = ../Common
  VBoxAutostartSvc_SOURCES    = \
 	VBoxAutostartCfg.cpp \
@@ -27,5 +28,7 @@
 	VBoxAutostartStop.cpp \
 	VBoxAutostartUtils.cpp \
-	VBoxAutostart-win.cpp
+	VBoxAutostart-win.cpp \
+	../Common/PasswordInput.cpp
+ VBoxAutostartSvc_LIBS.win += Secur32.lib	
 else
  PROGRAMS += VBoxAutostart
Index: trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp	(revision 76582)
+++ trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart-win.cpp	(revision 80569)
@@ -23,21 +23,27 @@
 #include <tchar.h>
 
+#define SECURITY_WIN32
+#include <Security.h>
+
+#include <VBox/com/array.h>
 #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/Guid.h>
+#include <VBox/com/listeners.h>
 #include <VBox/com/NativeEventQueue.h>
-#include <VBox/com/listeners.h>
+#include <VBox/com/string.h>
 #include <VBox/com/VirtualBox.h>
 
 #include <VBox/log.h>
 #include <VBox/version.h>
+
+#include <iprt/env.h>
 #include <iprt/errcore.h>
+#include <iprt/getopt.h>
 #include <iprt/initterm.h>
 #include <iprt/mem.h>
-#include <iprt/getopt.h>
+#include <iprt/process.h>
+#include <iprt/path.h>
 #include <iprt/semaphore.h>
 #include <iprt/stream.h>
@@ -46,4 +52,5 @@
 
 #include "VBoxAutostart.h"
+#include "PasswordInput.h"
 
 
@@ -71,4 +78,6 @@
 /** The semaphore the main service thread is waiting on in autostartSvcWinServiceMain. */
 static RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
+/** The service name is used for send to service main. */
+static com::Bstr g_bstrServiceName;
 
 
@@ -77,4 +86,95 @@
 *********************************************************************************************************************************/
 static SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
+
+static int autostartGetProcessDomainUser(com::Utf8Str &aUser)
+{
+    int rc = VERR_NOT_SUPPORTED;
+
+    RTUTF16 wszUsername[1024] = { 0 };
+    ULONG   cwcUsername = RT_ELEMENTS(wszUsername);
+    char *pszUser = NULL;
+    if (!GetUserNameExW(NameSamCompatible, &wszUsername[0], &cwcUsername))
+        return RTErrConvertFromWin32(GetLastError());
+    rc = RTUtf16ToUtf8(wszUsername, &pszUser);
+    aUser = pszUser;
+    RTStrFree(pszUser);
+    return rc;
+}
+
+static int autostartGetLocalDomain(com::Utf8Str &aDomain)
+{
+    RTUTF16 pwszDomain[MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
+    uint32_t cwcDomainSize =  MAX_COMPUTERNAME_LENGTH + 1;
+    if (!GetComputerNameW(pwszDomain, (LPDWORD)&cwcDomainSize))
+        return RTErrConvertFromWin32(GetLastError());
+    char *pszDomain = NULL;
+    int rc = RTUtf16ToUtf8(pwszDomain, &pszDomain);
+    aDomain = pszDomain;
+    RTStrFree(pszDomain);
+    return rc;
+}
+
+static int autostartGetDomainAndUser(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aDomain, com::Utf8Str &aUser)
+{
+    size_t offDelim = aDomainAndUser.find("\\");
+    if (offDelim != aDomainAndUser.npos)
+    {
+        // if only domain is specified
+        if (aDomainAndUser.length() - offDelim == 1)
+            return VERR_INVALID_PARAMETER;
+
+        if (offDelim == 1 && aDomainAndUser[0] == '.')
+        {
+            int rc = autostartGetLocalDomain(aDomain);
+            aUser = aDomainAndUser.substr(offDelim + 1);
+            return rc;
+        }
+        aDomain = aDomainAndUser.substr(0, offDelim);
+        aUser   = aDomainAndUser.substr(offDelim + 1);
+        return VINF_SUCCESS;
+    }
+
+    offDelim = aDomainAndUser.find("@");
+    if (offDelim != aDomainAndUser.npos)
+    {
+        // if only domain is specified
+        if (offDelim == 0)
+            return VERR_INVALID_PARAMETER;
+
+        // with '@' but without domain
+        if (aDomainAndUser.length() - offDelim == 1)
+        {
+            int rc = autostartGetLocalDomain(aDomain);
+            aUser = aDomainAndUser.substr(0, offDelim);
+            return rc;
+        }
+        aDomain = aDomainAndUser.substr(offDelim + 1);
+        aUser   = aDomainAndUser.substr(0, offDelim);
+        return VINF_SUCCESS;
+    }
+
+    // only user is specified
+    int rc = autostartGetLocalDomain(aDomain);
+    aUser = aDomainAndUser;
+    return rc;
+}
+
+/** Common helper for formatting the service name. */
+static void autostartFormatServiceName(const com::Utf8Str &aDomain, const com::Utf8Str &aUser, com::Utf8Str &aServiceName)
+{
+    aServiceName.printf("%s%s%s", AUTOSTART_SERVICE_NAME, aDomain.c_str(), aUser.c_str());
+}
+
+/** Used by the delete service operation. */
+static int autostartGetServiceName(const com::Utf8Str &aDomainAndUser, com::Utf8Str &aServiceName)
+{
+    com::Utf8Str sDomain;
+    com::Utf8Str sUser;
+    int rc = autostartGetDomainAndUser(aDomainAndUser, sDomain, sUser);
+    if (RT_FAILURE(rc))
+        return rc;
+    autostartFormatServiceName(sDomain, sUser, aServiceName);
+    return VINF_SUCCESS;
+}
 
 /**
@@ -228,5 +328,5 @@
  * @param   ...                 Errors codes that should not cause a message to be displayed.
  */
-static SC_HANDLE autostartSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
+static SC_HANDLE autostartSvcWinOpenService(const PRTUTF16 pwszServiceName, const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
                                             unsigned cIgnoredErrors, ...)
 {
@@ -235,5 +335,5 @@
         return NULL;
 
-    SC_HANDLE hSvc = OpenServiceA(hSCM, AUTOSTART_SERVICE_NAME, dwSVCAccess);
+    SC_HANDLE hSvc = OpenServiceW(hSCM, pwszServiceName, dwSVCAccess);
     if (hSvc)
     {
@@ -258,5 +358,6 @@
                     break;
                 case ERROR_SERVICE_DOES_NOT_EXIST:
-                    autostartSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction);
+                    autostartSvcDisplayError("%s - OpenService failure: The service %ls does not exist. Reinstall it.\n",
+                                             pszAction, pwszServiceName);
                     break;
                 default:
@@ -356,10 +457,11 @@
      */
     bool fVerbose = false;
+    const char *pszUser = NULL;
     static const RTGETOPTDEF s_aOptions[] =
     {
-        { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
+        { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
+        { "--user",    'u', RTGETOPT_REQ_STRING  },
     };
     int ch;
-    unsigned iArg = 0;
     RTGETOPTUNION Value;
     RTGETOPTSTATE GetState;
@@ -372,18 +474,25 @@
                 fVerbose = true;
                 break;
-            case VINF_GETOPT_NOT_OPTION:
-                return autostartSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
+            case 'u':
+                pszUser = Value.psz;
+                break;
             default:
-                return autostartSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value);
-        }
-
-        iArg++;
-    }
-
+                return autostartSvcDisplayGetOptError("delete", ch, &Value);
+        }
+    }
+
+    if (!pszUser)
+        return autostartSvcDisplayError("delete - DeleteService failed, user name required.\n");
+
+    com::Utf8Str sServiceName;
+    int vrc = autostartGetServiceName(pszUser, sServiceName);
+    if (!RT_FAILURE(vrc))
+        return autostartSvcDisplayError("delete - DeleteService failed, service name for user %s can not be constructed.\n", 
+                                        pszUser);
     /*
      * Create the service.
      */
-    int rc = RTEXITCODE_FAILURE;
-    SC_HANDLE hSvc = autostartSvcWinOpenService("delete", SERVICE_CHANGE_CONFIG, DELETE,
+    RTEXITCODE rc = RTEXITCODE_FAILURE;
+    SC_HANDLE hSvc = autostartSvcWinOpenService(com::Bstr(sServiceName).raw(), "delete", SERVICE_CHANGE_CONFIG, DELETE,
                                                 1, ERROR_SERVICE_DOES_NOT_EXIST);
     if (hSvc)
@@ -391,5 +500,5 @@
         if (DeleteService(hSvc))
         {
-            RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
+            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
             rc = RTEXITCODE_SUCCESS;
         }
@@ -402,7 +511,7 @@
 
         if (fVerbose)
-            RTPrintf("The service %s was not installed, nothing to be done.", AUTOSTART_SERVICE_NAME);
+            RTPrintf("The service %s was not installed, nothing to be done.", sServiceName.c_str());
         else
-            RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
+            RTPrintf("Successfully deleted the %s service.\n", sServiceName.c_str());
         rc = RTEXITCODE_SUCCESS;
     }
@@ -425,12 +534,12 @@
     bool fVerbose = false;
     const char *pszUser = NULL;
-    const char *pszPwd = NULL;
+    com::Utf8Str strPwd;
+    const char *pszPwdFile = NULL;
     static const RTGETOPTDEF s_aOptions[] =
     {
-        { "--verbose",  'v', RTGETOPT_REQ_NOTHING },
-        { "--user",     'u', RTGETOPT_REQ_STRING  },
-        { "--password", 'p', RTGETOPT_REQ_STRING  }
+        { "--verbose",       'v', RTGETOPT_REQ_NOTHING },
+        { "--user",          'u', RTGETOPT_REQ_STRING  },
+        { "--password-file", 'p', RTGETOPT_REQ_STRING  }
     };
-    int iArg = 0;
     int ch;
     RTGETOPTUNION Value;
@@ -448,13 +557,42 @@
                 break;
             case 'p':
-                pszPwd = Value.psz;
+                pszPwdFile = Value.psz;
                 break;
             default:
-                return autostartSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
-        }
-        iArg++;
-    }
-    if (iArg != argc)
-        return autostartSvcDisplayTooManyArgsError("create", argc, argv, iArg);
+                return autostartSvcDisplayGetOptError("create", ch, &Value);
+        }
+    }
+
+    if (!pszUser)
+        return autostartSvcDisplayError("Username is missing");
+
+    if (pszPwdFile)
+    {
+        /* Get password from file. */
+        RTEXITCODE rcExit = readPasswordFile(pszPwdFile, &strPwd);
+        if (rcExit == RTEXITCODE_FAILURE)
+            return rcExit;
+    }
+    else
+    {
+        /* Get password from console. */
+        RTEXITCODE rcExit = readPasswordFromConsole(&strPwd, "Enter password:");
+        if (rcExit == RTEXITCODE_FAILURE)
+            return rcExit;
+    }
+
+    if (strPwd.isEmpty())
+        return autostartSvcDisplayError("Password is missing");
+
+    com::Utf8Str sDomain;
+    com::Utf8Str sUserTmp;
+    int vrc = autostartGetDomainAndUser(pszUser, sDomain, sUserTmp);
+    if (RT_FAILURE(vrc))
+        return autostartSvcDisplayError("create - CreateService failed, failed to get domain and user from string %s (%d).\n",
+                                        pszUser, vrc);
+    com::Utf8StrFmt sUserFullName("%s\\%s", sDomain.c_str(), sUserTmp.c_str());
+    com::Utf8StrFmt sDisplayName("%s %s@%s", AUTOSTART_SERVICE_DISPLAY_NAME, sUserTmp.c_str(), sDomain.c_str());
+    com::Utf8Str    sServiceName;
+    autostartFormatServiceName(sDomain, sUserTmp, sServiceName);
 
     /*
@@ -465,27 +603,31 @@
     if (hSCM)
     {
-        char szExecPath[MAX_PATH];
-        if (GetModuleFileNameA(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
+        char szExecPath[RTPATH_MAX];
+        if (RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))
         {
             if (fVerbose)
                 RTPrintf("Creating the %s service, binary \"%s\"...\n",
-                         AUTOSTART_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
-
-            SC_HANDLE hSvc = CreateServiceA(hSCM,                            /* hSCManager */
-                                            AUTOSTART_SERVICE_NAME,          /* lpServiceName */
-                                            AUTOSTART_SERVICE_DISPLAY_NAME,  /* lpDisplayName */
+                         sServiceName.c_str(), szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
+
+            /*
+             * Add service name as command line parameter for the service
+             */
+            com::Utf8StrFmt sCmdLine("\"%s\" --service=%s", szExecPath, sServiceName.c_str());
+            SC_HANDLE hSvc = CreateServiceW(hSCM,                            /* hSCManager */
+                                            com::Bstr(sServiceName).raw(),   /* lpServiceName */
+                                            com::Bstr(sDisplayName).raw(),   /* lpDisplayName */
                                             SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
                                             SERVICE_WIN32_OWN_PROCESS,       /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
                                             SERVICE_AUTO_START,              /* dwStartType */
                                             SERVICE_ERROR_NORMAL,            /* dwErrorControl */
-                                            szExecPath,                      /* lpBinaryPathName */
+                                            com::Bstr(sCmdLine).raw(),       /* lpBinaryPathName */
                                             NULL,                            /* lpLoadOrderGroup */
                                             NULL,                            /* lpdwTagId */
                                             NULL,                            /* lpDependencies */
-                                            pszUser,                         /* lpServiceStartName (NULL => LocalSystem) */
-                                            pszPwd);                         /* lpPassword */
+                                            com::Bstr(sUserFullName).raw(),  /* lpServiceStartName (NULL => LocalSystem) */
+                                            com::Bstr(strPwd).raw());        /* lpPassword */
             if (hSvc)
             {
-                RTPrintf("Successfully created the %s service.\n", AUTOSTART_SERVICE_NAME);
+                RTPrintf("Successfully created the %s service.\n", sServiceName.c_str());
                 /** @todo Set the service description or it'll look weird in the vista service manager.
                  *  Anything else that should be configured? Start access or something? */
@@ -631,13 +773,94 @@
 }
 
-static DECLCALLBACK(int) autostartWorkerThread(RTTHREAD hThreadSelf, void *pvUser)
-{
-    RT_NOREF(hThreadSelf, pvUser);
+static int autostartStartVMs()
+{
     int rc = autostartSetup();
 
-    /** @todo Implement config options. */
-    rc = autostartStartMain(NULL);
+    const char *pszConfigFile = RTEnvGet("VBOXAUTOSTART_CONFIG");
+    if (!pszConfigFile)
+        return autostartSvcLogError("Starting VMs failed. VBOXAUTOSTART_CONFIG environment variable is not defined.\n");
+    bool fAllow = false;
+
+    PCFGAST pCfgAst = NULL;
+    rc = autostartParseConfig(pszConfigFile, &pCfgAst);
     if (RT_FAILURE(rc))
-        autostartSvcLogError("Starting VMs failed, rc=%Rrc", rc);
+        return autostartSvcLogError("Starting VMs failed. Failed to parse the config file. Check the access permissions and file structure.\n");
+
+    PCFGAST pCfgAstPolicy = autostartConfigAstGetByName(pCfgAst, "default_policy");
+    /* Check default policy. */
+    if (pCfgAstPolicy)
+    {
+        if (   pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE
+            && (   !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow")
+                || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "deny")))
+        {
+            if (!RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "allow"))
+                fAllow = true;
+        }
+        else
+        {
+            autostartConfigAstDestroy(pCfgAst);
+            return autostartSvcLogError("'default_policy' must be either 'allow' or 'deny'.\n");
+        }
+    }
+
+    com::Utf8Str sUser;
+    rc = autostartGetProcessDomainUser(sUser);
+    if (RT_FAILURE(rc))
+    {
+        autostartConfigAstDestroy(pCfgAst);
+        return autostartSvcLogError("Failed to query username of the process (%Rrc).\n", rc);
+    }
+
+    PCFGAST pCfgAstUser = NULL;
+    for (unsigned i = 0; i < pCfgAst->u.Compound.cAstNodes; i++)
+    {
+        PCFGAST pNode = pCfgAst->u.Compound.apAstNodes[i];
+        com::Utf8Str sDomain;
+        com::Utf8Str sUserTmp;
+        int rc = autostartGetDomainAndUser(pNode->pszKey, sDomain, sUserTmp);
+        if (RT_FAILURE(rc))
+            continue;
+        com::Utf8StrFmt sDomainUser("%s\\%s", sDomain.c_str(), sUserTmp.c_str());
+        if (sDomainUser == sUser)
+        {
+            pCfgAstUser = pNode;
+            break;
+        }
+    }
+
+    if (   pCfgAstUser
+        && pCfgAstUser->enmType == CFGASTNODETYPE_COMPOUND)
+    {
+        pCfgAstPolicy = autostartConfigAstGetByName(pCfgAstUser, "allow");
+        if (pCfgAstPolicy)
+        {
+            if (   pCfgAstPolicy->enmType == CFGASTNODETYPE_KEYVALUE
+                && (   !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true")
+                    || !RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "false")))
+                fAllow = RTStrCmp(pCfgAstPolicy->u.KeyValue.aszValue, "true") == 0;
+            else
+            {
+                autostartConfigAstDestroy(pCfgAst);
+                return autostartSvcLogError("'allow' must be either 'true' or 'false'.\n");
+            }
+        }
+    }
+    else if (pCfgAstUser)
+    {
+        autostartConfigAstDestroy(pCfgAst);
+        return autostartSvcLogError("Invalid config, user is not a compound node.\n");
+    }
+
+    if (!fAllow)
+    {
+        autostartConfigAstDestroy(pCfgAst);
+        return autostartSvcLogError("User is not allowed to autostart VMs.\n");
+    }
+
+    rc = autostartStartMain(pCfgAstUser);
+    autostartConfigAstDestroy(pCfgAst);
+    if (RT_FAILURE(rc))
+        autostartSvcLogError("Starting VMs failed, rc=%Rrc\n", rc);
 
     return rc;
@@ -651,9 +874,9 @@
  *
  * @param   cArgs           Argument count.
- * @param   papszArgs       Argument vector.
- */
-static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPTSTR *papszArgs)
-{
-    RT_NOREF(papszArgs);
+ * @param   papwszArgs      Argument vector.
+ */
+static VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPWSTR *papwszArgs)
+{
+    RT_NOREF(papwszArgs);
     LogFlowFuncEnter();
 
@@ -662,5 +885,5 @@
      */
     Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED);
-    g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExA(AUTOSTART_SERVICE_NAME, autostartSvcWinServiceCtrlHandlerEx, NULL);
+    g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExW(g_bstrServiceName.raw(), autostartSvcWinServiceCtrlHandlerEx, NULL);
     if (g_hSupSvcWinCtrlHandler)
     {
@@ -682,19 +905,20 @@
                     if (autostartSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
                     {
-                        LogFlow(("autostartSvcWinServiceMain: calling RTSemEventMultiWait\n"));
-                        RTTHREAD hWorker;
-                        RTThreadCreate(&hWorker, autostartWorkerThread, NULL, 0, RTTHREADTYPE_DEFAULT, 0, "WorkerThread");
-
-                        LogFlow(("autostartSvcWinServiceMain: woke up\n"));
-                        err = NO_ERROR;
-                        rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
+                        LogFlow(("autostartSvcWinServiceMain: calling autostartStartVMs\n"));
+                        rc = autostartStartVMs();
                         if (RT_SUCCESS(rc))
                         {
-                            LogFlow(("autostartSvcWinServiceMain: woke up\n"));
-                            /** @todo Autostop part. */
+                            LogFlow(("autostartSvcWinServiceMain: done string VMs\n"));
                             err = NO_ERROR;
+                            rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
+                            if (RT_SUCCESS(rc))
+                            {
+                                LogFlow(("autostartSvcWinServiceMain: woke up\n"));
+                                /** @todo Autostop part. */
+                                err = NO_ERROR;
+                            }
+                            else
+                                autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
                         }
-                        else
-                            autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
 
                         autostartShutdown();
@@ -703,5 +927,5 @@
                     {
                         err = GetLastError();
-                        autostartSvcLogError("SetServiceStatus failed, err=%d", err);
+                        autostartSvcLogError("SetServiceStatus failed, err=%u", err);
                     }
 
@@ -718,10 +942,10 @@
         {
             err = GetLastError();
-            autostartSvcLogError("SetServiceStatus failed, err=%d", err);
+            autostartSvcLogError("SetServiceStatus failed, err=%u", err);
         }
         autostartSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
     }
     else
-        autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
+        autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%u", GetLastError());
 
     LogFlowFuncLeave();
@@ -750,7 +974,83 @@
     static const RTGETOPTDEF s_aOptions[] =
     {
-        { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
+        { "--service", 's', RTGETOPT_REQ_STRING },
     };
-    int iArg = 0;
+
+    const char *pszServiceName = NULL;
+    int ch;
+    RTGETOPTUNION Value;
+    RTGETOPTSTATE GetState;
+    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
+    while ((ch = RTGetOpt(&GetState, &Value)))
+    {
+        switch (ch)
+        {
+            case 's':
+                pszServiceName = Value.psz;
+                try
+                {
+                    g_bstrServiceName = com::Bstr(Value.psz);
+                }
+                catch (...)
+                {
+                    autostartSvcLogError("runit failed, service name is not valid utf-8 string or out of memory");
+                    return RTEXITCODE_FAILURE;
+                }
+                break;
+            default:
+                return autostartSvcDisplayGetOptError("runit", ch, &Value);
+        }
+    }
+
+    if (!pszServiceName)
+    {
+        autostartSvcLogError("runit failed, service name is missing");
+        return RTEXITCODE_FAILURE;
+    }
+
+    /*
+     * Register the service with the service control manager
+     * and start dispatching requests from it (all done by the API).
+     */
+    SERVICE_TABLE_ENTRYW const s_aServiceStartTable[] =
+    {
+        { g_bstrServiceName.raw(), autostartSvcWinServiceMain },
+        { NULL, NULL}
+    };
+    if (StartServiceCtrlDispatcherW(&s_aServiceStartTable[0]))
+    {
+        LogFlowFuncLeave();
+        return RTEXITCODE_SUCCESS; /* told to quit, so quit. */
+    }
+
+    DWORD err = GetLastError();
+    switch (err)
+    {
+        case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
+            autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
+            break;
+        default:
+            autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%u", err);
+            break;
+    }
+    return RTEXITCODE_FAILURE;
+}
+
+
+/**
+ * Show the version info.
+ *
+ * @returns RTEXITCODE_SUCCESS.
+ */
+static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)
+{
+    /*
+     * Parse the arguments.
+     */
+    bool fBrief = false;
+    static const RTGETOPTDEF s_aOptions[] =
+    {
+        { "--brief", 'b', RTGETOPT_REQ_NOTHING }
+    };
     int ch;
     RTGETOPTUNION Value;
@@ -760,67 +1060,7 @@
         switch (ch)
         {
-            default:    return autostartSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);
-        }
-    if (iArg != argc)
-        return autostartSvcDisplayTooManyArgsError("runit", argc, argv, iArg);
-
-    /*
-     * Register the service with the service control manager
-     * and start dispatching requests from it (all done by the API).
-     */
-    static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =
-    {
-        { _T(AUTOSTART_SERVICE_NAME), autostartSvcWinServiceMain },
-        { NULL, NULL}
-    };
-    if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))
-    {
-        LogFlowFuncLeave();
-        return RTEXITCODE_SUCCESS; /* told to quit, so quit. */
-    }
-
-    DWORD err = GetLastError();
-    switch (err)
-    {
-        case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
-            autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
-            break;
-        default:
-            autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);
-            break;
-    }
-    return RTEXITCODE_FAILURE;
-}
-
-
-/**
- * Show the version info.
- *
- * @returns RTEXITCODE_SUCCESS.
- */
-static RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)
-{
-    /*
-     * Parse the arguments.
-     */
-    bool fBrief = false;
-    static const RTGETOPTDEF s_aOptions[] =
-    {
-        { "--brief", 'b', RTGETOPT_REQ_NOTHING }
-    };
-    int iArg = 0;
-    int ch;
-    RTGETOPTUNION Value;
-    RTGETOPTSTATE GetState;
-    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
-    while ((ch = RTGetOpt(&GetState, &Value)))
-        switch (ch)
-        {
             case 'b':   fBrief = true;  break;
-            default:    return autostartSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value);
-
-        }
-    if (iArg != argc)
-        return autostartSvcDisplayTooManyArgsError("version", argc, argv, iArg);
+            default:    return autostartSvcDisplayGetOptError("version", ch, &Value);
+        }
 
     /*
Index: trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h
===================================================================
--- trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h	(revision 76582)
+++ trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostart.h	(revision 80569)
@@ -253,5 +253,5 @@
  * @todo    This should later be replaced by the release logger and callback destination(s).
  */
-DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va);
+DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va);
 
 /**
@@ -265,5 +265,5 @@
  * @todo    This should later be replaced by the release logger and callback destination(s).
  */
-DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...);
+DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...);
 
 /**
@@ -297,5 +297,5 @@
  * @param   va          Format arguments.
  */
-DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va);
 
 /**
@@ -305,29 +305,15 @@
  * @param   ...         Format arguments.
  */
-DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...);
-
-/**
- * Deals with RTGetOpt failure.
- *
- * @returns 1
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...);
+
+/**
+ * Deals with RTGetOpt failure, i.e. an syntax error.
+ *
+ * @returns RTEXITCODE_SYNTAX
  * @param   pszAction       The action name.
  * @param   rc              The RTGetOpt return value.
- * @param   argc            The argument count.
- * @param   argv            The argument vector.
- * @param   iArg            The argument index.
  * @param   pValue          The value returned by RTGetOpt.
  */
-DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg, PCRTGETOPTUNION pValue);
-
-/**
- * Bitch about too many arguments (after RTGetOpt stops).
- *
- * @returns RTEXITCODE_FAILURE
- * @param   pszAction       The action name.
- * @param   argc            The argument count.
- * @param   argv            The argument vector.
- * @param   iArg            The argument index.
- */
-DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg);
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue);
 
 DECLHIDDEN(int) autostartSetup();
Index: trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp
===================================================================
--- trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp	(revision 76582)
+++ trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp	(revision 80569)
@@ -94,5 +94,5 @@
 }
 
-DECLHIDDEN(void) autostartSvcLogErrorV(const char *pszFormat, va_list va)
+DECLHIDDEN(RTEXITCODE) autostartSvcLogErrorV(const char *pszFormat, va_list va)
 {
     if (*pszFormat)
@@ -107,7 +107,8 @@
             autostartSvcOsLogStr(pszFormat, AUTOSTARTLOGTYPE_ERROR);
     }
-}
-
-DECLHIDDEN(void) autostartSvcLogError(const char *pszFormat, ...)
+    return RTEXITCODE_FAILURE;
+}
+
+DECLHIDDEN(RTEXITCODE) autostartSvcLogError(const char *pszFormat, ...)
 {
     va_list va;
@@ -115,4 +116,5 @@
     autostartSvcLogErrorV(pszFormat, va);
     va_end(va);
+    return RTEXITCODE_FAILURE;
 }
 
@@ -203,12 +205,13 @@
 }
 
-DECLHIDDEN(void) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayErrorV(const char *pszFormat, va_list va)
 {
     RTStrmPrintf(g_pStdErr, "VBoxSupSvc error: ");
     RTStrmPrintfV(g_pStdErr, pszFormat, va);
     Log(("autostartSvcDisplayErrorV: %s", pszFormat)); /** @todo format it! */
-}
-
-DECLHIDDEN(void) autostartSvcDisplayError(const char *pszFormat, ...)
+    return RTEXITCODE_FAILURE;
+}
+
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayError(const char *pszFormat, ...)
 {
     va_list va;
@@ -216,21 +219,13 @@
     autostartSvcDisplayErrorV(pszFormat, va);
     va_end(va);
-}
-
-DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, int argc, char **argv, int iArg,
-                                                      PCRTGETOPTUNION pValue)
-{
-    RT_NOREF(pValue);
-    autostartSvcDisplayError("%s - RTGetOpt failure, %Rrc (%d): %s\n",
-                       pszAction, rc, rc, iArg < argc ? argv[iArg] : "<null>");
-    return RTEXITCODE_FAILURE;
-}
-
-DECLHIDDEN(RTEXITCODE) autostartSvcDisplayTooManyArgsError(const char *pszAction, int argc, char **argv, int iArg)
-{
-    RT_NOREF(argc);
-    Assert(iArg < argc);
-    autostartSvcDisplayError("%s - Too many arguments: %s\n", pszAction, argv[iArg]);
-    return RTEXITCODE_FAILURE;
+    return RTEXITCODE_FAILURE;
+}
+
+DECLHIDDEN(RTEXITCODE) autostartSvcDisplayGetOptError(const char *pszAction, int rc, PCRTGETOPTUNION pValue)
+{
+    char szMsg[4096];
+    RTGetOptFormatError(szMsg, sizeof(szMsg), rc, pValue);
+    autostartSvcDisplayError("%s - %s", pszAction, szMsg);
+    return RTEXITCODE_SYNTAX;
 }
 
