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