1 /*
2  * PROJECT:     ReactOS Services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/applications/mscutils/servman/stop.c
5  * PURPOSE:     Stops running a service
6  * COPYRIGHT:   Copyright 2006-2015 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MAX_WAIT_TIME   30000
16 
17 DWORD
18 DoStopService(_In_z_ LPWSTR ServiceName,
19               _In_opt_ HANDLE hProgress)
20 {
21     SC_HANDLE hSCManager;
22     SC_HANDLE hService;
23     SERVICE_STATUS_PROCESS ServiceStatus;
24     DWORD BytesNeeded;
25     DWORD StartTime;
26     DWORD WaitTime;
27     DWORD Timeout;
28     DWORD dwResult = ERROR_SUCCESS;
29 
30     hSCManager = OpenSCManagerW(NULL,
31                                 NULL,
32                                 SC_MANAGER_CONNECT);
33     if (!hSCManager) return GetLastError();
34 
35     hService = OpenServiceW(hSCManager,
36                             ServiceName,
37                             SERVICE_STOP | SERVICE_QUERY_STATUS);
38     if (!hService)
39     {
40         dwResult = GetLastError();
41         CloseServiceHandle(hSCManager);
42         return dwResult;
43     }
44 
45     if (hProgress)
46     {
47         /* Increment the progress bar */
48         IncrementProgressBar(hProgress, DEFAULT_STEP);
49     }
50 
51     /* Set the start and max wait times */
52     StartTime = GetTickCount();
53     Timeout = MAX_WAIT_TIME;
54 
55     /* Send the service the stop code */
56     if (ControlService(hService,
57                         SERVICE_CONTROL_STOP,
58                         (LPSERVICE_STATUS)&ServiceStatus))
59     {
60         if (hProgress)
61         {
62             /* Increment the progress bar */
63             IncrementProgressBar(hProgress, DEFAULT_STEP);
64         }
65 
66         while (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
67         {
68             int i;
69             /* Fixup the wait time */
70             WaitTime = ServiceStatus.dwWaitHint / 10;
71 
72             if (WaitTime < 1000) WaitTime = 1000;
73             else if (WaitTime > 10000) WaitTime = 10000;
74 
75             /* We don't wanna wait for up to 10 secs without incrementing */
76             for (i = WaitTime / 1000; i > 0; i--)
77             {
78                 Sleep(1000);
79                 if (hProgress)
80                 {
81                     /* Increment the progress bar */
82                     IncrementProgressBar(hProgress, DEFAULT_STEP);
83                 }
84             }
85 
86             if (QueryServiceStatusEx(hService,
87                                         SC_STATUS_PROCESS_INFO,
88                                         (LPBYTE)&ServiceStatus,
89                                         sizeof(SERVICE_STATUS_PROCESS),
90                                         &BytesNeeded))
91             {
92                 /* Have we exceeded our wait time? */
93                 if (GetTickCount() - StartTime > Timeout)
94                 {
95                     /* Yep, give up */
96                     DPRINT1("Timeout\n");
97                     dwResult = ERROR_SERVICE_REQUEST_TIMEOUT;
98                     break;
99                 }
100             }
101             else
102             {
103                 dwResult = GetLastError();
104                 DPRINT1("QueryServiceStatusEx failed: %d\n", dwResult);
105             }
106         }
107 
108         /* If the service is stopped, return TRUE */
109         if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
110         {
111             dwResult = ERROR_SUCCESS;
112         }
113     }
114     else
115     {
116         dwResult = GetLastError();
117     }
118 
119     CloseServiceHandle(hService);
120     CloseServiceHandle(hSCManager);
121 
122     return dwResult;
123 }
124