1 /* 2 * PROJECT: ReactOS Applications 3 * LICENSE: LGPL - See COPYING in the top level directory 4 * FILE: base/applications/msconfig_new/systempage.c 5 * PURPOSE: System page message handler 6 * COPYRIGHT: Copyright 2005-2006 Christoph von Wittich <Christoph@ApiViewer.de> 7 * 2011 Gregor Schneider <Gregor.Schneider@reactos.org> 8 * Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr> 9 */ 10 11 #include "precomp.h" 12 #include <share.h> 13 14 #include "treeview.h" 15 #include "uxthemesupp.h" 16 17 #include "regutils.h" 18 #include "utils.h" 19 20 21 extern "C" { 22 23 LPCWSTR lpszSystemIni = L"%SystemRoot%\\system.ini"; // or: %windir%\\... ? 24 LPCWSTR lpszWinIni = L"%SystemRoot%\\win.ini"; // or: %windir%\\... ? 25 26 } 27 28 static LPCWSTR szMSConfigTok = L";msconfig "; // Note the trailing whitespace 29 static const size_t MSConfigTokLen = 10; 30 31 32 extern "C" { 33 34 DWORD GetSystemIniActivation(VOID) 35 { 36 DWORD dwSystemIni = 0; 37 RegGetDWORDValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L"system.ini", &dwSystemIni); 38 return dwSystemIni; 39 } 40 41 DWORD GetWinIniActivation(VOID) 42 { 43 DWORD dwWinIni = 0; 44 RegGetDWORDValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Shared Tools\\MSConfig\\state", L"win.ini", &dwWinIni); 45 return dwWinIni; 46 } 47 48 } 49 50 51 52 static HWND hTree = NULL; 53 static WCHAR szSearchString[MAX_VALUE_NAME] = L""; 54 static BOOL bMatchExactText = FALSE; 55 static BOOL bSearchSense = TRUE; // TRUE == down, FALSE == up. 56 static BOOL bCaseSensitive = FALSE; 57 58 static void 59 ToLower(LPWSTR lpszString) 60 { 61 if (!lpszString) 62 return; 63 64 while (*lpszString) 65 { 66 *lpszString = towlower(*lpszString); 67 ++lpszString; 68 } 69 } 70 71 INT_PTR CALLBACK 72 FindDialogWndProc(HWND hDlg, 73 UINT message, 74 WPARAM wParam, 75 LPARAM lParam) 76 { 77 UNREFERENCED_PARAMETER(lParam); 78 79 switch (message) 80 { 81 case WM_INITDIALOG: 82 { 83 hTree = (HWND)lParam; 84 85 Button_SetCheck(GetDlgItem(hDlg, IDC_CBX_FIND_WHOLE_WORD_ONLY), (bMatchExactText ? BST_CHECKED : BST_UNCHECKED)); 86 Button_SetCheck(GetDlgItem(hDlg, IDC_RB_FIND_DOWN), (bSearchSense ? BST_CHECKED : BST_UNCHECKED)); // TRUE == down, FALSE == up. 87 Button_SetCheck(GetDlgItem(hDlg, IDC_RB_FIND_UP ), (bSearchSense ? BST_UNCHECKED : BST_CHECKED )); // TRUE == down, FALSE == up. 88 Button_SetCheck(GetDlgItem(hDlg, IDC_CBX_FIND_MATCH_CASE), (bCaseSensitive ? BST_CHECKED : BST_UNCHECKED)); 89 90 Edit_SetText(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT), szSearchString); 91 SetFocus(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT)); 92 Edit_SetSel(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT), 0, -1); 93 94 return TRUE; 95 } 96 97 case WM_COMMAND: 98 { 99 switch (LOWORD(wParam)) 100 { 101 case IDOK: 102 { 103 TVITEMEXW tvItemEx; 104 HTREEITEM htiIterator; 105 WCHAR label[MAX_VALUE_NAME] = L""; 106 WCHAR szTemp[MAX_VALUE_NAME]; 107 108 bMatchExactText = (Button_GetCheck(GetDlgItem(hDlg, IDC_CBX_FIND_WHOLE_WORD_ONLY)) == BST_CHECKED); 109 bSearchSense = ((Button_GetCheck(GetDlgItem(hDlg, IDC_RB_FIND_DOWN)) == BST_CHECKED) && 110 (Button_GetCheck(GetDlgItem(hDlg, IDC_RB_FIND_UP )) == BST_UNCHECKED)); // TRUE == down, FALSE == up. 111 bCaseSensitive = (Button_GetCheck(GetDlgItem(hDlg, IDC_CBX_FIND_MATCH_CASE)) == BST_CHECKED); 112 113 Edit_GetText(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT), szSearchString, _ARRAYSIZE(szSearchString)); 114 wcscpy(szTemp, szSearchString); 115 if (!bCaseSensitive) 116 ToLower(szTemp); 117 118 for (htiIterator = ((Button_GetCheck(GetDlgItem(hDlg, IDC_CBX_FIND_FROM_BEGINNING)) == BST_CHECKED) ? (bSearchSense ? TreeView_GetFirst(hTree) 119 : TreeView_GetLast(hTree)) 120 : (bSearchSense ? TreeView_GetNext(hTree, TreeView_GetSelection(hTree)) 121 : TreeView_GetPrev(hTree, TreeView_GetSelection(hTree)))); 122 htiIterator ; 123 htiIterator = (bSearchSense ? TreeView_GetNext(hTree, htiIterator) 124 : TreeView_GetPrev(hTree, htiIterator))) 125 { 126 SecureZeroMemory(&tvItemEx, sizeof(tvItemEx)); 127 128 tvItemEx.hItem = htiIterator; // Handle of the item to be retrieved 129 tvItemEx.mask = TVIF_HANDLE | TVIF_TEXT; 130 tvItemEx.pszText = label; 131 tvItemEx.cchTextMax = MAX_VALUE_NAME; 132 TreeView_GetItem(hTree, &tvItemEx); 133 if (!bCaseSensitive) 134 ToLower(label); 135 136 if (bMatchExactText ? (_tcscmp(label, szTemp) == 0) : !!_tcsstr(label, szTemp)) // <-- hackish. A arranger. 137 { 138 TreeView_SelectItem(hTree, htiIterator); 139 EndDialog(hDlg, LOWORD(wParam)); 140 return TRUE; 141 } 142 //MessageBox(NULL, label, _T("Info"), MB_ICONINFORMATION | MB_OK); 143 } 144 145 // FIXME: Localize! 146 MessageBoxW(hDlg, L"No correspondence found.", szAppName, MB_ICONINFORMATION | MB_OK); 147 SetFocus(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT)); 148 Edit_SetSel(GetDlgItem(hDlg, IDC_TXT_FIND_TEXT), 0, -1); 149 //EndDialog(hDlg, LOWORD(wParam)); 150 return TRUE; 151 } 152 153 case IDCANCEL: 154 EndDialog(hDlg, LOWORD(wParam)); 155 return TRUE; 156 157 default: 158 //break; 159 return FALSE; 160 } 161 } 162 } 163 164 return FALSE; 165 } 166 167 168 169 static void 170 TreeView_SetBOOLCheck(HWND hTree, HTREEITEM htiItem, BOOL bState, BOOL bPropagateStateToParent) 171 { 172 if (!hTree || !htiItem) 173 return; 174 175 TreeView_SetCheckState(hTree, htiItem, bState); 176 177 /* 178 * Add or remove the token for tree leaves only. 179 */ 180 if (!TreeView_GetChild(hTree, htiItem)) 181 { 182 /* 1- Retrieve properties */ 183 TVITEMEXW tvItemEx; 184 SecureZeroMemory(&tvItemEx, sizeof(tvItemEx)); 185 186 tvItemEx.hItem = htiItem; // Handle of the item to be retrieved. 187 tvItemEx.mask = TVIF_HANDLE | TVIF_TEXT; 188 WCHAR label[MAX_VALUE_NAME] = L""; 189 tvItemEx.pszText = label; 190 tvItemEx.cchTextMax = MAX_VALUE_NAME; 191 TreeView_GetItem(hTree, &tvItemEx); 192 193 if (!bState) 194 { 195 /* 2- Add the token IF NEEDED */ 196 if ((wcslen(tvItemEx.pszText) < MSConfigTokLen) || (_wcsnicmp(tvItemEx.pszText, szMSConfigTok, MSConfigTokLen) != 0)) 197 { 198 LPWSTR newLabel = (LPWSTR)MemAlloc(0, (_tcslen(tvItemEx.pszText) + MSConfigTokLen + 1) * sizeof(WCHAR)); 199 wcscpy(newLabel, szMSConfigTok); 200 wcscat(newLabel, tvItemEx.pszText); 201 tvItemEx.pszText = newLabel; 202 203 TreeView_SetItem(hTree, &tvItemEx); 204 205 MemFree(newLabel); 206 } 207 } 208 else 209 { 210 /* 2- Remove the token IF NEEDED */ 211 if ((wcslen(tvItemEx.pszText) >= MSConfigTokLen) && (_wcsnicmp(tvItemEx.pszText, szMSConfigTok, MSConfigTokLen) == 0)) 212 { 213 LPWSTR newLabel = (LPWSTR)MemAlloc(0, (_tcslen(tvItemEx.pszText) - MSConfigTokLen + 1) * sizeof(WCHAR)); 214 wcscpy(newLabel, tvItemEx.pszText + MSConfigTokLen); 215 tvItemEx.pszText = newLabel; 216 217 TreeView_SetItem(hTree, &tvItemEx); 218 219 // TODO: if one finds tvItemEx.pszText == L"", one can 220 // directly remove the item (cf. message TVN_ENDLABELEDIT). 221 222 MemFree(newLabel); 223 } 224 } 225 } 226 //////////////////////// 227 228 for (HTREEITEM htiIterator = TreeView_GetChild(hTree, htiItem) ; htiIterator ; htiIterator = TreeView_GetNextSibling(hTree, htiIterator)) 229 TreeView_SetBOOLCheck(hTree, htiIterator, bState, FALSE); 230 231 if (bPropagateStateToParent) 232 TreeView_PropagateStateOfItemToParent(hTree, htiItem); 233 234 return; 235 } 236 237 static void 238 LoadIniFile(HWND hTree, LPCWSTR lpszIniFile) 239 { 240 // Ouverture en lecture (sans cr�ation de fichier si celui-ci n'esistait pas d�j�) 241 // d'un flux en mode texte, avec permission de lecture seule. 242 DWORD dwNumOfChars = ExpandEnvironmentStringsW(lpszIniFile, NULL, 0); 243 LPWSTR lpszFileName = (LPWSTR)MemAlloc(0, dwNumOfChars * sizeof(WCHAR)); 244 ExpandEnvironmentStringsW(lpszIniFile, lpszFileName, dwNumOfChars); 245 246 FILE* ini_file = _wfsopen(lpszFileName, L"rt", _SH_DENYWR); // r+t <-- read write text ; rt <-- read text 247 MemFree(lpszFileName); 248 249 if (!ini_file) 250 return; // error 251 252 WCHAR szLine[MAX_VALUE_NAME] = L""; 253 TVINSERTSTRUCT tvis; 254 HTREEITEM hParent = TVI_ROOT; 255 BOOL bIsSection = FALSE; 256 LPWSTR lpsz1 = NULL; 257 LPWSTR lpsz2 = NULL; 258 259 while (!feof(ini_file) && fgetws(szLine, _ARRAYSIZE(szLine), ini_file)) 260 { 261 /* Skip hypothetical starting spaces or newline characters */ 262 lpsz1 = szLine; 263 while (*lpsz1 == L' ' || *lpsz1 == L'\r' || *lpsz1 == L'\n') 264 ++lpsz1; 265 266 /* Skip empty lines */ 267 if (!*lpsz1) 268 continue; 269 270 /* Find the last newline character (if exists) and replace it by the NULL terminator */ 271 lpsz2 = lpsz1; 272 while (*lpsz2) 273 { 274 if (*lpsz2 == L'\r' || *lpsz2 == L'\n') 275 { 276 *lpsz2 = L'\0'; 277 break; 278 } 279 280 ++lpsz2; 281 } 282 283 /* Check for new sections. They should be parent of ROOT. */ 284 if (*lpsz1 == L'[') 285 { 286 bIsSection = TRUE; 287 hParent = TVI_ROOT; 288 } 289 290 SecureZeroMemory(&tvis, sizeof(tvis)); 291 tvis.hParent = hParent; 292 tvis.hInsertAfter = TVI_LAST; 293 tvis.itemex.mask = TVIF_TEXT; // TVIF_HANDLE | TVIF_TEXT; 294 tvis.itemex.pszText = lpsz1; 295 tvis.itemex.hItem = TreeView_InsertItem(hTree, &tvis); 296 297 /* The special ";msconfig " token disables the line */ 298 if (!bIsSection && _wcsnicmp(lpsz1, szMSConfigTok, MSConfigTokLen) == 0) 299 TreeView_SetBOOLCheck(hTree, tvis.itemex.hItem, FALSE, TRUE); 300 else 301 TreeView_SetBOOLCheck(hTree, tvis.itemex.hItem, TRUE, TRUE); 302 303 /* 304 * Now, all the elements will be children of this section, 305 * until we create a new one. 306 */ 307 if (bIsSection) 308 { 309 bIsSection = FALSE; 310 hParent = tvis.itemex.hItem; 311 } 312 } 313 314 fclose(ini_file); 315 return; 316 317 //// Test code for the TreeView //// 318 /* 319 HTREEITEM hItem[16]; 320 321 hItem[0] = InsertItem(hTree, _T("B"),TVI_ROOT,TVI_LAST); 322 hItem[1] = InsertItem(hTree, _T("C"),TVI_ROOT,TVI_LAST); 323 hItem[2] = InsertItem(hTree, _T("A"),TVI_ROOT,TVI_LAST); 324 hItem[3] = InsertItem(hTree, _T("D"),TVI_ROOT,TVI_LAST); 325 hItem[4] = InsertItem(hTree, _T("D-1"),hItem[3] ,TVI_LAST); 326 hItem[5] = InsertItem(hTree, _T("D-2"),hItem[3] ,TVI_LAST); 327 hItem[9] = InsertItem(hTree, _T("D-2-1"),hItem[5],TVI_LAST); 328 hItem[6] = InsertItem(hTree, _T("D-3"),hItem[3] ,TVI_LAST); 329 hItem[7] = InsertItem(hTree, _T("D-3-1"),hItem[6],TVI_LAST); 330 hItem[10] = InsertItem(hTree, _T("D-3-1-1"),hItem[7],TVI_LAST); 331 hItem[11] = InsertItem(hTree, _T("D-3-1-2"),hItem[7],TVI_LAST); 332 hItem[12] = InsertItem(hTree, _T("D-3-1-3"),hItem[7],TVI_LAST); 333 hItem[13] = InsertItem(hTree, _T("D-3-1-4"),hItem[7],TVI_LAST); 334 hItem[14] = InsertItem(hTree, _T("D-3-1-5"),hItem[7],TVI_LAST); 335 hItem[15] = InsertItem(hTree, _T("D-3-1-6"),hItem[7],TVI_LAST); 336 hItem[13] = InsertItem(hTree, _T("E"),TVI_ROOT,TVI_LAST); 337 */ 338 //////////////////////////////////// 339 340 } 341 342 static void 343 WriteIniFile(HWND hTree, LPCWSTR lpszIniFile) 344 { 345 // Ouverture en �criture (avec cr�ation de fichier si celui-ci n'esistait pas d�j�) 346 // d'un flux en mode texte, avec permission de lecture seule. 347 #if 0 348 DWORD dwNumOfChars = ExpandEnvironmentStringsW(lpszIniFile, NULL, 0); 349 LPWSTR lpszFileName = MemAlloc(0, dwNumOfChars * sizeof(WCHAR)); 350 ExpandEnvironmentStringsW(lpszIniFile, lpszFileName, dwNumOfChars); 351 #else 352 // HACK: delete these following lines when the program will be ready. 353 DWORD dwNumOfChars = ExpandEnvironmentStringsW(lpszIniFile, NULL, 0) + 11; 354 LPWSTR lpszFileName = (LPWSTR)MemAlloc(0, dwNumOfChars * sizeof(WCHAR)); 355 ExpandEnvironmentStringsW(lpszIniFile, lpszFileName, dwNumOfChars); 356 wcscat(lpszFileName, L"__tests.ini"); 357 // END HACK. 358 #endif 359 360 FILE* ini_file = _wfsopen(lpszFileName, L"wt", _SH_DENYRW); // w+t <-- write read text ; wt <-- write text 361 MemFree(lpszFileName); 362 363 if (!ini_file) 364 return; // error 365 366 367 TVITEMEXW tvItemEx; 368 WCHAR label[MAX_VALUE_NAME] = L""; 369 // WCHAR szLine[MAX_VALUE_NAME] = L""; 370 371 // for (HTREEITEM htiIterator = TreeView_GetRoot(hTree) ; htiIterator ; htiIterator = TreeView_GetNextSibling(hTree, htiIterator)) 372 for (HTREEITEM htiIterator = TreeView_GetFirst(hTree) ; htiIterator ; htiIterator = TreeView_GetNext(hTree, htiIterator)) 373 { 374 SecureZeroMemory(&tvItemEx, sizeof(tvItemEx)); 375 376 tvItemEx.hItem = htiIterator; // Handle of the item to be retrieved. 377 tvItemEx.mask = TVIF_HANDLE | TVIF_TEXT; 378 tvItemEx.pszText = label; 379 tvItemEx.cchTextMax = MAX_VALUE_NAME; 380 TreeView_GetItem(hTree, &tvItemEx); 381 382 // Write into the file. 383 wcscat(label, L"\n"); 384 fputws(label, ini_file); 385 } 386 387 fclose(ini_file); 388 return; 389 } 390 391 static void 392 Update_Btn_States(HWND hDlg) 393 { 394 HWND hTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 395 396 HTREEITEM hti = TreeView_GetSelection(hTree); 397 HTREEITEM htiPrev = TreeView_GetPrevSibling(hTree, hti); 398 HTREEITEM htiNext = TreeView_GetNextSibling(hTree, hti); 399 400 // 401 // "Up" / "Down" buttons. 402 // 403 if (htiPrev) 404 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_UP), TRUE); 405 else 406 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_UP), FALSE); 407 408 if (htiNext) 409 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DOWN), TRUE); 410 else 411 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DOWN), FALSE); 412 413 // 414 // "Enable" / "Disable" buttons. 415 // 416 UINT uCheckState = TreeView_GetCheckState(hTree, hti); 417 if (uCheckState == 0) 418 { 419 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE) , TRUE); 420 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE), FALSE); 421 } 422 else if (uCheckState == 1) 423 { 424 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE) , FALSE); 425 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE), TRUE); 426 } 427 else if (uCheckState == 2) 428 { 429 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE) , TRUE); 430 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE), TRUE); 431 } 432 else 433 { 434 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE) , FALSE); 435 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE), FALSE); 436 } 437 438 // 439 // "Enable all" / "Disable all" buttons. 440 // 441 UINT uRootCheckState = TreeView_GetRealSubtreeState(hTree, TVI_ROOT); 442 if (uRootCheckState == 0) 443 { 444 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE_ALL) , TRUE); 445 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE_ALL), FALSE); 446 } 447 else if (uRootCheckState == 1) 448 { 449 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE_ALL) , FALSE); 450 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE_ALL), TRUE); 451 } 452 else if (uRootCheckState == 2) 453 { 454 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE_ALL) , TRUE); 455 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE_ALL), TRUE); 456 } 457 else 458 { 459 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_ENABLE_ALL) , FALSE); 460 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DISABLE_ALL), FALSE); 461 } 462 463 // 464 // "Search" / "Edit" / "Delete" buttons. 465 // 466 if (TreeView_GetRoot(hTree)) 467 { 468 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_FIND) , TRUE); 469 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_EDIT) , TRUE); 470 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DELETE), TRUE); 471 } 472 else 473 { 474 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_FIND) , FALSE); 475 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_EDIT) , FALSE); 476 EnableWindow(GetDlgItem(hDlg, IDC_BTN_SYSTEM_DELETE), FALSE); 477 } 478 479 return; 480 } 481 482 483 INT_PTR 484 CommonWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 485 { 486 UNREFERENCED_PARAMETER(lParam); 487 UNREFERENCED_PARAMETER(wParam); 488 489 switch (message) 490 { 491 case WM_INITDIALOG: 492 { 493 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 494 495 // 496 // Initialize the styles. 497 // 498 TreeView_Set3StateCheck(hSystemTree); 499 SetWindowTheme(hSystemTree, L"Explorer", NULL); 500 501 TreeView_SetIndent(hSystemTree, TreeView_GetIndent(hSystemTree) + 2); 502 503 /* Load data */ 504 LoadIniFile(hSystemTree, (LPCWSTR)((LPPROPSHEETPAGE)lParam)->lParam); 505 506 /* Select the first item */ 507 TreeView_SelectItem(hSystemTree, TreeView_GetRoot(hSystemTree)); // Is it really necessary? 508 SetFocus(hSystemTree); 509 510 Update_Btn_States(hDlg); 511 512 return TRUE; 513 } 514 515 case WM_DESTROY: 516 { 517 TreeView_Cleanup(GetDlgItem(hDlg, IDC_SYSTEM_TREE)); 518 return FALSE; 519 } 520 521 case WM_COMMAND: 522 { 523 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 524 525 switch (LOWORD(wParam)) 526 { 527 case IDC_BTN_SYSTEM_UP: 528 { 529 TreeView_UpItem(hSystemTree, TreeView_GetSelection(hSystemTree)); 530 PropSheet_Changed(GetParent(hDlg), hDlg); 531 return TRUE; 532 } 533 534 case IDC_BTN_SYSTEM_DOWN: 535 { 536 TreeView_DownItem(hSystemTree, TreeView_GetSelection(hSystemTree)); 537 PropSheet_Changed(GetParent(hDlg), hDlg); 538 return TRUE; 539 } 540 541 case IDC_BTN_SYSTEM_ENABLE: 542 { 543 HTREEITEM hItem = TreeView_GetSelection(hSystemTree); 544 TreeView_SetBOOLCheck(hSystemTree, hItem, TRUE, TRUE); 545 TreeView_SelectItem(hSystemTree, hItem); 546 Update_Btn_States(hDlg); 547 548 PropSheet_Changed(GetParent(hDlg), hDlg); 549 550 return TRUE; 551 } 552 553 case IDC_BTN_SYSTEM_ENABLE_ALL: 554 { 555 for (HTREEITEM htiIterator = TreeView_GetRoot(hSystemTree) ; htiIterator ; htiIterator = TreeView_GetNextSibling(hSystemTree, htiIterator)) 556 TreeView_SetBOOLCheck(hSystemTree, htiIterator, TRUE, TRUE); 557 558 Update_Btn_States(hDlg); 559 560 PropSheet_Changed(GetParent(hDlg), hDlg); 561 562 return TRUE; 563 } 564 565 case IDC_BTN_SYSTEM_DISABLE: 566 { 567 HTREEITEM hItem = TreeView_GetSelection(hSystemTree); 568 TreeView_SetBOOLCheck(hSystemTree, hItem, FALSE, TRUE); 569 TreeView_SelectItem(hSystemTree, hItem); 570 571 Update_Btn_States(hDlg); 572 573 PropSheet_Changed(GetParent(hDlg), hDlg); 574 575 return TRUE; 576 } 577 578 case IDC_BTN_SYSTEM_DISABLE_ALL: 579 { 580 for (HTREEITEM htiIterator = TreeView_GetRoot(hSystemTree) ; htiIterator ; htiIterator = TreeView_GetNextSibling(hSystemTree, htiIterator)) 581 TreeView_SetBOOLCheck(hSystemTree, htiIterator, FALSE, TRUE); 582 583 Update_Btn_States(hDlg); 584 585 PropSheet_Changed(GetParent(hDlg), hDlg); 586 587 return TRUE; 588 } 589 590 case IDC_BTN_SYSTEM_FIND: 591 { 592 DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_FIND_DIALOG), hDlg /* hMainWnd */, FindDialogWndProc, (LPARAM)hSystemTree); 593 return TRUE; 594 } 595 596 case IDC_BTN_SYSTEM_NEW: 597 { 598 HTREEITEM hInsertAfter = TreeView_GetSelection(hSystemTree); 599 HTREEITEM hNewItem = InsertItem(hSystemTree, L"", TreeView_GetParent(hSystemTree, hInsertAfter), hInsertAfter); 600 TreeView_EditLabel(hSystemTree, hNewItem); 601 TreeView_SelectItem(hSystemTree, hNewItem); 602 603 PropSheet_Changed(GetParent(hDlg), hDlg); 604 605 return TRUE; 606 } 607 608 case IDC_BTN_SYSTEM_EDIT: 609 { 610 TreeView_EditLabel(hSystemTree, TreeView_GetSelection(hSystemTree)); 611 return TRUE; 612 } 613 614 case IDC_BTN_SYSTEM_DELETE: 615 { 616 TreeView_DeleteItem(hSystemTree, TreeView_GetSelection(hSystemTree)); 617 Update_Btn_States(hDlg); 618 PropSheet_Changed(GetParent(hDlg), hDlg); 619 return TRUE; 620 } 621 622 default: 623 return FALSE; 624 } 625 // return FALSE; 626 } 627 628 case UM_CHECKSTATECHANGE: 629 { 630 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 631 632 /* Retrieve the new checked state of the item and handle the notification */ 633 HTREEITEM hItemChanged = (HTREEITEM)lParam; 634 635 // 636 // State before | State after 637 // ------------------------------- 638 // 0 (unchecked) | 1 (checked) 639 // 1 (checked) | 0 (unchecked) 640 // 2 (grayed) | 1 (checked) --> this case corresponds to the former 641 // | with 0 == 2 mod 2. 642 // 643 UINT uiCheckState = TreeView_GetCheckState(hSystemTree, hItemChanged) % 2; 644 TreeView_SetBOOLCheck(hSystemTree, hItemChanged, uiCheckState ? FALSE : TRUE, TRUE); 645 TreeView_SelectItem(hSystemTree, hItemChanged); 646 Update_Btn_States(hDlg); 647 648 PropSheet_Changed(GetParent(hDlg), hDlg); 649 650 return TRUE; 651 } 652 653 case WM_NOTIFY: 654 { 655 if (((LPNMHDR)lParam)->idFrom == IDC_SYSTEM_TREE) 656 { 657 switch (((LPNMHDR)lParam)->code) 658 { 659 case NM_CLICK: 660 { 661 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 662 663 DWORD dwpos = GetMessagePos(); 664 TVHITTESTINFO ht = {}; 665 ht.pt.x = GET_X_LPARAM(dwpos); 666 ht.pt.y = GET_Y_LPARAM(dwpos); 667 MapWindowPoints(HWND_DESKTOP /*NULL*/, hSystemTree, &ht.pt, 1); 668 669 TreeView_HitTest(hSystemTree, &ht); 670 671 if (TVHT_ONITEMSTATEICON & ht.flags) 672 { 673 PostMessage(hDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)ht.hItem); 674 675 // Disable default behaviour. Needed for the UM_CHECKSTATECHANGE 676 // custom notification to work as expected. 677 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); 678 } 679 /* 680 else 681 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); 682 */ 683 684 return TRUE; 685 } 686 687 case TVN_KEYDOWN: 688 { 689 if (((LPNMTVKEYDOWN)lParam)->wVKey == VK_SPACE) 690 { 691 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 692 693 HTREEITEM hti = TreeView_GetSelection(hSystemTree); 694 695 // Hack the tree item state. This is needed because whether or not 696 // TRUE is being returned, the default implementation of SysTreeView32 697 // is always being processed for a key down ! 698 if (GetWindowLongPtr(hSystemTree, GWL_STYLE) & TVS_CHECKBOXES) 699 { 700 TreeView_SetItemState(hSystemTree, hti, INDEXTOSTATEIMAGEMASK(TreeView_GetCheckState(hSystemTree, hti)), TVIS_STATEIMAGEMASK); 701 } 702 703 PostMessage(hDlg, UM_CHECKSTATECHANGE, 0, (LPARAM)hti); 704 705 // Disable default behaviour. Needed for the UM_CHECKSTATECHANGE 706 // custom notification to work as expected. 707 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); 708 } 709 710 return TRUE; 711 } 712 713 case TVN_ENDLABELEDIT: 714 { 715 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 716 717 /* 718 * Ehh yes, we have to deal with a "dialog proc", which is quite different from a "window proc": 719 * 720 * (excerpt from: MSDN library http://msdn.microsoft.com/en-us/library/ms645469(VS.85).aspx) 721 * 722 * Return Value 723 * ============ 724 * INT_PTR 725 * 726 * Typically, the dialog box procedure should return TRUE if it processed the message, and FALSE if it did not. 727 * If the dialog box procedure returns FALSE, the dialog manager performs the default dialog operation in response 728 * to the message. 729 * 730 * If the dialog box procedure processes a message that requires a specific return value, the dialog box procedure 731 * should set the desired return value by calling SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before 732 * returning TRUE. Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may result 733 * in the DWL_MSGRESULT value being overwritten by a nested dialog box message. 734 * 735 * [...] 736 * 737 * Remarks 738 * ======= 739 * You should use the dialog box procedure only if you use the dialog box class for the dialog box. This is the default 740 * class and is used when no explicit class is specified in the dialog box template. Although the dialog box procedure 741 * is similar to a window procedure, it must not call the DefWindowProc function to process unwanted messages. Unwanted 742 * messages are processed internally by the dialog box window procedure. 743 * 744 */ 745 746 // A arranger un peu ???? Certainement. 747 TVITEMW truc = ((LPNMTVDISPINFO)lParam)->item; 748 if (truc.pszText) 749 { 750 if (!*truc.pszText) 751 TreeView_DeleteItem(hSystemTree, truc.hItem); 752 753 PropSheet_Changed(GetParent(hDlg), hDlg); 754 755 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE); 756 } 757 else 758 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); 759 760 Update_Btn_States(hDlg); 761 return TRUE; 762 } 763 764 case TVN_SELCHANGED: 765 Update_Btn_States(hDlg); 766 return TRUE; 767 768 default: 769 return FALSE; 770 } 771 } 772 else 773 { 774 switch (((LPNMHDR)lParam)->code) 775 { 776 case PSN_APPLY: 777 { 778 // TODO: Enum the items. 779 // HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 780 // 781 PropSheet_CancelToClose(GetParent(hDlg)); 782 783 /* TODO: see : 784 * 785 * dll/win32/devmgr/advprop.c: PropSheet_RebootSystem(hwndDlg); 786 * include/psdk/prsht.h:#define PropSheet_RebootSystem(d) SendMessage(d,PSM_REBOOTSYSTEM,0,0) 787 * 788 * dll/shellext/deskadp/deskadp.c: PropSheet_RestartWindows(GetParent(This->hwndDlg)); 789 * dll/shellext/deskmon/deskmon.c: PropSheet_RestartWindows(GetParent(This->hwndDlg)); 790 * include/psdk/prsht.h:#define PropSheet_RestartWindows(d) SendMessage(d,PSM_RESTARTWINDOWS,0,0) 791 * 792 * for their usage. 793 */ 794 PropSheet_RebootSystem(GetParent(hDlg)); 795 //PropSheet_RestartWindows(GetParent(hDlg)); 796 797 WriteIniFile(GetDlgItem(hDlg, IDC_SYSTEM_TREE), (LPCWSTR)wParam); 798 799 // Since there are nothing to modify, applying modifications 800 // cannot return any error. 801 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR); 802 //PropSheet_UnChanged(GetParent(hDlg) /*hMainWnd*/, hDlg); 803 return TRUE; 804 } 805 806 case PSN_HELP: 807 { 808 MessageBox(hDlg, _T("Help not implemented yet!"), _T("Help"), MB_ICONINFORMATION | MB_OK); 809 return TRUE; 810 } 811 812 case PSN_KILLACTIVE: // Is going to lose activation. 813 { 814 // Changes are always valid of course. 815 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); 816 return TRUE; 817 } 818 819 case PSN_QUERYCANCEL: 820 { 821 // Allows cancellation since there are nothing to cancel... 822 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); 823 return TRUE; 824 } 825 826 case PSN_QUERYINITIALFOCUS: 827 { 828 HWND hSystemTree = GetDlgItem(hDlg, IDC_SYSTEM_TREE); 829 830 // Give the focus on and select the first item. 831 ListView_SetItemState(hSystemTree, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 832 833 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR)hSystemTree); 834 return TRUE; 835 } 836 837 // 838 // DO NOT TOUCH THESE NEXT MESSAGES, THEY ARE OK LIKE THIS... 839 // 840 case PSN_RESET: // Perform final cleaning, called before WM_DESTROY. 841 return TRUE; 842 843 case PSN_SETACTIVE: // Is going to gain activation. 844 { 845 SetWindowLongPtr(hDlg, DWLP_MSGRESULT, 0); 846 return TRUE; 847 } 848 849 default: 850 break; 851 } 852 } 853 854 return FALSE; 855 } 856 857 default: 858 return FALSE; 859 } 860 861 // return FALSE; 862 } 863 864 865 extern "C" { 866 867 INT_PTR CALLBACK 868 SystemPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 869 { 870 static LPCWSTR lpszIniFile = NULL; 871 872 if (message == WM_INITDIALOG) 873 lpszIniFile = (LPCWSTR)((LPPROPSHEETPAGE)lParam)->lParam; 874 875 if ( (message == WM_NOTIFY) && (((LPNMHDR)lParam)->code == PSN_APPLY) ) 876 wParam = (WPARAM)lpszIniFile; 877 878 return CommonWndProc(hDlg, message, wParam, lParam); 879 } 880 881 INT_PTR CALLBACK 882 WinPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 883 { 884 static LPCWSTR lpszIniFile = NULL; 885 886 if (message == WM_INITDIALOG) 887 lpszIniFile = (LPCWSTR)((LPPROPSHEETPAGE)lParam)->lParam; 888 889 if ( (message == WM_NOTIFY) && (((LPNMHDR)lParam)->code == PSN_APPLY) ) 890 wParam = (WPARAM)lpszIniFile; 891 892 return CommonWndProc(hDlg, message, wParam, lParam); 893 } 894 895 } 896