-
Notifications
You must be signed in to change notification settings - Fork 38
/
Copy pathNtUtils.Svc.SingleTaskSvc.pas
118 lines (95 loc) · 2.74 KB
/
NtUtils.Svc.SingleTaskSvc.pas
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
unit NtUtils.Svc.SingleTaskSvc;
{
This module provides a template for a simple service application that executes
its payload and exits.
}
interface
uses
NtUtils, NtUtils.Svc;
type
TSvcxPayload = reference to procedure(const ScvParams: TArray<String>);
// Starts service control dispatcher.
function SvcxMain(
const ServiceName: String;
Payload: TSvcxPayload
): TNtxStatus;
implementation
uses
Ntapi.WinNt, Ntapi.WinSvc, Ntapi.WinError, Ntapi.WinBase;
{$BOOLEVAL OFF}
{$IFOPT R+}{$DEFINE R+}{$ENDIF}
{$IFOPT Q+}{$DEFINE Q+}{$ENDIF}
var
SvcxName: String;
SvcxPayload: TSvcxPayload = nil;
SvcxStatusHandle: THandle;
SvcxStatus: TServiceStatus = (
ServiceType: SERVICE_WIN32_OWN_PROCESS;
CurrentState: SERVICE_RUNNING;
ControlsAccepted: 0;
Win32ExitCode: 0;
ServiceSpecificExitCode: 0;
CheckPoint: 0;
WaitHint: 5000
);
function SvcxHandlerEx(
Control: TServiceControl;
EventType: Cardinal;
EventData: Pointer;
var Context
): TWin32Error; stdcall;
begin
if Control = SERVICE_CONTROL_INTERROGATE then
Result := ERROR_SUCCESS
else
Result := ERROR_CALL_NOT_IMPLEMENTED;
end;
procedure SvcxServiceMain(
dwNumServicesArgs: Integer;
const [ref] ServiceArgVectors: TAnysizeArray<PWideChar>
); stdcall;
var
i: Integer;
Parameters: TArray<String>;
begin
// Register service control handler
SvcxStatusHandle := RegisterServiceCtrlHandlerExW(PWideChar(SvcxName),
SvcxHandlerEx, nil);
// Report running status
SetServiceStatus(SvcxStatusHandle, SvcxStatus);
// Prepare passed parameters
SetLength(Parameters, dwNumServicesArgs);
for i := 0 to High(Parameters) do
Parameters[i] := String(ServiceArgVectors{$R-}[i]{$IFDEF R+}{$R+}{$ENDIF});
{$IFDEF DEBUG}
OutputDebugStringW(PWideChar(ParamStr(0)));
OutputDebugStringW('Service parameters: ');
for i := 0 to dwNumServicesArgs - 1 do
OutputDebugStringW(PWideChar(Parameters[i]));
{$ENDIF}
// Call the payload
try
if Assigned(SvcxPayload) then
SvcxPayload(Parameters);
except
OutputDebugStringW('Exception in ServiceMain');
end;
// Report that we have finished
SvcxStatus.CurrentState := SERVICE_STOPPED;
SetServiceStatus(SvcxStatusHandle, SvcxStatus);
end;
function SvcxMain;
var
ServiceTable: array [0 .. 1] of TServiceTableEntry;
begin
SvcxName := ServiceName;
SvcxPayload := Payload;
ServiceTable[0].ServiceName := PWideChar(SvcxName);
ServiceTable[0].ServiceProc := SvcxServiceMain;
ServiceTable[1].ServiceName := nil;
ServiceTable[1].ServiceProc := nil;
Result.Location := 'StartServiceCtrlDispatcherW';
Result.Win32Result := StartServiceCtrlDispatcherW(PServiceTableEntry(
@ServiceTable));
end;
end.