mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
773 lines
16 KiB
C++
773 lines
16 KiB
C++
/*************************************************************************
|
|
* UrBackup - Client/Server backup system
|
|
* Copyright (C) 2011-2016 Martin Raiber
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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 Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
**************************************************************************/
|
|
|
|
#include "vld.h"
|
|
#define DEF_SERVER
|
|
#ifdef _WIN32
|
|
#include <ws2tcpip.h>
|
|
#endif
|
|
#include "Server.h"
|
|
#include "AcceptThread.h"
|
|
#include "SessionMgr.h"
|
|
#include "LoadbalancerClient.h"
|
|
#include "libs.h"
|
|
#ifdef USE_SYSTEM_SQLITE
|
|
#include <sqlite3.h>
|
|
#else
|
|
#include "sqlite/sqlite3.h"
|
|
#endif
|
|
#include "stringtools.h"
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <conio.h>
|
|
#include <signal.h>
|
|
#endif
|
|
#ifdef AS_SERVICE
|
|
# include "win_service/nt_service.h"
|
|
using namespace nt;
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
# include <sys/types.h>
|
|
# include <pwd.h>
|
|
# include <sys/wait.h>
|
|
# include <grp.h>
|
|
# include <errno.h>
|
|
#endif
|
|
|
|
#ifdef __ANDROID__
|
|
int getdtablesize() { return 1024; }
|
|
#endif
|
|
|
|
IServer *Server=NULL;
|
|
|
|
using namespace std;
|
|
|
|
bool run=true;
|
|
bool no_server=false;
|
|
namespace
|
|
{
|
|
std::string g_logfile;
|
|
std::string g_logfile_user;
|
|
}
|
|
|
|
void init_mutex_selthread(void);
|
|
void destroy_mutex_selthread(void);
|
|
|
|
#ifndef _WIN32
|
|
void termination_handler(int signum)
|
|
{
|
|
run=false;
|
|
Server->Log("Shutting down (Signal "+convert(signum)+")", LL_WARNING);
|
|
}
|
|
|
|
void hub_handler(int signum)
|
|
{
|
|
if(!g_logfile.empty())
|
|
{
|
|
Server->setLogFile(g_logfile, g_logfile_user);
|
|
}
|
|
}
|
|
#else
|
|
void abort_handler(int signal)
|
|
{
|
|
Server->Log("Program abort (SIGABRT)", LL_ERROR);
|
|
RaiseException(0, 0, 0, NULL);
|
|
}
|
|
|
|
void invalid_parameter_handler(const wchar_t* expression,
|
|
const wchar_t* function,
|
|
const wchar_t* file,
|
|
unsigned int line,
|
|
uintptr_t pReserved)
|
|
{
|
|
Server->Log("Invalid parameter detected in function " + Server->ConvertFromWchar(function) +
|
|
" File: " + Server->ConvertFromWchar(file) + " Line: " + convert(line) + " Expression: " + Server->ConvertFromWchar(expression), LL_ERROR);
|
|
RaiseException(0, 0, 0, NULL);
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef AS_SERVICE
|
|
char **srv_argv;
|
|
int srv_argc;
|
|
#endif
|
|
|
|
void DisplayHelp(void)
|
|
{
|
|
cout << "CServer - Compiled C++ Server" << endl;
|
|
cout << "CServer [--port 34255] [--workers 3] [--plugin x] [--loadbalancer 192.168.0.1] [--lb-weight 1] [--lb-port 2304]" << endl;
|
|
}
|
|
|
|
CAcceptThread *c_at=NULL;
|
|
|
|
int main_fkt(int argc, char *argv[]);
|
|
|
|
int main_fkt_catch(int argc, char *argv[])
|
|
{
|
|
try
|
|
{
|
|
return main_fkt(argc, argv);
|
|
}
|
|
catch (std::exception& e)
|
|
{
|
|
Server->Log(std::string("Main thread exit with unhandled std::exception ") + e.what(), LL_ERROR);
|
|
throw;
|
|
}
|
|
catch (...)
|
|
{
|
|
Server->Log(std::string("Main thread exit with unhandled C++ exception "), LL_ERROR);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
#ifndef AS_SERVICE
|
|
|
|
#ifdef _WIN32
|
|
#define MAINNAME main
|
|
#else
|
|
#define MAINNAME real_main
|
|
#endif
|
|
|
|
int MAINNAME(int argc, char *argv[])
|
|
{
|
|
#else //AS_SERVICE
|
|
int my_init_fcn_t(int argc, char *argv[])
|
|
{
|
|
#endif
|
|
#if !defined(_DEBUG) && defined(_WIN32)
|
|
__try{
|
|
#endif
|
|
#if defined(_DEBUG)
|
|
return main_fkt(argc, argv);
|
|
#else
|
|
return main_fkt_catch(argc, argv);
|
|
#endif
|
|
#if !defined(_DEBUG) && defined(_WIN32)
|
|
}__except(CServer::WriteDump(GetExceptionInformation()) )
|
|
{
|
|
}
|
|
return 101;
|
|
#endif
|
|
}
|
|
|
|
int main_fkt(int argc, char *argv[])
|
|
{
|
|
CServer* Server=new CServer;
|
|
::Server = Server;
|
|
Server->setup();
|
|
|
|
#ifdef _WIN32
|
|
int rc;
|
|
|
|
WSADATA wsadata;
|
|
rc = WSAStartup(MAKEWORD(2,2), &wsadata);
|
|
if(rc == SOCKET_ERROR)
|
|
{
|
|
Server->Log("Error starting Winsock 2.2", LL_ERROR);
|
|
return 23;
|
|
}
|
|
#endif
|
|
|
|
srand(Server->getSecureRandomNumber());
|
|
|
|
//Parse Parameters
|
|
|
|
int port=34255;
|
|
int workers=5;
|
|
|
|
std::vector<std::string> plugins;
|
|
|
|
std::string loadbalancer;
|
|
int loadbalancer_weight=1;
|
|
int loadbalancer_port=2305;
|
|
|
|
if( argc==2 && (std::string)argv[1]=="--version" )
|
|
{
|
|
cout << "CServer version 0.1.0.0" << endl;
|
|
return 1;
|
|
}
|
|
|
|
if( argc==2 && ( (std::string)argv[1]=="--help" || (std::string)argv[1]=="-h") )
|
|
{
|
|
DisplayHelp();
|
|
return 6;
|
|
}
|
|
|
|
std::map<std::string, std::string> srv_params;
|
|
|
|
std::string loglevel;
|
|
std::string logfile;
|
|
std::string workingdir;
|
|
bool daemon=false;
|
|
std::string daemon_user;
|
|
std::string pidfile;
|
|
bool log_console_no_time=false;
|
|
|
|
for(int i=1;i<argc;++i)
|
|
{
|
|
std::string carg=argv[i];
|
|
std::string narg;
|
|
if( i+1<argc )
|
|
narg=argv[i+1];
|
|
|
|
if( carg=="--daemon" || carg=="-d" )
|
|
{
|
|
daemon=true;
|
|
}
|
|
else if( carg=="--user" || carg=="-u" )
|
|
{
|
|
daemon_user=narg;
|
|
++i;
|
|
}
|
|
else if( carg=="--workingdir" )
|
|
{
|
|
workingdir=narg;
|
|
++i;
|
|
}
|
|
else if( carg=="--port" || carg=="-p" )
|
|
{
|
|
port=atoi( narg.c_str() );
|
|
++i;
|
|
}
|
|
else if( carg=="--workers" || carg=="-w" )
|
|
{
|
|
workers=atoi( narg.c_str() );
|
|
++i;
|
|
}
|
|
else if( carg=="--plugin" || carg=="-p" || carg=="--add" || carg=="-a")
|
|
{
|
|
plugins.push_back( narg );
|
|
++i;
|
|
}
|
|
else if( carg=="--loadbalancer" || carg=="-lb" )
|
|
{
|
|
loadbalancer=narg;
|
|
++i;
|
|
}
|
|
else if( carg=="--lb-weight" || carg=="-lbw" )
|
|
{
|
|
loadbalancer_weight=atoi( narg.c_str() );
|
|
++i;
|
|
}
|
|
else if( carg=="--lb-port" || carg=="-lbp" )
|
|
{
|
|
loadbalancer_port=atoi( narg.c_str() );
|
|
++i;
|
|
}
|
|
else if( carg=="--no-server" || carg=="-n" )
|
|
{
|
|
no_server=true;
|
|
}
|
|
else if (carg=="--loglevel" || carg=="-ll" )
|
|
{
|
|
loglevel=strlower(narg);
|
|
++i;
|
|
}
|
|
else if (carg=="--logfile" || carg=="-lf" )
|
|
{
|
|
logfile=narg;
|
|
++i;
|
|
}
|
|
else if( carg=="--pidfile" )
|
|
{
|
|
pidfile=narg;
|
|
++i;
|
|
}
|
|
else if( carg=="--rotate-filesize")
|
|
{
|
|
Server->setLogRotationFilesize(atoi(narg.c_str()));
|
|
++i;
|
|
}
|
|
else if( carg=="--rotate-numfiles")
|
|
{
|
|
Server->setLogRotationNumFiles(atoi(narg.c_str()));
|
|
++i;
|
|
}
|
|
else if( carg=="--log_console_no_time")
|
|
{
|
|
log_console_no_time = true;
|
|
}
|
|
else
|
|
{
|
|
if( carg.size()>1 && carg[0]=='-' )
|
|
{
|
|
std::string p;
|
|
if( carg[1]=='-' && carg.size()>2 )
|
|
p=carg.substr(2, carg.size()-2);
|
|
else
|
|
p=carg.substr(1, carg.size()-1);
|
|
|
|
std::string v;
|
|
|
|
if( narg.size()>0 && narg[0]!='-' )
|
|
{
|
|
v=narg;
|
|
++i;
|
|
}
|
|
else
|
|
{
|
|
size_t g=p.find_last_of("=");
|
|
if(g!=std::string::npos)
|
|
{
|
|
v=p.substr(g+1);
|
|
p=p.substr(0,g);
|
|
}
|
|
else
|
|
{
|
|
v="true";
|
|
}
|
|
}
|
|
|
|
|
|
srv_params[p]=v;
|
|
}
|
|
}
|
|
}
|
|
|
|
Server->setServerParameters(srv_params);
|
|
|
|
if(workingdir.empty())
|
|
{
|
|
#ifdef _WIN32
|
|
#ifndef AS_SERVICE
|
|
{
|
|
wchar_t buf[MAX_PATH];
|
|
GetCurrentDirectoryW(MAX_PATH, buf);
|
|
Server->setServerWorkingDir(Server->ConvertFromWchar(buf));
|
|
}
|
|
#else
|
|
{
|
|
wchar_t buf[MAX_PATH+1];
|
|
GetModuleFileNameW(NULL, buf, MAX_PATH);
|
|
Server->setServerWorkingDir(ExtractFilePath(Server->ConvertFromWchar(buf)));
|
|
SetCurrentDirectoryW(Server->ConvertToWchar(ExtractFilePath(Server->ConvertFromWchar(buf))).c_str());
|
|
}
|
|
#endif
|
|
#else
|
|
char buf[4096];
|
|
char* cwd = getcwd(buf, sizeof(buf));
|
|
if(cwd==NULL)
|
|
{
|
|
Server->setServerWorkingDir((ExtractFilePath(argv[0])));
|
|
}
|
|
else
|
|
{
|
|
Server->setServerWorkingDir((cwd));
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
Server->setServerWorkingDir((workingdir));
|
|
#ifndef _WIN32
|
|
int rc = chdir((Server->getServerWorkingDir()).c_str());
|
|
if(rc!=0)
|
|
{
|
|
Server->Log("Cannot set working directory to directory "+workingdir, LL_ERROR);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifndef _WIN32
|
|
if(daemon)
|
|
{
|
|
size_t pid1;
|
|
if( (pid1=fork())==0 )
|
|
{
|
|
setsid();
|
|
if(fork()==0)
|
|
{
|
|
for (int i=getdtablesize();i>=0;--i) close(i);
|
|
int i=open("/dev/null",O_RDWR);
|
|
dup(i);
|
|
dup(i);
|
|
}
|
|
else
|
|
{
|
|
exit(0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int status;
|
|
waitpid(pid1, &status, 0);
|
|
exit(0);
|
|
}
|
|
|
|
int rc = chdir((Server->getServerWorkingDir()).c_str());
|
|
if (rc != 0)
|
|
{
|
|
Server->Log("Cannot set working directory to directory " + workingdir+" (2)", LL_ERROR);
|
|
}
|
|
|
|
if(pidfile.empty())
|
|
{
|
|
pidfile="/var/run/urbackup_srv.pid";
|
|
}
|
|
|
|
std::fstream pf;
|
|
pf.open(pidfile.c_str(), std::ios::out|std::ios::binary);
|
|
if(pf.is_open())
|
|
{
|
|
pf << getpid();
|
|
pf.close();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if(!logfile.empty())
|
|
{
|
|
g_logfile=logfile;
|
|
g_logfile_user=daemon_user;
|
|
Server->setLogFile(logfile, daemon_user);
|
|
}
|
|
|
|
|
|
if(!loglevel.empty())
|
|
{
|
|
if(FileExists("debug_logging_enabled"))
|
|
Server->setLogLevel(LL_DEBUG);
|
|
else if(loglevel=="debug")
|
|
Server->setLogLevel(LL_DEBUG);
|
|
else if(loglevel=="warn")
|
|
Server->setLogLevel(LL_WARNING);
|
|
else if(loglevel=="info")
|
|
Server->setLogLevel(LL_INFO);
|
|
else if(loglevel=="error")
|
|
Server->setLogLevel(LL_ERROR);
|
|
}
|
|
|
|
if(log_console_no_time)
|
|
{
|
|
Server->setLogConsoleTime(false);
|
|
}
|
|
|
|
if(is_big_endian())
|
|
{
|
|
Server->setLogLevel(LL_DEBUG);
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
if( !daemon_user.empty() && (getuid()==0 || geteuid()==0) )
|
|
{
|
|
char buf[1000];
|
|
passwd pwbuf;
|
|
passwd *pw;
|
|
int rc=getpwnam_r(daemon_user.c_str(), &pwbuf, buf, 1000, &pw);
|
|
if(pw!=NULL)
|
|
{
|
|
if (setgroups(0, NULL) != 0)
|
|
{
|
|
Server->Log("Unable to drop groups. Errno: " + convert(errno), LL_ERROR);
|
|
return 44;
|
|
}
|
|
if (setgid(pw->pw_gid) != 0)
|
|
{
|
|
Server->Log("Unable to set group to gid "+convert(pw->pw_gid)+" of user \""+daemon_user+"\". Errno: " + convert(errno), LL_ERROR);
|
|
return 44;
|
|
}
|
|
if (setuid(pw->pw_uid) != 0)
|
|
{
|
|
Server->Log("Unable to set user to uid " + convert(pw->pw_gid) + " of user \"" + daemon_user + "\". Errno: " + convert(errno), LL_ERROR);
|
|
return 44;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Server->Log("Cannot get uid and gid of user \"" + daemon_user + "\" -1. Errno: " + convert(errno), LL_ERROR);
|
|
return 44;
|
|
}
|
|
}
|
|
else if (!daemon_user.empty())
|
|
{
|
|
char buf[1000];
|
|
passwd pwbuf;
|
|
passwd *pw;
|
|
int rc = getpwnam_r(daemon_user.c_str(), &pwbuf, buf, 1000, &pw);
|
|
if (pw != NULL)
|
|
{
|
|
if (pw->pw_uid != getuid())
|
|
{
|
|
Server->Log("Running as wrong user. Specified user \"" + daemon_user + "\" with uid "+convert(pw->pw_uid)+" but running as uid "+convert(getuid()), LL_ERROR);
|
|
return 44;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Server->Log("Cannot get uid of user \""+daemon_user+"\". Errno: " + convert(errno), LL_ERROR);
|
|
return 44;
|
|
}
|
|
}
|
|
#endif
|
|
if( sqlite3_threadsafe()==0 )
|
|
{
|
|
Server->Log("SQLite3 wasn't compiled with the SQLITE_THREADSAFE. Exiting.", LL_ERROR);
|
|
return 43;
|
|
}
|
|
|
|
sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
|
|
//sqlite3_enable_shared_cache(1);
|
|
|
|
{
|
|
str_map::iterator iter=srv_params.find("sqlite_tmpdir");
|
|
if(iter!=srv_params.end() && !iter->second.empty())
|
|
{
|
|
sqlite3_temp_directory=sqlite3_mprintf("%s", iter->second.c_str());
|
|
}
|
|
}
|
|
|
|
|
|
for( size_t i=0;i<plugins.size();++i)
|
|
{
|
|
if( !Server->LoadDLL(plugins[i]) )
|
|
{
|
|
Server->Log("Loading "+(std::string)plugins[i]+" failed", LL_ERROR);
|
|
}
|
|
}
|
|
|
|
Server->LoadStaticPlugins();
|
|
|
|
CLoadbalancerClient *lbs=NULL;
|
|
if( loadbalancer!="" )
|
|
{
|
|
lbs=new CLoadbalancerClient( loadbalancer, loadbalancer_port, loadbalancer_weight, port);
|
|
|
|
Server->createThread(lbs);
|
|
}
|
|
|
|
#ifndef _WIN32
|
|
if (signal (SIGINT, termination_handler) == SIG_IGN)
|
|
signal (SIGINT, SIG_IGN);
|
|
/*if(!daemon)
|
|
{
|
|
if (signal (SIGHUP, termination_handler) == SIG_IGN)
|
|
signal (SIGHUP, SIG_IGN);
|
|
}
|
|
else*/
|
|
{
|
|
if (signal (SIGHUP, hub_handler) == SIG_IGN)
|
|
signal (SIGHUP, SIG_IGN);
|
|
}
|
|
if (signal (SIGTERM, termination_handler) == SIG_IGN)
|
|
signal (SIGTERM, SIG_IGN);
|
|
#else
|
|
signal(SIGABRT, abort_handler);
|
|
_set_invalid_parameter_handler(invalid_parameter_handler);
|
|
#endif
|
|
|
|
((CSessionMgr*)Server->getSessionMgr())->startTimeoutSessionThread();
|
|
|
|
Server->startupComplete();
|
|
|
|
if(no_server==false )
|
|
{
|
|
init_mutex_selthread();
|
|
c_at=new CAcceptThread(workers, port);
|
|
if(c_at->has_error())
|
|
{
|
|
Server->Log("Error while starting listening to ports. Stopping server.", LL_ERROR);
|
|
run=false;
|
|
}
|
|
#ifndef AS_SERVICE
|
|
while(run==true)
|
|
{
|
|
(*c_at)(true);
|
|
#ifdef _WIN32
|
|
if( _kbhit()!=0 )
|
|
{
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Server->Log("Exited Loop");
|
|
|
|
Server->Log("Deleting at..");
|
|
delete c_at;
|
|
|
|
destroy_mutex_selthread();
|
|
}
|
|
else
|
|
{
|
|
while(run==true)
|
|
{
|
|
Server->wait(1000);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifndef AS_SERVICE
|
|
Server->Log("Deleting lbs...");
|
|
delete lbs;
|
|
Server->Log("Shutting down plugins...");
|
|
Server->ShutdownPlugins();
|
|
|
|
Server->Log("Deleting server...");
|
|
delete Server;
|
|
|
|
sqlite3_free(sqlite3_temp_directory);
|
|
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
#ifdef AS_SERVICE
|
|
void WINAPI my_service_main(DWORD argc, char_* argv[])
|
|
{
|
|
if( c_at!=NULL )
|
|
{
|
|
(*c_at)(true);
|
|
}
|
|
else if(no_server==false)
|
|
{
|
|
Sleep(500);
|
|
//throw std::exception("Service stopped");
|
|
}
|
|
else
|
|
{
|
|
Sleep(500);
|
|
}
|
|
}
|
|
void my_shutdown_fcn(void)
|
|
{
|
|
/*if(c_at !=NULL )
|
|
{
|
|
delete c_at;
|
|
destroy_mutex_selthread();
|
|
c_at=NULL;
|
|
}
|
|
if(Server!=NULL)
|
|
{
|
|
delete Server;
|
|
Server=NULL;
|
|
}*/
|
|
if (Server != NULL)
|
|
{
|
|
static_cast<CServer*>(Server)->ShutdownPlugins();
|
|
}
|
|
nt_service& service = nt_service::instance(L"UrBackupBackend");
|
|
service.stop(0);
|
|
}
|
|
void my_stop_fcn(void)
|
|
{
|
|
/*if(c_at !=NULL )
|
|
{
|
|
CAcceptThread *tmp=c_at;
|
|
c_at=NULL;
|
|
delete tmp;
|
|
delete Server;
|
|
}
|
|
if(Server!=NULL)
|
|
{
|
|
CServer *srv=Server;
|
|
Server=NULL;
|
|
delete srv;
|
|
}*/
|
|
if(Server!=NULL)
|
|
{
|
|
static_cast<CServer*>(Server)->ShutdownPlugins();
|
|
}
|
|
nt_service& service = nt_service::instance(L"UrBackupBackend");
|
|
service.stop(0);
|
|
}
|
|
|
|
void my_init_fcn(void)
|
|
{
|
|
my_init_fcn_t(srv_argc, srv_argv);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
SetCurrentDirectoryA(ExtractFilePath(argv[0]).c_str() );
|
|
if( argc>1 && (std::string)argv[1]=="--cmdline" )
|
|
{
|
|
srv_argv=argv;
|
|
srv_argc=argc;
|
|
}
|
|
else
|
|
{
|
|
std::string args=trim(getFile("args.txt"));
|
|
|
|
for (size_t i = 0; i < 10; ++i)
|
|
{
|
|
std::string extra_args = trim(getFile("extra_args_" + convert(i) + ".txt"));
|
|
if (!extra_args.empty())
|
|
{
|
|
args += "\n" + extra_args;
|
|
}
|
|
}
|
|
|
|
int lc=linecount(args);
|
|
srv_argv=new char*[lc+1];
|
|
srv_argv[0]=new char[strlen(argv[0])+1];
|
|
strcpy_s(srv_argv[0], strlen(argv[0])+1, argv[0]);
|
|
for(int i=0;i<lc;++i)
|
|
{
|
|
std::string l=trim(getline(i, args));
|
|
std::cout << l << std::endl;
|
|
srv_argv[i+1]=new char[l.size()+1];
|
|
memcpy(srv_argv[i+1], &l[0], l.size());
|
|
srv_argv[i+1][l.size()]=0;
|
|
}
|
|
|
|
srv_argc=lc+1;
|
|
}
|
|
|
|
if( argc>1 && ( (std::string)argv[1]=="pgo" || (std::string)argv[1]=="cmdline" || (std::string)argv[1]=="--cmdline" ) )
|
|
{
|
|
my_init_fcn();
|
|
|
|
while(true)
|
|
{
|
|
my_service_main(0,NULL);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// creates an access point to the instance of the service framework
|
|
nt_service& service = nt_service::instance(L"UrBackupBackend");
|
|
|
|
// register "my_service_main" to be executed as the service main method
|
|
service.register_service_main( my_service_main );
|
|
|
|
// register "my_init_fcn" as initialization fcn
|
|
service.register_init_function( my_init_fcn );
|
|
|
|
// config the service to accepts stop controls. Do nothing when it happens
|
|
//service.accept_control( SERVICE_ACCEPT_STOP );
|
|
service.register_control_handler( SERVICE_CONTROL_STOP, my_stop_fcn );
|
|
|
|
// config the service to accepts shutdown controls and do something when receive it
|
|
service.register_control_handler( SERVICE_CONTROL_SHUTDOWN, my_shutdown_fcn );
|
|
|
|
service.start();
|
|
}
|
|
}
|
|
#endif
|