/* * PROJECT: ReactOS kernel-mode tests * LICENSE: GPLv2+ - See COPYING in the top level directory * PURPOSE: Kernel-Mode Test Suite Loader service control functions * PROGRAMMER: Thomas Faber */ #include #include "kmtest.h" #include #define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE) static SC_HANDLE ScmHandle; /** * @name KmtServiceInit * * Initialize service management routines (by opening the service control manager) * * @return Win32 error code */ DWORD KmtServiceInit(VOID) { DWORD Error = ERROR_SUCCESS; assert(!ScmHandle); ScmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (!ScmHandle) error(Error); return Error; } /** * @name KmtServiceCleanup * * Clean up resources used by service management routines. * * @param IgnoreErrors * If TRUE, the function will never set ErrorLineAndFile, and always return ERROR_SUCCESS * * @return Win32 error code */ DWORD KmtServiceCleanup( BOOLEAN IgnoreErrors) { DWORD Error = ERROR_SUCCESS; if (ScmHandle && !CloseServiceHandle(ScmHandle) && !IgnoreErrors) error(Error); return Error; } /** * @name KmtCreateService * * Create the specified driver service and return a handle to it * * @param ServiceName * Name of the service to create * @param ServicePath * File name of the driver, relative to the current directory * @param DisplayName * Service display name * @param ServiceHandle * Pointer to a variable to receive the handle to the service * * @return Win32 error code */ DWORD KmtCreateService( IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle) { DWORD Error = ERROR_SUCCESS; WCHAR DriverPath[MAX_PATH]; HRESULT result = S_OK; assert(ServiceHandle); assert(ServiceName && ServicePath); if (!GetModuleFileName(NULL, DriverPath, sizeof DriverPath / sizeof DriverPath[0])) error_goto(Error, cleanup); assert(wcsrchr(DriverPath, L'\\') != NULL); wcsrchr(DriverPath, L'\\')[1] = L'\0'; result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath); if (FAILED(result)) error_value_goto(Error, result, cleanup); if (GetFileAttributes(DriverPath) == INVALID_FILE_ATTRIBUTES) error_goto(Error, cleanup); *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName, SERVICE_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL, NULL); if (!*ServiceHandle) error_goto(Error, cleanup); cleanup: return Error; } /** * @name KmtStartService * * Start the specified driver service by handle or name (and return a handle to it) * * @param ServiceName * If *ServiceHandle is NULL, name of the service to start * @param ServiceHandle * Pointer to a variable containing the service handle, * or NULL (in which case it will be filled with a handle to the service) * * @return Win32 error code */ DWORD KmtStartService( IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle) { DWORD Error = ERROR_SUCCESS; assert(ServiceHandle); assert(ServiceName || *ServiceHandle); if (!*ServiceHandle) *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS); if (!*ServiceHandle) error_goto(Error, cleanup); if (!StartService(*ServiceHandle, 0, NULL)) error_goto(Error, cleanup); cleanup: return Error; } /** * @name KmtCreateAndStartService * * Create and start the specified driver service and return a handle to it * * @param ServiceName * Name of the service to create * @param ServicePath * File name of the driver, relative to the current directory * @param DisplayName * Service display name * @param ServiceHandle * Pointer to a variable to receive the handle to the service * @param RestartIfRunning * TRUE to stop and restart the service if it is already running * * @return Win32 error code */ DWORD KmtCreateAndStartService( IN PCWSTR ServiceName, IN PCWSTR ServicePath, IN PCWSTR DisplayName OPTIONAL, OUT SC_HANDLE *ServiceHandle, IN BOOLEAN RestartIfRunning) { DWORD Error = ERROR_SUCCESS; assert(ServiceHandle); Error = KmtCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle); if (Error && Error != ERROR_SERVICE_EXISTS) goto cleanup; Error = KmtStartService(ServiceName, ServiceHandle); if (Error != ERROR_SERVICE_ALREADY_RUNNING) goto cleanup; Error = ERROR_SUCCESS; if (!RestartIfRunning) goto cleanup; Error = KmtStopService(ServiceName, ServiceHandle); if (Error) goto cleanup; Error = KmtStartService(ServiceName, ServiceHandle); if (Error) goto cleanup; cleanup: assert(Error || *ServiceHandle); return Error; } /** * @name KmtStopService * * Stop the specified driver service by handle or name (and return a handle to it) * * @param ServiceName * If *ServiceHandle is NULL, name of the service to stop * @param ServiceHandle * Pointer to a variable containing the service handle, * or NULL (in which case it will be filled with a handle to the service) * * @return Win32 error code */ DWORD KmtStopService( IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle) { DWORD Error = ERROR_SUCCESS; SERVICE_STATUS ServiceStatus; assert(ServiceHandle); assert(ServiceName || *ServiceHandle); if (!*ServiceHandle) *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS); if (!*ServiceHandle) error_goto(Error, cleanup); if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus)) error_goto(Error, cleanup); cleanup: return Error; } /** * @name KmtDeleteService * * Delete the specified driver service by handle or name (and return a handle to it) * * @param ServiceName * If *ServiceHandle is NULL, name of the service to delete * @param ServiceHandle * Pointer to a variable containing the service handle. * Will be set to NULL on success * * @return Win32 error code */ DWORD KmtDeleteService( IN PCWSTR ServiceName OPTIONAL, IN OUT SC_HANDLE *ServiceHandle) { DWORD Error = ERROR_SUCCESS; assert(ServiceHandle); assert(ServiceName || *ServiceHandle); if (!*ServiceHandle) *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS); if (!*ServiceHandle) error_goto(Error, cleanup); if (!DeleteService(*ServiceHandle)) error_goto(Error, cleanup); if (*ServiceHandle) CloseServiceHandle(*ServiceHandle); cleanup: return Error; } /** * @name KmtCloseService * * Close the specified driver service handle * * @param ServiceHandle * Pointer to a variable containing the service handle. * Will be set to NULL on success * * @return Win32 error code */ DWORD KmtCloseService( IN OUT SC_HANDLE *ServiceHandle) { DWORD Error = ERROR_SUCCESS; assert(ServiceHandle); if (*ServiceHandle && !CloseServiceHandle(*ServiceHandle)) error_goto(Error, cleanup); *ServiceHandle = NULL; cleanup: return Error; }