Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

921 lines
28 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1994
  4. *
  5. * TITLE: REGFIND.C
  6. *
  7. * VERSION: 4.0
  8. *
  9. * AUTHOR: Tracy Sharpe
  10. *
  11. * DATE: 14 Jul 1994
  12. *
  13. * Find routines for the Registry Editor.
  14. *
  15. *******************************************************************************/
  16. #include "pch.h"
  17. #include "regedit.h"
  18. #include "regkey.h"
  19. #include "regresid.h"
  20. #include "reghelp.h"
  21. #include "regvalue.h"
  22. #define SIZE_FINDSPEC (max(MAXKEYNAME, MAXVALUENAME_LENGTH))
  23. TCHAR s_FindSpecification[SIZE_FINDSPEC] = { 0 };
  24. #define FIND_EXACT 0x00000001
  25. #define FIND_KEYS 0x00000002
  26. #define FIND_VALUES 0x00000004
  27. #define FIND_DATA 0x00000008
  28. // Initialized value is the default if we don't find last known state in the
  29. // registry.
  30. DWORD g_FindFlags = FIND_KEYS | FIND_VALUES | FIND_DATA;
  31. // Global needed to monitor the find abort dialog status.
  32. BOOL s_fContinueFind;
  33. //
  34. // Reference data for the RegFind dialog.
  35. //
  36. typedef struct _REGFINDDATA {
  37. UINT LookForCount;
  38. } REGFINDDATA;
  39. REGFINDDATA s_RegFindData;
  40. //
  41. // Association between the items of the RegFind dialog and the find flags.
  42. //
  43. typedef struct _DLGITEMFINDFLAGASSOC {
  44. int DlgItem;
  45. DWORD Flag;
  46. } DLGITEMFINDFLAGASSOC;
  47. const DLGITEMFINDFLAGASSOC s_DlgItemFindFlagAssoc[] = {
  48. IDC_WHOLEWORDONLY, FIND_EXACT,
  49. IDC_FORKEYS, FIND_KEYS,
  50. IDC_FORVALUES, FIND_VALUES,
  51. IDC_FORDATA, FIND_DATA
  52. };
  53. const DWORD s_RegFindHelpIDs[] = {
  54. IDC_FINDWHAT, IDH_FIND_SEARCHTEXT,
  55. IDC_GROUPBOX, IDH_REGEDIT_LOOK,
  56. IDC_FORKEYS, IDH_REGEDIT_LOOK,
  57. IDC_FORVALUES, IDH_REGEDIT_LOOK,
  58. IDC_FORDATA, IDH_REGEDIT_LOOK,
  59. IDC_WHOLEWORDONLY, IDH_FIND_WHOLE,
  60. IDOK, IDH_FIND_NEXT_BUTTON,
  61. 0, 0
  62. };
  63. BOOL
  64. PASCAL
  65. FindCompare(
  66. LPTSTR lpString
  67. );
  68. INT_PTR
  69. PASCAL
  70. RegFindDlgProc(
  71. HWND hWnd,
  72. UINT Message,
  73. WPARAM wParam,
  74. LPARAM lParam
  75. );
  76. BOOL
  77. PASCAL
  78. RegFind_OnInitDialog(
  79. HWND hWnd,
  80. HWND hFocusWnd,
  81. LPARAM lParam
  82. );
  83. VOID
  84. PASCAL
  85. RegFind_OnCommand(
  86. HWND hWnd,
  87. int DlgItem,
  88. HWND hControlWnd,
  89. UINT NotificationCode
  90. );
  91. BOOL
  92. PASCAL
  93. RegFindAbortProc(
  94. HWND hRegFindAbortWnd
  95. );
  96. INT_PTR
  97. CALLBACK
  98. RegFindAbortDlgProc(
  99. HWND hWnd,
  100. UINT Message,
  101. WPARAM wParam,
  102. LPARAM lParam
  103. );
  104. /*******************************************************************************
  105. *
  106. * RegEdit_OnCommandFindNext
  107. *
  108. * DESCRIPTION:
  109. *
  110. * PARAMETERS:
  111. *
  112. *******************************************************************************/
  113. VOID
  114. PASCAL
  115. RegEdit_OnCommandFindNext(
  116. HWND hWnd,
  117. BOOL fForceDialog
  118. )
  119. {
  120. UINT uErrorStringID;
  121. BOOL fError = FALSE;
  122. BOOL fSearchedToEnd;
  123. HWND hFocusWnd;
  124. LV_ITEM LVItem;
  125. TCHAR ValueName[MAXVALUENAME_LENGTH];
  126. DWORD Type;
  127. DWORD cbValueData;
  128. TV_ITEM TVItem;
  129. TCHAR KeyName[MAXKEYNAME];
  130. HWND hRegFindAbortWnd;
  131. HTREEITEM hTempTreeItem;
  132. UINT ExpandCounter;
  133. HKEY hRootKey;
  134. HKEY hKey;
  135. DWORD EnumIndex;
  136. DWORD cbValueName;
  137. BOOL fFoundMatch;
  138. TCHAR BestValueName[MAXVALUENAME_LENGTH];
  139. LV_FINDINFO LVFindInfo;
  140. fSearchedToEnd = FALSE;
  141. hFocusWnd = NULL;
  142. hRegFindAbortWnd = NULL;
  143. //
  144. // Check if we're to show the find dialog. This is either due to the user
  145. // explicitly choosing the "Find" menu item or causing a "Find Next" with
  146. // the search specification being uninitialized.
  147. //
  148. if (fForceDialog || s_FindSpecification[0] == 0) {
  149. if (DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_REGFIND), hWnd,
  150. RegFindDlgProc) != IDOK)
  151. return;
  152. }
  153. RegEdit_SetWaitCursor(TRUE);
  154. //
  155. // Check if we're trying to finding either value names or data. If so,
  156. // then the next match might be part of the current ValueList.
  157. //
  158. if (g_FindFlags & (FIND_VALUES | FIND_DATA))
  159. {
  160. LVItem.iItem = ListView_GetNextItem(g_RegEditData.hValueListWnd, -1, LVNI_FOCUSED);
  161. LVItem.iSubItem = 0;
  162. LVItem.mask = LVIF_TEXT;
  163. LVItem.pszText = ValueName;
  164. LVItem.cchTextMax = ARRAYSIZE(ValueName);
  165. //
  166. // Walk over all of the rest of the value names attempting to find a
  167. // match.
  168. //
  169. while ((LVItem.iItem = ListView_GetNextItem(g_RegEditData.hValueListWnd,
  170. LVItem.iItem, LVNI_ALL)) != -1) {
  171. ListView_GetItem(g_RegEditData.hValueListWnd, &LVItem);
  172. //
  173. // Check if this value name meets our search specification. We'll
  174. // assume that this value name still exists.
  175. //
  176. if ((g_FindFlags & FIND_VALUES) && FindCompare(ValueName))
  177. goto SelectListItem;
  178. //
  179. // Check if this value data meets our search specification. We'll
  180. // have to go back to the registry to determine this.
  181. //
  182. if (g_FindFlags & FIND_DATA)
  183. {
  184. if ((RegEdit_QueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
  185. NULL, &Type, NULL, &cbValueData) == ERROR_SUCCESS) &&
  186. IsRegStringType(Type))
  187. {
  188. // Allocate storage space
  189. PBYTE pbDataValue = (PBYTE)LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type));
  190. if (pbDataValue)
  191. {
  192. BOOL fSuccess = FALSE;
  193. if (RegEdit_QueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
  194. NULL, &Type, pbDataValue, &cbValueData) == ERROR_SUCCESS)
  195. {
  196. if (Type == REG_MULTI_SZ)
  197. {
  198. EDITVALUEPARAM evp;
  199. evp.pValueData = pbDataValue;
  200. evp.cbValueData = cbValueData;
  201. if (ValueList_MultiStringToString(&evp))
  202. {
  203. pbDataValue = evp.pValueData;
  204. }
  205. }
  206. fSuccess = FindCompare((PTSTR)pbDataValue);
  207. }
  208. LocalFree(pbDataValue);
  209. if (fSuccess)
  210. {
  211. goto SelectListItem;
  212. }
  213. }
  214. else
  215. {
  216. fError = TRUE;
  217. uErrorStringID = IDS_NOMEMORY;
  218. goto DismissRegFindAbortWnd;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. //
  225. // Searching the registry (especially with this code!) is a lengthy
  226. // operation, so we must provide a way for the user to cancel the
  227. // operation.
  228. //
  229. s_fContinueFind = TRUE;
  230. if ((hRegFindAbortWnd = CreateDialog(g_hInstance,
  231. MAKEINTRESOURCE(IDD_REGFINDABORT), hWnd, RegFindAbortDlgProc)) !=
  232. NULL) {
  233. EnableWindow(hWnd, FALSE);
  234. //
  235. // Major hack: The following code sequence relies heavily on the
  236. // TreeView to maintain the state of the find process. Even though I'm
  237. // inserting and deleting non-visible tree items, the TreeView
  238. // currently flickers despite this.
  239. //
  240. // So, we set this internal flag and turn off the TreeView's redraw
  241. // flag. Whenever we get a WM_PAINT message for our main window, we
  242. // temporarily "let" it redraw itself then and only then. That way,
  243. // the user can move the modeless abort dialog or switch away and back
  244. // and still have the TreeView look normal.
  245. //
  246. // Yes, it's difficult at this time to fix the TreeView's paint logic.
  247. //
  248. g_RegEditData.fProcessingFind = TRUE;
  249. SetWindowRedraw(g_RegEditData.hKeyTreeWnd, FALSE);
  250. }
  251. //
  252. // Either the user wasn't trying to find value names or data or else no
  253. // matches were found. This means that we must move on to the next branch
  254. // of the registry.
  255. //
  256. // We first walk into the children of the current branch, then the
  257. // siblings, and finally pop back through the parent.
  258. //
  259. // We use the information already in the KeyTree pane as much as possible.
  260. //
  261. ExpandCounter = 0;
  262. fFoundMatch = FALSE;
  263. BestValueName[0] = '\0';
  264. TVItem.mask = TVIF_TEXT | TVIF_STATE | TVIF_CHILDREN;
  265. TVItem.pszText = KeyName;
  266. TVItem.cchTextMax = ARRAYSIZE(KeyName);
  267. TVItem.hItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
  268. TreeView_GetItem(g_RegEditData.hKeyTreeWnd, &TVItem);
  269. while (TRUE) {
  270. //
  271. // Check if we should cancel the find operation. If so, restore our
  272. // initial state and exit.
  273. //
  274. if (!RegFindAbortProc(hRegFindAbortWnd)) {
  275. if (ExpandCounter) {
  276. hTempTreeItem = TVItem.hItem;
  277. do {
  278. hTempTreeItem =
  279. TreeView_GetParent(g_RegEditData.hKeyTreeWnd,
  280. hTempTreeItem);
  281. } while (--ExpandCounter);
  282. TreeView_Expand(g_RegEditData.hKeyTreeWnd, hTempTreeItem,
  283. TVE_COLLAPSE | TVE_COLLAPSERESET);
  284. }
  285. goto DismissRegFindAbortWnd;
  286. }
  287. //
  288. // Does this branch have any children? This would have been determined
  289. // when the tree item was built by the routine KeyTree_ExpandBranch.
  290. //
  291. if (TVItem.cChildren) {
  292. //
  293. // The branch may have children, but it may not have been expanded
  294. // yet.
  295. //
  296. if ((hTempTreeItem = TreeView_GetChild(g_RegEditData.hKeyTreeWnd,
  297. TVItem.hItem)) == NULL) {
  298. if (!KeyTree_ExpandBranch(g_RegEditData.hKeyTreeWnd,
  299. TVItem.hItem))
  300. goto SkipToSibling;
  301. if ((hTempTreeItem = TreeView_GetChild(g_RegEditData.hKeyTreeWnd,
  302. TVItem.hItem)) == NULL)
  303. goto SkipToSibling;
  304. ExpandCounter++;
  305. }
  306. TVItem.hItem = hTempTreeItem;
  307. }
  308. //
  309. // The branch doesn't have any children, so we'll move on to the next
  310. // sibling of the current branch. If none exists, then try finding
  311. // the next sibling of the parent branch, and so on.
  312. //
  313. else {
  314. SkipToSibling:
  315. while (TRUE) {
  316. if ((hTempTreeItem =
  317. TreeView_GetNextSibling(g_RegEditData.hKeyTreeWnd,
  318. TVItem.hItem)) != NULL) {
  319. TVItem.hItem = hTempTreeItem;
  320. break;
  321. }
  322. //
  323. // If no more parents exist, then we've finished searching the
  324. // tree. We're outta here!
  325. //
  326. if ((TVItem.hItem =
  327. TreeView_GetParent(g_RegEditData.hKeyTreeWnd,
  328. TVItem.hItem)) == NULL) {
  329. fSearchedToEnd = TRUE;
  330. goto DismissRegFindAbortWnd;
  331. }
  332. if (ExpandCounter) {
  333. ExpandCounter--;
  334. TreeView_Expand(g_RegEditData.hKeyTreeWnd, TVItem.hItem,
  335. TVE_COLLAPSE | TVE_COLLAPSERESET);
  336. }
  337. }
  338. }
  339. //
  340. // If we made it this far, then we're at the next branch of the
  341. // registry to evaluate.
  342. //
  343. TreeView_GetItem(g_RegEditData.hKeyTreeWnd, &TVItem);
  344. //
  345. // Check if we're trying to find keys.
  346. //
  347. if (g_FindFlags & FIND_KEYS) {
  348. if (FindCompare(KeyName))
  349. goto SelectTreeItem;
  350. }
  351. //
  352. // Check if we're trying to find value names or data.
  353. //
  354. if (g_FindFlags & (FIND_VALUES | FIND_DATA)) {
  355. //
  356. // Try to open the registry at the new current branch.
  357. //
  358. hRootKey = KeyTree_BuildKeyPath( g_RegEditData.hKeyTreeWnd,
  359. TVItem.hItem,
  360. KeyName,
  361. ARRAYSIZE(KeyName),
  362. BKP_TOSUBKEY);
  363. if(hRootKey && RegOpenKeyEx(hRootKey, KeyName, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
  364. {
  365. //
  366. // Here's the simple case-- we're trying to find an exact match
  367. // for a value name. We can just use the registry API to do
  368. // this for us!
  369. //
  370. if ((g_FindFlags & (FIND_VALUES | FIND_DATA | FIND_EXACT)) ==
  371. (FIND_VALUES | FIND_EXACT)) {
  372. if (RegEdit_QueryValueEx(hKey, s_FindSpecification, NULL, NULL,
  373. NULL, NULL) == ERROR_SUCCESS) {
  374. StringCchCopy(BestValueName, ARRAYSIZE(BestValueName), s_FindSpecification);
  375. fFoundMatch = TRUE;
  376. }
  377. }
  378. //
  379. // Bummer... we need to walk through all of the registry
  380. // value/data pairs for this key to try to find a match. Even
  381. // worse, we have to look at _all_ of the entries, not just the
  382. // first hit... we must display the first alphabetically
  383. // matching entry!
  384. //
  385. else {
  386. EnumIndex = 0;
  387. while (TRUE)
  388. {
  389. cbValueName = ARRAYSIZE(ValueName);
  390. if (RegEnumValue(hKey, EnumIndex++, ValueName,
  391. &cbValueName, NULL, &Type, NULL,
  392. &cbValueData) == ERROR_SUCCESS)
  393. {
  394. PBYTE pbValueData = (g_FindFlags & FIND_DATA) ?
  395. (PBYTE)LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type)) : NULL;
  396. if (pbValueData || !(g_FindFlags & FIND_DATA))
  397. {
  398. if (RegEdit_QueryValueEx(hKey, ValueName, NULL, &Type,
  399. pbValueData, &cbValueData) == ERROR_SUCCESS)
  400. {
  401. if (pbValueData && (Type == REG_MULTI_SZ))
  402. {
  403. EDITVALUEPARAM evp;
  404. evp.pValueData = pbValueData;
  405. evp.cbValueData = cbValueData;
  406. if (ValueList_MultiStringToString(&evp))
  407. {
  408. pbValueData = evp.pValueData;
  409. }
  410. }
  411. if (((g_FindFlags & FIND_VALUES) &&
  412. FindCompare(ValueName)) ||
  413. ((g_FindFlags & FIND_DATA) && IsRegStringType(Type) &&
  414. FindCompare((PTSTR)pbValueData)))
  415. {
  416. //
  417. // We've got to check if we've found a "better"
  418. // value name to display-- one that's at the top of
  419. // the sorted list.
  420. //
  421. if (fFoundMatch)
  422. {
  423. if (lstrcmpi(BestValueName, ValueName) > 0)
  424. {
  425. StringCchCopy(BestValueName, ARRAYSIZE(BestValueName), ValueName);
  426. }
  427. }
  428. else
  429. {
  430. StringCchCopy(BestValueName, ARRAYSIZE(BestValueName), ValueName);
  431. fFoundMatch = TRUE;
  432. }
  433. }
  434. }
  435. if (pbValueData)
  436. {
  437. LocalFree(pbValueData);
  438. }
  439. }
  440. else
  441. {
  442. fError = TRUE;
  443. uErrorStringID = IDS_NOMEMORY;
  444. goto DismissRegFindAbortWnd;
  445. }
  446. }
  447. else
  448. {
  449. break;
  450. }
  451. }
  452. }
  453. RegCloseKey(hKey);
  454. if (fFoundMatch)
  455. goto SelectTreeItem;
  456. }
  457. }
  458. }
  459. SelectTreeItem:
  460. TreeView_EnsureVisible(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
  461. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
  462. if (!fFoundMatch)
  463. hFocusWnd = g_RegEditData.hKeyTreeWnd;
  464. else {
  465. //
  466. // Right now, the TreeView_SelectItem above will cause the ValueListWnd
  467. // to update, but only after a short time delay. We want the list
  468. // immediately updated, so force the timer to go off now.
  469. //
  470. RegEdit_OnSelChangedTimer(hWnd);
  471. if (BestValueName[0] == 0)
  472. LVItem.iItem = 0;
  473. else {
  474. LVFindInfo.flags = LVFI_STRING;
  475. LVFindInfo.psz = BestValueName;
  476. LVItem.iItem = ListView_FindItem(g_RegEditData.hValueListWnd,
  477. -1, &LVFindInfo);
  478. }
  479. SelectListItem:
  480. ListView_SetItemState(g_RegEditData.hValueListWnd, -1, 0,
  481. LVIS_SELECTED | LVIS_FOCUSED);
  482. ListView_SetItemState(g_RegEditData.hValueListWnd, LVItem.iItem,
  483. LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  484. ListView_EnsureVisible(g_RegEditData.hValueListWnd, LVItem.iItem,
  485. FALSE);
  486. hFocusWnd = g_RegEditData.hValueListWnd;
  487. }
  488. DismissRegFindAbortWnd:
  489. RegEdit_SetWaitCursor(FALSE);
  490. if (hRegFindAbortWnd != NULL) {
  491. g_RegEditData.fProcessingFind = FALSE;
  492. SetWindowRedraw(g_RegEditData.hKeyTreeWnd, TRUE);
  493. EnableWindow(hWnd, TRUE);
  494. DestroyWindow(hRegFindAbortWnd);
  495. }
  496. if (hFocusWnd != NULL)
  497. SetFocus(hFocusWnd);
  498. if (fError)
  499. {
  500. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(uErrorStringID),
  501. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
  502. }
  503. if (fSearchedToEnd)
  504. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(IDS_SEARCHEDTOEND),
  505. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONINFORMATION | MB_OK);
  506. }
  507. /*******************************************************************************
  508. *
  509. * FindCompare
  510. *
  511. * DESCRIPTION:
  512. *
  513. * PARAMETERS:
  514. *
  515. *******************************************************************************/
  516. BOOL
  517. PASCAL
  518. FindCompare(
  519. LPTSTR lpString
  520. )
  521. {
  522. if (g_FindFlags & FIND_EXACT)
  523. return lstrcmpi(lpString, s_FindSpecification) == 0;
  524. else
  525. return StrStrI(lpString, s_FindSpecification) != NULL;
  526. }
  527. /*******************************************************************************
  528. *
  529. * RegFindDlgProc
  530. *
  531. * DESCRIPTION:
  532. *
  533. * PARAMETERS:
  534. *
  535. *******************************************************************************/
  536. INT_PTR
  537. PASCAL
  538. RegFindDlgProc(
  539. HWND hWnd,
  540. UINT Message,
  541. WPARAM wParam,
  542. LPARAM lParam
  543. )
  544. {
  545. switch (Message) {
  546. HANDLE_MSG(hWnd, WM_INITDIALOG, RegFind_OnInitDialog);
  547. HANDLE_MSG(hWnd, WM_COMMAND, RegFind_OnCommand);
  548. case WM_HELP:
  549. WinHelp(((LPHELPINFO) lParam)-> hItemHandle, g_pHelpFileName,
  550. HELP_WM_HELP, (ULONG_PTR) s_RegFindHelpIDs);
  551. break;
  552. case WM_CONTEXTMENU:
  553. WinHelp((HWND) wParam, g_pHelpFileName, HELP_CONTEXTMENU,
  554. (ULONG_PTR) s_RegFindHelpIDs);
  555. break;
  556. default:
  557. return FALSE;
  558. }
  559. return TRUE;
  560. }
  561. /*******************************************************************************
  562. *
  563. * RegFind_OnInitDialog
  564. *
  565. * DESCRIPTION:
  566. *
  567. * PARAMETERS:
  568. *
  569. *******************************************************************************/
  570. BOOL
  571. PASCAL
  572. RegFind_OnInitDialog(
  573. HWND hWnd,
  574. HWND hFocusWnd,
  575. LPARAM lParam
  576. )
  577. {
  578. UINT Counter;
  579. int DlgItem;
  580. //
  581. // Initialize the "Find What" edit control.
  582. //
  583. SendDlgItemMessage(hWnd, IDC_FINDWHAT, EM_SETLIMITTEXT,
  584. SIZE_FINDSPEC, 0);
  585. SetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification);
  586. //
  587. // Initialize the checkboxes based on the state of the global find flags.
  588. //
  589. s_RegFindData.LookForCount = 0;
  590. for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) / sizeof(DLGITEMFINDFLAGASSOC); Counter++)
  591. {
  592. if (g_FindFlags & s_DlgItemFindFlagAssoc[Counter].Flag) {
  593. DlgItem = s_DlgItemFindFlagAssoc[Counter].DlgItem;
  594. CheckDlgButton(hWnd, DlgItem, TRUE);
  595. if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA)
  596. s_RegFindData.LookForCount++;
  597. }
  598. }
  599. return TRUE;
  600. UNREFERENCED_PARAMETER(hFocusWnd);
  601. UNREFERENCED_PARAMETER(lParam);
  602. }
  603. /*******************************************************************************
  604. *
  605. * RegFind_OnCommand
  606. *
  607. * DESCRIPTION:
  608. *
  609. * PARAMETERS:
  610. *
  611. *******************************************************************************/
  612. VOID
  613. PASCAL
  614. RegFind_OnCommand(
  615. HWND hWnd,
  616. int DlgItem,
  617. HWND hControlWnd,
  618. UINT NotificationCode
  619. )
  620. {
  621. UINT Counter;
  622. if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA) {
  623. if (NotificationCode == BN_CLICKED) {
  624. IsDlgButtonChecked(hWnd, DlgItem) ? s_RegFindData.LookForCount++ :
  625. s_RegFindData.LookForCount--;
  626. goto EnableFindNextButton;
  627. }
  628. }
  629. else {
  630. switch (DlgItem) {
  631. case IDC_FINDWHAT:
  632. if (NotificationCode == EN_CHANGE) {
  633. EnableFindNextButton:
  634. EnableWindow(GetDlgItem(hWnd, IDOK),
  635. s_RegFindData.LookForCount > 0 &&
  636. SendDlgItemMessage(hWnd, IDC_FINDWHAT,
  637. WM_GETTEXTLENGTH, 0, 0) != 0);
  638. }
  639. break;
  640. case IDOK:
  641. GetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification, ARRAYSIZE(s_FindSpecification));
  642. for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) / sizeof(DLGITEMFINDFLAGASSOC); Counter++)
  643. {
  644. if (IsDlgButtonChecked(hWnd,
  645. s_DlgItemFindFlagAssoc[Counter].DlgItem))
  646. g_FindFlags |= s_DlgItemFindFlagAssoc[Counter].Flag;
  647. else
  648. g_FindFlags &= ~s_DlgItemFindFlagAssoc[Counter].Flag;
  649. }
  650. // FALL THROUGH
  651. case IDCANCEL:
  652. EndDialog(hWnd, DlgItem);
  653. break;
  654. }
  655. }
  656. }
  657. /*******************************************************************************
  658. *
  659. * RegFindAbortProc
  660. *
  661. * DESCRIPTION:
  662. *
  663. * PARAMETERS:
  664. * (returns), TRUE to continue the find, else FALSE to cancel.
  665. *
  666. *******************************************************************************/
  667. BOOL
  668. PASCAL
  669. RegFindAbortProc(
  670. HWND hRegFindAbortWnd
  671. )
  672. {
  673. while (s_fContinueFind && MessagePump(hRegFindAbortWnd))
  674. ;
  675. return s_fContinueFind;
  676. }
  677. /*******************************************************************************
  678. *
  679. * RegAbortDlgProc
  680. *
  681. * DESCRIPTION:
  682. * Callback procedure for the RegAbort dialog box.
  683. *
  684. * PARAMETERS:
  685. * hWnd, handle of RegAbort window.
  686. * Message,
  687. * wParam,
  688. * lParam,
  689. * (returns),
  690. *
  691. *******************************************************************************/
  692. INT_PTR
  693. CALLBACK
  694. RegFindAbortDlgProc(
  695. HWND hWnd,
  696. UINT Message,
  697. WPARAM wParam,
  698. LPARAM lParam
  699. )
  700. {
  701. switch (Message) {
  702. case WM_INITDIALOG:
  703. break;
  704. case WM_CLOSE:
  705. case WM_COMMAND:
  706. s_fContinueFind = FALSE;
  707. break;
  708. default:
  709. return FALSE;
  710. }
  711. return TRUE;
  712. }