📄 nt_service.hpp
字号:
// Copyright E骾n O'Callaghan 2008 - 2008.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef NT_SERVICE_HPP_INCLUDED
#define NT_SERVICE_HPP_INCLUDED
#include "StdAfx.hpp"
#include "auxiliary/logger.hpp"
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/split_free.hpp>
#include "nt_service_exception.hpp"
#include "nt_service_control_manager.hpp"
#include "enum_services_sequence.hpp"
class nt_service : private boost::noncopyable
{
#if defined(UNICODE_) || defined(UNICODE)
typedef std::wstring t_string;
#else
typedef std::string t_string;
#endif
public:
class service_settings
{
friend class nt_service;
public:
service_settings() :
dwServiceType_(0),
dwCurrentState_(SERVICE_NO_CHANGE),
dwStartType_(SERVICE_NO_CHANGE),
inherited_(false)
{
assert(is_inert());
}
service_settings(nt_service_control_manager::manager_settings_ptr manager, t_string lpServiceName) :
manager_(manager),
lpServiceName_(lpServiceName),
dwServiceType_(0),
dwCurrentState_(SERVICE_NO_CHANGE),
dwStartType_(SERVICE_NO_CHANGE),
inherited_(false)
{
boost::to_lower(lpServiceName_);
assert(is_inert());
}
service_settings(const nt_service& svc, bool inherit_state=true, bool inherit_start_type=true) :
manager_(svc.manager_->settings()),
lpServiceName_(svc.lpServiceName_),
dwServiceType_(0),
dwCurrentState_(SERVICE_NO_CHANGE),
dwStartType_(SERVICE_NO_CHANGE),
inherited_(false)
{
boost::to_lower(lpServiceName_);
assert(is_inert());
if (inherit_state)
{
std::pair<DWORD, t_string> cs = svc.dwCurrentState();
set_dwCurrentState(cs.first);
}
if (inherit_start_type)
{
std::pair<DWORD, t_string> st = svc.dwStartType();
set_dwStartType(st.first);
}
}
bool operator==(const service_settings& svc_s) const
{
return (lpServiceName_ == svc_s.lpServiceName_);
}
bool operator!=(const service_settings& svc_s) const
{
return !(*this == svc_s);
}
bool operator<(const service_settings& svc_s) const
{
return (lpServiceName_ < svc_s.lpServiceName_);
}
bool compare_state(const service_settings& svc_s) const
{
return (lpServiceName_ == svc_s.lpServiceName_ &&
(dwServiceType_ == 0 || dwServiceType_ == svc_s.dwServiceType_) &&
(dwCurrentState_ == SERVICE_NO_CHANGE || dwCurrentState_ == svc_s.dwCurrentState_) &&
(dwStartType_ == SERVICE_NO_CHANGE || dwStartType_ == svc_s.dwStartType_) &&
(!lpServiceStartName_ || lpServiceStartName_ == svc_s.lpServiceStartName_) &&
(!lpBinaryPathName_ || lpBinaryPathName_ == svc_s.lpBinaryPathName_) &&
(!lpDescription_ || lpDescription_ == svc_s.lpDescription_));
}
bool is_inert()
{
return (dwServiceType_ == 0 &&
dwCurrentState_ == SERVICE_NO_CHANGE &&
dwStartType_ == SERVICE_NO_CHANGE &&
!lpServiceStartName_ &&
!lpBinaryPathName_ &&
!lpDescription_);
}
bool is_inherited() const { return inherited_; }
void set_inherited(bool i=true) { inherited_ = i; }
void set_dwCurrentState(DWORD CurrentState)
{
switch (CurrentState)
{
case SERVICE_STOPPED:
case SERVICE_STOP_PENDING:
dwCurrentState_ = SERVICE_STOPPED;
break;
case SERVICE_START_PENDING:
case SERVICE_CONTINUE_PENDING:
case SERVICE_RUNNING:
dwCurrentState_ = SERVICE_RUNNING;
break;
case SERVICE_PAUSED:
case SERVICE_PAUSE_PENDING:
dwCurrentState_ = SERVICE_PAUSED;
break;
case SERVICE_NO_CHANGE:
default:
dwCurrentState_ = SERVICE_NO_CHANGE;
};
}
const t_string lpServiceName() const { return lpServiceName_; }
DWORD dwCurrentState() const { return dwCurrentState_; }
void set_dwStartType(DWORD StartType)
{
dwStartType_ = StartType;
}
DWORD dwStartType() const { return dwStartType_; }
nt_service_control_manager::manager_settings_ptr manager() { return manager_; }
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
using boost::serialization::make_nvp;
ar & make_nvp("manager", manager_);
ar & make_nvp("service_name", lpServiceName_);
boost::to_lower(lpServiceName_);
ar & make_nvp("current_state", dwCurrentState_);
ar & make_nvp("start_type", dwStartType_);
}
private:
nt_service_control_manager::manager_settings_ptr manager_;
t_string lpServiceName_;
DWORD dwServiceType_;
DWORD dwCurrentState_;
DWORD dwStartType_;
boost::optional<t_string> lpServiceStartName_;
boost::optional<t_string> lpBinaryPathName_;
boost::optional<t_string> lpDescription_;
bool inherited_;
};
friend class service_settings;
public:
nt_service(nt_service_control_manager_ptr manager, LPCTSTR lpServiceName, DWORD dwDesiredAccess=SERVICE_ALL_ACCESS) :
manager_(manager),
dwDesiredAccess_(dwDesiredAccess)
{
if (lpServiceName)
{
lpServiceName_ = lpServiceName;
boost::to_lower(lpServiceName_);
}
aux::wlog() << L"Opening service...";
handle_ = OpenService(*manager, lpServiceName, dwDesiredAccess);
if (!handle_) throw_nt_service_exception(lpServiceName);
aux::wlog() << L"...success.";
}
explicit nt_service(enum_services_sequence_item essi, DWORD dwDesiredAccess=SERVICE_ALL_ACCESS) :
manager_(essi.manager_),
dwDesiredAccess_(dwDesiredAccess)
{
if (essi.lpServiceName())
{
lpServiceName_ = essi.lpServiceName();
boost::to_lower(lpServiceName_);
}
aux::wlog() << L"Opening service...";
handle_ = OpenService(*essi.manager_, essi.lpServiceName(), dwDesiredAccess);
if (!handle_) throw_nt_service_exception(essi.lpServiceName());
aux::wlog() << L"...success.";
}
explicit nt_service(nt_service_control_manager_ptr manager,
const service_settings ss, DWORD dwDesiredAccess=SERVICE_ALL_ACCESS) :
manager_(manager),
dwDesiredAccess_(dwDesiredAccess)
{
lpServiceName_ = ss.lpServiceName();
boost::to_lower(lpServiceName_);
aux::wlog() << L"Opening service...";
handle_ = OpenService(*manager_, lpServiceName_.c_str(), dwDesiredAccess);
if (!handle_) throw_nt_service_exception(lpServiceName_.c_str());
aux::wlog() << L"...success.";
}
~nt_service()
{
if (handle_) CloseServiceHandle(handle_);
}
bool operator==(const nt_service& nt_s) const
{
return (handle_ == nt_s.handle_ && lpServiceName_ == nt_s.lpServiceName_);
}
bool operator!=(const nt_service& nt_s) const
{
return !(*this == nt_s);
}
bool operator<(const nt_service& nt_s) const
{
return (handle_ < nt_s.handle_);
}
bool matches_settings(const service_settings& svc_s) const
{
SERVICE_STATUS_PROCESS ssp = QueryServiceStatus();
std::pair<DWORD, t_string> st = dwServiceType(&ssp);
std::pair<DWORD, t_string> cs = dwCurrentState(&ssp);
boost::shared_array<BYTE> qsc = QueryServiceConfig();
std::pair<DWORD, t_string> stt = dwStartType(qsc);
return (lpServiceName_ == svc_s.lpServiceName_ &&
cs.first == svc_s.dwCurrentState_ &&
stt.first == svc_s.dwStartType_);
}
t_string lpServiceName() const { return lpServiceName_; }
t_string lpServiceDisplayName() const
{
DWORD BytesNeeded = 4096;
boost::scoped_array<TCHAR> dis_name(new TCHAR[BytesNeeded]);
BOOL result = ::GetServiceDisplayName(*manager_, (LPCTSTR)lpServiceName_.c_str(), dis_name.get(), & BytesNeeded);
assert(result);
return t_string(dis_name.get(), BytesNeeded+1);
}
SERVICE_STATUS_PROCESS QueryServiceStatus() const
{
assert (dwDesiredAccess_ | SERVICE_QUERY_STATUS);
SERVICE_STATUS_PROCESS ssp;
DWORD BytesNeeded = 0;
BOOL ret = QueryServiceStatusEx(handle_, SC_STATUS_PROCESS_INFO, (LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS), &BytesNeeded);
assert(ret);
return ssp;
}
boost::shared_array<BYTE> QueryServiceConfig() const
{
assert (dwDesiredAccess_ | SERVICE_QUERY_CONFIG);
DWORD BytesNeeded = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -