spectrum win32 service, in progress

This commit is contained in:
Vitaly Takmazov 2012-08-01 13:26:04 +04:00
parent f68020a6ba
commit 98982a60fb
10 changed files with 364 additions and 8 deletions

3
.gitignore vendored
View file

@ -1,2 +1,3 @@
*.pb.cc
*.pb.h
*.pb.h
plugin/python/protocol_pb2.py

View file

@ -59,12 +59,8 @@ endif()
find_package(Boost COMPONENTS program_options date_time system filesystem regex signals REQUIRED)
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
if (CMAKE_COMPILER_IS_GNUCXX)
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Protobuf REQUIRED)
else()
set(PROTOBUF_FOUND TRUE)
endif()
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Communi)

View file

@ -1,2 +1 @@
ADD_SUBDIRECTORY(sqlite3)
ADD_SUBDIRECTORY(protobuf)

View file

@ -1,7 +1,15 @@
cmake_minimum_required(VERSION 2.6)
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})
endif()
ADD_DEPENDENCIES(spectrum2 spectrum2_libpurple_backend)
ADD_DEPENDENCIES(spectrum2 spectrum2_libircclient-qt_backend)

View file

@ -26,6 +26,7 @@
#else
#include <process.h>
#define getpid _getpid
#include "win32/SpectrumService.h"
#endif
#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")
("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
{
boost::program_options::positional_options_description p;
@ -170,6 +176,46 @@ int main(int argc, char **argv)
if(vm.count("no-daemonize")) {
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)
{
@ -286,7 +332,7 @@ int main(int argc, char **argv)
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";
return -1;
}

View 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);
}

View 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);

View 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);
}

View 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);
};

View file

@ -55,12 +55,13 @@ bool Config::load(const std::string &configfile, boost::program_options::options
m_file = configfile;
bool ret = load(ifs, opts, jid);
ifs.close();
#ifndef WIN32
char path[PATH_MAX] = "";
if (m_file.find_first_of("/") != 0) {
getcwd(path, PATH_MAX);
m_file = std::string(path) + "/" + m_file;
}
#endif
return ret;
}