https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0c683c264c7c908e4bcc971d0a904afb2dad6b41

commit 0c683c264c7c908e4bcc971d0a904afb2dad6b41
Author:     Serge Gautherie <reactos-git_serge_171...@gautherie.fr>
AuthorDate: Tue Jan 16 05:47:34 2018 +0100
Commit:     Ged Murphy <gedmur...@reactos.org>
CommitDate: Thu May 17 16:17:36 2018 +0100

    [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
---
 modules/rostests/kmtests/kmtest/service.c | 111 +++++++++++++++++++++++++++++-
 1 file changed, 109 insertions(+), 2 deletions(-)

diff --git a/modules/rostests/kmtests/kmtest/service.c 
b/modules/rostests/kmtests/kmtest/service.c
index cc2e91a96e..7427fbfdd3 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 <thomas.fa...@reactos.org>
  *              Copyright 2017 Ged Murphy <gedmur...@reactos.org>
+ *              Copyright 2018 Serge Gautherie 
<reactos-git_serge_171...@gautherie.fr>
  */
 
 #include <kmt_test.h>
@@ -11,7 +12,7 @@
 
 #include <assert.h>
 
-#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
+}

Reply via email to