diff --git a/ServiceExample/Main.cpp b/ServiceExample/Main.cpp index 801726f..45dd3d1 100644 --- a/ServiceExample/Main.cpp +++ b/ServiceExample/Main.cpp @@ -12,63 +12,23 @@ #include "Models.h" #include "ServiceEntryPoint.hpp" -#include "ServiceControlHandler.hpp" -#define SVCNAME TEXT("ServiceExample") -// #define SERVICE_NAME _T("My Service Example") - -// service::ServiceControlHandler::g_ServiceStatus = {0}; -// SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; -// service::ServiceControlHandler::g_StatusHandle = nullptr; -SERVICE_STATUS g_ServiceStatus; - // static SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; -SERVICE_STATUS_HANDLE g_StatusHandle; - -HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE; - -// template -// VOID WINAPI ServiceMain(D, LStr *); +template VOID ServiceInstall(void); -VOID WINAPI ServiceMain(DWORD, LPTSTR*); -VOID WINAPI ServiceCtrlHandler(DWORD); -// DWORD WINAPI ServiceWorkerThread(LPVOID lpParam); - -VOID ReportServiceStatus(DWORD, DWORD, DWORD); -VOID ServiceInit(DWORD, LPTSTR*); +template VOID ServiceReportEvent(LPTSTR); -DWORD WINAPI ServiceWorkerThread(LPVOID lpParam); - -// models::ServiceInfo<> service_info(L"Service Example"); std::shared_ptr> service_info(new models::ServiceInfo<>(L"Service Example")); #undef main -// int main() int _tmain(int argc, TCHAR *argv[]) -// int __cdel_tmain(int argc, TCHAR *argv[]) { std::cout << "ServiceExample\n"; - auto v = TEXT("sss"); - - // service::ServiceControlHandler::g_ServiceStatus = {0}; - // SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; - // service::ServiceControlHandler::g_StatusHandle = nullptr; - - /** - SERVICE_TABLE_ENTRY SERVICETABLE[] = - { - // { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain }, - { SVCNAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain}, - {nullptr, nullptr} - }; - */ - - // if (StartServiceCtr) - if (lstrcmpi(argv[1], TEXT("install")) == 0) { ServiceInstall(); @@ -76,18 +36,12 @@ int _tmain(int argc, TCHAR *argv[]) return -1; } - service::ServiceEntryPoint entry; - // models::ServiceInfo<> service_info(TEXT("ServiceExample")); - // models::ServiceInfo<> service_info(L"Service Example"); SERVICE_TABLE_ENTRY SERVICETABLE[] = { - // { SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain }, - // { SVCNAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, - // { service_info.service_name, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, - // { (const_cast(service_info.service_name)) , (LPSERVICE_MAIN_FUNCTION)entry.service_main }, - // { SVCNAME, (LPSERVICE_MAIN_FUNCTION)entry.service_main_start}, - { SVCNAME, (LPSERVICE_MAIN_FUNCTION)service::ServiceEntryPoint::service_main_start }, + { service_info->service_name, + (LPSERVICE_MAIN_FUNCTION) + service::ServiceEntryPoint::service_main_start }, { nullptr, nullptr }, }; @@ -103,14 +57,11 @@ int _tmain(int argc, TCHAR *argv[]) +template VOID ServiceInstall() { - SC_HANDLE schSCManager; - SC_HANDLE schService; - // TCHAR szPath[MAX_PATH]; - wchar_t buffer[MAX_PATH]; + Char buffer[MAX_PATH]; - // if (!GetModuleFileName("", szPath, MAX_PATH)) if (!GetModuleFileName(nullptr, buffer, MAX_PATH)) { std::cout << "Cannot install service " << GetLastError() << "\n"; @@ -120,12 +71,12 @@ VOID ServiceInstall() // Get a handle to the SCM database. - schSCManager = OpenSCManager( - NULL, // local computer - NULL, // ServicesActive database + Handle schSCManager = OpenSCManager( + nullptr, // local computer + nullptr, // ServicesActive database SC_MANAGER_ALL_ACCESS); // full access rights - if (NULL == schSCManager) + if (nullptr == schSCManager) { std::cout << "OpenSCManager failed " << GetLastError() << "\n"; @@ -134,25 +85,23 @@ VOID ServiceInstall() // Create the service - schService = CreateService( + Handle schService = CreateService( schSCManager, // SCM database - SVCNAME, // name of service - SVCNAME, // service name to display + service_info->service_name, // name of service + service_info->service_name, // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type - // szPath, // path to service's binary buffer, // path to service's binary - NULL, // no load ordering group - NULL, // no tag identifier - NULL, // no dependencies - NULL, // LocalSystem account - NULL); // no password + nullptr, // no load ordering group + nullptr, // no tag identifier + nullptr, // no dependencies + nullptr, // LocalSystem account + nullptr); // no password - if (schService == NULL) + if (schService == nullptr) { - // printf("CreateService failed (%d)\n", GetLastError()); std::cout << "CreateService failed " << GetLastError() << "\n"; CloseServiceHandle(schSCManager); @@ -160,7 +109,6 @@ VOID ServiceInstall() } else { - // printf("Service installed successfully\n"); std::cout << "Service installed successfully\n"; } @@ -168,204 +116,33 @@ VOID ServiceInstall() CloseServiceHandle(schSCManager); } +template VOID ServiceReportEvent(LPTSTR szFunction) { - HANDLE hEventSource; - LPCTSTR lpszStrings[2]; - TCHAR Buffer[80]; + CTStr lpszStrings[2]; + Char Buffer[80]; - hEventSource = RegisterEventSource(NULL, SVCNAME); + Handle hEventSource = RegisterEventSource(nullptr, service_info->service_name); - if (NULL != hEventSource) + if (nullptr != hEventSource) { StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); - lpszStrings[0] = SVCNAME; + lpszStrings[0] = service_info->service_name; lpszStrings[1] = Buffer; ReportEvent(hEventSource, // event log handle EVENTLOG_ERROR_TYPE, // event type 0, // event category - // SVC_ERROR, SERVICE_ERROR_NORMAL, // event identifier - NULL, // no security identifier + nullptr, // no security identifier 2, // size of lpszStrings array 0, // no binary data lpszStrings, // array of strings - NULL); // no binary data + nullptr); // no binary data DeregisterEventSource(hEventSource); } } - -VOID ReportServiceStatus(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) -{ - static DWORD dwCheckPoint = 1; - - g_ServiceStatus.dwCurrentState = dwCurrentState; - g_ServiceStatus.dwWin32ExitCode = dwWin32ExitCode; - g_ServiceStatus.dwWaitHint = dwWaitHint; - - if (dwCurrentState == SERVICE_START_PENDING) - { - g_ServiceStatus.dwControlsAccepted = 0; - } - else - { - g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - } - - if ((dwCurrentState == SERVICE_RUNNING) || - (dwCurrentState == SERVICE_STOPPED)) - { - g_ServiceStatus.dwCheckPoint = 0; - } - else - { - g_ServiceStatus.dwCheckPoint = dwCheckPoint++; - } - - SetServiceStatus(g_StatusHandle, &g_ServiceStatus); -} - -VOID WINAPI ServiceCtrlHandler(DWORD dwCtrl) -{ - switch (dwCtrl) - { - case SERVICE_CONTROL_STOP: - ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); - - SetEvent(g_ServiceStopEvent); - ReportServiceStatus(g_ServiceStatus.dwCurrentState, NO_ERROR, 0); - - return; - case SERVICE_CONTROL_INTERROGATE: - break; - default: - break; - } -} - - - - - -VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) -// template -// VOID WINAPI ServiceMain(D argc, LStr *argv) -{ - g_StatusHandle = RegisterServiceCtrlHandler( - SVCNAME, - ServiceCtrlHandler); - - if (!g_StatusHandle) - { - // Report the service event - return; - } - - - - // Tell the service controller we are starting - ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus)); - g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - g_ServiceStatus.dwControlsAccepted = 0; - g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; - g_ServiceStatus.dwWin32ExitCode = 0; - g_ServiceStatus.dwServiceSpecificExitCode = 0; - g_ServiceStatus.dwCheckPoint = 0; - - if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) - { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); - } - - /* - * Perform tasks necessary to start the service here - */ - - // Create a service stop event to wait on later - g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (g_ServiceStopEvent == NULL) - { - // Error creating event - // Tell service controller we are stopped and exit - g_ServiceStatus.dwControlsAccepted = 0; - g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; - g_ServiceStatus.dwWin32ExitCode = GetLastError(); - g_ServiceStatus.dwCheckPoint = 1; - - if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) - { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); - } - - return; - } - - - // Tell the service controller we are started - g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; - g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; - g_ServiceStatus.dwWin32ExitCode = 0; - g_ServiceStatus.dwCheckPoint = 0; - - if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) - { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); - } - - // Start a thread that will perform the main task of the service - HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); - - // Wait until our worker thread exits signaling that the service needs to stop - WaitForSingleObject(hThread, INFINITE); - - - /* - * Perform any cleanup tasks - */ - - CloseHandle(g_ServiceStopEvent); - - // Tell the service controller we are stopped - g_ServiceStatus.dwControlsAccepted = 0; - g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; - g_ServiceStatus.dwWin32ExitCode = 0; - g_ServiceStatus.dwCheckPoint = 3; - - if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) - { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); - } -} - -DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) -{ - // const auto some_file_path = "C:\\Users\\brahmix\\example_file.txt"; - const auto some_file_path = "C:\\example_file.txt"; - - while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0) - { - std::fstream file(some_file_path, std::ios::out | std::ios::app); - - const auto content = "test"; - - file << content << "\n"; - - file.close(); - - Sleep(3000); - } - - - return ERROR_SUCCESS; -} - diff --git a/ServiceExample/ServiceControlHandler.hpp b/ServiceExample/ServiceControlHandler.hpp index 0fc07bb..4597c54 100644 --- a/ServiceExample/ServiceControlHandler.hpp +++ b/ServiceExample/ServiceControlHandler.hpp @@ -14,20 +14,20 @@ namespace service class ServiceControlHandler { public: - template + template, + typename Ptr = std::shared_ptr> static VOID WINAPI ServiceCtrlHandler(D ctrlCode) { - extern std::shared_ptr> service_info; + extern Ptr service_info; switch (ctrlCode) { case SERVICE_CONTROL_STOP: - // ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); - ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); + ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); SetEvent(service_info->service_stop_event); - // ReportServiceStatus(g_ServiceStatus.dwCurrentState, NO_ERROR, 0); - ReportServiceStatus(service_info->service_status.dwCurrentState, NO_ERROR, 0); + ReportServiceStatus(service_info->service_status.dwCurrentState, NO_ERROR, 0); return; case SERVICE_CONTROL_INTERROGATE: @@ -36,21 +36,18 @@ namespace service break; } } - // static SERVICE_STATUS g_ServiceStatus = {0}; - // static SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; - // static SERVICE_STATUS g_ServiceStatus; - // static SERVICE_STATUS_HANDLE g_StatusHandle = nullptr; - // static SERVICE_STATUS_HANDLE g_StatusHandle; - - static VOID ReportServiceStatus(DWORD dwCurrentState, - DWORD dwWin32ExitCode, - DWORD dwWaitHint) + template, + typename Ptr = std::shared_ptr> + static VOID ReportServiceStatus(D dwCurrentState, + D dwWin32ExitCode, + D dwWaitHint) { - extern std::shared_ptr> service_info; + extern Ptr service_info; - static DWORD dwCheckPoint = 1; + static D dwCheckPoint = 1; service_info->service_status.dwCurrentState = dwCurrentState; service_info->service_status.dwWin32ExitCode = dwWin32ExitCode; @@ -75,7 +72,6 @@ namespace service service_info->service_status.dwCheckPoint = dwCheckPoint++; } - // SetServiceStatus(g_StatusHandle, &service_info->service_status); SetServiceStatus(service_info->service_handle, &service_info->service_status); } diff --git a/ServiceExample/ServiceEntryPoint.hpp b/ServiceExample/ServiceEntryPoint.hpp index f742fcf..8aaacd4 100644 --- a/ServiceExample/ServiceEntryPoint.hpp +++ b/ServiceExample/ServiceEntryPoint.hpp @@ -16,60 +16,85 @@ namespace service class ServiceEntryPoint { public: - ServiceEntryPoint() - { - initialize(); - } + ServiceEntryPoint() = default; - ServiceEntryPoint(std::wstring name) + template, + typename Ptr = std::shared_ptr> + static VOID WINAPI service_main_start(D argc, TStr *argv) { - // service_name = static_cast(name); - // service_name = name.c_str(); - initialize(); - } - - static VOID WINAPI service_main_start(DWORD argc, LPTSTR *argv) - { - // extern models::ServiceInfo<> service_info; - extern std::shared_ptr> service_info; - + extern Ptr service_info; service_info->service_handle = RegisterServiceCtrlHandler( - // SVCNAME, service_info->service_name, - // ServiceCtrlHandler); service::ServiceControlHandler::ServiceCtrlHandler); if (!service_info->service_handle) { - // Report the service event return; } + notify_service_controller_starting(service_info); - - // Tell the service controller we are starting - ZeroMemory(&service_info->service_status, sizeof(service_info->service_status)); - service_info->service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - service_info->service_status.dwControlsAccepted = 0; - service_info->service_status.dwCurrentState = SERVICE_START_PENDING; - service_info->service_status.dwWin32ExitCode = 0; - service_info->service_status.dwServiceSpecificExitCode = 0; - service_info->service_status.dwCheckPoint = 0; - - if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE) + + if (!starting_service(service_info)) { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); + return; } + notify_service_controller_started(service_info); + + // Start a thread that will perform the main task of the service + Handle hThread = CreateThread(nullptr, 0, ServiceWorkerThread, nullptr, 0, nullptr); + + // Wait until our worker thread exits signaling that the service needs to stop + WaitForSingleObject(hThread, INFINITE); + + + close_handle(service_info); + } + private: + template, + typename Ptr = std::shared_ptr> + static D WINAPI ServiceWorkerThread(Lp lpParam) + { + extern Ptr service_info; + + const auto INTERVAL = 1500; + + const auto some_file_path = "C:\\example_file.txt"; + + while (WaitForSingleObject(service_info->service_stop_event, 0) != WAIT_OBJECT_0) + { + std::fstream file(some_file_path, std::ios::out | std::ios::app); + + const auto content = "burrow"; + + file << content << "\n"; + + file.close(); + + Sleep(INTERVAL); + } + + + return ERROR_SUCCESS; + } + + + template, + typename Ptr = std::shared_ptr> + static bool starting_service(Ptr service_info) + { /* * Perform tasks necessary to start the service here */ // Create a service stop event to wait on later - service_info->service_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL); - if (service_info->service_stop_event == NULL) + service_info->service_stop_event = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (service_info->service_stop_event == nullptr) { // Error creating event // Tell service controller we are stopped and exit @@ -84,29 +109,17 @@ namespace service "My Sample Service: ServiceMain: SetServiceStatus returned error")); } - return; + return false; } - - // Tell the service controller we are started - service_info->service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; - service_info->service_status.dwCurrentState = SERVICE_RUNNING; - service_info->service_status.dwWin32ExitCode = 0; - service_info->service_status.dwCheckPoint = 0; - - if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE) - { - OutputDebugString(_T( - "My Sample Service: ServiceMain: SetServiceStatus returned error")); - } - - // Start a thread that will perform the main task of the service - HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); - - // Wait until our worker thread exits signaling that the service needs to stop - WaitForSingleObject(hThread, INFINITE); + return true; + } + template, + typename Ptr = std::shared_ptr> + static void close_handle(Ptr service_info) + { /* * Perform any cleanup tasks */ @@ -126,104 +139,42 @@ namespace service } } - - - static DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) - // static DWORD WINAPI ServiceWorkerThread(LPVOID lpParam, - // std::shared_ptr> service_info) + template, + typename Ptr = std::shared_ptr> + static void notify_service_controller_starting(Ptr service_info) { - extern std::shared_ptr> service_info; + // Tell the service controller we are starting + ZeroMemory(&service_info->service_status, sizeof(service_info->service_status)); + service_info->service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + service_info->service_status.dwControlsAccepted = 0; + service_info->service_status.dwCurrentState = SERVICE_START_PENDING; + service_info->service_status.dwWin32ExitCode = 0; + service_info->service_status.dwServiceSpecificExitCode = 0; + service_info->service_status.dwCheckPoint = 0; - // const auto some_file_path = "C:\\Users\\brahmix\\example_file.txt"; - const auto some_file_path = "C:\\example_file.txt"; - - // while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0) - while (WaitForSingleObject(service_info->service_stop_event, 0) != WAIT_OBJECT_0) + if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE) { - std::fstream file(some_file_path, std::ios::out | std::ios::app); - - const auto content = "woof"; - - file << content << "\n"; - - file.close(); - - Sleep(3000); - } - - - return ERROR_SUCCESS; - } - - - template - // VOID ServiceReportEvent(LPTSTR szFunction) - VOID ServiceReportEvent(TStr szFunction) - { - // HANDLE hEventSource; - H hEventSource; - // LPCTSTR lpszStrings[2]; - CSTR lpszStrings[2]; - // TCHAR Buffer[80]; - CHR Buffer[80]; - - hEventSource = RegisterEventSource(NULL, this->service_info.service_name); - // hEventSource = RegisterEventSource(NULL, L("")); - - if (NULL != hEventSource) - { - StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); - - lpszStrings[0] = SVCNAME; - lpszStrings[1] = Buffer; - - ReportEvent(hEventSource, // event log handle - EVENTLOG_ERROR_TYPE, // event type - 0, // event category - // SVC_ERROR, - SERVICE_ERROR_NORMAL, // event identifier - NULL, // no security identifier - 2, // size of lpszStrings array - 0, // no binary data - lpszStrings, // array of strings - NULL); // no binary data - - DeregisterEventSource(hEventSource); + OutputDebugString(_T( + "My Sample Service: ServiceMain: SetServiceStatus returned error")); } } - private: - models::ServiceInfo<> service_info; - void initialize() + template, + typename Ptr = std::shared_ptr> + static void notify_service_controller_started(Ptr service_info) { - // service_info.service_name = L" Server Example"; + // Tell the service controller we are started + service_info->service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + service_info->service_status.dwCurrentState = SERVICE_RUNNING; + service_info->service_status.dwWin32ExitCode = 0; + service_info->service_status.dwCheckPoint = 0; + + if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE) + { + OutputDebugString(_T( + "My Sample Service: ServiceMain: SetServiceStatus returned error")); + } } - /** - class ServiceInfo; - - - service::ServiceEntryPoint::ServiceInfo service_info = {}; - - class ServiceInfo - { - public: - ServiceInfo() - { - } - - ServiceInfo(std::wstring &&name) : - service_name(const_cast(name.c_str())) - { - - } - - wchar_t *service_name; - wchar_t *service_description; - }; - */ - }; }