From: Serge Gautherie Date: Tue, 16 Jan 2018 04:47:34 +0000 (+0100) Subject: [KMTEST] Check/Wait for start/stop of services to complete X-Git-Tag: 0.4.9-RC~32 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=0c683c264c7c908e4bcc971d0a904afb2dad6b41 [KMTEST] Check/Wait for start/stop of services to complete This is cleaner behavior and lets report failures. - Create KmtEnsureServiceState(), called at end of KmtStartService() and KmtStopService(). - Create KmtGetServiceStateAsString(), called from KmtEnsureServiceState(). ROSTESTS-263 --- diff --git a/modules/rostests/kmtests/kmtest/service.c b/modules/rostests/kmtests/kmtest/service.c index cc2e91a96eb..7427fbfdd39 100644 --- a/modules/rostests/kmtests/kmtest/service.c +++ b/modules/rostests/kmtests/kmtest/service.c @@ -4,6 +4,7 @@ * PURPOSE: Kernel-Mode Test Suite loader service control functions * COPYRIGHT: Copyright 2011-2018 Thomas Faber * Copyright 2017 Ged Murphy + * Copyright 2018 Serge Gautherie */ #include @@ -11,7 +12,7 @@ #include -#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE) +#define SERVICE_ACCESS (SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE) /* * This is an internal function not meant for use by the kmtests app, @@ -101,6 +102,104 @@ KmtCreateService( ServiceHandle); } +/** + * @name KmtGetServiceStateAsString + * + * @param ServiceState + * Service state as a number + * + * @return Service state as a string + */ +static +PCSTR +KmtGetServiceStateAsString( + IN DWORD ServiceState) +{ + switch(ServiceState) + { + case SERVICE_STOPPED: + return "STOPPED"; + case SERVICE_START_PENDING: + return "START_PENDING"; + case SERVICE_STOP_PENDING: + return "STOP_PENDING"; + case SERVICE_RUNNING: + return "RUNNING"; + case SERVICE_CONTINUE_PENDING: + return "CONTINUE_PENDING"; + case SERVICE_PAUSE_PENDING: + return "PAUSE_PENDING"; + case SERVICE_PAUSED: + return "PAUSED"; + default: + ok(FALSE, "Unknown service state = %lu\n", ServiceState); + return "(Unknown)"; + } +} + +/** + * @name KmtEnsureServiceState + * + * @param ServiceName + * Name of the service to check, + * or NULL + * @param ServiceHandle + * Handle to the service + * @param ExpectedServiceState + * State which the service should be in + * + * @return Win32 error code + */ +static +DWORD +KmtEnsureServiceState( + IN PCWSTR ServiceName OPTIONAL, + IN SC_HANDLE ServiceHandle, + IN DWORD ExpectedServiceState) +{ + DWORD Error = ERROR_SUCCESS; + SERVICE_STATUS ServiceStatus; + DWORD StartTime = GetTickCount(); + DWORD Timeout = 10 * 1000; + PCWSTR ServiceNameOut = ServiceName ? ServiceName : L"(handle only, no name)"; + + assert(ServiceHandle); + assert(ExpectedServiceState); + + if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) + error_goto(Error, cleanup); + + while (ServiceStatus.dwCurrentState != ExpectedServiceState) + { + // NB: ServiceStatus.dwWaitHint and ServiceStatus.dwCheckPoint logic could be added, if need be. + + Sleep(1 * 1000); + + if (!QueryServiceStatus(ServiceHandle, &ServiceStatus)) + error_goto(Error, cleanup); + + if (GetTickCount() - StartTime >= Timeout) + break; + } + + if (ServiceStatus.dwCurrentState != ExpectedServiceState) + { + ok(FALSE, "Service = %ls, state = %lu %s (!= %lu %s), waitHint = %lu, checkPoint = %lu\n", + ServiceNameOut, + ServiceStatus.dwCurrentState, KmtGetServiceStateAsString(ServiceStatus.dwCurrentState), + ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState), + ServiceStatus.dwWaitHint, ServiceStatus.dwCheckPoint); + goto cleanup; + } + + trace("Service = %ls, state = %lu %s\n", + ServiceNameOut, + ExpectedServiceState, KmtGetServiceStateAsString(ExpectedServiceState)); + +cleanup: + return Error; +} + /** * @name KmtStartService * @@ -133,6 +232,10 @@ KmtStartService( if (!StartService(*ServiceHandle, 0, NULL)) error_goto(Error, cleanup); + Error = KmtEnsureServiceState(ServiceName, *ServiceHandle, SERVICE_RUNNING); + if (Error) + goto cleanup; + cleanup: return Error; } @@ -228,6 +331,10 @@ KmtStopService( if (!ControlService(*ServiceHandle, SERVICE_CONTROL_STOP, &ServiceStatus)) error_goto(Error, cleanup); + Error = KmtEnsureServiceState(ServiceName, *ServiceHandle, SERVICE_STOPPED); + if (Error) + goto cleanup; + cleanup: return Error; } @@ -340,4 +447,4 @@ KmtpCreateService( cleanup: return Error; -} \ No newline at end of file +}