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.
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.
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
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
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
;
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
"\\";
40 extern VOID
SetValueName(HWND hwndLV
, LPCWSTR pszValueName
);
45 if (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
47 if (msg
.message
== WM_QUIT
)
49 if (!IsDialogMessageW(s_hwndAbortDialog
, &msg
))
51 TranslateMessage(&msg
);
52 DispatchMessageW(&msg
);
58 static LPWSTR
lstrstri(LPCWSTR psz1
, LPCWSTR psz2
)
64 for(i
= 0; i
<= cch1
- cch2
; i
++)
66 if (CompareStringW(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
,
67 psz1
+ i
, cch2
, psz2
, cch2
) == 2)
68 return (LPWSTR
) (psz1
+ i
);
73 static BOOL
CompareName(LPCWSTR pszName1
, LPCWSTR pszName2
)
75 if (s_dwFlags
& RSF_WHOLESTRING
)
77 if (s_dwFlags
& RSF_MATCHCASE
)
78 return wcscmp(pszName1
, pszName2
) == 0;
80 return wcsicmp(pszName1
, pszName2
) == 0;
84 if (s_dwFlags
& RSF_MATCHCASE
)
85 return wcsstr(pszName1
, pszName2
) != NULL
;
87 return lstrstri(pszName1
, pszName2
) != NULL
;
97 INT i
, cch1
= wcslen(psz1
), cch2
= wcslen(psz2
);
98 if (dwType
== REG_SZ
|| dwType
== REG_EXPAND_SZ
)
100 if (s_dwFlags
& RSF_WHOLESTRING
)
102 if (s_dwFlags
& RSF_MATCHCASE
)
103 return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
, 0,
104 psz1
, cch1
, psz2
, cch2
);
106 return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
,
107 NORM_IGNORECASE
, psz1
, cch1
, psz2
, cch2
);
110 for(i
= 0; i
<= cch1
- cch2
; i
++)
112 if (s_dwFlags
& RSF_MATCHCASE
)
114 if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
, 0,
115 psz1
+ i
, cch2
, psz2
, cch2
))
120 if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
,
121 NORM_IGNORECASE
, psz1
+ i
, cch2
, psz2
, cch2
))
129 int compare(const void *x
, const void *y
)
131 const LPCWSTR
*a
= (const LPCWSTR
*)x
;
132 const LPCWSTR
*b
= (const LPCWSTR
*)y
;
133 return wcsicmp(*a
, *b
);
139 LPCWSTR pszValueName
,
140 LPWSTR
*ppszFoundSubKey
,
141 LPWSTR
*ppszFoundValueName
)
145 WCHAR szSubKey
[MAX_PATH
];
146 DWORD i
, c
, cb
, type
;
148 LPWSTR
*ppszNames
= NULL
;
154 wcscpy(szSubKey
, pszSubKey
);
157 lResult
= RegOpenKeyExW(hKey
, szSubKey
, 0, KEY_ALL_ACCESS
, &hSubKey
);
158 if (lResult
!= ERROR_SUCCESS
)
161 if (pszValueName
== NULL
)
162 pszValueName
= s_empty
;
164 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
165 &c
, NULL
, NULL
, NULL
, NULL
);
166 if (lResult
!= ERROR_SUCCESS
)
168 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
169 if (ppszNames
== NULL
)
171 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
173 for(i
= 0; i
< c
; i
++)
178 s_cbName
= MAX_PATH
* sizeof(WCHAR
);
179 lResult
= RegEnumValueW(hSubKey
, i
, s_szName
, &s_cbName
, NULL
, NULL
,
181 if (lResult
== ERROR_NO_MORE_ITEMS
)
186 if (lResult
!= ERROR_SUCCESS
)
188 if (s_cbName
>= MAX_PATH
* sizeof(WCHAR
))
191 ppszNames
[i
] = _wcsdup(s_szName
);
194 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
196 for(i
= 0; i
< c
; i
++)
201 if (!fPast
&& wcsicmp(ppszNames
[i
], pszValueName
) == 0)
209 if ((s_dwFlags
& RSF_LOOKATVALUES
) &&
210 CompareName(ppszNames
[i
], s_szFindWhat
))
212 *ppszFoundSubKey
= _wcsdup(szSubKey
);
213 if (ppszNames
[i
][0] == 0)
214 *ppszFoundValueName
= NULL
;
216 *ppszFoundValueName
= _wcsdup(ppszNames
[i
]);
220 lResult
= RegQueryValueExW(hSubKey
, ppszNames
[i
], NULL
, &type
,
222 if (lResult
!= ERROR_SUCCESS
)
227 lResult
= RegQueryValueExW(hSubKey
, ppszNames
[i
], NULL
, &type
,
229 if (lResult
!= ERROR_SUCCESS
)
232 if ((s_dwFlags
& RSF_LOOKATDATA
) &&
233 CompareData(type
, (LPWSTR
) pb
, s_szFindWhat
))
235 *ppszFoundSubKey
= _wcsdup(szSubKey
);
236 if (ppszNames
[i
][0] == 0)
237 *ppszFoundValueName
= NULL
;
239 *ppszFoundValueName
= _wcsdup(ppszNames
[i
]);
246 if (ppszNames
!= NULL
)
248 for(i
= 0; i
< c
; i
++)
254 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &c
, NULL
, NULL
,
255 NULL
, NULL
, NULL
, NULL
, NULL
);
256 if (lResult
!= ERROR_SUCCESS
)
258 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
259 if (ppszNames
== NULL
)
261 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
263 for(i
= 0; i
< c
; i
++)
268 s_cbName
= MAX_PATH
* sizeof(WCHAR
);
269 lResult
= RegEnumKeyExW(hSubKey
, i
, s_szName
, &s_cbName
, NULL
, NULL
,
271 if (lResult
== ERROR_NO_MORE_ITEMS
)
276 if (lResult
!= ERROR_SUCCESS
)
278 if (s_cbName
>= MAX_PATH
* sizeof(WCHAR
))
281 ppszNames
[i
] = _wcsdup(s_szName
);
284 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
286 for(i
= 0; i
< c
; i
++)
291 if ((s_dwFlags
& RSF_LOOKATKEYS
) &&
292 CompareName(ppszNames
[i
], s_szFindWhat
))
294 *ppszFoundSubKey
= malloc(
295 (wcslen(szSubKey
) + wcslen(ppszNames
[i
]) + 2) *
297 if (*ppszFoundSubKey
== NULL
)
301 wcscpy(*ppszFoundSubKey
, szSubKey
);
302 wcscat(*ppszFoundSubKey
, s_backslash
);
305 **ppszFoundSubKey
= 0;
306 wcscat(*ppszFoundSubKey
, ppszNames
[i
]);
307 *ppszFoundValueName
= NULL
;
311 if (RegFindRecurse(hSubKey
, ppszNames
[i
], NULL
, ppszFoundSubKey
,
314 LPWSTR psz
= *ppszFoundSubKey
;
315 *ppszFoundSubKey
= malloc(
316 (wcslen(szSubKey
) + wcslen(psz
) + 2) * sizeof(WCHAR
));
317 if (*ppszFoundSubKey
== NULL
)
321 wcscpy(*ppszFoundSubKey
, szSubKey
);
322 wcscat(*ppszFoundSubKey
, s_backslash
);
325 **ppszFoundSubKey
= 0;
326 wcscat(*ppszFoundSubKey
, psz
);
333 if (ppszNames
!= NULL
)
335 for(i
= 0; i
< c
; i
++)
340 RegCloseKey(hSubKey
);
344 if (ppszNames
!= NULL
)
346 for(i
= 0; i
< c
; i
++)
350 RegCloseKey(hSubKey
);
357 LPCWSTR pszValueName
,
358 LPWSTR
*ppszFoundSubKey
,
359 LPWSTR
*ppszFoundValueName
)
363 HKEY hBaseKey
, hSubKey
;
364 WCHAR szKeyName
[MAX_PATH
];
365 WCHAR szSubKey
[MAX_PATH
];
368 LPWSTR
*ppszNames
= NULL
;
371 if (RegFindRecurse(hBaseKey
, pszSubKey
, pszValueName
, ppszFoundSubKey
,
375 if (wcslen(pszSubKey
) >= MAX_PATH
)
378 wcscpy(szSubKey
, pszSubKey
);
379 while(szSubKey
[0] != 0)
384 pch
= wcsrchr(szSubKey
, L
'\\');
387 wcscpy(szKeyName
, szSubKey
);
393 wcsncpy(szKeyName
, pch
+ 1, MAX_PATH
);
395 lResult
= RegOpenKeyExW(hBaseKey
, szSubKey
, 0, KEY_ALL_ACCESS
,
397 if (lResult
!= ERROR_SUCCESS
)
401 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &c
, NULL
, NULL
,
402 NULL
, NULL
, NULL
, NULL
, NULL
);
403 if (lResult
!= ERROR_SUCCESS
)
406 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
407 if (ppszNames
== NULL
)
409 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
411 for(i
= 0; i
< c
; i
++)
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
)
424 if (lResult
!= ERROR_SUCCESS
)
426 ppszNames
[i
] = _wcsdup(s_szName
);
429 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
432 for(i
= 0; i
< c
; i
++)
437 if (!fPast
&& wcsicmp(ppszNames
[i
], szKeyName
) == 0)
445 if ((s_dwFlags
& RSF_LOOKATKEYS
) &&
446 CompareName(ppszNames
[i
], s_szFindWhat
))
448 *ppszFoundSubKey
= malloc(
449 (wcslen(szSubKey
) + wcslen(ppszNames
[i
]) + 2) *
451 if (*ppszFoundSubKey
== NULL
)
455 wcscpy(*ppszFoundSubKey
, szSubKey
);
456 wcscat(*ppszFoundSubKey
, s_backslash
);
459 **ppszFoundSubKey
= 0;
460 wcscat(*ppszFoundSubKey
, ppszNames
[i
]);
461 *ppszFoundValueName
= NULL
;
465 if (RegFindRecurse(hSubKey
, ppszNames
[i
], NULL
,
466 ppszFoundSubKey
, ppszFoundValueName
))
468 LPWSTR psz
= *ppszFoundSubKey
;
469 *ppszFoundSubKey
= malloc(
470 (wcslen(szSubKey
) + wcslen(psz
) + 2) *
472 if (*ppszFoundSubKey
== NULL
)
476 wcscpy(*ppszFoundSubKey
, szSubKey
);
477 wcscat(*ppszFoundSubKey
, s_backslash
);
480 **ppszFoundSubKey
= 0;
481 wcscat(*ppszFoundSubKey
, psz
);
486 if (ppszNames
!= NULL
)
488 for(i
= 0; i
< c
; i
++)
494 if (hBaseKey
!= hSubKey
)
495 RegCloseKey(hSubKey
);
498 if (*phKey
== HKEY_CLASSES_ROOT
)
500 *phKey
= HKEY_CURRENT_USER
;
501 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
506 if (*phKey
== HKEY_CURRENT_USER
)
508 *phKey
= HKEY_LOCAL_MACHINE
;
509 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
514 if (*phKey
== HKEY_LOCAL_MACHINE
)
517 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
522 if (*phKey
== HKEY_USERS
)
524 *phKey
= HKEY_CURRENT_CONFIG
;
525 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
531 if (ppszNames
!= NULL
)
533 for(i
= 0; i
< c
; i
++)
537 if (hBaseKey
!= hSubKey
)
538 RegCloseKey(hSubKey
);
542 if (ppszNames
!= NULL
)
544 for(i
= 0; i
< c
; i
++)
548 if (hBaseKey
!= hSubKey
)
549 RegCloseKey(hSubKey
);
554 static DWORD
GetFindFlags(void)
557 DWORD dwType
, dwValue
, cbData
;
558 DWORD dwFlags
= RSF_LOOKATKEYS
| RSF_LOOKATVALUES
| RSF_LOOKATDATA
;
560 if (RegOpenKeyW(HKEY_CURRENT_USER
, g_szGeneralRegKey
, &hKey
) == ERROR_SUCCESS
)
562 /* Retrieve flags from registry key */
563 cbData
= sizeof(dwValue
);
564 if (RegQueryValueExW(hKey
, s_szFindFlags
, NULL
, &dwType
, (LPBYTE
) &dwValue
, &cbData
) == ERROR_SUCCESS
)
566 if (dwType
== REG_DWORD
)
567 dwFlags
= (dwFlags
& ~0x0000FFFF) | ((dwValue
& 0x0000FFFF) << 0);
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
)
574 if (dwType
== REG_DWORD
)
575 dwFlags
= (dwFlags
& ~0xFFFF0000) | ((dwValue
& 0x0000FFFF) << 16);
583 static void SetFindFlags(DWORD dwFlags
)
589 if (RegCreateKeyExW(HKEY_CURRENT_USER
, g_szGeneralRegKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwDisposition
) == ERROR_SUCCESS
)
591 dwData
= (dwFlags
>> 0) & 0x0000FFFF;
592 RegSetValueExW(hKey
, s_szFindFlags
, 0, REG_DWORD
, (const BYTE
*) &dwData
, sizeof(dwData
));
594 dwData
= (dwFlags
>> 16) & 0x0000FFFF;
595 RegSetValueExW(hKey
, s_szFindFlagsR
, 0, REG_DWORD
, (const BYTE
*) &dwData
, sizeof(dwData
));
601 static INT_PTR CALLBACK
AbortFindDialogProc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
603 UNREFERENCED_PARAMETER(lParam
);
604 UNREFERENCED_PARAMETER(hDlg
);
613 switch(HIWORD(wParam
))
616 switch(LOWORD(wParam
))
629 BOOL
FindNext(HWND hWnd
)
634 WCHAR szFullKey
[512];
635 LPCWSTR pszValueName
;
636 LPWSTR pszFoundSubKey
, pszFoundValueName
;
638 if (wcslen(s_szFindWhat
) == 0)
644 s_dwFlags
= GetFindFlags();
646 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
647 if (pszKeyPath
== NULL
)
649 hKeyRoot
= HKEY_CLASSES_ROOT
;
650 pszKeyPath
= s_empty
;
653 /* Create abort find dialog */
654 s_hwndAbortDialog
= CreateDialogW(GetModuleHandle(NULL
),
655 MAKEINTRESOURCEW(IDD_FINDING
), hWnd
, AbortFindDialogProc
);
656 if (s_hwndAbortDialog
)
658 ShowWindow(s_hwndAbortDialog
, SW_SHOW
);
659 UpdateWindow(s_hwndAbortDialog
);
663 pszValueName
= GetValueName(g_pChildWnd
->hListWnd
, -1);
665 EnableWindow(hFrameWnd
, FALSE
);
666 EnableWindow(g_pChildWnd
->hTreeWnd
, FALSE
);
667 EnableWindow(g_pChildWnd
->hListWnd
, FALSE
);
668 EnableWindow(g_pChildWnd
->hAddressBarWnd
, FALSE
);
670 fSuccess
= RegFindWalk(&hKeyRoot
, pszKeyPath
, pszValueName
,
671 &pszFoundSubKey
, &pszFoundValueName
);
673 EnableWindow(hFrameWnd
, TRUE
);
674 EnableWindow(g_pChildWnd
->hTreeWnd
, TRUE
);
675 EnableWindow(g_pChildWnd
->hListWnd
, TRUE
);
676 EnableWindow(g_pChildWnd
->hAddressBarWnd
, TRUE
);
678 if (s_hwndAbortDialog
)
680 DestroyWindow(s_hwndAbortDialog
);
681 s_hwndAbortDialog
= NULL
;
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
);
693 return fSuccess
|| s_bAbort
;
696 static INT_PTR CALLBACK
FindDialogProc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
702 static WCHAR s_szSavedFindValue
[256];
707 dwFlags
= GetFindFlags();
709 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_KEYS
);
711 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATKEYS
) ? TRUE
: FALSE
, 0);
713 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_VALUES
);
715 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATVALUES
) ? TRUE
: FALSE
, 0);
717 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_DATA
);
719 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATDATA
) ? TRUE
: FALSE
, 0);
721 /* Match whole string */
722 hControl
= GetDlgItem(hDlg
, IDC_MATCHSTRING
);
724 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_WHOLESTRING
) ? TRUE
: FALSE
, 0);
726 /* Case sensitivity */
727 hControl
= GetDlgItem(hDlg
, IDC_MATCHCASE
);
729 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_MATCHCASE
) ? TRUE
: FALSE
, 0);
731 hControl
= GetDlgItem(hDlg
, IDC_FINDWHAT
);
734 SetWindowTextW(hControl
, s_szSavedFindValue
);
736 SendMessageW(hControl
, EM_SETSEL
, 0, -1);
745 switch(HIWORD(wParam
))
748 switch(LOWORD(wParam
))
753 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_KEYS
);
754 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
755 dwFlags
|= RSF_LOOKATKEYS
;
757 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_VALUES
);
758 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
759 dwFlags
|= RSF_LOOKATVALUES
;
761 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_DATA
);
762 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
763 dwFlags
|= RSF_LOOKATDATA
;
765 hControl
= GetDlgItem(hDlg
, IDC_MATCHSTRING
);
766 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
767 dwFlags
|= RSF_WHOLESTRING
;
769 hControl
= GetDlgItem(hDlg
, IDC_MATCHCASE
);
770 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
771 dwFlags
|= RSF_MATCHCASE
;
773 SetFindFlags(dwFlags
);
775 hControl
= GetDlgItem(hDlg
, IDC_FINDWHAT
);
777 GetWindowTextW(hControl
, s_szFindWhat
, COUNT_OF(s_szFindWhat
));
788 switch(LOWORD(wParam
))
791 GetWindowTextW((HWND
) lParam
, s_szSavedFindValue
, COUNT_OF(s_szSavedFindValue
));
792 hControl
= GetDlgItem(hDlg
, IDOK
);
795 lStyle
= GetWindowLongPtr(hControl
, GWL_STYLE
);
796 if (s_szSavedFindValue
[0])
797 lStyle
&= ~WS_DISABLED
;
799 lStyle
|= WS_DISABLED
;
800 SetWindowLongPtr(hControl
, GWL_STYLE
, lStyle
);
801 RedrawWindow(hControl
, NULL
, NULL
, RDW_INVALIDATE
);
811 void FindDialog(HWND hWnd
)
813 if (DialogBoxParamW(GetModuleHandle(NULL
), MAKEINTRESOURCEW(IDD_FIND
),
814 hWnd
, FindDialogProc
, 0) != 0)
818 WCHAR msg
[128], caption
[128];
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
);