ReactOS  0.4.13-dev-52-g0efcfec
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  */
21 DWORD
24  IN PCWSTR ServicePath,
25  IN PCWSTR DisplayName OPTIONAL,
26  IN DWORD ServiceType,
27  OUT SC_HANDLE *ServiceHandle);
28 
29 
30 static SC_HANDLE ScmHandle;
31 
39 DWORD
41 {
43 
44  assert(!ScmHandle);
45 
47  if (!ScmHandle)
48  error(Error);
49 
50  return Error;
51 }
52 
63 DWORD
65  BOOLEAN IgnoreErrors)
66 {
68 
69  if (ScmHandle && !CloseServiceHandle(ScmHandle) && !IgnoreErrors)
70  error(Error);
71 
72  return Error;
73 }
74 
91 DWORD
94  IN PCWSTR ServicePath,
95  IN PCWSTR DisplayName OPTIONAL,
96  OUT SC_HANDLE *ServiceHandle)
97 {
99  ServicePath,
100  DisplayName,
102  ServiceHandle);
103 }
104 
113 static
114 PCSTR
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 
153 static
154 DWORD
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 
199 cleanup:
200  return Error;
201 }
202 
216 DWORD
219  IN OUT SC_HANDLE *ServiceHandle)
220 {
222 
223  assert(ServiceHandle);
224  assert(ServiceName || *ServiceHandle);
225 
226  if (!*ServiceHandle)
227  *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
228 
229  if (!*ServiceHandle)
231 
232  if (!StartService(*ServiceHandle, 0, NULL))
234 
236  if (Error)
237  goto cleanup;
238 
239 cleanup:
240  return Error;
241 }
242 
261 DWORD
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 
275  if (Error && Error != ERROR_SERVICE_EXISTS)
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 
296 cleanup:
297  assert(Error || *ServiceHandle);
298  return Error;
299 }
300 
314 DWORD
317  IN OUT SC_HANDLE *ServiceHandle)
318 {
321 
322  assert(ServiceHandle);
323  assert(ServiceName || *ServiceHandle);
324 
325  if (!*ServiceHandle)
326  *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
327 
328  if (!*ServiceHandle)
330 
331  if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus))
333 
335  if (Error)
336  goto cleanup;
337 
338 cleanup:
339  return Error;
340 }
341 
355 DWORD
358  IN OUT SC_HANDLE *ServiceHandle)
359 {
361 
362  assert(ServiceHandle);
363  assert(ServiceName || *ServiceHandle);
364 
365  if (!*ServiceHandle)
366  *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
367 
368  if (!*ServiceHandle)
370 
371  if (!DeleteService(*ServiceHandle))
373 
374  if (*ServiceHandle)
375  CloseServiceHandle(*ServiceHandle);
376 
377 cleanup:
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 
404 cleanup:
405  return Error;
406 }
407 
408 
409 /*
410  * Private function, not meant for use in kmtests
411  * See KmtCreateService & KmtFltCreateService
412  */
413 DWORD
416  IN PCWSTR ServicePath,
417  IN PCWSTR DisplayName OPTIONAL,
418  IN DWORD ServiceType,
419  OUT SC_HANDLE *ServiceHandle)
420 {
422  WCHAR DriverPath[MAX_PATH];
423  HRESULT result = S_OK;
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 = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
435  if (FAILED(result))
437 
438  if (GetFileAttributes(DriverPath) == INVALID_FILE_ATTRIBUTES)
440 
441  *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
442  SERVICE_ACCESS, ServiceType, SERVICE_DEMAND_START,
443  SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL, NULL);
444 
445  if (!*ServiceHandle)
447 
448 cleanup:
449  return Error;
450 }
#define StartService
Definition: winsvc.h:585
#define SERVICE_ACCESS
Definition: service.c:15
DWORD KmtpCreateService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, IN DWORD ServiceType, OUT SC_HANDLE *ServiceHandle)
Definition: service.c:414
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define trace(...)
Definition: kmt_test.h:217
#define IN
Definition: typedefs.h:38
#define SERVICE_ERROR_NORMAL
Definition: cmtypes.h:980
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
#define ERROR_SUCCESS
Definition: deptool.c:10
DWORD KmtDeleteService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:356
DWORD dwCurrentState
Definition: winsvc.h:100
#define error(str)
Definition: mkdosfs.c:1605
#define SERVICE_PAUSE_PENDING
Definition: winsvc.h:26
#define error_goto(Error, label)
Definition: kmtest.h:21
#define SERVICE_PAUSED
Definition: winsvc.h:27
static SERVICE_STATUS ServiceStatus
Definition: dcomlaunch.c:27
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
#define assert(x)
Definition: debug.h:53
#define SERVICE_START_PENDING
Definition: winsvc.h:22
DWORD KmtStartService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:217
BOOL WINAPI DeleteService(SC_HANDLE hService)
Definition: scm.c:916
#define CreateService
Definition: winsvc.h:569
static LARGE_INTEGER StartTime
Definition: sys_arch.c:18
#define OpenService
Definition: winsvc.h:576
DWORD dwCheckPoint
Definition: winsvc.h:104
#define SERVICE_STOPPED
Definition: winsvc.h:21
#define SERVICE_RUNNING
Definition: winsvc.h:24
#define ok(value,...)
BOOL WINAPI CloseServiceHandle(SC_HANDLE hSCObject)
Definition: scm.c:577
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
#define SC_MANAGER_CREATE_SERVICE
Definition: winsvc.h:15
#define OpenSCManager
Definition: winsvc.h:575
#define StringCbCat
Definition: strsafe.h:334
LPTSTR ServiceName
Definition: ServiceMain.c:15
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
DWORD dwWaitHint
Definition: winsvc.h:105
DWORD KmtCloseService(IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:392
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL Error
Definition: chkdsk.c:66
BOOL WINAPI QueryServiceStatus(SC_HANDLE hService, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:2788
#define GetModuleFileName
Definition: winbase.h:3645
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define ERROR_SERVICE_EXISTS
Definition: winerror.h:624
static const WCHAR L[]
Definition: oid.c:1250
DWORD KmtStopService(IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle)
Definition: service.c:315
DWORD KmtCreateAndStartService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle, IN BOOLEAN RestartIfRunning)
Definition: service.c:262
#define GetFileAttributes
Definition: winbase.h:3629
static DWORD KmtEnsureServiceState(IN PCWSTR ServiceName OPTIONAL, IN SC_HANDLE ServiceHandle, IN DWORD ExpectedServiceState)
Definition: service.c:155
#define S_OK
Definition: intsafe.h:59
#define SERVICE_CONTINUE_PENDING
Definition: winsvc.h:25
static ULONG Timeout
Definition: ping.c:61
DWORD KmtCreateService(IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle)
Definition: service.c:92
DWORD KmtServiceInit(VOID)
Definition: service.c:40
BOOL WINAPI ControlService(SC_HANDLE hService, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus)
Definition: scm.c:619
#define error_value_goto(Error, value, label)
Definition: kmtest.h:22
#define OUT
Definition: typedefs.h:39
char * cleanup(char *str)
Definition: wpickclick.c:99
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
const char * PCSTR
Definition: typedefs.h:51
static PCSTR KmtGetServiceStateAsString(IN DWORD ServiceState)
Definition: service.c:115
DWORD KmtServiceCleanup(BOOLEAN IgnoreErrors)
Definition: service.c:64
#define SERVICE_DEMAND_START
Definition: cmtypes.h:976
#define ERROR_SERVICE_ALREADY_RUNNING
Definition: winerror.h:607
GLuint64EXT * result
Definition: glext.h:11304
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
static SC_HANDLE ScmHandle
Definition: service.c:30
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:951
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68