1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox Support Service - Windows Specific Code.
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2011 Oracle Corporation
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * available from http://www.virtualbox.org. This file is free software;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * you can redistribute it and/or modify it under the terms of the GNU
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * General Public License (GPL) as published by the Free Software
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The contents of this file may alternatively be used under the terms
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * of the Common Development and Distribution License Version 1.0
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox OSE distribution, in which case the provisions of the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * CDDL are applicable instead of those of the GPL.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * You may elect to license modified versions of this file under the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * terms and conditions of either the GPL or the CDDL or both.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Header Files *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Defined Constants And Macros *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service name. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service display name. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#define SUPSVC_SERVICE_DISPLAY_NAME "VirtualBox Support Service"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Global Variables *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service control handler handle. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SERVICE_STATUS_HANDLE g_hSupSvcWinCtrlHandler = NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service status. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic uint32_t volatile g_u32SupSvcWinStatus = SERVICE_STOPPED;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The semaphore the main service thread is waiting on in supSvcWinServiceMain. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Internal Functions *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Opens the service control manager.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * When this fails, an error message will be displayed.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Valid handle on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * NULL on failure, will display an error message.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pszAction The action which is requesting access to SCM.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwAccess The desired access.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = OpenSCManager(NULL /* lpMachineName*/, NULL /* lpDatabaseName */, dwAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenSCManager failure: access denied\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenSCManager failure: %d\n", pszAction, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Opens the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Last error is preserved on failure and set to 0 on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Valid service handle on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * NULL on failure, will display an error message unless it's ignored.
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @param pszAction The action which is requesting access to the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwSCMAccess The service control manager access.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwSVCAccess The desired service access.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param cIgnoredErrors The number of ignored errors.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param ... Errors codes that should not cause a message to be displayed.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned cIgnoredErrors, ...)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = supSvcWinOpenSCManager(pszAction, dwSCMAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = OpenService(hSCM, SUPSVC_SERVICE_NAME, dwSVCAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: access denied\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: %d\n", pszAction, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync HANDLE hEventLog = RegisterEventSource(NULL /* local computer */, "VBoxSupSvc");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 0, /* wCategory */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 0, /* dwDataSize */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinInterrogate(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"interrogate\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"stop\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"continue\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"pause\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"start\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinQueryDescription(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"qdescription\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinQueryConfig(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"qconfig\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"disable\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"enable\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'delete' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync return supSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync return supSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = supSvcWinOpenService("delete", SERVICE_CHANGE_CONFIG, DELETE,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Successfully deleted the %s service.\n", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("delete - DeleteService failed, err=%d.\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("The service %s was not installed, nothing to be done.", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Successfully deleted the %s service.\n", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'create' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("create", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = supSvcWinOpenSCManager("create", SC_MANAGER_CREATE_SERVICE); /*SC_MANAGER_ALL_ACCESS*/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (GetModuleFileName(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Creating the %s service, binary \"%s\"...\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVC_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = CreateService(hSCM, /* hSCManager */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_WIN32_OWN_PROCESS, /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Successfully created the %s service.\n", SUPSVC_SERVICE_NAME);
46fd1b35e55cbd736b7abe0d856a940f0336eb81vboxsync /** @todo Set the service description or it'll look weird in the vista service manager.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Anything else that should be configured? Start access or something? */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - The service already exists.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - CreateService failed, err=%d.\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - Failed to obtain the executable path: %d\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Sets the service status, just a SetServiceStatus Wrapper.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns See SetServiceStatus.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwStatus The current status.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param iWaitHint The wait hint, if < 0 then supply a default.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwExitCode The service exit code.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic bool supSvcWinSetServiceStatus(DWORD dwStatus, int iWaitHint, DWORD dwExitCode)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwWaitHint = iWaitHint >= 0 ? iWaitHint : 3000;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinSetServiceStatus: %d -> %d\n", g_u32SupSvcWinStatus, dwStatus));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return SetServiceStatus(g_hSupSvcWinCtrlHandler, &SvcStatus) != FALSE;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Service control handler (extended).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Windows status (see HandlerEx).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @retval NO_ERROR if handled.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @retval ERROR_CALL_NOT_IMPLEMENTED if not handled.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwControl The control code.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwEventType Event type. (specific to the control?)
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * @param pvEventData Event data, specific to the event.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pvContext The context pointer registered with the handler.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Currently not used.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic DWORD WINAPI supSvcWinServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID pvEventData, LPVOID pvContext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinServiceCtrlHandlerEx: dwControl=%#x dwEventType=%#x pvEventData=%p\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Interrogate the service about it's current status.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * MSDN says that this should just return NO_ERROR and does
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * not need to set the status again.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Request to stop the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Check if the real services can be stopped and then tell them to stop.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcWinSetServiceStatus(SERVICE_STOP_PENDING, 3000, NO_ERROR);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Notify the main thread that we're done, it will wait for the
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * real services to stop, destroy them, and finally set the windows
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * service status to SERVICE_STOPPED and return.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SERVICE_CONTROL_STOP: RTSemEventMultiSignal failed, %Rrc\n", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Windows Service Main.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This is invoked when the service is started and should not return until
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the service has been stopped.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param cArgs Argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param papszArgs Argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic VOID WINAPI supSvcWinServiceMain(DWORD cArgs, LPSTR *papszArgs)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Register the control handler function for the service and report to SCM.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerEx(SUPSVC_SERVICE_NAME, supSvcWinServiceCtrlHandlerEx, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (supSvcWinSetServiceStatus(SERVICE_START_PENDING, 3000, NO_ERROR))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 1; /* the first arg is the service name */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync && (ch = RTGetOpt(cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: rc = supSvcLogGetOptError("main", ch, cArgs, papszArgs, iArg, &Value); break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcLogTooManyArgsError("main", cArgs, papszArgs, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the event semaphore we'll be waiting on and
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * then instantiate the actual services.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTSemEventMultiCreate(&g_hSupSvcWinEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Update the status and enter the work loop.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The work loop is just a dummy wait here as the services run
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * in independent threads.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (supSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinServiceMain: calling RTSemEventMultiWait\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SetServiceStatus failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Destroy the service instances, stopping them if
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * they're still running (weird failure cause).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RTSemEventMultiCreate failed, rc=%Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* else: bad args */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SetServiceStatus failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'create' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Initialize release logging.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** @todo release logging of the system-wide service. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("runit", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Register the service with the service control manager
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * and start dispatching requests from it (all done by the API).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 0; /* told to quit, so quit. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Show the version info.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinShowVersion(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("version", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Do the printing.
f313ed48a0cc2d9d12580dc9412291ae15773f02vboxsync "(C) 2008-2010 Oracle Corporation\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "All rights reserved.\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Show the usage help screen.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0.
f313ed48a0cc2d9d12580dc9412291ae15773f02vboxsync "(C) 2008-2010 Oracle Corporation\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "All rights reserved.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "VBoxSupSvc\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync " Runs the service.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "VBoxSupSvc <version|-v|--version> [-brief]\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync " Displays the version.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "VBoxSupSvc <help|-?|-h|--help> [...]\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync " Displays this help screen.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "VBoxSupSvc <install|/RegServer|/i>\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync " Installs the service.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "VBoxSupSvc <install|delete|/UnregServer|/u>\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync " Uninstalls the service.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VBoxSUPSvc main(), Windows edition.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc Number of arguments in argv.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv Argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Initialize the IPRT first of all.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTEnvSet("VBOX_LOG_DEST", "file=E:\\temp\\VBoxSupSvc.log");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTEnvSet("VBOX_LOG_FLAGS", "unbuffered thread msprog");
230bd8589bba39933ac5ec21482d6186d675e604vboxsync supSvcLogError("RTR3InitExe failed with rc=%Rrc", rc);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Parse the initial arguments to determine the desired action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinShowVersion(argc - iArg - 1, argv + iArg + 1);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Dispatch it.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinQueryConfig(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinQueryDescription(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinContinue(argc - iArg, argv + iArg);