[uxtheme]
[reactos.git] / rostests / kmtests / kmtest / service.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Loader service control functions
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
6 */
7
8 #include <kmt_test.h>
9 #include "kmtest.h"
10
11 #include <assert.h>
12
13 #define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
14
15 static SC_HANDLE ScmHandle;
16
17 /**
18 * @name KmtServiceInit
19 *
20 * Initialize service management routines (by opening the service control manager)
21 *
22 * @return Win32 error code
23 */
24 DWORD
25 KmtServiceInit(VOID)
26 {
27 DWORD Error = ERROR_SUCCESS;
28
29 assert(!ScmHandle);
30
31 ScmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
32 if (!ScmHandle)
33 error(Error);
34
35 return Error;
36 }
37
38 /**
39 * @name KmtServiceCleanup
40 *
41 * Clean up resources used by service management routines.
42 *
43 * @param IgnoreErrors
44 * If TRUE, the function will never set ErrorLineAndFile, and always return ERROR_SUCCESS
45 *
46 * @return Win32 error code
47 */
48 DWORD
49 KmtServiceCleanup(
50 BOOLEAN IgnoreErrors)
51 {
52 DWORD Error = ERROR_SUCCESS;
53
54 if (ScmHandle && !CloseServiceHandle(ScmHandle) && !IgnoreErrors)
55 error(Error);
56
57 return Error;
58 }
59
60 /**
61 * @name KmtCreateService
62 *
63 * Create the specified driver service and return a handle to it
64 *
65 * @param ServiceName
66 * Name of the service to create
67 * @param ServicePath
68 * File name of the driver, relative to the current directory
69 * @param DisplayName
70 * Service display name
71 * @param ServiceHandle
72 * Pointer to a variable to receive the handle to the service
73 *
74 * @return Win32 error code
75 */
76 DWORD
77 KmtCreateService(
78 IN PCWSTR ServiceName,
79 IN PCWSTR ServicePath,
80 IN PCWSTR DisplayName OPTIONAL,
81 OUT SC_HANDLE *ServiceHandle)
82 {
83 DWORD Error = ERROR_SUCCESS;
84 WCHAR DriverPath[MAX_PATH];
85 HRESULT result = S_OK;
86
87 assert(ServiceHandle);
88 assert(ServiceName && ServicePath);
89
90 if (!GetModuleFileName(NULL, DriverPath, sizeof DriverPath / sizeof DriverPath[0]))
91 error_goto(Error, cleanup);
92
93 assert(wcsrchr(DriverPath, L'\\') != NULL);
94 wcsrchr(DriverPath, L'\\')[1] = L'\0';
95
96 result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
97 if (FAILED(result))
98 error_value_goto(Error, result, cleanup);
99
100 if (GetFileAttributes(DriverPath) == INVALID_FILE_ATTRIBUTES)
101 error_goto(Error, cleanup);
102
103 *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
104 SERVICE_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
105 SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL, NULL);
106
107 if (!*ServiceHandle)
108 error_goto(Error, cleanup);
109
110 cleanup:
111 return Error;
112 }
113
114 /**
115 * @name KmtStartService
116 *
117 * Start the specified driver service by handle or name (and return a handle to it)
118 *
119 * @param ServiceName
120 * If *ServiceHandle is NULL, name of the service to start
121 * @param ServiceHandle
122 * Pointer to a variable containing the service handle,
123 * or NULL (in which case it will be filled with a handle to the service)
124 *
125 * @return Win32 error code
126 */
127 DWORD
128 KmtStartService(
129 IN PCWSTR ServiceName OPTIONAL,
130 IN OUT SC_HANDLE *ServiceHandle)
131 {
132 DWORD Error = ERROR_SUCCESS;
133
134 assert(ServiceHandle);
135 assert(ServiceName || *ServiceHandle);
136
137 if (!*ServiceHandle)
138 *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
139
140 if (!*ServiceHandle)
141 error_goto(Error, cleanup);
142
143 if (!StartService(*ServiceHandle, 0, NULL))
144 error_goto(Error, cleanup);
145
146 cleanup:
147 return Error;
148 }
149
150 /**
151 * @name KmtCreateAndStartService
152 *
153 * Create and start the specified driver service and return a handle to it
154 *
155 * @param ServiceName
156 * Name of the service to create
157 * @param ServicePath
158 * File name of the driver, relative to the current directory
159 * @param DisplayName
160 * Service display name
161 * @param ServiceHandle
162 * Pointer to a variable to receive the handle to the service
163 * @param RestartIfRunning
164 * TRUE to stop and restart the service if it is already running
165 *
166 * @return Win32 error code
167 */
168 DWORD
169 KmtCreateAndStartService(
170 IN PCWSTR ServiceName,
171 IN PCWSTR ServicePath,
172 IN PCWSTR DisplayName OPTIONAL,
173 OUT SC_HANDLE *ServiceHandle,
174 IN BOOLEAN RestartIfRunning)
175 {
176 DWORD Error = ERROR_SUCCESS;
177
178 assert(ServiceHandle);
179
180 Error = KmtCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle);
181
182 if (Error && Error != ERROR_SERVICE_EXISTS)
183 goto cleanup;
184
185 Error = KmtStartService(ServiceName, ServiceHandle);
186
187 if (Error != ERROR_SERVICE_ALREADY_RUNNING)
188 goto cleanup;
189
190 Error = ERROR_SUCCESS;
191
192 if (!RestartIfRunning)
193 goto cleanup;
194
195 Error = KmtStopService(ServiceName, ServiceHandle);
196 if (Error)
197 goto cleanup;
198
199 Error = KmtStartService(ServiceName, ServiceHandle);
200 if (Error)
201 goto cleanup;
202
203 cleanup:
204 assert(Error || *ServiceHandle);
205 return Error;
206 }
207
208 /**
209 * @name KmtStopService
210 *
211 * Stop the specified driver service by handle or name (and return a handle to it)
212 *
213 * @param ServiceName
214 * If *ServiceHandle is NULL, name of the service to stop
215 * @param ServiceHandle
216 * Pointer to a variable containing the service handle,
217 * or NULL (in which case it will be filled with a handle to the service)
218 *
219 * @return Win32 error code
220 */
221 DWORD
222 KmtStopService(
223 IN PCWSTR ServiceName OPTIONAL,
224 IN OUT SC_HANDLE *ServiceHandle)
225 {
226 DWORD Error = ERROR_SUCCESS;
227 SERVICE_STATUS ServiceStatus;
228
229 assert(ServiceHandle);
230 assert(ServiceName || *ServiceHandle);
231
232 if (!*ServiceHandle)
233 *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
234
235 if (!*ServiceHandle)
236 error_goto(Error, cleanup);
237
238 if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus))
239 error_goto(Error, cleanup);
240
241 cleanup:
242 return Error;
243 }
244
245 /**
246 * @name KmtDeleteService
247 *
248 * Delete the specified driver service by handle or name (and return a handle to it)
249 *
250 * @param ServiceName
251 * If *ServiceHandle is NULL, name of the service to delete
252 * @param ServiceHandle
253 * Pointer to a variable containing the service handle.
254 * Will be set to NULL on success
255 *
256 * @return Win32 error code
257 */
258 DWORD
259 KmtDeleteService(
260 IN PCWSTR ServiceName OPTIONAL,
261 IN OUT SC_HANDLE *ServiceHandle)
262 {
263 DWORD Error = ERROR_SUCCESS;
264
265 assert(ServiceHandle);
266 assert(ServiceName || *ServiceHandle);
267
268 if (!*ServiceHandle)
269 *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
270
271 if (!*ServiceHandle)
272 error_goto(Error, cleanup);
273
274 if (!DeleteService(*ServiceHandle))
275 error_goto(Error, cleanup);
276
277 if (*ServiceHandle)
278 CloseServiceHandle(*ServiceHandle);
279
280 cleanup:
281 return Error;
282 }
283
284 /**
285 * @name KmtCloseService
286 *
287 * Close the specified driver service handle
288 *
289 * @param ServiceHandle
290 * Pointer to a variable containing the service handle.
291 * Will be set to NULL on success
292 *
293 * @return Win32 error code
294 */
295 DWORD KmtCloseService(
296 IN OUT SC_HANDLE *ServiceHandle)
297 {
298 DWORD Error = ERROR_SUCCESS;
299
300 assert(ServiceHandle);
301
302 if (*ServiceHandle && !CloseServiceHandle(*ServiceHandle))
303 error_goto(Error, cleanup);
304
305 *ServiceHandle = NULL;
306
307 cleanup:
308 return Error;
309 }