diff options
Diffstat (limited to 'um/libservice')
24 files changed, 1242 insertions, 0 deletions
diff --git a/um/libservice/CMakeLists.txt b/um/libservice/CMakeLists.txt new file mode 100644 index 0000000..34b3d13 --- /dev/null +++ b/um/libservice/CMakeLists.txt @@ -0,0 +1,10 @@ +file(GLOB libservice_sources "src/*.cpp") +file(GLOB_RECURSE libservice_headers "include/*.hpp") +add_library(libservice + ${libservice_sources} + ${libservice_headers}) +target_include_directories(libservice PUBLIC include) +target_compile_definitions(libservice PRIVATE NOMINMAX) + +add_subdirectory(test) +add_subdirectory(utils) diff --git a/um/libservice/README.md b/um/libservice/README.md new file mode 100644 index 0000000..f9fb601 --- /dev/null +++ b/um/libservice/README.md @@ -0,0 +1,53 @@ +Driver management utilities +=========================== + +Utilities to load/unload the drivers. + +Usage +----- + +### install_service.exe + + Usage: install_service.exe NAME SYS_PATH + +Installs a driver as a service. +The same as + + > sc create NAME type= kernel binPath= SYS_PATH + +### start_service.exe + + Usage: start_service.exe NAME + +Starts the service `NAME` (loading the corresponding driver). +The same as + + > net start NAME + +### stop_service.exe + + Usage: stop_service.exe NAME + +Stops the service `NAME` (unloading the corresponding driver). +The same as + + > net stop NAME + +### uninstall_service.exe + + Usage: uninstall_service.exe NAME + +Uninstalls the service `NAME`, wiping the corresponding record from the +registry. +The same as + + > sc delete NAME + +See also +-------- + +* [Building the utilities] +* [License] + +[Building the utilities]: ../README.md#building-the-utilities +[License]: ../../README.md#license diff --git a/um/libservice/include/libservice/all.hpp b/um/libservice/include/libservice/all.hpp new file mode 100644 index 0000000..a5761e0 --- /dev/null +++ b/um/libservice/include/libservice/all.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" +#include "device.hpp" +#include "handle.hpp" +#include "service.hpp" +#include "service_handle.hpp" +#include "service_manager.hpp" +#include "singleton.hpp" +#include "windows_error.hpp" diff --git a/um/libservice/include/libservice/common.hpp b/um/libservice/include/libservice/common.hpp new file mode 100644 index 0000000..a1c46fb --- /dev/null +++ b/um/libservice/include/libservice/common.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#define LIBSERVICE_FILE_PATH __FILE__ +#define LIBSERVICE_LINE_NUMBER __LINE__ +#define LIBSERVICE_FUNCTION_NAME __FUNCTION__ + +#define LIBSERVICE_TO_STRING(s) LIBSERVICE_TO_STRING_(s) +#define LIBSERVICE_TO_STRING_(s) #s + +#define LIBSERVICE_LINE_NUMBER_STRING LIBSERVICE_TO_STRING(LIBSERVICE_LINE_NUMBER) + +#define LIBSERVICE_NOEXCEPT throw() diff --git a/um/libservice/include/libservice/device.hpp b/um/libservice/include/libservice/device.hpp new file mode 100644 index 0000000..ac292c8 --- /dev/null +++ b/um/libservice/include/libservice/device.hpp @@ -0,0 +1,75 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" +#include "handle.hpp" + +#include <Windows.h> + +#include <cstddef> + +#include <string> +#include <utility> + +namespace libservice +{ + class Device + { + public: + typedef DWORD Code; + + static Device open(const std::string& path); + + Device(Device&& other) LIBSERVICE_NOEXCEPT + { + swap(other); + } + + Device& operator=(Device other) LIBSERVICE_NOEXCEPT + { + swap(other); + return *this; + } + + void swap(Device& other) LIBSERVICE_NOEXCEPT + { + using std::swap; + swap(handle, other.handle); + } + + std::size_t get_required_output_size( + Code code, + const void* in_buf, + std::size_t in_buf_size) const; + + std::size_t send_control_code( + Code code, + const void* in_buf, + std::size_t in_buf_size, + void* out_buf, + std::size_t out_buf_size) const; + + private: + Device(Handle handle) + : handle(std::move(handle)) + { } + + Handle handle; + + Device(const Device&) = delete; + }; + + void swap(Device&, Device&) LIBSERVICE_NOEXCEPT; +} + +namespace std +{ + template <> + void swap<libservice::Device>( + libservice::Device&, + libservice::Device&) LIBSERVICE_NOEXCEPT; +} diff --git a/um/libservice/include/libservice/handle.hpp b/um/libservice/include/libservice/handle.hpp new file mode 100644 index 0000000..5e351d2 --- /dev/null +++ b/um/libservice/include/libservice/handle.hpp @@ -0,0 +1,77 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" + +#include <Windows.h> + +#include <memory> +#include <type_traits> +#include <utility> + +namespace libservice +{ + class Handle + { + public: + Handle() = default; + + Handle(HANDLE raw) + : impl(raw) + { } + + Handle(Handle&& other) LIBSERVICE_NOEXCEPT + { + swap(other); + } + + Handle& operator=(Handle other) LIBSERVICE_NOEXCEPT + { + swap(other); + return *this; + } + + operator bool() const + { + return static_cast<bool>(impl); + } + + operator HANDLE() const + { + return impl.get(); + } + + void swap(Handle& other) LIBSERVICE_NOEXCEPT + { + using std::swap; + swap(impl, other.impl); + } + + private: + struct Deleter + { + void operator()(HANDLE raw) + { + CloseHandle(raw); + } + }; + + std::unique_ptr<std::remove_pointer<HANDLE>::type, Deleter> impl; + + Handle(const Handle&) = delete; + }; + + void swap(Handle& a, Handle& b) LIBSERVICE_NOEXCEPT; +} + +namespace std +{ + template <> + void swap<libservice::Handle>( + libservice::Handle& a, + libservice::Handle& b) LIBSERVICE_NOEXCEPT; +} diff --git a/um/libservice/include/libservice/service.hpp b/um/libservice/include/libservice/service.hpp new file mode 100644 index 0000000..089f790 --- /dev/null +++ b/um/libservice/include/libservice/service.hpp @@ -0,0 +1,73 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" +#include "service_handle.hpp" +#include "service_manager.hpp" + +#include <string> +#include <utility> + +namespace libservice +{ + class Service + { + public: + static bool exists( + const ServiceManager&, + const std::string& name); + + static Service open( + const ServiceManager&, + const std::string& name); + + static Service install( + const ServiceManager&, + const std::string& name, + const std::string& bin_path); + + void start() const; + void stop() const; + void uninstall() const; + + Service(Service&& other) LIBSERVICE_NOEXCEPT + { + swap(other); + } + + Service& operator=(Service other) LIBSERVICE_NOEXCEPT + { + swap(other); + return *this; + } + + void swap(Service& other) LIBSERVICE_NOEXCEPT + { + using std::swap; + swap(handle, other.handle); + } + + private: + Service(ServiceHandle handle) + : handle(std::move(handle)) + { } + + ServiceHandle handle; + + Service(const Service&) = delete; + }; + + void swap(Service&, Service&) LIBSERVICE_NOEXCEPT; +} + +namespace std +{ + template <> + void swap<libservice::Service>( + libservice::Service&, + libservice::Service&) LIBSERVICE_NOEXCEPT; +} diff --git a/um/libservice/include/libservice/service_handle.hpp b/um/libservice/include/libservice/service_handle.hpp new file mode 100644 index 0000000..2883ff3 --- /dev/null +++ b/um/libservice/include/libservice/service_handle.hpp @@ -0,0 +1,76 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" + +#include <Windows.h> + +#include <memory> +#include <utility> + +namespace libservice +{ + class ServiceHandle + { + public: + ServiceHandle() = default; + + ServiceHandle(SC_HANDLE raw) + : impl(raw) + { } + + ServiceHandle(ServiceHandle&& other) LIBSERVICE_NOEXCEPT + { + swap(other); + } + + ServiceHandle& operator=(ServiceHandle other) LIBSERVICE_NOEXCEPT + { + swap(other); + return *this; + } + + operator bool() const + { + return static_cast<bool>(impl); + } + + operator SC_HANDLE() const + { + return impl.get(); + } + + void swap(ServiceHandle& other) LIBSERVICE_NOEXCEPT + { + using std::swap; + swap(impl, other.impl); + } + + private: + struct Deleter + { + void operator()(SC_HANDLE raw) + { + CloseServiceHandle(raw); + } + }; + + std::unique_ptr<SC_HANDLE__, Deleter> impl; + + ServiceHandle(const ServiceHandle&) = delete; + }; + + void swap(ServiceHandle&, ServiceHandle&) LIBSERVICE_NOEXCEPT; +} + +namespace std +{ + template <> + void swap<libservice::ServiceHandle>( + libservice::ServiceHandle&, + libservice::ServiceHandle&) LIBSERVICE_NOEXCEPT; +} diff --git a/um/libservice/include/libservice/service_manager.hpp b/um/libservice/include/libservice/service_manager.hpp new file mode 100644 index 0000000..80e6f12 --- /dev/null +++ b/um/libservice/include/libservice/service_manager.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" +#include "service_handle.hpp" + +#include <Windows.h> + +#include <utility> + +namespace libservice +{ + class ServiceManager + { + public: + static ServiceManager open(); + + ServiceManager(ServiceManager&& other) LIBSERVICE_NOEXCEPT + { + swap(other); + } + + ServiceManager& operator=(ServiceManager other) LIBSERVICE_NOEXCEPT + { + swap(other); + return *this; + } + + void swap(ServiceManager& other) LIBSERVICE_NOEXCEPT + { + using std::swap; + swap(handle, other.handle); + } + + operator SC_HANDLE() const + { + return handle; + } + + private: + ServiceManager(ServiceHandle handle) + : handle(std::move(handle)) + { } + + ServiceHandle handle; + + ServiceManager(const ServiceManager&) = delete; + }; + + void swap(ServiceManager& a, ServiceManager& b) LIBSERVICE_NOEXCEPT; +} + +namespace std +{ + template <> + void swap<libservice::ServiceManager>( + libservice::ServiceManager&, + libservice::ServiceManager&) LIBSERVICE_NOEXCEPT; +} diff --git a/um/libservice/include/libservice/singleton.hpp b/um/libservice/include/libservice/singleton.hpp new file mode 100644 index 0000000..1c7b1a7 --- /dev/null +++ b/um/libservice/include/libservice/singleton.hpp @@ -0,0 +1,43 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include <mutex> + +namespace libservice +{ + template <typename DerivedT> + class Singleton + { + public: + static DerivedT& get() + { + std::call_once(initialized, initialize); + return get_unsafe(); + } + + protected: + Singleton() = default; + virtual ~Singleton() = default; + + private: + static void initialize() + { + get_unsafe(); + } + + static DerivedT& get_unsafe() + { + static DerivedT instance; + return instance; + } + + static std::once_flag initialized; + }; + + template <typename DerivedT> + std::once_flag Singleton<DerivedT>::initialized; +} diff --git a/um/libservice/include/libservice/windows_error.hpp b/um/libservice/include/libservice/windows_error.hpp new file mode 100644 index 0000000..f7ac90e --- /dev/null +++ b/um/libservice/include/libservice/windows_error.hpp @@ -0,0 +1,31 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#pragma once + +#include "common.hpp" +#include "singleton.hpp" + +#include <string> +#include <system_error> + +namespace libservice +{ + class WindowsErrorCategory + : public std::error_category + , public Singleton<WindowsErrorCategory> + { + public: + const char* name() const LIBSERVICE_NOEXCEPT { return "Windows"; } + + std::string message(int) const; + + private: + friend class Singleton<WindowsErrorCategory>; + }; +} + +#define LIBSERVICE_ERROR_PREFIX \ + "Error in function '" LIBSERVICE_FUNCTION_NAME "' at file '" LIBSERVICE_FILE_PATH "', line " LIBSERVICE_LINE_NUMBER_STRING diff --git a/um/libservice/src/device.cpp b/um/libservice/src/device.cpp new file mode 100644 index 0000000..5643106 --- /dev/null +++ b/um/libservice/src/device.cpp @@ -0,0 +1,136 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <Windows.h> + +#include <cstddef> + +#include <limits> +#include <stdexcept> +#include <string> +#include <system_error> +#include <utility> + +namespace libservice +{ + namespace + { + Handle open_device(const std::string& path) + { + const auto raw = CreateFileA( + path.c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (INVALID_HANDLE_VALUE == raw) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return Handle(raw); + } + } + + Device Device::open(const std::string& path) + { + return Device(open_device(path)); + } + + std::size_t Device::get_required_output_size( + Code code, + const void* in_buf, + std::size_t in_buf_size) const + { + DWORD nbreq; + + if (in_buf_size > std::numeric_limits<DWORD>::max()) + throw std::range_error("input buffer size is too large"); + + std::size_t nbwritten = DeviceIoControl( + handle, + code, + const_cast<void*>(in_buf), + static_cast<DWORD>(in_buf_size), + NULL, + 0, + &nbreq, + NULL); + + if (0 == nbwritten) + { + const auto ec = GetLastError(); + + switch (ec) + { + case ERROR_MORE_DATA: + return nbreq; + + default: + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + } + + return nbwritten; + } + + std::size_t Device::send_control_code( + Code code, + const void* in_buf, + std::size_t in_buf_size, + void* out_buf, + std::size_t out_buf_size) const + { + DWORD nbreq; + + if (in_buf_size > std::numeric_limits<DWORD>::max()) + throw std::range_error("input buffer size is too large"); + if (out_buf_size > std::numeric_limits<DWORD>::max()) + throw std::range_error("output buffer size is too large"); + + std::size_t nbwritten = DeviceIoControl( + handle, + code, + const_cast<void*>(in_buf), + static_cast<DWORD>(in_buf_size), + out_buf, + static_cast<DWORD>(out_buf_size), + &nbreq, + NULL); + + if (0 == nbwritten) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return nbwritten; + } + + void swap(Device& a, Device& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} + +namespace std +{ + template <> + void swap<libservice::Device>( + libservice::Device& a, + libservice::Device& b) + { + a.swap(b); + } +} diff --git a/um/libservice/src/handle.cpp b/um/libservice/src/handle.cpp new file mode 100644 index 0000000..7567781 --- /dev/null +++ b/um/libservice/src/handle.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <utility> + +namespace libservice +{ + void swap(Handle& a, Handle& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} + +namespace std +{ + template <> + void swap<libservice::Handle>( + libservice::Handle& a, + libservice::Handle& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} diff --git a/um/libservice/src/service.cpp b/um/libservice/src/service.cpp new file mode 100644 index 0000000..8b5e043 --- /dev/null +++ b/um/libservice/src/service.cpp @@ -0,0 +1,276 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <Windows.h> + +#include <string> +#include <system_error> +#include <utility> +#include <vector> + +namespace libservice +{ + namespace + { + ServiceHandle open_service( + const ServiceManager& mgr, + const std::string& name) + { + const auto raw = OpenServiceA( + mgr, + name.c_str(), + SERVICE_ALL_ACCESS); + + if (NULL == raw) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return raw; + } + + ServiceHandle install_service( + const ServiceManager& mgr, + const std::string& name, + const std::string& bin_path) + { + const auto raw = CreateServiceA( + mgr, + name.c_str(), + name.c_str(), + SERVICE_ALL_ACCESS, + SERVICE_KERNEL_DRIVER, + SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + bin_path.c_str(), + NULL, + NULL, + NULL, + NULL, + NULL); + + if (NULL == raw) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return raw; + } + + void start_service(const ServiceHandle& handle) + { + if (!StartService(handle, 0, NULL)) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + } + + void stop_service(const ServiceHandle& handle) + { + SERVICE_STATUS service_status; + + if (!ControlService(handle, SERVICE_CONTROL_STOP, &service_status)) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + } + + void uninstall_service(const ServiceHandle& handle) + { + if (!DeleteService(handle)) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + } + + bool service_exists( + const ServiceManager& mgr, + const std::string& name) + { + const auto raw = OpenServiceA( + mgr, + name.c_str(), + SERVICE_QUERY_STATUS); + + if (NULL != raw) + { + ServiceHandle handle(raw); + return true; + } + + const auto ec = GetLastError(); + + switch (ec) + { + case ERROR_SERVICE_DOES_NOT_EXIST: + return false; + + default: + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + } + + SERVICE_STATUS_PROCESS query_service_status(const ServiceHandle& handle) + { + SERVICE_STATUS_PROCESS status; + DWORD nbreq; + + const auto buf_ptr = reinterpret_cast<BYTE*>(&status); + const auto buf_size = sizeof(status); + + if (!QueryServiceStatusEx( + handle, SC_STATUS_PROCESS_INFO, buf_ptr, buf_size, &nbreq)) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return status; + } + + DWORD query_service_state(const ServiceHandle& handle) + { + return query_service_status(handle).dwCurrentState; + } + + SERVICE_STATUS_PROCESS wait_for_service_state( + const ServiceHandle& handle, + const DWORD desired_state) + { + auto status = query_service_status(handle); + + DWORD old_timestamp = GetTickCount(); + + DWORD old_check_point = status.dwCheckPoint; + DWORD old_wait_hint = status.dwWaitHint; + + while (desired_state != status.dwCurrentState) + { + DWORD wait_time = old_wait_hint / 10; + + if (wait_time < 1000) + wait_time = 1000; + else if (wait_time > 10000) + wait_time = 10000; + + Sleep(wait_time); + + status = query_service_status(handle); + + if (desired_state == status.dwCurrentState) + break; + + if (status.dwCheckPoint > old_check_point) + { + old_timestamp = GetTickCount(); + + old_check_point = status.dwCheckPoint; + old_wait_hint = status.dwWaitHint; + } + else if (GetTickCount() - old_timestamp > old_wait_hint) + { + return status; + } + } + + return status; + } + } + + Service Service::open( + const ServiceManager& mgr, + const std::string& name) + { + return open_service(mgr, name); + } + + Service Service::install( + const ServiceManager& mgr, + const std::string& name, + const std::string& bin_path) + { + return install_service(mgr, name, bin_path); + } + + bool Service::exists( + const ServiceManager& mgr, + const std::string& name) + { + return service_exists(mgr, name); + } + + void Service::start() const + { + const auto state = query_service_state(handle); + + switch (state) + { + case SERVICE_STOPPED: + break; + + case SERVICE_STOP_PENDING: + wait_for_service_state(handle, SERVICE_STOPPED); + break; + + default: + return; + } + + start_service(handle); + wait_for_service_state(handle, SERVICE_RUNNING); + } + + void Service::stop() const + { + switch (query_service_state(handle)) + { + case SERVICE_STOPPED: + return; + + case SERVICE_STOP_PENDING: + wait_for_service_state(handle, SERVICE_STOPPED); + return; + } + + stop_service(handle); + wait_for_service_state(handle, SERVICE_STOPPED); + } + + void Service::uninstall() const + { + stop(); + uninstall_service(handle); + } + + void swap(Service& a, Service& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} + +namespace std +{ + template <> + void swap<libservice::Service>( + libservice::Service& a, + libservice::Service& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} diff --git a/um/libservice/src/service_handle.cpp b/um/libservice/src/service_handle.cpp new file mode 100644 index 0000000..adce7f0 --- /dev/null +++ b/um/libservice/src/service_handle.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <utility> + +namespace libservice +{ + void swap(ServiceHandle& a, ServiceHandle& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} + +namespace std +{ + template <> + void swap<libservice::ServiceHandle>( + libservice::ServiceHandle& a, + libservice::ServiceHandle& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} diff --git a/um/libservice/src/service_manager.cpp b/um/libservice/src/service_manager.cpp new file mode 100644 index 0000000..61662de --- /dev/null +++ b/um/libservice/src/service_manager.cpp @@ -0,0 +1,44 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <Windows.h> + +#include <system_error> +#include <utility> + +namespace libservice +{ + ServiceManager ServiceManager::open() + { + SC_HANDLE raw = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if (NULL == raw) + { + const auto ec = GetLastError(); + throw std::system_error( + ec, WindowsErrorCategory::get(), LIBSERVICE_ERROR_PREFIX); + } + + return ServiceHandle(raw); + } + + void swap(ServiceManager& a, ServiceManager& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} + +namespace std +{ + template <> + void swap<libservice::ServiceManager>( + libservice::ServiceManager& a, + libservice::ServiceManager& b) LIBSERVICE_NOEXCEPT + { + a.swap(b); + } +} diff --git a/um/libservice/src/windows_error.cpp b/um/libservice/src/windows_error.cpp new file mode 100644 index 0000000..f27018b --- /dev/null +++ b/um/libservice/src/windows_error.cpp @@ -0,0 +1,39 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <Windows.h> + +#include <string> + +namespace libservice +{ + std::string WindowsErrorCategory::message(int code) const + { + char* buf_ptr; + + const auto nbwritten = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + code, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast<char*>(&buf_ptr), + 0, + NULL); + + if (0 == nbwritten) + { + LocalFree(buf_ptr); + return "Couldn't format error message"; + } + + std::string str(buf_ptr, nbwritten - 2); + LocalFree(buf_ptr); + return str; + } +} diff --git a/um/libservice/test/CMakeLists.txt b/um/libservice/test/CMakeLists.txt new file mode 100644 index 0000000..4780deb --- /dev/null +++ b/um/libservice/test/CMakeLists.txt @@ -0,0 +1,4 @@ +add_executable(libservice_test_windows_error windows_error.cpp) +target_link_libraries(libservice_test_windows_error libservice) +set_target_properties(libservice_test_windows_error PROPERTIES + OUTPUT_NAME windows_error) diff --git a/um/libservice/test/windows_error.cpp b/um/libservice/test/windows_error.cpp new file mode 100644 index 0000000..b909670 --- /dev/null +++ b/um/libservice/test/windows_error.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <Windows.h> + +#include <exception> +#include <iostream> +#include <system_error> + +int main() +{ + try + { + throw std::system_error( + ERROR_FILE_NOT_FOUND, + libservice::WindowsErrorCategory::get(), + LIBSERVICE_ERROR_PREFIX); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + return 0; +} diff --git a/um/libservice/utils/CMakeLists.txt b/um/libservice/utils/CMakeLists.txt new file mode 100644 index 0000000..061ab25 --- /dev/null +++ b/um/libservice/utils/CMakeLists.txt @@ -0,0 +1,11 @@ +add_executable(install_service install_service.cpp) +target_link_libraries(install_service libservice) + +add_executable(start_service start_service.cpp) +target_link_libraries(start_service libservice) + +add_executable(stop_service stop_service.cpp) +target_link_libraries(stop_service libservice) + +add_executable(uninstall_service uninstall_service.cpp) +target_link_libraries(uninstall_service libservice) diff --git a/um/libservice/utils/install_service.cpp b/um/libservice/utils/install_service.cpp new file mode 100644 index 0000000..f36af75 --- /dev/null +++ b/um/libservice/utils/install_service.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <exception> +#include <iostream> + +int main(int argc, char* argv[]) +{ + if (argc != 3) + { + std::cout << "Usage: " << argv[0] << " NAME SYS_PATH\n"; + return 1; + } + + try + { + libservice::Service::install(libservice::ServiceManager::open(), argv[1], argv[2]); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + return 0; +} diff --git a/um/libservice/utils/start_service.cpp b/um/libservice/utils/start_service.cpp new file mode 100644 index 0000000..fafee53 --- /dev/null +++ b/um/libservice/utils/start_service.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <exception> +#include <iostream> + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: " << argv[0] << " NAME\n"; + return 1; + } + + try + { + libservice::Service::open(libservice::ServiceManager::open(), argv[1]).start(); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + return 0; +} diff --git a/um/libservice/utils/stop_service.cpp b/um/libservice/utils/stop_service.cpp new file mode 100644 index 0000000..800c7a9 --- /dev/null +++ b/um/libservice/utils/stop_service.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <exception> +#include <iostream> + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: " << argv[0] << " NAME\n"; + return 1; + } + + try + { + libservice::Service::open(libservice::ServiceManager::open(), argv[1]).stop(); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + return 0; +} diff --git a/um/libservice/utils/uninstall_service.cpp b/um/libservice/utils/uninstall_service.cpp new file mode 100644 index 0000000..395bb51 --- /dev/null +++ b/um/libservice/utils/uninstall_service.cpp @@ -0,0 +1,29 @@ +// Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Windows 7 drivers" project. +// For details, see https://github.com/egor-tensin/windows7-drivers. +// Distributed under the MIT License. + +#include "libservice/all.hpp" + +#include <exception> +#include <iostream> + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cout << "Usage: " << argv[0] << " NAME\n"; + return 1; + } + + try + { + libservice::Service::open(libservice::ServiceManager::open(), argv[1]).uninstall(); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + return 0; +} |