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