1 /***********************************************************************\
2 *                                winsvc.d                               *
3 *                                                                       *
4 *                       Windows API header module                       *
5 *                                                                       *
6 *                 Translated from MinGW Windows headers                 *
7 *                           by Stewart Gordon                           *
8 *                                                                       *
9 *                       Placed into public domain                       *
10 \***********************************************************************/
11 module win32.winsvc;
12 pragma(lib, "advapi32.lib");
13 
14 private import win32.w32api, win32.windef;
15 
16 static assert (_WIN32_WINNT_ONLY,
17 	"win32.winsvc is available only if version WindowsNTonly, WindowsXP, "
18 	"Windows2003 or WindowsVista is set");
19 
20 
21 // FIXME: check Windows version support
22 
23 const TCHAR[]
24 	SERVICES_ACTIVE_DATABASE = "ServicesActive",
25 	SERVICES_FAILED_DATABASE = "ServicesFailed";
26 
27 const TCHAR SC_GROUP_IDENTIFIER = '+';
28 
29 const DWORD
30 	SC_MANAGER_ALL_ACCESS         = 0xf003f,
31 	SC_MANAGER_CONNECT            =  1,
32 	SC_MANAGER_CREATE_SERVICE     =  2,
33 	SC_MANAGER_ENUMERATE_SERVICE  =  4,
34 	SC_MANAGER_LOCK               =  8,
35 	SC_MANAGER_QUERY_LOCK_STATUS  = 16,
36 	SC_MANAGER_MODIFY_BOOT_CONFIG = 32;
37 
38 const DWORD SERVICE_NO_CHANGE = 0xffffffff;
39 
40 enum : DWORD {
41 	SERVICE_STOPPED = 1,
42 	SERVICE_START_PENDING,
43 	SERVICE_STOP_PENDING,
44 	SERVICE_RUNNING,
45 	SERVICE_CONTINUE_PENDING,
46 	SERVICE_PAUSE_PENDING,
47 	SERVICE_PAUSED // = 7
48 }
49 
50 const DWORD
51 	SERVICE_ACCEPT_STOP                  =   1,
52 	SERVICE_ACCEPT_PAUSE_CONTINUE        =   2,
53 	SERVICE_ACCEPT_SHUTDOWN              =   4,
54 	SERVICE_ACCEPT_PARAMCHANGE           =   8,
55 	SERVICE_ACCEPT_NETBINDCHANGE         =  16,
56 	SERVICE_ACCEPT_HARDWAREPROFILECHANGE =  32,
57 	SERVICE_ACCEPT_POWEREVENT            =  64,
58 	SERVICE_ACCEPT_SESSIONCHANGE         = 128;
59 
60 enum : DWORD {
61 	SERVICE_CONTROL_STOP = 1,
62 	SERVICE_CONTROL_PAUSE,
63 	SERVICE_CONTROL_CONTINUE,
64 	SERVICE_CONTROL_INTERROGATE,
65 	SERVICE_CONTROL_SHUTDOWN,
66 	SERVICE_CONTROL_PARAMCHANGE,
67 	SERVICE_CONTROL_NETBINDADD,
68 	SERVICE_CONTROL_NETBINDREMOVE,
69 	SERVICE_CONTROL_NETBINDENABLE,
70 	SERVICE_CONTROL_NETBINDDISABLE,
71 	SERVICE_CONTROL_DEVICEEVENT,
72 	SERVICE_CONTROL_HARDWAREPROFILECHANGE,
73 	SERVICE_CONTROL_POWEREVENT,
74 	SERVICE_CONTROL_SESSIONCHANGE, // = 14
75 }
76 
77 enum : DWORD {
78 	SERVICE_ACTIVE = 1,
79 	SERVICE_INACTIVE,
80 	SERVICE_STATE_ALL
81 }
82 
83 const DWORD
84 	SERVICE_QUERY_CONFIG         = 0x0001,
85 	SERVICE_CHANGE_CONFIG        = 0x0002,
86 	SERVICE_QUERY_STATUS         = 0x0004,
87 	SERVICE_ENUMERATE_DEPENDENTS = 0x0008,
88 	SERVICE_START                = 0x0010,
89 	SERVICE_STOP                 = 0x0020,
90 	SERVICE_PAUSE_CONTINUE       = 0x0040,
91 	SERVICE_INTERROGATE          = 0x0080,
92 	SERVICE_USER_DEFINED_CONTROL = 0x0100,
93 	SERVICE_ALL_ACCESS           = 0x01FF | STANDARD_RIGHTS_REQUIRED;
94 
95 // This is not documented on the MSDN site
96 const SERVICE_RUNS_IN_SYSTEM_PROCESS = 1;
97 
98 enum : DWORD {
99 	SERVICE_CONFIG_DESCRIPTION         = 1,
100 	SERVICE_CONFIG_FAILURE_ACTIONS,
101 	SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
102 	SERVICE_CONFIG_FAILURE_ACTIONS_FLAG,
103 	SERVICE_CONFIG_SERVICE_SID_INFO,
104 	SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO,
105 	SERVICE_CONFIG_PRESHUTDOWN_INFO // = 7
106 }
107 
108 struct SERVICE_STATUS {
109 	DWORD dwServiceType;
110 	DWORD dwCurrentState;
111 	DWORD dwControlsAccepted;
112 	DWORD dwWin32ExitCode;
113 	DWORD dwServiceSpecificExitCode;
114 	DWORD dwCheckPoint;
115 	DWORD dwWaitHint;
116 }
117 alias SERVICE_STATUS* LPSERVICE_STATUS;
118 
119 struct ENUM_SERVICE_STATUSA {
120 	LPSTR          lpServiceName;
121 	LPSTR          lpDisplayName;
122 	SERVICE_STATUS ServiceStatus;
123 }
124 alias ENUM_SERVICE_STATUSA* LPENUM_SERVICE_STATUSA;
125 
126 struct ENUM_SERVICE_STATUSW {
127 	LPWSTR         lpServiceName;
128 	LPWSTR         lpDisplayName;
129 	SERVICE_STATUS ServiceStatus;
130 }
131 alias ENUM_SERVICE_STATUSW* LPENUM_SERVICE_STATUSW;
132 
133 struct QUERY_SERVICE_CONFIGA {
134 	DWORD dwServiceType;
135 	DWORD dwStartType;
136 	DWORD dwErrorControl;
137 	LPSTR lpBinaryPathName;
138 	LPSTR lpLoadOrderGroup;
139 	DWORD dwTagId;
140 	LPSTR lpDependencies;
141 	LPSTR lpServiceStartName;
142 	LPSTR lpDisplayName;
143 }
144 alias QUERY_SERVICE_CONFIGA* LPQUERY_SERVICE_CONFIGA;
145 
146 struct QUERY_SERVICE_CONFIGW {
147 	DWORD  dwServiceType;
148 	DWORD  dwStartType;
149 	DWORD  dwErrorControl;
150 	LPWSTR lpBinaryPathName;
151 	LPWSTR lpLoadOrderGroup;
152 	DWORD  dwTagId;
153 	LPWSTR lpDependencies;
154 	LPWSTR lpServiceStartName;
155 	LPWSTR lpDisplayName;
156 }
157 alias QUERY_SERVICE_CONFIGW* LPQUERY_SERVICE_CONFIGW;
158 
159 struct QUERY_SERVICE_LOCK_STATUSA {
160 	DWORD fIsLocked;
161 	LPSTR lpLockOwner;
162 	DWORD dwLockDuration;
163 }
164 alias QUERY_SERVICE_LOCK_STATUSA* LPQUERY_SERVICE_LOCK_STATUSA;
165 
166 struct QUERY_SERVICE_LOCK_STATUSW {
167 	DWORD  fIsLocked;
168 	LPWSTR lpLockOwner;
169 	DWORD  dwLockDuration;
170 }
171 alias QUERY_SERVICE_LOCK_STATUSW* LPQUERY_SERVICE_LOCK_STATUSW;
172 
173 extern (Windows) {
174 	alias void function(DWORD, LPSTR*)  LPSERVICE_MAIN_FUNCTIONA;
175 	alias void function(DWORD, LPWSTR*) LPSERVICE_MAIN_FUNCTIONW;
176 }
177 
178 struct SERVICE_TABLE_ENTRYA {
179 	LPSTR                    lpServiceName;
180 	LPSERVICE_MAIN_FUNCTIONA lpServiceProc;
181 }
182 alias SERVICE_TABLE_ENTRYA* LPSERVICE_TABLE_ENTRYA;
183 
184 struct SERVICE_TABLE_ENTRYW {
185 	LPWSTR                   lpServiceName;
186 	LPSERVICE_MAIN_FUNCTIONW lpServiceProc;
187 }
188 alias SERVICE_TABLE_ENTRYW* LPSERVICE_TABLE_ENTRYW;
189 
190 alias HANDLE SC_HANDLE;
191 alias HANDLE* LPSC_HANDLE;
192 alias void* SC_LOCK;
193 alias DWORD SERVICE_STATUS_HANDLE;
194 
195 extern (Windows) {
196 	alias void function(DWORD) LPHANDLER_FUNCTION;
197 	alias DWORD function(DWORD, DWORD, LPVOID, LPVOID) LPHANDLER_FUNCTION_EX;
198 }
199 
200 static if (_WIN32_WINNT >= 0x500) {
201 	struct SERVICE_STATUS_PROCESS {
202 		DWORD dwServiceType;
203 		DWORD dwCurrentState;
204 		DWORD dwControlsAccepted;
205 		DWORD dwWin32ExitCode;
206 		DWORD dwServiceSpecificExitCode;
207 		DWORD dwCheckPoint;
208 		DWORD dwWaitHint;
209 		DWORD dwProcessId;
210 		DWORD dwServiceFlags;
211 	}
212 	alias SERVICE_STATUS_PROCESS* LPSERVICE_STATUS_PROCESS;
213 
214 	enum SC_STATUS_TYPE {
215 		SC_STATUS_PROCESS_INFO = 0
216 	}
217 
218 	enum SC_ENUM_TYPE {
219 		SC_ENUM_PROCESS_INFO = 0
220 	}
221 
222 	struct ENUM_SERVICE_STATUS_PROCESSA {
223 		LPSTR                  lpServiceName;
224 		LPSTR                  lpDisplayName;
225 		SERVICE_STATUS_PROCESS ServiceStatusProcess;
226 	}
227 	alias ENUM_SERVICE_STATUS_PROCESSA* LPENUM_SERVICE_STATUS_PROCESSA;
228 
229 	struct ENUM_SERVICE_STATUS_PROCESSW {
230 		LPWSTR                 lpServiceName;
231 		LPWSTR                 lpDisplayName;
232 		SERVICE_STATUS_PROCESS ServiceStatusProcess;
233 	}
234 	alias ENUM_SERVICE_STATUS_PROCESSW* LPENUM_SERVICE_STATUS_PROCESSW;
235 
236 	struct SERVICE_DESCRIPTIONA {
237 		LPSTR lpDescription;
238 	}
239 	alias SERVICE_DESCRIPTIONA* LPSERVICE_DESCRIPTIONA;
240 
241 	struct SERVICE_DESCRIPTIONW {
242 		LPWSTR lpDescription;
243 	}
244 	alias SERVICE_DESCRIPTIONW* LPSERVICE_DESCRIPTIONW;
245 
246 	enum SC_ACTION_TYPE {
247 		SC_ACTION_NONE,
248 		SC_ACTION_RESTART,
249 		SC_ACTION_REBOOT,
250 		SC_ACTION_RUN_COMMAND
251 	}
252 
253 	struct SC_ACTION {
254 		SC_ACTION_TYPE Type;
255 		DWORD          Delay;
256 	}
257 	alias SC_ACTION* LPSC_ACTION;
258 
259 	struct SERVICE_FAILURE_ACTIONSA {
260 		DWORD      dwResetPeriod;
261 		LPSTR      lpRebootMsg;
262 		LPSTR      lpCommand;
263 		DWORD      cActions;
264 		SC_ACTION* lpsaActions;
265 	}
266 	alias SERVICE_FAILURE_ACTIONSA* LPSERVICE_FAILURE_ACTIONSA;
267 
268 	struct SERVICE_FAILURE_ACTIONSW {
269 		DWORD      dwResetPeriod;
270 		LPWSTR     lpRebootMsg;
271 		LPWSTR     lpCommand;
272 		DWORD      cActions;
273 		SC_ACTION* lpsaActions;
274 	}
275 	alias SERVICE_FAILURE_ACTIONSW* LPSERVICE_FAILURE_ACTIONSW;
276 }
277 
278 extern (Windows) {
279 	BOOL ChangeServiceConfigA(SC_HANDLE, DWORD, DWORD, DWORD, LPCSTR,
280 	  LPCSTR, LPDWORD, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
281 	BOOL ChangeServiceConfigW(SC_HANDLE, DWORD, DWORD, DWORD, LPCWSTR,
282 	  LPCWSTR, LPDWORD, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR);
283 	BOOL CloseServiceHandle(SC_HANDLE);
284 	BOOL ControlService(SC_HANDLE, DWORD, LPSERVICE_STATUS);
285 	SC_HANDLE CreateServiceA(SC_HANDLE, LPCSTR, LPCSTR, DWORD, DWORD,
286 	  DWORD, DWORD, LPCSTR, LPCSTR, PDWORD, LPCSTR, LPCSTR, LPCSTR);
287 	SC_HANDLE CreateServiceW(SC_HANDLE, LPCWSTR, LPCWSTR, DWORD, DWORD,
288 	  DWORD, DWORD, LPCWSTR, LPCWSTR, PDWORD, LPCWSTR, LPCWSTR, LPCWSTR);
289 	BOOL DeleteService(SC_HANDLE);
290 	BOOL EnumDependentServicesA(SC_HANDLE, DWORD, LPENUM_SERVICE_STATUSA,
291 	  DWORD, PDWORD, PDWORD);
292 	BOOL EnumDependentServicesW(SC_HANDLE, DWORD, LPENUM_SERVICE_STATUSW,
293 	  DWORD, PDWORD, PDWORD);
294 	BOOL EnumServicesStatusA(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUSA,
295 	  DWORD, PDWORD, PDWORD, PDWORD);
296 	BOOL EnumServicesStatusW(SC_HANDLE, DWORD, DWORD, LPENUM_SERVICE_STATUSW,
297 	  DWORD, PDWORD, PDWORD, PDWORD);
298 	BOOL GetServiceDisplayNameA(SC_HANDLE, LPCSTR, LPSTR, PDWORD);
299 	BOOL GetServiceDisplayNameW(SC_HANDLE, LPCWSTR, LPWSTR, PDWORD);
300 	BOOL GetServiceKeyNameA(SC_HANDLE, LPCSTR, LPSTR, PDWORD);
301 	BOOL GetServiceKeyNameW(SC_HANDLE, LPCWSTR, LPWSTR, PDWORD);
302 	SC_LOCK LockServiceDatabase(SC_HANDLE);
303 	BOOL NotifyBootConfigStatus(BOOL);
304 	SC_HANDLE OpenSCManagerA(LPCSTR, LPCSTR, DWORD);
305 	SC_HANDLE OpenSCManagerW(LPCWSTR, LPCWSTR, DWORD);
306 	SC_HANDLE OpenServiceA(SC_HANDLE, LPCSTR, DWORD);
307 	SC_HANDLE OpenServiceW(SC_HANDLE, LPCWSTR, DWORD);
308 	BOOL QueryServiceConfigA(SC_HANDLE, LPQUERY_SERVICE_CONFIGA, DWORD,
309 	  PDWORD);
310 	BOOL QueryServiceConfigW(SC_HANDLE, LPQUERY_SERVICE_CONFIGW, DWORD,
311 	  PDWORD);
312 	BOOL QueryServiceLockStatusA(SC_HANDLE, LPQUERY_SERVICE_LOCK_STATUSA,
313 	  DWORD, PDWORD);
314 	BOOL QueryServiceLockStatusW(SC_HANDLE, LPQUERY_SERVICE_LOCK_STATUSW,
315 	  DWORD, PDWORD);
316 	BOOL QueryServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION,
317 	  PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
318 	BOOL QueryServiceStatus(SC_HANDLE, LPSERVICE_STATUS);
319 	SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerA(LPCSTR,
320 	  LPHANDLER_FUNCTION);
321 	SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerW(LPCWSTR,
322 	  LPHANDLER_FUNCTION);
323 	BOOL SetServiceObjectSecurity(SC_HANDLE, SECURITY_INFORMATION,
324 	  PSECURITY_DESCRIPTOR);
325 	BOOL SetServiceStatus(SERVICE_STATUS_HANDLE, LPSERVICE_STATUS);
326 	BOOL StartServiceA(SC_HANDLE, DWORD, LPCSTR*);
327 	BOOL StartServiceW(SC_HANDLE, DWORD, LPCWSTR*);
328 	BOOL StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA);
329 	BOOL StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW);
330 	BOOL UnlockServiceDatabase(SC_LOCK);
331 
332 	static if (_WIN32_WINNT >= 0x500) {
333 		BOOL EnumServicesStatusExA(SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPBYTE,
334 		  DWORD, LPDWORD, LPDWORD, LPDWORD, LPCSTR);
335 		BOOL EnumServicesStatusExW(SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPBYTE,
336 		  DWORD, LPDWORD, LPDWORD, LPDWORD, LPCWSTR);
337 		BOOL QueryServiceConfig2A(SC_HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
338 		BOOL QueryServiceConfig2W(SC_HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);
339 		BOOL QueryServiceStatusEx(SC_HANDLE, SC_STATUS_TYPE, LPBYTE, DWORD,
340 		  LPDWORD);
341 		SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExA(LPCSTR,
342 		  LPHANDLER_FUNCTION_EX, LPVOID);
343 		SERVICE_STATUS_HANDLE RegisterServiceCtrlHandlerExW(LPCWSTR,
344 		  LPHANDLER_FUNCTION_EX, LPVOID);
345 	}
346 
347 	static if (_WIN32_WINNT >= 0x501) {
348 		BOOL ChangeServiceConfig2A(SC_HANDLE, DWORD, LPVOID);
349 		BOOL ChangeServiceConfig2W(SC_HANDLE, DWORD, LPVOID);
350 	}
351 }
352 
353 version (Unicode) {
354 	alias ENUM_SERVICE_STATUSW ENUM_SERVICE_STATUS;
355 	alias QUERY_SERVICE_CONFIGW QUERY_SERVICE_CONFIG;
356 	alias QUERY_SERVICE_LOCK_STATUSW QUERY_SERVICE_LOCK_STATUS;
357 	alias LPSERVICE_MAIN_FUNCTIONW LPSERVICE_MAIN_FUNCTION;
358 	alias SERVICE_TABLE_ENTRYW SERVICE_TABLE_ENTRY;
359 	alias ChangeServiceConfigW ChangeServiceConfig;
360 	alias CreateServiceW CreateService;
361 	alias EnumDependentServicesW EnumDependentServices;
362 	alias EnumServicesStatusW EnumServicesStatus;
363 	alias GetServiceDisplayNameW GetServiceDisplayName;
364 	alias GetServiceKeyNameW GetServiceKeyName;
365 	alias OpenSCManagerW OpenSCManager;
366 	alias OpenServiceW OpenService;
367 	alias QueryServiceConfigW QueryServiceConfig;
368 	alias QueryServiceLockStatusW QueryServiceLockStatus;
369 	alias RegisterServiceCtrlHandlerW RegisterServiceCtrlHandler;
370 	alias StartServiceW StartService;
371 	alias StartServiceCtrlDispatcherW StartServiceCtrlDispatcher;
372 
373 	static if (_WIN32_WINNT >= 0x500) {
374 		alias ENUM_SERVICE_STATUS_PROCESSW ENUM_SERVICE_STATUS_PROCESS;
375 		alias SERVICE_DESCRIPTIONW SERVICE_DESCRIPTION;
376 		alias SERVICE_FAILURE_ACTIONSW SERVICE_FAILURE_ACTIONS;
377 		alias EnumServicesStatusExW EnumServicesStatusEx;
378 		alias QueryServiceConfig2W QueryServiceConfig2;
379 		alias RegisterServiceCtrlHandlerExW RegisterServiceCtrlHandlerEx;
380 	}
381 
382 	static if (_WIN32_WINNT >= 0x501) {
383 		alias ChangeServiceConfig2W ChangeServiceConfig2;
384 	}
385 
386 } else {
387 	alias ENUM_SERVICE_STATUSA ENUM_SERVICE_STATUS;
388 	alias QUERY_SERVICE_CONFIGA QUERY_SERVICE_CONFIG;
389 	alias QUERY_SERVICE_LOCK_STATUSA QUERY_SERVICE_LOCK_STATUS;
390 	alias LPSERVICE_MAIN_FUNCTIONA LPSERVICE_MAIN_FUNCTION;
391 	alias SERVICE_TABLE_ENTRYA SERVICE_TABLE_ENTRY;
392 	alias ChangeServiceConfigA ChangeServiceConfig;
393 	alias CreateServiceA CreateService;
394 	alias EnumDependentServicesA EnumDependentServices;
395 	alias EnumServicesStatusA EnumServicesStatus;
396 	alias GetServiceDisplayNameA GetServiceDisplayName;
397 	alias GetServiceKeyNameA GetServiceKeyName;
398 	alias OpenSCManagerA OpenSCManager;
399 	alias OpenServiceA OpenService;
400 	alias QueryServiceConfigA QueryServiceConfig;
401 	alias QueryServiceLockStatusA QueryServiceLockStatus;
402 	alias RegisterServiceCtrlHandlerA RegisterServiceCtrlHandler;
403 	alias StartServiceA StartService;
404 	alias StartServiceCtrlDispatcherA StartServiceCtrlDispatcher;
405 
406 	static if (_WIN32_WINNT >= 0x500) {
407 		alias ENUM_SERVICE_STATUS_PROCESSA ENUM_SERVICE_STATUS_PROCESS;
408 		alias SERVICE_DESCRIPTIONA SERVICE_DESCRIPTION;
409 		alias SERVICE_FAILURE_ACTIONSA SERVICE_FAILURE_ACTIONS;
410 		alias EnumServicesStatusExA EnumServicesStatusEx;
411 		alias QueryServiceConfig2A QueryServiceConfig2;
412 		alias RegisterServiceCtrlHandlerExA RegisterServiceCtrlHandlerEx;
413 	}
414 
415 	static if (_WIN32_WINNT >= 0x501) {
416 		alias ChangeServiceConfig2A ChangeServiceConfig2;
417 	}
418 
419 }
420 
421 alias ENUM_SERVICE_STATUS* LPENUM_SERVICE_STATUS;
422 alias QUERY_SERVICE_CONFIG* LPQUERY_SERVICE_CONFIG;
423 alias QUERY_SERVICE_LOCK_STATUS* LPQUERY_SERVICE_LOCK_STATUS;
424 alias SERVICE_TABLE_ENTRY* LPSERVICE_TABLE_ENTRY;
425 
426 static if (_WIN32_WINNT >= 0x500) {
427 	alias ENUM_SERVICE_STATUS_PROCESS* LPENUM_SERVICE_STATUS_PROCESS;
428 	alias SERVICE_DESCRIPTION* LPSERVICE_DESCRIPTION;
429 	alias SERVICE_FAILURE_ACTIONS* LPSERVICE_FAILURE_ACTIONS;
430 }