Regedit:  Partially implemented Find/Find Next

Currently only implemented "Search Key Names"; searching key values and data not yet implemented.  Also, the searching algorithm is pretty crude right now.
Modified: trunk/reactos/subsys/system/regedit/De.rc
Modified: trunk/reactos/subsys/system/regedit/En.rc
Modified: trunk/reactos/subsys/system/regedit/childwnd.c
Added: trunk/reactos/subsys/system/regedit/find.c
Modified: trunk/reactos/subsys/system/regedit/framewnd.c
Modified: trunk/reactos/subsys/system/regedit/main.c
Modified: trunk/reactos/subsys/system/regedit/main.h
Modified: trunk/reactos/subsys/system/regedit/regedit.xml
Modified: trunk/reactos/subsys/system/regedit/regproc.c
Modified: trunk/reactos/subsys/system/regedit/regproc.h
Modified: trunk/reactos/subsys/system/regedit/resource.h

Modified: trunk/reactos/subsys/system/regedit/De.rc
--- trunk/reactos/subsys/system/regedit/De.rc	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/De.rc	2005-11-27 23:23:38 UTC (rev 19712)
@@ -366,7 +366,7 @@
     PUSHBUTTON      "A&bbrechen",IDCANCEL,197,24,50,14
     GROUPBOX        "Look at",IDC_STATIC,7,25,63,51
     LTEXT           "Suche &nach:",IDC_STATIC,7,8,37,10
-    EDITTEXT        IDD_FINDWHAT,47,7,142,13,ES_AUTOHSCROLL
+    EDITTEXT        IDC_FINDWHAT,47,7,142,13,ES_AUTOHSCROLL
     CONTROL         "&Schl³ssel",IDC_LOOKAT_KEYS,"Button",BS_AUTOCHECKBOX | 
                     WS_TABSTOP,14,36,35,8
     CONTROL         "&Werte",IDC_LOOKAT_VALUES,"Button",BS_AUTOCHECKBOX | 

Modified: trunk/reactos/subsys/system/regedit/En.rc
--- trunk/reactos/subsys/system/regedit/En.rc	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/En.rc	2005-11-27 23:23:38 UTC (rev 19712)
@@ -81,8 +81,8 @@
         MENUITEM SEPARATOR
         MENUITEM "&Copy Key Name",              ID_EDIT_COPYKEYNAME
         MENUITEM SEPARATOR
-        MENUITEM "&Find\tCtrl+F",               ID_EDIT_FIND, GRAYED
-        MENUITEM "Find Ne&xt\tF3",              ID_EDIT_FINDNEXT, GRAYED
+        MENUITEM "&Find\tCtrl+F",               ID_EDIT_FIND
+        MENUITEM "Find Ne&xt\tF3",              ID_EDIT_FINDNEXT
     END
     POPUP "&View"
     BEGIN
@@ -139,7 +139,7 @@
             MENUITEM "&Binary Value",               ID_EDIT_NEW_BINARYVALUE
             MENUITEM "&DWORD Value",                ID_EDIT_NEW_DWORDVALUE
         END
-        MENUITEM "&Find",                           ID_EDIT_FIND, GRAYED
+        MENUITEM "&Find",                           ID_EDIT_FIND
         MENUITEM SEPARATOR
         MENUITEM "&Delete",                         ID_TREE_DELETE
         MENUITEM "&Rename",                         ID_TREE_RENAME
@@ -351,6 +351,7 @@
   IDS_EXPAND                     "&Expand"
   IDS_COLLAPSE                   "&Collapse"
   IDS_GOTO_SUGGESTED_KEY         "&Go to '%s'"
+  IDS_FINISHEDFIND               "Finished searching through the registry."
 END
 
 /*****************************************************************/
@@ -403,7 +404,7 @@
     PUSHBUTTON      "Cancel",IDCANCEL,197,24,50,14
     GROUPBOX        "Look at",IDC_STATIC,7,25,63,51
     LTEXT           "Fi&nd what:",IDC_STATIC,7,8,37,10
-    EDITTEXT        IDD_FINDWHAT,47,7,142,13,ES_AUTOHSCROLL
+    EDITTEXT        IDC_FINDWHAT,47,7,142,13,ES_AUTOHSCROLL
     CONTROL         "&Keys",IDC_LOOKAT_KEYS,"Button",BS_AUTOCHECKBOX | 
                     WS_TABSTOP,14,36,35,8
     CONTROL         "&Values",IDC_LOOKAT_VALUES,"Button",BS_AUTOCHECKBOX | 
@@ -416,6 +417,17 @@
                     WS_TABSTOP,83,48,90,12
 END
 
+IDD_FINDING DIALOGEX 0, 0, 145, 50
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | 
+    WS_CAPTION | WS_SYSMENU
+CAPTION "Find"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    ICON            IDI_REGEDIT,IDC_STATIC,7,7,20,20
+    PUSHBUTTON      "&Cancel",IDCANCEL,93,29,45,14
+    LTEXT           "Searching the registry...",IDC_STATIC,33,12,83,8
+END
+
 /*
  * TEXTINCLUDE
  */

Modified: trunk/reactos/subsys/system/regedit/childwnd.c
--- trunk/reactos/subsys/system/regedit/childwnd.c	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/childwnd.c	2005-11-27 23:23:38 UTC (rev 19712)
@@ -142,6 +142,9 @@
 	case ID_TREE_EXPORT:
         ExportRegistryFile(pChildWnd->hTreeWnd);
         break;
+	case ID_EDIT_FIND:
+        FindDialog(hWnd);
+        break;
     case ID_EDIT_COPYKEYNAME:
         hSelection = TreeView_GetSelection(pChildWnd->hTreeWnd);
         keyPath = GetItemPath(pChildWnd->hTreeWnd, hSelection, &hRootKey);

Added: trunk/reactos/subsys/system/regedit/find.c
--- trunk/reactos/subsys/system/regedit/find.c	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/find.c	2005-11-27 23:23:38 UTC (rev 19712)
@@ -0,0 +1,314 @@
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include <windows.h>
+#include <tchar.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <cderr.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <shellapi.h>
+#include <objsel.h>
+#include <objbase.h>
+#include <ole2.h>
+
+#include "main.h"
+#include "regproc.h"
+
+static TCHAR s_szFindWhat[256];
+static const TCHAR s_szFindFlags[] = _T("FindFlags");
+static const TCHAR s_szFindFlagsR[] = _T("FindFlagsReactOS");
+static HWND s_hwndAbortDialog;
+static BOOL s_bAbort;
+
+
+
+static DWORD GetFindFlags(void)
+{
+    HKEY hKey;
+    DWORD dwFlags = RSF_LOOKATKEYS;
+    DWORD dwType, dwValue, cbData;
+
+    if (RegOpenKey(HKEY_CURRENT_USER, g_szGeneralRegKey, &hKey) == ERROR_SUCCESS)
+    {
+        /* Retrieve flags from registry key */
+        cbData = sizeof(dwValue);
+        if (RegQueryValueEx(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 (RegQueryValueEx(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 (RegCreateKeyEx(HKEY_CURRENT_USER, g_szGeneralRegKey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS)
+    {
+        dwData = (dwFlags >> 0) & 0x0000FFFF;
+        RegSetValueEx(hKey, s_szFindFlags, 0, REG_DWORD, (const BYTE *) &dwData, sizeof(dwData));
+
+        dwData = (dwFlags >> 16) & 0x0000FFFF;
+        RegSetValueEx(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)
+{
+    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;
+}
+
+static BOOL RegSearchProc(LPVOID lpParam)
+{
+    MSG msg;
+
+    if (s_hwndAbortDialog && PeekMessage(&msg, s_hwndAbortDialog, 0, 0, PM_REMOVE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+    }
+    return s_bAbort;
+}
+
+BOOL FindNext(HWND hWnd)
+{
+    HKEY hKeyRoot;
+    LPCTSTR pszFindWhat;
+    LPCTSTR pszKeyPath;
+    DWORD dwFlags;
+    LONG lResult;
+    TCHAR szSubKey[512];
+    TCHAR szError[512];
+    TCHAR szTitle[64];
+    TCHAR szFullKey[512];
+
+    pszFindWhat = s_szFindWhat;
+    dwFlags = GetFindFlags() & ~(RSF_LOOKATVALUES | RSF_LOOKATDATA);
+
+    pszKeyPath = GetItemPath(g_pChildWnd->hTreeWnd, 0, &hKeyRoot);
+    lstrcpyn(szSubKey, pszKeyPath, sizeof(szSubKey) / sizeof(szSubKey[0]));
+
+    /* Create abort find dialog */
+    s_hwndAbortDialog = CreateDialog(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_FINDING), hWnd, AbortFindDialogProc);
+    if (s_hwndAbortDialog)
+        ShowWindow(s_hwndAbortDialog, SW_SHOW);
+    s_bAbort = FALSE;
+
+    lResult = RegSearch(hKeyRoot, szSubKey, sizeof(szSubKey) / sizeof(szSubKey[0]),
+        pszFindWhat, 0, dwFlags, RegSearchProc, NULL);
+
+    if (s_hwndAbortDialog)
+    {
+        DestroyWindow(s_hwndAbortDialog);
+        s_hwndAbortDialog = NULL;
+    }
+
+    /* Did the user click "Cancel"?  If so, exit without displaying an error message */
+    if (lResult == ERROR_OPERATION_ABORTED)
+        return FALSE;
+
+    if (lResult != ERROR_SUCCESS)
+    {
+        LoadString(NULL, IDS_APP_TITLE, szTitle, sizeof(szTitle) / sizeof(szTitle[0]));
+
+        if ((lResult != ERROR_NO_MORE_ITEMS) || !LoadString(NULL, IDS_FINISHEDFIND, szError, sizeof(szError) / sizeof(szError[0])))
+        {
+            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lResult, 0,
+                szError, sizeof(szError) / sizeof(szError[0]), NULL);
+        }
+        MessageBox(hWnd, szError, szTitle, MB_OK);
+        return FALSE;
+    }
+
+    RegKeyGetName(szFullKey, sizeof(szFullKey) / sizeof(szFullKey[0]), hKeyRoot, szSubKey);
+    SelectNode(g_pChildWnd->hTreeWnd, szFullKey);
+    return TRUE;
+}
+
+static INT_PTR CALLBACK FindDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    INT_PTR iResult = 0;
+    HWND hControl;
+    LONG lStyle;
+    DWORD dwFlags;
+    static TCHAR s_szSavedFindValue[256];
+
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            dwFlags = GetFindFlags();
+
+            /* Looking at values is not yet implemented */
+            hControl = GetDlgItem(hDlg, IDC_LOOKAT_KEYS);
+            if (hControl)
+                SendMessage(hControl, BM_SETCHECK, (dwFlags & RSF_LOOKATKEYS) ? TRUE : FALSE, 0);
+
+            /* Looking at values is not yet implemented */
+            hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
+            if (hControl)
+            {
+                lStyle = GetWindowLong(hControl, GWL_STYLE);
+                SetWindowLong(hControl, GWL_STYLE, lStyle | WS_DISABLED);
+            }
+
+            /* Looking at data is not yet implemented */
+            hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
+            if (hControl)
+            {
+                lStyle = GetWindowLong(hControl, GWL_STYLE);
+                SetWindowLong(hControl, GWL_STYLE, lStyle | WS_DISABLED);
+            }
+
+            /* Match whole string */
+            hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
+            if (hControl)
+                SendMessage(hControl, BM_SETCHECK, (dwFlags & RSF_WHOLESTRING) ? TRUE : FALSE, 0);
+
+            /* Case sensitivity */
+            hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
+            if (hControl)
+                SendMessage(hControl, BM_SETCHECK, (dwFlags & RSF_MATCHCASE) ? TRUE : FALSE, 0);
+
+            hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
+            if (hControl)
+            {
+                SetWindowText(hControl, s_szSavedFindValue);
+                SetFocus(hControl);
+                SendMessage(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 && (SendMessage(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
+                                dwFlags |= RSF_LOOKATKEYS;
+
+                            hControl = GetDlgItem(hDlg, IDC_LOOKAT_VALUES);
+                            if (hControl && (SendMessage(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
+                                dwFlags |= RSF_LOOKATVALUES;
+
+                            hControl = GetDlgItem(hDlg, IDC_LOOKAT_DATA);
+                            if (hControl && (SendMessage(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
+                                dwFlags |= RSF_LOOKATDATA;
+
+                            hControl = GetDlgItem(hDlg, IDC_MATCHSTRING);
+                            if (hControl && (SendMessage(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
+                                dwFlags |= RSF_WHOLESTRING;
+
+                            hControl = GetDlgItem(hDlg, IDC_MATCHCASE);
+                            if (hControl && (SendMessage(hControl, BM_GETCHECK, 0, 0) == BST_CHECKED))
+                                dwFlags |= RSF_MATCHCASE;
+
+                            SetFindFlags(dwFlags);
+
+                            hControl = GetDlgItem(hDlg, IDC_FINDWHAT);
+                            if (hControl)
+                                GetWindowText(hControl, s_szFindWhat, sizeof(s_szFindWhat) / sizeof(s_szFindWhat[0]));
+                            EndDialog(hDlg, 1);
+                            break;
+
+                        case IDCANCEL:
+                            EndDialog(hDlg, 0);
+                            break;
+                    }
+                    break;
+
+                case EN_CHANGE:
+                    switch(LOWORD(wParam))
+                    {
+                        case IDC_FINDWHAT:
+                            GetWindowText((HWND) lParam, s_szSavedFindValue, sizeof(s_szSavedFindValue) / sizeof(s_szSavedFindValue[0]));
+                            hControl = GetDlgItem(hDlg, IDOK);
+                            if (hControl)
+                            {
+                                lStyle = GetWindowLong(hControl, GWL_STYLE);
+                                if (s_szSavedFindValue[0])
+                                    lStyle &= ~WS_DISABLED;
+                                else
+                                    lStyle |= WS_DISABLED;
+                                SetWindowLong(hControl, GWL_STYLE, lStyle);
+                                RedrawWindow(hControl, NULL, NULL, RDW_INVALIDATE);
+                            }
+                            break;
+                    }
+            }
+            break;
+    }
+    return iResult;
+}
+
+void FindDialog(HWND hWnd)
+{
+    if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_FIND),
+        hWnd, FindDialogProc, 0) != 0)
+    {
+        FindNext(hWnd);
+    }
+}
+
Property changes on: trunk/reactos/subsys/system/regedit/find.c
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: trunk/reactos/subsys/system/regedit/framewnd.c
--- trunk/reactos/subsys/system/regedit/framewnd.c	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/framewnd.c	2005-11-27 23:23:38 UTC (rev 19712)
@@ -905,7 +905,7 @@
         break;
     case ID_EDIT_DELETE:
     {
-	if (GetFocus() == g_pChildWnd->hListWnd)
+        if (GetFocus() == g_pChildWnd->hListWnd)
         {
           UINT nSelected = ListView_GetSelectedCount(g_pChildWnd->hListWnd);
           if(nSelected >= 1)
@@ -966,6 +966,12 @@
         break;
 
     }
+    case ID_EDIT_FIND:
+        FindDialog(hWnd);
+        break;
+    case ID_EDIT_FINDNEXT:
+        FindNext(hWnd);
+        break;
     case ID_EDIT_COPYKEYNAME:
         CopyKeyName(hWnd, hKeyRoot, keyPath);
         break;

Modified: trunk/reactos/subsys/system/regedit/main.c
--- trunk/reactos/subsys/system/regedit/main.c	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/main.c	2005-11-27 23:23:38 UTC (rev 19712)
@@ -50,6 +50,7 @@
 HMENU hPopupMenus = 0;
 UINT nClipboardFormat;
 LPCTSTR strClipboardFormat = _T("TODO: SET CORRECT FORMAT");
+const TCHAR g_szGeneralRegKey[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit");
 
 
 #define MAX_LOADSTRING  100
@@ -162,8 +163,7 @@
     }
 
     /* Restore position */
-    if (RegQueryStringValue(HKEY_CURRENT_USER,
-        _T("Software\\Microsoft\\Windows\\CurrentVersion\\Applets\\Regedit"),
+    if (RegQueryStringValue(HKEY_CURRENT_USER, g_szGeneralRegKey,
         _T("LastKey"),
         szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])) == ERROR_SUCCESS)
     {

Modified: trunk/reactos/subsys/system/regedit/main.h
--- trunk/reactos/subsys/system/regedit/main.h	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/main.h	2005-11-27 23:23:38 UTC (rev 19712)
@@ -79,12 +79,18 @@
 extern TCHAR szFrameClass[];
 extern TCHAR szChildClass[];
 
+extern const TCHAR g_szGeneralRegKey[];
+
 /* about.c */
 extern void ShowAboutBox(HWND hWnd);
 
 /* childwnd.c */
 extern LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM);
 
+/* find.c */
+extern void FindDialog(HWND hWnd);
+extern BOOL FindNext(HWND hWnd);
+
 /* framewnd.c */
 extern LRESULT CALLBACK FrameWndProc(HWND, UINT, WPARAM, LPARAM);
 extern void SetupStatusBar(HWND hWnd, BOOL bResize);

Modified: trunk/reactos/subsys/system/regedit/regedit.xml
--- trunk/reactos/subsys/system/regedit/regedit.xml	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/regedit.xml	2005-11-27 23:23:38 UTC (rev 19712)
@@ -19,6 +19,7 @@
 	<file>about.c</file>
 	<file>childwnd.c</file>
 	<file>edit.c</file>
+	<file>find.c</file>
 	<file>framewnd.c</file>
 	<file>hexedit.c</file>
 	<file>listview.c</file>

Modified: trunk/reactos/subsys/system/regedit/regproc.c
--- trunk/reactos/subsys/system/regedit/regproc.c	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/regproc.c	2005-11-27 23:23:38 UTC (rev 19712)
@@ -1594,7 +1594,7 @@
 {
     LPCTSTR s;
     LPTSTR lpNewSubKey = NULL;
-	LONG Ret = 0;
+    LONG Ret = 0;
 
     s = _tcsrchr(lpSubKey, _T('\\'));
     if (s)
@@ -1687,6 +1687,145 @@
 }
 
 /******************************************************************************
+ * Searching
+ */
+
+static LONG RegNextKey(HKEY hKey, LPTSTR lpSubKey, size_t iSubKeyLength)
+{
+    LONG lResult;
+    LPTSTR s;
+    LPCTSTR pszOriginalKey;
+    TCHAR szKeyName[256];
+    HKEY hSubKey, hBaseKey;
+    DWORD dwIndex = 0;
+    DWORD cbName;
+    FILETIME ft;
+    BOOL bFoundKey = FALSE;
+
+    /* Try accessing a subkey */
+    if (RegOpenKeyEx(hKey, lpSubKey, 0, KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS)
+    {
+        cbName = iSubKeyLength - _tcslen(lpSubKey) - 1;
+        lResult = RegEnumKeyEx(hSubKey, 0, lpSubKey + _tcslen(lpSubKey) + 1,
+            &cbName, NULL, NULL, NULL, &ft);
+        RegCloseKey(hSubKey);
+        
+        if (lResult == ERROR_SUCCESS)
+        {
+            lpSubKey[_tcslen(lpSubKey)] = '\\';
+            bFoundKey = TRUE;
+        }
+    }
+
+    if (!bFoundKey)
+    {
+        /* Go up and find the next sibling key */
+        do
+        {
+            s = _tcsrchr(lpSubKey, '\\');
+            if (s)
+            {
+                *s = '\0';
+                pszOriginalKey = s + 1;
+
+                hBaseKey = NULL;
+                RegOpenKeyEx(hKey, lpSubKey, 0, KEY_ALL_ACCESS, &hBaseKey);
+            }
+            else
+            {
+                pszOriginalKey = lpSubKey;
+                hBaseKey = hKey;
+            }
+
+            if (hBaseKey)
+            {
+                dwIndex = 0;
+                do
+                {
+                    lResult = RegEnumKey(hBaseKey, dwIndex++, szKeyName, sizeof(szKeyName) / sizeof(szKeyName[0]));
+                }
+                while((lResult == ERROR_SUCCESS) && _tcscmp(szKeyName, pszOriginalKey));
+
+                if (lResult == ERROR_SUCCESS)
+                {
+                    lResult = RegEnumKey(hBaseKey, dwIndex++, szKeyName, sizeof(szKeyName) / sizeof(szKeyName[0]));
+                    if (lResult == ERROR_SUCCESS)
+                    {
+                        bFoundKey = TRUE;
+                        _sntprintf(lpSubKey + _tcslen(lpSubKey), iSubKeyLength - _tcslen(lpSubKey), _T("\\%s"), szKeyName);
+                    }
+                }
+                RegCloseKey(hBaseKey);
+            }
+        }
+        while(!bFoundKey);
+    }
+    return bFoundKey ? ERROR_SUCCESS : ERROR_NO_MORE_ITEMS;
+}
+
+static BOOL RegSearchCompare(LPCTSTR s1, LPCTSTR s2, DWORD dwSearchFlags)
+{
+    BOOL bResult;
+    if (dwSearchFlags & RSF_WHOLESTRING)
+    {
+        if (dwSearchFlags & RSF_MATCHCASE)
+            bResult = !_tcscmp(s1, s2);
+        else
+            bResult = !_tcsicmp(s1, s2);
+    }
+    else
+    {
+        if (dwSearchFlags & RSF_MATCHCASE)
+            bResult = (_tcsstr(s1, s2) != NULL);
+        else
+        {
+            /* My kingdom for _tcsistr() */
+            bResult = FALSE;
+            while(*s1)
+            {
+                if (!_tcsnicmp(s1, s2, _tcslen(s2)))
+                {
+                    bResult = TRUE;
+                    break;
+                }
+                s1++;
+            }
+        }
+    }
+    return bResult;
+}
+
+LONG RegSearch(HKEY hKey, LPTSTR lpSubKey, size_t iSubKeyLength,
+    LPCTSTR pszSearchString, DWORD dwValueIndex,    
+    DWORD dwSearchFlags, BOOL (*pfnCallback)(LPVOID), LPVOID lpParam)
+{
+    LONG lResult;
+    LPCTSTR s;
+
+    if (dwSearchFlags & (RSF_LOOKATVALUES | RSF_LOOKATDATA))
+        return ERROR_CALL_NOT_IMPLEMENTED;    /* NYI */
+
+    do
+    {
+        if (pfnCallback)
+        {
+            if (pfnCallback(lpParam))
+                return ERROR_OPERATION_ABORTED;
+        }
+
+        lResult = RegNextKey(hKey, lpSubKey, iSubKeyLength);
+        if (lResult != ERROR_SUCCESS)
+            return lResult;
+
+        s = _tcsrchr(lpSubKey, '\\');
+        s = s ? s + 1 : lpSubKey;
+    }
+    while(!(dwSearchFlags & RSF_LOOKATKEYS) || !RegSearchCompare(s, pszSearchString, dwSearchFlags));
+
+    return ERROR_SUCCESS;
+}
+
+/******************************************************************************
  * Key naming and parsing
  */
 

Modified: trunk/reactos/subsys/system/regedit/regproc.h
--- trunk/reactos/subsys/system/regedit/regproc.h	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/regproc.h	2005-11-27 23:23:38 UTC (rev 19712)
@@ -85,7 +85,6 @@
 /*
  * Processing
  */
-LONG RegDeleteKeyRecursive(HKEY hKey, LPCTSTR lpSubKey);
 LONG RegCopyKey(HKEY hDestKey, LPCTSTR lpDestSubKey, HKEY hSrcKey, LPCTSTR lpSrcSubKey);
 LONG RegMoveKey(HKEY hDestKey, LPCTSTR lpDestSubKey, HKEY hSrcKey, LPCTSTR lpSrcSubKey);
 LONG RegRenameKey(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpNewName);
@@ -95,6 +94,16 @@
 /*
  * Miscellaneous
  */
+#define RSF_WHOLESTRING    0x00000001
+#define RSF_LOOKATKEYS	   0x00000002
+#define RSF_LOOKATVALUES   0x00000004
+#define RSF_LOOKATDATA     0x00000008
+#define RSF_MATCHCASE      0x00010000
+
+LONG RegSearch(HKEY hKey, LPTSTR lpSubKey, size_t iSubKeyLength,
+    LPCTSTR pszSearchString, DWORD dwValueIndex,	
+    DWORD dwSearchFlags, BOOL (*pfnCallback)(LPVOID), LPVOID lpParam);
+
 BOOL RegKeyGetName(LPTSTR pszDest, size_t iDestLength, HKEY hRootKey, LPCTSTR lpSubKey);
 
 /* EOF */

Modified: trunk/reactos/subsys/system/regedit/resource.h
--- trunk/reactos/subsys/system/regedit/resource.h	2005-11-27 23:23:13 UTC (rev 19711)
+++ trunk/reactos/subsys/system/regedit/resource.h	2005-11-27 23:23:38 UTC (rev 19712)
@@ -45,6 +45,7 @@
 #define IDD_ADDFAVORITES                138
 #define IDD_REMOVEFAVORITES             139
 #define IDD_FIND                        140
+#define IDD_FINDING                     141
 #define IDC_LICENSE_EDIT                1029
 #define ID_REGISTRY_EXIT                32770
 #define ID_FAVOURITES_ADDTOFAVOURITES   32772
@@ -194,12 +195,13 @@
 
 #define IDC_FAVORITENAME                2011  
 #define IDC_FAVORITESLIST               2012
-#define IDD_FINDWHAT                    2013
+#define IDC_FINDWHAT                    2013
 #define IDC_LOOKAT_KEYS                 2014
 #define IDC_LOOKAT_VALUES               2015
 #define IDC_LOOKAT_DATA                 2016
 #define IDC_MATCHSTRING                 2017
 #define IDC_MATCHCASE                   2018
+#define IDS_FINISHEDFIND                2019
 
 #define ID_FAVORITES_MIN                2100
 #define ID_FAVORITES_MAX                2999