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