929 lines
27 KiB
C
929 lines
27 KiB
C
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORP., 1993-1994
|
||
|
*
|
||
|
* TITLE: REGFIND.C
|
||
|
*
|
||
|
* VERSION: 4.0
|
||
|
*
|
||
|
* AUTHOR: Tracy Sharpe
|
||
|
*
|
||
|
* DATE: 14 Jul 1994
|
||
|
*
|
||
|
* Find routines for the Registry Editor.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "regedit.h"
|
||
|
#include "regkey.h"
|
||
|
#include "regresid.h"
|
||
|
#include "reghelp.h"
|
||
|
#include "regvalue.h"
|
||
|
|
||
|
#define SIZE_FINDSPEC (max(MAXKEYNAME, MAXVALUENAME_LENGTH))
|
||
|
|
||
|
TCHAR s_FindSpecification[SIZE_FINDSPEC] = { 0 };
|
||
|
|
||
|
#define FIND_EXACT 0x00000001
|
||
|
#define FIND_KEYS 0x00000002
|
||
|
#define FIND_VALUES 0x00000004
|
||
|
#define FIND_DATA 0x00000008
|
||
|
|
||
|
// Initialized value is the default if we don't find last known state in the
|
||
|
// registry.
|
||
|
DWORD g_FindFlags = FIND_KEYS | FIND_VALUES | FIND_DATA;
|
||
|
|
||
|
// Global needed to monitor the find abort dialog status.
|
||
|
BOOL s_fContinueFind;
|
||
|
|
||
|
//
|
||
|
// Reference data for the RegFind dialog.
|
||
|
//
|
||
|
|
||
|
typedef struct _REGFINDDATA {
|
||
|
UINT LookForCount;
|
||
|
} REGFINDDATA;
|
||
|
|
||
|
REGFINDDATA s_RegFindData;
|
||
|
|
||
|
//
|
||
|
// Association between the items of the RegFind dialog and the find flags.
|
||
|
//
|
||
|
|
||
|
typedef struct _DLGITEMFINDFLAGASSOC {
|
||
|
int DlgItem;
|
||
|
DWORD Flag;
|
||
|
} DLGITEMFINDFLAGASSOC;
|
||
|
|
||
|
const DLGITEMFINDFLAGASSOC s_DlgItemFindFlagAssoc[] = {
|
||
|
IDC_WHOLEWORDONLY, FIND_EXACT,
|
||
|
IDC_FORKEYS, FIND_KEYS,
|
||
|
IDC_FORVALUES, FIND_VALUES,
|
||
|
IDC_FORDATA, FIND_DATA
|
||
|
};
|
||
|
|
||
|
const DWORD s_RegFindHelpIDs[] = {
|
||
|
IDC_FINDWHAT, IDH_FIND_SEARCHTEXT,
|
||
|
IDC_GROUPBOX, IDH_REGEDIT_LOOK,
|
||
|
IDC_FORKEYS, IDH_REGEDIT_LOOK,
|
||
|
IDC_FORVALUES, IDH_REGEDIT_LOOK,
|
||
|
IDC_FORDATA, IDH_REGEDIT_LOOK,
|
||
|
IDC_WHOLEWORDONLY, IDH_FIND_WHOLE,
|
||
|
IDOK, IDH_FIND_NEXT_BUTTON,
|
||
|
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
FindCompare(
|
||
|
LPTSTR lpString
|
||
|
);
|
||
|
|
||
|
INT_PTR
|
||
|
PASCAL
|
||
|
RegFindDlgProc(
|
||
|
HWND hWnd,
|
||
|
UINT Message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
RegFind_OnInitDialog(
|
||
|
HWND hWnd,
|
||
|
HWND hFocusWnd,
|
||
|
LPARAM lParam
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
PASCAL
|
||
|
RegFind_OnCommand(
|
||
|
HWND hWnd,
|
||
|
int DlgItem,
|
||
|
HWND hControlWnd,
|
||
|
UINT NotificationCode
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
RegFindAbortProc(
|
||
|
HWND hRegFindAbortWnd
|
||
|
);
|
||
|
|
||
|
INT_PTR
|
||
|
CALLBACK
|
||
|
RegFindAbortDlgProc(
|
||
|
HWND hWnd,
|
||
|
UINT Message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
);
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegEdit_OnCommandFindNext
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
VOID
|
||
|
PASCAL
|
||
|
RegEdit_OnCommandFindNext(
|
||
|
HWND hWnd,
|
||
|
BOOL fForceDialog
|
||
|
)
|
||
|
{
|
||
|
UINT uErrorStringID;
|
||
|
BOOL fError = FALSE;
|
||
|
BOOL fSearchedToEnd;
|
||
|
HWND hFocusWnd;
|
||
|
LV_ITEM LVItem;
|
||
|
TCHAR ValueName[MAXVALUENAME_LENGTH];
|
||
|
DWORD Type;
|
||
|
DWORD cbValueData;
|
||
|
TV_ITEM TVItem;
|
||
|
TCHAR KeyName[MAXKEYNAME];
|
||
|
HWND hRegFindAbortWnd;
|
||
|
HTREEITEM hTempTreeItem;
|
||
|
UINT ExpandCounter;
|
||
|
HKEY hRootKey;
|
||
|
HKEY hKey;
|
||
|
DWORD EnumIndex;
|
||
|
DWORD cbValueName;
|
||
|
BOOL fFoundMatch;
|
||
|
TCHAR BestValueName[MAXVALUENAME_LENGTH];
|
||
|
LV_FINDINFO LVFindInfo;
|
||
|
|
||
|
fSearchedToEnd = FALSE;
|
||
|
hFocusWnd = NULL;
|
||
|
hRegFindAbortWnd = NULL;
|
||
|
|
||
|
//
|
||
|
// Check if we're to show the find dialog. This is either due to the user
|
||
|
// explicitly choosing the "Find" menu item or causing a "Find Next" with
|
||
|
// the search specification being uninitialized.
|
||
|
//
|
||
|
|
||
|
if (fForceDialog || s_FindSpecification[0] == 0) {
|
||
|
|
||
|
if (DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_REGFIND), hWnd,
|
||
|
RegFindDlgProc) != IDOK)
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
RegEdit_SetWaitCursor(TRUE);
|
||
|
|
||
|
//
|
||
|
// Check if we're trying to finding either value names or data. If so,
|
||
|
// then the next match might be part of the current ValueList.
|
||
|
//
|
||
|
|
||
|
if (g_FindFlags & (FIND_VALUES | FIND_DATA)) {
|
||
|
|
||
|
LVItem.iItem = ListView_GetNextItem(g_RegEditData.hValueListWnd, -1,
|
||
|
LVNI_FOCUSED);
|
||
|
LVItem.iSubItem = 0;
|
||
|
LVItem.mask = LVIF_TEXT;
|
||
|
LVItem.pszText = ValueName;
|
||
|
LVItem.cchTextMax = sizeof(ValueName)/sizeof(TCHAR);
|
||
|
|
||
|
//
|
||
|
// Walk over all of the rest of the value names attempting to find a
|
||
|
// match.
|
||
|
//
|
||
|
|
||
|
while ((LVItem.iItem = ListView_GetNextItem(g_RegEditData.hValueListWnd,
|
||
|
LVItem.iItem, LVNI_ALL)) != -1) {
|
||
|
|
||
|
ListView_GetItem(g_RegEditData.hValueListWnd, &LVItem);
|
||
|
|
||
|
//
|
||
|
// Check if this value name meets our search specification. We'll
|
||
|
// assume that this value name still exists.
|
||
|
//
|
||
|
|
||
|
if ((g_FindFlags & FIND_VALUES) && FindCompare(ValueName))
|
||
|
goto SelectListItem;
|
||
|
|
||
|
//
|
||
|
// Check if this value data meets our search specification. We'll
|
||
|
// have to go back to the registry to determine this.
|
||
|
//
|
||
|
|
||
|
if (g_FindFlags & FIND_DATA)
|
||
|
{
|
||
|
if ((RegEdit_QueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
|
||
|
NULL, &Type, NULL, &cbValueData) == ERROR_SUCCESS) &&
|
||
|
IsRegStringType(Type))
|
||
|
{
|
||
|
// Allocate storage space
|
||
|
PBYTE pbDataValue = (PBYTE)LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type));
|
||
|
if (pbDataValue)
|
||
|
{
|
||
|
BOOL fSuccess = FALSE;
|
||
|
|
||
|
if (RegEdit_QueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
|
||
|
NULL, &Type, pbDataValue, &cbValueData) == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (Type == REG_MULTI_SZ)
|
||
|
{
|
||
|
EDITVALUEPARAM evp;
|
||
|
evp.pValueData = pbDataValue;
|
||
|
evp.cbValueData = cbValueData;
|
||
|
|
||
|
if (ValueList_MultiStringToString(&evp))
|
||
|
{
|
||
|
pbDataValue = evp.pValueData;
|
||
|
}
|
||
|
}
|
||
|
fSuccess = FindCompare((PTSTR)pbDataValue);
|
||
|
}
|
||
|
|
||
|
LocalFree(pbDataValue);
|
||
|
if (fSuccess)
|
||
|
{
|
||
|
goto SelectListItem;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fError = TRUE;
|
||
|
uErrorStringID = IDS_NOMEMORY;
|
||
|
goto DismissRegFindAbortWnd;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Searching the registry (especially with this code!) is a lengthy
|
||
|
// operation, so we must provide a way for the user to cancel the
|
||
|
// operation.
|
||
|
//
|
||
|
|
||
|
s_fContinueFind = TRUE;
|
||
|
|
||
|
if ((hRegFindAbortWnd = CreateDialog(g_hInstance,
|
||
|
MAKEINTRESOURCE(IDD_REGFINDABORT), hWnd, RegFindAbortDlgProc)) !=
|
||
|
NULL) {
|
||
|
|
||
|
EnableWindow(hWnd, FALSE);
|
||
|
|
||
|
//
|
||
|
// Major hack: The following code sequence relies heavily on the
|
||
|
// TreeView to maintain the state of the find process. Even though I'm
|
||
|
// inserting and deleting non-visible tree items, the TreeView
|
||
|
// currently flickers despite this.
|
||
|
//
|
||
|
// So, we set this internal flag and turn off the TreeView's redraw
|
||
|
// flag. Whenever we get a WM_PAINT message for our main window, we
|
||
|
// temporarily "let" it redraw itself then and only then. That way,
|
||
|
// the user can move the modeless abort dialog or switch away and back
|
||
|
// and still have the TreeView look normal.
|
||
|
//
|
||
|
// Yes, it's difficult at this time to fix the TreeView's paint logic.
|
||
|
//
|
||
|
|
||
|
g_RegEditData.fProcessingFind = TRUE;
|
||
|
SetWindowRedraw(g_RegEditData.hKeyTreeWnd, FALSE);
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Either the user wasn't trying to find value names or data or else no
|
||
|
// matches were found. This means that we must move on to the next branch
|
||
|
// of the registry.
|
||
|
//
|
||
|
// We first walk into the children of the current branch, then the
|
||
|
// siblings, and finally pop back through the parent.
|
||
|
//
|
||
|
// We use the information already in the KeyTree pane as much as possible.
|
||
|
//
|
||
|
|
||
|
ExpandCounter = 0;
|
||
|
fFoundMatch = FALSE;
|
||
|
BestValueName[0] = '\0';
|
||
|
|
||
|
TVItem.mask = TVIF_TEXT | TVIF_STATE | TVIF_CHILDREN;
|
||
|
TVItem.pszText = KeyName;
|
||
|
TVItem.cchTextMax = sizeof(KeyName)/sizeof(TCHAR);
|
||
|
|
||
|
TVItem.hItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
|
||
|
TreeView_GetItem(g_RegEditData.hKeyTreeWnd, &TVItem);
|
||
|
|
||
|
while (TRUE) {
|
||
|
|
||
|
//
|
||
|
// Check if we should cancel the find operation. If so, restore our
|
||
|
// initial state and exit.
|
||
|
//
|
||
|
|
||
|
if (!RegFindAbortProc(hRegFindAbortWnd)) {
|
||
|
|
||
|
if (ExpandCounter) {
|
||
|
|
||
|
hTempTreeItem = TVItem.hItem;
|
||
|
|
||
|
do {
|
||
|
|
||
|
hTempTreeItem =
|
||
|
TreeView_GetParent(g_RegEditData.hKeyTreeWnd,
|
||
|
hTempTreeItem);
|
||
|
|
||
|
} while (--ExpandCounter);
|
||
|
|
||
|
TreeView_Expand(g_RegEditData.hKeyTreeWnd, hTempTreeItem,
|
||
|
TVE_COLLAPSE | TVE_COLLAPSERESET);
|
||
|
|
||
|
}
|
||
|
|
||
|
goto DismissRegFindAbortWnd;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Does this branch have any children? This would have been determined
|
||
|
// when the tree item was built by the routine KeyTree_ExpandBranch.
|
||
|
//
|
||
|
|
||
|
if (TVItem.cChildren) {
|
||
|
|
||
|
//
|
||
|
// The branch may have children, but it may not have been expanded
|
||
|
// yet.
|
||
|
//
|
||
|
|
||
|
if ((hTempTreeItem = TreeView_GetChild(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem)) == NULL) {
|
||
|
|
||
|
if (!KeyTree_ExpandBranch(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem))
|
||
|
goto SkipToSibling;
|
||
|
|
||
|
if ((hTempTreeItem = TreeView_GetChild(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem)) == NULL)
|
||
|
goto SkipToSibling;
|
||
|
|
||
|
ExpandCounter++;
|
||
|
|
||
|
}
|
||
|
|
||
|
TVItem.hItem = hTempTreeItem;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// The branch doesn't have any children, so we'll move on to the next
|
||
|
// sibling of the current branch. If none exists, then try finding
|
||
|
// the next sibling of the parent branch, and so on.
|
||
|
//
|
||
|
|
||
|
else {
|
||
|
|
||
|
SkipToSibling:
|
||
|
while (TRUE) {
|
||
|
|
||
|
if ((hTempTreeItem =
|
||
|
TreeView_GetNextSibling(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem)) != NULL) {
|
||
|
|
||
|
TVItem.hItem = hTempTreeItem;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If no more parents exist, then we've finished searching the
|
||
|
// tree. We're outta here!
|
||
|
//
|
||
|
|
||
|
if ((TVItem.hItem =
|
||
|
TreeView_GetParent(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem)) == NULL) {
|
||
|
|
||
|
fSearchedToEnd = TRUE;
|
||
|
|
||
|
goto DismissRegFindAbortWnd;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (ExpandCounter) {
|
||
|
|
||
|
ExpandCounter--;
|
||
|
|
||
|
TreeView_Expand(g_RegEditData.hKeyTreeWnd, TVItem.hItem,
|
||
|
TVE_COLLAPSE | TVE_COLLAPSERESET);
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we made it this far, then we're at the next branch of the
|
||
|
// registry to evaluate.
|
||
|
//
|
||
|
|
||
|
TreeView_GetItem(g_RegEditData.hKeyTreeWnd, &TVItem);
|
||
|
|
||
|
//
|
||
|
// Check if we're trying to find keys.
|
||
|
//
|
||
|
|
||
|
if (g_FindFlags & FIND_KEYS) {
|
||
|
|
||
|
if (FindCompare(KeyName))
|
||
|
goto SelectTreeItem;
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check if we're trying to find value names or data.
|
||
|
//
|
||
|
|
||
|
if (g_FindFlags & (FIND_VALUES | FIND_DATA)) {
|
||
|
|
||
|
//
|
||
|
// Try to open the registry at the new current branch.
|
||
|
//
|
||
|
|
||
|
hRootKey = KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd,
|
||
|
TVItem.hItem, KeyName, BKP_TOSUBKEY);
|
||
|
|
||
|
if(hRootKey && RegOpenKeyEx(hRootKey,KeyName,0,KEY_QUERY_VALUE,&hKey) ==
|
||
|
ERROR_SUCCESS) {
|
||
|
|
||
|
//
|
||
|
// Here's the simple case-- we're trying to find an exact match
|
||
|
// for a value name. We can just use the registry API to do
|
||
|
// this for us!
|
||
|
//
|
||
|
|
||
|
if ((g_FindFlags & (FIND_VALUES | FIND_DATA | FIND_EXACT)) ==
|
||
|
(FIND_VALUES | FIND_EXACT)) {
|
||
|
|
||
|
if (RegEdit_QueryValueEx(hKey, s_FindSpecification, NULL, NULL,
|
||
|
NULL, NULL) == ERROR_SUCCESS) {
|
||
|
|
||
|
lstrcpy(BestValueName, s_FindSpecification);
|
||
|
fFoundMatch = TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Bummer... we need to walk through all of the registry
|
||
|
// value/data pairs for this key to try to find a match. Even
|
||
|
// worse, we have to look at _all_ of the entries, not just the
|
||
|
// first hit... we must display the first alphabetically
|
||
|
// matching entry!
|
||
|
//
|
||
|
|
||
|
else {
|
||
|
|
||
|
EnumIndex = 0;
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
cbValueName = sizeof(ValueName)/sizeof(TCHAR);
|
||
|
|
||
|
if (RegEnumValue(hKey, EnumIndex++, ValueName,
|
||
|
&cbValueName, NULL, &Type, NULL,
|
||
|
&cbValueData) == ERROR_SUCCESS)
|
||
|
{
|
||
|
PBYTE pbValueData = (g_FindFlags & FIND_DATA) ?
|
||
|
(PBYTE)LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type)) : NULL;
|
||
|
|
||
|
if (pbValueData || !(g_FindFlags & FIND_DATA))
|
||
|
{
|
||
|
if (RegEdit_QueryValueEx(hKey, ValueName, NULL, &Type,
|
||
|
pbValueData, &cbValueData) == ERROR_SUCCESS)
|
||
|
{
|
||
|
if (pbValueData && (Type == REG_MULTI_SZ))
|
||
|
{
|
||
|
EDITVALUEPARAM evp;
|
||
|
evp.pValueData = pbValueData;
|
||
|
evp.cbValueData = cbValueData;
|
||
|
|
||
|
if (ValueList_MultiStringToString(&evp))
|
||
|
{
|
||
|
pbValueData = evp.pValueData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (((g_FindFlags & FIND_VALUES) &&
|
||
|
FindCompare(ValueName)) ||
|
||
|
((g_FindFlags & FIND_DATA) && IsRegStringType(Type) &&
|
||
|
FindCompare((PTSTR)pbValueData)))
|
||
|
{
|
||
|
//
|
||
|
// We've got to check if we've found a "better"
|
||
|
// value name to display-- one that's at the top of
|
||
|
// the sorted list.
|
||
|
//
|
||
|
|
||
|
if (fFoundMatch) {
|
||
|
|
||
|
if (lstrcmpi(BestValueName, ValueName) > 0)
|
||
|
lstrcpy(BestValueName, ValueName);
|
||
|
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
|
||
|
lstrcpy(BestValueName, ValueName);
|
||
|
fFoundMatch = TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
if (pbValueData)
|
||
|
{
|
||
|
LocalFree(pbValueData);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
fError = TRUE;
|
||
|
uErrorStringID = IDS_NOMEMORY;
|
||
|
goto DismissRegFindAbortWnd;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
RegCloseKey(hKey);
|
||
|
|
||
|
if (fFoundMatch)
|
||
|
goto SelectTreeItem;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
SelectTreeItem:
|
||
|
TreeView_EnsureVisible(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
|
||
|
TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
|
||
|
|
||
|
if (!fFoundMatch)
|
||
|
hFocusWnd = g_RegEditData.hKeyTreeWnd;
|
||
|
|
||
|
else {
|
||
|
|
||
|
//
|
||
|
// Right now, the TreeView_SelectItem above will cause the ValueListWnd
|
||
|
// to update, but only after a short time delay. We want the list
|
||
|
// immediately updated, so force the timer to go off now.
|
||
|
//
|
||
|
|
||
|
RegEdit_OnSelChangedTimer(hWnd);
|
||
|
|
||
|
if (BestValueName[0] == 0)
|
||
|
LVItem.iItem = 0;
|
||
|
|
||
|
else {
|
||
|
|
||
|
LVFindInfo.flags = LVFI_STRING;
|
||
|
LVFindInfo.psz = BestValueName;
|
||
|
|
||
|
LVItem.iItem = ListView_FindItem(g_RegEditData.hValueListWnd,
|
||
|
-1, &LVFindInfo);
|
||
|
|
||
|
}
|
||
|
|
||
|
SelectListItem:
|
||
|
ListView_SetItemState(g_RegEditData.hValueListWnd, -1, 0,
|
||
|
LVIS_SELECTED | LVIS_FOCUSED);
|
||
|
ListView_SetItemState(g_RegEditData.hValueListWnd, LVItem.iItem,
|
||
|
LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
|
||
|
ListView_EnsureVisible(g_RegEditData.hValueListWnd, LVItem.iItem,
|
||
|
FALSE);
|
||
|
|
||
|
hFocusWnd = g_RegEditData.hValueListWnd;
|
||
|
|
||
|
}
|
||
|
|
||
|
DismissRegFindAbortWnd:
|
||
|
RegEdit_SetWaitCursor(FALSE);
|
||
|
|
||
|
if (hRegFindAbortWnd != NULL) {
|
||
|
|
||
|
g_RegEditData.fProcessingFind = FALSE;
|
||
|
SetWindowRedraw(g_RegEditData.hKeyTreeWnd, TRUE);
|
||
|
|
||
|
EnableWindow(hWnd, TRUE);
|
||
|
DestroyWindow(hRegFindAbortWnd);
|
||
|
|
||
|
}
|
||
|
|
||
|
if (hFocusWnd != NULL)
|
||
|
SetFocus(hFocusWnd);
|
||
|
|
||
|
if (fError)
|
||
|
{
|
||
|
InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(uErrorStringID),
|
||
|
MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
|
||
|
}
|
||
|
|
||
|
if (fSearchedToEnd)
|
||
|
InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(IDS_SEARCHEDTOEND),
|
||
|
MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONINFORMATION | MB_OK);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* FindCompare
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
FindCompare(
|
||
|
LPTSTR lpString
|
||
|
)
|
||
|
{
|
||
|
|
||
|
if (g_FindFlags & FIND_EXACT)
|
||
|
return lstrcmpi(lpString, s_FindSpecification) == 0;
|
||
|
|
||
|
else
|
||
|
return StrStrI(lpString, s_FindSpecification) != NULL;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegFindDlgProc
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
INT_PTR
|
||
|
PASCAL
|
||
|
RegFindDlgProc(
|
||
|
HWND hWnd,
|
||
|
UINT Message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
|
||
|
switch (Message) {
|
||
|
|
||
|
HANDLE_MSG(hWnd, WM_INITDIALOG, RegFind_OnInitDialog);
|
||
|
HANDLE_MSG(hWnd, WM_COMMAND, RegFind_OnCommand);
|
||
|
|
||
|
case WM_HELP:
|
||
|
WinHelp(((LPHELPINFO) lParam)-> hItemHandle, g_pHelpFileName,
|
||
|
HELP_WM_HELP, (ULONG_PTR) s_RegFindHelpIDs);
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU:
|
||
|
WinHelp((HWND) wParam, g_pHelpFileName, HELP_CONTEXTMENU,
|
||
|
(ULONG_PTR) s_RegFindHelpIDs);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegFind_OnInitDialog
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
RegFind_OnInitDialog(
|
||
|
HWND hWnd,
|
||
|
HWND hFocusWnd,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
|
||
|
UINT Counter;
|
||
|
int DlgItem;
|
||
|
|
||
|
//
|
||
|
// Initialize the "Find What" edit control.
|
||
|
//
|
||
|
|
||
|
SendDlgItemMessage(hWnd, IDC_FINDWHAT, EM_SETLIMITTEXT,
|
||
|
SIZE_FINDSPEC, 0);
|
||
|
SetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification);
|
||
|
|
||
|
//
|
||
|
// Initialize the checkboxes based on the state of the global find flags.
|
||
|
//
|
||
|
|
||
|
s_RegFindData.LookForCount = 0;
|
||
|
|
||
|
for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) /
|
||
|
sizeof(DLGITEMFINDFLAGASSOC); Counter++) {
|
||
|
|
||
|
if (g_FindFlags & s_DlgItemFindFlagAssoc[Counter].Flag) {
|
||
|
|
||
|
DlgItem = s_DlgItemFindFlagAssoc[Counter].DlgItem;
|
||
|
|
||
|
CheckDlgButton(hWnd, DlgItem, TRUE);
|
||
|
|
||
|
if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA)
|
||
|
s_RegFindData.LookForCount++;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
UNREFERENCED_PARAMETER(hFocusWnd);
|
||
|
UNREFERENCED_PARAMETER(lParam);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegFind_OnCommand
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
VOID
|
||
|
PASCAL
|
||
|
RegFind_OnCommand(
|
||
|
HWND hWnd,
|
||
|
int DlgItem,
|
||
|
HWND hControlWnd,
|
||
|
UINT NotificationCode
|
||
|
)
|
||
|
{
|
||
|
|
||
|
UINT Counter;
|
||
|
|
||
|
if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA) {
|
||
|
|
||
|
if (NotificationCode == BN_CLICKED) {
|
||
|
|
||
|
IsDlgButtonChecked(hWnd, DlgItem) ? s_RegFindData.LookForCount++ :
|
||
|
s_RegFindData.LookForCount--;
|
||
|
|
||
|
goto EnableFindNextButton;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
else {
|
||
|
|
||
|
switch (DlgItem) {
|
||
|
|
||
|
case IDC_FINDWHAT:
|
||
|
if (NotificationCode == EN_CHANGE) {
|
||
|
|
||
|
EnableFindNextButton:
|
||
|
EnableWindow(GetDlgItem(hWnd, IDOK),
|
||
|
s_RegFindData.LookForCount > 0 &&
|
||
|
SendDlgItemMessage(hWnd, IDC_FINDWHAT,
|
||
|
WM_GETTEXTLENGTH, 0, 0) != 0);
|
||
|
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDOK:
|
||
|
GetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification,
|
||
|
sizeof(s_FindSpecification)/sizeof(TCHAR));
|
||
|
|
||
|
for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) /
|
||
|
sizeof(DLGITEMFINDFLAGASSOC); Counter++) {
|
||
|
|
||
|
if (IsDlgButtonChecked(hWnd,
|
||
|
s_DlgItemFindFlagAssoc[Counter].DlgItem))
|
||
|
g_FindFlags |= s_DlgItemFindFlagAssoc[Counter].Flag;
|
||
|
else
|
||
|
g_FindFlags &= ~s_DlgItemFindFlagAssoc[Counter].Flag;
|
||
|
|
||
|
}
|
||
|
|
||
|
// FALL THROUGH
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog(hWnd, DlgItem);
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegFindAbortProc
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* (returns), TRUE to continue the find, else FALSE to cancel.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
PASCAL
|
||
|
RegFindAbortProc(
|
||
|
HWND hRegFindAbortWnd
|
||
|
)
|
||
|
{
|
||
|
|
||
|
while (s_fContinueFind && MessagePump(hRegFindAbortWnd))
|
||
|
;
|
||
|
|
||
|
return s_fContinueFind;
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* RegAbortDlgProc
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Callback procedure for the RegAbort dialog box.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
* hWnd, handle of RegAbort window.
|
||
|
* Message,
|
||
|
* wParam,
|
||
|
* lParam,
|
||
|
* (returns),
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
INT_PTR
|
||
|
CALLBACK
|
||
|
RegFindAbortDlgProc(
|
||
|
HWND hWnd,
|
||
|
UINT Message,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
|
||
|
switch (Message) {
|
||
|
|
||
|
case WM_INITDIALOG:
|
||
|
break;
|
||
|
|
||
|
case WM_CLOSE:
|
||
|
case WM_COMMAND:
|
||
|
s_fContinueFind = FALSE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|