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.

675 lines
20 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2002 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 = S_OK;
  111. DWORD _sc;
  112. CWaitCursor _wc;
  113. // Call the base class method.
  114. _hr = CBasePropertyPage::HrInit(peo);
  115. if (FAILED(_hr))
  116. {
  117. goto Cleanup;
  118. }
  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. Cleanup:
  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. {
  224. EnableNext(TRUE);
  225. }
  226. return CBasePropertyPage::OnSetActive();
  227. } //*** CRegReplParamsPage::OnSetActive()
  228. /////////////////////////////////////////////////////////////////////////////
  229. //++
  230. //
  231. // CRegReplParamsPage::BApplyChanges
  232. //
  233. // Routine Description:
  234. // Apply changes made on the page.
  235. //
  236. // Arguments:
  237. // None.
  238. //
  239. // Return Value:
  240. // TRUE Page successfully applied.
  241. // FALSE Error applying page.
  242. //
  243. //--
  244. /////////////////////////////////////////////////////////////////////////////
  245. BOOL CRegReplParamsPage::BApplyChanges(void)
  246. {
  247. DWORD dwStatus = ERROR_SUCCESS;
  248. CWaitCursor wc;
  249. // Add new items.
  250. {
  251. int iitem;
  252. CString strItem;
  253. LPCWSTR pwszRegKeys;
  254. DWORD cbReturned;
  255. for ( iitem = -1
  256. ; (iitem = m_lcRegKeys.GetNextItem(iitem, LVNI_ALL)) != -1
  257. ; )
  258. {
  259. strItem = m_lcRegKeys.GetItemText(iitem, 0);
  260. pwszRegKeys = PwszRegKeys();
  261. while (*pwszRegKeys != L'\0')
  262. {
  263. if (strItem.CompareNoCase(pwszRegKeys) == 0)
  264. break;
  265. pwszRegKeys += wcslen(pwszRegKeys) + 1;
  266. } // while: more items in the list
  267. if (*pwszRegKeys == L'\0')
  268. {
  269. dwStatus = ClusterResourceControl(
  270. Peo()->PrdResData()->m_hresource,
  271. NULL, // hNode
  272. CLUSCTL_RESOURCE_ADD_REGISTRY_CHECKPOINT,
  273. (PVOID) (LPCWSTR) strItem,
  274. (strItem.GetLength() + 1) * sizeof(WCHAR),
  275. NULL, // OutBuffer
  276. 0, // OutBufferSize
  277. &cbReturned // BytesReturned
  278. );
  279. if ((dwStatus != ERROR_SUCCESS) && (dwStatus != ERROR_ALREADY_EXISTS))
  280. {
  281. CString strPrompt;
  282. CString strError;
  283. CString strMsg;
  284. {
  285. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  286. strPrompt.FormatMessage(IDS_ERROR_ADDING_REGKEY, strItem);
  287. }
  288. FormatError(strError, dwStatus);
  289. strMsg.Format(_T("%s\n\n%s"), strPrompt, strError);
  290. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  291. return FALSE;
  292. } // if: error adding the item
  293. } // if: found a new one
  294. } // for: each item in the list
  295. } // Add new items
  296. // Remove deleted items.
  297. {
  298. int iitem;
  299. CString strItem;
  300. LPCWSTR pwszRegKeys = PwszRegKeys();
  301. DWORD cbReturned;
  302. while (*pwszRegKeys != L'\0')
  303. {
  304. for ( iitem = -1
  305. ; (iitem = m_lcRegKeys.GetNextItem(iitem, LVNI_ALL)) != -1
  306. ; )
  307. {
  308. strItem = m_lcRegKeys.GetItemText(iitem, 0);
  309. if (strItem.CompareNoCase(pwszRegKeys) == 0)
  310. break;
  311. } // for: all items in the list
  312. if (iitem == -1)
  313. {
  314. dwStatus = ClusterResourceControl(
  315. Peo()->PrdResData()->m_hresource,
  316. NULL, // hNode
  317. CLUSCTL_RESOURCE_DELETE_REGISTRY_CHECKPOINT,
  318. (PVOID) pwszRegKeys,
  319. static_cast< DWORD >( (wcslen(pwszRegKeys) + 1) * sizeof(WCHAR) ),
  320. NULL, // OutBuffer
  321. 0, // OutBufferSize
  322. &cbReturned // BytesReturned
  323. );
  324. if (dwStatus != ERROR_SUCCESS)
  325. {
  326. CString strPrompt;
  327. CString strError;
  328. CString strMsg;
  329. {
  330. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  331. strPrompt.FormatMessage(IDS_ERROR_DELETING_REGKEY, strItem);
  332. }
  333. FormatError(strError, dwStatus);
  334. strMsg.Format(_T("%s\n\n%s"), strPrompt, strError);
  335. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  336. return FALSE;
  337. } // if: error adding the item
  338. } // if: key was deleted
  339. pwszRegKeys += wcslen(pwszRegKeys) + 1;
  340. } // while: more strings
  341. } // Remove deleted items
  342. // Re-read the keys.
  343. ScReadRegKeys();
  344. FillList();
  345. return CBasePropertyPage::BApplyChanges();
  346. } //*** CRegReplParamsPage::BApplyChanges()
  347. /////////////////////////////////////////////////////////////////////////////
  348. //++
  349. //
  350. // CRegReplParamsPage::OnAdd
  351. //
  352. // Routine Description:
  353. // Handler for the BN_CLICKED message on the Add button.
  354. //
  355. // Arguments:
  356. // None.
  357. //
  358. // Return Value:
  359. // None.
  360. //
  361. //--
  362. /////////////////////////////////////////////////////////////////////////////
  363. void CRegReplParamsPage::OnAdd(void)
  364. {
  365. INT_PTR idReturn;
  366. CEditRegKeyDlg dlg(this);
  367. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  368. idReturn = dlg.DoModal();
  369. if (idReturn == IDOK)
  370. {
  371. m_lcRegKeys.InsertItem(m_lcRegKeys.GetItemCount(), dlg.m_strRegKey);
  372. m_lcRegKeys.SetFocus();
  373. SetModified(TRUE);
  374. } // if: user accepted the dialog
  375. } //*** CRegReplParamsPage::OnAdd()
  376. /////////////////////////////////////////////////////////////////////////////
  377. //++
  378. //
  379. // CRegReplParamsPage::OnModify
  380. //
  381. // Routine Description:
  382. // Handler for the BN_CLICKED message on the Modify button.
  383. //
  384. // Arguments:
  385. // None.
  386. //
  387. // Return Value:
  388. // None.
  389. //
  390. //--
  391. /////////////////////////////////////////////////////////////////////////////
  392. void CRegReplParamsPage::OnModify(void)
  393. {
  394. int iSelectedItem;
  395. INT_PTR idReturn;
  396. CEditRegKeyDlg dlg(this);
  397. // Set the text in the dialog to the text of the selected item.
  398. iSelectedItem = m_lcRegKeys.GetNextItem(-1, LVNI_SELECTED);
  399. ASSERT(iSelectedItem != -1);
  400. dlg.m_strRegKey = m_lcRegKeys.GetItemText(iSelectedItem, 0);
  401. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  402. // Display the dialog.
  403. idReturn = dlg.DoModal();
  404. if (idReturn == IDOK)
  405. {
  406. m_lcRegKeys.SetItemText(iSelectedItem, 0, dlg.m_strRegKey);
  407. m_lcRegKeys.SetFocus();
  408. SetModified(TRUE);
  409. } // if: user accepted the dialog
  410. } //*** CRegReplParamsPage::OnModify()
  411. /////////////////////////////////////////////////////////////////////////////
  412. //++
  413. //
  414. // CRegReplParamsPage::OnRemove
  415. //
  416. // Routine Description:
  417. // Handler for the BN_CLICKED message on the Remove button.
  418. //
  419. // Arguments:
  420. // None.
  421. //
  422. // Return Value:
  423. // None.
  424. //
  425. //--
  426. /////////////////////////////////////////////////////////////////////////////
  427. void CRegReplParamsPage::OnRemove(void)
  428. {
  429. int iSelectedItem;
  430. iSelectedItem = m_lcRegKeys.GetNextItem(-1, LVNI_SELECTED);
  431. ASSERT(iSelectedItem != -1);
  432. m_lcRegKeys.DeleteItem(iSelectedItem);
  433. SetModified(TRUE);
  434. } //*** CRegReplParamsPage::OnRemove()
  435. /////////////////////////////////////////////////////////////////////////////
  436. //++
  437. //
  438. // CRegReplParamsPage::OnItemChanged
  439. //
  440. // Routine Description:
  441. // Handler for the LVN_ITEM_CHANGED message on the list.
  442. //
  443. // Arguments:
  444. // None.
  445. //
  446. // Return Value:
  447. // None.
  448. //
  449. //--
  450. /////////////////////////////////////////////////////////////////////////////
  451. void CRegReplParamsPage::OnItemChanged(NMHDR * pNMHDR, LRESULT * pResult)
  452. {
  453. NM_LISTVIEW * pNMListView = (NM_LISTVIEW *) pNMHDR;
  454. // If the selection changed, enable/disable the Properties button.
  455. if ((pNMListView->uChanged & LVIF_STATE)
  456. && ((pNMListView->uOldState & LVIS_SELECTED)
  457. || (pNMListView->uNewState & LVIS_SELECTED)))
  458. {
  459. UINT cSelected = m_lcRegKeys.GetSelectedCount();
  460. // If there is an item selected, enable the Modify and Remove buttons.
  461. m_pbModify.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  462. m_pbRemove.EnableWindow((cSelected > 0) ? TRUE : FALSE);
  463. } // if: selection changed
  464. *pResult = 0;
  465. } //*** CRegReplParamsPage::OnItemChanged()
  466. /////////////////////////////////////////////////////////////////////////////
  467. //++
  468. //
  469. // CRegReplParamsPage::OnDblClkList
  470. //
  471. // Routine Description:
  472. // Handler for the NM_DBLCLK message on the list.
  473. //
  474. // Arguments:
  475. // None.
  476. //
  477. // Return Value:
  478. // None.
  479. //
  480. //--
  481. /////////////////////////////////////////////////////////////////////////////
  482. void CRegReplParamsPage::OnDblClkList(NMHDR * pNMHDR, LRESULT * pResult)
  483. {
  484. OnModify();
  485. *pResult = 0;
  486. } //*** CRegReplParamsPage::OnDblClkList()
  487. /////////////////////////////////////////////////////////////////////////////
  488. //++
  489. //
  490. // CRegReplParamsPage::ScReadRegKeys
  491. //
  492. // Routine Description:
  493. // Read the registry keys.
  494. //
  495. // Arguments:
  496. // None.
  497. //
  498. // Return Value:
  499. // ERROR_SUCCESS Registry keys read successfully.
  500. //
  501. //--
  502. /////////////////////////////////////////////////////////////////////////////
  503. DWORD CRegReplParamsPage::ScReadRegKeys(void)
  504. {
  505. DWORD dwStatus = ERROR_SUCCESS;
  506. DWORD cbRegKeys = 256;
  507. LPWSTR pwszRegKeys = NULL;
  508. CWaitCursor wc;
  509. CMemoryException me(FALSE /*bAutoDelete*/, 0 /*nResourceID*/);
  510. // Read the list of registry keys to replicate.
  511. try
  512. {
  513. // Get registry keys.
  514. pwszRegKeys = new WCHAR[cbRegKeys / sizeof(WCHAR)];
  515. if (pwszRegKeys == NULL)
  516. {
  517. throw &me;
  518. } // if: error allocating key name buffer
  519. dwStatus = ClusterResourceControl(
  520. Peo()->PrdResData()->m_hresource,
  521. NULL, // hNode
  522. CLUSCTL_RESOURCE_GET_REGISTRY_CHECKPOINTS,
  523. NULL, // lpInBuffer
  524. 0, // nInBufferSize
  525. pwszRegKeys,
  526. cbRegKeys,
  527. &cbRegKeys
  528. );
  529. if (dwStatus == ERROR_MORE_DATA)
  530. {
  531. delete [] pwszRegKeys;
  532. ASSERT(cbRegKeys == (cbRegKeys / sizeof(WCHAR)) * sizeof(WCHAR));
  533. pwszRegKeys = new WCHAR[cbRegKeys / sizeof(WCHAR)];
  534. if (pwszRegKeys == NULL)
  535. {
  536. throw &me;
  537. } // if: error allocating key name buffer
  538. dwStatus = ClusterResourceControl(
  539. Peo()->PrdResData()->m_hresource,
  540. NULL, // hNode
  541. CLUSCTL_RESOURCE_GET_REGISTRY_CHECKPOINTS,
  542. NULL, // lpInBuffer
  543. 0, // nInBufferSize
  544. pwszRegKeys,
  545. cbRegKeys,
  546. &cbRegKeys
  547. );
  548. } // if: buffer too small
  549. } // try
  550. catch (CMemoryException * pme)
  551. {
  552. pme->ReportError();
  553. pme->Delete();
  554. return ERROR_NOT_ENOUGH_MEMORY;
  555. } // catch: CMemoryException
  556. if ((dwStatus != ERROR_SUCCESS) || (cbRegKeys == 0))
  557. {
  558. *pwszRegKeys = L'\0';
  559. }
  560. delete [] m_pwszRegKeys;
  561. m_pwszRegKeys = pwszRegKeys;
  562. return dwStatus;
  563. } //*** CRegReplParamsPage::ScReadRegKeys()
  564. /////////////////////////////////////////////////////////////////////////////
  565. //++
  566. //
  567. // CRegReplParamsPage::FillList
  568. //
  569. // Routine Description:
  570. // Fill the list control.
  571. //
  572. // Arguments:
  573. // None.
  574. //
  575. // Return Value:
  576. // None.
  577. //
  578. //--
  579. /////////////////////////////////////////////////////////////////////////////
  580. void CRegReplParamsPage::FillList(void)
  581. {
  582. m_lcRegKeys.DeleteAllItems();
  583. if (PwszRegKeys() != NULL)
  584. {
  585. int iitem;
  586. int iitemRet;
  587. LPCWSTR pwszRegKeys = PwszRegKeys();
  588. for (iitem = 0 ; *pwszRegKeys != L'\0' ; iitem++)
  589. {
  590. iitemRet = m_lcRegKeys.InsertItem(iitem, pwszRegKeys);
  591. ASSERT(iitemRet == iitem);
  592. pwszRegKeys += wcslen(pwszRegKeys) + 1;
  593. } // while: more strings in the list
  594. } // if: there are any keys to display
  595. } //*** CRegReplParamsPage::FillList()