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>
15 #define SERVICE_ACCESS (SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE)
18 * This is an internal function not meant for use by the kmtests app,
19 * so we declare it here instead of kmtest.h
23 IN PCWSTR ServiceName
,
24 IN PCWSTR ServicePath
,
25 IN PCWSTR DisplayName OPTIONAL
,
27 OUT SC_HANDLE
*ServiceHandle
);
30 static SC_HANDLE ScmHandle
;
33 * @name KmtServiceInit
35 * Initialize service management routines (by opening the service control manager)
37 * @return Win32 error code
42 DWORD Error
= ERROR_SUCCESS
;
46 ScmHandle
= OpenSCManager(NULL
, NULL
, SC_MANAGER_CREATE_SERVICE
);
54 * @name KmtServiceCleanup
56 * Clean up resources used by service management routines.
59 * If TRUE, the function will never set ErrorLineAndFile, and always return ERROR_SUCCESS
61 * @return Win32 error code
67 DWORD Error
= ERROR_SUCCESS
;
69 if (ScmHandle
&& !CloseServiceHandle(ScmHandle
) && !IgnoreErrors
)
76 * @name KmtCreateService
78 * Create the specified driver service and return a handle to it
81 * Name of the service to create
83 * File name of the driver, relative to the current directory
85 * Service display name
86 * @param ServiceHandle
87 * Pointer to a variable to receive the handle to the service
89 * @return Win32 error code
93 IN PCWSTR ServiceName
,
94 IN PCWSTR ServicePath
,
95 IN PCWSTR DisplayName OPTIONAL
,
96 OUT SC_HANDLE
*ServiceHandle
)
98 return KmtpCreateService(ServiceName
,
101 SERVICE_KERNEL_DRIVER
,
106 * @name KmtGetServiceStateAsString
108 * @param ServiceState
109 * Service state as a number
111 * @return Service state as a string
115 KmtGetServiceStateAsString(
116 IN DWORD ServiceState
)
120 case SERVICE_STOPPED
:
122 case SERVICE_START_PENDING
:
123 return "START_PENDING";
124 case SERVICE_STOP_PENDING
:
125 return "STOP_PENDING";
126 case SERVICE_RUNNING
:
128 case SERVICE_CONTINUE_PENDING
:
129 return "CONTINUE_PENDING";
130 case SERVICE_PAUSE_PENDING
:
131 return "PAUSE_PENDING";
135 ok(FALSE
, "Unknown service state = %lu\n", ServiceState
);
141 * @name KmtEnsureServiceState
144 * Name of the service to check,
146 * @param ServiceHandle
147 * Handle to the service
148 * @param ExpectedServiceState
149 * State which the service should be in
151 * @return Win32 error code
155 KmtEnsureServiceState(
156 IN PCWSTR ServiceName OPTIONAL
,
157 IN SC_HANDLE ServiceHandle
,
158 IN DWORD ExpectedServiceState
)
160 DWORD Error
= ERROR_SUCCESS
;
161 SERVICE_STATUS ServiceStatus
;
162 DWORD StartTime
= GetTickCount();
163 DWORD Timeout
= 10 * 1000;
164 PCWSTR ServiceNameOut
= ServiceName
? ServiceName
: L
"(handle only, no name)";
166 assert(ServiceHandle
);
167 assert(ExpectedServiceState
);
169 if (!QueryServiceStatus(ServiceHandle
, &ServiceStatus
))
170 error_goto(Error
, cleanup
);
172 while (ServiceStatus
.dwCurrentState
!= ExpectedServiceState
)
174 // NB: ServiceStatus.dwWaitHint and ServiceStatus.dwCheckPoint logic could be added, if need be.
178 if (!QueryServiceStatus(ServiceHandle
, &ServiceStatus
))
179 error_goto(Error
, cleanup
);
181 if (GetTickCount() - StartTime
>= Timeout
)
185 if (ServiceStatus
.dwCurrentState
!= ExpectedServiceState
)
187 ok(FALSE
, "Service = %ls, state = %lu %s (!= %lu %s), waitHint = %lu, checkPoint = %lu\n",
189 ServiceStatus
.dwCurrentState
, KmtGetServiceStateAsString(ServiceStatus
.dwCurrentState
),
190 ExpectedServiceState
, KmtGetServiceStateAsString(ExpectedServiceState
),
191 ServiceStatus
.dwWaitHint
, ServiceStatus
.dwCheckPoint
);
195 trace("Service = %ls, state = %lu %s\n",
197 ExpectedServiceState
, KmtGetServiceStateAsString(ExpectedServiceState
));
204 * @name KmtStartService
206 * Start the specified driver service by handle or name (and return a handle to it)
209 * If *ServiceHandle is NULL, name of the service to start
210 * @param ServiceHandle
211 * Pointer to a variable containing the service handle,
212 * or NULL (in which case it will be filled with a handle to the service)
214 * @return Win32 error code
218 IN PCWSTR ServiceName OPTIONAL
,
219 IN OUT SC_HANDLE
*ServiceHandle
)
221 DWORD Error
= ERROR_SUCCESS
;
223 assert(ServiceHandle
);
224 assert(ServiceName
|| *ServiceHandle
);
227 *ServiceHandle
= OpenService(ScmHandle
, ServiceName
, SERVICE_ACCESS
);
230 error_goto(Error
, cleanup
);
232 if (!StartService(*ServiceHandle
, 0, NULL
))
233 error_goto(Error
, cleanup
);
235 Error
= KmtEnsureServiceState(ServiceName
, *ServiceHandle
, SERVICE_RUNNING
);
244 * @name KmtCreateAndStartService
246 * Create and start the specified driver service and return a handle to it
249 * Name of the service to create
251 * File name of the driver, relative to the current directory
253 * Service display name
254 * @param ServiceHandle
255 * Pointer to a variable to receive the handle to the service
256 * @param RestartIfRunning
257 * TRUE to stop and restart the service if it is already running
259 * @return Win32 error code
262 KmtCreateAndStartService(
263 IN PCWSTR ServiceName
,
264 IN PCWSTR ServicePath
,
265 IN PCWSTR DisplayName OPTIONAL
,
266 OUT SC_HANDLE
*ServiceHandle
,
267 IN BOOLEAN RestartIfRunning
)
269 DWORD Error
= ERROR_SUCCESS
;
271 assert(ServiceHandle
);
273 Error
= KmtCreateService(ServiceName
, ServicePath
, DisplayName
, ServiceHandle
);
275 if (Error
&& Error
!= ERROR_SERVICE_EXISTS
)
278 Error
= KmtStartService(ServiceName
, ServiceHandle
);
280 if (Error
!= ERROR_SERVICE_ALREADY_RUNNING
)
283 Error
= ERROR_SUCCESS
;
285 if (!RestartIfRunning
)
288 Error
= KmtStopService(ServiceName
, ServiceHandle
);
292 Error
= KmtStartService(ServiceName
, ServiceHandle
);
297 assert(Error
|| *ServiceHandle
);
302 * @name KmtStopService
304 * Stop the specified driver service by handle or name (and return a handle to it)
307 * If *ServiceHandle is NULL, name of the service to stop
308 * @param ServiceHandle
309 * Pointer to a variable containing the service handle,
310 * or NULL (in which case it will be filled with a handle to the service)
312 * @return Win32 error code
316 IN PCWSTR ServiceName OPTIONAL
,
317 IN OUT SC_HANDLE
*ServiceHandle
)
319 DWORD Error
= ERROR_SUCCESS
;
320 SERVICE_STATUS ServiceStatus
;
322 assert(ServiceHandle
);
323 assert(ServiceName
|| *ServiceHandle
);
326 *ServiceHandle
= OpenService(ScmHandle
, ServiceName
, SERVICE_ACCESS
);
329 error_goto(Error
, cleanup
);
331 if (!ControlService(*ServiceHandle
, SERVICE_CONTROL_STOP
, &ServiceStatus
))
332 error_goto(Error
, cleanup
);
334 Error
= KmtEnsureServiceState(ServiceName
, *ServiceHandle
, SERVICE_STOPPED
);
343 * @name KmtDeleteService
345 * Delete the specified driver service by handle or name (and return a handle to it)
348 * If *ServiceHandle is NULL, name of the service to delete
349 * @param ServiceHandle
350 * Pointer to a variable containing the service handle.
351 * Will be set to NULL on success
353 * @return Win32 error code
357 IN PCWSTR ServiceName OPTIONAL
,
358 IN OUT SC_HANDLE
*ServiceHandle
)
360 DWORD Error
= ERROR_SUCCESS
;
362 assert(ServiceHandle
);
363 assert(ServiceName
|| *ServiceHandle
);
366 *ServiceHandle
= OpenService(ScmHandle
, ServiceName
, SERVICE_ACCESS
);
369 error_goto(Error
, cleanup
);
371 if (!DeleteService(*ServiceHandle
))
372 error_goto(Error
, cleanup
);
375 CloseServiceHandle(*ServiceHandle
);
382 * @name KmtCloseService
384 * Close the specified driver service handle
386 * @param ServiceHandle
387 * Pointer to a variable containing the service handle.
388 * Will be set to NULL on success
390 * @return Win32 error code
392 DWORD
KmtCloseService(
393 IN OUT SC_HANDLE
*ServiceHandle
)
395 DWORD Error
= ERROR_SUCCESS
;
397 assert(ServiceHandle
);
399 if (*ServiceHandle
&& !CloseServiceHandle(*ServiceHandle
))
400 error_goto(Error
, cleanup
);
402 *ServiceHandle
= NULL
;
410 * Private function, not meant for use in kmtests
411 * See KmtCreateService & KmtFltCreateService
415 IN PCWSTR ServiceName
,
416 IN PCWSTR ServicePath
,
417 IN PCWSTR DisplayName OPTIONAL
,
418 IN DWORD ServiceType
,
419 OUT SC_HANDLE
*ServiceHandle
)
421 DWORD Error
= ERROR_SUCCESS
;
422 WCHAR DriverPath
[MAX_PATH
];
423 HRESULT result
= S_OK
;
425 assert(ServiceHandle
);
426 assert(ServiceName
&& ServicePath
);
428 if (!GetModuleFileName(NULL
, DriverPath
, sizeof DriverPath
/ sizeof DriverPath
[0]))
429 error_goto(Error
, cleanup
);
431 assert(wcsrchr(DriverPath
, L
'\\') != NULL
);
432 wcsrchr(DriverPath
, L
'\\')[1] = L
'\0';
434 result
= StringCbCat(DriverPath
, sizeof DriverPath
, ServicePath
);
436 error_value_goto(Error
, result
, cleanup
);
438 if (GetFileAttributes(DriverPath
) == INVALID_FILE_ATTRIBUTES
)
439 error_goto(Error
, cleanup
);
441 *ServiceHandle
= CreateService(ScmHandle
, ServiceName
, DisplayName
,
442 SERVICE_ACCESS
, ServiceType
, SERVICE_DEMAND_START
,
443 SERVICE_ERROR_NORMAL
, DriverPath
, NULL
, NULL
, NULL
, NULL
, NULL
);
446 error_goto(Error
, cleanup
);