First commit
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.40629.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServiceExample", "ServiceExample\ServiceExample.vcxproj", "{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,371 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#pragma comment(lib, "kernel32.lib")
|
||||
|
||||
#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<typename D = DWORD, typename LStr = LPTSTR>
|
||||
// VOID WINAPI ServiceMain(D, LStr *);
|
||||
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*);
|
||||
VOID ServiceReportEvent(LPTSTR);
|
||||
|
||||
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
|
||||
|
||||
// models::ServiceInfo<> service_info(L"Service Example");
|
||||
std::shared_ptr<models::ServiceInfo<>> 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<DWORD, LPTSTR> },
|
||||
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
*/
|
||||
|
||||
// if (StartServiceCtr)
|
||||
|
||||
if (lstrcmpi(argv[1], TEXT("install")) == 0)
|
||||
{
|
||||
ServiceInstall();
|
||||
|
||||
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<DWORD, LPTSTR> },
|
||||
// { SVCNAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
|
||||
// { service_info.service_name, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
|
||||
// { (const_cast<wchar_t*>(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 },
|
||||
{ nullptr, nullptr },
|
||||
};
|
||||
|
||||
if (!StartServiceCtrlDispatcher(SERVICETABLE))
|
||||
{
|
||||
auto func = reinterpret_cast<LPTSTR>(TEXT("StartServiceCtrlDispatcher"));
|
||||
ServiceReportEvent(func);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
VOID ServiceInstall()
|
||||
{
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
// TCHAR szPath[MAX_PATH];
|
||||
wchar_t buffer[MAX_PATH];
|
||||
|
||||
// if (!GetModuleFileName("", szPath, MAX_PATH))
|
||||
if (!GetModuleFileName(nullptr, buffer, MAX_PATH))
|
||||
{
|
||||
std::cout << "Cannot install service " << GetLastError() << "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a handle to the SCM database.
|
||||
|
||||
schSCManager = OpenSCManager(
|
||||
NULL, // local computer
|
||||
NULL, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
||||
if (NULL == schSCManager)
|
||||
{
|
||||
std::cout << "OpenSCManager failed " << GetLastError() << "\n";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the service
|
||||
|
||||
schService = CreateService(
|
||||
schSCManager, // SCM database
|
||||
SVCNAME, // name of service
|
||||
SVCNAME, // 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
|
||||
|
||||
if (schService == NULL)
|
||||
{
|
||||
// printf("CreateService failed (%d)\n", GetLastError());
|
||||
std::cout << "CreateService failed " << GetLastError() << "\n";
|
||||
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printf("Service installed successfully\n");
|
||||
std::cout << "Service installed successfully\n";
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
}
|
||||
|
||||
VOID ServiceReportEvent(LPTSTR szFunction)
|
||||
{
|
||||
HANDLE hEventSource;
|
||||
LPCTSTR lpszStrings[2];
|
||||
TCHAR Buffer[80];
|
||||
|
||||
hEventSource = RegisterEventSource(NULL, SVCNAME);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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<typename D, typename LStr>
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef MODELS_H_
|
||||
#define MODELS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace models
|
||||
{
|
||||
template<typename Str = std::wstring,
|
||||
typename Char = wchar_t,
|
||||
typename Status = SERVICE_STATUS,
|
||||
typename StatusHandle = SERVICE_STATUS_HANDLE,
|
||||
typename Handle = HANDLE>
|
||||
class ServiceInfo
|
||||
{
|
||||
public:
|
||||
ServiceInfo()
|
||||
{
|
||||
service_stop_event = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
ServiceInfo(std::wstring &&name) :
|
||||
service_name(const_cast<wchar_t*>(name.c_str()))
|
||||
{
|
||||
service_stop_event = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
wchar_t *service_name;
|
||||
Status service_status;
|
||||
StatusHandle service_handle;
|
||||
Handle service_stop_event;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef SERVICECONTROLHANDLER_H_
|
||||
#define SERVICECONTROLHANDLER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include "Models.h"
|
||||
|
||||
namespace service
|
||||
{
|
||||
class ServiceControlHandler
|
||||
{
|
||||
public:
|
||||
template<typename D = DWORD>
|
||||
static VOID WINAPI ServiceCtrlHandler(D ctrlCode)
|
||||
{
|
||||
extern std::shared_ptr<models::ServiceInfo<>> service_info;
|
||||
|
||||
switch (ctrlCode)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
// 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);
|
||||
|
||||
return;
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
extern std::shared_ptr<models::ServiceInfo<>> service_info;
|
||||
|
||||
static DWORD dwCheckPoint = 1;
|
||||
|
||||
service_info->service_status.dwCurrentState = dwCurrentState;
|
||||
service_info->service_status.dwWin32ExitCode = dwWin32ExitCode;
|
||||
service_info->service_status.dwWaitHint = dwWaitHint;
|
||||
|
||||
if (dwCurrentState == SERVICE_START_PENDING)
|
||||
{
|
||||
service_info->service_status.dwControlsAccepted = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
service_info->service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
}
|
||||
|
||||
if ((dwCurrentState == SERVICE_RUNNING) ||
|
||||
(dwCurrentState == SERVICE_STOPPED))
|
||||
{
|
||||
service_info->service_status.dwCheckPoint = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
service_info->service_status.dwCheckPoint = dwCheckPoint++;
|
||||
}
|
||||
|
||||
// SetServiceStatus(g_StatusHandle, &service_info->service_status);
|
||||
SetServiceStatus(service_info->service_handle, &service_info->service_status);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,230 @@
|
||||
#ifndef SERVICEENTRYPOINT_H_
|
||||
#define SERVICEENTRYPOINT_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include "Models.h"
|
||||
#include "ServiceControlHandler.hpp"
|
||||
|
||||
namespace service
|
||||
{
|
||||
class ServiceEntryPoint
|
||||
{
|
||||
public:
|
||||
ServiceEntryPoint()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
ServiceEntryPoint(std::wstring name)
|
||||
{
|
||||
// service_name = static_cast<std::wstring>(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<models::ServiceInfo<>> 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 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)
|
||||
{
|
||||
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
|
||||
service_info->service_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (service_info->service_stop_event == NULL)
|
||||
{
|
||||
// Error creating event
|
||||
// Tell service controller we are stopped and exit
|
||||
service_info->service_status.dwControlsAccepted = 0;
|
||||
service_info->service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
service_info->service_status.dwWin32ExitCode = GetLastError();
|
||||
service_info->service_status.dwCheckPoint = 1;
|
||||
|
||||
if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE)
|
||||
{
|
||||
OutputDebugString(_T(
|
||||
"My Sample Service: ServiceMain: SetServiceStatus returned error"));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
/*
|
||||
* Perform any cleanup tasks
|
||||
*/
|
||||
|
||||
CloseHandle(service_info->service_stop_event);
|
||||
|
||||
// Tell the service controller we are stopped
|
||||
service_info->service_status.dwControlsAccepted = 0;
|
||||
service_info->service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
service_info->service_status.dwWin32ExitCode = 0;
|
||||
service_info->service_status.dwCheckPoint = 3;
|
||||
|
||||
if (SetServiceStatus(service_info->service_handle, &service_info->service_status) == FALSE)
|
||||
{
|
||||
OutputDebugString(_T(
|
||||
"My Sample Service: ServiceMain: SetServiceStatus returned error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
|
||||
// static DWORD WINAPI ServiceWorkerThread(LPVOID lpParam,
|
||||
// std::shared_ptr<models::ServiceInfo<>> service_info)
|
||||
{
|
||||
extern std::shared_ptr<models::ServiceInfo<>> service_info;
|
||||
|
||||
// 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)
|
||||
{
|
||||
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<typename TStr = LPTSTR, typename H = HANDLE,
|
||||
typename CSTR = LPCTSTR,
|
||||
typename Chr = TCHAR>
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
private:
|
||||
models::ServiceInfo<> service_info;
|
||||
|
||||
void initialize()
|
||||
{
|
||||
// service_info.service_name = L" Server Example";
|
||||
}
|
||||
/**
|
||||
class ServiceInfo;
|
||||
|
||||
|
||||
service::ServiceEntryPoint::ServiceInfo service_info = {};
|
||||
|
||||
class ServiceInfo
|
||||
{
|
||||
public:
|
||||
ServiceInfo()
|
||||
{
|
||||
}
|
||||
|
||||
ServiceInfo(std::wstring &&name) :
|
||||
service_name(const_cast<wchar_t*>(name.c_str()))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
wchar_t *service_name;
|
||||
wchar_t *service_description;
|
||||
};
|
||||
*/
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{19AD11CD-7C72-41C6-B372-32A63C2EAB7A}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ServiceExample</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>C:\Users\brahmix\Programming\c++\pre_2015\soci\soci_4_0_0\include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Users\brahmix\Programming\c++\pre_2015\soci\soci_4_0_0\bin;C:\Windows\System32;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalLibraryDirectories>C:\Users\brahmix\Programming\c++\pre_2015\soci\soci_4_0_0\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BaseService.hpp" />
|
||||
<ClInclude Include="Models.h" />
|
||||
<ClInclude Include="ServiceControlHandler.hpp" />
|
||||
<ClInclude Include="ServiceEntryPoint.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user