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
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
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
;
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
"\\";
39 extern VOID
SetValueName(HWND hwndLV
, LPCWSTR pszValueName
);
44 if (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
46 if (msg
.message
== WM_QUIT
)
48 if (!IsDialogMessageW(s_hwndAbortDialog
, &msg
))
50 TranslateMessage(&msg
);
51 DispatchMessageW(&msg
);
57 static LPWSTR
lstrstri(LPCWSTR psz1
, LPCWSTR psz2
)
63 for(i
= 0; i
<= cch1
- cch2
; i
++)
65 if (CompareStringW(LOCALE_SYSTEM_DEFAULT
, NORM_IGNORECASE
,
66 psz1
+ i
, cch2
, psz2
, cch2
) == 2)
67 return (LPWSTR
) (psz1
+ i
);
72 static BOOL
CompareName(LPCWSTR pszName1
, LPCWSTR pszName2
)
74 if (s_dwFlags
& RSF_WHOLESTRING
)
76 if (s_dwFlags
& RSF_MATCHCASE
)
77 return wcscmp(pszName1
, pszName2
) == 0;
79 return _wcsicmp(pszName1
, pszName2
) == 0;
83 if (s_dwFlags
& RSF_MATCHCASE
)
84 return wcsstr(pszName1
, pszName2
) != NULL
;
86 return lstrstri(pszName1
, pszName2
) != NULL
;
96 INT i
, cch1
= wcslen(psz1
), cch2
= wcslen(psz2
);
97 if (dwType
== REG_SZ
|| dwType
== REG_EXPAND_SZ
)
99 if (s_dwFlags
& RSF_WHOLESTRING
)
101 if (s_dwFlags
& RSF_MATCHCASE
)
102 return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
, 0,
103 psz1
, cch1
, psz2
, cch2
);
105 return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
,
106 NORM_IGNORECASE
, psz1
, cch1
, psz2
, cch2
);
109 for(i
= 0; i
<= cch1
- cch2
; i
++)
111 if (s_dwFlags
& RSF_MATCHCASE
)
113 if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
, 0,
114 psz1
+ i
, cch2
, psz2
, cch2
))
119 if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT
,
120 NORM_IGNORECASE
, psz1
+ i
, cch2
, psz2
, cch2
))
128 int compare(const void *x
, const void *y
)
130 const LPCWSTR
*a
= (const LPCWSTR
*)x
;
131 const LPCWSTR
*b
= (const LPCWSTR
*)y
;
132 return _wcsicmp(*a
, *b
);
138 LPCWSTR pszValueName
,
139 LPWSTR
*ppszFoundSubKey
,
140 LPWSTR
*ppszFoundValueName
)
144 WCHAR szSubKey
[MAX_PATH
];
145 DWORD i
, c
, cb
, type
;
147 LPWSTR
*ppszNames
= NULL
;
153 wcscpy(szSubKey
, pszSubKey
);
156 lResult
= RegOpenKeyExW(hKey
, szSubKey
, 0, KEY_ALL_ACCESS
, &hSubKey
);
157 if (lResult
!= ERROR_SUCCESS
)
160 if (pszValueName
== NULL
)
161 pszValueName
= s_empty
;
163 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
164 &c
, NULL
, NULL
, NULL
, NULL
);
165 if (lResult
!= ERROR_SUCCESS
)
167 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
168 if (ppszNames
== NULL
)
170 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
172 for(i
= 0; i
< c
; i
++)
177 s_cbName
= MAX_PATH
* sizeof(WCHAR
);
178 lResult
= RegEnumValueW(hSubKey
, i
, s_szName
, &s_cbName
, NULL
, NULL
,
180 if (lResult
== ERROR_NO_MORE_ITEMS
)
185 if (lResult
!= ERROR_SUCCESS
)
187 if (s_cbName
>= MAX_PATH
* sizeof(WCHAR
))
190 ppszNames
[i
] = _wcsdup(s_szName
);
193 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
195 for(i
= 0; i
< c
; i
++)
200 if (!fPast
&& _wcsicmp(ppszNames
[i
], pszValueName
) == 0)
208 if ((s_dwFlags
& RSF_LOOKATVALUES
) &&
209 CompareName(ppszNames
[i
], s_szFindWhat
))
211 *ppszFoundSubKey
= _wcsdup(szSubKey
);
212 if (ppszNames
[i
][0] == 0)
213 *ppszFoundValueName
= NULL
;
215 *ppszFoundValueName
= _wcsdup(ppszNames
[i
]);
219 lResult
= RegQueryValueExW(hSubKey
, ppszNames
[i
], NULL
, &type
,
221 if (lResult
!= ERROR_SUCCESS
)
226 lResult
= RegQueryValueExW(hSubKey
, ppszNames
[i
], NULL
, &type
,
228 if (lResult
!= ERROR_SUCCESS
)
231 if ((s_dwFlags
& RSF_LOOKATDATA
) &&
232 CompareData(type
, (LPWSTR
) pb
, s_szFindWhat
))
234 *ppszFoundSubKey
= _wcsdup(szSubKey
);
235 if (ppszNames
[i
][0] == 0)
236 *ppszFoundValueName
= NULL
;
238 *ppszFoundValueName
= _wcsdup(ppszNames
[i
]);
245 if (ppszNames
!= NULL
)
247 for(i
= 0; i
< c
; i
++)
253 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &c
, NULL
, NULL
,
254 NULL
, NULL
, NULL
, NULL
, NULL
);
255 if (lResult
!= ERROR_SUCCESS
)
257 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
258 if (ppszNames
== NULL
)
260 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
262 for(i
= 0; i
< c
; i
++)
267 s_cbName
= MAX_PATH
* sizeof(WCHAR
);
268 lResult
= RegEnumKeyExW(hSubKey
, i
, s_szName
, &s_cbName
, NULL
, NULL
,
270 if (lResult
== ERROR_NO_MORE_ITEMS
)
275 if (lResult
!= ERROR_SUCCESS
)
277 if (s_cbName
>= MAX_PATH
* sizeof(WCHAR
))
280 ppszNames
[i
] = _wcsdup(s_szName
);
283 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
285 for(i
= 0; i
< c
; i
++)
290 if ((s_dwFlags
& RSF_LOOKATKEYS
) &&
291 CompareName(ppszNames
[i
], s_szFindWhat
))
293 *ppszFoundSubKey
= malloc(
294 (wcslen(szSubKey
) + wcslen(ppszNames
[i
]) + 2) *
296 if (*ppszFoundSubKey
== NULL
)
300 wcscpy(*ppszFoundSubKey
, szSubKey
);
301 wcscat(*ppszFoundSubKey
, s_backslash
);
304 **ppszFoundSubKey
= 0;
305 wcscat(*ppszFoundSubKey
, ppszNames
[i
]);
306 *ppszFoundValueName
= NULL
;
310 if (RegFindRecurse(hSubKey
, ppszNames
[i
], NULL
, ppszFoundSubKey
,
313 LPWSTR psz
= *ppszFoundSubKey
;
314 *ppszFoundSubKey
= malloc(
315 (wcslen(szSubKey
) + wcslen(psz
) + 2) * sizeof(WCHAR
));
316 if (*ppszFoundSubKey
== NULL
)
320 wcscpy(*ppszFoundSubKey
, szSubKey
);
321 wcscat(*ppszFoundSubKey
, s_backslash
);
324 **ppszFoundSubKey
= 0;
325 wcscat(*ppszFoundSubKey
, psz
);
332 if (ppszNames
!= NULL
)
334 for(i
= 0; i
< c
; i
++)
339 RegCloseKey(hSubKey
);
343 if (ppszNames
!= NULL
)
345 for(i
= 0; i
< c
; i
++)
349 RegCloseKey(hSubKey
);
356 LPCWSTR pszValueName
,
357 LPWSTR
*ppszFoundSubKey
,
358 LPWSTR
*ppszFoundValueName
)
362 HKEY hBaseKey
, hSubKey
;
363 WCHAR szKeyName
[MAX_PATH
];
364 WCHAR szSubKey
[MAX_PATH
];
367 LPWSTR
*ppszNames
= NULL
;
370 if (RegFindRecurse(hBaseKey
, pszSubKey
, pszValueName
, ppszFoundSubKey
,
374 if (wcslen(pszSubKey
) >= MAX_PATH
)
377 wcscpy(szSubKey
, pszSubKey
);
378 while(szSubKey
[0] != 0)
383 pch
= wcsrchr(szSubKey
, L
'\\');
386 wcscpy(szKeyName
, szSubKey
);
392 lstrcpynW(szKeyName
, pch
+ 1, MAX_PATH
);
394 lResult
= RegOpenKeyExW(hBaseKey
, szSubKey
, 0, KEY_ALL_ACCESS
,
396 if (lResult
!= ERROR_SUCCESS
)
400 lResult
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, &c
, NULL
, NULL
,
401 NULL
, NULL
, NULL
, NULL
, NULL
);
402 if (lResult
!= ERROR_SUCCESS
)
405 ppszNames
= (LPWSTR
*) malloc(c
* sizeof(LPWSTR
));
406 if (ppszNames
== NULL
)
408 ZeroMemory(ppszNames
, c
* sizeof(LPWSTR
));
410 for(i
= 0; i
< c
; i
++)
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
)
423 if (lResult
!= ERROR_SUCCESS
)
425 ppszNames
[i
] = _wcsdup(s_szName
);
428 qsort(ppszNames
, c
, sizeof(LPWSTR
), compare
);
431 for(i
= 0; i
< c
; i
++)
436 if (!fPast
&& _wcsicmp(ppszNames
[i
], szKeyName
) == 0)
444 if ((s_dwFlags
& RSF_LOOKATKEYS
) &&
445 CompareName(ppszNames
[i
], s_szFindWhat
))
447 *ppszFoundSubKey
= malloc(
448 (wcslen(szSubKey
) + wcslen(ppszNames
[i
]) + 2) *
450 if (*ppszFoundSubKey
== NULL
)
454 wcscpy(*ppszFoundSubKey
, szSubKey
);
455 wcscat(*ppszFoundSubKey
, s_backslash
);
458 **ppszFoundSubKey
= 0;
459 wcscat(*ppszFoundSubKey
, ppszNames
[i
]);
460 *ppszFoundValueName
= NULL
;
464 if (RegFindRecurse(hSubKey
, ppszNames
[i
], NULL
,
465 ppszFoundSubKey
, ppszFoundValueName
))
467 LPWSTR psz
= *ppszFoundSubKey
;
468 *ppszFoundSubKey
= malloc(
469 (wcslen(szSubKey
) + wcslen(psz
) + 2) *
471 if (*ppszFoundSubKey
== NULL
)
475 wcscpy(*ppszFoundSubKey
, szSubKey
);
476 wcscat(*ppszFoundSubKey
, s_backslash
);
479 **ppszFoundSubKey
= 0;
480 wcscat(*ppszFoundSubKey
, psz
);
485 if (ppszNames
!= NULL
)
487 for(i
= 0; i
< c
; i
++)
493 if (hBaseKey
!= hSubKey
)
494 RegCloseKey(hSubKey
);
497 if (*phKey
== HKEY_CLASSES_ROOT
)
499 *phKey
= HKEY_CURRENT_USER
;
500 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
505 if (*phKey
== HKEY_CURRENT_USER
)
507 *phKey
= HKEY_LOCAL_MACHINE
;
508 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
513 if (*phKey
== HKEY_LOCAL_MACHINE
)
516 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
521 if (*phKey
== HKEY_USERS
)
523 *phKey
= HKEY_CURRENT_CONFIG
;
524 if (RegFindRecurse(*phKey
, s_empty
, NULL
, ppszFoundSubKey
,
530 if (ppszNames
!= NULL
)
532 for(i
= 0; i
< c
; i
++)
536 if (hBaseKey
!= hSubKey
)
537 RegCloseKey(hSubKey
);
541 if (ppszNames
!= NULL
)
543 for(i
= 0; i
< c
; i
++)
547 if (hBaseKey
!= hSubKey
)
548 RegCloseKey(hSubKey
);
553 static DWORD
GetFindFlags(void)
556 DWORD dwType
, dwValue
, cbData
;
557 DWORD dwFlags
= RSF_LOOKATKEYS
| RSF_LOOKATVALUES
| RSF_LOOKATDATA
;
559 if (RegOpenKeyW(HKEY_CURRENT_USER
, g_szGeneralRegKey
, &hKey
) == ERROR_SUCCESS
)
561 /* Retrieve flags from registry key */
562 cbData
= sizeof(dwValue
);
563 if (RegQueryValueExW(hKey
, s_szFindFlags
, NULL
, &dwType
, (LPBYTE
) &dwValue
, &cbData
) == ERROR_SUCCESS
)
565 if (dwType
== REG_DWORD
)
566 dwFlags
= (dwFlags
& ~0x0000FFFF) | ((dwValue
& 0x0000FFFF) << 0);
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
)
573 if (dwType
== REG_DWORD
)
574 dwFlags
= (dwFlags
& ~0xFFFF0000) | ((dwValue
& 0x0000FFFF) << 16);
582 static void SetFindFlags(DWORD dwFlags
)
588 if (RegCreateKeyExW(HKEY_CURRENT_USER
, g_szGeneralRegKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwDisposition
) == ERROR_SUCCESS
)
590 dwData
= (dwFlags
>> 0) & 0x0000FFFF;
591 RegSetValueExW(hKey
, s_szFindFlags
, 0, REG_DWORD
, (const BYTE
*) &dwData
, sizeof(dwData
));
593 dwData
= (dwFlags
>> 16) & 0x0000FFFF;
594 RegSetValueExW(hKey
, s_szFindFlagsR
, 0, REG_DWORD
, (const BYTE
*) &dwData
, sizeof(dwData
));
600 static INT_PTR CALLBACK
AbortFindDialogProc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
602 UNREFERENCED_PARAMETER(lParam
);
603 UNREFERENCED_PARAMETER(hDlg
);
612 switch(HIWORD(wParam
))
615 switch(LOWORD(wParam
))
628 BOOL
FindNext(HWND hWnd
)
633 WCHAR szFullKey
[512];
634 LPCWSTR pszValueName
;
635 LPWSTR pszFoundSubKey
, pszFoundValueName
;
637 if (wcslen(s_szFindWhat
) == 0)
643 s_dwFlags
= GetFindFlags();
645 pszKeyPath
= GetItemPath(g_pChildWnd
->hTreeWnd
, 0, &hKeyRoot
);
646 if (pszKeyPath
== NULL
)
648 hKeyRoot
= HKEY_CLASSES_ROOT
;
649 pszKeyPath
= s_empty
;
652 /* Create abort find dialog */
653 s_hwndAbortDialog
= CreateDialogW(GetModuleHandle(NULL
),
654 MAKEINTRESOURCEW(IDD_FINDING
), hWnd
, AbortFindDialogProc
);
655 if (s_hwndAbortDialog
)
657 ShowWindow(s_hwndAbortDialog
, SW_SHOW
);
658 UpdateWindow(s_hwndAbortDialog
);
662 pszValueName
= GetValueName(g_pChildWnd
->hListWnd
, -1);
664 EnableWindow(hFrameWnd
, FALSE
);
665 EnableWindow(g_pChildWnd
->hTreeWnd
, FALSE
);
666 EnableWindow(g_pChildWnd
->hListWnd
, FALSE
);
667 EnableWindow(g_pChildWnd
->hAddressBarWnd
, FALSE
);
669 fSuccess
= RegFindWalk(&hKeyRoot
, pszKeyPath
, pszValueName
,
670 &pszFoundSubKey
, &pszFoundValueName
);
672 EnableWindow(hFrameWnd
, TRUE
);
673 EnableWindow(g_pChildWnd
->hTreeWnd
, TRUE
);
674 EnableWindow(g_pChildWnd
->hListWnd
, TRUE
);
675 EnableWindow(g_pChildWnd
->hAddressBarWnd
, TRUE
);
677 if (s_hwndAbortDialog
)
679 DestroyWindow(s_hwndAbortDialog
);
680 s_hwndAbortDialog
= NULL
;
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
);
692 return fSuccess
|| s_bAbort
;
695 static INT_PTR CALLBACK
FindDialogProc(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
701 static WCHAR s_szSavedFindValue
[256];
706 dwFlags
= GetFindFlags();
708 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_KEYS
);
710 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATKEYS
) ? TRUE
: FALSE
, 0);
712 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_VALUES
);
714 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATVALUES
) ? TRUE
: FALSE
, 0);
716 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_DATA
);
718 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_LOOKATDATA
) ? TRUE
: FALSE
, 0);
720 /* Match whole string */
721 hControl
= GetDlgItem(hDlg
, IDC_MATCHSTRING
);
723 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_WHOLESTRING
) ? TRUE
: FALSE
, 0);
725 /* Case sensitivity */
726 hControl
= GetDlgItem(hDlg
, IDC_MATCHCASE
);
728 SendMessageW(hControl
, BM_SETCHECK
, (dwFlags
& RSF_MATCHCASE
) ? TRUE
: FALSE
, 0);
730 hControl
= GetDlgItem(hDlg
, IDC_FINDWHAT
);
733 SetWindowTextW(hControl
, s_szSavedFindValue
);
735 SendMessageW(hControl
, EM_SETSEL
, 0, -1);
744 switch(HIWORD(wParam
))
747 switch(LOWORD(wParam
))
752 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_KEYS
);
753 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
754 dwFlags
|= RSF_LOOKATKEYS
;
756 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_VALUES
);
757 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
758 dwFlags
|= RSF_LOOKATVALUES
;
760 hControl
= GetDlgItem(hDlg
, IDC_LOOKAT_DATA
);
761 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
762 dwFlags
|= RSF_LOOKATDATA
;
764 hControl
= GetDlgItem(hDlg
, IDC_MATCHSTRING
);
765 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
766 dwFlags
|= RSF_WHOLESTRING
;
768 hControl
= GetDlgItem(hDlg
, IDC_MATCHCASE
);
769 if (hControl
&& (SendMessageW(hControl
, BM_GETCHECK
, 0, 0) == BST_CHECKED
))
770 dwFlags
|= RSF_MATCHCASE
;
772 SetFindFlags(dwFlags
);
774 hControl
= GetDlgItem(hDlg
, IDC_FINDWHAT
);
776 GetWindowTextW(hControl
, s_szFindWhat
, COUNT_OF(s_szFindWhat
));
787 switch(LOWORD(wParam
))
790 GetWindowTextW((HWND
) lParam
, s_szSavedFindValue
, COUNT_OF(s_szSavedFindValue
));
791 hControl
= GetDlgItem(hDlg
, IDOK
);
794 lStyle
= GetWindowLongPtr(hControl
, GWL_STYLE
);
795 if (s_szSavedFindValue
[0])
796 lStyle
&= ~WS_DISABLED
;
798 lStyle
|= WS_DISABLED
;
799 SetWindowLongPtr(hControl
, GWL_STYLE
, lStyle
);
800 RedrawWindow(hControl
, NULL
, NULL
, RDW_INVALIDATE
);
810 void FindDialog(HWND hWnd
)
812 if (DialogBoxParamW(GetModuleHandle(NULL
), MAKEINTRESOURCEW(IDD_FIND
),
813 hWnd
, FindDialogProc
, 0) != 0)
817 WCHAR msg
[128], caption
[128];
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
);