1 #include "Unfrag.h" 2 #include "MainDialog.h" 3 #include "resource.h" 4 #include "Fraginator.h" 5 #include "Defragment.h" 6 #include "ReportDialog.h" 7 8 9 vector<wstring> DrivesList; 10 LRESULT AnalyzeID; 11 LRESULT FastID; 12 LRESULT ExtensiveID; 13 bool QuitWhenDone; 14 bool Stopping; 15 16 17 LRESULT PriHighID; 18 LRESULT PriAboveNormID; 19 LRESULT PriNormalID; 20 LRESULT PriBelowNormID; 21 LRESULT PriIdleID; 22 23 24 static void InitDialog (HWND Dlg); 25 void UpdateDefragInfo (HWND Dlg); 26 void UpdatePriority (HWND Dlg); 27 wstring GetDefaultTitle (void); 28 wstring GetDefragTitle (void); 29 void SetDisables (HWND Dlg); 30 INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam); 31 32 33 static void InitDialog (HWND Dlg) 34 { 35 // Make internal list 36 DWORD DriveMask; 37 HWND DlgItem; 38 size_t d; 39 40 // Clear out wisecracks line for now 41 SetDlgItemText (Dlg, IDC_WISECRACKS, L"\"Defrag, baby!\""); 42 43 // Make list of logical drives 44 DrivesList.resize (0); 45 DriveMask = GetLogicalDrives (); 46 47 for (d = 0; d < 26; d++) 48 { 49 if (DriveMask & (1 << d)) 50 { 51 wstring Name; 52 53 Name = (wchar_t)(L'A' + d); 54 Name += L':'; 55 DrivesList.push_back (Name); 56 } 57 } 58 59 // Give list to dropdown list 60 DlgItem = GetDlgItem (Dlg, IDC_DRIVES_LIST); 61 SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); 62 for (d = 0; d < DrivesList.size(); d++) 63 { 64 SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) DrivesList[d].c_str()); 65 } 66 67 // Put in defrag methods 68 DlgItem = GetDlgItem (Dlg, IDC_METHODS_LIST); 69 SendMessage (DlgItem, CB_RESETCONTENT, 0, 0); 70 AnalyzeID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Analyze Only"); 71 FastID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Fast Defrag"); 72 ExtensiveID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Extensive Defrag"); 73 74 // Set up process priorities 75 DlgItem = GetDlgItem (Dlg, IDC_PRIORITY_LIST); 76 SendMessage (Dlg, CB_RESETCONTENT, 0, 0); 77 PriHighID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"High"); 78 PriAboveNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Above Normal"); 79 PriNormalID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Normal"); 80 PriBelowNormID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Below Normal"); 81 PriIdleID = SendMessage (DlgItem, CB_ADDSTRING, 0, (LPARAM) L"Idle"); 82 UpdatePriority (Dlg); 83 84 // Reset texts and progress meters 85 SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, (LPARAM) L""); 86 SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) L""); 87 SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETRANGE, 0, MAKELPARAM (0, 10000)); 88 SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, 0, 0); 89 90 return; 91 } 92 93 94 void UpdateDefragInfo (HWND Dlg) 95 { 96 wchar_t PercentText[100]; 97 static double OldPercent = 200.0f; 98 static wstring OldStatus = L"Non"; 99 wstring NewStatus; 100 double NewPercent; 101 102 if (Defrag == NULL) 103 return; 104 105 NewPercent = Defrag->GetStatusPercent (); 106 if (NewPercent > 100.0f) 107 NewPercent = 100.0f; 108 if (NewPercent < 0.0f) 109 NewPercent = 0.0f; 110 if (NewPercent != OldPercent) 111 { 112 swprintf (PercentText, L"%6.2f%%", NewPercent); 113 SendDlgItemMessage (Dlg, IDC_PERCENT, WM_SETTEXT, 0, (LPARAM) PercentText); 114 SendDlgItemMessage (Dlg, IDC_PROGRESS, PBM_SETPOS, 115 (WPARAM) (int)(NewPercent * 100.0f), 0); 116 OldPercent = NewPercent; 117 } 118 119 NewStatus = Defrag->GetStatusString (); 120 if (NewStatus != OldStatus) 121 { // Change & characters to && to avoid underlining 122 wstring Status; 123 wstring::iterator it; 124 125 Status = NewStatus; 126 it = Status.begin (); 127 while (it < Status.end()) 128 { 129 if (*it == L'&') 130 { 131 Status.insert (it, 1, L'&'); 132 it++; 133 } 134 135 it++; 136 } 137 138 SendDlgItemMessage (Dlg, IDC_STATUS, WM_SETTEXT, 0, 139 (LPARAM) Status.c_str()); 140 141 OldStatus = NewStatus; 142 } 143 144 return; 145 } 146 147 148 wstring GetDefaultTitle (void) 149 { 150 wstring DefaultText; 151 152 DefaultText = wstring(wstring(APPNAME_GUI) + wstring(L" v") + wstring(APPVER_STR) + 153 wstring(L" (C) 2000 by Rick Brewster")); 154 155 return (DefaultText); 156 } 157 158 159 wstring GetDefragTitle (void) 160 { 161 wstring DefragText; 162 wchar_t Percent[10]; 163 164 swprintf (Percent, L"%.2f%%", Defrag->GetStatusPercent()); 165 166 DefragText = GetDefaultTitle (); 167 if (Defrag != NULL) 168 { 169 DefragText = wstring(Percent) + wstring (L" - ") + Defrag->GetVolume().GetRootPath() + 170 wstring (L" - ") + DefragText; 171 } 172 173 return (DefragText); 174 } 175 176 177 void SetDisables (HWND Dlg) 178 { 179 // If a defrag is in process, set L'Start' button to say L'Stop' and disable 180 // the Select Drive and Select Action controls 181 if (Defrag != NULL && !Defrag->IsDoneYet() && !Defrag->HasError()) 182 { 183 SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) L"Stop"); 184 EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), FALSE); 185 EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), FALSE); 186 } 187 else 188 { 189 SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), WM_SETTEXT, 0, (LPARAM) L"Start"); 190 EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), TRUE); 191 EnableWindow (GetDlgItem (Dlg, IDC_QUIT), TRUE); 192 EnableWindow (GetDlgItem (Dlg, IDC_DRIVES_LIST), TRUE); 193 EnableWindow (GetDlgItem (Dlg, IDC_METHODS_LIST), TRUE); 194 } 195 196 return; 197 } 198 199 200 void UpdatePriority (HWND Dlg) 201 { 202 LRESULT Id; 203 DWORD Priority; 204 205 Id = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); 206 207 if (Id == PriHighID) 208 Priority = HIGH_PRIORITY_CLASS; 209 else 210 if (Id == PriAboveNormID) 211 Priority = ABOVE_NORMAL_PRIORITY_CLASS; 212 else 213 if (Id == PriNormalID) 214 Priority = NORMAL_PRIORITY_CLASS; 215 else 216 if (Id == PriBelowNormID) 217 Priority = BELOW_NORMAL_PRIORITY_CLASS; 218 else 219 if (Id == PriIdleID) 220 Priority = IDLE_PRIORITY_CLASS; 221 else 222 return; 223 224 SetPriorityClass (GetCurrentProcess(), Priority); 225 return; 226 } 227 228 229 // Save settings (ie, process priority and defrag type options) 230 bool GetRegKeys (HKEY *RegKeyResult) 231 { 232 HKEY RegKey; 233 LONG Error; 234 235 Error = RegCreateKeyEx 236 ( 237 HKEY_CURRENT_USER, 238 L"Software\\Fraginator", 239 0, 240 NULL, 241 REG_OPTION_NON_VOLATILE, 242 KEY_ALL_ACCESS, 243 NULL, 244 &RegKey, 245 NULL 246 ); 247 248 if (Error != ERROR_SUCCESS) 249 return (false); 250 251 *RegKeyResult = RegKey; 252 return (true); 253 } 254 255 256 bool DoneRegKey (HKEY RegKey) 257 { 258 RegCloseKey (RegKey); 259 return (true); 260 } 261 262 263 void SaveSettings (HWND Dlg) 264 { 265 LRESULT DefragID; 266 DWORD DefragVal; 267 LRESULT PriID; 268 DWORD PriVal; 269 HKEY RegKey; 270 271 DefragID = SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_GETCURSEL, 0, 0); 272 PriID = SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_GETCURSEL, 0, 0); 273 274 // Action 275 if (DefragID == AnalyzeID) 276 DefragVal = (DWORD) DefragAnalyze; 277 else 278 if (DefragID == FastID) 279 DefragVal = (DWORD) DefragFast; 280 else 281 if (DefragID == ExtensiveID) 282 DefragVal = (DWORD) DefragExtensive; 283 284 // Process Priority 285 if (PriID == PriHighID) 286 PriVal = HIGH_PRIORITY_CLASS; 287 else 288 if (PriID == PriAboveNormID) 289 PriVal = ABOVE_NORMAL_PRIORITY_CLASS; 290 else 291 if (PriID == PriNormalID) 292 PriVal = NORMAL_PRIORITY_CLASS; 293 else 294 if (PriID == PriBelowNormID) 295 PriVal = BELOW_NORMAL_PRIORITY_CLASS; 296 else 297 if (PriID == PriIdleID) 298 PriVal = IDLE_PRIORITY_CLASS; 299 300 if (!GetRegKeys (&RegKey)) 301 return; 302 303 RegSetValueEx 304 ( 305 RegKey, 306 L"Default Action", 307 0, 308 REG_DWORD, 309 (CONST BYTE *)&DefragVal, 310 sizeof (DefragVal) 311 ); 312 313 RegSetValueEx 314 ( 315 RegKey, 316 L"Process Priority", 317 0, 318 REG_DWORD, 319 (CONST BYTE *)&PriVal, 320 sizeof (PriVal) 321 ); 322 323 DoneRegKey (RegKey); 324 return; 325 } 326 327 328 void LoadSettings (HWND Dlg) 329 { 330 DefragType DType; 331 DWORD DTypeVal; 332 LRESULT DefragID; 333 DWORD PriVal; 334 LRESULT PriID; 335 HKEY RegKey; 336 DWORD RegType; 337 DWORD RegSize; 338 LONG Error; 339 340 if (!GetRegKeys (&RegKey)) 341 return; 342 343 RegSize = sizeof (DTypeVal); 344 RegType = REG_DWORD; 345 346 Error = RegQueryValueEx 347 ( 348 RegKey, 349 L"Default Action", 350 0, 351 &RegType, 352 (BYTE *)&DTypeVal, 353 &RegSize 354 ); 355 356 if (Error != ERROR_SUCCESS) 357 DTypeVal = DefragAnalyze; 358 359 Error = RegQueryValueEx 360 ( 361 RegKey, 362 L"Process Priority", 363 0, 364 &RegType, 365 (BYTE *)&PriVal, 366 &RegSize 367 ); 368 369 DoneRegKey (RegKey); 370 371 if (Error != ERROR_SUCCESS) 372 PriVal = NORMAL_PRIORITY_CLASS; 373 374 DType = (DefragType) DTypeVal; 375 switch (DType) 376 { 377 default: 378 case DefragAnalyze: 379 DefragID = AnalyzeID; 380 break; 381 382 case DefragFast: 383 DefragID = FastID; 384 break; 385 386 case DefragExtensive: 387 DefragID = ExtensiveID; 388 break; 389 } 390 391 switch (PriVal) 392 { 393 case HIGH_PRIORITY_CLASS: 394 PriID = PriHighID; 395 break; 396 397 case ABOVE_NORMAL_PRIORITY_CLASS: 398 PriID = PriAboveNormID; 399 break; 400 401 default: 402 case NORMAL_PRIORITY_CLASS: 403 PriID = PriNormalID; 404 break; 405 406 case BELOW_NORMAL_PRIORITY_CLASS: 407 PriID = PriBelowNormID; 408 break; 409 410 case IDLE_PRIORITY_CLASS: 411 PriID = PriIdleID; 412 break; 413 } 414 415 SendDlgItemMessage (Dlg, IDC_PRIORITY_LIST, CB_SETCURSEL, PriID, 0); 416 SendDlgItemMessage (Dlg, IDC_METHODS_LIST, CB_SETCURSEL, DefragID, 0); 417 return; 418 } 419 420 421 #define IDLETIME 25 422 wstring OldWindowText = L""; 423 424 INT_PTR CALLBACK MainDialogProc (HWND Dlg, UINT Msg, WPARAM WParam, LPARAM LParam) 425 { 426 static bool ReEntrance = false; 427 428 switch (Msg) 429 { 430 case WM_INITDIALOG: 431 Stopping = false; 432 SetWindowText (Dlg, GetDefaultTitle().c_str()); 433 SetDisables (Dlg); 434 InitDialog (Dlg); 435 SetTimer (Dlg, 1, IDLETIME, NULL); 436 SetClassLong (Dlg, GCL_HICON, (LONG) LoadIcon (GlobalHInstance, MAKEINTRESOURCE(IDI_ICON))); 437 QuitWhenDone = false; 438 LoadSettings (Dlg); 439 UpdatePriority (Dlg); 440 return (1); 441 442 443 case WM_TIMER: 444 if (Defrag != NULL && !ReEntrance) 445 { 446 wstring NewTitle; 447 448 SendMessage (Dlg, WM_UPDATEINFO, 0, 0); 449 450 NewTitle = GetDefragTitle (); 451 if (NewTitle != OldWindowText) 452 { 453 OldWindowText = NewTitle; 454 SetWindowText (Dlg, NewTitle.c_str()); 455 } 456 457 if (Defrag->IsDoneYet() || Defrag->HasError()) 458 { // This is the code executed when defragging is finished (or stopped :) 459 if (Defrag->GetDefragType() == DefragAnalyze && 460 !Defrag->HasError() && 461 !Stopping) 462 { // Show report 463 ReEntrance = true; 464 465 DialogBoxParam (GlobalHInstance, MAKEINTRESOURCE (IDD_REPORT), 466 Dlg, ReportDialogProc, (LPARAM) Defrag); 467 468 ReEntrance = false; 469 } 470 471 delete Defrag; 472 Defrag = NULL; 473 SetDisables (Dlg); 474 SetWindowText (Dlg, GetDefaultTitle().c_str()); 475 476 Stopping = false; 477 478 if (QuitWhenDone) 479 SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); 480 } 481 } 482 483 SetTimer (Dlg, 1, IDLETIME, NULL); 484 return (0); 485 486 487 case WM_UPDATEINFO: 488 UpdateDefragInfo (Dlg); 489 return (1); 490 491 492 case WM_CLOSE: 493 SendMessage (GetDlgItem (Dlg, IDC_QUIT), BM_CLICK, 0, 0); 494 return (1); 495 496 497 case WM_COMMAND: 498 switch (LOWORD(WParam)) 499 { 500 case IDC_PRIORITY_LIST: 501 UpdatePriority (Dlg); 502 return (1); 503 504 505 case ID_MAIN_HELP: 506 ShellExecute (Dlg, L"open", L"Fraginator.chm", L"", L".", SW_SHOW); 507 return (1); 508 509 510 case IDC_QUIT: 511 if (Defrag == NULL) 512 { // This is the code executing when quitting 513 SaveSettings (Dlg); 514 EndDialog (Dlg, 0); 515 } 516 else 517 { // Tell defragging to finish and disable our button 518 QuitWhenDone = true; 519 SendMessage (GetDlgItem (Dlg, IDC_STARTSTOP), BM_CLICK, 0, 0); 520 EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); 521 } 522 return (1); 523 524 525 case IDC_STARTSTOP: 526 if (Defrag == NULL) 527 { // L"Start" 528 wchar_t Drive[10]; 529 LRESULT ID; 530 DefragType Method; 531 HANDLE H; 532 533 if (Defrag != NULL) 534 return (1); 535 536 SendMessage (GetDlgItem (Dlg, IDC_DRIVES_LIST), WM_GETTEXT, 537 sizeof (Drive) - 1, (LPARAM) Drive); 538 539 if (wcslen(Drive) != 2 || Drive[1] != L':') 540 return (1); 541 542 ID = SendMessage (GetDlgItem (Dlg, IDC_METHODS_LIST), CB_GETCURSEL, 0, 0); 543 Method = DefragInvalid; 544 if (ID == AnalyzeID) 545 Method = DefragAnalyze; 546 else 547 if (ID == FastID) 548 Method = DefragFast; 549 else 550 if (ID == ExtensiveID) 551 Method = DefragExtensive; 552 553 if (Method != DefragInvalid) 554 { 555 Defrag = StartDefragThread (Drive, Method, H); 556 Defrag->SetDoLimitLength (false); 557 SetWindowText (Dlg, GetDefragTitle().c_str()); 558 SetDisables (Dlg); 559 } 560 } 561 else 562 { // L"Stop" 563 Stopping = true; 564 Defrag->Stop (); 565 EnableWindow (GetDlgItem (Dlg, IDC_STARTSTOP), FALSE); 566 EnableWindow (GetDlgItem (Dlg, IDC_QUIT), FALSE); 567 } 568 return (1); 569 } 570 } 571 572 // Otherwise, return 0 to say we did not process the message. 573 return (0); 574 } 575