campo-sirio/SSAservice/ServiceInstaller.cpp
guy d40707a134 Versione 12
git-svn-id: svn://10.65.10.50/branches/R_10_00@23098 c028cbd2-c16b-5b4b-a496-9718f37d4682
2015-05-15 09:09:10 +00:00

257 lines
7.9 KiB
C++

/****************************** Module Header ******************************\
* Module Name: ServiceInstaller.cpp
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* The file implements functions that install and uninstall the service.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
#pragma region "Includes"
#include "ServiceBase.h"
#include "ServiceInstaller.h"
#pragma endregion
static bool LogError(const char* funcname)
{
fprintf(stderr, "%s failed with error 0x%08lx\n", funcname, GetLastError());
return false;
}
class SCManager
{
SC_HANDLE _handle;
public:
bool IsOk() const { return _handle != NULL; }
operator SC_HANDLE() const { return _handle; }
bool Start(LPCTSTR pszServiceName);
bool Stop(LPCTSTR pszServiceName);
bool Delete(LPCTSTR pszServiceName);
SCManager(DWORD mode)
{
_handle = ::OpenSCManager(NULL, NULL, mode);
if (_handle == NULL)
LogError("OpenSCManager");
}
~SCManager()
{
if (_handle != NULL)
CloseServiceHandle(_handle);
}
};
bool SCManager::Stop(LPCTSTR pszServiceName)
{
bool bDone = false;
if (IsOk())
{
// Open the service with delete, stop, and query status permissions
SC_HANDLE schService = ::OpenService(_handle, pszServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS);
if (schService == NULL)
{
LogError("OpenService");
return false;
}
// Try to stop the service
SERVICE_STATUS ssSvcStatus = {};
if (::ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
{
wprintf(L"Stopping %s.", pszServiceName);
while (::QueryServiceStatus(schService, &ssSvcStatus))
{
if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
wprintf(L".");
Sleep(1000);
}
else
break;
}
bDone = ssSvcStatus.dwCurrentState == SERVICE_STOPPED;
wprintf(L"\n");
}
::CloseServiceHandle(schService);
if (bDone)
wprintf(L"%s stopped.\n", pszServiceName);
else
wprintf(L"%s failed to stop.\n", pszServiceName);
}
return bDone;
}
bool SCManager::Start(LPCTSTR pszServiceName)
{
bool bDone = false;
if (IsOk())
{
SC_HANDLE schService = ::OpenService(_handle, pszServiceName, SERVICE_START);
if (schService)
{
bDone = ::StartService(schService, 0, NULL) != 0;
if (bDone)
wprintf(L"%s started.\n", pszServiceName);
else
LogError("StartService");
}
else
LogError("OpenService");
}
return bDone;
}
bool SCManager::Delete(LPCTSTR pszServiceName)
{
bool bDone = false;
if (IsOk())
{
// Open the service with delete, stop, and query status permissions
SC_HANDLE schService = ::OpenService(_handle, pszServiceName, DELETE);
if (schService)
{
// Now remove the service by calling DeleteService.
bDone = ::DeleteService(schService) != 0;
if (bDone)
wprintf(L"%s has been removed.\n", pszServiceName);
else
LogError("DeleteService");
// Centralized cleanup for all allocated resources.
if (schService)
{
CloseServiceHandle(schService);
schService = NULL;
}
}
else
LogError("OpenService");
}
return bDone;
}
//
// FUNCTION: InstallService
//
// PURPOSE: Install the current application as a service to the local
// service control manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be installed
// * pszDisplayName - the display name of the service
// * dwStartType - the service start option. This parameter can be one of
// the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
// SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
// * pszDependencies - a pointer to a double null-terminated array of null-
// separated names of services or load ordering groups that the system
// must start before this service.
// * pszAccount - the name of the account under which the service runs.
// * pszPassword - the password to the account name.
//
// NOTE: If the function fails to install the service, it prints the error
// in the standard output stream for users to diagnose the problem.
//
bool InstallService(LPCTSTR pszServiceName,
LPCTSTR pszDisplayName,
DWORD dwServiceType,
DWORD dwStartType,
LPCTSTR pszDependencies,
LPCTSTR pszAccount,
LPCTSTR pszPassword)
{
TCHAR szPath[MAX_PATH];
if (::GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
return LogError("GetModuleFileName");
if (dwServiceType == 0)
dwServiceType = SERVICE_WIN32_OWN_PROCESS;
// Open the local default service control manager database
SCManager schSCManager(SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE);
if (schSCManager.IsOk())
{
// Install the service into SCM by calling CreateService
SC_HANDLE schService = ::CreateService(
schSCManager, // SCManager database
pszServiceName, // Name of service
pszDisplayName, // Name to display
SERVICE_QUERY_STATUS, // Desired access
dwServiceType, // Service type
dwStartType, // Service start type
SERVICE_ERROR_NORMAL, // Error control type
szPath, // Service's binary
NULL, // No load ordering group
NULL, // No tag identifier
pszDependencies, // Dependencies
pszAccount, // Service running account
pszPassword // Password of the account
);
if (schService != NULL)
{
wprintf(L"%s (%s) has been installed.\n", pszServiceName, pszDisplayName);
CloseServiceHandle(schService);
}
else
return LogError("CreateService");
}
return true;
}
//
// FUNCTION: UninstallService
//
// PURPOSE: Stop and remove the service from the local service control
// manager database.
//
// PARAMETERS:
// * pszServiceName - the name of the service to be removed.
//
// NOTE: If the function fails to uninstall the service, it prints the
// error in the standard output stream for users to diagnose the problem.
//
bool UninstallService(PWSTR pszServiceName)
{
bool done = false;
// Open the local default service control manager database
SCManager schSCManager(SC_MANAGER_CONNECT);
if (schSCManager.IsOk())
{
schSCManager.Stop(pszServiceName);
done = schSCManager.Delete(pszServiceName);
}
return done;
}
bool StartService(PWSTR pszServiceName)
{
bool done = false;
SCManager schSCManager(SC_MANAGER_CONNECT);
if (schSCManager.IsOk())
done = schSCManager.Start(pszServiceName);
return done;
}
bool StopService(PWSTR pszServiceName)
{
bool done = false;
SCManager schSCManager(SC_MANAGER_CONNECT);
if (schSCManager.IsOk())
done = schSCManager.Stop(pszServiceName);
return done;
}