4b9e4cda621c63c3ee44d5ed6e4f8f4b940c2010
[reactos.git] / reactos / 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_cbName;
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 wcscpy(szSubKey, pszSubKey);
154 hSubKey = NULL;
155
156 lResult = RegOpenKeyExW(hKey, szSubKey, 0, KEY_ALL_ACCESS, &hSubKey);
157 if (lResult != ERROR_SUCCESS)
158 return FALSE;
159
160 if (pszValueName == NULL)
161 pszValueName = s_empty;
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_cbName = MAX_PATH * sizeof(WCHAR);
178 lResult = RegEnumValueW(hSubKey, i, s_szName, &s_cbName, 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_cbName >= MAX_PATH * sizeof(WCHAR))
188 continue;
189
190 ppszNames[i] = _wcsdup(s_szName);
191 }
192
193 qsort(ppszNames, c, sizeof(LPWSTR), compare);
194
195 for(i = 0; i < c; i++)
196 {
197 if (DoEvents())
198 goto err;
199
200 if (!fPast && _wcsicmp(ppszNames[i], pszValueName) == 0)
201 {
202 fPast = TRUE;
203 continue;
204 }
205 if (!fPast)
206 continue;
207
208 if ((s_dwFlags & RSF_LOOKATVALUES) &&
209 CompareName(ppszNames[i], s_szFindWhat))
210 {
211 *ppszFoundSubKey = _wcsdup(szSubKey);
212 if (ppszNames[i][0] == 0)
213 *ppszFoundValueName = NULL;
214 else
215 *ppszFoundValueName = _wcsdup(ppszNames[i]);
216 goto success;
217 }
218
219 lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type,
220 NULL, &cb);
221 if (lResult != ERROR_SUCCESS)
222 goto err;
223 pb = malloc(cb);
224 if (pb == NULL)
225 goto err;
226 lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type,
227 pb, &cb);
228 if (lResult != ERROR_SUCCESS)
229 goto err;
230
231 if ((s_dwFlags & RSF_LOOKATDATA) &&
232 CompareData(type, (LPWSTR) pb, s_szFindWhat))
233 {
234 *ppszFoundSubKey = _wcsdup(szSubKey);
235 if (ppszNames[i][0] == 0)
236 *ppszFoundValueName = NULL;
237 else
238 *ppszFoundValueName = _wcsdup(ppszNames[i]);
239 goto success;
240 }
241 free(pb);
242 pb = NULL;
243 }
244
245 if (ppszNames != NULL)
246 {
247 for(i = 0; i < c; i++)
248 free(ppszNames[i]);
249 free(ppszNames);
250 }
251 ppszNames = NULL;
252
253 lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL,
254 NULL, NULL, NULL, NULL, NULL);
255 if (lResult != ERROR_SUCCESS)
256 goto err;
257 ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR));
258 if (ppszNames == NULL)
259 goto err;
260 ZeroMemory(ppszNames, c * sizeof(LPWSTR));
261
262 for(i = 0; i < c; i++)
263 {
264 if (DoEvents())
265 goto err;
266
267 s_cbName = MAX_PATH * sizeof(WCHAR);
268 lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cbName, NULL, NULL,
269 NULL, NULL);
270 if (lResult == ERROR_NO_MORE_ITEMS)
271 {
272 c = i;
273 break;
274 }
275 if (lResult != ERROR_SUCCESS)
276 goto err;
277 if (s_cbName >= MAX_PATH * sizeof(WCHAR))
278 continue;
279
280 ppszNames[i] = _wcsdup(s_szName);
281 }
282
283 qsort(ppszNames, c, sizeof(LPWSTR), compare);
284
285 for(i = 0; i < c; i++)
286 {
287 if (DoEvents())
288 goto err;
289
290 if ((s_dwFlags & RSF_LOOKATKEYS) &&
291 CompareName(ppszNames[i], s_szFindWhat))
292 {
293 *ppszFoundSubKey = malloc(
294 (wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) *
295 sizeof(WCHAR));
296 if (*ppszFoundSubKey == NULL)
297 goto err;
298 if (szSubKey[0])
299 {
300 wcscpy(*ppszFoundSubKey, szSubKey);
301 wcscat(*ppszFoundSubKey, s_backslash);
302 }
303 else
304 **ppszFoundSubKey = 0;
305 wcscat(*ppszFoundSubKey, ppszNames[i]);
306 *ppszFoundValueName = NULL;
307 goto success;
308 }
309
310 if (RegFindRecurse(hSubKey, ppszNames[i], NULL, ppszFoundSubKey,
311 ppszFoundValueName))
312 {
313 LPWSTR psz = *ppszFoundSubKey;
314 *ppszFoundSubKey = malloc(
315 (wcslen(szSubKey) + wcslen(psz) + 2) * sizeof(WCHAR));
316 if (*ppszFoundSubKey == NULL)
317 goto err;
318 if (szSubKey[0])
319 {
320 wcscpy(*ppszFoundSubKey, szSubKey);
321 wcscat(*ppszFoundSubKey, s_backslash);
322 }
323 else
324 **ppszFoundSubKey = 0;
325 wcscat(*ppszFoundSubKey, psz);
326 free(psz);
327 goto success;
328 }
329 }
330
331 err:
332 if (ppszNames != NULL)
333 {
334 for(i = 0; i < c; i++)
335 free(ppszNames[i]);
336 free(ppszNames);
337 }
338 free(pb);
339 RegCloseKey(hSubKey);
340 return FALSE;
341
342 success:
343 if (ppszNames != NULL)
344 {
345 for(i = 0; i < c; i++)
346 free(ppszNames[i]);
347 free(ppszNames);
348 }
349 RegCloseKey(hSubKey);
350 return TRUE;
351 }
352
353 BOOL RegFindWalk(
354 HKEY * phKey,
355 LPCWSTR pszSubKey,
356 LPCWSTR pszValueName,
357 LPWSTR *ppszFoundSubKey,
358 LPWSTR *ppszFoundValueName)
359 {
360 LONG lResult;
361 DWORD i, c;
362 HKEY hBaseKey, hSubKey;
363 WCHAR szKeyName[MAX_PATH];
364 WCHAR szSubKey[MAX_PATH];
365 LPWSTR pch;
366 BOOL fPast;
367 LPWSTR *ppszNames = NULL;
368
369 hBaseKey = *phKey;
370 if (RegFindRecurse(hBaseKey, pszSubKey, pszValueName, ppszFoundSubKey,
371 ppszFoundValueName))
372 return TRUE;
373
374 if (wcslen(pszSubKey) >= MAX_PATH)
375 return FALSE;
376
377 wcscpy(szSubKey, pszSubKey);
378 while(szSubKey[0] != 0)
379 {
380 if (DoEvents())
381 return FALSE;
382
383 pch = wcsrchr(szSubKey, L'\\');
384 if (pch == NULL)
385 {
386 wcscpy(szKeyName, szSubKey);
387 szSubKey[0] = 0;
388 hSubKey = hBaseKey;
389 }
390 else
391 {
392 lstrcpynW(szKeyName, pch + 1, MAX_PATH);
393 *pch = 0;
394 lResult = RegOpenKeyExW(hBaseKey, szSubKey, 0, KEY_ALL_ACCESS,
395 &hSubKey);
396 if (lResult != ERROR_SUCCESS)
397 return FALSE;
398 }
399
400 lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL,
401 NULL, NULL, NULL, NULL, NULL);
402 if (lResult != ERROR_SUCCESS)
403 goto err;
404
405 ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR));
406 if (ppszNames == NULL)
407 goto err;
408 ZeroMemory(ppszNames, c * sizeof(LPWSTR));
409
410 for(i = 0; i < c; i++)
411 {
412 if (DoEvents())
413 goto err;
414
415 s_cbName = MAX_PATH * sizeof(WCHAR);
416 lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cbName,
417 NULL, NULL, NULL, NULL);
418 if (lResult == ERROR_NO_MORE_ITEMS)
419 {
420 c = i;
421 break;
422 }
423 if (lResult != ERROR_SUCCESS)
424 break;
425 ppszNames[i] = _wcsdup(s_szName);
426 }
427
428 qsort(ppszNames, c, sizeof(LPWSTR), compare);
429
430 fPast = FALSE;
431 for(i = 0; i < c; i++)
432 {
433 if (DoEvents())
434 goto err;
435
436 if (!fPast && _wcsicmp(ppszNames[i], szKeyName) == 0)
437 {
438 fPast = TRUE;
439 continue;
440 }
441 if (!fPast)
442 continue;
443
444 if ((s_dwFlags & RSF_LOOKATKEYS) &&
445 CompareName(ppszNames[i], s_szFindWhat))
446 {
447 *ppszFoundSubKey = malloc(
448 (wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) *
449 sizeof(WCHAR));
450 if (*ppszFoundSubKey == NULL)
451 goto err;
452 if (szSubKey[0])
453 {
454 wcscpy(*ppszFoundSubKey, szSubKey);
455 wcscat(*ppszFoundSubKey, s_backslash);
456 }
457 else
458 **ppszFoundSubKey = 0;
459 wcscat(*ppszFoundSubKey, ppszNames[i]);
460 *ppszFoundValueName = NULL;
461 goto success;
462 }
463
464 if (RegFindRecurse(hSubKey, ppszNames[i], NULL,
465 ppszFoundSubKey, ppszFoundValueName))
466 {
467 LPWSTR psz = *ppszFoundSubKey;
468 *ppszFoundSubKey = malloc(
469 (wcslen(szSubKey) + wcslen(psz) + 2) *
470 sizeof(WCHAR));
471 if (*ppszFoundSubKey == NULL)
472 goto err;
473 if (szSubKey[0])
474 {
475 wcscpy(*ppszFoundSubKey, szSubKey);
476 wcscat(*ppszFoundSubKey, s_backslash);
477 }
478 else
479 **ppszFoundSubKey = 0;
480 wcscat(*ppszFoundSubKey, psz);
481 free(psz);
482 goto success;
483 }
484 }
485 if (ppszNames != NULL)
486 {
487 for(i = 0; i < c; i++)
488 free(ppszNames[i]);
489 free(ppszNames);
490 }
491 ppszNames = NULL;
492
493 if (hBaseKey != hSubKey)
494 RegCloseKey(hSubKey);
495 }
496
497 if (*phKey == HKEY_CLASSES_ROOT)
498 {
499 *phKey = HKEY_CURRENT_USER;
500 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
501 ppszFoundValueName))
502 return TRUE;
503 }
504
505 if (*phKey == HKEY_CURRENT_USER)
506 {
507 *phKey = HKEY_LOCAL_MACHINE;
508 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
509 ppszFoundValueName))
510 goto success;
511 }
512
513 if (*phKey == HKEY_LOCAL_MACHINE)
514 {
515 *phKey = HKEY_USERS;
516 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
517 ppszFoundValueName))
518 goto success;
519 }
520
521 if (*phKey == HKEY_USERS)
522 {
523 *phKey = HKEY_CURRENT_CONFIG;
524 if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
525 ppszFoundValueName))
526 goto success;
527 }
528
529 err:
530 if (ppszNames != NULL)
531 {
532 for(i = 0; i < c; i++)
533 free(ppszNames[i]);
534 free(ppszNames);
535 }
536 if (hBaseKey != hSubKey)
537 RegCloseKey(hSubKey);
538 return FALSE;
539
540 success:
541 if (ppszNames != NULL)
542 {
543 for(i = 0; i < c; i++)
544 free(ppszNames[i]);
545 free(ppszNames);
546 }
547 if (hBaseKey != hSubKey)
548 RegCloseKey(hSubKey);
549 return TRUE;
550 }
551
552
553 static DWORD GetFindFlags(void)
554 {
555 HKEY hKey;
556 DWORD dwType, dwValue, cbData;
557 DWORD dwFlags = RSF_LOOKATKEYS | RSF_LOOKATVALUES | RSF_LOOKATDATA;
558
559 if (RegOpenKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
560 {
561 /* Retrieve flags from registry key */
562 cbData = sizeof(dwValue);
563 if (RegQueryValueExW(hKey, s_szFindFlags, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS)
564 {
565 if (dwType == REG_DWORD)
566 dwFlags = (dwFlags & ~0x0000FFFF) | ((dwValue & 0x0000FFFF) << 0);
567 }
568
569 /* Retrieve ReactOS Regedit specific flags from registry key */
570 cbData = sizeof(dwValue);
571 if (RegQueryValueExW(hKey, s_szFindFlagsR, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS)
572 {
573 if (dwType == REG_DWORD)
574 dwFlags = (dwFlags & ~0xFFFF0000) | ((dwValue & 0x0000FFFF) << 16);
575 }
576
577 RegCloseKey(hKey);
578 }
579 return dwFlags;
580 }
581
582 static void SetFindFlags(DWORD dwFlags)
583 {
584 HKEY hKey;
585 DWORD dwDisposition;
586 DWORD dwData;
587
588 if (RegCreateKeyExW(HKEY_CURRENT_USER, g_szGeneralRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS)
589 {
590 dwData = (dwFlags >> 0) & 0x0000FFFF;
591 RegSetValueExW(hKey, s_szFindFlags, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData));
592
593 dwData = (dwFlags >> 16) & 0x0000FFFF;
594 RegSetValueExW(hKey, s_szFindFlagsR, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData));
595
596 RegCloseKey(hKey);
597 }
598 }
599
600 static INT_PTR CALLBACK AbortFindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
601 {
602 UNREFERENCED_PARAMETER(lParam);
603 UNREFERENCED_PARAMETER(hDlg);
604
605 switch(uMsg)
606 {
607 case WM_CLOSE:
608 s_bAbort = TRUE;
609 break;
610
611 case WM_COMMAND:
612 switch(HIWORD(wParam))
613 {
614 case BN_CLICKED:
615 switch(LOWORD(wParam))
616 {
617 case IDCANCEL:
618 s_bAbort = TRUE;
619 break;
620 }
621 break;
622 }
623 break;
624 }
625 return 0;
626 }
627
628 BOOL FindNext(HWND hWnd)
629 {
630 HKEY hKeyRoot;
631 LPCWSTR pszKeyPath;
632 BOOL fSuccess;
633 WCHAR szFullKey[512];
634 LPCWSTR pszValueName;
635 LPWSTR pszFoundSubKey, pszFoundValueName;
636
637 if (wcslen(s_szFindWhat) == 0)
638 {
639 FindDialog(hWnd);
640 return TRUE;
641 }
642
643 s_dwFlags = GetFindFlags();
644
645 pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
646 if (pszKeyPath == NULL)
647 {
648 hKeyRoot = HKEY_CLASSES_ROOT;
649 pszKeyPath = s_empty;
650 }
651
652 /* Create abort find dialog */
653 s_hwndAbortDialog = CreateDialogW(GetModuleHandle(NULL),
654 MAKEINTRESOURCEW(IDD_FINDING), hWnd, AbortFindDialogProc);
655 if (s_hwndAbortDialog)
656 {
657 ShowWindow(s_hwndAbortDialog, SW_SHOW);
658 UpdateWindow(s_hwndAbortDialog);
659 }
660 s_bAbort = FALSE;
661
662 pszValueName = GetValueName(g_pChildWnd->hListWnd, -1);
663
664 EnableWindow(hFrameWnd, FALSE);
665 EnableWindow(g_pChildWnd->hTreeWnd, FALSE);
666 EnableWindow(g_pChildWnd->hListWnd, FALSE);
667 EnableWindow(g_pChildWnd->hAddressBarWnd, FALSE);
668
669 fSuccess = RegFindWalk(&hKeyRoot, pszKeyPath, pszValueName,
670 &pszFoundSubKey, &pszFoundValueName);
671
672 EnableWindow(hFrameWnd, TRUE);
673 EnableWindow(g_pChildWnd->hTreeWnd, TRUE);
674 EnableWindow(g_pChildWnd->hListWnd, TRUE);
675 EnableWindow(g_pChildWnd->hAddressBarWnd, TRUE);
676
677 if (s_hwndAbortDialog)
678 {
679 DestroyWindow(s_hwndAbortDialog);
680 s_hwndAbortDialog = NULL;
681 }
682
683 if (fSuccess)
684 {
685 GetKeyName(szFullKey, COUNT_OF(szFullKey), hKeyRoot, pszFoundSubKey);
686 SelectNode(g_pChildWnd->hTreeWnd, szFullKey);
687 SetValueName(g_pChildWnd->hListWnd, pszFoundValueName);
688 free(pszFoundSubKey);
689 free(pszFoundValueName);
690 SetFocus(g_pChildWnd->hListWnd);
691 }
692 return fSuccess || s_bAbort;
693 }
694
695 static INT_PTR CALLBACK FindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
696 {
697 INT_PTR iResult = 0;
698 HWND hControl;
699 LONG lStyle;
700 DWORD dwFlags;
701 static WCHAR s_szSavedFindValue[256];
702
703 switch(uMsg)
704 {
705 case WM_INITDIALOG:
706 dwFlags = GetFindFlags();
707
708 hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS);
709 if (hControl)
710 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATKEYS) ? TRUE : FALSE, 0);
711
712 hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
713 if (hControl)
714 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATVALUES) ? TRUE : FALSE, 0);
715
716 hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
717 if (hControl)
718 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATDATA) ? TRUE : FALSE, 0);
719
720 /* Match whole string */
721 hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
722 if (hControl)
723 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_WHOLESTRING) ? TRUE : FALSE, 0);
724
725 /* Case sensitivity */
726 hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
727 if (hControl)
728 SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_MATCHCASE) ? TRUE : FALSE, 0);
729
730 hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
731 if (hControl)
732 {
733 SetWindowTextW(hControl, s_szSavedFindValue);
734 SetFocus(hControl);
735 SendMessageW(hControl, EM_SETSEL, 0, -1);
736 }
737 break;
738
739 case WM_CLOSE:
740 EndDialog(hDlg, 0);
741 break;
742
743 case WM_COMMAND:
744 switch(HIWORD(wParam))
745 {
746 case BN_CLICKED:
747 switch(LOWORD(wParam))
748 {
749 case IDOK:
750 dwFlags = 0;
751
752 hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS);
753 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
754 dwFlags |= RSF_LOOKATKEYS;
755
756 hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
757 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
758 dwFlags |= RSF_LOOKATVALUES;
759
760 hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
761 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
762 dwFlags |= RSF_LOOKATDATA;
763
764 hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
765 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
766 dwFlags |= RSF_WHOLESTRING;
767
768 hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
769 if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
770 dwFlags |= RSF_MATCHCASE;
771
772 SetFindFlags(dwFlags);
773
774 hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
775 if (hControl)
776 GetWindowTextW(hControl, s_szFindWhat, COUNT_OF(s_szFindWhat));
777 EndDialog(hDlg, 1);
778 break;
779
780 case IDCANCEL:
781 EndDialog(hDlg, 0);
782 break;
783 }
784 break;
785
786 case EN_CHANGE:
787 switch(LOWORD(wParam))
788 {
789 case IDC_FINDWHAT:
790 GetWindowTextW((HWND) lParam, s_szSavedFindValue, COUNT_OF(s_szSavedFindValue));
791 hControl = GetDlgItem(hDlg, IDOK);
792 if (hControl)
793 {
794 lStyle = GetWindowLongPtr(hControl, GWL_STYLE);
795 if (s_szSavedFindValue[0])
796 lStyle &= ~WS_DISABLED;
797 else
798 lStyle |= WS_DISABLED;
799 SetWindowLongPtr(hControl, GWL_STYLE, lStyle);
800 RedrawWindow(hControl, NULL, NULL, RDW_INVALIDATE);
801 }
802 break;
803 }
804 }
805 break;
806 }
807 return iResult;
808 }
809
810 void FindDialog(HWND hWnd)
811 {
812 if (DialogBoxParamW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_FIND),
813 hWnd, FindDialogProc, 0) != 0)
814 {
815 if (!FindNext(hWnd))
816 {
817 WCHAR msg[128], caption[128];
818
819 LoadStringW(hInst, IDS_FINISHEDFIND, msg, COUNT_OF(msg));
820 LoadStringW(hInst, IDS_APP_TITLE, caption, COUNT_OF(caption));
821 MessageBoxW(0, msg, caption, MB_ICONINFORMATION);
822 }
823 }
824 }