Windows NTService 后台框架封装

时间:2023-02-12 16:11:24

  对于后台运行的程序,比如基于C/S架构的服务器、各种监控系统的程序、或者是程序额外的功能需要后台运行来实现,在Windows平台中,服务经常会用到,这种对于需要24×7运行的程序是必备的,至少本人经常需要运用windows服务来搭建后台程序。于是查阅网上的各种资料,发现有不少的参考实例,但是使用起来有各种问题,不少是这些作者或者使用者对Windows NT Service API接口运用的不熟练或者不清楚,导致自己花费很多时间在理解这些错误的实例当中,不过折腾到最后,还是从错误中得到不少教训的。所以为了方便以后能够直接使用,不再做重复的工作,便在工作之余将Windows NT Service API接口进行了二次封装并简单的测试通过,发上来也让大家使用并指正其中的错误。

  当然,有更权威的参考实例。http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx

  废话不多说, 先直接贴上代码,希望不要被贱笑了...

  NTService.h

#ifndef _NTSERVICE_H_
#define _NTSERVICE_H_ ///服务启动类型定义
enum SERVICE_STARTUP_TYPE
{
//禁用不可启动
SST_DISABLED=, //随系统启动自动启动
SST_AUTO_START=, //命令/手动启动
SST_DEMAND_START=
}; ///服务执行的任务对象
class ServiceTask
{
public:
ServiceTask(){}
virtual ~ServiceTask(){} public:
///服务初始化通知
///@return 成功返回0, 否则-1
///@remark 完成后需及时返回, 不能长时间阻塞
virtual int OnInit(int argc, char **argv){return ;} ///服务启动通知
///@remark 服务启动阻塞执行此过程, 直至服务停止/关闭
virtual void OnStart(){} ///服务停止通知
///@remark OnStart结束返回, 服务变为停止状态
virtual void OnStop(){} ///服务暂停通知
///@remark OnStart暂停执行, 服务变为暂停状态
virtual void OnPause(){} ///被暂停的服务恢复通知
///@remark OnStart恢复执行, 服务变为恢复状态
virtual void OnContinue(){} ///服务被强制关闭通知
///@remark 通常是OS关闭时发生
virtual void OnShutdown(){}
}; class NTServiceImpl; ///服务接口控制对象
class NTService
{
public:
///@param name服务名称
///@param canstop是否可停止
///@param canshutdown是否可关闭
///@param canpausecontinue是否可暂停继续
NTService(const char *name,
bool canstop=true,
bool canshutdown=true,
bool canpausecontinue=false); ~NTService(); public:
///检查服务是否安装
bool IsInstalled(); ///安装服务
///@param display_name服务显示的名称
///@param type服务启动类型
///@return 成功返回0, 否则-1
int Install(const char *display_name, SERVICE_STARTUP_TYPE type); ///卸载服务
///@return 成功返回0, 否则-1
int UnInstall(); ///设置服务启动类型
///@return 成功返回0, 否则-1
int SetStartupType(SERVICE_STARTUP_TYPE type); ///更新服务描述信息
///@return 成功返回0, 否则-1
int UpdateDesc(const char *desc); ///启动服务
///@return 成功返回0, 否则-1
///@param argc启动参数个数
///@param argv启动参数列表
int Start(int argc=, const char **argv=); ///停止服务
///@return 成功返回0, 否则-1
int Stop(); ///获取服务当前状态
///@return 成功返回状态值, 否则-1
int GetCurrentStatus(); public:
///系统启动服务调用
///@remark 不可主动调用
int Run(ServiceTask &service); private:
NTServiceImpl *m_impl;
}; #endif//_NTSERVICE_H_

  NTServiceImpl.h

  

#ifndef _NTSERVICE_IMPL_H_
#define _NTSERVICE_IMPL_H_
#include "NTService.h"
#include <Windows.h>
#include <string> class NTServiceImpl
{
public:
NTServiceImpl(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue); ~NTServiceImpl(); public:
bool IsInstalled();
int Install(const char *display_name, SERVICE_STARTUP_TYPE type);
int UnInstall();
int SetStartupType(SERVICE_STARTUP_TYPE type);
int UpdateDesc(const char *desc);
int Start(int argc, const char **argv);
int Stop();
int GetCurrentStatus(); int Run(ServiceTask &service); private:
std::string m_name;
bool m_canstop;
bool m_canshutdown;
bool m_canpausecontinue;
}; class NTServiceManager
{
private:
NTServiceManager();
~NTServiceManager(); public:
static bool IsInstalled(const char *name);
static int Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type);
static int UnInstall(const char *name);
static int SetStartupType(const char *name, SERVICE_STARTUP_TYPE type);
static int UpdateDesc(const char *name, const char *desc);
static int Start(const char *name, int argc, const char **argv);
static int Stop(const char *name);
static int GetCurrentStatus(const char *name); private:
static int GetRealStartupType(SERVICE_STARTUP_TYPE type);
}; class NTServiceHandler
{
private:
NTServiceHandler(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service); ~NTServiceHandler(); public:
static void CreateInstance(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service)
{
DestroyInstance();
m_this =new NTServiceHandler(name, canstop, canshutdown, canpausecontinue, service);
}
static NTServiceHandler *GetInstance()
{
return m_this;
}
static void DestroyInstance()
{
if (m_this)
{
delete m_this;
m_this = ;
}
} public:
int Run(); private:
static void ServiceMainHandler(DWORD argc, LPSTR *argv);
static void ServiceCtrlHandler(DWORD ctrl); private:
void NTS_Start(DWORD argc, LPSTR *argv);
void NTS_Stop();
void NTS_Pause();
void NTS_Continue();
void NTS_Shutdown(); void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode=NO_ERROR,
DWORD dwWaitHint=); int OnInit(int argc, char **argv);
void OnStart();
void OnStop();
void OnPause();
void OnContinue();
void OnShutdown(); private:
std::string m_name;
ServiceTask &m_service; SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_status_handle; static NTServiceHandler *m_this;
}; NTServiceHandler *NTServiceHandler::m_this = ; #endif//_NTSERVICE_IMPL_H_

  NTServiceImpl.cpp

#include "NTServiceImpl.h"
#include <assert.h> NTService::NTService(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue)
{
m_impl = new NTServiceImpl(name, canstop, canshutdown, canpausecontinue);
}
NTService::~NTService()
{
if (m_impl)
{
delete m_impl;
m_impl = ;
}
}
bool NTService::IsInstalled()
{
return m_impl->IsInstalled();
}
int NTService::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
{
return m_impl->Install(display_name, type);
}
int NTService::UnInstall()
{
return m_impl->UnInstall();
}
int NTService::SetStartupType(SERVICE_STARTUP_TYPE type)
{
return m_impl->SetStartupType(type);
}
int NTService::UpdateDesc(const char *desc)
{
return m_impl->UpdateDesc(desc);
}
int NTService::Start(int argc, const char **argv)
{
return m_impl->Start(argc, argv);
}
int NTService::Stop()
{
return m_impl->Stop();
}
int NTService::GetCurrentStatus()
{
return m_impl->GetCurrentStatus();
}
int NTService:: Run(ServiceTask &service)
{
return m_impl->Run(service);
} NTServiceImpl::NTServiceImpl(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue)
: m_name(name)
{
m_canstop = canstop;
m_canshutdown = canshutdown;
m_canpausecontinue = canpausecontinue;
} NTServiceImpl::~NTServiceImpl()
{
} bool NTServiceImpl::IsInstalled()
{
return NTServiceManager::IsInstalled(m_name.c_str());
} int NTServiceImpl::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
{
return NTServiceManager::Install(m_name.c_str(), display_name, type);
} int NTServiceImpl::UnInstall()
{
return NTServiceManager::UnInstall(m_name.c_str());
} int NTServiceImpl::Start(int argc, const char **argv)
{
return NTServiceManager::Start(m_name.c_str(), argc, argv);
} int NTServiceImpl::Stop()
{
return NTServiceManager::Stop(m_name.c_str());
} int NTServiceImpl::SetStartupType(SERVICE_STARTUP_TYPE type)
{
return NTServiceManager::SetStartupType(m_name.c_str(), type);
} int NTServiceImpl::UpdateDesc(const char *desc)
{
return NTServiceManager::UpdateDesc(m_name.c_str(), desc);
} int NTServiceImpl::GetCurrentStatus()
{
return NTServiceManager::GetCurrentStatus(m_name.c_str());
} int NTServiceImpl::Run(ServiceTask &service)
{
NTServiceHandler::CreateInstance(m_name, m_canstop, m_canshutdown, m_canpausecontinue, service);
NTServiceHandler *handler = NTServiceHandler::GetInstance();
return handler ? handler->Run() : -;
} bool NTServiceManager::IsInstalled(const char *name)
{
assert(name); bool result = false;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS); __Cleanup:
if (service)
{
result = true;
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type)
{
assert(name && display_name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE);
if (!scmanager)
{
goto __Cleanup;
} char file_path[MAX_PATH] = {};
::GetModuleFileName(NULL, file_path, MAX_PATH); int startup_type = GetRealStartupType(type); service = CreateService(
scmanager, // SCM database
name, // name of service
display_name, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
startup_type, // start type
SERVICE_ERROR_NORMAL, // error control type
file_path, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password __Cleanup:
if (service)
{
result = ;
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::UnInstall(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {}; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS|DELETE);
if (!service)
{
goto __Cleanup;
} if (ControlService(service, SERVICE_CONTROL_STOP, &status))
{
::Sleep(); while (QueryServiceStatus(service, &status))
{
if (status.dwCurrentState != SERVICE_STOP_PENDING)
{
break;
}
else
{
Sleep();
}
}
} if (DeleteService(service))
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::SetStartupType(const char *name, SERVICE_STARTUP_TYPE type)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
if (!service)
{
goto __Cleanup;
} int startup_type = GetRealStartupType(type); BOOL csc_result = ChangeServiceConfig(
service, // handle of service
SERVICE_NO_CHANGE, // service type: no change
startup_type, // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL); // display name: no change if (csc_result)
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::UpdateDesc(const char *name, const char *desc)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_DESCRIPTION sd = {};
sd.lpDescription = (char *)desc; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
if (!service)
{
goto __Cleanup;
} if (ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sd))
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Start(const char *name, int argc, const char **argv)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {};
DWORD dwStartTickCount = ;
DWORD dwOldCheckPoint = ;
DWORD dwWaitTime = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_ALL_ACCESS);
if (!service)
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if(status.dwCurrentState!=SERVICE_STOPPED
&& status.dwCurrentState!=SERVICE_STOP_PENDING)
{
goto __Cleanup;
} dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
while (status.dwCurrentState == SERVICE_STOP_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCheckPoint > dwOldCheckPoint)
{
dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
}
else
{
if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
{
goto __Cleanup;
}
}
} if (!StartService(service, argc, argv))
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
while (status.dwCurrentState == SERVICE_START_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCheckPoint > dwOldCheckPoint)
{
dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
}
else
{
if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
{
break;
}
}
} __Cleanup:
if (status.dwCurrentState==SERVICE_RUNNING)
{
result = ;
} if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Stop(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {};
DWORD dwStartTime = GetTickCount();
DWORD dwTimeout = ;
DWORD dwWaitTime = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS);
if (!service)
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} while (status.dwCurrentState == SERVICE_STOP_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} if ((GetTickCount() - dwStartTime) > dwTimeout)
{
goto __Cleanup;
}
} if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
{
goto __Cleanup;
} while (status.dwCurrentState != SERVICE_STOPPED)
{
::Sleep(status.dwWaitHint); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} if ( GetTickCount() - dwStartTime > dwTimeout )
{
goto __Cleanup;
}
} __Cleanup:
if (status.dwCurrentState == SERVICE_STOPPED)
{
result = ;
} if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::GetCurrentStatus(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {}; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS);
if (!service)
{
goto __Cleanup;
} if (QueryServiceStatus(service, &status))
{
result = status.dwCurrentState;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::GetRealStartupType(SERVICE_STARTUP_TYPE type)
{
switch (type)
{
case SST_AUTO_START:
{
return SERVICE_AUTO_START;
}
case SST_DEMAND_START:
{
return SERVICE_DEMAND_START;
}
case SST_DISABLED:
default:
{
return SERVICE_DISABLED;
}
}
} NTServiceHandler::NTServiceHandler(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service)
: m_name(name),
m_service(service)
{
memset(&m_status, , sizeof(SERVICE_STATUS));
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_START_PENDING;
m_status.dwWin32ExitCode = NO_ERROR;
m_status.dwServiceSpecificExitCode = ;
m_status.dwCheckPoint = ;
m_status.dwWaitHint = ; if (canstop)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_STOP;
}
if (canshutdown)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
}
if (canpausecontinue)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
} m_status_handle = ;
} NTServiceHandler::~NTServiceHandler()
{
} int NTServiceHandler::Run()
{
SERVICE_TABLE_ENTRY st[] =
{
{(LPSTR)m_name.c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMainHandler},
{NULL, NULL}
}; return ::StartServiceCtrlDispatcher(st) ? : -;
} void NTServiceHandler::ServiceMainHandler(DWORD argc, LPSTR *argv)
{
NTServiceHandler *m_this = GetInstance();
if (m_this)
{
m_this->m_status_handle = RegisterServiceCtrlHandler(m_this->m_name.c_str(), (LPHANDLER_FUNCTION)ServiceCtrlHandler);
if (!m_this->m_status_handle)
{
return;
} m_this->NTS_Start(argc, argv);
}
} void NTServiceHandler::ServiceCtrlHandler(DWORD ctrl)
{
NTServiceHandler *m_this = GetInstance();
if (m_this)
{
switch (ctrl)
{
case SERVICE_CONTROL_STOP:
{
m_this->NTS_Stop();
}
break;
case SERVICE_CONTROL_PAUSE:
{
m_this->NTS_Pause();
}
break;
case SERVICE_CONTROL_CONTINUE:
{
m_this->NTS_Continue();
}
break;
case SERVICE_CONTROL_SHUTDOWN:
{
m_this->NTS_Shutdown();
}
break;
case SERVICE_CONTROL_INTERROGATE:
default:
break;
}
}
} void NTServiceHandler::NTS_Start(DWORD argc, LPSTR *argv)
{
try
{
SetServiceStatus(SERVICE_START_PENDING); if (OnInit(argc, argv) != )
{
exit();
} SetServiceStatus(SERVICE_RUNNING); OnStart(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
SetServiceStatus(SERVICE_STOPPED);
}
} void NTServiceHandler::NTS_Stop()
{
DWORD dwOriginalState = m_status.dwCurrentState; try
{
SetServiceStatus(SERVICE_STOP_PENDING); OnStop(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(dwOriginalState);
}
catch (...)
{
SetServiceStatus(dwOriginalState);
}
} void NTServiceHandler::NTS_Pause()
{
try
{
SetServiceStatus(SERVICE_PAUSE_PENDING); OnPause(); SetServiceStatus(SERVICE_PAUSED);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
SetServiceStatus(SERVICE_RUNNING);
}
} void NTServiceHandler::NTS_Continue()
{
try
{
SetServiceStatus(SERVICE_CONTINUE_PENDING); OnContinue(); SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
SetServiceStatus(SERVICE_PAUSED);
}
} void NTServiceHandler::NTS_Shutdown()
{
try
{
OnShutdown(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
dwError = ;
}
catch (...)
{
}
} void NTServiceHandler::SetServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
assert(m_status_handle); static DWORD dwCheckPoint = ; m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint; if (dwCurrentState==SERVICE_RUNNING
|| dwCurrentState==SERVICE_STOPPED)
{
m_status.dwCheckPoint = ;
}
else
{
m_status.dwCheckPoint = ++dwCheckPoint;
} ::SetServiceStatus(m_status_handle, &m_status);
} int NTServiceHandler::OnInit(int argc, char **argv)
{
return m_service.OnInit(argc, argv);
} void NTServiceHandler::OnStart()
{
m_service.OnStart();
} void NTServiceHandler::OnStop()
{
m_service.OnStop();
} void NTServiceHandler::OnPause()
{
m_service.OnPause();
} void NTServiceHandler::OnContinue()
{
m_service.OnContinue();
} void NTServiceHandler::OnShutdown()
{
m_service.OnShutdown();
}