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.

1422 lines
41 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1997 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // BasePage.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CBasePropertyPage class.
  10. //
  11. // Author:
  12. // David Potter (davidp) June 28, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "IISClEx4.h"
  21. #include "ExtObj.h"
  22. #include "BasePage.h"
  23. #include "BasePage.inl"
  24. #include "PropList.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CBasePropertyPage property page
  32. /////////////////////////////////////////////////////////////////////////////
  33. IMPLEMENT_DYNCREATE(CBasePropertyPage, CPropertyPage)
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Message Maps
  36. BEGIN_MESSAGE_MAP(CBasePropertyPage, CPropertyPage)
  37. //{{AFX_MSG_MAP(CBasePropertyPage)
  38. ON_WM_CREATE()
  39. ON_WM_DESTROY()
  40. ON_WM_HELPINFO()
  41. ON_WM_CONTEXTMENU()
  42. ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
  43. //}}AFX_MSG_MAP
  44. END_MESSAGE_MAP()
  45. /////////////////////////////////////////////////////////////////////////////
  46. //++
  47. //
  48. // CBasePropertyPage::CBasePropertyPage
  49. //
  50. // Routine Description:
  51. // Default constructor.
  52. //
  53. // Arguments:
  54. // None.
  55. //
  56. // Return Value:
  57. // None.
  58. //
  59. //--
  60. /////////////////////////////////////////////////////////////////////////////
  61. CBasePropertyPage::CBasePropertyPage(void)
  62. {
  63. CommonConstruct();
  64. } //*** CBasePropertyPage::CBasePropertyPage()
  65. /////////////////////////////////////////////////////////////////////////////
  66. //++
  67. //
  68. // CBasePropertyPage::CBasePropertyPage
  69. //
  70. // Routine Description:
  71. // Default constructor.
  72. //
  73. // Arguments:
  74. // pmap [IN] Control to help ID map.
  75. //
  76. // Return Value:
  77. // None.
  78. //
  79. //--
  80. /////////////////////////////////////////////////////////////////////////////
  81. CBasePropertyPage::CBasePropertyPage(
  82. IN const CMapCtrlToHelpID * pmap
  83. )
  84. : m_dlghelp(pmap, 0)
  85. {
  86. CommonConstruct();
  87. } //*** CBasePropertyPage::CBasePropertyPage()
  88. /////////////////////////////////////////////////////////////////////////////
  89. //++
  90. //
  91. // CBasePropertyPage::CBasePropertyPage
  92. //
  93. // Routine Description:
  94. // Default constructor.
  95. //
  96. // Arguments:
  97. // pmap [IN] Control to help ID map.
  98. // nIDTemplate [IN] Dialog template resource ID.
  99. // nIDCaption [IN] Caption string resource ID.
  100. //
  101. // Return Value:
  102. // None.
  103. //
  104. //--
  105. /////////////////////////////////////////////////////////////////////////////
  106. CBasePropertyPage::CBasePropertyPage(
  107. IN const CMapCtrlToHelpID * pmap,
  108. IN UINT nIDTemplate,
  109. IN UINT nIDCaption
  110. )
  111. : CPropertyPage(nIDTemplate, nIDCaption)
  112. , m_dlghelp(pmap, nIDTemplate)
  113. {
  114. CommonConstruct();
  115. } //*** CBasePropertyPage::CBasePropertyPage(UINT, UINT)
  116. /////////////////////////////////////////////////////////////////////////////
  117. //++
  118. //
  119. // CBasePropertyPage::CommonConstruct
  120. //
  121. // Routine Description:
  122. // Common construction.
  123. //
  124. // Arguments:
  125. // None.
  126. //
  127. // Return Value:
  128. // None.
  129. //
  130. //--
  131. /////////////////////////////////////////////////////////////////////////////
  132. void CBasePropertyPage::CommonConstruct(void)
  133. {
  134. //{{AFX_DATA_INIT(CBasePropertyPage)
  135. //}}AFX_DATA_INIT
  136. m_peo = NULL;
  137. m_hpage = NULL;
  138. m_bBackPressed = FALSE;
  139. m_bDoDetach = FALSE;
  140. m_iddPropertyPage = NULL;
  141. m_iddWizardPage = NULL;
  142. m_idcPPTitle = NULL;
  143. m_idsCaption = NULL;
  144. } //*** CBasePropertyPage::CommonConstruct()
  145. /////////////////////////////////////////////////////////////////////////////
  146. //++
  147. //
  148. // CBasePropertyPage::BInit
  149. //
  150. // Routine Description:
  151. // Initialize the page.
  152. //
  153. // Arguments:
  154. // peo [IN OUT] Pointer to the extension object.
  155. //
  156. // Return Value:
  157. // TRUE Page initialized successfully.
  158. // FALSE Page failed to initialize.
  159. //
  160. //--
  161. /////////////////////////////////////////////////////////////////////////////
  162. BOOL CBasePropertyPage::BInit(IN OUT CExtObject * peo)
  163. {
  164. ASSERT(peo != NULL);
  165. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  166. m_peo = peo;
  167. // Don't display a help button.
  168. m_psp.dwFlags &= ~PSP_HASHELP;
  169. // Construct the property page.
  170. if (Peo()->BWizard())
  171. {
  172. ASSERT(IddWizardPage() != NULL);
  173. Construct(IddWizardPage(), IdsCaption());
  174. m_dlghelp.SetHelpMask(IddWizardPage());
  175. } // if: adding page to wizard
  176. else
  177. {
  178. ASSERT(IddPropertyPage() != NULL);
  179. Construct(IddPropertyPage(), IdsCaption());
  180. m_dlghelp.SetHelpMask(IddPropertyPage());
  181. } // else: adding page to property sheet
  182. // Read the properties private to this resource and parse them.
  183. {
  184. DWORD dwStatus;
  185. CClusPropList cpl;
  186. ASSERT(Peo() != NULL);
  187. ASSERT(Peo()->PrdResData() != NULL);
  188. ASSERT(Peo()->PrdResData()->m_hresource != NULL);
  189. // Read the properties.
  190. dwStatus = cpl.DwGetResourceProperties(
  191. Peo()->PrdResData()->m_hresource,
  192. CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
  193. );
  194. // Parse the properties.
  195. if (dwStatus == ERROR_SUCCESS)
  196. {
  197. // Parse the properties.
  198. try
  199. {
  200. dwStatus = DwParseProperties(cpl);
  201. } // try
  202. catch (CMemoryException * pme)
  203. {
  204. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  205. pme->Delete();
  206. } // catch: CMemoryException
  207. } // if: properties read successfully
  208. if (dwStatus != ERROR_SUCCESS)
  209. {
  210. return FALSE;
  211. } // if: error parsing getting or parsing properties
  212. } // Read the properties private to this resource and parse them
  213. return TRUE;
  214. } //*** CBasePropertyPage::BInit()
  215. /////////////////////////////////////////////////////////////////////////////
  216. //++
  217. //
  218. // CBasePropertyPage::DwParseProperties
  219. //
  220. // Routine Description:
  221. // Parse the properties of the resource. This is in a separate function
  222. // from BInit so that the optimizer can do a better job.
  223. //
  224. // Arguments:
  225. // rcpl [IN] Cluster property list to parse.
  226. //
  227. // Return Value:
  228. // ERROR_SUCCESS Properties were parsed successfully.
  229. //
  230. // Exceptions Thrown:
  231. // Any exceptions from CString::operator=().
  232. //
  233. //--
  234. /////////////////////////////////////////////////////////////////////////////
  235. DWORD CBasePropertyPage::DwParseProperties(IN const CClusPropList & rcpl)
  236. {
  237. DWORD cProps;
  238. DWORD cprop;
  239. const CObjectProperty * pprop;
  240. CLUSPROP_BUFFER_HELPER props;
  241. CLUSPROP_PROPERTY_NAME const * pName;
  242. ASSERT(rcpl.PbProplist() != NULL);
  243. props.pb = rcpl.PbProplist();
  244. // Loop through each property.
  245. for (cProps = *(props.pdw++) ; cProps > 0 ; cProps--)
  246. {
  247. pName = props.pName;
  248. ASSERT(pName->Syntax.dw == CLUSPROP_SYNTAX_NAME);
  249. props.pb += sizeof(*pName) + ALIGN_CLUSPROP(pName->cbLength);
  250. // Parse known properties.
  251. for (pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop--)
  252. {
  253. if (lstrcmpiW(pName->sz, pprop->m_pwszName) == 0)
  254. {
  255. ASSERT(props.pSyntax->wFormat == pprop->m_propFormat);
  256. switch (pprop->m_propFormat)
  257. {
  258. case CLUSPROP_FORMAT_SZ:
  259. *pprop->m_value.pstr = props.pStringValue->sz;
  260. *pprop->m_valuePrev.pstr = props.pStringValue->sz;
  261. break;
  262. case CLUSPROP_FORMAT_DWORD:
  263. *pprop->m_value.pdw = props.pDwordValue->dw;
  264. *pprop->m_valuePrev.pdw = props.pDwordValue->dw;
  265. break;
  266. case CLUSPROP_FORMAT_BINARY:
  267. case CLUSPROP_FORMAT_MULTI_SZ:
  268. *pprop->m_value.ppb = props.pBinaryValue->rgb;
  269. *pprop->m_value.pcb = props.pBinaryValue->cbLength;
  270. *pprop->m_valuePrev.ppb = props.pBinaryValue->rgb;
  271. *pprop->m_valuePrev.pcb = props.pBinaryValue->cbLength;
  272. break;
  273. default:
  274. ASSERT(0); // don't know how to deal with this type
  275. } // switch: property format
  276. // Exit the loop since we found the parameter.
  277. break;
  278. } // if: found a match
  279. } // for: each property
  280. // If the property wasn't known, ask the derived class to parse it.
  281. if (cprop == 0)
  282. {
  283. DWORD dwStatus;
  284. dwStatus = DwParseUnknownProperty(pName->sz, props);
  285. if (dwStatus != ERROR_SUCCESS)
  286. return dwStatus;
  287. } // if: property not parsed
  288. // Advance the pointer.
  289. if ((props.pSyntax->wFormat == CLUSPROP_FORMAT_BINARY)
  290. || (props.pSyntax->wFormat == CLUSPROP_FORMAT_SZ)
  291. || (props.pSyntax->wFormat == CLUSPROP_FORMAT_MULTI_SZ))
  292. props.pb += sizeof(*props.pBinaryValue)
  293. + ALIGN_CLUSPROP(props.pBinaryValue->cbLength)
  294. + sizeof(*props.pSyntax); // endmark
  295. else if (props.pSyntax->wFormat == CLUSPROP_FORMAT_DWORD)
  296. props.pb += sizeof(*props.pDwordValue) + sizeof(*props.pSyntax);
  297. else
  298. {
  299. ASSERT(0); // Unknown property syntax
  300. break;
  301. } // else: unknown property format
  302. } // for: each property
  303. return ERROR_SUCCESS;
  304. } //*** CBasePropertyPage::DwParseProperties()
  305. /////////////////////////////////////////////////////////////////////////////
  306. //++
  307. //
  308. // CBasePropertyPage::OnCreate
  309. //
  310. // Routine Description:
  311. // Handler for the WM_CREATE message.
  312. //
  313. // Arguments:
  314. // lpCreateStruct [IN OUT] Window create structure.
  315. //
  316. // Return Value:
  317. // -1 Error.
  318. // 0 Success.
  319. //
  320. //--
  321. /////////////////////////////////////////////////////////////////////////////
  322. int CBasePropertyPage::OnCreate(LPCREATESTRUCT lpCreateStruct)
  323. {
  324. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  325. // Attach the window to the property page structure.
  326. // This has been done once already in the main application, since the
  327. // main application owns the property sheet. It needs to be done here
  328. // so that the window handle can be found in the DLL's handle map.
  329. if (FromHandlePermanent(m_hWnd) == NULL) // is the window handle already in the handle map
  330. {
  331. HWND hWnd = m_hWnd;
  332. m_hWnd = NULL;
  333. Attach(hWnd);
  334. m_bDoDetach = TRUE;
  335. } // if: is the window handle in the handle map
  336. return CPropertyPage::OnCreate(lpCreateStruct);
  337. } //*** CBasePropertyPage::OnCreate()
  338. /////////////////////////////////////////////////////////////////////////////
  339. //++
  340. //
  341. // CBasePropertyPage::OnDestroy
  342. //
  343. // Routine Description:
  344. // Handler for the WM_DESTROY message.
  345. //
  346. // Arguments:
  347. // None.
  348. //
  349. // Return Value:
  350. // None.
  351. //
  352. //--
  353. /////////////////////////////////////////////////////////////////////////////
  354. void CBasePropertyPage::OnDestroy(void)
  355. {
  356. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  357. // Detach the window from the property page structure.
  358. // This will be done again by the main application, since it owns the
  359. // property sheet. It needs to be done here so that the window handle
  360. // can be removed from the DLL's handle map.
  361. if (m_bDoDetach)
  362. {
  363. if (m_hWnd != NULL)
  364. {
  365. HWND hWnd = m_hWnd;
  366. Detach();
  367. m_hWnd = hWnd;
  368. } // if: do we have a window handle?
  369. } // if: do we need to balance the attach we did with a detach?
  370. CPropertyPage::OnDestroy();
  371. } //*** CBasePropertyPage::OnDestroy()
  372. /////////////////////////////////////////////////////////////////////////////
  373. //++
  374. //
  375. // CBasePropertyPage::DoDataExchange
  376. //
  377. // Routine Description:
  378. // Do data exchange between the dialog and the class.
  379. //
  380. // Arguments:
  381. // pDX [IN OUT] Data exchange object
  382. //
  383. // Return Value:
  384. // None.
  385. //
  386. //--
  387. /////////////////////////////////////////////////////////////////////////////
  388. void CBasePropertyPage::DoDataExchange(CDataExchange * pDX)
  389. {
  390. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  391. CPropertyPage::DoDataExchange(pDX);
  392. //{{AFX_DATA_MAP(CBasePropertyPage)
  393. // NOTE: the ClassWizard will add DDX and DDV calls here
  394. //}}AFX_DATA_MAP
  395. DDX_Control(pDX, IDC_PP_ICON, m_staticIcon);
  396. DDX_Control(pDX, m_idcPPTitle, m_staticTitle);
  397. if (!pDX->m_bSaveAndValidate)
  398. {
  399. // Set the title.
  400. DDX_Text(pDX, m_idcPPTitle, m_strTitle);
  401. } // if: not saving data
  402. } //*** CBasePropertyPage::DoDataExchange()
  403. /////////////////////////////////////////////////////////////////////////////
  404. //++
  405. //
  406. // CBasePropertyPage::OnInitDialog
  407. //
  408. // Routine Description:
  409. // Handler for the WM_INITDIALOG message.
  410. //
  411. // Arguments:
  412. // None.
  413. //
  414. // Return Value:
  415. // TRUE We need the focus to be set for us.
  416. // FALSE We already set the focus to the proper control.
  417. //
  418. //--
  419. /////////////////////////////////////////////////////////////////////////////
  420. BOOL CBasePropertyPage::OnInitDialog(void)
  421. {
  422. ASSERT(Peo() != NULL);
  423. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  424. // Set the title string.
  425. m_strTitle = Peo()->RrdResData().m_strName;
  426. // Call the base class method.
  427. CPropertyPage::OnInitDialog();
  428. // Display an icon for the object.
  429. if (Peo()->Hicon() != NULL)
  430. m_staticIcon.SetIcon(Peo()->Hicon());
  431. return TRUE; // return TRUE unless you set the focus to a control
  432. // EXCEPTION: OCX Property Pages should return FALSE
  433. } //*** CBasePropertyPage::OnInitDialog()
  434. /////////////////////////////////////////////////////////////////////////////
  435. //++
  436. //
  437. // CBasePropertyPage::OnSetActive
  438. //
  439. // Routine Description:
  440. // Handler for the PSN_SETACTIVE message.
  441. //
  442. // Arguments:
  443. // None.
  444. //
  445. // Return Value:
  446. // TRUE Page successfully initialized.
  447. // FALSE Page not initialized.
  448. //
  449. //--
  450. /////////////////////////////////////////////////////////////////////////////
  451. BOOL CBasePropertyPage::OnSetActive(void)
  452. {
  453. HRESULT hr;
  454. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  455. // Reread the data.
  456. hr = Peo()->HrGetObjectInfo();
  457. if (hr != NOERROR)
  458. return FALSE;
  459. // Set the title string.
  460. m_strTitle = Peo()->RrdResData().m_strName;
  461. m_bBackPressed = FALSE;
  462. return CPropertyPage::OnSetActive();
  463. } //*** CBasePropertyPage::OnSetActive()
  464. /////////////////////////////////////////////////////////////////////////////
  465. //++
  466. //
  467. // CBasePropertyPage::OnApply
  468. //
  469. // Routine Description:
  470. // Handler for the PSM_APPLY message.
  471. //
  472. // Arguments:
  473. // None.
  474. //
  475. // Return Value:
  476. // TRUE Page successfully applied.
  477. // FALSE Error applying page.
  478. //
  479. //--
  480. /////////////////////////////////////////////////////////////////////////////
  481. BOOL CBasePropertyPage::OnApply(void)
  482. {
  483. ASSERT(!BWizard());
  484. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  485. // Update the data in the class from the page.
  486. UpdateData(/*bSaveAndValidate*/);
  487. if (!BApplyChanges())
  488. return FALSE;
  489. return CPropertyPage::OnApply();
  490. } //*** CBasePropertyPage::OnApply()
  491. /////////////////////////////////////////////////////////////////////////////
  492. //++
  493. //
  494. // CBasePropertyPage::OnWizardBack
  495. //
  496. // Routine Description:
  497. // Handler for the PSN_WIZBACK message.
  498. //
  499. // Arguments:
  500. // None.
  501. //
  502. // Return Value:
  503. // -1 Don't change the page.
  504. // 0 Change the page.
  505. //
  506. //--
  507. /////////////////////////////////////////////////////////////////////////////
  508. LRESULT CBasePropertyPage::OnWizardBack(void)
  509. {
  510. LRESULT lResult;
  511. ASSERT(BWizard());
  512. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  513. lResult = CPropertyPage::OnWizardBack();
  514. if (lResult != -1)
  515. m_bBackPressed = TRUE;
  516. return lResult;
  517. } //*** CBasePropertyPage::OnWizardBack()
  518. /////////////////////////////////////////////////////////////////////////////
  519. //++
  520. //
  521. // CBasePropertyPage::OnWizardNext
  522. //
  523. // Routine Description:
  524. // Handler for the PSN_WIZNEXT message.
  525. //
  526. // Arguments:
  527. // None.
  528. //
  529. // Return Value:
  530. // -1 Don't change the page.
  531. // 0 Change the page.
  532. //
  533. //--
  534. /////////////////////////////////////////////////////////////////////////////
  535. LRESULT CBasePropertyPage::OnWizardNext(void)
  536. {
  537. ASSERT(BWizard());
  538. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  539. // Update the data in the class from the page.
  540. UpdateData(/*bSaveAndValidate*/);
  541. // Save the data in the sheet.
  542. if (!BApplyChanges())
  543. return -1;
  544. // Create the object.
  545. return CPropertyPage::OnWizardNext();
  546. } //*** CBasePropertyPage::OnWizardNext()
  547. /////////////////////////////////////////////////////////////////////////////
  548. //++
  549. //
  550. // CBasePropertyPage::OnWizardFinish
  551. //
  552. // Routine Description:
  553. // Handler for the PSN_WIZFINISH message.
  554. //
  555. // Arguments:
  556. // None.
  557. //
  558. // Return Value:
  559. // FALSE Don't change the page.
  560. // TRUE Change the page.
  561. //
  562. //--
  563. /////////////////////////////////////////////////////////////////////////////
  564. BOOL CBasePropertyPage::OnWizardFinish(void)
  565. {
  566. ASSERT(BWizard());
  567. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  568. // Update the data in the class from the page.
  569. UpdateData(/*bSaveAndValidate*/);
  570. // Save the data in the sheet.
  571. if (!BApplyChanges())
  572. return FALSE;
  573. return CPropertyPage::OnWizardFinish();
  574. } //*** CBasePropertyPage::OnWizardFinish()
  575. /////////////////////////////////////////////////////////////////////////////
  576. //++
  577. //
  578. // CBasePropertyPage::OnChangeCtrl
  579. //
  580. // Routine Description:
  581. // Handler for the messages sent when a control is changed. This
  582. // method can be specified in a message map if all that needs to be
  583. // done is enable the Apply button.
  584. //
  585. // Arguments:
  586. // None.
  587. //
  588. // Return Value:
  589. // None.
  590. //
  591. //--
  592. /////////////////////////////////////////////////////////////////////////////
  593. void CBasePropertyPage::OnChangeCtrl(void)
  594. {
  595. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  596. SetModified(TRUE);
  597. } //*** CBasePropertyPage::OnChangeCtrl()
  598. /////////////////////////////////////////////////////////////////////////////
  599. //++
  600. //
  601. // CBasePropertyPage::EnableNext
  602. //
  603. // Routine Description:
  604. // Enables or disables the NEXT or FINISH button.
  605. //
  606. // Arguments:
  607. // bEnable [IN] TRUE = enable the button, FALSE = disable the button.
  608. //
  609. // Return Value:
  610. // None.
  611. //
  612. //--
  613. /////////////////////////////////////////////////////////////////////////////
  614. void CBasePropertyPage::EnableNext(IN BOOL bEnable /*TRUE*/)
  615. {
  616. ASSERT(BWizard());
  617. ASSERT(PiWizardCallback());
  618. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  619. PiWizardCallback()->EnableNext((LONG *) Hpage(), bEnable);
  620. } //*** CBasePropertyPage::EnableNext()
  621. /////////////////////////////////////////////////////////////////////////////
  622. //++
  623. //
  624. // CBasePropertyPage::BApplyChanges
  625. //
  626. // Routine Description:
  627. // Apply changes made on the page.
  628. //
  629. // Arguments:
  630. // None.
  631. //
  632. // Return Value:
  633. // TRUE Page successfully applied.
  634. // FALSE Error applying page.
  635. //
  636. //--
  637. /////////////////////////////////////////////////////////////////////////////
  638. BOOL CBasePropertyPage::BApplyChanges(void)
  639. {
  640. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  641. DWORD dwStatus = ERROR_SUCCESS;
  642. CClusPropList cpl(BWizard() /*bAlwaysAddProp*/);
  643. // Save data.
  644. {
  645. // Build the property list.
  646. try
  647. {
  648. BuildPropList(cpl);
  649. } // try
  650. catch (CMemoryException * pme)
  651. {
  652. pme->Delete();
  653. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  654. } // catch: CMemoryException
  655. // Set the data.
  656. if (dwStatus == ERROR_SUCCESS)
  657. dwStatus = DwSetPrivateProps(cpl);
  658. // Handle errors.
  659. if (dwStatus != ERROR_SUCCESS)
  660. {
  661. CString strError;
  662. CString strMsg;
  663. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  664. FormatError(strError, dwStatus);
  665. if (dwStatus == ERROR_RESOURCE_PROPERTIES_STORED)
  666. {
  667. AfxMessageBox(strError, MB_OK | MB_ICONEXCLAMATION);
  668. dwStatus = ERROR_SUCCESS;
  669. } // if: properties were stored
  670. else
  671. {
  672. strMsg.FormatMessage(IDS_APPLY_PARAM_CHANGES_ERROR, strError);
  673. AfxMessageBox(strMsg, MB_OK | MB_ICONEXCLAMATION);
  674. return FALSE;
  675. } // else: error setting properties.
  676. } // if: error setting properties
  677. if (dwStatus == ERROR_SUCCESS)
  678. {
  679. // Save new values as previous values.
  680. try
  681. {
  682. DWORD cprop;
  683. const CObjectProperty * pprop;
  684. for (pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop--)
  685. {
  686. switch (pprop->m_propFormat)
  687. {
  688. case CLUSPROP_FORMAT_SZ:
  689. ASSERT(pprop->m_value.pstr != NULL);
  690. ASSERT(pprop->m_valuePrev.pstr != NULL);
  691. *pprop->m_valuePrev.pstr = *pprop->m_value.pstr;
  692. break;
  693. case CLUSPROP_FORMAT_DWORD:
  694. ASSERT(pprop->m_value.pdw != NULL);
  695. ASSERT(pprop->m_valuePrev.pdw != NULL);
  696. *pprop->m_valuePrev.pdw = *pprop->m_value.pdw;
  697. break;
  698. case CLUSPROP_FORMAT_BINARY:
  699. case CLUSPROP_FORMAT_MULTI_SZ:
  700. ASSERT(pprop->m_value.ppb != NULL);
  701. ASSERT(*pprop->m_value.ppb != NULL);
  702. ASSERT(pprop->m_value.pcb != NULL);
  703. ASSERT(pprop->m_valuePrev.ppb != NULL);
  704. ASSERT(*pprop->m_valuePrev.ppb != NULL);
  705. ASSERT(pprop->m_valuePrev.pcb != NULL);
  706. delete [] *pprop->m_valuePrev.ppb;
  707. *pprop->m_valuePrev.ppb = new BYTE[*pprop->m_value.pcb];
  708. CopyMemory(*pprop->m_valuePrev.ppb, *pprop->m_value.ppb, *pprop->m_value.pcb);
  709. *pprop->m_valuePrev.pcb = *pprop->m_value.pcb;
  710. break;
  711. default:
  712. ASSERT(0); // don't know how to deal with this type
  713. } // switch: property format
  714. } // for: each property
  715. } // try
  716. catch (CMemoryException * pme)
  717. {
  718. pme->ReportError();
  719. pme->Delete();
  720. } // catch: CMemoryException
  721. } // if: properties set successfully
  722. } // Save data
  723. return TRUE;
  724. } //*** CBasePropertyPage::BApplyChanges()
  725. /////////////////////////////////////////////////////////////////////////////
  726. //++
  727. //
  728. // CBasePropertyPage::BuildPropList
  729. //
  730. // Routine Description:
  731. // Build the property list.
  732. //
  733. // Arguments:
  734. // rcpl [IN OUT] Cluster property list.
  735. //
  736. // Return Value:
  737. // None.
  738. //
  739. // Exceptions Thrown:
  740. // Any exceptions thrown by CClusPropList::AddProp().
  741. //
  742. //--
  743. /////////////////////////////////////////////////////////////////////////////
  744. void CBasePropertyPage::BuildPropList(
  745. IN OUT CClusPropList & rcpl
  746. )
  747. {
  748. DWORD cprop;
  749. const CObjectProperty * pprop;
  750. for (pprop = Pprops(), cprop = Cprops() ; cprop > 0 ; pprop++, cprop--)
  751. {
  752. switch (pprop->m_propFormat)
  753. {
  754. case CLUSPROP_FORMAT_SZ:
  755. rcpl.AddProp(
  756. pprop->m_pwszName,
  757. *pprop->m_value.pstr,
  758. *pprop->m_valuePrev.pstr
  759. );
  760. break;
  761. case CLUSPROP_FORMAT_DWORD:
  762. rcpl.AddProp(
  763. pprop->m_pwszName,
  764. *pprop->m_value.pdw,
  765. *pprop->m_valuePrev.pdw
  766. );
  767. break;
  768. case CLUSPROP_FORMAT_BINARY:
  769. case CLUSPROP_FORMAT_MULTI_SZ:
  770. rcpl.AddProp(
  771. pprop->m_pwszName,
  772. *pprop->m_value.ppb,
  773. *pprop->m_value.pcb,
  774. *pprop->m_valuePrev.ppb,
  775. *pprop->m_valuePrev.pcb
  776. );
  777. break;
  778. default:
  779. ASSERT(0); // don't know how to deal with this type
  780. return;
  781. } // switch: property format
  782. } // for: each property
  783. } //*** CBasePropertyPage::BuildPropList()
  784. /////////////////////////////////////////////////////////////////////////////
  785. //++
  786. //
  787. // CBasePropertyPage::DwSetPrivateProps
  788. //
  789. // Routine Description:
  790. // Set the private properties for this object.
  791. //
  792. // Arguments:
  793. // rcpl [IN] Property list to set on the object.
  794. //
  795. // Return Value:
  796. // ERROR_SUCCESS The operation was completed successfully.
  797. // !0 Failure.
  798. //
  799. //--
  800. /////////////////////////////////////////////////////////////////////////////
  801. DWORD CBasePropertyPage::DwSetPrivateProps(
  802. IN const CClusPropList & rcpl
  803. )
  804. {
  805. DWORD dwStatus;
  806. DWORD cbProps;
  807. ASSERT(Peo() != NULL);
  808. ASSERT(Peo()->PrdResData());
  809. ASSERT(Peo()->PrdResData()->m_hresource);
  810. if ((rcpl.PbProplist() != NULL) && (rcpl.CbProplist() > 0))
  811. {
  812. // Set private properties.
  813. dwStatus = ClusterResourceControl(
  814. Peo()->PrdResData()->m_hresource,
  815. NULL, // hNode
  816. CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES,
  817. rcpl.PbProplist(),
  818. rcpl.CbProplist(),
  819. NULL, // lpOutBuffer
  820. 0, // nOutBufferSize
  821. &cbProps
  822. );
  823. } // if: there is data to set
  824. else
  825. dwStatus = ERROR_SUCCESS;
  826. return dwStatus;
  827. } //*** CBasePropertyPage::DwSetPrivateProps()
  828. /////////////////////////////////////////////////////////////////////////////
  829. //++
  830. //
  831. // CBasePropertyPage::DwReadValue
  832. //
  833. // Routine Description:
  834. // Read a REG_SZ value for this item.
  835. //
  836. // Arguments:
  837. // pszValueName [IN] Name of the value to read.
  838. // rstrValue [OUT] String in which to return the value.
  839. // hkey [IN] Handle to the registry key to read from.
  840. //
  841. // Return Value:
  842. // dwStatus ERROR_SUCCESS = success, !0 = failure
  843. //
  844. //--
  845. /////////////////////////////////////////////////////////////////////////////
  846. DWORD CBasePropertyPage::DwReadValue(
  847. IN LPCTSTR pszValueName,
  848. OUT CString & rstrValue,
  849. IN HKEY hkey
  850. )
  851. {
  852. DWORD dwStatus;
  853. LPWSTR pwszValue = NULL;
  854. DWORD dwValueLen;
  855. DWORD dwValueType;
  856. ASSERT(pszValueName != NULL);
  857. ASSERT(hkey != NULL);
  858. rstrValue.Empty();
  859. try
  860. {
  861. // Get the size of the value.
  862. dwValueLen = 0;
  863. dwStatus = ::ClusterRegQueryValue(
  864. hkey,
  865. pszValueName,
  866. &dwValueType,
  867. NULL,
  868. &dwValueLen
  869. );
  870. if ((dwStatus == ERROR_SUCCESS) || (dwStatus == ERROR_MORE_DATA))
  871. {
  872. ASSERT(dwValueType == REG_SZ);
  873. // Allocate enough space for the data.
  874. pwszValue = rstrValue.GetBuffer(dwValueLen / sizeof(WCHAR));
  875. ASSERT(pwszValue != NULL);
  876. dwValueLen += 1 * sizeof(WCHAR); // Don't forget the final null-terminator.
  877. // Read the value.
  878. dwStatus = ::ClusterRegQueryValue(
  879. hkey,
  880. pszValueName,
  881. &dwValueType,
  882. (LPBYTE) pwszValue,
  883. &dwValueLen
  884. );
  885. if (dwStatus == ERROR_SUCCESS)
  886. {
  887. ASSERT(dwValueType == REG_SZ);
  888. } // if: value read successfully
  889. rstrValue.ReleaseBuffer();
  890. } // if: got the size successfully
  891. } // try
  892. catch (CMemoryException * pme)
  893. {
  894. pme->Delete();
  895. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  896. } // catch: CMemoryException
  897. return dwStatus;
  898. } //*** CBasePropertyPage::DwReadValue(LPCTSTR, CString&)
  899. /////////////////////////////////////////////////////////////////////////////
  900. //++
  901. //
  902. // CBasePropertyPage::DwReadValue
  903. //
  904. // Routine Description:
  905. // Read a REG_DWORD value for this item.
  906. //
  907. // Arguments:
  908. // pszValueName [IN] Name of the value to read.
  909. // pdwValue [OUT] DWORD in which to return the value.
  910. // hkey [IN] Handle to the registry key to read from.
  911. //
  912. // Return Value:
  913. // dwStatus ERROR_SUCCESS = success, !0 = failure
  914. //
  915. //--
  916. /////////////////////////////////////////////////////////////////////////////
  917. DWORD CBasePropertyPage::DwReadValue(
  918. IN LPCTSTR pszValueName,
  919. OUT DWORD * pdwValue,
  920. IN HKEY hkey
  921. )
  922. {
  923. DWORD dwStatus;
  924. DWORD dwValue;
  925. DWORD dwValueLen;
  926. DWORD dwValueType;
  927. ASSERT(pszValueName != NULL);
  928. ASSERT(pdwValue != NULL);
  929. ASSERT(hkey != NULL);
  930. *pdwValue = 0;
  931. // Read the value.
  932. dwValueLen = sizeof(dwValue);
  933. dwStatus = ::ClusterRegQueryValue(
  934. hkey,
  935. pszValueName,
  936. &dwValueType,
  937. (LPBYTE) &dwValue,
  938. &dwValueLen
  939. );
  940. if (dwStatus == ERROR_SUCCESS)
  941. {
  942. ASSERT(dwValueType == REG_DWORD);
  943. ASSERT(dwValueLen == sizeof(dwValue));
  944. *pdwValue = dwValue;
  945. } // if: value read successfully
  946. return dwStatus;
  947. } //*** CBasePropertyPage::DwReadValue(LPCTSTR, DWORD*)
  948. /////////////////////////////////////////////////////////////////////////////
  949. //++
  950. //
  951. // CBasePropertyPage::DwReadValue
  952. //
  953. // Routine Description:
  954. // Read a REG_BINARY value for this item.
  955. //
  956. // Arguments:
  957. // pszValueName [IN] Name of the value to read.
  958. // ppbValue [OUT] Pointer in which to return the data. Caller
  959. // is responsible for deallocating the data.
  960. // hkey [IN] Handle to the registry key to read from.
  961. //
  962. // Return Value:
  963. // dwStatus ERROR_SUCCESS = success, !0 = failure
  964. //
  965. //--
  966. /////////////////////////////////////////////////////////////////////////////
  967. DWORD CBasePropertyPage::DwReadValue(
  968. IN LPCTSTR pszValueName,
  969. OUT LPBYTE * ppbValue,
  970. IN HKEY hkey
  971. )
  972. {
  973. DWORD dwStatus;
  974. DWORD dwValueLen;
  975. DWORD dwValueType;
  976. ASSERT(pszValueName != NULL);
  977. ASSERT(ppbValue != NULL);
  978. ASSERT(hkey != NULL);
  979. *ppbValue = NULL;
  980. // Get the length of the value.
  981. dwValueLen = 0;
  982. dwStatus = ::ClusterRegQueryValue(
  983. hkey,
  984. pszValueName,
  985. &dwValueType,
  986. NULL,
  987. &dwValueLen
  988. );
  989. if (dwStatus != ERROR_MORE_DATA)
  990. return dwStatus;
  991. ASSERT(dwValueType == REG_BINARY);
  992. // Allocate a buffer,
  993. try
  994. {
  995. *ppbValue = new BYTE[dwValueLen];
  996. } // try
  997. catch (CMemoryException *)
  998. {
  999. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1000. return dwStatus;
  1001. } // catch: CMemoryException
  1002. // Read the value.
  1003. dwStatus = ::ClusterRegQueryValue(
  1004. hkey,
  1005. pszValueName,
  1006. &dwValueType,
  1007. *ppbValue,
  1008. &dwValueLen
  1009. );
  1010. if (dwStatus != ERROR_SUCCESS)
  1011. {
  1012. delete [] *ppbValue;
  1013. *ppbValue = NULL;
  1014. } // if: value read successfully
  1015. return dwStatus;
  1016. } //*** CBasePropertyPage::DwReadValue(LPCTSTR, LPBYTE)
  1017. /////////////////////////////////////////////////////////////////////////////
  1018. //++
  1019. //
  1020. // CBasePropertyPage::DwWriteValue
  1021. //
  1022. // Routine Description:
  1023. // Write a REG_SZ value for this item if it hasn't changed.
  1024. //
  1025. // Arguments:
  1026. // pszValueName [IN] Name of the value to write.
  1027. // rstrValue [IN] Value data.
  1028. // rstrPrevValue [IN OUT] Previous value.
  1029. // hkey [IN] Handle to the registry key to write to.
  1030. //
  1031. // Return Value:
  1032. // dwStatus
  1033. //
  1034. //--
  1035. /////////////////////////////////////////////////////////////////////////////
  1036. DWORD CBasePropertyPage::DwWriteValue(
  1037. IN LPCTSTR pszValueName,
  1038. IN const CString & rstrValue,
  1039. IN OUT CString & rstrPrevValue,
  1040. IN HKEY hkey
  1041. )
  1042. {
  1043. DWORD dwStatus;
  1044. ASSERT(pszValueName != NULL);
  1045. ASSERT(hkey != NULL);
  1046. // Write the value if it hasn't changed.
  1047. if (rstrValue != rstrPrevValue)
  1048. {
  1049. dwStatus = ::ClusterRegSetValue(
  1050. hkey,
  1051. pszValueName,
  1052. REG_SZ,
  1053. (CONST BYTE *) (LPCTSTR) rstrValue,
  1054. (rstrValue.GetLength() + 1) * sizeof(TCHAR)
  1055. );
  1056. if (dwStatus == ERROR_SUCCESS)
  1057. rstrPrevValue = rstrValue;
  1058. } // if: value changed
  1059. else
  1060. dwStatus = ERROR_SUCCESS;
  1061. return dwStatus;
  1062. } //*** CBasePropertyPage::DwWriteValue(LPCTSTR, CString&)
  1063. /////////////////////////////////////////////////////////////////////////////
  1064. //++
  1065. //
  1066. // CBasePropertyPage::DwWriteValue
  1067. //
  1068. // Routine Description:
  1069. // Write a REG_DWORD value for this item if it hasn't changed.
  1070. //
  1071. // Arguments:
  1072. // pszValueName [IN] Name of the value to write.
  1073. // dwValue [IN] Value data.
  1074. // pdwPrevValue [IN OUT] Previous value.
  1075. // hkey [IN] Handle to the registry key to write to.
  1076. //
  1077. // Return Value:
  1078. // dwStatus
  1079. //
  1080. //--
  1081. /////////////////////////////////////////////////////////////////////////////
  1082. DWORD CBasePropertyPage::DwWriteValue(
  1083. IN LPCTSTR pszValueName,
  1084. IN DWORD dwValue,
  1085. IN OUT DWORD * pdwPrevValue,
  1086. IN HKEY hkey
  1087. )
  1088. {
  1089. DWORD dwStatus;
  1090. ASSERT(pszValueName != NULL);
  1091. ASSERT(pdwPrevValue != NULL);
  1092. ASSERT(hkey != NULL);
  1093. // Write the value if it hasn't changed.
  1094. if (dwValue != *pdwPrevValue)
  1095. {
  1096. dwStatus = ::ClusterRegSetValue(
  1097. hkey,
  1098. pszValueName,
  1099. REG_DWORD,
  1100. (CONST BYTE *) &dwValue,
  1101. sizeof(dwValue)
  1102. );
  1103. if (dwStatus == ERROR_SUCCESS)
  1104. *pdwPrevValue = dwValue;
  1105. } // if: value changed
  1106. else
  1107. dwStatus = ERROR_SUCCESS;
  1108. return dwStatus;
  1109. } //*** CBasePropertyPage::DwWriteValue(LPCTSTR, DWORD)
  1110. /////////////////////////////////////////////////////////////////////////////
  1111. //++
  1112. //
  1113. // CBasePropertyPage::DwWriteValue
  1114. //
  1115. // Routine Description:
  1116. // Write a REG_BINARY value for this item if it hasn't changed.
  1117. //
  1118. // Arguments:
  1119. // pszValueName [IN] Name of the value to write.
  1120. // pbValue [IN] Value data.
  1121. // cbValue [IN] Size of value data.
  1122. // ppbPrevValue [IN OUT] Previous value.
  1123. // cbPrevValue [IN] Size of the previous data.
  1124. // hkey [IN] Handle to the registry key to write to.
  1125. //
  1126. // Return Value:
  1127. // dwStatus
  1128. //
  1129. //--
  1130. /////////////////////////////////////////////////////////////////////////////
  1131. DWORD CBasePropertyPage::DwWriteValue(
  1132. IN LPCTSTR pszValueName,
  1133. IN const LPBYTE pbValue,
  1134. IN DWORD cbValue,
  1135. IN OUT LPBYTE * ppbPrevValue,
  1136. IN DWORD cbPrevValue,
  1137. IN HKEY hkey
  1138. )
  1139. {
  1140. DWORD dwStatus;
  1141. LPBYTE pbPrevValue = NULL;
  1142. ASSERT(pszValueName != NULL);
  1143. ASSERT(pbValue != NULL);
  1144. ASSERT(ppbPrevValue != NULL);
  1145. ASSERT(cbValue > 0);
  1146. ASSERT(hkey != NULL);
  1147. // See if the data has changed.
  1148. if (cbValue == cbPrevValue)
  1149. {
  1150. if (memcmp(pbValue, *ppbPrevValue, cbValue) == 0)
  1151. return ERROR_SUCCESS;
  1152. } // if: lengths are the same
  1153. // Allocate a new buffer for the previous data pointer.
  1154. try
  1155. {
  1156. pbPrevValue = new BYTE[cbValue];
  1157. }
  1158. catch (CMemoryException *)
  1159. {
  1160. return ERROR_NOT_ENOUGH_MEMORY;
  1161. } // catch: CMemoryException
  1162. ::CopyMemory(pbPrevValue, pbValue, cbValue);
  1163. // Write the value if it hasn't changed.
  1164. dwStatus = ::ClusterRegSetValue(
  1165. hkey,
  1166. pszValueName,
  1167. REG_BINARY,
  1168. pbValue,
  1169. cbValue
  1170. );
  1171. if (dwStatus == ERROR_SUCCESS)
  1172. {
  1173. delete [] *ppbPrevValue;
  1174. *ppbPrevValue = pbPrevValue;
  1175. } // if: set was successful
  1176. else
  1177. delete [] pbPrevValue;
  1178. return dwStatus;
  1179. } //*** CBasePropertyPage::DwWriteValue(LPCTSTR, const LPBYTE)
  1180. /////////////////////////////////////////////////////////////////////////////
  1181. //++
  1182. //
  1183. // CBasePropertyPage::OnContextMenu
  1184. //
  1185. // Routine Description:
  1186. // Handler for the WM_CONTEXTMENU message.
  1187. //
  1188. // Arguments:
  1189. // pWnd Window in which user clicked the right mouse button.
  1190. // point Position of the cursor, in screen coordinates.
  1191. //
  1192. // Return Value:
  1193. // TRUE Help processed.
  1194. // FALSE Help not processed.
  1195. //
  1196. //--
  1197. /////////////////////////////////////////////////////////////////////////////
  1198. void CBasePropertyPage::OnContextMenu(CWnd * pWnd, CPoint point)
  1199. {
  1200. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1201. m_dlghelp.OnContextMenu(pWnd, point);
  1202. } //*** CBasePropertyPage::OnContextMenu()
  1203. /////////////////////////////////////////////////////////////////////////////
  1204. //++
  1205. //
  1206. // CBasePropertyPage::OnHelpInfo
  1207. //
  1208. // Routine Description:
  1209. // Handler for the WM_HELPINFO message.
  1210. //
  1211. // Arguments:
  1212. // pHelpInfo Structure containing info about displaying help.
  1213. //
  1214. // Return Value:
  1215. // TRUE Help processed.
  1216. // FALSE Help not processed.
  1217. //
  1218. //--
  1219. /////////////////////////////////////////////////////////////////////////////
  1220. BOOL CBasePropertyPage::OnHelpInfo(HELPINFO * pHelpInfo)
  1221. {
  1222. BOOL bProcessed;
  1223. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1224. bProcessed = m_dlghelp.OnHelpInfo(pHelpInfo);
  1225. if (!bProcessed)
  1226. bProcessed = CDialog::OnHelpInfo(pHelpInfo);
  1227. return bProcessed;
  1228. } //*** CBasePropertyPage::OnHelpInfo()
  1229. /////////////////////////////////////////////////////////////////////////////
  1230. //++
  1231. //
  1232. // CBasePropertyPage::OnCommandHelp
  1233. //
  1234. // Routine Description:
  1235. // Handler for the WM_COMMANDHELP message.
  1236. //
  1237. // Arguments:
  1238. // wParam [IN] WPARAM.
  1239. // lParam [IN] LPARAM.
  1240. //
  1241. // Return Value:
  1242. // TRUE Help processed.
  1243. // FALSE Help not processed.
  1244. //
  1245. //--
  1246. /////////////////////////////////////////////////////////////////////////////
  1247. LRESULT CBasePropertyPage::OnCommandHelp(WPARAM wParam, LPARAM lParam)
  1248. {
  1249. BOOL bProcessed;
  1250. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1251. bProcessed = (BOOL)m_dlghelp.OnCommandHelp(wParam, lParam);
  1252. if (!bProcessed)
  1253. bProcessed = (BOOL)CDialog::OnCommandHelp(wParam, lParam);
  1254. return bProcessed;
  1255. } //*** CBasePropertyPage::OnCommandHelp()