Synchronize with trunk revision 59781.
[reactos.git] / base / applications / mscutils / servman / stop.c
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-2010 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 static BOOL
13 StopService(PMAIN_WND_INFO pInfo,
14 LPWSTR lpServiceName,
15 HWND hProgress OPTIONAL)
16 {
17 SC_HANDLE hSCManager;
18 SC_HANDLE hService;
19 SERVICE_STATUS_PROCESS ServiceStatus;
20 DWORD dwBytesNeeded;
21 DWORD dwStartTime;
22 DWORD dwTimeout;
23 BOOL bRet = FALSE;
24
25 if (hProgress)
26 {
27 /* Set the service name and reset the progress bag */
28 InitializeProgressDialog(hProgress, lpServiceName);
29 }
30
31 hSCManager = OpenSCManager(NULL,
32 NULL,
33 SC_MANAGER_CONNECT);
34 if (hSCManager)
35 {
36 hService = OpenService(hSCManager,
37 lpServiceName,
38 SERVICE_STOP | SERVICE_QUERY_STATUS);
39 if (hService)
40 {
41 if (hProgress)
42 {
43 /* Increment the progress bar */
44 IncrementProgressBar(hProgress, DEFAULT_STEP);
45 }
46
47 /* Set the wait time to 30 secs */
48 dwStartTime = GetTickCount();
49 dwTimeout = 30000;
50
51 /* Send the service the stop code */
52 if (ControlService(hService,
53 SERVICE_CONTROL_STOP,
54 (LPSERVICE_STATUS)&ServiceStatus))
55 {
56 if (hProgress)
57 {
58 /* Increment the progress bar */
59 IncrementProgressBar(hProgress, DEFAULT_STEP);
60 }
61
62 while (ServiceStatus.dwCurrentState != SERVICE_STOPPED)
63 {
64 /* Don't sleep for more than 3 seconds */
65 if (ServiceStatus.dwWaitHint > 3000)
66 ServiceStatus.dwWaitHint = 3000;
67
68 Sleep(ServiceStatus.dwWaitHint);
69
70 if (hProgress)
71 {
72 /* Increment the progress bar */
73 IncrementProgressBar(hProgress, DEFAULT_STEP);
74 }
75
76 if (QueryServiceStatusEx(hService,
77 SC_STATUS_PROCESS_INFO,
78 (LPBYTE)&ServiceStatus,
79 sizeof(SERVICE_STATUS_PROCESS),
80 &dwBytesNeeded))
81 {
82 /* Have we exceeded our wait time? */
83 if (GetTickCount() - dwStartTime > dwTimeout)
84 {
85 /* Yep, give up */
86 break;
87 }
88 }
89 }
90
91 /* If the service is stopped, return TRUE */
92 if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
93 {
94 bRet = TRUE;
95 }
96 }
97
98 CloseServiceHandle(hService);
99 }
100
101 CloseServiceHandle(hSCManager);
102 }
103
104 return bRet;
105 }
106
107 static BOOL
108 StopDependantServices(PMAIN_WND_INFO pInfo,
109 LPWSTR lpServiceList,
110 HWND hProgress OPTIONAL)
111 {
112 LPWSTR lpStr;
113 BOOL bRet = FALSE;
114
115 lpStr = lpServiceList;
116
117 /* Loop through all the services in the list */
118 while (TRUE)
119 {
120 /* Break when we hit the double null */
121 if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
122 break;
123
124 /* If this isn't our first time in the loop we'll
125 have been left on a null char */
126 if (*lpStr == L'\0')
127 lpStr++;
128
129 /* Stop the requested service */
130 bRet = StopService(pInfo,
131 lpStr,
132 hProgress);
133
134 /* Complete the progress bar if we succeeded */
135 if (bRet)
136 {
137 CompleteProgressBar(hProgress);
138 }
139
140 /* Move onto the next string */
141 while (*lpStr != L'\0')
142 lpStr++;
143 }
144
145 return bRet;
146 }
147
148 BOOL
149 DoStop(PMAIN_WND_INFO pInfo)
150 {
151 HWND hProgress;
152 LPWSTR lpServiceList;
153 BOOL bRet = FALSE;
154 BOOL bStopMainService = TRUE;
155
156 if (pInfo)
157 {
158 /* Does the service have any dependent services which need stopping first */
159 lpServiceList = GetListOfServicesToStop(pInfo->pCurrentService->lpServiceName);
160 if (lpServiceList)
161 {
162 /* Tag the service list to the main wnd info */
163 pInfo->pTag = (PVOID)lpServiceList;
164
165 /* List them and ask the user if they want to stop them */
166 if (DialogBoxParamW(hInstance,
167 MAKEINTRESOURCEW(IDD_DLG_DEPEND_STOP),
168 pInfo->hMainWnd,
169 StopDependsDialogProc,
170 (LPARAM)pInfo) == IDOK)
171 {
172 /* Create a progress window to track the progress of the stopping services */
173 hProgress = CreateProgressDialog(pInfo->hMainWnd,
174 IDS_PROGRESS_INFO_STOP);
175
176 /* Stop all the dependant services */
177 StopDependantServices(pInfo, lpServiceList, hProgress);
178
179 /* Now stop the requested one */
180 bRet = StopService(pInfo,
181 pInfo->pCurrentService->lpServiceName,
182 hProgress);
183
184 /* We've already stopped the main service, don't try to stop it again */
185 bStopMainService = FALSE;
186
187 if (hProgress)
188 {
189 /* Complete and destroy the progress bar */
190 DestroyProgressDialog(hProgress, TRUE);
191 }
192 }
193 else
194 {
195 /* Don't stop the main service if the user selected not to */
196 bStopMainService = FALSE;
197 }
198
199 HeapFree(GetProcessHeap(),
200 0,
201 lpServiceList);
202 }
203
204 /* If the service has no running dependents, then we stop it here */
205 if (bStopMainService)
206 {
207 /* Create a progress window to track the progress of the stopping service */
208 hProgress = CreateProgressDialog(pInfo->hMainWnd,
209 IDS_PROGRESS_INFO_STOP);
210
211 /* Stop the requested service */
212 bRet = StopService(pInfo,
213 pInfo->pCurrentService->lpServiceName,
214 hProgress);
215
216 if (hProgress)
217 {
218 /* Complete and destroy the progress bar */
219 DestroyProgressDialog(hProgress, TRUE);
220 }
221 }
222 }
223
224 return bRet;
225 }