2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * VirtualBox Autostart Service - Windows Specific Code.
1bb6533bfb0d3d111161e0fb45b04b5e8f2c7c85vboxsync * Copyright (C) 2012-2013 Oracle Corporation
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * available from http://www.virtualbox.org. This file is free software;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * General Public License (GPL) as published by the Free Software
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/*******************************************************************************
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync* Header Files *
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync*******************************************************************************/
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/*******************************************************************************
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync* Defined Constants And Macros *
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync*******************************************************************************/
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/** The service name. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/** The service display name. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync#define AUTOSTART_SERVICE_DISPLAY_NAME "VirtualBox Autostart Service"
b6013430932520fe58eba109db1dfce66a7cad88vboxsyncComPtr<IVirtualBoxClient> g_pVirtualBoxClient = NULL;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/*******************************************************************************
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync* Global Variables *
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync*******************************************************************************/
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/** The service control handler handle. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic SERVICE_STATUS_HANDLE g_hSupSvcWinCtrlHandler = NULL;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/** The service status. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic uint32_t volatile g_u32SupSvcWinStatus = SERVICE_STOPPED;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/** The semaphore the main service thread is waiting on in autostartSvcWinServiceMain. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTSEMEVENTMULTI g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync/*******************************************************************************
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync* Internal Functions *
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync*******************************************************************************/
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * Print out progress on the console.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * This runs the main event queue every now and then to prevent piling up
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * unhandled things (which doesn't cause real problems, just makes things
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * react a little slower than in the ideal case).
b6013430932520fe58eba109db1dfce66a7cad88vboxsyncDECLHIDDEN(HRESULT) showProgress(ComPtr<IProgress> progress)
b6013430932520fe58eba109db1dfce66a7cad88vboxsync using namespace com;
1bb6533bfb0d3d111161e0fb45b04b5e8f2c7c85vboxsync NativeEventQueue::getMainEventQueue()->processEventQueue(0);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync HRESULT hrc = progress->COMGETTER(OperationCount)(&cOperations);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /* setup signal handling if cancelable */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync hrc = progress->COMGETTER(Cancelable)(&fCancelable);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /* process async cancelation */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /* make sure the loop is not too tight */
1bb6533bfb0d3d111161e0fb45b04b5e8f2c7c85vboxsync NativeEventQueue::getMainEventQueue()->processEventQueue(0);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /* complete the line. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsyncDECLHIDDEN(void) autostartSvcOsLogStr(const char *pszMsg, AUTOSTARTLOGTYPE enmLogType)
b6013430932520fe58eba109db1dfce66a7cad88vboxsync HANDLE hEventLog = RegisterEventSourceA(NULL /* local computer */, "VBoxAutostartSvc");
b6013430932520fe58eba109db1dfce66a7cad88vboxsync AssertMsgFailed(("Invalid log type %d\n", enmLogType));
b6013430932520fe58eba109db1dfce66a7cad88vboxsync 0, /* wCategory */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync 0, /* dwDataSize */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Opens the service control manager.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * When this fails, an error message will be displayed.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns Valid handle on success.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * NULL on failure, will display an error message.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param pszAction The action which is requesting access to SCM.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwAccess The desired access.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic SC_HANDLE autostartSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SC_HANDLE hSCM = OpenSCManager(NULL /* lpMachineName*/, NULL /* lpDatabaseName */, dwAccess);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("%s - OpenSCManager failure: access denied\n", pszAction);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("%s - OpenSCManager failure: %d\n", pszAction, err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Opens the service.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Last error is preserved on failure and set to 0 on success.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns Valid service handle on success.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * NULL on failure, will display an error message unless it's ignored.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param pszAction The action which is requesting access to the service.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwSCMAccess The service control manager access.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwSVCAccess The desired service access.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param cIgnoredErrors The number of ignored errors.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param ... Errors codes that should not cause a message to be displayed.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic SC_HANDLE autostartSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync unsigned cIgnoredErrors, ...)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SC_HANDLE hSCM = autostartSvcWinOpenSCManager(pszAction, dwSCMAccess);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync SC_HANDLE hSvc = OpenServiceA(hSCM, AUTOSTART_SERVICE_NAME, dwSVCAccess);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("%s - OpenService failure: access denied\n", pszAction);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("%s - OpenService failure: %d\n", pszAction, err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinInterrogate(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"interrogate\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinStop(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"stop\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinContinue(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"continue\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinPause(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"pause\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinStart(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"start\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinQueryDescription(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"qdescription\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinQueryConfig(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"qconfig\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinDisable(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"disable\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinEnable(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VBoxAutostartSvc: The \"enable\" action is not implemented.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Handle the 'delete' action.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argc The action argument count.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argv The action argument vector.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic int autostartSvcWinDelete(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Parse the arguments.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Create the service.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SC_HANDLE hSvc = autostartSvcWinOpenService("delete", SERVICE_CHANGE_CONFIG, DELETE,
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("delete - DeleteService failed, err=%d.\n", GetLastError());
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTPrintf("The service %s was not installed, nothing to be done.", AUTOSTART_SERVICE_NAME);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTPrintf("Successfully deleted the %s service.\n", AUTOSTART_SERVICE_NAME);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Handle the 'create' action.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns 0 or 1.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argc The action argument count.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argv The action argument vector.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinCreate(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Parse the arguments.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayTooManyArgsError("create", argc, argv, iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Create the service.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SC_HANDLE hSCM = autostartSvcWinOpenSCManager("create", SC_MANAGER_CREATE_SERVICE); /*SC_MANAGER_ALL_ACCESS*/
b6013430932520fe58eba109db1dfce66a7cad88vboxsync if (GetModuleFileNameA(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("Creating the %s service, binary \"%s\"...\n",
b6013430932520fe58eba109db1dfce66a7cad88vboxsync AUTOSTART_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync SC_HANDLE hSvc = CreateServiceA(hSCM, /* hSCManager */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync AUTOSTART_SERVICE_DISPLAY_NAME, /* lpDisplayName */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync SERVICE_WIN32_OWN_PROCESS, /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync pszUser, /* lpServiceStartName (NULL => LocalSystem) */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTPrintf("Successfully created the %s service.\n", AUTOSTART_SERVICE_NAME);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync /** @todo Set the service description or it'll look weird in the vista service manager.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Anything else that should be configured? Start access or something? */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("create - The service already exists.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("create - CreateService failed, err=%d.\n", GetLastError());
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcDisplayError("create - Failed to obtain the executable path: %d\n", GetLastError());
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Sets the service status, just a SetServiceStatus Wrapper.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns See SetServiceStatus.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwStatus The current status.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param iWaitHint The wait hint, if < 0 then supply a default.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwExitCode The service exit code.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic bool autostartSvcWinSetServiceStatus(DWORD dwStatus, int iWaitHint, DWORD dwExitCode)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SvcStatus.dwWaitHint = iWaitHint >= 0 ? iWaitHint : 3000;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync LogFlow(("autostartSvcWinSetServiceStatus: %d -> %d\n", g_u32SupSvcWinStatus, dwStatus));
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return SetServiceStatus(g_hSupSvcWinCtrlHandler, &SvcStatus) != FALSE;
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Service control handler (extended).
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns Windows status (see HandlerEx).
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @retval NO_ERROR if handled.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @retval ERROR_CALL_NOT_IMPLEMENTED if not handled.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwControl The control code.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param dwEventType Event type. (specific to the control?)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param pvEventData Event data, specific to the event.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param pvContext The context pointer registered with the handler.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Currently not used.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic DWORD WINAPI autostartSvcWinServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID pvEventData, LPVOID pvContext)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync LogFlow(("autostartSvcWinServiceCtrlHandlerEx: dwControl=%#x dwEventType=%#x pvEventData=%p\n",
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Interrogate the service about it's current status.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * MSDN says that this should just return NO_ERROR and does
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * not need to set the status again.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Request to stop the service.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Check if the real services can be stopped and then tell them to stop.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcWinSetServiceStatus(SERVICE_STOP_PENDING, 3000, NO_ERROR);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * Notify the main thread that we're done, it will wait for the
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * VMs to stop, and set the windows service status to SERVICE_STOPPED
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * and return.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogError("SERVICE_CONTROL_STOP: RTSemEventMultiSignal failed, %Rrc\n", rc);
b6013430932520fe58eba109db1dfce66a7cad88vboxsyncstatic int autostartWorker(RTTHREAD ThreadSelf, void *pvUser)
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /** @todo: Implement config options. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogError("Starting VMs failed, rc=%Rrc", rc);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Windows Service Main.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * This is invoked when the service is started and should not return until
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * the service has been stopped.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param cArgs Argument count.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param papszArgs Argument vector.
b6013430932520fe58eba109db1dfce66a7cad88vboxsyncstatic VOID WINAPI autostartSvcWinServiceMain(DWORD cArgs, LPTSTR *papszArgs)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Register the control handler function for the service and report to SCM.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerExA(AUTOSTART_SERVICE_NAME, autostartSvcWinServiceCtrlHandlerEx, NULL);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync if (autostartSvcWinSetServiceStatus(SERVICE_START_PENDING, 3000, NO_ERROR))
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Create the event semaphore we'll be waiting on and
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * then instantiate the actual services.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync int rc = RTSemEventMultiCreate(&g_hSupSvcWinEvent);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync * Update the status and enter the work loop.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync if (autostartSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
b6013430932520fe58eba109db1dfce66a7cad88vboxsync LogFlow(("autostartSvcWinServiceMain: calling RTSemEventMultiWait\n"));
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTThreadCreate(&hWorker, autostartWorker, NULL, 0, RTTHREADTYPE_DEFAULT, 0, "WorkerThread");
b6013430932520fe58eba109db1dfce66a7cad88vboxsync LogFlow(("autostartSvcWinServiceMain: woke up\n"));
b6013430932520fe58eba109db1dfce66a7cad88vboxsync rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync LogFlow(("autostartSvcWinServiceMain: woke up\n"));
b6013430932520fe58eba109db1dfce66a7cad88vboxsync /** @todo: Autostop part. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogError("SetServiceStatus failed, err=%d", err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcLogError("RTSemEventMultiCreate failed, rc=%Rrc", rc);
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcLogTooManyArgsError("main", cArgs, NULL, 0);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcLogError("SetServiceStatus failed, err=%d", err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Handle the 'create' action.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns RTEXITCODE_SUCCESS or RTEXITCODE_FAILURE.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argc The action argument count.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argv The action argument vector.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic int autostartSvcWinRunIt(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Initialize release logging.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync /** @todo release logging of the system-wide service. */
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Parse the arguments.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync default: return autostartSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayTooManyArgsError("runit", argc, argv, iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Register the service with the service control manager
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * and start dispatching requests from it (all done by the API).
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =
b6013430932520fe58eba109db1dfce66a7cad88vboxsync { _T(AUTOSTART_SERVICE_NAME), autostartSvcWinServiceMain },
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return RTEXITCODE_SUCCESS; /* told to quit, so quit. */
b6013430932520fe58eba109db1dfce66a7cad88vboxsync autostartSvcWinServiceMain(0, NULL);//autostartSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Show the version info.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns RTEXITCODE_SUCCESS.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsyncstatic RTEXITCODE autostartSvcWinShowVersion(int argc, char **argv)
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Parse the arguments.
b6013430932520fe58eba109db1dfce66a7cad88vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync default: return autostartSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcDisplayTooManyArgsError("version", argc, argv, iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Do the printing.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VirtualBox Autostart Service Version %s\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "(C) 2012 Oracle Corporation\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "All rights reserved.\n",
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Show the usage help screen.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns RTEXITCODE_SUCCESS.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync RTPrintf("VirtualBox Autostart Service Version %s\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "(C) 2012 Oracle Corporation\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "All rights reserved.\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "VBoxAutostartSvc\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync " Runs the service.\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "VBoxAutostartSvc <version|-v|--version> [-brief]\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync " Displays the version.\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "VBoxAutostartSvc <help|-?|-h|--help> [...]\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync " Displays this help screen.\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync "VBoxAutostartSvc <install|/RegServer|/i>\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync " Installs the service.\n"
b6013430932520fe58eba109db1dfce66a7cad88vboxsync "VBoxAutostartSvc <uninstall|delete|/UnregServer|/u>\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync " Uninstalls the service.\n"
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * VBoxAutostart main(), Windows edition.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @returns 0 on success.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argc Number of arguments in argv.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * @param argv Argument vector.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Initialize the IPRT first of all.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync autostartSvcLogError("RTR3InitExe failed with rc=%Rrc", rc);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Parse the initial arguments to determine the desired action.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinShowVersion(argc - iArg - 1, argv + iArg + 1);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync * Dispatch it.
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinRunIt(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinCreate(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinDelete(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinEnable(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinDisable(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinQueryConfig(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinQueryDescription(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinStart(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinPause(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinContinue(argc - iArg, argv + iArg);
2e3ce94efec87c786a0c87a6f7739faccb3a7e66vboxsync return autostartSvcWinStop(argc - iArg, argv + iArg);