services: Fix handling of user defined service controls.

Sebastian Lackner sebastian at fds-team.de
Wed Aug 10 03:27:59 CDT 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
 programs/services/rpc.c           |    7 +++++++
 programs/services/tests/service.c |   23 +++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 3ebf378..48e90de 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -981,6 +981,13 @@ static BOOL service_accepts_control(const struct service_entry *service, DWORD d
             return TRUE;
         break;
     }
+
+    if (dwControl >= 128 && dwControl <= 255)
+    {
+        if (a&SERVICE_USER_DEFINED_CONTROL)
+            return TRUE;
+    }
+
     return FALSE;
 }
 
diff --git a/programs/services/tests/service.c b/programs/services/tests/service.c
index 85b8e86..1f8e7e5 100644
--- a/programs/services/tests/service.c
+++ b/programs/services/tests/service.c
@@ -83,6 +83,9 @@ static DWORD WINAPI service_handler(DWORD ctrl, DWORD event_type, void *event_da
         SetServiceStatus(service_handle, &status);
         SetEvent(service_stop_event);
         return NO_ERROR;
+    case 128:
+        service_event("CUSTOM");
+        return 0xdeadbeef;
     default:
         status.dwCurrentState = SERVICE_RUNNING;
         SetServiceStatus( service_handle, &status );
@@ -106,12 +109,18 @@ static void WINAPI service_main(DWORD argc, char **argv)
 
     status.dwServiceType             = SERVICE_WIN32;
     status.dwCurrentState            = SERVICE_RUNNING;
-    status.dwControlsAccepted        = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
+    status.dwControlsAccepted        = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
+                                       SERVICE_USER_DEFINED_CONTROL;
     status.dwWin32ExitCode           = 0;
     status.dwServiceSpecificExitCode = 0;
     status.dwCheckPoint              = 0;
     status.dwWaitHint                = 10000;
     res = SetServiceStatus(service_handle, &status);
+    if (!res) /* WinXP / 2003 */
+    {
+        status.dwControlsAccepted &= ~SERVICE_USER_DEFINED_CONTROL;
+        res = SetServiceStatus(service_handle, &status);
+    }
     service_ok(res, "SetServiceStatus(SERVICE_RUNNING) failed: %u\n", GetLastError());
 
     service_event("RUNNING");
@@ -317,6 +326,7 @@ static DWORD WINAPI pipe_thread(void *arg)
 
 static void test_service(void)
 {
+    static const DWORD controls = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_USER_DEFINED_CONTROL;
     SC_HANDLE service_handle = register_service("simple_service");
     SERVICE_STATUS status;
     BOOL res;
@@ -338,7 +348,7 @@ static void test_service(void)
     ok(res, "QueryServiceStatus failed: %d\n", GetLastError());
     todo_wine ok(status.dwServiceType == SERVICE_WIN32_OWN_PROCESS, "status.dwServiceType = %x\n", status.dwServiceType);
     ok(status.dwCurrentState == SERVICE_RUNNING, "status.dwCurrentState = %x\n", status.dwCurrentState);
-    ok(status.dwControlsAccepted == (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN),
+    ok(status.dwControlsAccepted == controls || broken(status.dwControlsAccepted == (controls & ~SERVICE_USER_DEFINED_CONTROL)),
             "status.dwControlsAccepted = %x\n", status.dwControlsAccepted);
     ok(status.dwWin32ExitCode == 0, "status.dwExitCode = %d\n", status.dwWin32ExitCode);
     ok(status.dwServiceSpecificExitCode == 0, "status.dwServiceSpecificExitCode = %d\n",
@@ -346,6 +356,15 @@ static void test_service(void)
     ok(status.dwCheckPoint == 0, "status.dwCheckPoint = %d\n", status.dwCheckPoint);
     todo_wine ok(status.dwWaitHint == 0, "status.dwWaitHint = %d\n", status.dwWaitHint);
 
+    if (!(status.dwControlsAccepted & SERVICE_USER_DEFINED_CONTROL))
+        win_skip("user defined controls not supported, skipping test\n");
+    else
+    {
+        res = ControlService(service_handle, 128, &status);
+        ok(res, "ControlService failed: %u\n", GetLastError());
+        expect_event("CUSTOM");
+    }
+
     res = ControlService(service_handle, SERVICE_CONTROL_STOP, &status);
     ok(res, "ControlService failed: %u\n", GetLastError());
     expect_event("STOP");
-- 
2.9.0



More information about the wine-patches mailing list