#include "StdAfx.h"
#include "ServiceInfo.h"
// Interval in milliseconds for updating values of dynamic properties
// of the interface, such as m_dwProcessID and m_CurrentState:
#define UPDATE_PROPERTY_DELAY 200
CServiceInfo::CServiceInfo(void)
{
m_sName = _T("");
m_sDisplayName = _T("");
m_sDescription = _T("");
m_sPath = _T("");
m_sStartName = _T("");
m_sDependencies = _T("");
m_CurrentState = ssStopped;
m_dwServiceType = 0; // Invalid;
m_dwStartType = -1; // Unknown;
m_dwProcessID = 0;
m_dwTickCount = 0;
}
void CServiceInfo::Initialize(SC_HANDLE hService, ENUM_SERVICE_STATUS_PROCESS & ssp, LPBYTE pTempBuffer, DWORD dwBufferSize)
{
m_sName = ssp.lpServiceName;
m_sDisplayName = ssp.lpDisplayName;
m_CurrentState = (PSLServiceState)ssp.ServiceStatusProcess.dwCurrentState;
m_dwServiceType = ssp.ServiceStatusProcess.dwServiceType;
m_dwProcessID = ssp.ServiceStatusProcess.dwProcessId;
DWORD dwBytesNeeded = 0;
LPQUERY_SERVICE_CONFIG pConfig = (LPQUERY_SERVICE_CONFIG)pTempBuffer;
if(::QueryServiceConfig(hService, pConfig, dwBufferSize, &dwBytesNeeded))
{
tstring s = pConfig->lpBinaryPathName;
CPSLUtilities::FixSysPath(s);
m_sPath = s.c_str();
if(pConfig->lpServiceStartName)
m_sStartName = pConfig->lpServiceStartName;
if(pConfig->lpDependencies)
m_sDependencies = pConfig->lpDependencies;
m_dwStartType = pConfig->dwStartType;
}
LPSERVICE_DESCRIPTION pDesc = (LPSERVICE_DESCRIPTION)pTempBuffer;
if(::QueryServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)pDesc, dwBufferSize, &dwBytesNeeded))
m_sDescription = pDesc->lpDescription;
}
PSLException CServiceInfo::Update()
{
if(m_sName.length() < 1)
return exNone;
DWORD dwCount = ::GetTickCount();
if(abs((long)(dwCount - m_dwTickCount)) < UPDATE_PROPERTY_DELAY)
return exNone;
m_dwTickCount = dwCount;
m_dwProcessID = 0;
m_CurrentState = ssStopped;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, GENERIC_READ);
if(!hSCM)
{
if(::GetLastError() == ERROR_ACCESS_DENIED)
return exAccessDenied;
else
return exGeneric;
}
SC_HANDLE hService = ::OpenService(hSCM, m_sName, GENERIC_READ);
if(!hService)
{
DWORD dwError = ::GetLastError();
::CloseServiceHandle(hSCM);
if(dwError == ERROR_ACCESS_DENIED)
return exAccessDenied;
else
return exGeneric;
}
PSLException ex = exGeneric;
DWORD dwBytesNeeded = 0;
SERVICE_STATUS_PROCESS Status;
if(::QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&Status, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
m_dwProcessID = Status.dwProcessId;
m_CurrentState = static_cast<PSLServiceState>(Status.dwCurrentState);
ex = exNone;
}
::CloseServiceHandle(hService);
::CloseServiceHandle(hSCM);
return ex;
}
long CServiceInfo::StartService(SAFEARRAY * CmdParams, PSLException & ex)
{
ex = exNone;
long ResultCode = 0;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, STANDARD_RIGHTS_EXECUTE);
if(hSCM)
{
SC_HANDLE hService = ::OpenService(hSCM, m_sName, SERVICE_START);
if(hService)
{
TCHAR ** Params = NULL;
DWORD dwCounter = 0;
if(CmdParams)
{
long nElements; // Number of elements in the array;
if(::SafeArrayGetUBound(CmdParams, 1, &nElements) == S_OK)
{
nElements ++;
dwCounter = nElements + 1;
Params = new TCHAR*[dwCounter];
int L = m_sName.length();
Params[0] = new TCHAR[L + 1];
_tcsncpy_s(Params[0], L + 1, m_sName, L);
BSTR sName = NULL;
for(long i = 0;i < nElements;i ++)
if(::SafeArrayGetElement(CmdParams, &i, &sName) == S_OK)
{
_bstr_t tmp(sName);
L = tmp.length();
Params[i + 1] = new TCHAR[L + 1];
_tcsncpy_s(Params[i + 1], L + 1, tmp, L);
::SysFreeString(sName);
}
}
}
if(!::StartService(hService, dwCounter, (LPCTSTR*)Params))
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
for(DWORD i = 0;i < dwCounter;i ++)
delete Params[i];
delete []Params;
::CloseServiceHandle(hService);
}
else
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
::CloseServiceHandle(hSCM);
}
else
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
return ResultCode;
}
long CServiceInfo::StopService(PSLException & ex)
{
ex = exNone;
long ResultCode = 0;
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, STANDARD_RIGHTS_EXECUTE);
if(hSCM)
{
SC_HANDLE hService = ::OpenService(hSCM, m_sName, SERVICE_STOP);
if(hService)
{
SERVICE_STATUS s;
if(!::ControlService(hService, SERVICE_CONTROL_STOP, &s))
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
::CloseServiceHandle(hService);
}
else
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
::CloseServiceHandle(hSCM);
}
else
{
DWORD dwError = ::GetLastError();
if(dwError == ERROR_ACCESS_DENIED)
ex = exAccessDenied;
ResultCode = dwError;
}
return ResultCode;
}