172 lines
3.9 KiB
C++
172 lines
3.9 KiB
C++
/*
|
|
*(C) 2006 Roku LLC
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License Version 2 as published
|
|
* by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* without any warranty; without even the implied warranty of
|
|
* merchantability or fitness for a particular purpose. See the GNU General
|
|
* Public License for more details.
|
|
*
|
|
* Please read README.txt in the same directory as this source file for
|
|
* further license information.
|
|
*/
|
|
|
|
#ifndef SERVICECONTROL_H
|
|
#define SERVICECONTROL_H
|
|
|
|
class Service
|
|
{
|
|
SC_HANDLE m_sc_manager;
|
|
SC_HANDLE m_sc_service;
|
|
bool m_can_control;
|
|
|
|
public:
|
|
|
|
class Status : public SERVICE_STATUS
|
|
{
|
|
bool WaitPending();
|
|
|
|
public:
|
|
Status()
|
|
{
|
|
SERVICE_STATUS *clearable_this = this;
|
|
ZeroMemory(clearable_this, sizeof(SERVICE_STATUS));
|
|
}
|
|
|
|
bool operator==(const Status &r) const
|
|
{
|
|
const SERVICE_STATUS *lhs = this;
|
|
const SERVICE_STATUS *rhs = &r;
|
|
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) == 0;
|
|
}
|
|
|
|
bool operator!=(const Status &r) const
|
|
{
|
|
const SERVICE_STATUS *lhs = this;
|
|
const SERVICE_STATUS *rhs = &r;
|
|
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) != 0;
|
|
}
|
|
|
|
void AssertValid() const
|
|
{
|
|
// If we've been written then this shouldn't be zero.
|
|
ATLASSERT(dwCurrentState != 0);
|
|
}
|
|
|
|
bool IsValid() const
|
|
{
|
|
return dwCurrentState != 0;
|
|
}
|
|
|
|
bool IsRunning() const
|
|
{
|
|
AssertValid();
|
|
return dwCurrentState == SERVICE_RUNNING;
|
|
}
|
|
|
|
bool IsStopped() const
|
|
{
|
|
AssertValid();
|
|
return dwCurrentState == SERVICE_STOPPED;
|
|
}
|
|
|
|
bool IsPaused() const
|
|
{
|
|
AssertValid();
|
|
return dwCurrentState == SERVICE_PAUSED;
|
|
}
|
|
|
|
bool IsPending() const
|
|
{
|
|
AssertValid();
|
|
switch (dwCurrentState)
|
|
{
|
|
case SERVICE_CONTINUE_PENDING:
|
|
case SERVICE_PAUSE_PENDING:
|
|
case SERVICE_START_PENDING:
|
|
case SERVICE_STOP_PENDING:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
};
|
|
|
|
Service() : m_sc_manager(NULL), m_sc_service(NULL), m_can_control(false) {}
|
|
~Service() { Close(); }
|
|
|
|
bool IsOpen() const
|
|
{
|
|
return m_sc_service != NULL;
|
|
}
|
|
bool Open(const TCHAR *name);
|
|
void Close();
|
|
|
|
bool GetStatus(Status *status) const;
|
|
|
|
bool Start();
|
|
bool StartAndWait();
|
|
bool Stop();
|
|
bool StopAndWait();
|
|
bool WaitPending(Status *status, DWORD existing_state);
|
|
bool PollPending(Status *status, DWORD existing_state);
|
|
|
|
bool CanControl() const
|
|
{
|
|
// For the time being - need to deal with running as a user that can't control.
|
|
return IsOpen() && m_can_control;
|
|
}
|
|
|
|
CString GetBinaryPath() const;
|
|
|
|
/// Pass SERVICE_AUTO_START, SERVICE_BOOT_START, SERVICE_DEMAND_START,
|
|
/// SERVICE_DISABLED or SERVICE_SYSTEM_START.
|
|
bool ConfigureStartup(DWORD dwStartup);
|
|
|
|
DWORD GetStartup() const;
|
|
};
|
|
|
|
class ServiceStatusObserver
|
|
{
|
|
public:
|
|
virtual void OnServiceStatus(Service::Status old_status, Service::Status new_status) = 0;
|
|
};
|
|
|
|
class ServiceStatusMonitor
|
|
{
|
|
Service::Status m_service_status;
|
|
std::vector<ServiceStatusObserver *> m_service_observers;
|
|
|
|
void FireServiceStatus(Service::Status old_status, Service::Status new_status)
|
|
{
|
|
std::vector<ServiceStatusObserver *>::iterator i = m_service_observers.begin();
|
|
while (i != m_service_observers.end())
|
|
{
|
|
(*i)->OnServiceStatus(old_status, new_status);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
public:
|
|
void Poll(Service *service);
|
|
void Subscribe(ServiceStatusObserver *obs)
|
|
{
|
|
m_service_observers.push_back(obs);
|
|
}
|
|
|
|
void Unsubscribe(ServiceStatusObserver *obs)
|
|
{
|
|
std::vector<ServiceStatusObserver *>::iterator i = std::find(m_service_observers.begin(), m_service_observers.end(), obs);
|
|
ATLASSERT(i != m_service_observers.end());
|
|
if (i != m_service_observers.end())
|
|
{
|
|
m_service_observers.erase(i);
|
|
}
|
|
}
|
|
|
|
};
|
|
#endif // SERVICECONTROL_H
|