1 /* 2 * Regedit find dialog 3 * 4 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 5 */ 6 7 #include "regedit.h" 8 9 #define RSF_WHOLESTRING 0x00000001 10 #define RSF_LOOKATKEYS 0x00000002 11 #define RSF_LOOKATVALUES 0x00000004 12 #define RSF_LOOKATDATA 0x00000008 13 #define RSF_MATCHCASE 0x00010000 14 15 static WCHAR s_szFindWhat[256]; 16 static const WCHAR s_szFindFlags[] = L"FindFlags"; 17 static const WCHAR s_szFindFlagsR[] = L"FindFlagsReactOS"; 18 static HWND s_hwndAbortDialog; 19 static BOOL s_bAbort; 20 21 static DWORD s_dwFlags; 22 static WCHAR s_szName[MAX_PATH]; 23 static DWORD s_cchName; 24 static const WCHAR s_empty[] = L""; 25 static const WCHAR s_backslash[] = L"\\"; 26 27 extern VOID SetValueName(HWND hwndLV, LPCWSTR pszValueName); 28 29 BOOL DoEvents(VOID) 30 { 31 MSG msg; 32 if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) 33 { 34 if (msg.message == WM_QUIT) 35 s_bAbort = TRUE; 36 if (!IsDialogMessageW(s_hwndAbortDialog, &msg)) 37 { 38 TranslateMessage(&msg); 39 DispatchMessageW(&msg); 40 } 41 } 42 return s_bAbort; 43 } 44 45 static LPWSTR lstrstri(LPCWSTR psz1, LPCWSTR psz2) 46 { 47 INT i, cch1, cch2; 48 49 cch1 = wcslen(psz1); 50 cch2 = wcslen(psz2); 51 for(i = 0; i <= cch1 - cch2; i++) 52 { 53 if (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, 54 psz1 + i, cch2, psz2, cch2) == 2) 55 return (LPWSTR) (psz1 + i); 56 } 57 return NULL; 58 } 59 60 static BOOL CompareName(LPCWSTR pszName1, LPCWSTR pszName2) 61 { 62 if (s_dwFlags & RSF_WHOLESTRING) 63 { 64 if (s_dwFlags & RSF_MATCHCASE) 65 return wcscmp(pszName1, pszName2) == 0; 66 else 67 return _wcsicmp(pszName1, pszName2) == 0; 68 } 69 else 70 { 71 if (s_dwFlags & RSF_MATCHCASE) 72 return wcsstr(pszName1, pszName2) != NULL; 73 else 74 return lstrstri(pszName1, pszName2) != NULL; 75 } 76 } 77 78 /* Do not assume that pch1 is terminated with UNICODE_NULL */ 79 static BOOL MatchString(LPCWCH pch1, INT cch1, LPCWCH pch2, INT cch2) 80 { 81 INT i; 82 DWORD dwNorm = ((s_dwFlags & RSF_MATCHCASE) ? 0 : NORM_IGNORECASE); 83 84 if (s_dwFlags & RSF_WHOLESTRING) 85 return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT, dwNorm, pch1, cch1, pch2, cch2); 86 87 if (cch1 < cch2) 88 return FALSE; 89 90 for (i = 0; i <= cch1 - cch2; i++) 91 { 92 if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT, dwNorm, pch1 + i, cch2, pch2, cch2)) 93 return TRUE; 94 } 95 96 return FALSE; 97 } 98 99 static BOOL MatchData(DWORD dwType, LPCVOID pv1, DWORD cb1) 100 { 101 if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ) 102 return MatchString(pv1, (INT)(cb1 / sizeof(WCHAR)), s_szFindWhat, lstrlenW(s_szFindWhat)); 103 104 return FALSE; 105 } 106 107 int compare(const void *x, const void *y) 108 { 109 const LPCWSTR *a = (const LPCWSTR *)x; 110 const LPCWSTR *b = (const LPCWSTR *)y; 111 return _wcsicmp(*a, *b); 112 } 113 114 BOOL RegFindRecurse( 115 HKEY hKey, 116 LPCWSTR pszSubKey, 117 LPCWSTR pszValueName, 118 LPWSTR *ppszFoundSubKey, 119 LPWSTR *ppszFoundValueName) 120 { 121 HKEY hSubKey; 122 LONG lResult; 123 WCHAR szSubKey[MAX_PATH]; 124 DWORD i, c, cb, type; 125 BOOL fPast; 126 LPWSTR *ppszNames = NULL; 127 LPBYTE pb = NULL; 128 129 if (DoEvents()) 130 return FALSE; 131 132 if(wcslen(pszSubKey) >= _countof(szSubKey)) 133 return FALSE; 134 135 StringCbCopyW(szSubKey, sizeof(szSubKey), pszSubKey); 136 hSubKey = NULL; 137 138 lResult = RegOpenKeyExW(hKey, szSubKey, 0, KEY_ALL_ACCESS, &hSubKey); 139 if (lResult != ERROR_SUCCESS) 140 return FALSE; 141 142 lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL, 143 &c, NULL, NULL, NULL, NULL); 144 if (lResult != ERROR_SUCCESS) 145 goto err; 146 ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR)); 147 if (ppszNames == NULL) 148 goto err; 149 ZeroMemory(ppszNames, c * sizeof(LPWSTR)); 150 151 /* Retrieve the value names associated with the current key */ 152 for(i = 0; i < c; i++) 153 { 154 if (DoEvents()) 155 goto err; 156 157 s_cchName = _countof(s_szName); 158 lResult = RegEnumValueW(hSubKey, i, s_szName, &s_cchName, NULL, NULL, 159 NULL, &cb); 160 if (lResult == ERROR_NO_MORE_ITEMS) 161 { 162 c = i; 163 break; 164 } 165 if (lResult != ERROR_SUCCESS) 166 goto err; 167 if (s_cchName >= _countof(s_szName)) 168 continue; 169 170 ppszNames[i] = _wcsdup(s_szName); 171 } 172 173 qsort(ppszNames, c, sizeof(LPWSTR), compare); 174 175 /* If pszValueName is NULL, the function will search for all values within the key */ 176 fPast = (pszValueName == NULL); 177 178 /* Search within the values */ 179 for (i = 0; i < c; i++) 180 { 181 if (DoEvents()) 182 goto err; 183 184 if (!fPast && _wcsicmp(ppszNames[i], pszValueName) == 0) 185 { 186 fPast = TRUE; 187 continue; 188 } 189 if (!fPast) 190 continue; 191 192 if ((s_dwFlags & RSF_LOOKATVALUES) && 193 CompareName(ppszNames[i], s_szFindWhat)) 194 { 195 *ppszFoundSubKey = _wcsdup(szSubKey); 196 *ppszFoundValueName = _wcsdup(ppszNames[i]); 197 goto success; 198 } 199 200 lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type, 201 NULL, &cb); 202 if (lResult != ERROR_SUCCESS) 203 goto err; 204 pb = malloc(cb); 205 if (pb == NULL) 206 goto err; 207 lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type, 208 pb, &cb); 209 if (lResult != ERROR_SUCCESS) 210 goto err; 211 212 if ((s_dwFlags & RSF_LOOKATDATA) && MatchData(type, pb, cb)) 213 { 214 *ppszFoundSubKey = _wcsdup(szSubKey); 215 *ppszFoundValueName = _wcsdup(ppszNames[i]); 216 goto success; 217 } 218 free(pb); 219 pb = NULL; 220 } 221 222 if (ppszNames != NULL) 223 { 224 for(i = 0; i < c; i++) 225 free(ppszNames[i]); 226 free(ppszNames); 227 } 228 ppszNames = NULL; 229 230 /* Retrieve the number of sub-keys */ 231 lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL, 232 NULL, NULL, NULL, NULL, NULL); 233 if (lResult != ERROR_SUCCESS) 234 goto err; 235 ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR)); 236 if (ppszNames == NULL) 237 goto err; 238 ZeroMemory(ppszNames, c * sizeof(LPWSTR)); 239 240 /* Retrieve the names of the sub-keys */ 241 for(i = 0; i < c; i++) 242 { 243 if (DoEvents()) 244 goto err; 245 246 s_cchName = _countof(s_szName); 247 lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cchName, NULL, NULL, 248 NULL, NULL); 249 if (lResult == ERROR_NO_MORE_ITEMS) 250 { 251 c = i; 252 break; 253 } 254 if (lResult != ERROR_SUCCESS) 255 goto err; 256 if (s_cchName >= _countof(s_szName)) 257 continue; 258 259 ppszNames[i] = _wcsdup(s_szName); 260 } 261 262 qsort(ppszNames, c, sizeof(LPWSTR), compare); 263 264 /* Search within the sub-keys */ 265 for(i = 0; i < c; i++) 266 { 267 if (DoEvents()) 268 goto err; 269 270 if ((s_dwFlags & RSF_LOOKATKEYS) && 271 CompareName(ppszNames[i], s_szFindWhat)) 272 { 273 *ppszFoundSubKey = malloc( 274 (wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) * 275 sizeof(WCHAR)); 276 if (*ppszFoundSubKey == NULL) 277 goto err; 278 if (szSubKey[0]) 279 { 280 wcscpy(*ppszFoundSubKey, szSubKey); 281 wcscat(*ppszFoundSubKey, s_backslash); 282 } 283 else 284 **ppszFoundSubKey = 0; 285 wcscat(*ppszFoundSubKey, ppszNames[i]); 286 *ppszFoundValueName = NULL; 287 goto success; 288 } 289 290 /* Search within the value entries of the sub-key */ 291 if (RegFindRecurse(hSubKey, ppszNames[i], NULL, ppszFoundSubKey, 292 ppszFoundValueName)) 293 { 294 LPWSTR psz = *ppszFoundSubKey; 295 SIZE_T cbFoundSubKey = (wcslen(szSubKey) + wcslen(psz) + 2) * sizeof(WCHAR); 296 *ppszFoundSubKey = malloc(cbFoundSubKey); 297 if (*ppszFoundSubKey == NULL) 298 goto err; 299 if (szSubKey[0]) 300 { 301 StringCbCopyW(*ppszFoundSubKey, cbFoundSubKey, szSubKey); 302 StringCbCatW(*ppszFoundSubKey, cbFoundSubKey, s_backslash); 303 } 304 else 305 **ppszFoundSubKey = 0; 306 wcscat(*ppszFoundSubKey, psz); 307 free(psz); 308 goto success; 309 } 310 } 311 312 err: 313 if (ppszNames != NULL) 314 { 315 for(i = 0; i < c; i++) 316 free(ppszNames[i]); 317 free(ppszNames); 318 } 319 free(pb); 320 RegCloseKey(hSubKey); 321 return FALSE; 322 323 success: 324 if (ppszNames != NULL) 325 { 326 for(i = 0; i < c; i++) 327 free(ppszNames[i]); 328 free(ppszNames); 329 } 330 RegCloseKey(hSubKey); 331 return TRUE; 332 } 333 334 BOOL RegFindWalk( 335 HKEY * phKey, 336 LPCWSTR pszSubKey, 337 LPCWSTR pszValueName, 338 LPWSTR *ppszFoundSubKey, 339 LPWSTR *ppszFoundValueName) 340 { 341 LONG lResult; 342 DWORD i, c; 343 HKEY hBaseKey, hSubKey; 344 WCHAR szKeyName[MAX_PATH]; 345 WCHAR szSubKey[MAX_PATH]; 346 LPWSTR pch; 347 BOOL fPast, fKeyMatched; 348 LPWSTR *ppszNames = NULL; 349 350 hBaseKey = *phKey; 351 352 if (wcslen(pszSubKey) >= _countof(szSubKey)) 353 return FALSE; 354 355 if (RegFindRecurse(hBaseKey, pszSubKey, pszValueName, ppszFoundSubKey, 356 ppszFoundValueName)) 357 return TRUE; 358 359 StringCbCopyW(szSubKey, sizeof(szSubKey), pszSubKey); 360 while(szSubKey[0] != 0) 361 { 362 if (DoEvents()) 363 return FALSE; 364 365 pch = wcsrchr(szSubKey, L'\\'); 366 if (pch == NULL) 367 { 368 wcscpy(szKeyName, szSubKey); 369 szSubKey[0] = 0; 370 hSubKey = hBaseKey; 371 } 372 else 373 { 374 lstrcpynW(szKeyName, pch + 1, MAX_PATH); 375 *pch = 0; 376 lResult = RegOpenKeyExW(hBaseKey, szSubKey, 0, KEY_ALL_ACCESS, 377 &hSubKey); 378 if (lResult != ERROR_SUCCESS) 379 return FALSE; 380 } 381 382 lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL, 383 NULL, NULL, NULL, NULL, NULL); 384 if (lResult != ERROR_SUCCESS) 385 goto err; 386 387 ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR)); 388 if (ppszNames == NULL) 389 goto err; 390 ZeroMemory(ppszNames, c * sizeof(LPWSTR)); 391 392 for(i = 0; i < c; i++) 393 { 394 if (DoEvents()) 395 goto err; 396 397 s_cchName = _countof(s_szName); 398 lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cchName, 399 NULL, NULL, NULL, NULL); 400 if (lResult == ERROR_NO_MORE_ITEMS) 401 { 402 c = i; 403 break; 404 } 405 if (lResult != ERROR_SUCCESS) 406 break; 407 ppszNames[i] = _wcsdup(s_szName); 408 } 409 410 qsort(ppszNames, c, sizeof(LPWSTR), compare); 411 412 fPast = FALSE; 413 for(i = 0; i < c; i++) 414 { 415 if (DoEvents()) 416 goto err; 417 418 if (!fPast && _wcsicmp(ppszNames[i], szKeyName) == 0) 419 { 420 fPast = TRUE; 421 continue; 422 } 423 if (!fPast) 424 continue; 425 426 if ((s_dwFlags & RSF_LOOKATKEYS) && 427 CompareName(ppszNames[i], s_szFindWhat)) 428 { 429 *ppszFoundSubKey = malloc( 430 (wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) * 431 sizeof(WCHAR)); 432 if (*ppszFoundSubKey == NULL) 433 goto err; 434 if (szSubKey[0]) 435 { 436 wcscpy(*ppszFoundSubKey, szSubKey); 437 wcscat(*ppszFoundSubKey, s_backslash); 438 } 439 else 440 **ppszFoundSubKey = 0; 441 wcscat(*ppszFoundSubKey, ppszNames[i]); 442 *ppszFoundValueName = NULL; 443 goto success; 444 } 445 446 fKeyMatched = (_wcsicmp(ppszNames[i], szKeyName) == 0); 447 if (RegFindRecurse(hSubKey, ppszNames[i], (fKeyMatched ? pszValueName : NULL), 448 ppszFoundSubKey, ppszFoundValueName)) 449 { 450 LPWSTR psz = *ppszFoundSubKey; 451 SIZE_T cbFoundSubKey = (wcslen(szSubKey) + wcslen(psz) + 2) * sizeof(WCHAR); 452 *ppszFoundSubKey = malloc(cbFoundSubKey); 453 if (*ppszFoundSubKey == NULL) 454 goto err; 455 if (szSubKey[0]) 456 { 457 StringCbCopyW(*ppszFoundSubKey, cbFoundSubKey, szSubKey); 458 StringCbCatW(*ppszFoundSubKey, cbFoundSubKey, s_backslash); 459 } 460 else 461 **ppszFoundSubKey = 0; 462 wcscat(*ppszFoundSubKey, psz); 463 free(psz); 464 goto success; 465 } 466 } 467 if (ppszNames != NULL) 468 { 469 for(i = 0; i < c; i++) 470 free(ppszNames[i]); 471 free(ppszNames); 472 } 473 ppszNames = NULL; 474 475 if (hBaseKey != hSubKey) 476 RegCloseKey(hSubKey); 477 } 478 479 if (*phKey == HKEY_CLASSES_ROOT) 480 { 481 *phKey = HKEY_CURRENT_USER; 482 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey, 483 ppszFoundValueName)) 484 return TRUE; 485 } 486 487 if (*phKey == HKEY_CURRENT_USER) 488 { 489 *phKey = HKEY_LOCAL_MACHINE; 490 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey, 491 ppszFoundValueName)) 492 goto success; 493 } 494 495 if (*phKey == HKEY_LOCAL_MACHINE) 496 { 497 *phKey = HKEY_USERS; 498 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey, 499 ppszFoundValueName)) 500 goto success; 501 } 502 503 if (*phKey == HKEY_USERS) 504 { 505 *phKey = HKEY_CURRENT_CONFIG; 506 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey, 507 ppszFoundValueName)) 508 goto success; 509 } 510 511 err: 512 if (ppszNames != NULL) 513 { 514 for(i = 0; i < c; i++) 515 free(ppszNames[i]); 516 free(ppszNames); 517 } 518 if (hBaseKey != hSubKey) 519 RegCloseKey(hSubKey); 520 return FALSE; 521 522 success: 523 if (ppszNames != NULL) 524 { 525 for(i = 0; i < c; i++) 526 free(ppszNames[i]); 527 free(ppszNames); 528 } 529 if (hBaseKey != hSubKey) 530 RegCloseKey(hSubKey); 531 return TRUE; 532 } 533 534 static DWORD GetFindFlags(void) 535 { 536 HKEY hKey; 537 DWORD dwType, dwValue, cbData; 538 DWORD dwFlags = RSF_LOOKATKEYS | RSF_LOOKATVALUES | RSF_LOOKATDATA; 539 540 if (RegOpenKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS) 541 { 542 /* Retrieve flags from registry key */ 543 cbData = sizeof(dwValue); 544 if (RegQueryValueExW(hKey, s_szFindFlags, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS) 545 { 546 if (dwType == REG_DWORD) 547 dwFlags = (dwFlags & ~0x0000FFFF) | ((dwValue & 0x0000FFFF) << 0); 548 } 549 550 /* Retrieve ReactOS Regedit specific flags from registry key */ 551 cbData = sizeof(dwValue); 552 if (RegQueryValueExW(hKey, s_szFindFlagsR, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS) 553 { 554 if (dwType == REG_DWORD) 555 dwFlags = (dwFlags & ~0xFFFF0000) | ((dwValue & 0x0000FFFF) << 16); 556 } 557 558 RegCloseKey(hKey); 559 } 560 return dwFlags; 561 } 562 563 static void SetFindFlags(DWORD dwFlags) 564 { 565 HKEY hKey; 566 DWORD dwDisposition; 567 DWORD dwData; 568 569 if (RegCreateKeyExW(HKEY_CURRENT_USER, g_szGeneralRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) 570 { 571 dwData = (dwFlags >> 0) & 0x0000FFFF; 572 RegSetValueExW(hKey, s_szFindFlags, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData)); 573 574 dwData = (dwFlags >> 16) & 0x0000FFFF; 575 RegSetValueExW(hKey, s_szFindFlagsR, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData)); 576 577 RegCloseKey(hKey); 578 } 579 } 580 581 static INT_PTR CALLBACK AbortFindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 582 { 583 UNREFERENCED_PARAMETER(lParam); 584 UNREFERENCED_PARAMETER(hDlg); 585 586 switch(uMsg) 587 { 588 case WM_CLOSE: 589 s_bAbort = TRUE; 590 break; 591 592 case WM_COMMAND: 593 switch(HIWORD(wParam)) 594 { 595 case BN_CLICKED: 596 switch(LOWORD(wParam)) 597 { 598 case IDCANCEL: 599 s_bAbort = TRUE; 600 break; 601 } 602 break; 603 } 604 break; 605 } 606 return 0; 607 } 608 609 BOOL FindNext(HWND hWnd) 610 { 611 HKEY hKeyRoot; 612 LPCWSTR pszKeyPath; 613 BOOL fSuccess; 614 WCHAR szFullKey[512]; 615 LPCWSTR pszValueName; 616 LPWSTR pszFoundSubKey, pszFoundValueName; 617 618 if (wcslen(s_szFindWhat) == 0) 619 { 620 FindDialog(hWnd); 621 return TRUE; 622 } 623 624 s_dwFlags = GetFindFlags(); 625 626 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot); 627 if (pszKeyPath == NULL) 628 { 629 hKeyRoot = HKEY_CLASSES_ROOT; 630 pszKeyPath = s_empty; 631 } 632 633 /* Create abort find dialog */ 634 s_hwndAbortDialog = CreateDialogW(GetModuleHandle(NULL), 635 MAKEINTRESOURCEW(IDD_FINDING), hWnd, AbortFindDialogProc); 636 if (s_hwndAbortDialog) 637 { 638 ShowWindow(s_hwndAbortDialog, SW_SHOW); 639 UpdateWindow(s_hwndAbortDialog); 640 } 641 s_bAbort = FALSE; 642 643 pszValueName = GetValueName(g_pChildWnd->hListWnd, -1); 644 645 EnableWindow(hFrameWnd, FALSE); 646 EnableWindow(g_pChildWnd->hTreeWnd, FALSE); 647 EnableWindow(g_pChildWnd->hListWnd, FALSE); 648 EnableWindow(g_pChildWnd->hAddressBarWnd, FALSE); 649 650 fSuccess = RegFindWalk(&hKeyRoot, pszKeyPath, pszValueName, 651 &pszFoundSubKey, &pszFoundValueName); 652 653 EnableWindow(hFrameWnd, TRUE); 654 EnableWindow(g_pChildWnd->hTreeWnd, TRUE); 655 EnableWindow(g_pChildWnd->hListWnd, TRUE); 656 EnableWindow(g_pChildWnd->hAddressBarWnd, TRUE); 657 658 if (s_hwndAbortDialog) 659 { 660 DestroyWindow(s_hwndAbortDialog); 661 s_hwndAbortDialog = NULL; 662 } 663 664 if (fSuccess) 665 { 666 GetKeyName(szFullKey, ARRAY_SIZE(szFullKey), hKeyRoot, pszFoundSubKey); 667 SelectNode(g_pChildWnd->hTreeWnd, szFullKey); 668 free(pszFoundSubKey); 669 670 if (pszFoundValueName != NULL) 671 { 672 SetValueName(g_pChildWnd->hListWnd, pszFoundValueName); 673 free(pszFoundValueName); 674 SetFocus(g_pChildWnd->hListWnd); 675 } 676 else 677 { 678 SetFocus(g_pChildWnd->hTreeWnd); 679 } 680 } 681 return fSuccess || s_bAbort; 682 } 683 684 static INT_PTR CALLBACK FindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 685 { 686 INT_PTR iResult = 0; 687 HWND hControl; 688 LONG lStyle; 689 DWORD dwFlags; 690 static WCHAR s_szSavedFindValue[256]; 691 692 switch(uMsg) 693 { 694 case WM_INITDIALOG: 695 dwFlags = GetFindFlags(); 696 697 hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS); 698 if (hControl) 699 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATKEYS) ? TRUE : FALSE, 0); 700 701 hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES); 702 if (hControl) 703 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATVALUES) ? TRUE : FALSE, 0); 704 705 hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA); 706 if (hControl) 707 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATDATA) ? TRUE : FALSE, 0); 708 709 /* Match whole string */ 710 hControl = GetDlgItem(hDlg, IDC_MATCHSTRING); 711 if (hControl) 712 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_WHOLESTRING) ? TRUE : FALSE, 0); 713 714 /* Case sensitivity */ 715 hControl = GetDlgItem(hDlg, IDC_MATCHCASE); 716 if (hControl) 717 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_MATCHCASE) ? TRUE : FALSE, 0); 718 719 hControl = GetDlgItem(hDlg, IDC_FINDWHAT); 720 if (hControl) 721 { 722 SetWindowTextW(hControl, s_szSavedFindValue); 723 SetFocus(hControl); 724 SendMessageW(hControl, EM_SETSEL, 0, -1); 725 } 726 break; 727 728 case WM_CLOSE: 729 EndDialog(hDlg, 0); 730 break; 731 732 case WM_COMMAND: 733 switch(HIWORD(wParam)) 734 { 735 case BN_CLICKED: 736 switch(LOWORD(wParam)) 737 { 738 case IDOK: 739 dwFlags = 0; 740 741 hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS); 742 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED)) 743 dwFlags |= RSF_LOOKATKEYS; 744 745 hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES); 746 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED)) 747 dwFlags |= RSF_LOOKATVALUES; 748 749 hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA); 750 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED)) 751 dwFlags |= RSF_LOOKATDATA; 752 753 hControl = GetDlgItem(hDlg, IDC_MATCHSTRING); 754 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED)) 755 dwFlags |= RSF_WHOLESTRING; 756 757 hControl = GetDlgItem(hDlg, IDC_MATCHCASE); 758 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED)) 759 dwFlags |= RSF_MATCHCASE; 760 761 SetFindFlags(dwFlags); 762 763 hControl = GetDlgItem(hDlg, IDC_FINDWHAT); 764 if (hControl) 765 GetWindowTextW(hControl, s_szFindWhat, ARRAY_SIZE(s_szFindWhat)); 766 EndDialog(hDlg, 1); 767 break; 768 769 case IDCANCEL: 770 EndDialog(hDlg, 0); 771 break; 772 } 773 break; 774 775 case EN_CHANGE: 776 switch(LOWORD(wParam)) 777 { 778 case IDC_FINDWHAT: 779 GetWindowTextW((HWND) lParam, s_szSavedFindValue, ARRAY_SIZE(s_szSavedFindValue)); 780 hControl = GetDlgItem(hDlg, IDOK); 781 if (hControl) 782 { 783 lStyle = GetWindowLongPtr(hControl, GWL_STYLE); 784 if (s_szSavedFindValue[0]) 785 lStyle &= ~WS_DISABLED; 786 else 787 lStyle |= WS_DISABLED; 788 SetWindowLongPtr(hControl, GWL_STYLE, lStyle); 789 RedrawWindow(hControl, NULL, NULL, RDW_INVALIDATE); 790 } 791 break; 792 } 793 } 794 break; 795 } 796 return iResult; 797 } 798 799 void FindNextMessageBox(HWND hWnd) 800 { 801 if (!FindNext(hWnd)) 802 { 803 WCHAR msg[128], caption[128]; 804 805 LoadStringW(hInst, IDS_FINISHEDFIND, msg, ARRAY_SIZE(msg)); 806 LoadStringW(hInst, IDS_APP_TITLE, caption, ARRAY_SIZE(caption)); 807 MessageBoxW(hWnd, msg, caption, MB_ICONINFORMATION); 808 } 809 } 810 811 void FindDialog(HWND hWnd) 812 { 813 if (DialogBoxParamW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_FIND), 814 hWnd, FindDialogProc, 0) != 0) 815 { 816 FindNextMessageBox(hWnd); 817 } 818 } 819