395 lines
11 KiB
C
395 lines
11 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997 - 1998
|
||
|
//
|
||
|
// File: C S E R V I C E . H
|
||
|
//
|
||
|
// Contents: This file contains CService and CServiceManager, wrapper
|
||
|
// classes to the Win32 Service APIs.
|
||
|
//
|
||
|
// Notes: Note that not all functionallity is currently extended through
|
||
|
// these classes.
|
||
|
// Note that most functionality is inline in this file. What is
|
||
|
// not inline is in cservice.cpp
|
||
|
//
|
||
|
// Author: mikemi 6 Mar 1997
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef _CSERVICE_H_
|
||
|
#define _CSERVICE_H_
|
||
|
|
||
|
//#include "debugx.h"
|
||
|
//#include "ncbase.h"
|
||
|
|
||
|
//-------------------------------------------------------------------
|
||
|
//
|
||
|
//
|
||
|
//-------------------------------------------------------------------
|
||
|
|
||
|
size_t CchMsz(const TCHAR * msz);
|
||
|
|
||
|
|
||
|
class CService
|
||
|
{
|
||
|
friend class CServiceManager;
|
||
|
|
||
|
public:
|
||
|
CService()
|
||
|
{
|
||
|
_schandle = NULL;
|
||
|
};
|
||
|
|
||
|
~CService()
|
||
|
{
|
||
|
Close();
|
||
|
};
|
||
|
|
||
|
VOID Close()
|
||
|
{
|
||
|
BOOL frt;
|
||
|
|
||
|
if (_schandle)
|
||
|
{
|
||
|
frt = ::CloseServiceHandle( _schandle );
|
||
|
AssertSz(frt, "CloseServiceHandle failed!");
|
||
|
_schandle = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT HrDelete()
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::DeleteService( _schandle ))
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
HRESULT HrStart( DWORD cNumServiceArgs = 0,
|
||
|
LPCTSTR* papServiceArgs = NULL)
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::StartService( _schandle, cNumServiceArgs, papServiceArgs ))
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
HRESULT HrControl( DWORD dwControl )
|
||
|
{
|
||
|
SERVICE_STATUS sStatus;
|
||
|
|
||
|
Assert(_schandle != NULL );
|
||
|
AssertSz((dwControl != SERVICE_CONTROL_INTERROGATE),
|
||
|
"CService::HrControl does not support the SERVICE_CONTROL_INTERROGATE flag");
|
||
|
|
||
|
if ( ::ControlService( _schandle, dwControl, &sStatus ))
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
HRESULT HrMoveOutOfState( DWORD dwState );
|
||
|
HRESULT HrQueryState( DWORD* pdwState );
|
||
|
HRESULT HrQueryStartType( DWORD* pdwStartType );
|
||
|
HRESULT HrSetStartType( DWORD dwStartType )
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::ChangeServiceConfig( _schandle,
|
||
|
SERVICE_NO_CHANGE,
|
||
|
dwStartType,
|
||
|
SERVICE_NO_CHANGE,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL))
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
HRESULT HrQueryDependencies(OUT LPTSTR * pmszDependencyList);
|
||
|
HRESULT HrSetDependencies(IN LPCTSTR mszDependencyList)
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::ChangeServiceConfig( _schandle,
|
||
|
SERVICE_NO_CHANGE, // ServiceType
|
||
|
SERVICE_NO_CHANGE, // StartType
|
||
|
SERVICE_NO_CHANGE, // ErrorControl
|
||
|
NULL, // BinaryPathName
|
||
|
NULL, // LoadOredrGroup
|
||
|
NULL, // TagId
|
||
|
mszDependencyList, // Dependencies
|
||
|
NULL, // ServiceStartName
|
||
|
NULL, // Password
|
||
|
NULL)) // DisplayName
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
HRESULT HrSetDisplayName(IN LPCTSTR mszDisplayName)
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::ChangeServiceConfig( _schandle,
|
||
|
SERVICE_NO_CHANGE, // ServiceType
|
||
|
SERVICE_NO_CHANGE, // StartType
|
||
|
SERVICE_NO_CHANGE, // ErrorControl
|
||
|
NULL, // BinaryPathName
|
||
|
NULL, // LoadOredrGroup
|
||
|
NULL, // TagId
|
||
|
NULL, // Dependencies
|
||
|
NULL, // ServiceStartName
|
||
|
NULL, // Password
|
||
|
mszDisplayName)) // DisplayName
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HRESULT HrSetServiceObjectSecurity(
|
||
|
SECURITY_INFORMATION dwSecurityInformation,
|
||
|
PSECURITY_DESCRIPTOR lpSecurityDescriptor)
|
||
|
{
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
if (::SetServiceObjectSecurity( _schandle,
|
||
|
dwSecurityInformation, lpSecurityDescriptor))
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
SC_HANDLE _schandle;
|
||
|
};
|
||
|
|
||
|
//-------------------------------------------------------------------
|
||
|
//
|
||
|
//
|
||
|
//-------------------------------------------------------------------
|
||
|
|
||
|
class CServiceManager
|
||
|
{
|
||
|
public:
|
||
|
CServiceManager()
|
||
|
{
|
||
|
_schandle = NULL;
|
||
|
_sclock = NULL;
|
||
|
};
|
||
|
|
||
|
~CServiceManager()
|
||
|
{
|
||
|
if (_sclock)
|
||
|
{
|
||
|
Unlock();
|
||
|
}
|
||
|
if (_schandle)
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
HRESULT HrOpen( DWORD dwDesiredAccess = SC_MANAGER_ALL_ACCESS,
|
||
|
LPCTSTR pszMachineName = NULL,
|
||
|
LPCTSTR pszDatabaseName = NULL )
|
||
|
{
|
||
|
if (_schandle != NULL)
|
||
|
{
|
||
|
Close();
|
||
|
}
|
||
|
_schandle = ::OpenSCManager( pszMachineName,
|
||
|
pszDatabaseName,
|
||
|
dwDesiredAccess );
|
||
|
if ( _schandle != NULL )
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
VOID Close()
|
||
|
{
|
||
|
BOOL frt;
|
||
|
|
||
|
Assert(_schandle != NULL );
|
||
|
|
||
|
frt = ::CloseServiceHandle( _schandle );
|
||
|
_schandle = NULL;
|
||
|
AssertSz(frt, "CloseServiceHandle failed!");
|
||
|
}
|
||
|
|
||
|
HRESULT HrLock()
|
||
|
{
|
||
|
INT cRetries = 3;
|
||
|
static const INT c_secWait = 30;
|
||
|
static const INT c_msecWait = (c_secWait / (cRetries - 1)) * 1000;
|
||
|
|
||
|
Assert(_schandle != NULL );
|
||
|
Assert(_sclock == NULL );
|
||
|
|
||
|
while (cRetries--)
|
||
|
{
|
||
|
_sclock = ::LockServiceDatabase( _schandle );
|
||
|
if (_sclock != NULL)
|
||
|
return S_OK;
|
||
|
else
|
||
|
{
|
||
|
if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED ||
|
||
|
!cRetries)
|
||
|
{
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
Trace1("SCM is locked, waiting for %d seconds before retrying...", c_msecWait / 1000);
|
||
|
// wait for a bit to see if the database unlocks in that
|
||
|
Sleep(c_msecWait);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
AssertSz(FALSE, "HrLock error");
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
VOID Unlock()
|
||
|
{
|
||
|
BOOL frt;
|
||
|
Assert(_schandle != NULL );
|
||
|
Assert(_sclock != NULL );
|
||
|
|
||
|
frt = ::UnlockServiceDatabase( _sclock );
|
||
|
_sclock = NULL;
|
||
|
AssertSz(frt, "UnlockServiceDatabase failed!");
|
||
|
}
|
||
|
|
||
|
HRESULT HrQueryLocked(BOOL *pfLocked);
|
||
|
|
||
|
HRESULT HrOpenService( CService* pcsService,
|
||
|
LPCTSTR pszServiceName,
|
||
|
DWORD dwDesiredAccess = SERVICE_ALL_ACCESS )
|
||
|
{
|
||
|
// make sure the service is not in use
|
||
|
if (pcsService->_schandle != NULL)
|
||
|
{
|
||
|
pcsService->Close();
|
||
|
}
|
||
|
pcsService->_schandle = ::OpenService( _schandle, pszServiceName, dwDesiredAccess );
|
||
|
if ( pcsService->_schandle != NULL )
|
||
|
return S_OK;
|
||
|
else
|
||
|
{
|
||
|
DWORD dw=GetLastError();
|
||
|
return HRESULT_FROM_WIN32(dw);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT HrCreateService( CService* pcsService,
|
||
|
LPCTSTR pszServiceName,
|
||
|
LPCTSTR pszDisplayName,
|
||
|
DWORD dwServiceType,
|
||
|
DWORD dwStartType,
|
||
|
DWORD dwErrorControl,
|
||
|
LPCTSTR pszBinaryPathName,
|
||
|
LPCTSTR pslzDependencies = NULL,
|
||
|
LPCTSTR pszLoadOrderGroup = NULL,
|
||
|
PDWORD pdwTagId = NULL,
|
||
|
DWORD dwDesiredAccess = SERVICE_ALL_ACCESS,
|
||
|
LPCTSTR pszServiceStartName = NULL,
|
||
|
LPCTSTR pszPassword = NULL )
|
||
|
{
|
||
|
// make sure the service is not in use
|
||
|
if (pcsService->_schandle != NULL)
|
||
|
{
|
||
|
pcsService->Close();
|
||
|
}
|
||
|
pcsService->_schandle = ::CreateService( _schandle,
|
||
|
pszServiceName,
|
||
|
pszDisplayName,
|
||
|
dwDesiredAccess,
|
||
|
dwServiceType,
|
||
|
dwStartType,
|
||
|
dwErrorControl,
|
||
|
pszBinaryPathName,
|
||
|
pszLoadOrderGroup,
|
||
|
pdwTagId,
|
||
|
pslzDependencies,
|
||
|
pszServiceStartName,
|
||
|
pszPassword );
|
||
|
|
||
|
if ( pcsService->_schandle != NULL )
|
||
|
return S_OK;
|
||
|
else
|
||
|
return HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
enum SERVICE_START_CRITERIA
|
||
|
{
|
||
|
SERVICE_NO_CRITERIA, // Start the service regardless
|
||
|
SERVICE_ONLY_AUTO_START // Only start the service if it is of type
|
||
|
// Auto-Start
|
||
|
};
|
||
|
|
||
|
HRESULT HrStartService(LPCTSTR szService)
|
||
|
{
|
||
|
return (HrStartServiceHelper(szService, SERVICE_NO_CRITERIA));
|
||
|
}
|
||
|
|
||
|
HRESULT HrStartAutoStartService(LPCTSTR szService)
|
||
|
{
|
||
|
return (HrStartServiceHelper(szService, SERVICE_ONLY_AUTO_START));
|
||
|
}
|
||
|
|
||
|
HRESULT HrStartServiceHelper(LPCTSTR szService,
|
||
|
SERVICE_START_CRITERIA eCriteria);
|
||
|
HRESULT HrStopService(LPCTSTR szService);
|
||
|
|
||
|
enum DEPENDENCY_ADDREMOVE
|
||
|
{
|
||
|
DEPENDENCY_ADD,
|
||
|
DEPENDENCY_REMOVE
|
||
|
};
|
||
|
|
||
|
HRESULT HrAddServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency)
|
||
|
{
|
||
|
return HrAddRemoveServiceDependency(szServiceName,
|
||
|
szDependency,
|
||
|
DEPENDENCY_ADD);
|
||
|
}
|
||
|
|
||
|
HRESULT HrRemoveServiceDependency(LPCTSTR szServiceName, LPCTSTR szDependency)
|
||
|
{
|
||
|
return HrAddRemoveServiceDependency(szServiceName,
|
||
|
szDependency,
|
||
|
DEPENDENCY_REMOVE);
|
||
|
}
|
||
|
|
||
|
HRESULT HrAddRemoveServiceDependency(LPCTSTR szServiceName,
|
||
|
LPCTSTR szDependency,
|
||
|
DEPENDENCY_ADDREMOVE enumFlag);
|
||
|
|
||
|
private:
|
||
|
SC_HANDLE _schandle;
|
||
|
SC_LOCK _sclock;
|
||
|
};
|
||
|
|
||
|
#endif // _CSERVICE_H_
|
||
|
|