-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathServiceMain.cpp
70 lines (59 loc) · 2.3 KB
/
ServiceMain.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <windows.h>
#include <tchar.h>
#include <string>
#define SERVICE_NAME TEXT("OnShutdown")
SERVICE_STATUS service_status = {};
SERVICE_STATUS_HANDLE status_handle = NULL;
HANDLE stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
TCHAR* shell_command;
DWORD wait_hint;
VOID WINAPI ServiceMain(DWORD, LPTSTR*);
DWORD WINAPI ServiceCtrlHandlerEx(DWORD, DWORD, LPVOID, LPVOID);
void _tmain(int argc, TCHAR* argv[])
{
if (argc < 3)
_tprintf(TEXT("Usage: %s <wait hint in ms> <command>"), SERVICE_NAME);
else
{
wait_hint = std::stoi(argv[1]);
shell_command = argv[2];
SERVICE_TABLE_ENTRY DispatchTable[] = { {SERVICE_NAME, ServiceMain}, {NULL, NULL} };
StartServiceCtrlDispatcher(DispatchTable);
}
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv)
{
status_handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, ServiceCtrlHandlerEx, NULL);
service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
service_status.dwCurrentState = SERVICE_RUNNING;
service_status.dwWin32ExitCode = NO_ERROR;
SetServiceStatus(status_handle, &service_status);
WaitForSingleObject(stop_event, INFINITE);
service_status.dwCurrentState = SERVICE_STOPPED;
service_status.dwCheckPoint++;
SetServiceStatus(status_handle, &service_status);
CloseHandle(stop_event);
}
DWORD WINAPI ServiceCtrlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
switch (dwControl) // intentional fall through..
{
case SERVICE_CONTROL_PRESHUTDOWN:
{
service_status.dwCurrentState = SERVICE_STOP_PENDING;
service_status.dwCheckPoint++;
service_status.dwWaitHint = wait_hint;
SetServiceStatus(status_handle, &service_status);
PROCESS_INFORMATION pi = {}; STARTUPINFO si = { sizeof(si) };
if (CreateProcess(NULL, shell_command, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
case SERVICE_CONTROL_STOP: SetEvent(stop_event);
default: return NO_ERROR;
}
}