d40707a134
git-svn-id: svn://10.65.10.50/branches/R_10_00@23098 c028cbd2-c16b-5b4b-a496-9718f37d4682
257 lines
7.9 KiB
C++
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;
|
|
}
|