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