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.

670 lines
16 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1999 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // RegRepl.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CRegReplParamsPage class.
  10. //
  11. // Author:
  12. // David Potter (davidp) February 23, 1997
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "CluAdmX.h"
  21. #include "RegRepl.h"
  22. #include "RegKey.h"
  23. #include "ExtObj.h"
  24. #include "HelpData.h" // for g_rghelpmap*
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CRegReplParamsPage property page
  32. /////////////////////////////////////////////////////////////////////////////
  33. IMPLEMENT_DYNCREATE(CRegReplParamsPage, CBasePropertyPage)
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Message Maps
  36. BEGIN_MESSAGE_MAP(CRegReplParamsPage, CBasePropertyPage)
  37. //{{AFX_MSG_MAP(CRegReplParamsPage)
  38. ON_BN_CLICKED(IDC_PP_REGREPL_PARAMS_ADD, OnAdd)
  39. ON_BN_CLICKED(IDC_PP_REGREPL_PARAMS_MODIFY, OnModify)
  40. ON_BN_CLICKED(IDC_PP_REGREPL_PARAMS_REMOVE, OnRemove)
  41. ON_NOTIFY(LVN_ITEMCHANGED, IDC_PP_REGREPL_PARAMS_LIST, OnItemChanged)
  42. ON_NOTIFY(NM_DBLCLK, IDC_PP_REGREPL_PARAMS_LIST, OnDblClkList)
  43. //}}AFX_MSG_MAP
  44. END_MESSAGE_MAP()
  45. /////////////////////////////////////////////////////////////////////////////
  46. //++
  47. //
  48. // CRegReplParamsPage::CRegReplParamsPage
  49. //
  50. // Routine Description:
  51. // Default constructor.
  52. //
  53. // Arguments:
  54. // None.
  55. //
  56. // Return Value:
  57. // None.
  58. //
  59. //--
  60. /////////////////////////////////////////////////////////////////////////////
  61. CRegReplParamsPage::CRegReplParamsPage(void)
  62. : CBasePropertyPage(g_aHelpIDs_IDD_PP_REGREPL_PARAMETERS, g_aHelpIDs_IDD_WIZ_REGREPL_PARAMETERS)
  63. {
  64. //{{AFX_DATA_INIT(CRegReplParamsPage)
  65. //}}AFX_DATA_INIT
  66. m_pwszRegKeys = NULL;
  67. m_iddPropertyPage = IDD_PP_REGREPL_PARAMETERS;
  68. m_iddWizardPage = IDD_WIZ_REGREPL_PARAMETERS;
  69. } //*** CRegReplParamsPage::CRegReplParamsPage()
  70. /////////////////////////////////////////////////////////////////////////////
  71. //++
  72. //
  73. // CRegReplParamsPage::~CRegReplParamsPage
  74. //
  75. // Routine Description:
  76. // Destructor.
  77. //
  78. // Arguments:
  79. // None.
  80. //
  81. // Return Value:
  82. // None.
  83. //
  84. //--
  85. /////////////////////////////////////////////////////////////////////////////
  86. CRegReplParamsPage::~CRegReplParamsPage(void)
  87. {
  88. delete [] m_pwszRegKeys;
  89. } //*** CRegReplParamsPage::~CRegReplParamsPage()
  90. /////////////////////////////////////////////////////////////////////////////
  91. //++
  92. //
  93. // CRegReplParamsPage::HrInit
  94. //
  95. // Routine Description:
  96. // Initialize the page.
  97. //
  98. // Arguments:
  99. // peo [IN OUT] Pointer to the extension object.
  100. // property sheet.
  101. //
  102. // Return Value:
  103. // S_OK Page initialized successfully.
  104. // hr Page failed to initialize.
  105. //
  106. //--
  107. /////////////////////////////////////////////////////////////////////////////
  108. HRESULT CRegReplParamsPage::HrInit(IN OUT CExtObject * peo)
  109. {
  110. HRESULT _hr;
  111. DWORD _sc;
  112. CWaitCursor _wc;
  113. do
  114. {
  115. // Call the base class method.
  116. _hr = CBasePropertyPage::HrInit(peo);
  117. if (FAILED(_hr))
  118. break;
  119. ASSERT(m_pwszRegKeys == NULL);
  120. // Read the list of registry keys to replicate.
  121. _sc = ScReadRegKeys();
  122. if (_sc != ERROR_SUCCESS)
  123. {
  124. CString strPrompt;
  125. CString strError;
  126. CString strMsg;
  127. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  128. strPrompt.LoadString(IDS_ERROR_READING_REGKEYS);
  129. FormatError(strError, _sc);
  130. strMsg.Format(_T("%s\n\n%s"), strPrompt, strError);
  131. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  132. } // if: error eading registry keys
  133. } while ( 0 );
  134. return _hr;
  135. } //*** CRegReplParamsPage::HrInit()
  136. /////////////////////////////////////////////////////////////////////////////
  137. //++
  138. //
  139. // CRegReplParamsPage::DoDataExchange
  140. //
  141. // Routine Description:
  142. // Do data exchange between the dialog and the class.
  143. //
  144. // Arguments:
  145. // pDX [IN OUT] Data exchange object
  146. //
  147. // Return Value:
  148. // None.
  149. //
  150. //--
  151. /////////////////////////////////////////////////////////////////////////////
  152. void CRegReplParamsPage::DoDataExchange(CDataExchange* pDX)
  153. {
  154. if (!pDX->m_bSaveAndValidate || !BSaved())
  155. {
  156. //{{AFX_DATA_MAP(CRegReplParamsPage)
  157. DDX_Control(pDX, IDC_PP_REGREPL_PARAMS_REMOVE, m_pbRemove);
  158. DDX_Control(pDX, IDC_PP_REGREPL_PARAMS_MODIFY, m_pbModify);
  159. DDX_Control(pDX, IDC_PP_REGREPL_PARAMS_LIST, m_lcRegKeys);
  160. //}}AFX_DATA_MAP
  161. } // if: not saving or haven't saved yet
  162. CBasePropertyPage::DoDataExchange(pDX);
  163. } //*** CRegReplParamsPage::DoDataExchange()
  164. /////////////////////////////////////////////////////////////////////////////
  165. //++
  166. //
  167. // CRegReplParamsPage::OnInitDialog
  168. //
  169. // Routine Description:
  170. // Handler for the WM_INITDIALOG message.
  171. //
  172. // Arguments:
  173. // None.
  174. //
  175. // Return Value:
  176. // TRUE We need the focus to be set for us.
  177. // FALSE We already set the focus to the proper control.
  178. //
  179. //--
  180. /////////////////////////////////////////////////////////////////////////////
  181. BOOL CRegReplParamsPage::OnInitDialog(void)
  182. {
  183. CBasePropertyPage::OnInitDialog();
  184. // Add the column.
  185. {
  186. CString strColumn;
  187. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  188. strColumn.LoadString(IDS_COLTEXT_REGKEY);
  189. m_lcRegKeys.InsertColumn(0, strColumn, LVCFMT_LEFT, 300);
  190. } // Add the column
  191. // Display the list of registry keys.
  192. FillList();
  193. // Enable/disable the Modify and Remove buttons.
  194. {
  195. UINT cSelected = m_lcRegKeys.GetSelectedCount();
  196. // If there is an item selected, enable the Modify and Remove buttons.
  197. m_pbModify.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  198. m_pbRemove.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  199. } // Enable/disable the Modify and Remove buttons
  200. return TRUE; // return TRUE unless you set the focus to a control
  201. // EXCEPTION: OCX Property Pages should return FALSE
  202. } //*** CRegReplParamsPage::OnInitDialog()
  203. /////////////////////////////////////////////////////////////////////////////
  204. //++
  205. //
  206. // CRegReplParamsPage::OnSetActive
  207. //
  208. // Routine Description:
  209. // Handler for the PSN_SETACTIVE message.
  210. //
  211. // Arguments:
  212. // None.
  213. //
  214. // Return Value:
  215. // TRUE Page successfully initialized.
  216. // FALSE Page not initialized.
  217. //
  218. //--
  219. /////////////////////////////////////////////////////////////////////////////
  220. BOOL CRegReplParamsPage::OnSetActive(void)
  221. {
  222. if (BWizard())
  223. EnableNext(TRUE);
  224. return CBasePropertyPage::OnSetActive();
  225. } //*** CRegReplParamsPage::OnSetActive()
  226. /////////////////////////////////////////////////////////////////////////////
  227. //++
  228. //
  229. // CRegReplParamsPage::BApplyChanges
  230. //
  231. // Routine Description:
  232. // Apply changes made on the page.
  233. //
  234. // Arguments:
  235. // None.
  236. //
  237. // Return Value:
  238. // TRUE Page successfully applied.
  239. // FALSE Error applying page.
  240. //
  241. //--
  242. /////////////////////////////////////////////////////////////////////////////
  243. BOOL CRegReplParamsPage::BApplyChanges(void)
  244. {
  245. DWORD dwStatus = ERROR_SUCCESS;
  246. CWaitCursor wc;
  247. // Add new items.
  248. {
  249. int iitem;
  250. CString strItem;
  251. LPCWSTR pwszRegKeys;
  252. DWORD cbReturned;
  253. for ( iitem = -1
  254. ; (iitem = m_lcRegKeys.GetNextItem(iitem, LVNI_ALL)) != -1
  255. ; )
  256. {
  257. strItem = m_lcRegKeys.GetItemText(iitem, 0);
  258. pwszRegKeys = PwszRegKeys();
  259. while (*pwszRegKeys != L'\0')
  260. {
  261. if (strItem.CompareNoCase(pwszRegKeys) == 0)
  262. break;
  263. pwszRegKeys += lstrlenW(pwszRegKeys) + 1;
  264. } // while: more items in the list
  265. if (*pwszRegKeys == L'\0')
  266. {
  267. dwStatus = ClusterResourceControl(
  268. Peo()->PrdResData()->m_hresource,
  269. NULL, // hNode
  270. CLUSCTL_RESOURCE_ADD_REGISTRY_CHECKPOINT,
  271. (PVOID) (LPCWSTR) strItem,
  272. (strItem.GetLength() + 1) * sizeof(WCHAR),
  273. NULL, // OutBuffer
  274. 0, // OutBufferSize
  275. &cbReturned // BytesReturned
  276. );
  277. if ((dwStatus != ERROR_SUCCESS) && (dwStatus != ERROR_ALREADY_EXISTS))
  278. {
  279. CString strPrompt;
  280. CString strError;
  281. CString strMsg;
  282. {
  283. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  284. strPrompt.FormatMessage(IDS_ERROR_ADDING_REGKEY, strItem);
  285. }
  286. FormatError(strError, dwStatus);
  287. strMsg.Format(_T("%s\n\n%s"), strPrompt, strError);
  288. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  289. return FALSE;
  290. } // if: error adding the item
  291. } // if: found a new one
  292. } // for: each item in the list
  293. } // Add new items
  294. // Remove deleted items.
  295. {
  296. int iitem;
  297. CString strItem;
  298. LPCWSTR pwszRegKeys = PwszRegKeys();
  299. DWORD cbReturned;
  300. while (*pwszRegKeys != L'\0')
  301. {
  302. for ( iitem = -1
  303. ; (iitem = m_lcRegKeys.GetNextItem(iitem, LVNI_ALL)) != -1
  304. ; )
  305. {
  306. strItem = m_lcRegKeys.GetItemText(iitem, 0);
  307. if (strItem.CompareNoCase(pwszRegKeys) == 0)
  308. break;
  309. } // for: all items in the list
  310. if (iitem == -1)
  311. {
  312. dwStatus = ClusterResourceControl(
  313. Peo()->PrdResData()->m_hresource,
  314. NULL, // hNode
  315. CLUSCTL_RESOURCE_DELETE_REGISTRY_CHECKPOINT,
  316. (PVOID) pwszRegKeys,
  317. (lstrlenW(pwszRegKeys) + 1) * sizeof(WCHAR),
  318. NULL, // OutBuffer
  319. 0, // OutBufferSize
  320. &cbReturned // BytesReturned
  321. );
  322. if (dwStatus != ERROR_SUCCESS)
  323. {
  324. CString strPrompt;
  325. CString strError;
  326. CString strMsg;
  327. {
  328. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  329. strPrompt.FormatMessage(IDS_ERROR_DELETING_REGKEY, strItem);
  330. }
  331. FormatError(strError, dwStatus);
  332. strMsg.Format(_T("%s\n\n%s"), strPrompt, strError);
  333. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  334. return FALSE;
  335. } // if: error adding the item
  336. } // if: key was deleted
  337. pwszRegKeys += lstrlenW(pwszRegKeys) + 1;
  338. } // while: more strings
  339. } // Remove deleted items
  340. // Re-read the keys.
  341. ScReadRegKeys();
  342. FillList();
  343. return CBasePropertyPage::BApplyChanges();
  344. } //*** CRegReplParamsPage::BApplyChanges()
  345. /////////////////////////////////////////////////////////////////////////////
  346. //++
  347. //
  348. // CRegReplParamsPage::OnAdd
  349. //
  350. // Routine Description:
  351. // Handler for the BN_CLICKED message on the Add button.
  352. //
  353. // Arguments:
  354. // None.
  355. //
  356. // Return Value:
  357. // None.
  358. //
  359. //--
  360. /////////////////////////////////////////////////////////////////////////////
  361. void CRegReplParamsPage::OnAdd(void)
  362. {
  363. INT_PTR idReturn;
  364. CEditRegKeyDlg dlg(this);
  365. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  366. idReturn = dlg.DoModal();
  367. if (idReturn == IDOK)
  368. {
  369. m_lcRegKeys.InsertItem(m_lcRegKeys.GetItemCount(), dlg.m_strRegKey);
  370. m_lcRegKeys.SetFocus();
  371. SetModified(TRUE);
  372. } // if: user accepted the dialog
  373. } //*** CRegReplParamsPage::OnAdd()
  374. /////////////////////////////////////////////////////////////////////////////
  375. //++
  376. //
  377. // CRegReplParamsPage::OnModify
  378. //
  379. // Routine Description:
  380. // Handler for the BN_CLICKED message on the Modify button.
  381. //
  382. // Arguments:
  383. // None.
  384. //
  385. // Return Value:
  386. // None.
  387. //
  388. //--
  389. /////////////////////////////////////////////////////////////////////////////
  390. void CRegReplParamsPage::OnModify(void)
  391. {
  392. int iSelectedItem;
  393. INT_PTR idReturn;
  394. CEditRegKeyDlg dlg(this);
  395. // Set the text in the dialog to the text of the selected item.
  396. iSelectedItem = m_lcRegKeys.GetNextItem(-1, LVNI_SELECTED);
  397. ASSERT(iSelectedItem != -1);
  398. dlg.m_strRegKey = m_lcRegKeys.GetItemText(iSelectedItem, 0);
  399. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  400. // Display the dialog.
  401. idReturn = dlg.DoModal();
  402. if (idReturn == IDOK)
  403. {
  404. m_lcRegKeys.SetItemText(iSelectedItem, 0, dlg.m_strRegKey);
  405. m_lcRegKeys.SetFocus();
  406. SetModified(TRUE);
  407. } // if: user accepted the dialog
  408. } //*** CRegReplParamsPage::OnModify()
  409. /////////////////////////////////////////////////////////////////////////////
  410. //++
  411. //
  412. // CRegReplParamsPage::OnRemove
  413. //
  414. // Routine Description:
  415. // Handler for the BN_CLICKED message on the Remove button.
  416. //
  417. // Arguments:
  418. // None.
  419. //
  420. // Return Value:
  421. // None.
  422. //
  423. //--
  424. /////////////////////////////////////////////////////////////////////////////
  425. void CRegReplParamsPage::OnRemove(void)
  426. {
  427. int iSelectedItem;
  428. iSelectedItem = m_lcRegKeys.GetNextItem(-1, LVNI_SELECTED);
  429. ASSERT(iSelectedItem != -1);
  430. m_lcRegKeys.DeleteItem(iSelectedItem);
  431. SetModified(TRUE);
  432. } //*** CRegReplParamsPage::OnRemove()
  433. /////////////////////////////////////////////////////////////////////////////
  434. //++
  435. //
  436. // CRegReplParamsPage::OnItemChanged
  437. //
  438. // Routine Description:
  439. // Handler for the LVN_ITEM_CHANGED message on the list.
  440. //
  441. // Arguments:
  442. // None.
  443. //
  444. // Return Value:
  445. // None.
  446. //
  447. //--
  448. /////////////////////////////////////////////////////////////////////////////
  449. void CRegReplParamsPage::OnItemChanged(NMHDR * pNMHDR, LRESULT * pResult)
  450. {
  451. NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
  452. // If the selection changed, enable/disable the Properties button.
  453. if ((pNMListView->uChanged & LVIF_STATE)
  454. && ((pNMListView->uOldState & LVIS_SELECTED)
  455. || (pNMListView->uNewState & LVIS_SELECTED)))
  456. {
  457. UINT cSelected = m_lcRegKeys.GetSelectedCount();
  458. // If there is an item selected, enable the Modify and Remove buttons.
  459. m_pbModify.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  460. m_pbRemove.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  461. } // if: selection changed
  462. *pResult = 0;
  463. } //*** CRegReplParamsPage::OnItemChanged()
  464. /////////////////////////////////////////////////////////////////////////////
  465. //++
  466. //
  467. // CRegReplParamsPage::OnDblClkList
  468. //
  469. // Routine Description:
  470. // Handler for the NM_DBLCLK message on the list.
  471. //
  472. // Arguments:
  473. // None.
  474. //
  475. // Return Value:
  476. // None.
  477. //
  478. //--
  479. /////////////////////////////////////////////////////////////////////////////
  480. void CRegReplParamsPage::OnDblClkList(NMHDR * pNMHDR, LRESULT * pResult)
  481. {
  482. OnModify();
  483. *pResult = 0;
  484. } //*** CRegReplParamsPage::OnDblClkList()
  485. /////////////////////////////////////////////////////////////////////////////
  486. //++
  487. //
  488. // CRegReplParamsPage::ScReadRegKeys
  489. //
  490. // Routine Description:
  491. // Read the registry keys.
  492. //
  493. // Arguments:
  494. // None.
  495. //
  496. // Return Value:
  497. // ERROR_SUCCESS Registry keys read successfully.
  498. //
  499. //--
  500. /////////////////////////////////////////////////////////////////////////////
  501. DWORD CRegReplParamsPage::ScReadRegKeys(void)
  502. {
  503. DWORD dwStatus = ERROR_SUCCESS;
  504. DWORD cbRegKeys = 256;
  505. LPWSTR pwszRegKeys = NULL;
  506. CWaitCursor wc;
  507. CMemoryException me(FALSE /*bAutoDelete*/, 0 /*nResourceID*/);
  508. // Read the list of registry keys to replicate.
  509. try
  510. {
  511. // Get registry keys.
  512. pwszRegKeys = new WCHAR[cbRegKeys / sizeof(WCHAR)];
  513. if (pwszRegKeys == NULL)
  514. {
  515. throw &me;
  516. } // if: error allocating key name buffer
  517. dwStatus = ClusterResourceControl(
  518. Peo()->PrdResData()->m_hresource,
  519. NULL, // hNode
  520. CLUSCTL_RESOURCE_GET_REGISTRY_CHECKPOINTS,
  521. NULL, // lpInBuffer
  522. 0, // nInBufferSize
  523. pwszRegKeys,
  524. cbRegKeys,
  525. &cbRegKeys
  526. );
  527. if (dwStatus == ERROR_MORE_DATA)
  528. {
  529. delete [] pwszRegKeys;
  530. ASSERT(cbRegKeys == (cbRegKeys / sizeof(WCHAR)) * sizeof(WCHAR));
  531. pwszRegKeys = new WCHAR[cbRegKeys / sizeof(WCHAR)];
  532. if (pwszRegKeys == NULL)
  533. {
  534. throw &me;
  535. } // if: error allocating key name buffer
  536. dwStatus = ClusterResourceControl(
  537. Peo()->PrdResData()->m_hresource,
  538. NULL, // hNode
  539. CLUSCTL_RESOURCE_GET_REGISTRY_CHECKPOINTS,
  540. NULL, // lpInBuffer
  541. 0, // nInBufferSize
  542. pwszRegKeys,
  543. cbRegKeys,
  544. &cbRegKeys
  545. );
  546. } // if: buffer too small
  547. } // try
  548. catch (CMemoryException * pme)
  549. {
  550. pme->ReportError();
  551. pme->Delete();
  552. return ERROR_NOT_ENOUGH_MEMORY;
  553. } // catch: CMemoryException
  554. if ((dwStatus != ERROR_SUCCESS) || (cbRegKeys == 0))
  555. *pwszRegKeys = L'\0';
  556. delete [] m_pwszRegKeys;
  557. m_pwszRegKeys = pwszRegKeys;
  558. return dwStatus;
  559. } //*** CRegReplParamsPage::ScReadRegKeys()
  560. /////////////////////////////////////////////////////////////////////////////
  561. //++
  562. //
  563. // CRegReplParamsPage::FillList
  564. //
  565. // Routine Description:
  566. // Fill the list control.
  567. //
  568. // Arguments:
  569. // None.
  570. //
  571. // Return Value:
  572. // None.
  573. //
  574. //--
  575. /////////////////////////////////////////////////////////////////////////////
  576. void CRegReplParamsPage::FillList(void)
  577. {
  578. m_lcRegKeys.DeleteAllItems();
  579. if (PwszRegKeys() != NULL)
  580. {
  581. int iitem;
  582. int iitemRet;
  583. LPCWSTR pwszRegKeys = PwszRegKeys();
  584. for (iitem = 0 ; *pwszRegKeys != L'\0' ; iitem++)
  585. {
  586. iitemRet = m_lcRegKeys.InsertItem(iitem, pwszRegKeys);
  587. ASSERT(iitemRet == iitem);
  588. pwszRegKeys += lstrlenW(pwszRegKeys) + 1;
  589. } // while: more strings in the list
  590. } // if: there are any keys to display
  591. } //*** CRegReplParamsPage::FillList()