VBoxService-win.cpp revision a8e64340afb42c4918e2d6faecdba928a0b2b45c
/* $Id$ */
/** @file
* VBoxService - Guest Additions Service Skeleton, Windows Specific Parts.
*/
/*
* Copyright (C) 2009-2010 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;
}
/**
* 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,
{
/**@todo r=bird: rc = RTErrConvertFromWin32(GetLastError()); ?*/
}
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
}
/**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */
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)!",
return RTEXITCODE_SUCCESS;
}
#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))
break;
}
case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
#ifndef TARGET_NT4
# if 0
switch (dwEventType)
{
case WTS_SESSION_LOGON:
break;
case WTS_SESSION_LOGOFF:
break;
default:
break;
}
# endif
#endif /* !TARGET_NT4 */
break;
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;
}
}
}