mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 21:09:15 +00:00
8cef980ab9
Use safer functions for buffer manipulation to avoid buffer overflow/overrun. CORE-18876
832 lines
24 KiB
C
832 lines
24 KiB
C
/*
|
|
* Regedit find dialog
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "regedit.h"
|
|
|
|
#define RSF_WHOLESTRING 0x00000001
|
|
#define RSF_LOOKATKEYS 0x00000002
|
|
#define RSF_LOOKATVALUES 0x00000004
|
|
#define RSF_LOOKATDATA 0x00000008
|
|
#define RSF_MATCHCASE 0x00010000
|
|
|
|
static WCHAR s_szFindWhat[256];
|
|
static const WCHAR s_szFindFlags[] = L"FindFlags";
|
|
static const WCHAR s_szFindFlagsR[] = L"FindFlagsReactOS";
|
|
static HWND s_hwndAbortDialog;
|
|
static BOOL s_bAbort;
|
|
|
|
static DWORD s_dwFlags;
|
|
static WCHAR s_szName[MAX_PATH];
|
|
static DWORD s_cchName;
|
|
static const WCHAR s_empty[] = L"";
|
|
static const WCHAR s_backslash[] = L"\\";
|
|
|
|
extern VOID SetValueName(HWND hwndLV, LPCWSTR pszValueName);
|
|
|
|
BOOL DoEvents(VOID)
|
|
{
|
|
MSG msg;
|
|
if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if (msg.message == WM_QUIT)
|
|
s_bAbort = TRUE;
|
|
if (!IsDialogMessageW(s_hwndAbortDialog, &msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
}
|
|
}
|
|
return s_bAbort;
|
|
}
|
|
|
|
static LPWSTR lstrstri(LPCWSTR psz1, LPCWSTR psz2)
|
|
{
|
|
INT i, cch1, cch2;
|
|
|
|
cch1 = wcslen(psz1);
|
|
cch2 = wcslen(psz2);
|
|
for(i = 0; i <= cch1 - cch2; i++)
|
|
{
|
|
if (CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
|
|
psz1 + i, cch2, psz2, cch2) == 2)
|
|
return (LPWSTR) (psz1 + i);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static BOOL CompareName(LPCWSTR pszName1, LPCWSTR pszName2)
|
|
{
|
|
if (s_dwFlags & RSF_WHOLESTRING)
|
|
{
|
|
if (s_dwFlags & RSF_MATCHCASE)
|
|
return wcscmp(pszName1, pszName2) == 0;
|
|
else
|
|
return _wcsicmp(pszName1, pszName2) == 0;
|
|
}
|
|
else
|
|
{
|
|
if (s_dwFlags & RSF_MATCHCASE)
|
|
return wcsstr(pszName1, pszName2) != NULL;
|
|
else
|
|
return lstrstri(pszName1, pszName2) != NULL;
|
|
}
|
|
}
|
|
|
|
/* Do not assume that pch1 is terminated with UNICODE_NULL */
|
|
static BOOL MatchString(LPCWCH pch1, INT cch1, LPCWCH pch2, INT cch2)
|
|
{
|
|
INT i;
|
|
DWORD dwNorm = ((s_dwFlags & RSF_MATCHCASE) ? NORM_IGNORECASE : 0);
|
|
|
|
if (s_dwFlags & RSF_WHOLESTRING)
|
|
return 2 == CompareStringW(LOCALE_SYSTEM_DEFAULT, dwNorm, pch1, cch1, pch2, cch2);
|
|
|
|
if (cch1 < cch2)
|
|
return FALSE;
|
|
|
|
for (i = 0; i <= cch1 - cch2; i++)
|
|
{
|
|
if (2 == CompareStringW(LOCALE_SYSTEM_DEFAULT, dwNorm, pch1 + i, cch2, pch2, cch2))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL MatchData(DWORD dwType, LPCVOID pv1, DWORD cb1)
|
|
{
|
|
if (dwType == REG_SZ || dwType == REG_EXPAND_SZ || dwType == REG_MULTI_SZ)
|
|
return MatchString(pv1, (INT)(cb1 / sizeof(WCHAR)), s_szFindWhat, lstrlenW(s_szFindWhat));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int compare(const void *x, const void *y)
|
|
{
|
|
const LPCWSTR *a = (const LPCWSTR *)x;
|
|
const LPCWSTR *b = (const LPCWSTR *)y;
|
|
return _wcsicmp(*a, *b);
|
|
}
|
|
|
|
BOOL RegFindRecurse(
|
|
HKEY hKey,
|
|
LPCWSTR pszSubKey,
|
|
LPCWSTR pszValueName,
|
|
LPWSTR *ppszFoundSubKey,
|
|
LPWSTR *ppszFoundValueName)
|
|
{
|
|
HKEY hSubKey;
|
|
LONG lResult;
|
|
WCHAR szSubKey[MAX_PATH];
|
|
DWORD i, c, cb, type;
|
|
BOOL fPast;
|
|
LPWSTR *ppszNames = NULL;
|
|
LPBYTE pb = NULL;
|
|
|
|
if (DoEvents())
|
|
return FALSE;
|
|
|
|
if(wcslen(pszSubKey) >= _countof(szSubKey))
|
|
return FALSE;
|
|
|
|
StringCbCopyW(szSubKey, sizeof(szSubKey), pszSubKey);
|
|
hSubKey = NULL;
|
|
|
|
lResult = RegOpenKeyExW(hKey, szSubKey, 0, KEY_ALL_ACCESS, &hSubKey);
|
|
if (lResult != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&c, NULL, NULL, NULL, NULL);
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR));
|
|
if (ppszNames == NULL)
|
|
goto err;
|
|
ZeroMemory(ppszNames, c * sizeof(LPWSTR));
|
|
|
|
/* Retrieve the value names associated with the current key */
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
s_cchName = _countof(s_szName);
|
|
lResult = RegEnumValueW(hSubKey, i, s_szName, &s_cchName, NULL, NULL,
|
|
NULL, &cb);
|
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
c = i;
|
|
break;
|
|
}
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
if (s_cchName >= _countof(s_szName))
|
|
continue;
|
|
|
|
ppszNames[i] = _wcsdup(s_szName);
|
|
}
|
|
|
|
qsort(ppszNames, c, sizeof(LPWSTR), compare);
|
|
|
|
/* If pszValueName is NULL, the function will search for all values within the key */
|
|
fPast = (pszValueName == NULL);
|
|
|
|
/* Search within the values */
|
|
for (i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
if (!fPast && _wcsicmp(ppszNames[i], pszValueName) == 0)
|
|
{
|
|
fPast = TRUE;
|
|
continue;
|
|
}
|
|
if (!fPast)
|
|
continue;
|
|
|
|
if ((s_dwFlags & RSF_LOOKATVALUES) &&
|
|
CompareName(ppszNames[i], s_szFindWhat))
|
|
{
|
|
*ppszFoundSubKey = _wcsdup(szSubKey);
|
|
*ppszFoundValueName = _wcsdup(ppszNames[i]);
|
|
goto success;
|
|
}
|
|
|
|
lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type,
|
|
NULL, &cb);
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
pb = malloc(cb);
|
|
if (pb == NULL)
|
|
goto err;
|
|
lResult = RegQueryValueExW(hSubKey, ppszNames[i], NULL, &type,
|
|
pb, &cb);
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
|
|
if ((s_dwFlags & RSF_LOOKATDATA) && MatchData(type, pb, cb))
|
|
{
|
|
*ppszFoundSubKey = _wcsdup(szSubKey);
|
|
*ppszFoundValueName = _wcsdup(ppszNames[i]);
|
|
goto success;
|
|
}
|
|
free(pb);
|
|
pb = NULL;
|
|
}
|
|
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
ppszNames = NULL;
|
|
|
|
/* Retrieve the number of sub-keys */
|
|
lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR));
|
|
if (ppszNames == NULL)
|
|
goto err;
|
|
ZeroMemory(ppszNames, c * sizeof(LPWSTR));
|
|
|
|
/* Retrieve the names of the sub-keys */
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
s_cchName = _countof(s_szName);
|
|
lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cchName, NULL, NULL,
|
|
NULL, NULL);
|
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
c = i;
|
|
break;
|
|
}
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
if (s_cchName >= _countof(s_szName))
|
|
continue;
|
|
|
|
ppszNames[i] = _wcsdup(s_szName);
|
|
}
|
|
|
|
qsort(ppszNames, c, sizeof(LPWSTR), compare);
|
|
|
|
/* Search within the sub-keys */
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
if ((s_dwFlags & RSF_LOOKATKEYS) &&
|
|
CompareName(ppszNames[i], s_szFindWhat))
|
|
{
|
|
*ppszFoundSubKey = malloc(
|
|
(wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) *
|
|
sizeof(WCHAR));
|
|
if (*ppszFoundSubKey == NULL)
|
|
goto err;
|
|
if (szSubKey[0])
|
|
{
|
|
wcscpy(*ppszFoundSubKey, szSubKey);
|
|
wcscat(*ppszFoundSubKey, s_backslash);
|
|
}
|
|
else
|
|
**ppszFoundSubKey = 0;
|
|
wcscat(*ppszFoundSubKey, ppszNames[i]);
|
|
*ppszFoundValueName = NULL;
|
|
goto success;
|
|
}
|
|
|
|
/* Search within the value entries of the sub-key */
|
|
if (RegFindRecurse(hSubKey, ppszNames[i], NULL, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
{
|
|
LPWSTR psz = *ppszFoundSubKey;
|
|
SIZE_T cbFoundSubKey = (wcslen(szSubKey) + wcslen(psz) + 2) * sizeof(WCHAR);
|
|
*ppszFoundSubKey = malloc(cbFoundSubKey);
|
|
if (*ppszFoundSubKey == NULL)
|
|
goto err;
|
|
if (szSubKey[0])
|
|
{
|
|
StringCbCopyW(*ppszFoundSubKey, cbFoundSubKey, szSubKey);
|
|
StringCbCatW(*ppszFoundSubKey, cbFoundSubKey, s_backslash);
|
|
}
|
|
else
|
|
**ppszFoundSubKey = 0;
|
|
wcscat(*ppszFoundSubKey, psz);
|
|
free(psz);
|
|
goto success;
|
|
}
|
|
}
|
|
|
|
err:
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
free(pb);
|
|
RegCloseKey(hSubKey);
|
|
return FALSE;
|
|
|
|
success:
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
RegCloseKey(hSubKey);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL RegFindWalk(
|
|
HKEY * phKey,
|
|
LPCWSTR pszSubKey,
|
|
LPCWSTR pszValueName,
|
|
LPWSTR *ppszFoundSubKey,
|
|
LPWSTR *ppszFoundValueName)
|
|
{
|
|
LONG lResult;
|
|
DWORD i, c;
|
|
HKEY hBaseKey, hSubKey;
|
|
WCHAR szKeyName[MAX_PATH];
|
|
WCHAR szSubKey[MAX_PATH];
|
|
LPWSTR pch;
|
|
BOOL fPast, fKeyMatched;
|
|
LPWSTR *ppszNames = NULL;
|
|
|
|
hBaseKey = *phKey;
|
|
|
|
if (wcslen(pszSubKey) >= _countof(szSubKey))
|
|
return FALSE;
|
|
|
|
if (RegFindRecurse(hBaseKey, pszSubKey, pszValueName, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
return TRUE;
|
|
|
|
StringCbCopyW(szSubKey, sizeof(szSubKey), pszSubKey);
|
|
while(szSubKey[0] != 0)
|
|
{
|
|
if (DoEvents())
|
|
return FALSE;
|
|
|
|
pch = wcsrchr(szSubKey, L'\\');
|
|
if (pch == NULL)
|
|
{
|
|
wcscpy(szKeyName, szSubKey);
|
|
szSubKey[0] = 0;
|
|
hSubKey = hBaseKey;
|
|
}
|
|
else
|
|
{
|
|
lstrcpynW(szKeyName, pch + 1, MAX_PATH);
|
|
*pch = 0;
|
|
lResult = RegOpenKeyExW(hBaseKey, szSubKey, 0, KEY_ALL_ACCESS,
|
|
&hSubKey);
|
|
if (lResult != ERROR_SUCCESS)
|
|
return FALSE;
|
|
}
|
|
|
|
lResult = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &c, NULL, NULL,
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
if (lResult != ERROR_SUCCESS)
|
|
goto err;
|
|
|
|
ppszNames = (LPWSTR *) malloc(c * sizeof(LPWSTR));
|
|
if (ppszNames == NULL)
|
|
goto err;
|
|
ZeroMemory(ppszNames, c * sizeof(LPWSTR));
|
|
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
s_cchName = _countof(s_szName);
|
|
lResult = RegEnumKeyExW(hSubKey, i, s_szName, &s_cchName,
|
|
NULL, NULL, NULL, NULL);
|
|
if (lResult == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
c = i;
|
|
break;
|
|
}
|
|
if (lResult != ERROR_SUCCESS)
|
|
break;
|
|
ppszNames[i] = _wcsdup(s_szName);
|
|
}
|
|
|
|
qsort(ppszNames, c, sizeof(LPWSTR), compare);
|
|
|
|
fPast = FALSE;
|
|
for(i = 0; i < c; i++)
|
|
{
|
|
if (DoEvents())
|
|
goto err;
|
|
|
|
if (!fPast && _wcsicmp(ppszNames[i], szKeyName) == 0)
|
|
{
|
|
fPast = TRUE;
|
|
continue;
|
|
}
|
|
if (!fPast)
|
|
continue;
|
|
|
|
if ((s_dwFlags & RSF_LOOKATKEYS) &&
|
|
CompareName(ppszNames[i], s_szFindWhat))
|
|
{
|
|
*ppszFoundSubKey = malloc(
|
|
(wcslen(szSubKey) + wcslen(ppszNames[i]) + 2) *
|
|
sizeof(WCHAR));
|
|
if (*ppszFoundSubKey == NULL)
|
|
goto err;
|
|
if (szSubKey[0])
|
|
{
|
|
wcscpy(*ppszFoundSubKey, szSubKey);
|
|
wcscat(*ppszFoundSubKey, s_backslash);
|
|
}
|
|
else
|
|
**ppszFoundSubKey = 0;
|
|
wcscat(*ppszFoundSubKey, ppszNames[i]);
|
|
*ppszFoundValueName = NULL;
|
|
goto success;
|
|
}
|
|
|
|
fKeyMatched = (_wcsicmp(ppszNames[i], szKeyName) == 0);
|
|
if (RegFindRecurse(hSubKey, ppszNames[i], (fKeyMatched ? pszValueName : NULL),
|
|
ppszFoundSubKey, ppszFoundValueName))
|
|
{
|
|
LPWSTR psz = *ppszFoundSubKey;
|
|
SIZE_T cbFoundSubKey = (wcslen(szSubKey) + wcslen(psz) + 2) * sizeof(WCHAR);
|
|
*ppszFoundSubKey = malloc(cbFoundSubKey);
|
|
if (*ppszFoundSubKey == NULL)
|
|
goto err;
|
|
if (szSubKey[0])
|
|
{
|
|
StringCbCopyW(*ppszFoundSubKey, cbFoundSubKey, szSubKey);
|
|
StringCbCatW(*ppszFoundSubKey, cbFoundSubKey, s_backslash);
|
|
}
|
|
else
|
|
**ppszFoundSubKey = 0;
|
|
wcscat(*ppszFoundSubKey, psz);
|
|
free(psz);
|
|
goto success;
|
|
}
|
|
}
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
ppszNames = NULL;
|
|
|
|
if (hBaseKey != hSubKey)
|
|
RegCloseKey(hSubKey);
|
|
}
|
|
|
|
if (*phKey == HKEY_CLASSES_ROOT)
|
|
{
|
|
*phKey = HKEY_CURRENT_USER;
|
|
if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
return TRUE;
|
|
}
|
|
|
|
if (*phKey == HKEY_CURRENT_USER)
|
|
{
|
|
*phKey = HKEY_LOCAL_MACHINE;
|
|
if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
goto success;
|
|
}
|
|
|
|
if (*phKey == HKEY_LOCAL_MACHINE)
|
|
{
|
|
*phKey = HKEY_USERS;
|
|
if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
goto success;
|
|
}
|
|
|
|
if (*phKey == HKEY_USERS)
|
|
{
|
|
*phKey = HKEY_CURRENT_CONFIG;
|
|
if (RegFindRecurse(*phKey, s_empty, NULL, ppszFoundSubKey,
|
|
ppszFoundValueName))
|
|
goto success;
|
|
}
|
|
|
|
err:
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
if (hBaseKey != hSubKey)
|
|
RegCloseKey(hSubKey);
|
|
return FALSE;
|
|
|
|
success:
|
|
if (ppszNames != NULL)
|
|
{
|
|
for(i = 0; i < c; i++)
|
|
free(ppszNames[i]);
|
|
free(ppszNames);
|
|
}
|
|
if (hBaseKey != hSubKey)
|
|
RegCloseKey(hSubKey);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static DWORD GetFindFlags(void)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwType, dwValue, cbData;
|
|
DWORD dwFlags = RSF_LOOKATKEYS | RSF_LOOKATVALUES | RSF_LOOKATDATA;
|
|
|
|
if (RegOpenKeyW(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
/* Retrieve flags from registry key */
|
|
cbData = sizeof(dwValue);
|
|
if (RegQueryValueExW(hKey, s_szFindFlags, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS)
|
|
{
|
|
if (dwType == REG_DWORD)
|
|
dwFlags = (dwFlags & ~0x0000FFFF) | ((dwValue & 0x0000FFFF) << 0);
|
|
}
|
|
|
|
/* Retrieve ReactOS Regedit specific flags from registry key */
|
|
cbData = sizeof(dwValue);
|
|
if (RegQueryValueExW(hKey, s_szFindFlagsR, NULL, &dwType, (LPBYTE) &dwValue, &cbData) == ERROR_SUCCESS)
|
|
{
|
|
if (dwType == REG_DWORD)
|
|
dwFlags = (dwFlags & ~0xFFFF0000) | ((dwValue & 0x0000FFFF) << 16);
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
return dwFlags;
|
|
}
|
|
|
|
static void SetFindFlags(DWORD dwFlags)
|
|
{
|
|
HKEY hKey;
|
|
DWORD dwDisposition;
|
|
DWORD dwData;
|
|
|
|
if (RegCreateKeyExW(HKEY_CURRENT_USER, g_szGeneralRegKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS)
|
|
{
|
|
dwData = (dwFlags >> 0) & 0x0000FFFF;
|
|
RegSetValueExW(hKey, s_szFindFlags, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData));
|
|
|
|
dwData = (dwFlags >> 16) & 0x0000FFFF;
|
|
RegSetValueExW(hKey, s_szFindFlagsR, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData));
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
static INT_PTR CALLBACK AbortFindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
UNREFERENCED_PARAMETER(hDlg);
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_CLOSE:
|
|
s_bAbort = TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(HIWORD(wParam))
|
|
{
|
|
case BN_CLICKED:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDCANCEL:
|
|
s_bAbort = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL FindNext(HWND hWnd)
|
|
{
|
|
HKEY hKeyRoot;
|
|
LPCWSTR pszKeyPath;
|
|
BOOL fSuccess;
|
|
WCHAR szFullKey[512];
|
|
LPCWSTR pszValueName;
|
|
LPWSTR pszFoundSubKey, pszFoundValueName;
|
|
|
|
if (wcslen(s_szFindWhat) == 0)
|
|
{
|
|
FindDialog(hWnd);
|
|
return TRUE;
|
|
}
|
|
|
|
s_dwFlags = GetFindFlags();
|
|
|
|
pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
|
|
if (pszKeyPath == NULL)
|
|
{
|
|
hKeyRoot = HKEY_CLASSES_ROOT;
|
|
pszKeyPath = s_empty;
|
|
}
|
|
|
|
/* Create abort find dialog */
|
|
s_hwndAbortDialog = CreateDialogW(GetModuleHandle(NULL),
|
|
MAKEINTRESOURCEW(IDD_FINDING), hWnd, AbortFindDialogProc);
|
|
if (s_hwndAbortDialog)
|
|
{
|
|
ShowWindow(s_hwndAbortDialog, SW_SHOW);
|
|
UpdateWindow(s_hwndAbortDialog);
|
|
}
|
|
s_bAbort = FALSE;
|
|
|
|
pszValueName = GetValueName(g_pChildWnd->hListWnd, -1);
|
|
|
|
EnableWindow(hFrameWnd, FALSE);
|
|
EnableWindow(g_pChildWnd->hTreeWnd, FALSE);
|
|
EnableWindow(g_pChildWnd->hListWnd, FALSE);
|
|
EnableWindow(g_pChildWnd->hAddressBarWnd, FALSE);
|
|
|
|
fSuccess = RegFindWalk(&hKeyRoot, pszKeyPath, pszValueName,
|
|
&pszFoundSubKey, &pszFoundValueName);
|
|
|
|
EnableWindow(hFrameWnd, TRUE);
|
|
EnableWindow(g_pChildWnd->hTreeWnd, TRUE);
|
|
EnableWindow(g_pChildWnd->hListWnd, TRUE);
|
|
EnableWindow(g_pChildWnd->hAddressBarWnd, TRUE);
|
|
|
|
if (s_hwndAbortDialog)
|
|
{
|
|
DestroyWindow(s_hwndAbortDialog);
|
|
s_hwndAbortDialog = NULL;
|
|
}
|
|
|
|
if (fSuccess)
|
|
{
|
|
GetKeyName(szFullKey, ARRAY_SIZE(szFullKey), hKeyRoot, pszFoundSubKey);
|
|
SelectNode(g_pChildWnd->hTreeWnd, szFullKey);
|
|
free(pszFoundSubKey);
|
|
|
|
if (pszFoundValueName != NULL)
|
|
{
|
|
SetValueName(g_pChildWnd->hListWnd, pszFoundValueName);
|
|
free(pszFoundValueName);
|
|
SetFocus(g_pChildWnd->hListWnd);
|
|
}
|
|
else
|
|
{
|
|
SetFocus(g_pChildWnd->hTreeWnd);
|
|
}
|
|
}
|
|
return fSuccess || s_bAbort;
|
|
}
|
|
|
|
static INT_PTR CALLBACK FindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
INT_PTR iResult = 0;
|
|
HWND hControl;
|
|
LONG lStyle;
|
|
DWORD dwFlags;
|
|
static WCHAR s_szSavedFindValue[256];
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
dwFlags = GetFindFlags();
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS);
|
|
if (hControl)
|
|
SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATKEYS) ? TRUE : FALSE, 0);
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
|
|
if (hControl)
|
|
SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATVALUES) ? TRUE : FALSE, 0);
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
|
|
if (hControl)
|
|
SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATDATA) ? TRUE : FALSE, 0);
|
|
|
|
/* Match whole string */
|
|
hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
|
|
if (hControl)
|
|
SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_WHOLESTRING) ? TRUE : FALSE, 0);
|
|
|
|
/* Case sensitivity */
|
|
hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
|
|
if (hControl)
|
|
SendMessageW(hControl, BM_SETCHECK, (dwFlags & RSF_MATCHCASE) ? TRUE : FALSE, 0);
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
|
|
if (hControl)
|
|
{
|
|
SetWindowTextW(hControl, s_szSavedFindValue);
|
|
SetFocus(hControl);
|
|
SendMessageW(hControl, EM_SETSEL, 0, -1);
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hDlg, 0);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch(HIWORD(wParam))
|
|
{
|
|
case BN_CLICKED:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
dwFlags = 0;
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS);
|
|
if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
|
|
dwFlags |= RSF_LOOKATKEYS;
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
|
|
if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
|
|
dwFlags |= RSF_LOOKATVALUES;
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
|
|
if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
|
|
dwFlags |= RSF_LOOKATDATA;
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
|
|
if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
|
|
dwFlags |= RSF_WHOLESTRING;
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
|
|
if (hControl && (SendMessageW(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
|
|
dwFlags |= RSF_MATCHCASE;
|
|
|
|
SetFindFlags(dwFlags);
|
|
|
|
hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
|
|
if (hControl)
|
|
GetWindowTextW(hControl, s_szFindWhat, ARRAY_SIZE(s_szFindWhat));
|
|
EndDialog(hDlg, 1);
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, 0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case EN_CHANGE:
|
|
switch(LOWORD(wParam))
|
|
{
|
|
case IDC_FINDWHAT:
|
|
GetWindowTextW((HWND) lParam, s_szSavedFindValue, ARRAY_SIZE(s_szSavedFindValue));
|
|
hControl = GetDlgItem(hDlg, IDOK);
|
|
if (hControl)
|
|
{
|
|
lStyle = GetWindowLongPtr(hControl, GWL_STYLE);
|
|
if (s_szSavedFindValue[0])
|
|
lStyle &= ~WS_DISABLED;
|
|
else
|
|
lStyle |= WS_DISABLED;
|
|
SetWindowLongPtr(hControl, GWL_STYLE, lStyle);
|
|
RedrawWindow(hControl, NULL, NULL, RDW_INVALIDATE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return iResult;
|
|
}
|
|
|
|
void FindNextMessageBox(HWND hWnd)
|
|
{
|
|
if (!FindNext(hWnd))
|
|
{
|
|
WCHAR msg[128], caption[128];
|
|
|
|
LoadStringW(hInst, IDS_FINISHEDFIND, msg, ARRAY_SIZE(msg));
|
|
LoadStringW(hInst, IDS_APP_TITLE, caption, ARRAY_SIZE(caption));
|
|
MessageBoxW(hWnd, msg, caption, MB_ICONINFORMATION);
|
|
}
|
|
}
|
|
|
|
void FindDialog(HWND hWnd)
|
|
{
|
|
if (DialogBoxParamW(GetModuleHandle(NULL), MAKEINTRESOURCEW(IDD_FIND),
|
|
hWnd, FindDialogProc, 0) != 0)
|
|
{
|
|
FindNextMessageBox(hWnd);
|
|
}
|
|
}
|