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

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