[BTRFS]
[reactos.git] / base / applications / mscutils / servman / progress.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/progress.c
5 * PURPOSE: Progress dialog box message handler
6 * COPYRIGHT: Copyright 2006-2015 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 #define PROGRESS_RANGE 20
13 #define PROGRESS_STEP_MAX 15
14
15 typedef struct _PROGRESS_DATA
16 {
17 HWND hDlg;
18 HWND hProgress;
19 LPWSTR ServiceName;
20 ULONG Action;
21 BOOL StopDepends;
22 LPWSTR ServiceList;
23 PVOID Param;
24
25 } PROGRESS_DATA, *PPROGRESS_DATA;
26
27
28 static VOID
29 ResetProgressDialog(HWND hDlg,
30 LPWSTR ServiceName,
31 ULONG LabelId)
32 {
33 LPWSTR lpProgStr;
34
35 /* Load the label Id */
36 if (AllocAndLoadString(&lpProgStr,
37 hInstance,
38 LabelId))
39 {
40 /* Write it to the dialog */
41 SendDlgItemMessageW(hDlg,
42 IDC_SERVCON_INFO,
43 WM_SETTEXT,
44 0,
45 (LPARAM)lpProgStr);
46
47 LocalFree(lpProgStr);
48 }
49
50 /* Write the service name to the dialog */
51 SendDlgItemMessageW(hDlg,
52 IDC_SERVCON_NAME,
53 WM_SETTEXT,
54 0,
55 (LPARAM)ServiceName);
56
57 /* Set the progress bar to the start */
58 SendDlgItemMessageW(hDlg,
59 IDC_SERVCON_PROGRESS,
60 PBM_SETPOS,
61 0,
62 0);
63 }
64
65 unsigned int __stdcall ActionThread(void* Param)
66 {
67 PPROGRESS_DATA ProgressData = (PPROGRESS_DATA)Param;
68
69 if (ProgressData->Action == ACTION_START)
70 {
71 /* Setup the progress dialog for this action */
72 ResetProgressDialog(ProgressData->hDlg,
73 ProgressData->ServiceName,
74 IDS_PROGRESS_INFO_START);
75
76 /* Start the service */
77 if (DoStartService(ProgressData->ServiceName,
78 ProgressData->hProgress,
79 ProgressData->Param))
80 {
81 /* We're done, slide the progress bar up to the top */
82 CompleteProgressBar(ProgressData->hProgress);
83 }
84 }
85 else if (ProgressData->Action == ACTION_STOP || ProgressData->Action == ACTION_RESTART)
86 {
87 /* Check if there are and dependants to stop */
88 if (ProgressData->StopDepends && ProgressData->ServiceList)
89 {
90 LPWSTR lpStr = ProgressData->ServiceList;
91
92 /* Loop through all the services in the list */
93 for (;;)
94 {
95 /* Break when we hit the double null */
96 if (*lpStr == L'\0' && *(lpStr + 1) == L'\0')
97 break;
98
99 /* If this isn't our first time in the loop we'll
100 have been left on a null char */
101 if (*lpStr == L'\0')
102 lpStr++;
103
104 ResetProgressDialog(ProgressData->hDlg,
105 lpStr,
106 IDS_PROGRESS_INFO_STOP);
107
108 /* Stop the requested service */
109 if (DoStopService(ProgressData->ServiceName,
110 ProgressData->hProgress))
111 {
112 CompleteProgressBar(ProgressData->hProgress);
113 }
114
115 /* Move onto the next string */
116 while (*lpStr != L'\0')
117 lpStr++;
118 }
119 }
120
121 ResetProgressDialog(ProgressData->hDlg,
122 ProgressData->ServiceName,
123 IDS_PROGRESS_INFO_STOP);
124
125 if (DoStopService(ProgressData->ServiceName,
126 ProgressData->hProgress))
127 {
128 CompleteProgressBar(ProgressData->hProgress);
129 }
130
131
132 /* If this was a restart, we'll need to start the service back up */
133 if (ProgressData->Action == ACTION_RESTART)
134 {
135 /* Setup the progress dialog for this action */
136 ResetProgressDialog(ProgressData->hDlg,
137 ProgressData->ServiceName,
138 IDS_PROGRESS_INFO_START);
139
140 /* Start the service */
141 if (DoStartService(ProgressData->ServiceName,
142 ProgressData->hProgress,
143 NULL))
144 {
145 /* We're done, slide the progress bar up to the top */
146 CompleteProgressBar(ProgressData->hProgress);
147 }
148 }
149 }
150 else if (ProgressData->Action == ACTION_PAUSE)
151 {
152 /* Setup the progress dialog for this action */
153 ResetProgressDialog(ProgressData->hDlg,
154 ProgressData->ServiceName,
155 IDS_PROGRESS_INFO_PAUSE);
156
157 /* Pause the service */
158 if (DoControlService(ProgressData->ServiceName,
159 ProgressData->hProgress,
160 SERVICE_CONTROL_PAUSE))
161 {
162 /* We're done, slide the progress bar up to the top */
163 CompleteProgressBar(ProgressData->hProgress);
164 }
165 }
166 else if (ProgressData->Action == ACTION_RESUME)
167 {
168 /* Setup the progress dialog for this action */
169 ResetProgressDialog(ProgressData->hDlg,
170 ProgressData->ServiceName,
171 IDS_PROGRESS_INFO_RESUME);
172
173 /* resume the service */
174 if (DoControlService(ProgressData->ServiceName,
175 ProgressData->hProgress,
176 SERVICE_CONTROL_CONTINUE))
177 {
178 /* We're done, slide the progress bar up to the top */
179 CompleteProgressBar(ProgressData->hProgress);
180 }
181 }
182
183
184 EndDialog(ProgressData->hDlg, IDOK);
185
186 _endthreadex(0);
187 return 0;
188 }
189
190 static BOOL
191 InitDialog(HWND hDlg,
192 UINT Message,
193 WPARAM wParam,
194 LPARAM lParam)
195 {
196 PPROGRESS_DATA ProgressData = (PPROGRESS_DATA)lParam;
197 HANDLE hThread;
198
199 ProgressData->hDlg = hDlg;
200
201 /* Get a handle to the progress bar */
202 ProgressData->hProgress = GetDlgItem(hDlg,
203 IDC_SERVCON_PROGRESS);
204 if (!ProgressData->hProgress)
205 return FALSE;
206
207 /* Set the progress bar range */
208 SendMessageW(ProgressData->hProgress,
209 PBM_SETRANGE,
210 0,
211 MAKELPARAM(0, PROGRESS_RANGE));
212
213 /* Set the progress bar step */
214 SendMessageW(ProgressData->hProgress,
215 PBM_SETSTEP,
216 (WPARAM)1,
217 0);
218
219 /* Create a thread to handle the service control */
220 hThread = (HANDLE)_beginthreadex(NULL, 0, &ActionThread, ProgressData, 0, NULL);
221 if (!hThread) return FALSE;
222
223 CloseHandle(hThread);
224
225 return TRUE;
226 }
227
228 INT_PTR CALLBACK
229 ProgressDialogProc(HWND hDlg,
230 UINT Message,
231 WPARAM wParam,
232 LPARAM lParam)
233 {
234 switch(Message)
235 {
236 case WM_INITDIALOG:
237 {
238 return InitDialog(hDlg,
239 Message,
240 wParam,
241 lParam);
242 }
243
244 case WM_COMMAND:
245 switch(LOWORD(wParam))
246 {
247 case IDOK:
248 EndDialog(hDlg, wParam);
249 break;
250
251 }
252 break;
253
254 default:
255 return FALSE;
256 }
257
258 return TRUE;
259 }
260
261 VOID
262 CompleteProgressBar(HANDLE hProgress)
263 {
264 HWND hProgBar = (HWND)hProgress;
265 UINT Pos = 0;
266
267 /* Get the current position */
268 Pos = SendMessageW(hProgBar,
269 PBM_GETPOS,
270 0,
271 0);
272
273 /* Loop until we hit the max */
274 while (Pos <= PROGRESS_RANGE)
275 {
276 /* Increment the progress bar */
277 SendMessageW(hProgBar,
278 PBM_DELTAPOS,
279 Pos,
280 0);
281
282 /* Wait for 15ms to give it a smooth feel */
283 Sleep(15);
284 Pos++;
285 }
286 }
287
288 VOID
289 IncrementProgressBar(HANDLE hProgress,
290 UINT Step)
291 {
292 HWND hProgBar = (HWND)hProgress;
293 UINT Position;
294
295 /* Don't allow the progress to reach to complete*/
296 Position = SendMessageW(hProgBar,
297 PBM_GETPOS,
298 0,
299 0);
300 if (Position < PROGRESS_STEP_MAX)
301 {
302 /* Do we want to increment the default amount? */
303 if (Step == DEFAULT_STEP)
304 {
305 /* Use the step value we set on create */
306 SendMessageW(hProgBar,
307 PBM_STEPIT,
308 0,
309 0);
310 }
311 else
312 {
313 /* Use the value passed */
314 SendMessageW(hProgBar,
315 PBM_SETPOS,
316 Step,
317 0);
318 }
319 }
320 }
321
322 BOOL
323 RunActionWithProgress(HWND hParent,
324 LPWSTR ServiceName,
325 LPWSTR DisplayName,
326 UINT Action,
327 PVOID Param)
328 {
329 PROGRESS_DATA ProgressData;
330 LPWSTR ServiceList;
331 BOOL StopDepends;
332 INT_PTR Result;
333
334 StopDepends = FALSE;
335 ServiceList = NULL;
336
337
338 /* Check if we'll be stopping the service */
339 if (Action == ACTION_STOP || Action == ACTION_RESTART)
340 {
341 /* Does the service have any dependent services which need stopping first */
342 ServiceList = GetListOfServicesToStop(ServiceName);
343 if (ServiceList)
344 {
345 /* Ask the user if they want to stop the dependants */
346 StopDepends = CreateStopDependsDialog(hParent,
347 ServiceName,
348 DisplayName,
349 ServiceList);
350
351 /* Exit early if the user decided not to stop the dependants */
352 if (StopDepends == FALSE)
353 {
354 HeapFree(GetProcessHeap(), 0, ServiceList);
355 return FALSE;
356 }
357 }
358 }
359
360 ProgressData.hDlg = NULL;
361 ProgressData.ServiceName = ServiceName;
362 ProgressData.Action = Action;
363 ProgressData.StopDepends = StopDepends;
364 ProgressData.ServiceList = ServiceList;
365 ProgressData.Param = Param;
366
367 Result = DialogBoxParamW(hInstance,
368 MAKEINTRESOURCEW(IDD_DLG_PROGRESS),
369 hParent,
370 ProgressDialogProc,
371 (LPARAM)&ProgressData);
372
373 if (ServiceList)
374 HeapFree(GetProcessHeap(), 0, ServiceList);
375
376 return (Result == IDOK);
377 }