ReactOS 0.4.15-dev-7958-gcd0bb1a
service.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Kernel-Mode Test Suite loader service control functions
5 * COPYRIGHT: Copyright 2011-2018 Thomas Faber <thomas.faber@reactos.org>
6 * Copyright 2017 Ged Murphy <gedmurphy@reactos.org>
7 * Copyright 2018 Serge Gautherie <reactos-git_serge_171003@gautherie.fr>
8 */
9
10#include <kmt_test.h>
11#include "kmtest.h"
12
13#include <assert.h>
14
15#define SERVICE_ACCESS (SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE)
16
17/*
18 * This is an internal function not meant for use by the kmtests app,
19 * so we declare it here instead of kmtest.h
20 */
24 IN PCWSTR ServicePath,
25 IN PCWSTR DisplayName OPTIONAL,
26 IN DWORD ServiceType,
27 OUT SC_HANDLE *ServiceHandle);
28
29
30static SC_HANDLE ScmHandle;
31
41{
43
45
47 if (!ScmHandle)
48 error(Error);
49
50 return Error;
51}
52
65 BOOLEAN IgnoreErrors)
66{
68
69 if (ScmHandle && !CloseServiceHandle(ScmHandle) && !IgnoreErrors)
70 error(Error);
71
72 return Error;
73}
74
94 IN PCWSTR ServicePath,
95 IN PCWSTR DisplayName OPTIONAL,
96 OUT SC_HANDLE *ServiceHandle)
97{
99 ServicePath,
100 DisplayName,
102 ServiceHandle);
103}
104
113static
114PCSTR
116 IN DWORD ServiceState)
117{
118 switch(ServiceState)
119 {
120 case SERVICE_STOPPED:
121 return "STOPPED";
123 return "START_PENDING";
125 return "STOP_PENDING";
126 case SERVICE_RUNNING:
127 return "RUNNING";
129 return "CONTINUE_PENDING";
131 return "PAUSE_PENDING";
132 case SERVICE_PAUSED:
133 return "PAUSED";
134 default:
135 ok(FALSE, "Unknown service state = %lu\n", ServiceState);
136 return "(Unknown)";
137 }
138}
139
153static
154DWORD
157 IN SC_HANDLE ServiceHandle,
158 IN DWORD ExpectedServiceState)
159{
163 DWORD Timeout = 10 * 1000;
164 PCWSTR ServiceNameOut = ServiceName ? ServiceName : L"(handle only, no name)";
165
166 assert(ServiceHandle);
167 assert(ExpectedServiceState);
168
169 if (!QueryServiceStatus(ServiceHandle, &ServiceStatus))
171
172 while (ServiceStatus.dwCurrentState != ExpectedServiceState)
173 {
174 // NB: ServiceStatus.dwWaitHint and ServiceStatus.dwCheckPoint logic could be added, if need be.
175
176 Sleep(1 * 1000);
177
178 if (!QueryServiceStatus(ServiceHandle, &ServiceStatus))
180
181 if (GetTickCount() - StartTime >= Timeout)
182 break;
183 }
184
185 if (ServiceStatus.dwCurrentState != ExpectedServiceState)
186 {
187 ok(FALSE, "Service = %ls, state = %lu %s (!= %lu %s), waitHint = %lu, checkPoint = %lu\n",
188 ServiceNameOut,
190 ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState),
192 goto cleanup;
193 }
194
195 trace("Service = %ls, state = %lu %s\n",
196 ServiceNameOut,
197 ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState));
198
199cleanup:
200 return Error;
201}
202
216DWORD
219 IN OUT SC_HANDLE *ServiceHandle)
220{
222
223 assert(ServiceHandle);
224 assert(ServiceName || *ServiceHandle);
225
226 if (!*ServiceHandle)
228
229 if (!*ServiceHandle)
231
232 if (!StartService(*ServiceHandle, 0, NULL))
234
236 if (Error)
237 goto cleanup;
238
239cleanup:
240 return Error;
241}
242
261DWORD
264 IN PCWSTR ServicePath,
265 IN PCWSTR DisplayName OPTIONAL,
266 OUT SC_HANDLE *ServiceHandle,
267 IN BOOLEAN RestartIfRunning)
268{
270
271 assert(ServiceHandle);
272
273 Error = KmtCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle);
274
276 goto cleanup;
277
278 Error = KmtStartService(ServiceName, ServiceHandle);
279
281 goto cleanup;
282
284
285 if (!RestartIfRunning)
286 goto cleanup;
287
288 Error = KmtStopService(ServiceName, ServiceHandle);
289 if (Error)
290 goto cleanup;
291
292 Error = KmtStartService(ServiceName, ServiceHandle);
293 if (Error)
294 goto cleanup;
295
296cleanup:
297 assert(Error || *ServiceHandle);
298 return Error;
299}
300
314DWORD
317 IN OUT SC_HANDLE *ServiceHandle)
318{
321
322 assert(ServiceHandle);
323 assert(ServiceName || *ServiceHandle);
324
325 if (!*ServiceHandle)
327
328 if (!*ServiceHandle)
330
331 if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus))
333
335 if (Error)
336 goto cleanup;
337
338cleanup:
339 return Error;
340}
341
355DWORD
358 IN OUT SC_HANDLE *ServiceHandle)
359{
361
362 assert(ServiceHandle);
363 assert(ServiceName || *ServiceHandle);
364
365 if (!*ServiceHandle)
367
368 if (!*ServiceHandle)
370
371 if (!DeleteService(*ServiceHandle))
373
374 if (*ServiceHandle)
375 CloseServiceHandle(*ServiceHandle);
376
377cleanup:
378 return Error;
379}
380
393 IN OUT SC_HANDLE *ServiceHandle)
394{
396
397 assert(ServiceHandle);
398
399 if (*ServiceHandle && !CloseServiceHandle(*ServiceHandle))
401
402 *ServiceHandle = NULL;
403
404cleanup:
405 return Error;
406}
407
408
409/*
410 * Private function, not meant for use in kmtests
411 * See KmtCreateService & KmtFltCreateService
412 */
413DWORD
416 IN PCWSTR ServicePath,
417 IN PCWSTR DisplayName OPTIONAL,
418 IN DWORD ServiceType,
419 OUT SC_HANDLE *ServiceHandle)
420{
422 WCHAR DriverPath[MAX_PATH];
424
425 assert(ServiceHandle);
426 assert(ServiceName && ServicePath);
427
428 if (!GetModuleFileName(NULL, DriverPath, sizeof DriverPath / sizeof DriverPath[0]))
430
431 assert(wcsrchr(DriverPath, L'\\') != NULL);
432 wcsrchr(DriverPath, L'\\')[1] = L'\0';
433
434 result = StringCbCatW(DriverPath, sizeof(DriverPath), ServicePath);
435 if (FAILED(result))
437
440
441 *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
443 SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL, NULL);
444
445 if (!*ServiceHandle)
447
448cleanup:
449 return Error;
450}
unsigned char BOOLEAN
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
static WCHAR ServiceName[]
Definition: browser.c:19
static SERVICE_STATUS ServiceStatus
Definition: browser.c:22
BOOL Error
Definition: chkdsk.c:66
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define wcsrchr
Definition: compat.h:16
#define MAX_PATH
Definition: compat.h:34
static void cleanup(void)
Definition: main.c:1335
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
#define assert(x)
Definition: debug.h:53
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint64EXT * result
Definition: glext.h:11304
#define S_OK
Definition: intsafe.h:52
#define FAILED(hr)
Definition: intsafe.h:51
#define error_value_goto(Error, value, label)
Definition: kmtest.h:22
#define error_goto(Error, label)
Definition: kmtest.h:21
#define error(str)
Definition: mkdosfs.c:1605
DWORD KmtServiceCleanup(BOOLEAN IgnoreErrors)
Definition: service.c:64
DWORD KmtServiceInit(VOID)
Definition: service.c:40
DWORD KmtCloseService(IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:392
static PCSTR KmtGetServiceStateAsString(IN DWORD ServiceState)
Definition: service.c:115
static SC_HANDLE ScmHandle
Definition: service.c:30
DWORD KmtpCreateService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, IN DWORD ServiceType, OUT SC_HANDLE *ServiceHandle)
Definition: service.c:414
DWORD KmtDeleteService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:356
static DWORD KmtEnsureServiceState(IN PCWSTR ServiceName OPTIONAL, IN SC_HANDLE ServiceHandle, IN DWORD ExpectedServiceState)
Definition: service.c:155
DWORD KmtCreateService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle)
Definition: service.c:92
#define SERVICE_ACCESS
Definition: service.c:15
DWORD KmtStopService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:315
DWORD KmtStartService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:217
DWORD KmtCreateAndStartService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle, IN BOOLEAN RestartIfRunning)
Definition: service.c:262
#define L(x)
Definition: ntvdm.h:50
static ULONG Timeout
Definition: ping.c:61
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2845
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:921
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:622
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:580
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:342
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD dwCurrentState
Definition: winsvc.h:100
DWORD dwCheckPoint
Definition: winsvc.h:104
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static LARGE_INTEGER StartTime
Definition: sys_arch.c:13
const uint16_t * PCWSTR
Definition: typedefs.h:57
const char * PCSTR
Definition: typedefs.h:52
#define IN
Definition: typedefs.h:39
#define OUT
Definition: typedefs.h:40
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define GetFileAttributes
Definition: winbase.h:3815
#define GetModuleFileName
Definition: winbase.h:3831
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:607
#define ERROR_SERVICE_EXISTS
Definition: winerror.h:624
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define OpenSCManager
Definition: winsvc.h:575
#define CreateService
Definition: winsvc.h:569
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define SERVICE_PAUSED
Definition: winsvc.h:27
#define StartService
Definition: winsvc.h:585
#define SERVICE_START_PENDING
Definition: winsvc.h:22
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
#define OpenService
Definition: winsvc.h:576
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
#define SERVICE_DEMAND_START
Definition: cmtypes.h:978
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:982
__wchar_t WCHAR
Definition: xmlstorage.h:180