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