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.

2592 lines
71 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1994
  4. *
  5. * TITLE: REGEDIT.C
  6. *
  7. * VERSION: 4.01
  8. *
  9. * AUTHOR: Tracy Sharpe
  10. *
  11. * DATE: 05 Mar 1994
  12. *
  13. *******************************************************************************/
  14. #include "pch.h"
  15. #include <regstr.h>
  16. #include "regedit.h"
  17. #include "regkey.h"
  18. #include "regvalue.h"
  19. #include "regfile.h"
  20. #include "regprint.h"
  21. #include "regnet.h"
  22. #include "regfind.h"
  23. #include "regresid.h"
  24. #include <htmlhelp.h>
  25. #include <tchar.h>
  26. #include "authz.h"
  27. #include "objbase.h"
  28. #include "aclapi.h"
  29. #include "aclui.h"
  30. extern HRESULT CreateSecurityInformation( IN LPCWSTR strKeyName,
  31. IN LPCWSTR strParentName,
  32. IN LPCWSTR strMachineName,
  33. IN LPCWSTR strPageTitle,
  34. IN BOOL bRemote,
  35. IN PREDEFINE_KEY PredefinedKey,
  36. IN BOOL bReadOnly,
  37. IN HWND hWnd,
  38. OUT LPSECURITYINFO *pSi);
  39. //
  40. // Popup menu indexes of the IDM_REGEDIT menu.
  41. //
  42. #define IDM_REGEDIT_FILE_POPUP 0
  43. #define IDM_REGEDIT_EDIT_POPUP 1
  44. #define IDM_REGEDIT_VIEW_POPUP 2
  45. #define IDM_REGEDIT_FAVS_POPUP 3
  46. #define IDM_REGEDIT_HELP_POPUP 4
  47. //
  48. // Indexes of the "New->" popup menu under the IDM_REGEDIT's "Edit" menu when
  49. // the focus is in the KeyTree or the ValueList. Changes because "Modify" and
  50. // a seperator are dynamically added/removed.
  51. //
  52. #define IDM_EDIT_WHENKEY_NEW_POPUP 0
  53. #define IDM_EDIT_WHENVALUE_NEW_POPUP 2
  54. //
  55. // Data structure stored in the registry to store the position and sizes of
  56. // various elements of the Registry Editor interface.
  57. //
  58. typedef struct _REGEDITVIEW {
  59. WINDOWPLACEMENT WindowPlacement;
  60. int xPaneSplit;
  61. int cxNameColumn;
  62. int cxTypeColumn;
  63. int cxDataColumn;
  64. DWORD Flags;
  65. } REGEDITVIEW, FAR* LPREGEDITVIEW;
  66. #define REV_STATUSBARVISIBLE 0x00000001
  67. // Class name of main application window.
  68. const TCHAR g_RegEditClassName[] = TEXT("RegEdit_RegEdit");
  69. // Applet specific information is stored under this key of HKEY_CURRENT_USER.
  70. const TCHAR g_RegEditAppletKey[] = REGSTR_PATH_WINDOWSAPPLETS TEXT("\\Regedit");
  71. //
  72. // Favorites information is stored under this key of HKEY_CURRENT_USER
  73. //
  74. const TCHAR g_RegEditFavoritesKey[] = REGSTR_PATH_WINDOWSAPPLETS TEXT("\\Regedit\\Favorites");
  75. // Record of type REGEDITVIEW under g_RegEditAppletKey.
  76. const TCHAR g_RegEditViewValue[] = TEXT("View");
  77. // Record of type DWORD under g_RegEditAppletKey.
  78. const TCHAR g_RegEditFindFlagsValue[] = TEXT("FindFlags");
  79. //
  80. // Record of LPTSTR under g_RegEditAppletKey that rememebers that key where RegEdit was closed.
  81. //
  82. const TCHAR g_RegEditLastKeyValue[] = TEXT("LastKey");
  83. //
  84. // Values for import/export of multiline strings
  85. //
  86. const TCHAR g_RegEditMultiStringsValue[] = TEXT("MultiStrings");
  87. BOOL g_fMultiLineStrings = FALSE;
  88. // Data structure used when calling GetEffectiveClientRect (which takes into
  89. // account space taken up by the toolbars/status bars). First half of the
  90. // pair is zero when at the end of the list, second half is the control id.
  91. const int s_EffectiveClientRectData[] = {
  92. 1, 0, // For the menu bar, but is unused
  93. 1, IDC_STATUSBAR,
  94. 0, 0 // First zero marks end of data
  95. };
  96. // Context sensitive help array used by the WinHelp engine.
  97. const DWORD g_ContextMenuHelpIDs[] = {
  98. 0, 0
  99. };
  100. // Data structure used when calling MenuHelp.
  101. const int s_RegEditMenuHelpData[] = {
  102. 0, 0,
  103. 0, (UINT) 0
  104. };
  105. REGEDITDATA g_RegEditData = {
  106. NULL, // hKeyTreeWnd
  107. NULL, // hValueListWnd
  108. NULL, // hStatusBarWnd
  109. NULL, // hFocusWnd
  110. 0, // xPaneSplit
  111. NULL, // hImageList
  112. NULL, // hCurrentSelectionKey
  113. SCTS_INITIALIZING, // SelChangeTimerState
  114. SW_SHOW, // StatusBarShowCommand
  115. NULL, // pDefaultValue
  116. NULL, // pValueNotPresent
  117. NULL, // pEmptyBinary
  118. NULL, // pCollapse
  119. NULL, // pModify
  120. NULL, // pModifyBinary
  121. NULL, // pNewKeyTemplate
  122. NULL, // pNewValueTemplate
  123. FALSE, // fAllowLabelEdits
  124. NULL, // hMainMenu
  125. FALSE, // fMainMenuInited
  126. FALSE, // fHaveNetwork
  127. FALSE, // fProcessingFind
  128. NULL, // hMyComputer
  129. FILE_TYPE_REGEDIT5 // uExportFormat
  130. };
  131. BOOL
  132. PASCAL
  133. QueryRegEditView(
  134. LPREGEDITVIEW lpRegEditView
  135. );
  136. LRESULT
  137. PASCAL
  138. RegEditWndProc(
  139. HWND hWnd,
  140. UINT Message,
  141. WPARAM wParam,
  142. LPARAM lParam
  143. );
  144. BOOL
  145. PASCAL
  146. RegEdit_OnCreate(
  147. HWND hWnd,
  148. LPCREATESTRUCT lpCreateStruct
  149. );
  150. BOOL
  151. PASCAL
  152. RegEdit_OnContextMenu(
  153. HWND hWnd,
  154. HWND hWndTarget,
  155. int xPos,
  156. int yPos
  157. );
  158. VOID
  159. PASCAL
  160. RegEdit_OnDestroy(
  161. HWND hWnd
  162. );
  163. LRESULT
  164. PASCAL
  165. RegEdit_OnNotify(
  166. HWND hWnd,
  167. int DlgItem,
  168. LPNMHDR lpNMHdr
  169. );
  170. VOID
  171. PASCAL
  172. RegEdit_OnInitMenuPopup(
  173. HWND hWnd,
  174. HMENU hPopupMenu,
  175. UINT MenuPosition,
  176. BOOL fSystemMenu
  177. );
  178. VOID
  179. PASCAL
  180. RegEdit_OnMenuSelect(
  181. HWND hWnd,
  182. WPARAM wParam,
  183. LPARAM lParam
  184. );
  185. VOID
  186. PASCAL
  187. RegEdit_OnLButtonDown(
  188. HWND hWnd,
  189. BOOL fDoubleClick,
  190. int x,
  191. int y,
  192. UINT KeyFlags
  193. );
  194. VOID
  195. PASCAL
  196. RegEdit_OnCommandSplit(
  197. HWND hWnd
  198. );
  199. #define RESIZEFROM_UNKNOWN 0
  200. #define RESIZEFROM_SPLIT 1
  201. VOID
  202. PASCAL
  203. RegEdit_ResizeWindow(
  204. HWND hWnd,
  205. UINT ResizeFrom
  206. );
  207. BOOL
  208. PASCAL
  209. RegEdit_SetImageLists(
  210. HWND hWnd
  211. );
  212. VOID
  213. PASCAL
  214. RegEdit_SetSysColors(
  215. VOID
  216. );
  217. INT_PTR PASCAL
  218. RegAddFavoriteDlgProc(
  219. HWND hWnd,
  220. UINT Message,
  221. WPARAM wParam,
  222. LPARAM lParam
  223. );
  224. /*******************************************************************************
  225. *
  226. * RegisterRegEditClass
  227. *
  228. * DESCRIPTION:
  229. * Register the RegEdit window class with the system.
  230. *
  231. * PARAMETERS:
  232. * (none).
  233. *
  234. *******************************************************************************/
  235. BOOL
  236. PASCAL
  237. RegisterRegEditClass(
  238. VOID
  239. )
  240. {
  241. WNDCLASSEX WndClassEx;
  242. WndClassEx.cbSize = sizeof(WNDCLASSEX);
  243. WndClassEx.style = CS_DBLCLKS | CS_BYTEALIGNWINDOW | CS_GLOBALCLASS;
  244. WndClassEx.lpfnWndProc = RegEditWndProc;
  245. WndClassEx.cbClsExtra = 0;
  246. WndClassEx.cbWndExtra = 0;
  247. WndClassEx.hInstance = g_hInstance;
  248. WndClassEx.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_REGEDIT));
  249. WndClassEx.hCursor = LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_SPLIT));
  250. WndClassEx.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1);
  251. WndClassEx.lpszMenuName = MAKEINTRESOURCE(IDM_REGEDIT);
  252. WndClassEx.lpszClassName = g_RegEditClassName;
  253. WndClassEx.hIconSm = LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_REGEDIT),
  254. IMAGE_ICON, 16, 16, 0);
  255. return RegisterClassEx(&WndClassEx);
  256. }
  257. /*******************************************************************************
  258. *
  259. * CreateRegEditWnd
  260. *
  261. * DESCRIPTION:
  262. * Creates an instance of the RegEdit window.
  263. *
  264. * PARAMETERS:
  265. * (none).
  266. *
  267. *******************************************************************************/
  268. HWND
  269. PASCAL
  270. CreateRegEditWnd(
  271. VOID
  272. )
  273. {
  274. PTSTR pTitle;
  275. HWND hRegEditWnd;
  276. REGEDITVIEW RegEditView;
  277. BOOL fQueryRegEditViewSuccess;
  278. if ((pTitle = LoadDynamicString(IDS_REGEDIT)) != NULL) {
  279. fQueryRegEditViewSuccess = QueryRegEditView(&RegEditView);
  280. hRegEditWnd = CreateWindowEx(WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES,
  281. g_RegEditClassName, pTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  282. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  283. NULL, NULL, g_hInstance, (LPVOID) &RegEditView);
  284. if (fQueryRegEditViewSuccess) {
  285. RegEditView.WindowPlacement.length = sizeof(RegEditView.WindowPlacement);
  286. if (RegEditView.WindowPlacement.showCmd == SW_SHOWMINIMIZED)
  287. RegEditView.WindowPlacement.showCmd = SW_SHOWDEFAULT;
  288. SetWindowPlacement(hRegEditWnd, &RegEditView.WindowPlacement);
  289. }
  290. else
  291. ShowWindow(hRegEditWnd, SW_SHOWDEFAULT);
  292. DeleteDynamicString(pTitle);
  293. }
  294. else
  295. hRegEditWnd = NULL;
  296. return hRegEditWnd;
  297. }
  298. /*******************************************************************************
  299. *
  300. * QueryRegEditView
  301. *
  302. * DESCRIPTION:
  303. * Check the registry for a data structure that contains the last positions
  304. * of our various interface components.
  305. *
  306. * PARAMETERS:
  307. * (none).
  308. *
  309. *******************************************************************************/
  310. BOOL
  311. PASCAL
  312. QueryRegEditView(
  313. LPREGEDITVIEW lpRegEditView
  314. )
  315. {
  316. BOOL fSuccess;
  317. HKEY hKey;
  318. DWORD cbValueData;
  319. DWORD Type;
  320. int cxIcon;
  321. HDC hDC;
  322. int PixelsPerInch;
  323. fSuccess = FALSE;
  324. if (RegOpenKey(HKEY_CURRENT_USER, g_RegEditAppletKey, &hKey) ==
  325. ERROR_SUCCESS) {
  326. //
  327. // Sort of a hack, but while we're here, pull the last find flags from
  328. // the registry as well.
  329. //
  330. cbValueData = sizeof(DWORD);
  331. RegEdit_QueryValueEx(hKey, (LPTSTR) g_RegEditFindFlagsValue, NULL, &Type,
  332. (LPBYTE) &g_FindFlags, &cbValueData);
  333. cbValueData = sizeof(REGEDITVIEW);
  334. if (RegEdit_QueryValueEx(hKey, (LPTSTR) g_RegEditViewValue, NULL, &Type,
  335. (LPBYTE) lpRegEditView, &cbValueData) == ERROR_SUCCESS &&
  336. Type == REG_BINARY && cbValueData == sizeof(REGEDITVIEW))
  337. fSuccess = TRUE;
  338. RegCloseKey(hKey);
  339. }
  340. //
  341. // Validate the fields from the view data structure. Several people have
  342. // run into cases where the name and data column widths were invalid so
  343. // they couldn't see them. Without this validation, the only way to fix it
  344. // is to run our application... ugh.
  345. //
  346. if (fSuccess) {
  347. cxIcon = GetSystemMetrics(SM_CXICON);
  348. if (lpRegEditView-> cxNameColumn < cxIcon)
  349. lpRegEditView-> cxNameColumn = cxIcon;
  350. if (lpRegEditView-> cxDataColumn < cxIcon)
  351. lpRegEditView-> cxDataColumn = cxIcon;
  352. if (lpRegEditView-> xPaneSplit < cxIcon)
  353. lpRegEditView-> xPaneSplit = cxIcon;
  354. }
  355. //
  356. // This is probably our first time running the Registry Editor (or else
  357. // there was some sort of registry error), so pick some good(?) defaults
  358. // for the various interface components.
  359. //
  360. else {
  361. lpRegEditView-> Flags = REV_STATUSBARVISIBLE;
  362. //
  363. // Figure out how many pixels there are in two logical inches. We use this
  364. // to set the initial size of the TreeView pane (this is what the Cabinet
  365. // does) and of the Name column of the ListView pane.
  366. //
  367. hDC = GetDC(NULL);
  368. PixelsPerInch = GetDeviceCaps(hDC, LOGPIXELSX);
  369. ReleaseDC(NULL, hDC);
  370. lpRegEditView-> xPaneSplit = PixelsPerInch * 9 / 4; // 2.25 inches
  371. lpRegEditView-> cxNameColumn = PixelsPerInch * 5 / 4; // 1.25 inches
  372. lpRegEditView-> cxTypeColumn = PixelsPerInch * 5 / 4; // 1.25 inches
  373. lpRegEditView-> cxDataColumn = PixelsPerInch * 3; // 3.00 inches
  374. }
  375. return fSuccess;
  376. }
  377. /*******************************************************************************
  378. *
  379. * RegEditWndProc
  380. *
  381. * DESCRIPTION:
  382. * Callback procedure for the RegEdit window.
  383. *
  384. * PARAMETERS:
  385. * hWnd, handle of RegEdit window.
  386. * Message,
  387. * wParam,
  388. * lParam,
  389. * (returns),
  390. *
  391. *******************************************************************************/
  392. LRESULT
  393. PASCAL
  394. RegEditWndProc(
  395. HWND hWnd,
  396. UINT Message,
  397. WPARAM wParam,
  398. LPARAM lParam
  399. )
  400. {
  401. switch (Message) {
  402. HANDLE_MSG(hWnd, WM_CREATE, RegEdit_OnCreate);
  403. HANDLE_MSG(hWnd, WM_DESTROY, RegEdit_OnDestroy);
  404. HANDLE_MSG(hWnd, WM_COMMAND, RegEdit_OnCommand);
  405. HANDLE_MSG(hWnd, WM_NOTIFY, RegEdit_OnNotify);
  406. HANDLE_MSG(hWnd, WM_INITMENUPOPUP, RegEdit_OnInitMenuPopup);
  407. HANDLE_MSG(hWnd, WM_LBUTTONDOWN, RegEdit_OnLButtonDown);
  408. HANDLE_MSG(hWnd, WM_DROPFILES, RegEdit_OnDropFiles);
  409. //can't use HANDLE_MSG for this because we lose the sign on the x and y parms
  410. case WM_CONTEXTMENU:
  411. if (!RegEdit_OnContextMenu(hWnd, (HWND)(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)))
  412. goto dodefault;
  413. break;
  414. //
  415. // We have to update the status bar after a rename, but the tree item's
  416. // text hasn't changed until after we return from the end notification,
  417. // so we post this dummy message to tell ourselves to do it later.
  418. //
  419. case REM_UPDATESTATUSBAR:
  420. RegEdit_UpdateStatusBar();
  421. break;
  422. //
  423. // We must watch for this message to know that when we're in
  424. // WM_INITMENUPOPUP, we're really looking at the main menu and not a
  425. // context menu.
  426. //
  427. case WM_INITMENU:
  428. g_RegEditData.fMainMenuInited = (g_RegEditData.hMainMenu == (HMENU)
  429. wParam);
  430. break;
  431. case WM_ACTIVATE:
  432. if (wParam == WA_INACTIVE)
  433. break;
  434. // FALL THROUGH
  435. case WM_SETFOCUS:
  436. SetFocus(g_RegEditData.hFocusWnd);
  437. break;
  438. case WM_WININICHANGE:
  439. RegEdit_SetImageLists(hWnd);
  440. // FALL THROUGH
  441. case WM_SYSCOLORCHANGE:
  442. RegEdit_SetSysColors();
  443. SendChildrenMessage(hWnd, Message, wParam, lParam);
  444. // FALL THROUGH
  445. case WM_SIZE:
  446. RegEdit_ResizeWindow(hWnd, RESIZEFROM_UNKNOWN);
  447. break;
  448. case WM_TIMER:
  449. RegEdit_OnSelChangedTimer(hWnd);
  450. break;
  451. case WM_MENUSELECT:
  452. RegEdit_OnMenuSelect(hWnd, wParam, lParam);
  453. break;
  454. case WM_PAINT:
  455. //
  456. // Force a paint of the TreeView if we're in the middle of a find.
  457. // See REGFIND.C for details on this hack.
  458. //
  459. if (g_RegEditData.fProcessingFind) {
  460. SetWindowRedraw(g_RegEditData.hKeyTreeWnd, TRUE);
  461. UpdateWindow(g_RegEditData.hKeyTreeWnd);
  462. SetWindowRedraw(g_RegEditData.hKeyTreeWnd, FALSE);
  463. }
  464. goto dodefault;
  465. dodefault:
  466. default:
  467. return DefWindowProc(hWnd, Message, wParam, lParam);
  468. }
  469. return 0;
  470. }
  471. /*******************************************************************************
  472. *
  473. * RegEdit_ExpandKeyPath
  474. *
  475. * DESCRIPTION: Traverses registry tree to display the desired key path.
  476. *
  477. * PARAMETERS:
  478. * lpExpandPath - Destination path of registry key to expand
  479. *
  480. *******************************************************************************/
  481. VOID
  482. PASCAL
  483. RegEdit_ExpandKeyPath(
  484. LPTSTR lpExpandPath
  485. )
  486. {
  487. HTREEITEM hItem, hNext;
  488. TCHAR KeyName[MAXKEYNAMEPATH*2];
  489. LPTSTR lpKeyName = KeyName;
  490. TCHAR ExpandBuffer[MAXKEYNAMEPATH*2];
  491. LPTSTR lpExpandBuffer = ExpandBuffer;
  492. LPTSTR lpCurrent, lpOriginal;
  493. BOOL bLastNode = FALSE;
  494. TV_ITEM TVItem;
  495. // Make sure we aren't already at the destination path.
  496. hItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
  497. KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd, hItem, lpKeyName, BKP_TOCOMPUTER);
  498. if (!lstrcmpi(lpKeyName, lpExpandPath))
  499. return;
  500. // Intialize lpKeyName to the My Computer string
  501. KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd, g_RegEditData.hMyComputer, lpKeyName, BKP_TOCOMPUTER);
  502. // Walk backwards until we find a common root node and place that in lpKeyName.
  503. while ((hItem != g_RegEditData.hMyComputer) && hItem)
  504. {
  505. hItem = TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hItem);
  506. KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd, hItem, lpKeyName, BKP_TOCOMPUTER);
  507. if (!_tcsncmp(lpKeyName, lpExpandPath, lstrlen(lpKeyName)))
  508. break;
  509. }
  510. // Make sure the common parent node is selected and visible.
  511. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, hItem);
  512. TreeView_EnsureVisible(g_RegEditData.hKeyTreeWnd, hItem);
  513. //
  514. // If the destination path is deeper than the common parent,
  515. // we want to null-terminate the path components so we can
  516. // expand the registry tree for each path sub-component.
  517. //
  518. lstrcpy(lpExpandBuffer, lpExpandPath);
  519. lpOriginal = lpExpandBuffer;
  520. if (lstrlen(lpExpandBuffer) >= lstrlen(lpKeyName))
  521. {
  522. while (!bLastNode)
  523. {
  524. // Try to find the next path separator
  525. lpCurrent = (LPTSTR) _tcschr(lpOriginal, TEXT('\\'));
  526. if (lpCurrent)
  527. {
  528. // Null-terminate the sub-string
  529. *lpCurrent = 0;
  530. // Check if there's more
  531. if (lpCurrent <= (lpExpandBuffer + lstrlen(lpKeyName)))
  532. {
  533. // Now step over the path separator we just made NULL
  534. lpOriginal = lpCurrent + 1;
  535. } else bLastNode = TRUE;
  536. } else bLastNode = TRUE;
  537. }
  538. // Now reset bLastNode to FALSE
  539. bLastNode = FALSE;
  540. }
  541. //
  542. // Get the first child from the common parent and start traversing the treeview
  543. //
  544. hItem = TreeView_GetChild(g_RegEditData.hKeyTreeWnd, hItem);
  545. while(hItem)
  546. {
  547. // Get a handle to the next node
  548. hNext = TreeView_GetNextSibling(g_RegEditData.hKeyTreeWnd, hItem);
  549. ZeroMemory(&TVItem, sizeof(TV_ITEM));
  550. TVItem.hItem = hItem;
  551. TVItem.mask = TVIF_TEXT;
  552. TVItem.pszText = lpKeyName;
  553. TVItem.cchTextMax = sizeof(KeyName);
  554. TreeView_GetItem(g_RegEditData.hKeyTreeWnd, &TVItem);
  555. //
  556. // If the child node matches our path component, then we want to expand that node.
  557. //
  558. if (!lstrcmpi(lpKeyName, lpOriginal))
  559. {
  560. TreeView_Expand(g_RegEditData.hKeyTreeWnd, hItem, TVE_EXPAND);
  561. // Replace hNext with the first child of our freshly expanded node.
  562. hNext = TreeView_GetChild(g_RegEditData.hKeyTreeWnd, hItem);
  563. // If this is the last node, make it visible and return
  564. if (bLastNode || !lpCurrent)
  565. {
  566. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, hItem);
  567. TreeView_EnsureVisible(g_RegEditData.hKeyTreeWnd, hItem);
  568. return;
  569. }
  570. else lpOriginal = lpCurrent + 1;
  571. lpCurrent = (LPTSTR) _tcschr(lpOriginal, TEXT('\\'));
  572. if (!lpCurrent)
  573. bLastNode = TRUE;
  574. else *lpCurrent = 0;
  575. }
  576. // Repeat the loop with the appropriate next tree node
  577. hItem = hNext;
  578. }
  579. }
  580. /*******************************************************************************
  581. *
  582. * RegEdit_OnContextMenu
  583. *
  584. * DESCRIPTION:
  585. *
  586. * PARAMETERS:
  587. * hWnd, handle of RegEdit window.
  588. * hWndTarget, handle of window in which WM_CONTEXTMENU occurred.
  589. * xPos
  590. * yPos
  591. *
  592. *******************************************************************************/
  593. BOOL
  594. PASCAL
  595. RegEdit_OnContextMenu(
  596. HWND hWnd,
  597. HWND hWndTarget,
  598. int xPos,
  599. int yPos
  600. )
  601. {
  602. BOOL bAccel = ((xPos == -1) && (yPos == -1)) ? TRUE : FALSE;
  603. if (hWndTarget == g_RegEditData.hKeyTreeWnd)
  604. RegEdit_OnKeyTreeContextMenu(hWndTarget, bAccel);
  605. else if (hWndTarget == g_RegEditData.hValueListWnd)
  606. RegEdit_OnValueListContextMenu(hWndTarget, bAccel);
  607. else
  608. return FALSE;
  609. return TRUE;
  610. }
  611. /*******************************************************************************
  612. *
  613. * RegEdit_OnCreate
  614. *
  615. * DESCRIPTION:
  616. *
  617. * PARAMETERS:
  618. * hWnd, handle of RegEdit window.
  619. *
  620. *******************************************************************************/
  621. BOOL
  622. PASCAL
  623. RegEdit_OnCreate(
  624. HWND hWnd,
  625. LPCREATESTRUCT lpCreateStruct
  626. )
  627. {
  628. LPREGEDITVIEW lpRegEditView;
  629. UINT Index;
  630. TV_INSERTSTRUCT TVInsertStruct;
  631. TCHAR CheckChildrenKeyName[MAXKEYNAME];
  632. LV_COLUMN LVColumn;
  633. HMENU hPopupMenu;
  634. HKEY hKey;
  635. DWORD cbValueData;
  636. DWORD Type;
  637. TCHAR KeyName[MAXKEYNAMEPATH*2];
  638. LPTSTR lpKeyName = KeyName;
  639. DWORD dwStyleEx = WS_EX_CLIENTEDGE;
  640. DWORD dwLayout = 0;
  641. DWORD dwValue = 0;
  642. lpRegEditView = (LPREGEDITVIEW) lpCreateStruct-> lpCreateParams;
  643. //
  644. // Load several strings that will be using very often to display the keys
  645. // and values.
  646. //
  647. if ((g_RegEditData.pDefaultValue = LoadDynamicString(IDS_DEFAULTVALUE)) ==
  648. NULL)
  649. return FALSE;
  650. if ((g_RegEditData.pValueNotSet = LoadDynamicString(IDS_VALUENOTSET)) ==
  651. NULL)
  652. return FALSE;
  653. if ((g_RegEditData.pEmptyBinary = LoadDynamicString(IDS_EMPTYBINARY)) ==
  654. NULL)
  655. return FALSE;
  656. if ((g_RegEditData.pCollapse = LoadDynamicString(IDS_COLLAPSE)) == NULL)
  657. return FALSE;
  658. if ((g_RegEditData.pModify = LoadDynamicString(IDS_MODIFY)) == NULL)
  659. return FALSE;
  660. if ((g_RegEditData.pModifyBinary = LoadDynamicString(IDS_MODIFYBINARY)) == NULL)
  661. return FALSE;
  662. if ((g_RegEditData.pNewKeyTemplate =
  663. LoadDynamicString(IDS_NEWKEYNAMETEMPLATE)) == NULL)
  664. return FALSE;
  665. if ((g_RegEditData.pNewValueTemplate =
  666. LoadDynamicString(IDS_NEWVALUENAMETEMPLATE)) == NULL)
  667. return FALSE;
  668. /*
  669. * Check if the default layout for this process is RTL. Most data
  670. * in the registry is best edited with LTR reading order. So we
  671. * reverse the reading order for the two data windows (key tree and
  672. * value list) again.
  673. */
  674. if (GetProcessDefaultLayout(&dwLayout)) {
  675. if (dwLayout & LAYOUT_RTL) {
  676. dwStyleEx |= WS_EX_RTLREADING; // Actually just switches back to LTR.
  677. }
  678. }
  679. //
  680. // Create the left pane, a TreeView control that displays the keys of the
  681. // registry.
  682. //
  683. if ((g_RegEditData.hKeyTreeWnd = CreateWindowEx(dwStyleEx,
  684. WC_TREEVIEW, NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | TVS_HASBUTTONS |
  685. TVS_DISABLEDRAGDROP | TVS_LINESATROOT | TVS_HASLINES | TVS_EDITLABELS,
  686. 0, 0, 0, 0, hWnd, (HMENU) IDC_KEYTREE, g_hInstance, NULL)) == NULL)
  687. return FALSE;
  688. //
  689. // Create the right pane, a ListView control that displays the values of
  690. // the currently selected key of the sibling TreeView control.
  691. //
  692. if ((g_RegEditData.hValueListWnd = CreateWindowEx(dwStyleEx,
  693. WC_LISTVIEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN |
  694. WS_TABSTOP | LVS_REPORT | LVS_ALIGNLEFT | LVS_EDITLABELS |
  695. LVS_SHAREIMAGELISTS | LVS_NOSORTHEADER, 0, 0, 0, 0, hWnd,
  696. (HMENU) IDC_VALUELIST, g_hInstance, NULL)) == NULL)
  697. return FALSE;
  698. ListView_SetExtendedListViewStyleEx(g_RegEditData.hValueListWnd,
  699. LVS_EX_LABELTIP, LVS_EX_LABELTIP);
  700. //
  701. // Create the status bar window. We'll set it to "simple" mode now
  702. // because we need only one pane that's only used when scrolling through
  703. // the menus.
  704. //
  705. if ((g_RegEditData.hStatusBarWnd = CreateStatusWindow(WS_CHILD |
  706. SBARS_SIZEGRIP | CCS_NOHILITE, NULL, hWnd, IDC_STATUSBAR)) == NULL)
  707. return FALSE;
  708. g_RegEditData.StatusBarShowCommand = lpRegEditView-> Flags &
  709. REV_STATUSBARVISIBLE ? SW_SHOW : SW_HIDE;
  710. ShowWindow(g_RegEditData.hStatusBarWnd, g_RegEditData.StatusBarShowCommand);
  711. if (!RegEdit_SetImageLists(hWnd))
  712. return FALSE;
  713. RegEdit_SetSysColors();
  714. //
  715. //
  716. //
  717. TVInsertStruct.hParent = TVI_ROOT;
  718. TVInsertStruct.hInsertAfter = TVI_LAST;
  719. TVInsertStruct.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
  720. TVIF_PARAM | TVIF_CHILDREN;
  721. // TVInsertStruct.item.hItem = NULL;
  722. // TVInsertStruct.item.state = 0;
  723. // TVInsertStruct.item.stateMask = 0;
  724. // TVInsertStruct.item.cchTextMax = 0;
  725. TVInsertStruct.item.iImage = IMAGEINDEX(IDI_COMPUTER);
  726. TVInsertStruct.item.iSelectedImage = IMAGEINDEX(IDI_COMPUTER);
  727. TVInsertStruct.item.cChildren = TRUE;
  728. TVInsertStruct.item.lParam = 0;
  729. TVInsertStruct.item.pszText = LoadDynamicString(IDS_COMPUTER);
  730. TVInsertStruct.hParent = TreeView_InsertItem(g_RegEditData.hKeyTreeWnd,
  731. &TVInsertStruct);
  732. DeleteDynamicString(TVInsertStruct.item.pszText);
  733. TVInsertStruct.item.iImage = IMAGEINDEX(IDI_FOLDER);
  734. TVInsertStruct.item.iSelectedImage = IMAGEINDEX(IDI_FOLDEROPEN);
  735. for (Index = 0; Index < NUMBER_REGISTRY_ROOTS; Index++) {
  736. #ifdef WINNT
  737. //
  738. // HKEY_DYN_DATA is not available on NT, so don't bother including it
  739. // in the tree. Note we still keep the string around in case we can
  740. // connect to the key remotely.
  741. //
  742. if (Index == INDEX_HKEY_DYN_DATA)
  743. continue;
  744. #endif
  745. TVInsertStruct.item.pszText = g_RegistryRoots[Index].lpKeyName;
  746. TVInsertStruct.item.lParam = (LPARAM) g_RegistryRoots[Index].hKey;
  747. TVInsertStruct.item.cChildren = (RegEnumKey(g_RegistryRoots[Index].hKey,
  748. 0, CheckChildrenKeyName, sizeof(CheckChildrenKeyName)/sizeof(TCHAR)) ==
  749. ERROR_SUCCESS);
  750. TreeView_InsertItem(g_RegEditData.hKeyTreeWnd, &TVInsertStruct);
  751. }
  752. TreeView_Expand(g_RegEditData.hKeyTreeWnd, TVInsertStruct.hParent,
  753. TVE_EXPAND);
  754. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, TVInsertStruct.hParent);
  755. g_RegEditData.SelChangeTimerState = SCTS_TIMERCLEAR;
  756. //
  757. //
  758. //
  759. g_RegEditData.hFocusWnd = g_RegEditData.hKeyTreeWnd;
  760. g_RegEditData.xPaneSplit = lpRegEditView-> xPaneSplit;
  761. //
  762. // Set the column headings used by our report-style ListView control.
  763. //
  764. LVColumn.mask = LVCF_WIDTH | LVCF_TEXT;
  765. LVColumn.cx = lpRegEditView-> cxNameColumn;
  766. LVColumn.pszText = LoadDynamicString(IDS_NAMECOLUMNLABEL);
  767. ListView_InsertColumn(g_RegEditData.hValueListWnd, 0, &LVColumn);
  768. DeleteDynamicString(LVColumn.pszText);
  769. LVColumn.cx = lpRegEditView-> cxTypeColumn;
  770. LVColumn.pszText = LoadDynamicString(IDS_TYPECOLUMNLABEL);
  771. ListView_InsertColumn(g_RegEditData.hValueListWnd, 1, &LVColumn);
  772. DeleteDynamicString(LVColumn.pszText);
  773. LVColumn.cx = lpRegEditView-> cxDataColumn;
  774. LVColumn.pszText = LoadDynamicString(IDS_DATACOLUMNLABEL);
  775. ListView_InsertColumn(g_RegEditData.hValueListWnd, 2, &LVColumn);
  776. DeleteDynamicString(LVColumn.pszText);
  777. //
  778. // Do a one-time zero fill of the PRINTDLGEX to have it in a known state.
  779. //
  780. memset(&g_PrintDlg, 0, sizeof(PRINTDLGEX));
  781. g_RegEditData.hMainMenu = GetMenu(hWnd);
  782. g_RegEditData.fHaveNetwork = GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS;
  783. if (!g_RegEditData.fHaveNetwork) {
  784. hPopupMenu = GetSubMenu(g_RegEditData.hMainMenu,
  785. IDM_REGEDIT_FILE_POPUP);
  786. DeleteMenu(hPopupMenu, ID_CONNECT, MF_BYCOMMAND);
  787. DeleteMenu(hPopupMenu, ID_DISCONNECT, MF_BYCOMMAND);
  788. DeleteMenu(hPopupMenu, ID_NETSEPARATOR, MF_BYCOMMAND);
  789. }
  790. g_RegEditData.hMyComputer = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
  791. //
  792. // Send the tree-view control to the last location, if one is set.
  793. //
  794. if (RegOpenKey(HKEY_CURRENT_USER, g_RegEditAppletKey, &hKey) ==
  795. ERROR_SUCCESS)
  796. {
  797. cbValueData = MAXKEYNAMEPATH * 2;
  798. if (RegEdit_QueryValueEx(hKey, (LPTSTR) g_RegEditLastKeyValue, NULL, &Type,
  799. (LPBYTE) lpKeyName, &cbValueData) == ERROR_SUCCESS &&
  800. Type == REG_SZ && cbValueData > 0)
  801. {
  802. RegEdit_ExpandKeyPath(lpKeyName);
  803. }
  804. cbValueData = sizeof(dwValue);
  805. if ((RegEdit_QueryValueEx(hKey, (LPTSTR) g_RegEditMultiStringsValue, NULL, &Type,
  806. (LPBYTE) &dwValue, &cbValueData) == ERROR_SUCCESS) &&
  807. (Type == REG_DWORD) && (cbValueData > 0) && (dwValue != 0))
  808. {
  809. g_fMultiLineStrings = TRUE;
  810. }
  811. RegCloseKey(hKey);
  812. }
  813. return TRUE;
  814. }
  815. /*******************************************************************************
  816. *
  817. * RegEdit_OnDestroy
  818. *
  819. * DESCRIPTION:
  820. *
  821. * PARAMETERS:
  822. * hWnd, handle of RegEdit window.
  823. *
  824. *******************************************************************************/
  825. VOID
  826. PASCAL
  827. RegEdit_OnDestroy(
  828. HWND hWnd
  829. )
  830. {
  831. REGEDITVIEW RegEditView;
  832. HKEY hKey;
  833. HWND hValueListWnd;
  834. DWORD cbValueData;
  835. HWND hKeyTreeWnd;
  836. TCHAR KeyName[MAXKEYNAMEPATH * 2];
  837. LPTSTR lpKeyName = KeyName;
  838. //
  839. // Write out a new RegEditView record to the registry for our next
  840. // (hopeful?) activation.
  841. //
  842. if (RegCreateKey(HKEY_CURRENT_USER, g_RegEditAppletKey, &hKey) ==
  843. ERROR_SUCCESS) {
  844. RegEditView.WindowPlacement.length = sizeof(WINDOWPLACEMENT);
  845. GetWindowPlacement(hWnd, &RegEditView.WindowPlacement);
  846. RegEditView.xPaneSplit = g_RegEditData.xPaneSplit;
  847. hValueListWnd = g_RegEditData.hValueListWnd;
  848. RegEditView.cxNameColumn = ListView_GetColumnWidth(hValueListWnd, 0);
  849. RegEditView.cxTypeColumn = ListView_GetColumnWidth(hValueListWnd, 1);
  850. RegEditView.cxDataColumn = ListView_GetColumnWidth(hValueListWnd, 2);
  851. RegEditView.Flags = (g_RegEditData.StatusBarShowCommand == SW_HIDE) ?
  852. 0 : REV_STATUSBARVISIBLE;
  853. cbValueData = sizeof(REGEDITVIEW);
  854. RegSetValueEx(hKey, g_RegEditViewValue, 0, REG_BINARY,
  855. (LPBYTE) &RegEditView, cbValueData);
  856. cbValueData = sizeof(DWORD);
  857. RegSetValueEx(hKey, g_RegEditFindFlagsValue, 0, REG_DWORD,
  858. (LPBYTE) &g_FindFlags, cbValueData);
  859. //
  860. // Save the key before RegEdit closes so we can start there next time!
  861. //
  862. hKeyTreeWnd = g_RegEditData.hKeyTreeWnd;
  863. KeyTree_BuildKeyPath(hKeyTreeWnd, TreeView_GetSelection(hKeyTreeWnd), lpKeyName, BKP_TOCOMPUTER);
  864. cbValueData = (lstrlen(lpKeyName) + 1) * sizeof (TCHAR);
  865. RegSetValueEx(hKey, g_RegEditLastKeyValue, 0, REG_SZ, (LPBYTE) lpKeyName, cbValueData);
  866. RegCloseKey(hKey);
  867. }
  868. TreeView_SelectItem(g_RegEditData.hKeyTreeWnd, NULL);
  869. if (g_RegEditData.hCurrentSelectionKey != NULL)
  870. RegCloseKey(g_RegEditData.hCurrentSelectionKey);
  871. if (g_RegEditData.hImageList != NULL)
  872. ImageList_Destroy(g_RegEditData.hImageList);
  873. PostQuitMessage(0);
  874. }
  875. /*******************************************************************************
  876. *
  877. * RegAddFavoriteDlgProc
  878. *
  879. * DESCRIPTION:
  880. *
  881. * PARAMETERS:
  882. *
  883. *******************************************************************************/
  884. INT_PTR
  885. PASCAL
  886. RegAddFavoriteDlgProc(
  887. HWND hWnd,
  888. UINT Message,
  889. WPARAM wParam,
  890. LPARAM lParam
  891. )
  892. {
  893. static LPTSTR lpFavoriteName;
  894. switch (Message) {
  895. case WM_INITDIALOG:
  896. lpFavoriteName = (LPTSTR) lParam;
  897. SendDlgItemMessage(hWnd, IDC_FAVORITENAME, EM_SETLIMITTEXT,
  898. MAXKEYNAMEPATH, 0);
  899. SetWindowText(GetDlgItem(hWnd, IDC_FAVORITENAME), (LPTSTR) lParam);
  900. break;
  901. case WM_COMMAND:
  902. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  903. case IDC_FAVORITENAME:
  904. if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
  905. EnableWindow(GetDlgItem(hWnd, IDOK),
  906. SendMessage(GET_WM_COMMAND_HWND(wParam, lParam),
  907. WM_GETTEXTLENGTH, 0, 0) != 0);
  908. break;
  909. case IDOK:
  910. GetDlgItemText(hWnd, IDC_FAVORITENAME, lpFavoriteName,
  911. MAXKEYNAMEPATH);
  912. // FALL THROUGH
  913. case IDCANCEL:
  914. EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
  915. break;
  916. }
  917. break;
  918. default:
  919. return FALSE;
  920. }
  921. return TRUE;
  922. }
  923. /*******************************************************************************
  924. *
  925. * RegEdit_OnAddToFavorites
  926. *
  927. * DESCRIPTION:
  928. * Handles the selection of Favorites
  929. *
  930. * PARAMETERS:
  931. * hWnd, handle of RegEdit window.
  932. *
  933. *******************************************************************************/
  934. VOID
  935. PASCAL
  936. RegEdit_OnAddToFavorites(
  937. HWND hWnd
  938. )
  939. {
  940. TCHAR KeyName[MAXKEYNAMEPATH*2];
  941. LPTSTR lpKeyName = KeyName;
  942. TCHAR FavoriteName[MAXKEYNAMEPATH*2];
  943. LPTSTR lpFavoriteName = FavoriteName;
  944. LPTSTR lpCurrent, lpOriginal;
  945. DWORD cbValueData, dwType;
  946. LONG lRet;
  947. HKEY hKey;
  948. if (RegCreateKey(HKEY_CURRENT_USER, g_RegEditFavoritesKey, &hKey) ==
  949. ERROR_SUCCESS)
  950. {
  951. KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd, TreeView_GetSelection(g_RegEditData.hKeyTreeWnd),
  952. lpKeyName, BKP_TOCOMPUTER);
  953. lpOriginal = lpCurrent = lpKeyName;
  954. while (lpCurrent)
  955. {
  956. lpCurrent = (LPTSTR) _tcsrchr(lpOriginal, TEXT('\\'));
  957. if (lpCurrent)
  958. {
  959. lpCurrent++;
  960. lpOriginal = lpCurrent;
  961. }
  962. }
  963. while (TRUE)
  964. {
  965. lstrcpy(lpFavoriteName, lpOriginal);
  966. if (DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_ADDFAVORITE), hWnd,
  967. RegAddFavoriteDlgProc, (LPARAM) lpFavoriteName) != IDOK)
  968. {
  969. RegCloseKey(hKey);
  970. return;
  971. }
  972. if (*lpFavoriteName)
  973. {
  974. lRet = RegEdit_QueryValueEx(hKey, lpFavoriteName, NULL, &dwType, NULL, NULL);
  975. if (lRet)
  976. break;
  977. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(IDS_FAVORITEEXISTS),
  978. MAKEINTRESOURCE(IDS_FAVORITEERROR), MB_ICONERROR | MB_OK);
  979. }
  980. }
  981. cbValueData = (lstrlen(lpKeyName) + 1) * sizeof(TCHAR);
  982. RegSetValueEx(hKey, lpFavoriteName, 0, REG_SZ, (LPBYTE) lpKeyName, cbValueData);
  983. RegCloseKey(hKey);
  984. }
  985. }
  986. /*******************************************************************************
  987. *
  988. * RegRemoveFavoriteDlgProc
  989. *
  990. * DESCRIPTION:
  991. *
  992. * PARAMETERS:
  993. *
  994. *******************************************************************************/
  995. INT_PTR
  996. PASCAL
  997. RegRemoveFavoriteDlgProc(
  998. HWND hWnd,
  999. UINT Message,
  1000. WPARAM wParam,
  1001. LPARAM lParam
  1002. )
  1003. {
  1004. TCHAR KeyName[MAXKEYNAMEPATH*2];
  1005. LPTSTR lpKeyName = KeyName;
  1006. TCHAR ValueName[MAXKEYNAMEPATH*2];
  1007. LPTSTR lpValueName = ValueName;
  1008. DWORD cbValueName, dwType;
  1009. HWND hListBox;
  1010. HKEY hKey = NULL;
  1011. LONG lRet;
  1012. int i = 0;
  1013. switch (Message) {
  1014. case WM_INITDIALOG:
  1015. if (RegCreateKey(HKEY_CURRENT_USER, g_RegEditFavoritesKey, &hKey) ==
  1016. ERROR_SUCCESS)
  1017. {
  1018. while (TRUE)
  1019. {
  1020. cbValueName = MAXKEYNAMEPATH * 2;
  1021. lRet = RegEnumValue(hKey, i++, lpValueName, &cbValueName, NULL, &dwType, NULL, NULL);
  1022. if (lRet)
  1023. break;
  1024. ListBox_AddString(GetDlgItem(hWnd, IDC_FAVORITES), lpValueName);
  1025. }
  1026. RegCloseKey(hKey);
  1027. }
  1028. break;
  1029. case WM_COMMAND:
  1030. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  1031. case IDOK:
  1032. hListBox = GetDlgItem(hWnd, IDC_FAVORITES);
  1033. if (ListBox_GetSelCount(hListBox) > 0)
  1034. {
  1035. if (RegCreateKey(HKEY_CURRENT_USER, g_RegEditFavoritesKey, &hKey) ==
  1036. ERROR_SUCCESS)
  1037. {
  1038. for(i=0;i<ListBox_GetCount(hListBox);i++)
  1039. {
  1040. if (ListBox_GetSel(hListBox, i) != 0)
  1041. {
  1042. ListBox_GetText(hListBox, i, lpValueName);
  1043. RegDeleteValue(hKey, lpValueName);
  1044. }
  1045. }
  1046. }
  1047. }
  1048. // Fall through
  1049. case IDCANCEL:
  1050. EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
  1051. break;
  1052. }
  1053. break;
  1054. default:
  1055. return FALSE;
  1056. }
  1057. return TRUE;
  1058. }
  1059. /*******************************************************************************
  1060. *
  1061. * RegEdit_OnRemoveFavorite
  1062. *
  1063. * DESCRIPTION:
  1064. * Handles the removal of Favorites
  1065. *
  1066. * PARAMETERS:
  1067. * hWnd, handle of RegEdit window.
  1068. *
  1069. *******************************************************************************/
  1070. VOID
  1071. PASCAL
  1072. RegEdit_OnRemoveFavorite(
  1073. HWND hWnd
  1074. )
  1075. {
  1076. DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_REMFAVORITE), hWnd,
  1077. RegRemoveFavoriteDlgProc, (LPARAM) NULL);
  1078. }
  1079. /*******************************************************************************
  1080. *
  1081. * RegEdit_OnSelectFavorite
  1082. *
  1083. * DESCRIPTION:
  1084. * Handles the selection of Favorites
  1085. *
  1086. * PARAMETERS:
  1087. * hWnd, handle of RegEdit window.
  1088. * DlgItem, the favorite index
  1089. *
  1090. *******************************************************************************/
  1091. VOID
  1092. PASCAL
  1093. RegEdit_OnSelectFavorite(
  1094. HWND hWnd,
  1095. int DlgItem
  1096. )
  1097. {
  1098. TCHAR KeyName[MAXKEYNAMEPATH*2];
  1099. LPTSTR lpKeyName = KeyName;
  1100. TCHAR ValueName[MAXKEYNAMEPATH*2];
  1101. LPTSTR lpValueName = ValueName;
  1102. DWORD cbValueData, cbValueName, dwType;
  1103. HKEY hKey;
  1104. if (RegOpenKey(HKEY_CURRENT_USER, g_RegEditFavoritesKey, &hKey) ==
  1105. ERROR_SUCCESS)
  1106. {
  1107. cbValueData = MAXKEYNAMEPATH * 2;
  1108. cbValueName = MAXKEYNAMEPATH * 2;
  1109. if (RegEnumValue(hKey, DlgItem - ID_ADDTOFAVORITES - 1, lpValueName, &cbValueName, NULL,
  1110. &dwType, (LPBYTE) lpKeyName, &cbValueData) == ERROR_SUCCESS &&
  1111. dwType == REG_SZ && cbValueData > 0)
  1112. {
  1113. RegEdit_ExpandKeyPath(lpKeyName);
  1114. }
  1115. RegCloseKey(hKey);
  1116. }
  1117. }
  1118. /*******************************************************************************
  1119. *
  1120. * RegEdit_OnFavorites
  1121. *
  1122. * DESCRIPTION:
  1123. * Handles the selection of Favorites
  1124. *
  1125. * PARAMETERS:
  1126. * hWnd, handle of RegEdit window.
  1127. *
  1128. *******************************************************************************/
  1129. VOID
  1130. PASCAL
  1131. RegEdit_OnFavorites(
  1132. HWND hWnd,
  1133. UINT uItem
  1134. )
  1135. {
  1136. TCHAR KeyName[MAXKEYNAMEPATH*2];
  1137. LPTSTR lpKeyName = KeyName;
  1138. TCHAR ValueName[MAXKEYNAMEPATH*2];
  1139. LPTSTR lpValueName = ValueName;
  1140. TCHAR DataBuffer[MAXKEYNAMEPATH*2];
  1141. LPTSTR lpData = DataBuffer;
  1142. HMENU hMenu, hMainMenu;
  1143. MENUITEMINFO mii;
  1144. DWORD cbValueName, cbData, dwType;
  1145. BOOL bRet = TRUE;
  1146. HKEY hKey;
  1147. LONG lRet;
  1148. UINT i = 0;
  1149. // Get the main RegEdit Menu handle
  1150. hMainMenu = GetMenu(hWnd);
  1151. if (!hMainMenu)
  1152. {
  1153. return;
  1154. }
  1155. // Now get the handle to the Favorites submenu
  1156. hMenu = GetSubMenu(hMainMenu, uItem);
  1157. if (!hMenu)
  1158. {
  1159. return;
  1160. }
  1161. ZeroMemory(&mii, sizeof(MENUITEMINFO));
  1162. mii.cbSize = sizeof(MENUITEMINFO);
  1163. mii.fMask = MIIM_STATE;
  1164. mii.fState = MFS_DISABLED;
  1165. SetMenuItemInfo(hMenu, ID_REMOVEFAVORITE, FALSE, &mii);
  1166. // Now remove every menuitem after the separator so we have a clean slate.
  1167. i = 2;
  1168. while (bRet)
  1169. {
  1170. bRet = DeleteMenu(hMenu, i, MF_BYPOSITION);
  1171. }
  1172. if (RegCreateKey(HKEY_CURRENT_USER, g_RegEditFavoritesKey, &hKey) ==
  1173. ERROR_SUCCESS)
  1174. {
  1175. i = 0;
  1176. while (TRUE)
  1177. {
  1178. cbValueName = cbData = MAXKEYNAMEPATH * 2;
  1179. lRet = RegEnumValue(hKey, i, lpValueName, &cbValueName, NULL, &dwType, (LPBYTE) lpData, &cbData);
  1180. if (lRet)
  1181. break;
  1182. if (!i)
  1183. {
  1184. // Enable the "Remove Favorites" menu
  1185. ZeroMemory(&mii, sizeof(MENUITEMINFO));
  1186. mii.cbSize = sizeof(MENUITEMINFO);
  1187. mii.fMask = MIIM_STATE;
  1188. mii.fState = MFS_ENABLED;
  1189. SetMenuItemInfo(hMenu, ID_REMOVEFAVORITE, FALSE, &mii);
  1190. // Add a separator to make things pretty
  1191. ZeroMemory(&mii, sizeof(MENUITEMINFO));
  1192. mii.cbSize = sizeof(MENUITEMINFO);
  1193. mii.fMask = MIIM_TYPE;
  1194. mii.fType = MFT_SEPARATOR;
  1195. InsertMenuItem(hMenu, (UINT) -1, 2, &mii);
  1196. }
  1197. ZeroMemory(&mii, sizeof(MENUITEMINFO));
  1198. mii.cbSize = sizeof(MENUITEMINFO);
  1199. mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
  1200. mii.fType = MFT_STRING;
  1201. mii.wID = ID_ADDTOFAVORITES + i + 1;
  1202. mii.dwTypeData = lpValueName;
  1203. mii.fState = MFS_ENABLED;
  1204. mii.cch = lstrlen(lpValueName);
  1205. InsertMenuItem(hMenu, ID_ADDTOFAVORITES + i + 1, FALSE, &mii);
  1206. i++;
  1207. }
  1208. RegCloseKey(hKey);
  1209. }
  1210. DrawMenuBar(hWnd);
  1211. }
  1212. /*******************************************************************************
  1213. *
  1214. * RegEdit_OnCommand
  1215. *
  1216. * DESCRIPTION:
  1217. * Handles the selection of a menu item by the user, notification messages
  1218. * from a child control, or translated accelerated keystrokes for the
  1219. * RegEdit window.
  1220. *
  1221. * PARAMETERS:
  1222. * hWnd, handle of RegEdit window.
  1223. * DlgItem, identifier of control.
  1224. * hControlWnd, handle of control.
  1225. * NotificationCode, notification code from control.
  1226. *
  1227. *******************************************************************************/
  1228. VOID
  1229. PASCAL
  1230. RegEdit_OnCommand(
  1231. HWND hWnd,
  1232. int DlgItem,
  1233. HWND hControlWnd,
  1234. UINT NotificationCode
  1235. )
  1236. {
  1237. PTSTR pAppName;
  1238. //
  1239. // Check to see if this menu command should be handled by the main window's
  1240. // command handler.
  1241. //
  1242. if (DlgItem >= ID_FIRSTCONTEXTMENUITEM && DlgItem <=
  1243. ID_LASTCONTEXTMENUITEM) {
  1244. if (g_RegEditData.hFocusWnd == g_RegEditData.hKeyTreeWnd)
  1245. RegEdit_OnKeyTreeCommand(hWnd, DlgItem, NULL);
  1246. else
  1247. RegEdit_OnValueListCommand(hWnd, DlgItem);
  1248. }
  1249. switch (DlgItem) {
  1250. case ID_IMPORTREGFILE:
  1251. RegEdit_OnCommandImportRegFile(hWnd);
  1252. break;
  1253. case ID_EXPORTREGFILE:
  1254. RegEdit_OnCommandExportRegFile(hWnd);
  1255. break;
  1256. case ID_LOADHIVE:
  1257. RegEdit_OnCommandLoadHive(hWnd);
  1258. break;
  1259. case ID_UNLOADHIVE:
  1260. RegEdit_OnCommandUnloadHive(hWnd);
  1261. break;
  1262. case ID_CONNECT:
  1263. RegEdit_OnCommandConnect(hWnd);
  1264. break;
  1265. case ID_DISCONNECT:
  1266. RegEdit_OnCommandDisconnect(hWnd);
  1267. break;
  1268. case ID_PRINT:
  1269. RegEdit_OnCommandPrint(hWnd);
  1270. break;
  1271. case ID_EXIT:
  1272. PostMessage(hWnd, WM_CLOSE, 0, 0);
  1273. break;
  1274. case ID_FIND:
  1275. RegEdit_OnCommandFindNext(hWnd, TRUE);
  1276. break;
  1277. case ID_FINDNEXT:
  1278. RegEdit_OnCommandFindNext(hWnd, FALSE);
  1279. break;
  1280. case ID_NEWKEY:
  1281. RegEdit_OnNewKey(hWnd,
  1282. TreeView_GetSelection(g_RegEditData.hKeyTreeWnd));
  1283. break;
  1284. case ID_NEWSTRINGVALUE:
  1285. RegEdit_OnNewValue(hWnd, REG_SZ);
  1286. break;
  1287. case ID_NEWBINARYVALUE:
  1288. RegEdit_OnNewValue(hWnd, REG_BINARY);
  1289. break;
  1290. case ID_NEWDWORDVALUE:
  1291. RegEdit_OnNewValue(hWnd, REG_DWORD);
  1292. break;
  1293. case ID_NEWMULTSZVALUE:
  1294. RegEdit_OnNewValue(hWnd, REG_MULTI_SZ);
  1295. break;
  1296. case ID_NEWEXPSZVALUE:
  1297. RegEdit_OnNewValue(hWnd, REG_EXPAND_SZ);
  1298. break;
  1299. //
  1300. // Show or hide the status bar. In either case, we'll need to resize
  1301. // the KeyTree and ValueList panes.
  1302. //
  1303. case ID_STATUSBAR:
  1304. g_RegEditData.StatusBarShowCommand =
  1305. (g_RegEditData.StatusBarShowCommand == SW_HIDE) ? SW_SHOW :
  1306. SW_HIDE;
  1307. ShowWindow(g_RegEditData.hStatusBarWnd,
  1308. g_RegEditData.StatusBarShowCommand);
  1309. RegEdit_ResizeWindow(hWnd, RESIZEFROM_UNKNOWN);
  1310. break;
  1311. case ID_SPLIT:
  1312. RegEdit_OnCommandSplit(hWnd);
  1313. break;
  1314. case ID_DISPLAYBINARY:
  1315. RegEdit_DisplayBinaryData(hWnd);
  1316. break;
  1317. case ID_REFRESH:
  1318. RegEdit_OnKeyTreeRefresh(hWnd);
  1319. break;
  1320. case ID_ABOUT:
  1321. pAppName = LoadDynamicString(IDS_REGEDIT);
  1322. ShellAbout(hWnd, pAppName, g_NullString, LoadIcon(g_hInstance,
  1323. MAKEINTRESOURCE(IDI_REGEDIT)));
  1324. DeleteDynamicString(pAppName);
  1325. break;
  1326. //
  1327. // Cycle the focus to the next pane when the user presses "tab". The
  1328. // assumption is made that there are only two panes, so the tab
  1329. // direction doesn't really matter.
  1330. //
  1331. case ID_CYCLEFOCUS:
  1332. SetFocus(((g_RegEditData.hFocusWnd == g_RegEditData.hKeyTreeWnd) ?
  1333. g_RegEditData.hValueListWnd : g_RegEditData.hKeyTreeWnd));
  1334. break;
  1335. case ID_HELPTOPICS:
  1336. HtmlHelp( GetDesktopWindow(), TEXT("regedit.chm"), HH_HELP_FINDER, 0);
  1337. break;
  1338. case ID_COPYKEYNAME:
  1339. RegEdit_OnCopyKeyName(hWnd,
  1340. TreeView_GetSelection(g_RegEditData.hKeyTreeWnd));
  1341. break;
  1342. case ID_REMOVEFAVORITE:
  1343. RegEdit_OnRemoveFavorite(hWnd);
  1344. break;
  1345. case ID_ADDTOFAVORITES:
  1346. RegEdit_OnAddToFavorites(hWnd);
  1347. break;
  1348. case ID_PERMISSIONS:
  1349. RegEdit_InvokeSecurityEditor(hWnd);
  1350. break;
  1351. default:
  1352. if (DlgItem > ID_ADDTOFAVORITES)
  1353. {
  1354. RegEdit_OnSelectFavorite(hWnd, DlgItem);
  1355. break;
  1356. }
  1357. }
  1358. UNREFERENCED_PARAMETER(hControlWnd);
  1359. }
  1360. /*******************************************************************************
  1361. *
  1362. * RegEdit_OnNotify
  1363. *
  1364. * DESCRIPTION:
  1365. *
  1366. * PARAMETERS:
  1367. * hWnd, handle of RegEdit window.
  1368. * DlgItem, identifier of control.
  1369. * lpNMTreeView, control notification data.
  1370. *
  1371. *******************************************************************************/
  1372. LRESULT
  1373. PASCAL
  1374. RegEdit_OnNotify(
  1375. HWND hWnd,
  1376. int DlgItem,
  1377. LPNMHDR lpNMHdr
  1378. )
  1379. {
  1380. switch (DlgItem) {
  1381. case IDC_KEYTREE:
  1382. switch (lpNMHdr-> code) {
  1383. case TVN_ITEMEXPANDING:
  1384. return RegEdit_OnKeyTreeItemExpanding(hWnd,
  1385. (LPNM_TREEVIEW) lpNMHdr);
  1386. case TVN_SELCHANGED:
  1387. RegEdit_OnKeyTreeSelChanged(hWnd, (LPNM_TREEVIEW) lpNMHdr);
  1388. break;
  1389. case TVN_BEGINLABELEDIT:
  1390. return RegEdit_OnKeyTreeBeginLabelEdit(hWnd,
  1391. (TV_DISPINFO FAR*) lpNMHdr);
  1392. case TVN_ENDLABELEDIT:
  1393. return RegEdit_OnKeyTreeEndLabelEdit(hWnd,
  1394. (TV_DISPINFO FAR*) lpNMHdr);
  1395. case NM_SETFOCUS:
  1396. g_RegEditData.hFocusWnd = g_RegEditData.hKeyTreeWnd;
  1397. break;
  1398. }
  1399. break;
  1400. case IDC_VALUELIST:
  1401. switch (lpNMHdr-> code) {
  1402. case LVN_BEGINLABELEDIT:
  1403. return RegEdit_OnValueListBeginLabelEdit(hWnd,
  1404. (LV_DISPINFO FAR*) lpNMHdr);
  1405. case LVN_ENDLABELEDIT:
  1406. return RegEdit_OnValueListEndLabelEdit(hWnd,
  1407. (LV_DISPINFO FAR*) lpNMHdr);
  1408. case NM_RETURN:
  1409. case NM_DBLCLK:
  1410. RegEdit_OnValueListModify(hWnd, FALSE);
  1411. break;
  1412. case NM_SETFOCUS:
  1413. g_RegEditData.hFocusWnd = g_RegEditData.hValueListWnd;
  1414. break;
  1415. }
  1416. break;
  1417. }
  1418. return 0;
  1419. }
  1420. /*******************************************************************************
  1421. *
  1422. * RegEdit_OnInitMenuPopup
  1423. *
  1424. * DESCRIPTION:
  1425. *
  1426. * PARAMETERS:
  1427. * hWnd, handle of RegEdit window.
  1428. *
  1429. *******************************************************************************/
  1430. VOID
  1431. PASCAL
  1432. RegEdit_OnInitMenuPopup(
  1433. HWND hWnd,
  1434. HMENU hPopupMenu,
  1435. UINT MenuPosition,
  1436. BOOL fSystemMenu
  1437. )
  1438. {
  1439. UINT uEnableFlags;
  1440. int NewPopupPosition;
  1441. HTREEITEM hSelectedTreeItem;
  1442. HTREEITEM hComputerItem;
  1443. HWND hKeyTreeWnd = g_RegEditData.hKeyTreeWnd;
  1444. //
  1445. // We don't care about the items in the system menu or any of the context
  1446. // menus. All of the context menus should have been initialized already.
  1447. //
  1448. if (fSystemMenu || !g_RegEditData.fMainMenuInited)
  1449. return;
  1450. switch (MenuPosition)
  1451. {
  1452. case IDM_REGEDIT_FILE_POPUP:
  1453. {
  1454. Regedit_EnableHiveMenuItems(hPopupMenu);
  1455. if (g_RegEditData.fHaveNetwork)
  1456. {
  1457. // Enable or disable the "disconnect..." item depending on
  1458. // whether or not we have any open connections.
  1459. uEnableFlags = (TreeView_GetNextSibling(hKeyTreeWnd,
  1460. TreeView_GetRoot(hKeyTreeWnd)) != NULL) ? MF_BYCOMMAND |
  1461. MF_ENABLED : MF_BYCOMMAND | MF_GRAYED;
  1462. EnableMenuItem(hPopupMenu, ID_DISCONNECT, uEnableFlags);
  1463. }
  1464. }
  1465. break;
  1466. case IDM_REGEDIT_EDIT_POPUP:
  1467. // Cannot show permissions for "My Computer"
  1468. hSelectedTreeItem = TreeView_GetSelection(hKeyTreeWnd);
  1469. EnableMenuItem(hPopupMenu, ID_PERMISSIONS,
  1470. (TreeView_GetParent(hKeyTreeWnd, hSelectedTreeItem) != NULL) ?
  1471. (MF_BYCOMMAND | MF_ENABLED) : (MF_BYCOMMAND | MF_GRAYED));
  1472. if (g_RegEditData.hFocusWnd == hKeyTreeWnd)
  1473. {
  1474. //
  1475. // Don't show items that are specific only to the ValueList
  1476. // context.
  1477. //
  1478. if (GetMenuItemID(hPopupMenu, 0) == ID_MODIFY)
  1479. {
  1480. DeleteMenu(hPopupMenu, 0, MF_BYPOSITION);
  1481. DeleteMenu(hPopupMenu, 0, MF_BYPOSITION);
  1482. DeleteMenu(hPopupMenu, 0, MF_BYPOSITION);
  1483. }
  1484. RegEdit_SetKeyTreeEditMenuItems(hPopupMenu, hSelectedTreeItem);
  1485. //
  1486. // Disable "Copy Key Name" for top-level items such as
  1487. // "My Computer" or a remote registry connection.
  1488. //
  1489. EnableMenuItem(hPopupMenu, ID_COPYKEYNAME,
  1490. (TreeView_GetParent(hKeyTreeWnd,
  1491. hSelectedTreeItem) != NULL) ? (MF_BYCOMMAND | MF_ENABLED) :
  1492. (MF_BYCOMMAND | MF_GRAYED));
  1493. NewPopupPosition = IDM_EDIT_WHENKEY_NEW_POPUP;
  1494. }
  1495. else
  1496. {
  1497. //
  1498. // Show menu items that are specific only to the ValueList
  1499. // context.
  1500. //
  1501. if (GetMenuItemID(hPopupMenu, 0) != ID_MODIFY)
  1502. {
  1503. InsertMenu(hPopupMenu, 0, MF_BYPOSITION | MF_SEPARATOR, 0,
  1504. NULL);
  1505. InsertMenu(hPopupMenu, 0, MF_BYPOSITION | MF_STRING,
  1506. ID_MODIFYBINARY, g_RegEditData.pModifyBinary);
  1507. InsertMenu(hPopupMenu, 0, MF_BYPOSITION | MF_STRING,
  1508. ID_MODIFY, g_RegEditData.pModify);
  1509. SetMenuDefaultItem(hPopupMenu, 0, MF_BYPOSITION);
  1510. }
  1511. RegEdit_SetValueListEditMenuItems(hPopupMenu,
  1512. ListView_GetNextItem(g_RegEditData.hValueListWnd, -1,
  1513. LVNI_SELECTED));
  1514. NewPopupPosition = IDM_EDIT_WHENVALUE_NEW_POPUP;
  1515. }
  1516. RegEdit_SetNewObjectEditMenuItems(GetSubMenu(hPopupMenu,
  1517. NewPopupPosition));
  1518. break;
  1519. case IDM_REGEDIT_VIEW_POPUP:
  1520. CheckMenuItem(hPopupMenu, ID_STATUSBAR, MF_BYCOMMAND |
  1521. ((g_RegEditData.StatusBarShowCommand == SW_HIDE) ?
  1522. MF_UNCHECKED : MF_CHECKED));
  1523. EnableMenuItem(hPopupMenu, ID_DISPLAYBINARY, MF_BYCOMMAND |
  1524. ((g_RegEditData.hFocusWnd == g_RegEditData.hKeyTreeWnd) ?
  1525. MF_GRAYED : MF_ENABLED));
  1526. break;
  1527. case IDM_REGEDIT_FAVS_POPUP:
  1528. //Only allow "add to favorites" when the selected key is a child
  1529. //of the root key for my computer. (don't allow favs on remote)
  1530. hSelectedTreeItem =
  1531. TreeView_GetSelection(hKeyTreeWnd);
  1532. hComputerItem = RegEdit_GetComputerItem(hSelectedTreeItem);
  1533. EnableMenuItem(hPopupMenu, ID_ADDTOFAVORITES,
  1534. ((hComputerItem == TreeView_GetRoot(hKeyTreeWnd)) &&
  1535. (hSelectedTreeItem != TreeView_GetRoot(hKeyTreeWnd))) ?
  1536. (MF_BYCOMMAND | MF_ENABLED) :
  1537. (MF_BYCOMMAND | MF_GRAYED));
  1538. break;
  1539. }
  1540. }
  1541. //------------------------------------------------------------------------------
  1542. // Regedit_EnableHiveMenuItems
  1543. //
  1544. // DESSCRIPTION: Enables hive menu items
  1545. //
  1546. // PARAMETERS: HMENU hPopupMenu - handle to popup menu
  1547. //------------------------------------------------------------------------------
  1548. void Regedit_EnableHiveMenuItems(HMENU hPopupMenu)
  1549. {
  1550. UINT uLoadFlags = MF_BYCOMMAND | MF_GRAYED;
  1551. UINT uUnloadFlags = MF_BYCOMMAND | MF_GRAYED;
  1552. HWND hKeyTreeWnd = g_RegEditData.hKeyTreeWnd;
  1553. if (g_RegEditData.hFocusWnd == hKeyTreeWnd)
  1554. {
  1555. PREDEFINE_KEY hkeyPredefindedKey;
  1556. HTREEITEM hSelectedTreeItem;
  1557. HTREEITEM hComputerItem;
  1558. // get the key's predefined root key
  1559. hSelectedTreeItem = TreeView_GetSelection(hKeyTreeWnd);
  1560. hkeyPredefindedKey = RegEdit_GetPredefinedKey(hSelectedTreeItem);
  1561. if ((PREDEFINE_KEY_LOCAL_MACHINE == hkeyPredefindedKey) ||
  1562. (PREDEFINE_KEY_USERS == hkeyPredefindedKey))
  1563. {
  1564. HTREEITEM hParentTreeItem =
  1565. TreeView_GetParent(hKeyTreeWnd, hSelectedTreeItem);
  1566. HTREEITEM hComputerItem
  1567. = RegEdit_GetComputerItem(hSelectedTreeItem); //the computer
  1568. if (hParentTreeItem == hComputerItem)
  1569. {
  1570. // Enable Load Hive for root keys
  1571. uLoadFlags = MF_BYCOMMAND | MF_ENABLED;
  1572. }
  1573. else if (hParentTreeItem &&
  1574. (TreeView_GetParent(hKeyTreeWnd, hParentTreeItem) ==
  1575. hComputerItem))
  1576. {
  1577. // Enable Unload Hive for children of root keys
  1578. uUnloadFlags = MF_BYCOMMAND | MF_ENABLED;
  1579. }
  1580. }
  1581. }
  1582. EnableMenuItem(hPopupMenu, ID_LOADHIVE, uLoadFlags);
  1583. EnableMenuItem(hPopupMenu, ID_UNLOADHIVE, uUnloadFlags);
  1584. }
  1585. /*******************************************************************************
  1586. *
  1587. * RegEdit_SetNewObjectEditMenuItems
  1588. *
  1589. * DESCRIPTION:
  1590. *
  1591. * PARAMETERS:
  1592. * hPopupMenu,
  1593. *
  1594. *******************************************************************************/
  1595. VOID
  1596. PASCAL
  1597. RegEdit_SetNewObjectEditMenuItems(
  1598. HMENU hPopupMenu
  1599. )
  1600. {
  1601. HWND hKeyTreeWnd;
  1602. HTREEITEM hSelectedTreeItem;
  1603. UINT EnableFlags;
  1604. hKeyTreeWnd = g_RegEditData.hKeyTreeWnd;
  1605. hSelectedTreeItem = TreeView_GetSelection(hKeyTreeWnd);
  1606. if (g_RegEditData.hCurrentSelectionKey != NULL)
  1607. EnableFlags = MF_ENABLED | MF_BYCOMMAND;
  1608. else
  1609. EnableFlags = MF_GRAYED | MF_BYCOMMAND;
  1610. EnableMenuItem(hPopupMenu, ID_NEWKEY, EnableFlags);
  1611. EnableMenuItem(hPopupMenu, ID_NEWSTRINGVALUE, EnableFlags);
  1612. EnableMenuItem(hPopupMenu, ID_NEWBINARYVALUE, EnableFlags);
  1613. EnableMenuItem(hPopupMenu, ID_NEWDWORDVALUE, EnableFlags);
  1614. EnableMenuItem(hPopupMenu, ID_NEWMULTSZVALUE, EnableFlags);
  1615. EnableMenuItem(hPopupMenu, ID_NEWEXPSZVALUE, EnableFlags);
  1616. }
  1617. /*******************************************************************************
  1618. *
  1619. * RegEdit_OnMenuSelect
  1620. *
  1621. * DESCRIPTION:
  1622. *
  1623. * PARAMETERS:
  1624. * hWnd, handle of RegEdit window.
  1625. *
  1626. *******************************************************************************/
  1627. VOID
  1628. PASCAL
  1629. RegEdit_OnMenuSelect(
  1630. HWND hWnd,
  1631. WPARAM wParam,
  1632. LPARAM lParam
  1633. )
  1634. {
  1635. MENUITEMINFO MenuItemInfo;
  1636. //
  1637. // If this is one of our popup menus, then we'll fake out the MenuHelp
  1638. // API by sending it a normal menu item id. This makes it easier to
  1639. // display context sensitive help for the popups, too.
  1640. //
  1641. if ((GET_WM_MENUSELECT_FLAGS(wParam, lParam) & (MF_POPUP | MF_SYSMENU)) ==
  1642. MF_POPUP && GET_WM_MENUSELECT_HMENU(wParam, lParam) != NULL) {
  1643. ZeroMemory(&MenuItemInfo, sizeof(MENUITEMINFO));
  1644. MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
  1645. MenuItemInfo.fMask = MIIM_ID;
  1646. GetMenuItemInfo((HMENU) lParam, LOWORD(wParam), TRUE, &MenuItemInfo);
  1647. if (LOWORD(wParam) == 3)
  1648. {
  1649. RegEdit_OnFavorites(hWnd, LOWORD(wParam));
  1650. }
  1651. if (GetMenuItemInfo((HMENU) lParam, LOWORD(wParam), TRUE, &MenuItemInfo))
  1652. {
  1653. wParam = MenuItemInfo.wID;
  1654. }
  1655. }
  1656. MenuHelp(WM_MENUSELECT, wParam, lParam, g_RegEditData.hMainMenu,
  1657. g_hInstance, g_RegEditData.hStatusBarWnd, (UINT *)s_RegEditMenuHelpData);
  1658. }
  1659. /*******************************************************************************
  1660. *
  1661. * RegEdit_OnLButtonDown
  1662. *
  1663. * DESCRIPTION:
  1664. *
  1665. * PARAMETERS:
  1666. * hWnd, handle of RegEdit window.
  1667. * fDoubleClick, TRUE if this is a double-click message, else FALSE.
  1668. * x, x-coordinate of the cursor relative to the client area.
  1669. * y, y-coordinate of the cursor relative to the client area.
  1670. * KeyFlags, state of various virtual keys.
  1671. *
  1672. *******************************************************************************/
  1673. VOID
  1674. PASCAL
  1675. RegEdit_OnLButtonDown(
  1676. HWND hWnd,
  1677. BOOL fDoubleClick,
  1678. int x,
  1679. int y,
  1680. UINT KeyFlags
  1681. )
  1682. {
  1683. LONG Style;
  1684. RECT ClientRect;
  1685. int cxIcon;
  1686. int dx;
  1687. int dy;
  1688. HDC hDC;
  1689. MSG Msg;
  1690. int xLow;
  1691. int xHigh;
  1692. HBRUSH hDitherBrush;
  1693. HBRUSH hPrevBrush;
  1694. if (IsIconic(hWnd))
  1695. return;
  1696. Style = GetWindowLong(hWnd, GWL_STYLE);
  1697. SetWindowLong(hWnd, GWL_STYLE, Style & (~WS_CLIPCHILDREN));
  1698. GetEffectiveClientRect(hWnd, &ClientRect, (LPINT)s_EffectiveClientRectData);
  1699. cxIcon = GetSystemMetrics(SM_CXICON);
  1700. ClientRect.left += cxIcon;
  1701. ClientRect.right -= cxIcon;
  1702. dx = GetSystemMetrics(SM_CXSIZEFRAME);
  1703. y = GetSystemMetrics(SM_CYEDGE);
  1704. dy = ClientRect.bottom - ClientRect.top - y * 2;
  1705. hDC = GetDC(hWnd);
  1706. if ((hDitherBrush = CreateDitheredBrush()) != NULL)
  1707. hPrevBrush = SelectBrush(hDC, hDitherBrush);
  1708. PatBlt(hDC, x - dx / 2, y, dx, dy, PATINVERT);
  1709. SetCapture(hWnd);
  1710. while (GetMessage(&Msg, NULL, 0, 0)) {
  1711. if (Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN ||
  1712. (Msg.message >= WM_MOUSEFIRST && Msg.message <= WM_MOUSELAST)) {
  1713. if (Msg.message == WM_LBUTTONUP || Msg.message == WM_LBUTTONDOWN ||
  1714. Msg.message == WM_RBUTTONDOWN)
  1715. break;
  1716. if (Msg.message == WM_KEYDOWN) {
  1717. if (Msg.wParam == VK_LEFT) {
  1718. Msg.message = WM_MOUSEMOVE;
  1719. Msg.pt.x -= 2;
  1720. }
  1721. else if (Msg.wParam == VK_RIGHT) {
  1722. Msg.message = WM_MOUSEMOVE;
  1723. Msg.pt.x += 2;
  1724. }
  1725. else if (Msg.wParam == VK_RETURN || Msg.wParam == VK_ESCAPE)
  1726. break;
  1727. if (Msg.pt.x > ClientRect.right)
  1728. Msg.pt.x = ClientRect.right;
  1729. else if (Msg.pt.x < ClientRect.left)
  1730. Msg.pt.x = ClientRect.left;
  1731. SetCursorPos(Msg.pt.x, Msg.pt.y);
  1732. }
  1733. if (Msg.message == WM_MOUSEMOVE) {
  1734. ScreenToClient(hWnd, &Msg.pt);
  1735. if (Msg.pt.x > ClientRect.right)
  1736. Msg.pt.x = ClientRect.right;
  1737. else if (Msg.pt.x < ClientRect.left)
  1738. Msg.pt.x = ClientRect.left;
  1739. if (x < Msg.pt.x) {
  1740. xLow = x;
  1741. xHigh = Msg.pt.x;
  1742. }
  1743. else {
  1744. xLow = Msg.pt.x;
  1745. xHigh = x;
  1746. }
  1747. xLow -= dx / 2;
  1748. xHigh -= dx / 2;
  1749. if (xHigh < xLow + dx)
  1750. ExcludeClipRect(hDC, xHigh, y, xLow + dx, y + dy);
  1751. else
  1752. ExcludeClipRect(hDC, xLow + dx, y, xHigh, y + dy);
  1753. PatBlt(hDC, xLow, y, xHigh - xLow + dx, dy, PATINVERT);
  1754. SelectClipRgn(hDC, NULL);
  1755. x = Msg.pt.x;
  1756. }
  1757. }
  1758. else
  1759. DispatchMessage(&Msg);
  1760. }
  1761. ReleaseCapture();
  1762. PatBlt(hDC, x - dx / 2, y, dx, dy, PATINVERT);
  1763. if (hDitherBrush != NULL)
  1764. DeleteObject(SelectBrush(hDC, hPrevBrush));
  1765. ReleaseDC(hWnd, hDC);
  1766. SetWindowLong(hWnd, GWL_STYLE, Style);
  1767. g_RegEditData.xPaneSplit = x - dx / 2;
  1768. RegEdit_ResizeWindow(hWnd, RESIZEFROM_SPLIT);
  1769. UNREFERENCED_PARAMETER(fDoubleClick);
  1770. UNREFERENCED_PARAMETER(KeyFlags);
  1771. }
  1772. /*******************************************************************************
  1773. *
  1774. * RegEdit_OnCommandSplit
  1775. *
  1776. * DESCRIPTION:
  1777. * Keyboard alternative to changing the position of the "split" between the
  1778. * KeyTree and ValueList panes.
  1779. *
  1780. * PARAMETERS:
  1781. * hWnd, handle of RegEdit window.
  1782. *
  1783. *******************************************************************************/
  1784. VOID
  1785. PASCAL
  1786. RegEdit_OnCommandSplit(
  1787. HWND hWnd
  1788. )
  1789. {
  1790. RECT ClientRect;
  1791. POINT MessagePos;
  1792. POINT CursorPos;
  1793. GetEffectiveClientRect(hWnd, &ClientRect, (LPINT)s_EffectiveClientRectData);
  1794. MessagePos.x = g_RegEditData.xPaneSplit +
  1795. GetSystemMetrics(SM_CXSIZEFRAME) / 2;
  1796. MessagePos.y = (ClientRect.bottom - ClientRect.top) / 2;
  1797. CursorPos = MessagePos;
  1798. ClientToScreen(hWnd, &CursorPos);
  1799. SetCursorPos(CursorPos.x, CursorPos.y);
  1800. SetCursor(LoadCursor(g_hInstance, MAKEINTRESOURCE(IDC_SPLIT)));
  1801. ShowCursor(TRUE);
  1802. RegEdit_OnLButtonDown(hWnd, FALSE, MessagePos.x, MessagePos.y, 0);
  1803. ShowCursor(FALSE);
  1804. }
  1805. /*******************************************************************************
  1806. *
  1807. * RegEdit_ResizeWindow
  1808. *
  1809. * DESCRIPTION:
  1810. * Called whenever the size of the RegEdit window has changed or the size
  1811. * of its child controls should be adjusted.
  1812. *
  1813. * PARAMETERS:
  1814. * hWnd, handle of RegEdit window.
  1815. * ResizeFrom, source of the size change (RESIZEFROM_* constant).
  1816. *
  1817. *******************************************************************************/
  1818. VOID
  1819. PASCAL
  1820. RegEdit_ResizeWindow(
  1821. HWND hWnd,
  1822. UINT ResizeFrom
  1823. )
  1824. {
  1825. HDWP hDWP;
  1826. RECT ClientRect;
  1827. int Height;
  1828. HWND hKeyTreeWnd;
  1829. HWND hValueListWnd;
  1830. int x;
  1831. int dx;
  1832. if (IsIconic(hWnd))
  1833. return;
  1834. //
  1835. // Resize and/or reposition the status bar window. Don't do this when the
  1836. // resize comes from a change in the splitter position to avoid some
  1837. // flicker.
  1838. //
  1839. if (ResizeFrom == RESIZEFROM_UNKNOWN)
  1840. SendMessage(g_RegEditData.hStatusBarWnd, WM_SIZE, 0, 0);
  1841. if ((hDWP = BeginDeferWindowPos(2)) != NULL) {
  1842. GetEffectiveClientRect(hWnd, &ClientRect, (LPINT)s_EffectiveClientRectData);
  1843. Height = ClientRect.bottom - ClientRect.top;
  1844. hKeyTreeWnd = g_RegEditData.hKeyTreeWnd;
  1845. DeferWindowPos(hDWP, hKeyTreeWnd, NULL, 0, 0, g_RegEditData.xPaneSplit,
  1846. Height, SWP_NOZORDER | SWP_NOACTIVATE);
  1847. x = g_RegEditData.xPaneSplit + GetSystemMetrics(SM_CXSIZEFRAME);
  1848. dx = ClientRect.right - ClientRect.left - x;
  1849. hValueListWnd = g_RegEditData.hValueListWnd;
  1850. DeferWindowPos(hDWP, hValueListWnd, NULL, x, 0, dx, Height,
  1851. SWP_NOZORDER | SWP_NOACTIVATE);
  1852. EndDeferWindowPos(hDWP);
  1853. }
  1854. }
  1855. /*******************************************************************************
  1856. *
  1857. * RegEdit_SetImageLists
  1858. *
  1859. * DESCRIPTION:
  1860. *
  1861. * PARAMETERS:
  1862. * (none).
  1863. *
  1864. *******************************************************************************/
  1865. BOOL
  1866. PASCAL
  1867. RegEdit_SetImageLists(
  1868. HWND hWnd
  1869. )
  1870. {
  1871. int cxSmIcon;
  1872. int cySmIcon;
  1873. HIMAGELIST hImageList;
  1874. UINT Index;
  1875. HICON hIcon;
  1876. UINT uFlags = TRUE;
  1877. cxSmIcon = GetSystemMetrics(SM_CXSMICON);
  1878. cySmIcon = GetSystemMetrics(SM_CYSMICON);
  1879. if ( GetWindowLongPtr(hWnd , GWL_EXSTYLE) & WS_EX_LAYOUTRTL )
  1880. {
  1881. uFlags |= ILC_MIRROR;
  1882. }
  1883. if ((hImageList = ImageList_Create(cxSmIcon, cySmIcon, uFlags, IDI_LASTIMAGE -
  1884. IDI_FIRSTIMAGE + 1, 1)) == NULL)
  1885. return FALSE;
  1886. //
  1887. // Initialize the image list with all of the icons that we'll be using
  1888. // throughout the Registry Editor (at least this window!). Once set, send
  1889. // its handle to all interested child windows.
  1890. //
  1891. for (Index = IDI_FIRSTIMAGE; Index <= IDI_LASTIMAGE; Index++) {
  1892. if ((hIcon = LoadImage(g_hInstance, MAKEINTRESOURCE(Index), IMAGE_ICON,
  1893. cxSmIcon, cySmIcon, LR_DEFAULTCOLOR)) != NULL) {
  1894. ImageList_AddIcon(hImageList, hIcon);
  1895. DestroyIcon(hIcon);
  1896. }
  1897. else {
  1898. ImageList_Destroy(hImageList);
  1899. return FALSE;
  1900. }
  1901. }
  1902. TreeView_SetImageList(g_RegEditData.hKeyTreeWnd, hImageList, TVSIL_NORMAL);
  1903. ListView_SetImageList(g_RegEditData.hValueListWnd, hImageList, LVSIL_SMALL);
  1904. if (g_RegEditData.hImageList != NULL)
  1905. ImageList_Destroy(g_RegEditData.hImageList);
  1906. g_RegEditData.hImageList = hImageList;
  1907. return TRUE;
  1908. }
  1909. /*******************************************************************************
  1910. *
  1911. * RegEdit_SetSysColors
  1912. *
  1913. * DESCRIPTION:
  1914. * Queries the system for any desired system colors and sets window
  1915. * attributes as necessary.
  1916. *
  1917. * PARAMETERS:
  1918. * (none).
  1919. *
  1920. *******************************************************************************/
  1921. VOID
  1922. PASCAL
  1923. RegEdit_SetSysColors(
  1924. VOID
  1925. )
  1926. {
  1927. g_clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  1928. g_clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
  1929. g_clrWindowText = GetSysColor(COLOR_WINDOWTEXT);
  1930. g_clrWindow = GetSysColor(COLOR_WINDOW);
  1931. //
  1932. // Optimize the drawing of images by informing interested parties of the
  1933. // background color. This lets ImageLists avoid extra BitBlts (biggie) and
  1934. // ListViews do some minor stuff.
  1935. //
  1936. ImageList_SetBkColor(g_RegEditData.hImageList, g_clrWindow);
  1937. ListView_SetBkColor(g_RegEditData.hValueListWnd, g_clrWindow);
  1938. }
  1939. /*******************************************************************************
  1940. *
  1941. * RegEdit_SetWaitCursor
  1942. *
  1943. * DESCRIPTION:
  1944. * Simple logic to show or hide the wait cursor. Assumes that we won't be
  1945. * called by multiple layers, so no wait cursor count is maintained.
  1946. *
  1947. * PARAMETERS:
  1948. * fSet, TRUE if wait cursor should be displayed, else FALSE.
  1949. *
  1950. *******************************************************************************/
  1951. VOID
  1952. PASCAL
  1953. RegEdit_SetWaitCursor(
  1954. BOOL fSet
  1955. )
  1956. {
  1957. ShowCursor(fSet);
  1958. SetCursor(LoadCursor(NULL, fSet ? IDC_WAIT : IDC_ARROW));
  1959. }
  1960. //------------------------------------------------------------------------------
  1961. // RegEdit_GetComputerItem
  1962. //
  1963. // DESCRIPTION: Returns the root item (computer) of an item
  1964. //
  1965. // PARAMETERS: hTreeItem - treeview item
  1966. //------------------------------------------------------------------------------
  1967. HTREEITEM RegEdit_GetComputerItem(HTREEITEM hTreeItem)
  1968. {
  1969. HTREEITEM hTreeItemRoot;
  1970. HTREEITEM hCurrTreeItem = hTreeItem;
  1971. do
  1972. {
  1973. hTreeItemRoot = hCurrTreeItem;
  1974. hCurrTreeItem = TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hCurrTreeItem);
  1975. }
  1976. while (hCurrTreeItem);
  1977. return hTreeItemRoot;
  1978. }
  1979. //------------------------------------------------------------------------------
  1980. // RegEdit_GetPredefinedKey
  1981. //
  1982. // DESCRIPTION: Returns the RegEdit_GetPredefinedKey of an item
  1983. //
  1984. // PARAMETERS: hTreeItem - treeview item
  1985. //------------------------------------------------------------------------------
  1986. PREDEFINE_KEY RegEdit_GetPredefinedKey(HTREEITEM hTreeItem)
  1987. {
  1988. HTREEITEM hKeyTreeItem;
  1989. HTREEITEM hCurrTreeItem = hTreeItem;
  1990. TCHAR szKeyString[MAXKEYNAME];
  1991. PREDEFINE_KEY hkeyPredefindedKey = -1;
  1992. int i;
  1993. // Find Key
  1994. do
  1995. {
  1996. hKeyTreeItem = hCurrTreeItem;
  1997. hCurrTreeItem = TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hCurrTreeItem);
  1998. }
  1999. while ((hCurrTreeItem) &&
  2000. (TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hCurrTreeItem)));
  2001. // PREDEFINDED KEY from its name
  2002. KeyTree_GetKeyName(hKeyTreeItem, szKeyString, ARRAYSIZE(szKeyString));
  2003. for (i = 0; i < NUMBER_REGISTRY_ROOTS; i++)
  2004. {
  2005. if (_tcscmp((TCHAR*)&szKeyString, g_RegistryRoots[i].lpKeyName) == 0)
  2006. {
  2007. hkeyPredefindedKey = g_RegistryRoots[i].hPreDefKey;
  2008. break;
  2009. }
  2010. }
  2011. return hkeyPredefindedKey;
  2012. }
  2013. //------------------------------------------------------------------------------
  2014. // RegEdit_InvokeSecurityEditor
  2015. //
  2016. // DESCRIPTION: Invokes the security editor for the currently selected item.
  2017. //
  2018. // PARAMETERS: hWnd - handle to the current window
  2019. //------------------------------------------------------------------------------
  2020. VOID RegEdit_InvokeSecurityEditor(HWND hWnd)
  2021. {
  2022. HTREEITEM hSelectedTreeItem;
  2023. HTREEITEM hParentTreeItem;
  2024. HTREEITEM hComputerItem;
  2025. BOOL fRemote;
  2026. LPSECURITYINFO pSi;
  2027. PREDEFINE_KEY hkeyPredefindedKey;
  2028. TCHAR szItemName[MAXKEYNAME + 1];
  2029. TCHAR szItemParentName[MAXKEYNAME + 1];
  2030. TCHAR szComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1] = {'\\','\\'};
  2031. DWORD cbComputerName;
  2032. LPTSTR pszTitle = szItemName;
  2033. LPTSTR pszItemName = szItemName;
  2034. LPTSTR pszItemParentName = szItemParentName;
  2035. LPTSTR pszComputerName = szComputerName;
  2036. hSelectedTreeItem = TreeView_GetSelection(g_RegEditData.hKeyTreeWnd);
  2037. hParentTreeItem = TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hSelectedTreeItem);
  2038. hComputerItem = RegEdit_GetComputerItem(hSelectedTreeItem);
  2039. // ITEM NAME
  2040. KeyTree_GetKeyName(hSelectedTreeItem, pszItemName, ARRAYSIZE(szItemName));
  2041. // COMPUTER NAME
  2042. fRemote = (hComputerItem != g_RegEditData.hMyComputer);
  2043. if (fRemote)
  2044. {
  2045. KeyTree_GetKeyName(hComputerItem, pszComputerName + 2, ARRAYSIZE(szComputerName) - 2);
  2046. }
  2047. else
  2048. {
  2049. cbComputerName = ARRAYSIZE(szComputerName) - 2;
  2050. GetComputerName(szComputerName + 2, &cbComputerName);
  2051. }
  2052. // PARENT NAME
  2053. if (hParentTreeItem == hComputerItem)
  2054. {
  2055. pszItemName = NULL;
  2056. pszItemParentName = NULL;
  2057. }
  2058. else if (TreeView_GetParent(g_RegEditData.hKeyTreeWnd, hParentTreeItem) == hComputerItem)
  2059. {
  2060. pszItemParentName = NULL;
  2061. }
  2062. else
  2063. {
  2064. KeyTree_BuildKeyPath(g_RegEditData.hKeyTreeWnd, hParentTreeItem,
  2065. pszItemParentName, BKP_TOSUBKEY);
  2066. }
  2067. // PREDEFINED KEY
  2068. hkeyPredefindedKey = RegEdit_GetPredefinedKey(hSelectedTreeItem);
  2069. // SECURITY INFO
  2070. if (CreateSecurityInformation(pszItemName, pszItemParentName, pszComputerName, pszTitle,
  2071. fRemote, hkeyPredefindedKey, FALSE, hWnd, &pSi ) == S_OK)
  2072. {
  2073. EditSecurity( hWnd, pSi);
  2074. RegEdit_KeyTreeSelChanged(g_RegEditData.hKeyTreeWnd);
  2075. }
  2076. else
  2077. {
  2078. InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(IDS_GET_SECURITY_KEY_NOT_ACCESSIBLE_EX),
  2079. MAKEINTRESOURCE(IDS_SECURITY), MB_ICONERROR | MB_OK, NULL);
  2080. }
  2081. }