Source code of Windows XP (NT5)
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.

928 lines
27 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. LVItem.iItem = ListView_GetNextItem(g_RegEditData.hValueListWnd, -1,
  160. LVNI_FOCUSED);
  161. LVItem.iSubItem = 0;
  162. LVItem.mask = LVIF_TEXT;
  163. LVItem.pszText = ValueName;
  164. LVItem.cchTextMax = sizeof(ValueName)/sizeof(TCHAR);
  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 = sizeof(KeyName)/sizeof(TCHAR);
  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, KeyName, BKP_TOSUBKEY);
  360. if(hRootKey && RegOpenKeyEx(hRootKey,KeyName,0,KEY_QUERY_VALUE,&hKey) ==
  361. ERROR_SUCCESS) {
  362. //
  363. // Here's the simple case-- we're trying to find an exact match
  364. // for a value name. We can just use the registry API to do
  365. // this for us!
  366. //
  367. if ((g_FindFlags & (FIND_VALUES | FIND_DATA | FIND_EXACT)) ==
  368. (FIND_VALUES | FIND_EXACT)) {
  369. if (RegEdit_QueryValueEx(hKey, s_FindSpecification, NULL, NULL,
  370. NULL, NULL) == ERROR_SUCCESS) {
  371. lstrcpy(BestValueName, s_FindSpecification);
  372. fFoundMatch = TRUE;
  373. }
  374. }
  375. //
  376. // Bummer... we need to walk through all of the registry
  377. // value/data pairs for this key to try to find a match. Even
  378. // worse, we have to look at _all_ of the entries, not just the
  379. // first hit... we must display the first alphabetically
  380. // matching entry!
  381. //
  382. else {
  383. EnumIndex = 0;
  384. while (TRUE)
  385. {
  386. cbValueName = sizeof(ValueName)/sizeof(TCHAR);
  387. if (RegEnumValue(hKey, EnumIndex++, ValueName,
  388. &cbValueName, NULL, &Type, NULL,
  389. &cbValueData) == ERROR_SUCCESS)
  390. {
  391. PBYTE pbValueData = (g_FindFlags & FIND_DATA) ?
  392. (PBYTE)LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type)) : NULL;
  393. if (pbValueData || !(g_FindFlags & FIND_DATA))
  394. {
  395. if (RegEdit_QueryValueEx(hKey, ValueName, NULL, &Type,
  396. pbValueData, &cbValueData) == ERROR_SUCCESS)
  397. {
  398. if (pbValueData && (Type == REG_MULTI_SZ))
  399. {
  400. EDITVALUEPARAM evp;
  401. evp.pValueData = pbValueData;
  402. evp.cbValueData = cbValueData;
  403. if (ValueList_MultiStringToString(&evp))
  404. {
  405. pbValueData = evp.pValueData;
  406. }
  407. }
  408. if (((g_FindFlags & FIND_VALUES) &&
  409. FindCompare(ValueName)) ||
  410. ((g_FindFlags & FIND_DATA) && IsRegStringType(Type) &&
  411. FindCompare((PTSTR)pbValueData)))
  412. {
  413. //
  414. // We've got to check if we've found a "better"
  415. // value name to display-- one that's at the top of
  416. // the sorted list.
  417. //
  418. if (fFoundMatch) {
  419. if (lstrcmpi(BestValueName, ValueName) > 0)
  420. lstrcpy(BestValueName, ValueName);
  421. }
  422. else {
  423. lstrcpy(BestValueName, ValueName);
  424. fFoundMatch = TRUE;
  425. }
  426. }
  427. }
  428. if (pbValueData)
  429. {
  430. LocalFree(pbValueData);
  431. }
  432. }
  433. else
  434. {
  435. fError = TRUE;
  436. uErrorStringID = IDS_NOMEMORY;
  437. goto DismissRegFindAbortWnd;
  438. }
  439. }
  440. else
  441. {
  442. break;
  443. }
  444. }
  445. }
  446. RegCloseKey(hKey);
  447. if (fFoundMatch)
  448. goto SelectTreeItem;
  449. }
  450. }
  451. }
  452. SelectTreeItem:
  453. TreeView_EnsureVisible(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
  454. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, TVItem.hItem);
  455. if (!fFoundMatch)
  456. hFocusWnd = g_RegEditData.hKeyTreeWnd;
  457. else {
  458. //
  459. // Right now, the TreeView_SelectItem above will cause the ValueListWnd
  460. // to update, but only after a short time delay. We want the list
  461. // immediately updated, so force the timer to go off now.
  462. //
  463. RegEdit_OnSelChangedTimer(hWnd);
  464. if (BestValueName[0] == 0)
  465. LVItem.iItem = 0;
  466. else {
  467. LVFindInfo.flags = LVFI_STRING;
  468. LVFindInfo.psz = BestValueName;
  469. LVItem.iItem = ListView_FindItem(g_RegEditData.hValueListWnd,
  470. -1, &LVFindInfo);
  471. }
  472. SelectListItem:
  473. ListView_SetItemState(g_RegEditData.hValueListWnd, -1, 0,
  474. LVIS_SELECTED | LVIS_FOCUSED);
  475. ListView_SetItemState(g_RegEditData.hValueListWnd, LVItem.iItem,
  476. LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  477. ListView_EnsureVisible(g_RegEditData.hValueListWnd, LVItem.iItem,
  478. FALSE);
  479. hFocusWnd = g_RegEditData.hValueListWnd;
  480. }
  481. DismissRegFindAbortWnd:
  482. RegEdit_SetWaitCursor(FALSE);
  483. if (hRegFindAbortWnd != NULL) {
  484. g_RegEditData.fProcessingFind = FALSE;
  485. SetWindowRedraw(g_RegEditData.hKeyTreeWnd, TRUE);
  486. EnableWindow(hWnd, TRUE);
  487. DestroyWindow(hRegFindAbortWnd);
  488. }
  489. if (hFocusWnd != NULL)
  490. SetFocus(hFocusWnd);
  491. if (fError)
  492. {
  493. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(uErrorStringID),
  494. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONERROR | MB_OK);
  495. }
  496. if (fSearchedToEnd)
  497. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(IDS_SEARCHEDTOEND),
  498. MAKEINTRESOURCE(IDS_REGEDIT), MB_ICONINFORMATION | MB_OK);
  499. }
  500. /*******************************************************************************
  501. *
  502. * FindCompare
  503. *
  504. * DESCRIPTION:
  505. *
  506. * PARAMETERS:
  507. *
  508. *******************************************************************************/
  509. BOOL
  510. PASCAL
  511. FindCompare(
  512. LPTSTR lpString
  513. )
  514. {
  515. if (g_FindFlags & FIND_EXACT)
  516. return lstrcmpi(lpString, s_FindSpecification) == 0;
  517. else
  518. return StrStrI(lpString, s_FindSpecification) != NULL;
  519. }
  520. /*******************************************************************************
  521. *
  522. * RegFindDlgProc
  523. *
  524. * DESCRIPTION:
  525. *
  526. * PARAMETERS:
  527. *
  528. *******************************************************************************/
  529. INT_PTR
  530. PASCAL
  531. RegFindDlgProc(
  532. HWND hWnd,
  533. UINT Message,
  534. WPARAM wParam,
  535. LPARAM lParam
  536. )
  537. {
  538. switch (Message) {
  539. HANDLE_MSG(hWnd, WM_INITDIALOG, RegFind_OnInitDialog);
  540. HANDLE_MSG(hWnd, WM_COMMAND, RegFind_OnCommand);
  541. case WM_HELP:
  542. WinHelp(((LPHELPINFO) lParam)-> hItemHandle, g_pHelpFileName,
  543. HELP_WM_HELP, (ULONG_PTR) s_RegFindHelpIDs);
  544. break;
  545. case WM_CONTEXTMENU:
  546. WinHelp((HWND) wParam, g_pHelpFileName, HELP_CONTEXTMENU,
  547. (ULONG_PTR) s_RegFindHelpIDs);
  548. break;
  549. default:
  550. return FALSE;
  551. }
  552. return TRUE;
  553. }
  554. /*******************************************************************************
  555. *
  556. * RegFind_OnInitDialog
  557. *
  558. * DESCRIPTION:
  559. *
  560. * PARAMETERS:
  561. *
  562. *******************************************************************************/
  563. BOOL
  564. PASCAL
  565. RegFind_OnInitDialog(
  566. HWND hWnd,
  567. HWND hFocusWnd,
  568. LPARAM lParam
  569. )
  570. {
  571. UINT Counter;
  572. int DlgItem;
  573. //
  574. // Initialize the "Find What" edit control.
  575. //
  576. SendDlgItemMessage(hWnd, IDC_FINDWHAT, EM_SETLIMITTEXT,
  577. SIZE_FINDSPEC, 0);
  578. SetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification);
  579. //
  580. // Initialize the checkboxes based on the state of the global find flags.
  581. //
  582. s_RegFindData.LookForCount = 0;
  583. for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) /
  584. sizeof(DLGITEMFINDFLAGASSOC); Counter++) {
  585. if (g_FindFlags & s_DlgItemFindFlagAssoc[Counter].Flag) {
  586. DlgItem = s_DlgItemFindFlagAssoc[Counter].DlgItem;
  587. CheckDlgButton(hWnd, DlgItem, TRUE);
  588. if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA)
  589. s_RegFindData.LookForCount++;
  590. }
  591. }
  592. return TRUE;
  593. UNREFERENCED_PARAMETER(hFocusWnd);
  594. UNREFERENCED_PARAMETER(lParam);
  595. }
  596. /*******************************************************************************
  597. *
  598. * RegFind_OnCommand
  599. *
  600. * DESCRIPTION:
  601. *
  602. * PARAMETERS:
  603. *
  604. *******************************************************************************/
  605. VOID
  606. PASCAL
  607. RegFind_OnCommand(
  608. HWND hWnd,
  609. int DlgItem,
  610. HWND hControlWnd,
  611. UINT NotificationCode
  612. )
  613. {
  614. UINT Counter;
  615. if (DlgItem >= IDC_FORKEYS && DlgItem <= IDC_FORDATA) {
  616. if (NotificationCode == BN_CLICKED) {
  617. IsDlgButtonChecked(hWnd, DlgItem) ? s_RegFindData.LookForCount++ :
  618. s_RegFindData.LookForCount--;
  619. goto EnableFindNextButton;
  620. }
  621. }
  622. else {
  623. switch (DlgItem) {
  624. case IDC_FINDWHAT:
  625. if (NotificationCode == EN_CHANGE) {
  626. EnableFindNextButton:
  627. EnableWindow(GetDlgItem(hWnd, IDOK),
  628. s_RegFindData.LookForCount > 0 &&
  629. SendDlgItemMessage(hWnd, IDC_FINDWHAT,
  630. WM_GETTEXTLENGTH, 0, 0) != 0);
  631. }
  632. break;
  633. case IDOK:
  634. GetDlgItemText(hWnd, IDC_FINDWHAT, s_FindSpecification,
  635. sizeof(s_FindSpecification)/sizeof(TCHAR));
  636. for (Counter = 0; Counter < sizeof(s_DlgItemFindFlagAssoc) /
  637. sizeof(DLGITEMFINDFLAGASSOC); Counter++) {
  638. if (IsDlgButtonChecked(hWnd,
  639. s_DlgItemFindFlagAssoc[Counter].DlgItem))
  640. g_FindFlags |= s_DlgItemFindFlagAssoc[Counter].Flag;
  641. else
  642. g_FindFlags &= ~s_DlgItemFindFlagAssoc[Counter].Flag;
  643. }
  644. // FALL THROUGH
  645. case IDCANCEL:
  646. EndDialog(hWnd, DlgItem);
  647. break;
  648. }
  649. }
  650. }
  651. /*******************************************************************************
  652. *
  653. * RegFindAbortProc
  654. *
  655. * DESCRIPTION:
  656. *
  657. * PARAMETERS:
  658. * (returns), TRUE to continue the find, else FALSE to cancel.
  659. *
  660. *******************************************************************************/
  661. BOOL
  662. PASCAL
  663. RegFindAbortProc(
  664. HWND hRegFindAbortWnd
  665. )
  666. {
  667. while (s_fContinueFind && MessagePump(hRegFindAbortWnd))
  668. ;
  669. return s_fContinueFind;
  670. }
  671. /*******************************************************************************
  672. *
  673. * RegAbortDlgProc
  674. *
  675. * DESCRIPTION:
  676. * Callback procedure for the RegAbort dialog box.
  677. *
  678. * PARAMETERS:
  679. * hWnd, handle of RegAbort window.
  680. * Message,
  681. * wParam,
  682. * lParam,
  683. * (returns),
  684. *
  685. *******************************************************************************/
  686. INT_PTR
  687. CALLBACK
  688. RegFindAbortDlgProc(
  689. HWND hWnd,
  690. UINT Message,
  691. WPARAM wParam,
  692. LPARAM lParam
  693. )
  694. {
  695. switch (Message) {
  696. case WM_INITDIALOG:
  697. break;
  698. case WM_CLOSE:
  699. case WM_COMMAND:
  700. s_fContinueFind = FALSE;
  701. break;
  702. default:
  703. return FALSE;
  704. }
  705. return TRUE;
  706. }