spectrum win32 service, in progress
This commit is contained in:
parent
f68020a6ba
commit
98982a60fb
10 changed files with 364 additions and 8 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
||||||
*.pb.cc
|
*.pb.cc
|
||||||
*.pb.h
|
*.pb.h
|
||||||
|
plugin/python/protocol_pb2.py
|
|
@ -59,12 +59,8 @@ endif()
|
||||||
find_package(Boost COMPONENTS program_options date_time system filesystem regex signals REQUIRED)
|
find_package(Boost COMPONENTS program_options date_time system filesystem regex signals REQUIRED)
|
||||||
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
|
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
|
||||||
|
|
||||||
if (CMAKE_COMPILER_IS_GNUCXX)
|
|
||||||
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||||
find_package(Protobuf REQUIRED)
|
find_package(Protobuf REQUIRED)
|
||||||
else()
|
|
||||||
set(PROTOBUF_FOUND TRUE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
|
||||||
find_package(Communi)
|
find_package(Communi)
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
ADD_SUBDIRECTORY(sqlite3)
|
ADD_SUBDIRECTORY(sqlite3)
|
||||||
ADD_SUBDIRECTORY(protobuf)
|
|
|
@ -1,7 +1,15 @@
|
||||||
cmake_minimum_required(VERSION 2.6)
|
cmake_minimum_required(VERSION 2.6)
|
||||||
FILE(GLOB SRC *.cpp)
|
FILE(GLOB SRC *.cpp)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
FILE(GLOB WIN_SRC win32/*.cpp)
|
||||||
|
include_directories(win32)
|
||||||
|
ADD_EXECUTABLE(spectrum2 ${SRC} ${WIN_SRC})
|
||||||
|
else()
|
||||||
ADD_EXECUTABLE(spectrum2 ${SRC})
|
ADD_EXECUTABLE(spectrum2 ${SRC})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ADD_DEPENDENCIES(spectrum2 spectrum2_libpurple_backend)
|
ADD_DEPENDENCIES(spectrum2 spectrum2_libpurple_backend)
|
||||||
ADD_DEPENDENCIES(spectrum2 spectrum2_libircclient-qt_backend)
|
ADD_DEPENDENCIES(spectrum2 spectrum2_libircclient-qt_backend)
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#else
|
#else
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#define getpid _getpid
|
#define getpid _getpid
|
||||||
|
#include "win32/SpectrumService.h"
|
||||||
#endif
|
#endif
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
@ -143,6 +144,11 @@ int main(int argc, char **argv)
|
||||||
("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
|
("config", boost::program_options::value<std::string>(&config_file)->default_value(""), "Config file")
|
||||||
("version,v", "Shows Spectrum version")
|
("version,v", "Shows Spectrum version")
|
||||||
;
|
;
|
||||||
|
#ifdef WIN32
|
||||||
|
desc.add_options()
|
||||||
|
("install-service,i", "Install spectrum as Windows service")
|
||||||
|
("uninstall-service,u", "Uninstall Windows service");
|
||||||
|
#endif
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
boost::program_options::positional_options_description p;
|
boost::program_options::positional_options_description p;
|
||||||
|
@ -170,6 +176,46 @@ int main(int argc, char **argv)
|
||||||
if(vm.count("no-daemonize")) {
|
if(vm.count("no-daemonize")) {
|
||||||
no_daemon = true;
|
no_daemon = true;
|
||||||
}
|
}
|
||||||
|
#ifdef WIN32
|
||||||
|
if (vm.count("install-service")) {
|
||||||
|
SpectrumService ntservice;
|
||||||
|
if (!ntservice.IsInstalled()) {
|
||||||
|
// determine the name of the currently executing file
|
||||||
|
char szFilePath[MAX_PATH];
|
||||||
|
GetModuleFileName(NULL, szFilePath, sizeof(szFilePath));
|
||||||
|
std::string exe_file(szFilePath);
|
||||||
|
std::string config_file = exe_file.replace(exe_file.end() - 4, exe_file.end(), ".cfg");
|
||||||
|
std::string service_path = std::string(szFilePath) + std::string(" --config ") + config_file;
|
||||||
|
|
||||||
|
if (ntservice.Install(service_path.c_str())) {
|
||||||
|
std::cout << "Successfully installed" << std::endl;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
std::cout << "Error installing service, are you an Administrator?" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Already installed" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vm.count("uninstall-service")) {
|
||||||
|
SpectrumService ntservice;
|
||||||
|
if (ntservice.IsInstalled()) {
|
||||||
|
if (ntservice.Remove()) {
|
||||||
|
std::cout << "Successfully removed" << std::endl;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
std::cout << "Error removing service, are you an Administrator?" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Service not installed" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch (std::runtime_error& e)
|
catch (std::runtime_error& e)
|
||||||
{
|
{
|
||||||
|
@ -286,7 +332,7 @@ int main(int argc, char **argv)
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!storageBackend->connect()) {
|
else if (!storageBackend->connect()) {
|
||||||
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
19
spectrum/src/win32/SpectrumService.cpp
Normal file
19
spectrum/src/win32/SpectrumService.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "SpectrumService.h"
|
||||||
|
|
||||||
|
SpectrumService::SpectrumService(void) {
|
||||||
|
serviceName = "Spectrum2";
|
||||||
|
displayName = "Spectrum2 XMPP Transport";
|
||||||
|
username = NULL;
|
||||||
|
password = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpectrumService::~SpectrumService(void) {}
|
||||||
|
|
||||||
|
void SpectrumService::Stop() {
|
||||||
|
ReportStatus((DWORD)SERVICE_STOP_PENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpectrumService::Run(DWORD argc, LPTSTR *argv) {
|
||||||
|
ReportStatus((DWORD)SERVICE_RUNNING);
|
||||||
|
main(argc, argv);
|
||||||
|
}
|
14
spectrum/src/win32/SpectrumService.h
Normal file
14
spectrum/src/win32/SpectrumService.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include "WindowsService.h"
|
||||||
|
|
||||||
|
class SpectrumService : public WindowsService {
|
||||||
|
|
||||||
|
public:
|
||||||
|
SpectrumService(void);
|
||||||
|
~SpectrumService(void);
|
||||||
|
protected:
|
||||||
|
void Stop();
|
||||||
|
void Run(DWORD argc, LPTSTR *argv);
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv);
|
214
spectrum/src/win32/WindowsService.cpp
Normal file
214
spectrum/src/win32/WindowsService.cpp
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/* Copyright (C) 2005 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include ".\windowsservice.h"
|
||||||
|
|
||||||
|
static WindowsService *gService;
|
||||||
|
|
||||||
|
WindowsService::WindowsService(void) :
|
||||||
|
statusCheckpoint(0),
|
||||||
|
serviceName(NULL),
|
||||||
|
inited(false),
|
||||||
|
dwAcceptedControls(SERVICE_ACCEPT_STOP),
|
||||||
|
debugging(false)
|
||||||
|
{
|
||||||
|
gService= this;
|
||||||
|
status.dwServiceType= SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
status.dwServiceSpecificExitCode= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowsService::~WindowsService(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Install(const char *szFilePath)
|
||||||
|
{
|
||||||
|
bool ret_val= false;
|
||||||
|
SC_HANDLE newService;
|
||||||
|
SC_HANDLE scm;
|
||||||
|
|
||||||
|
if (IsInstalled()) return true;
|
||||||
|
|
||||||
|
// open a connection to the SCM
|
||||||
|
if (!(scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
newService= CreateService(scm, serviceName, displayName,
|
||||||
|
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
|
||||||
|
SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
|
||||||
|
szFilePath, NULL, NULL, NULL, username,
|
||||||
|
password);
|
||||||
|
|
||||||
|
if (newService)
|
||||||
|
{
|
||||||
|
CloseServiceHandle(newService);
|
||||||
|
ret_val= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Init()
|
||||||
|
{
|
||||||
|
assert(serviceName != NULL);
|
||||||
|
|
||||||
|
if (inited) return true;
|
||||||
|
|
||||||
|
SERVICE_TABLE_ENTRY stb[] =
|
||||||
|
{
|
||||||
|
{ (LPSTR)serviceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
inited= true;
|
||||||
|
return StartServiceCtrlDispatcher(stb); //register with the Service Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::Remove()
|
||||||
|
{
|
||||||
|
bool ret_val= false;
|
||||||
|
|
||||||
|
if (! IsInstalled())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// open a connection to the SCM
|
||||||
|
SC_HANDLE scm= OpenSCManager(0, 0,SC_MANAGER_CREATE_SERVICE);
|
||||||
|
if (! scm)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SC_HANDLE service= OpenService(scm, serviceName, DELETE);
|
||||||
|
if (service)
|
||||||
|
{
|
||||||
|
if (DeleteService(service))
|
||||||
|
ret_val= true;
|
||||||
|
DWORD dw= ::GetLastError();
|
||||||
|
CloseServiceHandle(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseServiceHandle(scm);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WindowsService::IsInstalled()
|
||||||
|
{
|
||||||
|
BOOL ret_val= FALSE;
|
||||||
|
|
||||||
|
SC_HANDLE scm= ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||||||
|
SC_HANDLE serv_handle= ::OpenService(scm, serviceName, SERVICE_QUERY_STATUS);
|
||||||
|
|
||||||
|
ret_val= serv_handle != NULL;
|
||||||
|
|
||||||
|
::CloseServiceHandle(serv_handle);
|
||||||
|
::CloseServiceHandle(scm);
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::SetAcceptedControls(DWORD acceptedControls)
|
||||||
|
{
|
||||||
|
dwAcceptedControls= acceptedControls;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL WindowsService::ReportStatus(DWORD currentState, DWORD waitHint,
|
||||||
|
DWORD dwError)
|
||||||
|
{
|
||||||
|
if(debugging) return TRUE;
|
||||||
|
|
||||||
|
if(currentState == SERVICE_START_PENDING)
|
||||||
|
status.dwControlsAccepted= 0;
|
||||||
|
else
|
||||||
|
status.dwControlsAccepted= dwAcceptedControls;
|
||||||
|
|
||||||
|
status.dwCurrentState= currentState;
|
||||||
|
status.dwWin32ExitCode= dwError != 0 ?
|
||||||
|
ERROR_SERVICE_SPECIFIC_ERROR : NO_ERROR;
|
||||||
|
status.dwWaitHint= waitHint;
|
||||||
|
status.dwServiceSpecificExitCode= dwError;
|
||||||
|
|
||||||
|
if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
|
||||||
|
{
|
||||||
|
status.dwCheckPoint= 0;
|
||||||
|
statusCheckpoint= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
status.dwCheckPoint= ++statusCheckpoint;
|
||||||
|
|
||||||
|
// Report the status of the service to the service control manager.
|
||||||
|
BOOL result= SetServiceStatus(statusHandle, &status);
|
||||||
|
if (!result)
|
||||||
|
Log("ReportStatus failed");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::RegisterAndRun(DWORD argc, LPTSTR *argv)
|
||||||
|
{
|
||||||
|
statusHandle= ::RegisterServiceCtrlHandler(serviceName, ControlHandler);
|
||||||
|
if (statusHandle && ReportStatus(SERVICE_START_PENDING))
|
||||||
|
Run(argc, argv);
|
||||||
|
ReportStatus(SERVICE_STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WindowsService::HandleControlCode(DWORD opcode)
|
||||||
|
{
|
||||||
|
// Handle the requested control code.
|
||||||
|
switch(opcode) {
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
// Stop the service.
|
||||||
|
status.dwCurrentState= SERVICE_STOP_PENDING;
|
||||||
|
Stop();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_PAUSE:
|
||||||
|
status.dwCurrentState= SERVICE_PAUSE_PENDING;
|
||||||
|
Pause();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_CONTINUE:
|
||||||
|
status.dwCurrentState= SERVICE_CONTINUE_PENDING;
|
||||||
|
Continue();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
Shutdown();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_INTERROGATE:
|
||||||
|
ReportStatus(status.dwCurrentState);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// invalid control code
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI WindowsService::ServiceMain(DWORD argc, LPTSTR *argv)
|
||||||
|
{
|
||||||
|
assert(gService != NULL);
|
||||||
|
|
||||||
|
// register our service control handler:
|
||||||
|
gService->RegisterAndRun(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI WindowsService::ControlHandler(DWORD opcode)
|
||||||
|
{
|
||||||
|
assert(gService != NULL);
|
||||||
|
|
||||||
|
return gService->HandleControlCode(opcode);
|
||||||
|
}
|
58
spectrum/src/win32/WindowsService.h
Normal file
58
spectrum/src/win32/WindowsService.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright (C) 2005 MySQL AB
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 of the License.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class WindowsService
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool inited;
|
||||||
|
const char *serviceName;
|
||||||
|
const char *displayName;
|
||||||
|
const char *username;
|
||||||
|
const char *password;
|
||||||
|
SERVICE_STATUS_HANDLE statusHandle;
|
||||||
|
DWORD statusCheckpoint;
|
||||||
|
SERVICE_STATUS status;
|
||||||
|
DWORD dwAcceptedControls;
|
||||||
|
bool debugging;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WindowsService(void);
|
||||||
|
~WindowsService(void);
|
||||||
|
|
||||||
|
BOOL Install(const char *szFilePath);
|
||||||
|
BOOL Remove();
|
||||||
|
BOOL Init();
|
||||||
|
BOOL IsInstalled();
|
||||||
|
void SetAcceptedControls(DWORD acceptedControls);
|
||||||
|
void Debug(bool debugFlag) { debugging= debugFlag; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
|
||||||
|
static void WINAPI ControlHandler(DWORD CtrlType);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void Run(DWORD argc, LPTSTR *argv)= 0;
|
||||||
|
virtual void Stop() {}
|
||||||
|
virtual void Shutdown() {}
|
||||||
|
virtual void Pause() {}
|
||||||
|
virtual void Continue() {}
|
||||||
|
virtual void Log(const char *msg) {}
|
||||||
|
|
||||||
|
BOOL ReportStatus(DWORD currentStatus, DWORD waitHint= 3000, DWORD dwError=0);
|
||||||
|
void HandleControlCode(DWORD opcode);
|
||||||
|
void RegisterAndRun(DWORD argc, LPTSTR *argv);
|
||||||
|
};
|
|
@ -55,12 +55,13 @@ bool Config::load(const std::string &configfile, boost::program_options::options
|
||||||
m_file = configfile;
|
m_file = configfile;
|
||||||
bool ret = load(ifs, opts, jid);
|
bool ret = load(ifs, opts, jid);
|
||||||
ifs.close();
|
ifs.close();
|
||||||
|
#ifndef WIN32
|
||||||
char path[PATH_MAX] = "";
|
char path[PATH_MAX] = "";
|
||||||
if (m_file.find_first_of("/") != 0) {
|
if (m_file.find_first_of("/") != 0) {
|
||||||
getcwd(path, PATH_MAX);
|
getcwd(path, PATH_MAX);
|
||||||
m_file = std::string(path) + "/" + m_file;
|
m_file = std::string(path) + "/" + m_file;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue