VBoxService-win.cpp revision c58f1213e628a545081c70e26c6b67a841cff880
/* $Id$ */
/** @file
* VBoxService - Guest Additions Service Skeleton, Windows Specific Parts.
*/
/*
* Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <VBox/VBoxGuestLib.h>
#include "VBoxServiceInternal.h"
#include <Windows.h>
#include <process.h>
#include <aclapi.h>
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/*******************************************************************************
* Global Variables *
*******************************************************************************/
static DWORD g_dwWinServiceLastStatus = 0;
/** The semaphore for the dummy Windows service. */
static SERVICE_TABLE_ENTRY const g_aServiceTable[] =
{
};
/**
* @todo Format code style.
* @todo Add full unicode support.
* @todo Add event log capabilities / check return values.
*/
{
if (NULL == pszObjName)
return ERROR_INVALID_PARAMETER;
/* Get a pointer to the existing DACL. */
if (ERROR_SUCCESS != dwRes)
{
if (dwRes == ERROR_FILE_NOT_FOUND)
VBoxServiceError("AddAceToObjectsSecurityDescriptor: Object not found/installed: %s\n", pszObjName);
else
goto l_Cleanup;
}
/* Initialize an EXPLICIT_ACCESS structure for the new ACE. */
/* Create a new ACL that merges the new ACE into the existing DACL. */
if (ERROR_SUCCESS != dwRes)
{
goto l_Cleanup;
}
/* Attach the new ACL as the object's DACL. */
if (ERROR_SUCCESS != dwRes)
{
goto l_Cleanup;
}
/** @todo get rid of that spaghetti jump ... */
return dwRes;
}
/** Reports our current status to the SCM. */
{
if (g_hWinServiceStatus == NULL) /* Program could be in testing mode, so no service environment available. */
return FALSE;
/* Don't accept controls when in start pending state. */
{
#ifndef TARGET_NT4
/* Don't use SERVICE_ACCEPT_SESSIONCHANGE on Windows 2000.
* This makes SCM angry. */
char szOSVersion[32];
szOSVersion, sizeof(szOSVersion));
if (RT_SUCCESS(rc))
{
}
else
#endif
}
if (!fStatusSet)
VBoxServiceError("Error reporting service status=%ld (controls=%x, checkpoint=%ld) to SCM: %ld\n",
return fStatusSet;
}
/**
* Reports SERVICE_STOP_PENDING to SCM.
*
* @param uCheckPoint Some number.
*/
{
}
{
#ifndef TARGET_NT4
/* On W2K+ there's ChangeServiceConfig2() which lets us set some fields
like a longer service description. */
/** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */
if (!ChangeServiceConfig2(hService,
SERVICE_CONFIG_DESCRIPTION, /* Service info level */
&desc))
{
return RTEXITCODE_FAILURE;
}
#endif
return RTEXITCODE_SUCCESS;
}
/**
* Installs the service.
*/
{
if (hSCManager == NULL)
{
return RTEXITCODE_FAILURE;
}
VBoxServiceVerbose(0, "Service successfully installed!\n");
else
{
switch (dwErr)
{
case ERROR_SERVICE_EXISTS:
if (hService)
{
if (ChangeServiceConfig (hService,
NULL,
NULL,
NULL,
NULL,
NULL,
else
}
else
break;
default:
break;
}
}
if (rc == RTEXITCODE_SUCCESS)
return rc;
}
/**
* Uninstalls the service.
*/
{
if (hSCManager == NULL)
{
return RTEXITCODE_FAILURE;
}
{
if (DeleteService(hService))
{
/*
* ???
*/
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\System",
0,
&hKey)
== ERROR_SUCCESS)
{
}
VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
}
else
}
else
return rcExit;
}
static int vboxServiceWinStart(void)
{
int rc = VINF_SUCCESS;
#ifndef TARGET_NT4
/* Create a well-known SID for the "Builtin Users" group. */
0, 0, 0, 0, 0, 0, 0,
{
}
else
{
if (dwRes != ERROR_SUCCESS)
{
if (dwRes == ERROR_FILE_NOT_FOUND)
{
/* If we don't find our "VBoxMiniRdrDN" (for Shared Folders) object above,
don't report an error; it just might be not installed. Otherwise this
would cause the SCM to hang on starting up the service. */
rc = VINF_SUCCESS;
}
else
}
}
#endif
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
}
else
{
#if 0 /** @todo r=bird: Enable this if SERVICE_CONTROL_STOP isn't triggered automatically */
#endif
}
}
else
if (RT_FAILURE(rc))
return rc;
}
/**
* Call StartServiceCtrlDispatcher.
*
* The main() thread invokes this when not started in foreground mode. It
* won't return till the service is being shutdown (unless start up fails).
*
* @returns RTEXITCODE_SUCCESS on normal return after service shutdown.
* Something else on failure, error will have been reported.
*/
{
if (!StartServiceCtrlDispatcher(&g_aServiceTable[0]))
return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!\n",
return RTEXITCODE_SUCCESS;
}
#ifndef TARGET_NT4
{
switch (dwEvent)
{
case WTS_CONSOLE_CONNECT:
return "A session was connected to the console terminal";
case WTS_CONSOLE_DISCONNECT:
return "A session was disconnected from the console terminal";
case WTS_REMOTE_CONNECT:
return "A session connected to the remote terminal";
case WTS_REMOTE_DISCONNECT:
return "A session was disconnected from the remote terminal";
case WTS_SESSION_LOGON:
return "A user has logged on to a session";
case WTS_SESSION_LOGOFF:
return "A user has logged off the session";
case WTS_SESSION_LOCK:
return "A session has been locked";
case WTS_SESSION_UNLOCK:
return "A session has been unlocked";
return "A session has changed its remote controlled status";
#if 0
case WTS_SESSION_CREATE:
return "A session has been created";
case WTS_SESSION_TERMINATE:
return "The session has been terminated";
#endif
default:
break;
}
return "Uknonwn state";
}
#endif /* !TARGET_NT4 */
#ifdef TARGET_NT4
#else
static DWORD WINAPI vboxServiceWinCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
#endif
{
#ifdef TARGET_NT4
#else
#endif
switch (dwControl)
{
break;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
{
int rc2 = VBoxServiceStopServices();
if (RT_FAILURE(rc2))
else
{
}
break;
}
# ifndef TARGET_NT4
case SERVICE_CONTROL_SESSIONCHANGE: /* Only Windows 2000 and up. */
{
/* Handle all events, regardless of dwEventType. */
int rc2 = VBoxServiceVMInfoSignal();
break;
}
# endif /* !TARGET_NT4 */
default:
break;
}
#ifndef TARGET_NT4
return rcRet;
#endif
}
{
#ifdef TARGET_NT4
#else
g_hWinServiceStatus = RegisterServiceCtrlHandlerEx(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler, NULL);
#endif
if (g_hWinServiceStatus != NULL)
{
}
else
{
switch (dwErr)
{
case ERROR_INVALID_NAME:
VBoxServiceError("Invalid service name!\n");
break;
VBoxServiceError("Service does not exist!\n");
break;
default:
break;
}
}
}