1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/* $Id$ */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** @file
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VirtualBox Support Service - Windows Specific Code.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2008-2011 Oracle Corporation
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
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 *
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 *
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
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Header Files *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#define LOG_GROUP LOG_GROUP_SUP
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <Windows.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <VBox/log.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <VBox/version.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/string.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/mem.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/initterm.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/stream.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/getopt.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include <iprt/semaphore.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#ifdef DEBUG_bird
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync# include <iprt/env.h>
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#endif
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#include "../SUPSvcInternal.h"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Defined Constants And Macros *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service name. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#define SUPSVC_SERVICE_NAME "VBoxSupSvc"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/** The service display name. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#define SUPSVC_SERVICE_DISPLAY_NAME "VirtualBox Support Service"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
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
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/*******************************************************************************
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync* Internal Functions *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync*******************************************************************************/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Opens the service control manager.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * When this fails, an error message will be displayed.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Valid handle on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * NULL on failure, will display an error message.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param pszAction The action which is requesting access to SCM.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param dwAccess The desired access.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenSCManager(const char *pszAction, DWORD dwAccess)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = OpenSCManager(NULL /* lpMachineName*/, NULL /* lpDatabaseName */, dwAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSCM == NULL)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DWORD err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (err)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case ERROR_ACCESS_DENIED:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenSCManager failure: access denied\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenSCManager failure: %d\n", pszAction, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return hSCM;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Opens the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Last error is preserved on failure and set to 0 on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Valid service handle on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * NULL on failure, will display an error message unless it's ignored.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
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.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic SC_HANDLE supSvcWinOpenService(const char *pszAction, DWORD dwSCMAccess, DWORD dwSVCAccess,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync unsigned cIgnoredErrors, ...)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = supSvcWinOpenSCManager(pszAction, dwSCMAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!hSCM)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return NULL;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = OpenService(hSCM, SUPSVC_SERVICE_NAME, dwSVCAccess);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSvc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync CloseServiceHandle(hSCM);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SetLastError(0);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DWORD err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fIgnored = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync va_list va;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync va_start(va, cIgnoredErrors);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while (!fIgnored && cIgnoredErrors-- > 0)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync fIgnored = va_arg(va, long) == err;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync va_end(va);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!fIgnored)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (err)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case ERROR_ACCESS_DENIED:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: access denied\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case ERROR_SERVICE_DOES_NOT_EXIST:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: The service does not exist. Reinstall it.\n", pszAction);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("%s - OpenService failure: %d\n", pszAction, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync CloseServiceHandle(hSCM);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SetLastError(err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return hSvc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncvoid supSvcOsLogErrorStr(const char *pszMsg)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync HANDLE hEventLog = RegisterEventSource(NULL /* local computer */, "VBoxSupSvc");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertReturnVoid(hEventLog != NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync const char *apsz[2];
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync apsz[0] = "VBoxSupSvc";
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync apsz[1] = pszMsg;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync BOOL fRc = ReportEvent(hEventLog, /* hEventLog */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync EVENTLOG_ERROR_TYPE, /* wType */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 0, /* wCategory */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 0 /** @todo mc */, /* dwEventID */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL, /* lpUserSid */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RT_ELEMENTS(apsz), /* wNumStrings */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 0, /* dwDataSize */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync apsz, /* lpStrings */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL); /* lpRawData */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertMsg(fRc, ("%d\n", GetLastError()));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DeregisterEventSource(hEventLog);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinInterrogate(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"interrogate\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinStop(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"stop\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinContinue(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"continue\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinPause(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"pause\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinStart(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"start\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinQueryDescription(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"qdescription\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinQueryConfig(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"qconfig\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinDisable(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"disable\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinEnable(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VBoxSupSvc: The \"enable\" action is not implemented.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'delete' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinDelete(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fVerbose = false;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync static const RTGETOPTDEF s_aOptions[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int ch;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTUNION Value;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTSTATE GetState;
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync while ((ch = RTGetOpt(&GetState, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (ch)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync case 'v':
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync fVerbose = true;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync break;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync case VINF_GETOPT_NOT_OPTION:
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync return supSvcDisplayTooManyArgsError("delete", argc, argv, iArg);
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync default:
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync return supSvcDisplayGetOptError("delete", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = supSvcWinOpenService("delete", SERVICE_CHANGE_CONFIG, DELETE,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync 1, ERROR_SERVICE_DOES_NOT_EXIST);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSvc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (DeleteService(hSvc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Successfully deleted the %s service.\n", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("delete - DeleteService failed, err=%d.\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync CloseServiceHandle(hSvc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (fVerbose)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("The service %s was not installed, nothing to be done.", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Successfully deleted the %s service.\n", SUPSVC_SERVICE_NAME);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'create' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinCreate(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fVerbose = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static const RTOPTIONDEF s_aOptions[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int ch;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTUNION Value;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (ch)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case 'v': fVerbose = true; break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (iArg != argc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("create", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSCM = supSvcWinOpenSCManager("create", SC_MANAGER_CREATE_SERVICE); /*SC_MANAGER_ALL_ACCESS*/
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSCM)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync char szExecPath[MAX_PATH];
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (GetModuleFileName(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (fVerbose)
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
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SC_HANDLE hSvc = CreateService(hSCM, /* hSCManager */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVC_SERVICE_NAME, /* lpServiceName */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SUPSVC_SERVICE_DISPLAY_NAME, /* lpDisplayName */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_WIN32_OWN_PROCESS, /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_DEMAND_START/*_AUTO*/, /* dwStartType */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_ERROR_NORMAL, /* dwErrorControl */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync szExecPath, /* lpBinaryPathName */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL, /* lpLoadOrderGroup */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL, /* lpdwTagId */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL, /* lpDependencies */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL, /* lpServiceStartName (=> LocalSystem) */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NULL); /* lpPassword */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (hSvc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
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 rc = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync CloseServiceHandle(hSvc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DWORD err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (err)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case ERROR_SERVICE_EXISTS:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - The service already exists.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - CreateService failed, err=%d.\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync CloseServiceHandle(hSvc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("create - Failed to obtain the executable path: %d\n", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return rc;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Sets the service status, just a SetServiceStatus Wrapper.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
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.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic bool supSvcWinSetServiceStatus(DWORD dwStatus, int iWaitHint, DWORD dwExitCode)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SERVICE_STATUS SvcStatus;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwWin32ExitCode = dwExitCode;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwServiceSpecificExitCode = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwWaitHint = iWaitHint >= 0 ? iWaitHint : 3000;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwCurrentState = dwStatus;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinSetServiceStatus: %d -> %d\n", g_u32SupSvcWinStatus, dwStatus));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync g_u32SupSvcWinStatus = dwStatus;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (dwStatus)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_START_PENDING:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwControlsAccepted = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static DWORD dwCheckPoint = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (dwStatus)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_RUNNING:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_STOPPED:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwCheckPoint = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync SvcStatus.dwCheckPoint = ++dwCheckPoint;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return SetServiceStatus(g_hSupSvcWinCtrlHandler, &SvcStatus) != FALSE;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Service control handler (extended).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns Windows status (see HandlerEx).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @retval NO_ERROR if handled.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @retval ERROR_CALL_NOT_IMPLEMENTED if not handled.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
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.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic DWORD WINAPI supSvcWinServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID pvEventData, LPVOID pvContext)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinServiceCtrlHandlerEx: dwControl=%#x dwEventType=%#x pvEventData=%p\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync dwControl, dwEventType, pvEventData));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (dwControl)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
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 */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_INTERROGATE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return NO_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Request to stop the service.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_STOP:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Check if the real services can be stopped and then tell them to stop.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcWinSetServiceStatus(SERVICE_STOP_PENDING, 3000, NO_ERROR);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = supSvcTryStopServices();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
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 */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventMultiSignal(g_hSupSvcWinEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SERVICE_CONTROL_STOP: RTSemEventMultiSignal failed, %Rrc\n", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return NO_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_PAUSE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_CONTINUE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_SHUTDOWN:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_PARAMCHANGE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_NETBINDADD:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_NETBINDREMOVE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_NETBINDENABLE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_NETBINDDISABLE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_DEVICEEVENT:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_HARDWAREPROFILECHANGE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_POWEREVENT:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_SESSIONCHANGE:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#ifdef SERVICE_CONTROL_PRESHUTDOWN /* vista */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case SERVICE_CONTROL_PRESHUTDOWN:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#endif
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return ERROR_CALL_NOT_IMPLEMENTED;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NOREF(dwEventType);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NOREF(pvEventData);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync NOREF(pvContext);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return NO_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Windows Service Main.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * This is invoked when the service is started and should not return until
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * the service has been stopped.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param cArgs Argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param papszArgs Argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic VOID WINAPI supSvcWinServiceMain(DWORD cArgs, LPSTR *papszArgs)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlowFuncEnter();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Register the control handler function for the service and report to SCM.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync Assert(g_u32SupSvcWinStatus == SERVICE_STOPPED);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync g_hSupSvcWinCtrlHandler = RegisterServiceCtrlHandlerEx(SUPSVC_SERVICE_NAME, supSvcWinServiceCtrlHandlerEx, NULL);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (g_hSupSvcWinCtrlHandler)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DWORD err = ERROR_GEN_FAILURE;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (supSvcWinSetServiceStatus(SERVICE_START_PENDING, 3000, NO_ERROR))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static const RTOPTIONDEF s_aOptions[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 1; /* the first arg is the service name */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int ch;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = 0;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTUNION Value;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ( !rc
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync && (ch = RTGetOpt(cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (ch)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: rc = supSvcLogGetOptError("main", ch, cArgs, papszArgs, iArg, &Value); break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (iArg != cArgs)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcLogTooManyArgsError("main", cArgs, papszArgs, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (!rc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Create the event semaphore we'll be waiting on and
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * then instantiate the actual services.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int rc = RTSemEventMultiCreate(&g_hSupSvcWinEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = supSvcCreateAndStartServices();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Update the status and enter the work loop.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * The work loop is just a dummy wait here as the services run
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * in independent threads.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (supSvcWinSetServiceStatus(SERVICE_RUNNING, 0, 0))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinServiceMain: calling RTSemEventMultiWait\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync rc = RTSemEventMultiWait(g_hSupSvcWinEvent, RT_INDEFINITE_WAIT);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_SUCCESS(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlow(("supSvcWinServiceMain: woke up\n"));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync err = NO_ERROR;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RTSemEventWait failed, rc=%Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SetServiceStatus failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Destroy the service instances, stopping them if
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * they're still running (weird failure cause).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcStopAndDestroyServices();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTSemEventMultiDestroy(g_hSupSvcWinEvent);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync g_hSupSvcWinEvent = NIL_RTSEMEVENTMULTI;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RTSemEventMultiCreate failed, rc=%Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /* else: bad args */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("SetServiceStatus failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcWinSetServiceStatus(SERVICE_STOPPED, 0, err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("RegisterServiceCtrlHandlerEx failed, err=%d", GetLastError());
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlowFuncLeave();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Handle the 'create' action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 or 1.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc The action argument count.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv The action argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinRunIt(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlowFuncEnter();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Initialize release logging.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /** @todo release logging of the system-wide service. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static const RTOPTIONDEF s_aOptions[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { "--dummy", 'd', RTGETOPT_REQ_NOTHING }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int ch;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTUNION Value;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (ch)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("runit", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (iArg != argc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("runit", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Register the service with the service control manager
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * and start dispatching requests from it (all done by the API).
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static SERVICE_TABLE_ENTRY const s_aServiceStartTable[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { SUPSVC_SERVICE_NAME, supSvcWinServiceMain },
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { NULL, NULL}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (StartServiceCtrlDispatcher(&s_aServiceStartTable[0]))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync LogFlowFuncLeave();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 0; /* told to quit, so quit. */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync DWORD err = GetLastError();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (err)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case ERROR_FAILED_SERVICE_CONTROLLER_CONNECT:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcDisplayError("Cannot run a service from the command line. Use the 'start' action to start it the right way.\n");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync supSvcLogError("StartServiceCtrlDispatcher failed, err=%d", err);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Show the version info.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinShowVersion(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Parse the arguments.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync bool fBrief = false;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync static const RTOPTIONDEF s_aOptions[] =
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync { "--brief", 'b', RTGETOPT_REQ_NOTHING }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync };
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int ch;
83dc9ca94cd3c31dabc33a35b945de124d43aaeavboxsync RTGETOPTUNION Value;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (ch)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case 'b': fBrief = true; break;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default: return supSvcDisplayGetOptError("version", ch, argc, argv, iArg, &Value);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (iArg != argc)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcDisplayTooManyArgsError("version", argc, argv, iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Do the printing.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (fBrief)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("%s\n", VBOX_VERSION_STRING);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VirtualBox System Service Version %s\n"
f313ed48a0cc2d9d12580dc9412291ae15773f02vboxsync "(C) 2008-2010 Oracle Corporation\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "All rights reserved.\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync VBOX_VERSION_STRING);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Show the usage help screen.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncstatic int supSvcWinShowHelp(void)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("VirtualBox System Service Version %s\n"
f313ed48a0cc2d9d12580dc9412291ae15773f02vboxsync "(C) 2008-2010 Oracle Corporation\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "All rights reserved.\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "\n",
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync VBOX_VERSION_STRING);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTPrintf("Usage:\n"
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync "\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 "\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 );
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 0;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync/**
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * VBoxSUPSvc main(), Windows edition.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @returns 0 on success.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync *
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argc Number of arguments in argv.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * @param argv Argument vector.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsyncint main(int argc, char **argv)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync{
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Initialize the IPRT first of all.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#ifdef DEBUG_bird
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTEnvSet("VBOX_LOG", "sup=~0");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTEnvSet("VBOX_LOG_DEST", "file=E:\\temp\\VBoxSupSvc.log");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync RTEnvSet("VBOX_LOG_FLAGS", "unbuffered thread msprog");
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync#endif
230bd8589bba39933ac5ec21482d6186d675e604vboxsync int rc = RTR3InitExe(argc, &argv, 0);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (RT_FAILURE(rc))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
230bd8589bba39933ac5ec21482d6186d675e604vboxsync supSvcLogError("RTR3InitExe failed with rc=%Rrc", rc);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Parse the initial arguments to determine the desired action.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enum
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_RunIt,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Create,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Delete,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Enable,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Disable,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_QueryConfig,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_QueryDescription,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Start,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Pause,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Continue,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Stop,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_Interrogate,
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync kSupSvcAction_End
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync } enmAction = kSupSvcAction_RunIt;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync int iArg = 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if (argc > 1)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync if ( !stricmp(argv[iArg], "/RegServer")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "install")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/i"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Create;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if ( !stricmp(argv[iArg], "/UnregServer")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/u")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "uninstall")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "delete"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Delete;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "enable"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Enable;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "disable"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Disable;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "qconfig"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_QueryConfig;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "qdescription"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_QueryDescription;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if ( !stricmp(argv[iArg], "start")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/t"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Start;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "pause"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Start;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "continue"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Continue;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "stop"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Stop;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if (!stricmp(argv[iArg], "interrogate"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync enmAction = kSupSvcAction_Interrogate;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if ( !stricmp(argv[iArg], "help")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "?")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/?")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "-?")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/h")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "-h")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/help")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "-help")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "--help"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinShowHelp();
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else if ( !stricmp(argv[iArg], "version")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/v")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "-v")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "/version")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "-version")
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync || !stricmp(argv[iArg], "--version"))
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinShowVersion(argc - iArg - 1, argv + iArg + 1);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync else
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync iArg--;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync iArg++;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync /*
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync * Dispatch it.
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync */
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync switch (enmAction)
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync {
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_RunIt:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinRunIt(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Create:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinCreate(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Delete:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinDelete(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Enable:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinEnable(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Disable:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinDisable(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_QueryConfig:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinQueryConfig(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_QueryDescription:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinQueryDescription(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Start:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinStart(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Pause:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinPause(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Continue:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinContinue(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Stop:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinStop(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync case kSupSvcAction_Interrogate:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return supSvcWinInterrogate(argc - iArg, argv + iArg);
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync default:
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync AssertMsgFailed(("enmAction=%d\n", enmAction));
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync return 1;
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync }
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync}
1c2c968fd241148110002d75b2c0fdeddc211e14vboxsync