mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-11 23:13:24 -05:00
Update nsi to include svcctrl.exe, update service code in shell to execute the svchelper rather than relying on having admin rights.
This commit is contained in:
parent
7ef720c407
commit
63b49ffd04
@ -4,6 +4,7 @@
|
|||||||
Version="8.00"
|
Version="8.00"
|
||||||
Name="FireflyShell"
|
Name="FireflyShell"
|
||||||
ProjectGUID="{ED38F171-854B-4EA3-B3A0-7681648969FC}"
|
ProjectGUID="{ED38F171-854B-4EA3-B3A0-7681648969FC}"
|
||||||
|
RootNamespace="FireflyShell"
|
||||||
Keyword="Win32Proj"
|
Keyword="Win32Proj"
|
||||||
>
|
>
|
||||||
<Platforms>
|
<Platforms>
|
||||||
|
@ -1,217 +1,253 @@
|
|||||||
/*
|
/*
|
||||||
*(C) 2006 Roku LLC
|
*(C) 2006 Roku LLC
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU General Public License Version 2 as published
|
||||||
* by the Free Software Foundation.
|
* by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but
|
* This program is distributed in the hope that it will be useful, but
|
||||||
* without any warranty; without even the implied warranty of
|
* without any warranty; without even the implied warranty of
|
||||||
* merchantability or fitness for a particular purpose. See the GNU General
|
* merchantability or fitness for a particular purpose. See the GNU General
|
||||||
* Public License for more details.
|
* Public License for more details.
|
||||||
*
|
*
|
||||||
* Please read README.txt in the same directory as this source file for
|
* Please read README.txt in the same directory as this source file for
|
||||||
* further license information.
|
* further license information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "ServiceControl.h"
|
#include "ServiceControl.h"
|
||||||
|
#include "DosPath.h"
|
||||||
|
|
||||||
|
bool Service::ExecHelper(const TCHAR *szAction) {
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
STARTUPINFO si;
|
||||||
|
CString commandline;
|
||||||
|
CDosPath path = CDosPath::AppPath();
|
||||||
|
CDosPath filename(_T("svcctrl.exe"));
|
||||||
|
DWORD dwResult;
|
||||||
|
LPTSTR cmd;
|
||||||
|
|
||||||
|
filename |= path;
|
||||||
|
commandline.Format(_T("%s %s \"%s\""),filename.GetPath(),szAction,m_name);
|
||||||
|
cmd = commandline.GetBuffer(commandline.GetLength() + 1);
|
||||||
|
ZeroMemory(&si,sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
|
ZeroMemory(&pi,sizeof(pi));
|
||||||
|
|
||||||
|
|
||||||
|
BOOL bStarted = CreateProcess(NULL,cmd,NULL,NULL,
|
||||||
|
FALSE,0,NULL,NULL,&si,&pi);
|
||||||
|
|
||||||
|
commandline.ReleaseBuffer();
|
||||||
|
|
||||||
|
if(!bStarted)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
GetExitCodeProcess(pi.hProcess,&dwResult);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
|
if(dwResult)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Service::Open(const TCHAR *name)
|
bool Service::Open(const TCHAR *name)
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
const DWORD ADMIN_ACCESS = SC_MANAGER_ALL_ACCESS;
|
const DWORD USER_ACCESS = SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | STANDARD_RIGHTS_READ;
|
||||||
const DWORD USER_ACCESS = SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE | STANDARD_RIGHTS_READ;
|
|
||||||
|
|
||||||
DWORD dwDesiredAccess = ADMIN_ACCESS;
|
DWORD dwDesiredAccess = USER_ACCESS;
|
||||||
|
|
||||||
m_sc_manager = ::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, dwDesiredAccess);
|
m_sc_manager = ::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, dwDesiredAccess);
|
||||||
if (!m_sc_manager)
|
if (!m_sc_manager)
|
||||||
{
|
{
|
||||||
dwDesiredAccess = USER_ACCESS;
|
m_can_control = false;
|
||||||
m_sc_manager = ::OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, dwDesiredAccess);
|
}
|
||||||
m_can_control = false;
|
else
|
||||||
}
|
{
|
||||||
else
|
m_can_control = true;
|
||||||
{
|
}
|
||||||
m_can_control = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_sc_manager)
|
if (m_sc_manager)
|
||||||
{
|
{
|
||||||
m_sc_service = ::OpenService(m_sc_manager, name, dwDesiredAccess);
|
m_sc_service = ::OpenService(m_sc_manager, name, dwDesiredAccess);
|
||||||
if (m_sc_service)
|
if (m_sc_service) {
|
||||||
return true;
|
m_name = name;
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Close();
|
Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Service::Close()
|
void Service::Close()
|
||||||
{
|
{
|
||||||
if (m_sc_service)
|
if (m_sc_service)
|
||||||
{
|
{
|
||||||
::CloseServiceHandle(m_sc_service);
|
::CloseServiceHandle(m_sc_service);
|
||||||
m_sc_service = NULL;
|
m_sc_service = NULL;
|
||||||
}
|
}
|
||||||
if (m_sc_manager)
|
if (m_sc_manager)
|
||||||
{
|
{
|
||||||
::CloseServiceHandle(m_sc_manager);
|
::CloseServiceHandle(m_sc_manager);
|
||||||
m_sc_manager = NULL;
|
m_sc_manager = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::GetStatus(Status *status) const
|
bool Service::GetStatus(Status *status) const
|
||||||
{
|
{
|
||||||
if (::QueryServiceStatus(m_sc_service, status))
|
if (::QueryServiceStatus(m_sc_service, status))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::Start()
|
bool Service::Start()
|
||||||
{
|
{
|
||||||
if (::StartService(m_sc_service, 0, NULL))
|
if (ExecHelper(_T("start")))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::StartAndWait()
|
bool Service::StartAndWait()
|
||||||
{
|
{
|
||||||
if (Start())
|
if (Start())
|
||||||
{
|
{
|
||||||
Status status;
|
Status status;
|
||||||
return WaitPending(&status, SERVICE_START_PENDING);
|
return WaitPending(&status, SERVICE_START_PENDING);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::Stop()
|
bool Service::Stop()
|
||||||
{
|
{
|
||||||
Status status;
|
Status status;
|
||||||
if (::ControlService(m_sc_service, SERVICE_CONTROL_STOP, &status))
|
if (ExecHelper(_T("stop")))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::StopAndWait()
|
bool Service::StopAndWait()
|
||||||
{
|
{
|
||||||
Status status;
|
Status status;
|
||||||
if (::ControlService(m_sc_service, SERVICE_CONTROL_STOP, &status))
|
if (Stop())
|
||||||
{
|
return WaitPending(&status, SERVICE_STOP_PENDING);
|
||||||
return WaitPending(&status, SERVICE_STOP_PENDING);
|
else
|
||||||
}
|
return false;
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::WaitPending(Status *status, DWORD existing_state)
|
bool Service::WaitPending(Status *status, DWORD existing_state)
|
||||||
{
|
{
|
||||||
ATLTRACE(_T("Enter Service::WaitPending\n"));
|
ATLTRACE(_T("Enter Service::WaitPending\n"));
|
||||||
if (GetStatus(status))
|
if (GetStatus(status))
|
||||||
{
|
{
|
||||||
DWORD dwStartTickCount = GetTickCount();
|
DWORD dwStartTickCount = GetTickCount();
|
||||||
DWORD dwOldCheckPoint = status->dwCheckPoint;
|
DWORD dwOldCheckPoint = status->dwCheckPoint;
|
||||||
|
|
||||||
while (status->dwCurrentState == existing_state)
|
while (status->dwCurrentState == existing_state)
|
||||||
{
|
{
|
||||||
ATLTRACE(_T("Service::WaitPending in loop\n"));
|
ATLTRACE(_T("Service::WaitPending in loop\n"));
|
||||||
DWORD dwWaitTime = status->dwWaitHint / 10;
|
DWORD dwWaitTime = status->dwWaitHint / 10;
|
||||||
if (dwWaitTime < 1000)
|
if (dwWaitTime < 1000)
|
||||||
dwWaitTime = 1000;
|
dwWaitTime = 1000;
|
||||||
else if (dwWaitTime > 10000)
|
else if (dwWaitTime > 10000)
|
||||||
dwWaitTime = 10000;
|
dwWaitTime = 10000;
|
||||||
|
|
||||||
ATLTRACE(_T("Sleeping\n"));
|
ATLTRACE(_T("Sleeping\n"));
|
||||||
::Sleep(dwWaitTime);
|
::Sleep(dwWaitTime);
|
||||||
|
|
||||||
if (!GetStatus(status))
|
if (!GetStatus(status))
|
||||||
{
|
{
|
||||||
ATLTRACE(_T("Service::WaitPending - Failed to get status\n"));
|
ATLTRACE(_T("Service::WaitPending - Failed to get status\n"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't changed state yet then check to see that the
|
// If we haven't changed state yet then check to see that the
|
||||||
// service is actually making progress.
|
// service is actually making progress.
|
||||||
if (status->dwCurrentState == existing_state)
|
if (status->dwCurrentState == existing_state)
|
||||||
{
|
{
|
||||||
if (status->dwCheckPoint != dwOldCheckPoint)
|
if (status->dwCheckPoint != dwOldCheckPoint)
|
||||||
{
|
{
|
||||||
// The service is making progress
|
// The service is making progress
|
||||||
dwStartTickCount = GetTickCount();
|
dwStartTickCount = GetTickCount();
|
||||||
dwOldCheckPoint = status->dwCheckPoint;
|
dwOldCheckPoint = status->dwCheckPoint;
|
||||||
}
|
}
|
||||||
else if (GetTickCount() - dwStartTickCount > status->dwWaitHint)
|
else if (GetTickCount() - dwStartTickCount > status->dwWaitHint)
|
||||||
{
|
{
|
||||||
ATLTRACE(_T("Service::WaitPending - No progress\n"));
|
ATLTRACE(_T("Service::WaitPending - No progress\n"));
|
||||||
/// Hmm. No progress
|
/// Hmm. No progress
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ATLTRACE(_T("Service::WaitPending success\n"));
|
ATLTRACE(_T("Service::WaitPending success\n"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString Service::GetBinaryPath() const
|
CString Service::GetBinaryPath() const
|
||||||
{
|
{
|
||||||
CString path;
|
CString path;
|
||||||
|
|
||||||
DWORD bytes_required;
|
DWORD bytes_required;
|
||||||
::QueryServiceConfig(m_sc_service, NULL, 0, &bytes_required);
|
::QueryServiceConfig(m_sc_service, NULL, 0, &bytes_required);
|
||||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||||
{
|
{
|
||||||
void *buffer = operator new(bytes_required);
|
void *buffer = operator new(bytes_required);
|
||||||
LPQUERY_SERVICE_CONFIG config = reinterpret_cast<LPQUERY_SERVICE_CONFIG>(buffer);
|
LPQUERY_SERVICE_CONFIG config = reinterpret_cast<LPQUERY_SERVICE_CONFIG>(buffer);
|
||||||
|
|
||||||
if (::QueryServiceConfig(m_sc_service, config, bytes_required, &bytes_required))
|
if (::QueryServiceConfig(m_sc_service, config, bytes_required, &bytes_required))
|
||||||
{
|
{
|
||||||
path = config->lpBinaryPathName;
|
path = config->lpBinaryPathName;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete buffer;
|
delete buffer;
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD Service::GetStartup() const
|
DWORD Service::GetStartup() const
|
||||||
{
|
{
|
||||||
DWORD result = 0xffffffff;
|
DWORD result = 0xffffffff;
|
||||||
const size_t BUFFER_SIZE = 8192;
|
const size_t BUFFER_SIZE = 8192;
|
||||||
void *buffer = operator new(BUFFER_SIZE);
|
void *buffer = operator new(BUFFER_SIZE);
|
||||||
LPQUERY_SERVICE_CONFIG config = reinterpret_cast<LPQUERY_SERVICE_CONFIG>(buffer);
|
LPQUERY_SERVICE_CONFIG config = reinterpret_cast<LPQUERY_SERVICE_CONFIG>(buffer);
|
||||||
|
|
||||||
DWORD bytes_required;
|
|
||||||
if (::QueryServiceConfig(m_sc_service, config, BUFFER_SIZE, &bytes_required))
|
|
||||||
result = config->dwStartType;
|
|
||||||
|
|
||||||
delete buffer;
|
DWORD bytes_required;
|
||||||
return result;
|
if (::QueryServiceConfig(m_sc_service, config, BUFFER_SIZE, &bytes_required))
|
||||||
|
result = config->dwStartType;
|
||||||
|
|
||||||
|
delete buffer;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Service::ConfigureStartup(DWORD startup)
|
bool Service::ConfigureStartup(DWORD startup)
|
||||||
{
|
{
|
||||||
if (::ChangeServiceConfig(m_sc_service, SERVICE_NO_CHANGE, startup, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
|
if (::ChangeServiceConfig(m_sc_service, SERVICE_NO_CHANGE, startup, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceStatusMonitor::Poll(Service *service)
|
void ServiceStatusMonitor::Poll(Service *service)
|
||||||
{
|
{
|
||||||
Service::Status new_status;
|
Service::Status new_status;
|
||||||
if (service->GetStatus(&new_status))
|
if (service->GetStatus(&new_status))
|
||||||
{
|
{
|
||||||
if (!m_service_status.IsValid() || (m_service_status != new_status))
|
if (!m_service_status.IsValid() || (m_service_status != new_status))
|
||||||
{
|
{
|
||||||
FireServiceStatus(m_service_status, new_status);
|
FireServiceStatus(m_service_status, new_status);
|
||||||
m_service_status = new_status;
|
m_service_status = new_status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,171 +1,174 @@
|
|||||||
/*
|
/*
|
||||||
*(C) 2006 Roku LLC
|
*(C) 2006 Roku LLC
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU General Public License Version 2 as published
|
||||||
* by the Free Software Foundation.
|
* by the Free Software Foundation.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but
|
* This program is distributed in the hope that it will be useful, but
|
||||||
* without any warranty; without even the implied warranty of
|
* without any warranty; without even the implied warranty of
|
||||||
* merchantability or fitness for a particular purpose. See the GNU General
|
* merchantability or fitness for a particular purpose. See the GNU General
|
||||||
* Public License for more details.
|
* Public License for more details.
|
||||||
*
|
*
|
||||||
* Please read README.txt in the same directory as this source file for
|
* Please read README.txt in the same directory as this source file for
|
||||||
* further license information.
|
* further license information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SERVICECONTROL_H
|
#ifndef SERVICECONTROL_H
|
||||||
#define SERVICECONTROL_H
|
#define SERVICECONTROL_H
|
||||||
|
|
||||||
class Service
|
class Service
|
||||||
{
|
{
|
||||||
SC_HANDLE m_sc_manager;
|
SC_HANDLE m_sc_manager;
|
||||||
SC_HANDLE m_sc_service;
|
SC_HANDLE m_sc_service;
|
||||||
bool m_can_control;
|
bool m_can_control;
|
||||||
|
CString m_name;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Status : public SERVICE_STATUS
|
|
||||||
{
|
|
||||||
bool WaitPending();
|
|
||||||
|
|
||||||
public:
|
class Status : public SERVICE_STATUS
|
||||||
Status()
|
{
|
||||||
{
|
bool WaitPending();
|
||||||
SERVICE_STATUS *clearable_this = this;
|
|
||||||
ZeroMemory(clearable_this, sizeof(SERVICE_STATUS));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Status &r) const
|
public:
|
||||||
{
|
Status()
|
||||||
const SERVICE_STATUS *lhs = this;
|
{
|
||||||
const SERVICE_STATUS *rhs = &r;
|
SERVICE_STATUS *clearable_this = this;
|
||||||
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) == 0;
|
ZeroMemory(clearable_this, sizeof(SERVICE_STATUS));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Status &r) const
|
bool operator==(const Status &r) const
|
||||||
{
|
{
|
||||||
const SERVICE_STATUS *lhs = this;
|
const SERVICE_STATUS *lhs = this;
|
||||||
const SERVICE_STATUS *rhs = &r;
|
const SERVICE_STATUS *rhs = &r;
|
||||||
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) != 0;
|
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertValid() const
|
bool operator!=(const Status &r) const
|
||||||
{
|
{
|
||||||
// If we've been written then this shouldn't be zero.
|
const SERVICE_STATUS *lhs = this;
|
||||||
ATLASSERT(dwCurrentState != 0);
|
const SERVICE_STATUS *rhs = &r;
|
||||||
}
|
return memcmp(lhs, rhs, sizeof(SERVICE_STATUS)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsValid() const
|
void AssertValid() const
|
||||||
{
|
{
|
||||||
return dwCurrentState != 0;
|
// If we've been written then this shouldn't be zero.
|
||||||
}
|
ATLASSERT(dwCurrentState != 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsRunning() const
|
bool IsValid() const
|
||||||
{
|
{
|
||||||
AssertValid();
|
return dwCurrentState != 0;
|
||||||
return dwCurrentState == SERVICE_RUNNING;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool IsStopped() const
|
bool IsRunning() const
|
||||||
{
|
{
|
||||||
AssertValid();
|
AssertValid();
|
||||||
return dwCurrentState == SERVICE_STOPPED;
|
return dwCurrentState == SERVICE_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPaused() const
|
bool IsStopped() const
|
||||||
{
|
{
|
||||||
AssertValid();
|
AssertValid();
|
||||||
return dwCurrentState == SERVICE_PAUSED;
|
return dwCurrentState == SERVICE_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPending() const
|
bool IsPaused() const
|
||||||
{
|
{
|
||||||
AssertValid();
|
AssertValid();
|
||||||
switch (dwCurrentState)
|
return dwCurrentState == SERVICE_PAUSED;
|
||||||
{
|
}
|
||||||
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) {}
|
bool IsPending() const
|
||||||
~Service() { Close(); }
|
{
|
||||||
|
AssertValid();
|
||||||
|
switch (dwCurrentState)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTINUE_PENDING:
|
||||||
|
case SERVICE_PAUSE_PENDING:
|
||||||
|
case SERVICE_START_PENDING:
|
||||||
|
case SERVICE_STOP_PENDING:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
bool IsOpen() const
|
Service() : m_sc_manager(NULL), m_sc_service(NULL), m_can_control(false) {}
|
||||||
{
|
~Service() { Close(); }
|
||||||
return m_sc_service != NULL;
|
|
||||||
}
|
|
||||||
bool Open(const TCHAR *name);
|
|
||||||
void Close();
|
|
||||||
|
|
||||||
bool GetStatus(Status *status) const;
|
bool IsOpen() const
|
||||||
|
{
|
||||||
|
return m_sc_service != NULL;
|
||||||
|
}
|
||||||
|
bool Open(const TCHAR *name);
|
||||||
|
void Close();
|
||||||
|
|
||||||
bool Start();
|
bool GetStatus(Status *status) const;
|
||||||
bool StartAndWait();
|
|
||||||
bool Stop();
|
bool Start();
|
||||||
bool StopAndWait();
|
bool StartAndWait();
|
||||||
bool WaitPending(Status *status, DWORD existing_state);
|
bool Stop();
|
||||||
bool PollPending(Status *status, DWORD existing_state);
|
bool StopAndWait();
|
||||||
|
bool WaitPending(Status *status, DWORD existing_state);
|
||||||
|
bool PollPending(Status *status, DWORD existing_state);
|
||||||
|
|
||||||
bool CanControl() const
|
bool CanControl() const
|
||||||
{
|
{
|
||||||
// For the time being - need to deal with running as a user that can't control.
|
// For the time being - need to deal with running as a user that can't control.
|
||||||
return IsOpen() && m_can_control;
|
return IsOpen() && m_can_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString GetBinaryPath() const;
|
CString GetBinaryPath() const;
|
||||||
|
|
||||||
/// Pass SERVICE_AUTO_START, SERVICE_BOOT_START, SERVICE_DEMAND_START,
|
/// Pass SERVICE_AUTO_START, SERVICE_BOOT_START, SERVICE_DEMAND_START,
|
||||||
/// SERVICE_DISABLED or SERVICE_SYSTEM_START.
|
/// SERVICE_DISABLED or SERVICE_SYSTEM_START.
|
||||||
bool ConfigureStartup(DWORD dwStartup);
|
bool ConfigureStartup(DWORD dwStartup);
|
||||||
|
DWORD GetStartup() const;
|
||||||
|
|
||||||
DWORD GetStartup() const;
|
private:
|
||||||
|
bool ExecHelper(const TCHAR *szAction);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServiceStatusObserver
|
class ServiceStatusObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void OnServiceStatus(Service::Status old_status, Service::Status new_status) = 0;
|
virtual void OnServiceStatus(Service::Status old_status, Service::Status new_status) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServiceStatusMonitor
|
class ServiceStatusMonitor
|
||||||
{
|
{
|
||||||
Service::Status m_service_status;
|
Service::Status m_service_status;
|
||||||
std::vector<ServiceStatusObserver *> m_service_observers;
|
std::vector<ServiceStatusObserver *> m_service_observers;
|
||||||
|
|
||||||
void FireServiceStatus(Service::Status old_status, Service::Status new_status)
|
void FireServiceStatus(Service::Status old_status, Service::Status new_status)
|
||||||
{
|
{
|
||||||
std::vector<ServiceStatusObserver *>::iterator i = m_service_observers.begin();
|
std::vector<ServiceStatusObserver *>::iterator i = m_service_observers.begin();
|
||||||
while (i != m_service_observers.end())
|
while (i != m_service_observers.end())
|
||||||
{
|
{
|
||||||
(*i)->OnServiceStatus(old_status, new_status);
|
(*i)->OnServiceStatus(old_status, new_status);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Poll(Service *service);
|
void Poll(Service *service);
|
||||||
void Subscribe(ServiceStatusObserver *obs)
|
void Subscribe(ServiceStatusObserver *obs)
|
||||||
{
|
{
|
||||||
m_service_observers.push_back(obs);
|
m_service_observers.push_back(obs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unsubscribe(ServiceStatusObserver *obs)
|
void Unsubscribe(ServiceStatusObserver *obs)
|
||||||
{
|
{
|
||||||
std::vector<ServiceStatusObserver *>::iterator i = std::find(m_service_observers.begin(), m_service_observers.end(), obs);
|
std::vector<ServiceStatusObserver *>::iterator i = std::find(m_service_observers.begin(), m_service_observers.end(), obs);
|
||||||
ATLASSERT(i != m_service_observers.end());
|
ATLASSERT(i != m_service_observers.end());
|
||||||
if (i != m_service_observers.end())
|
if (i != m_service_observers.end())
|
||||||
{
|
{
|
||||||
m_service_observers.erase(i);
|
m_service_observers.erase(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif // SERVICECONTROL_H
|
#endif // SERVICECONTROL_H
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
!define MTDROOT "..\.."
|
!define MTDROOT "..\.."
|
||||||
!define MTD_SOURCE "${MTDROOT}\win32\Release"
|
!define MTD_SOURCE "${MTDROOT}\win32\Release"
|
||||||
!define DLL_SOURCE "${PROJROOT}\win32\dll"
|
|
||||||
!define CONFIG_SOURCE "${MTDROOT}\win32\FireflyShell\Release"
|
!define CONFIG_SOURCE "${MTDROOT}\win32\FireflyShell\Release"
|
||||||
|
!define DLL_SOURCE "${PROJROOT}\win32\dll"
|
||||||
!define ADMIN_ROOT "${MTDROOT}\admin-root"
|
!define ADMIN_ROOT "${MTDROOT}\admin-root"
|
||||||
!define REDIST_SOURCE "${PROJROOT}\win32\redist"
|
!define REDIST_SOURCE "${PROJROOT}\win32\redist"
|
||||||
|
|
||||||
@ -171,6 +171,7 @@ NoProgramItems:
|
|||||||
File "${CONFIG_SOURCE}\FireflyShell-11.dll"
|
File "${CONFIG_SOURCE}\FireflyShell-11.dll"
|
||||||
File "${CONFIG_SOURCE}\FireflyShell-10.dll"
|
File "${CONFIG_SOURCE}\FireflyShell-10.dll"
|
||||||
File "${CONFIG_SOURCE}\..\FireflyShell.exe.manifest"
|
File "${CONFIG_SOURCE}\..\FireflyShell.exe.manifest"
|
||||||
|
File "${CONFIG_SOURCE}\svcctrl.exe"
|
||||||
File "${DLL_SOURCE}\gnu_regex.dll"
|
File "${DLL_SOURCE}\gnu_regex.dll"
|
||||||
File "${DLL_SOURCE}\pthreadVC2.dll"
|
File "${DLL_SOURCE}\pthreadVC2.dll"
|
||||||
File "${DLL_SOURCE}\sqlite.dll"
|
File "${DLL_SOURCE}\sqlite.dll"
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)FireflyShell\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
ConfigurationType="1"
|
ConfigurationType="1"
|
||||||
CharacterSet="2"
|
CharacterSet="2"
|
||||||
@ -92,7 +92,7 @@
|
|||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|Win32"
|
Name="Release|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)FireflyShell\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
ConfigurationType="1"
|
ConfigurationType="1"
|
||||||
CharacterSet="2"
|
CharacterSet="2"
|
||||||
|
Loading…
Reference in New Issue
Block a user