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.

906 lines
21 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name :
  4. idlg.cpp
  5. Abstract:
  6. Inheritance Dialog
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "common.h"
  18. #include "iisdebug.h"
  19. #include "idlg.h"
  20. #ifdef _DEBUG
  21. #undef THIS_FILE
  22. static char BASED_CODE THIS_FILE[] = __FILE__;
  23. #endif
  24. #define new DEBUG_NEW
  25. extern HINSTANCE hDLLInstance;
  26. //
  27. // Inheritance dialog
  28. //
  29. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  30. CInheritanceDlg::CInheritanceDlg(
  31. IN DWORD dwMetaID,
  32. IN BOOL fWrite,
  33. IN CComAuthInfo * pAuthInfo, OPTIONAL
  34. IN LPCTSTR lpstrMetaRoot,
  35. IN CStringList & strlMetaChildNodes,
  36. IN LPCTSTR lpstrPropertyName, OPTIONAL
  37. IN CWnd * pParent OPTIONAL
  38. )
  39. /*++
  40. Routine Description:
  41. Inheritance dialog constructor. This constructor assumes GetDataPaths()
  42. has already been called.
  43. Arguments:
  44. DWORD dwMetaID : Meta ID
  45. BOOL fWrite : TRUE from write, FALSE from delete
  46. CIISServer * pAuthInfo : Auth info object or NULL
  47. LPCTSTR lpstrMetaRoot : Meta root
  48. CStringList & strlMetaChildNodes : List of child nodes from GetDataPaths
  49. LPCTSTR lpstrPropertyName : Optional text string for the property
  50. CWnd * pParent : Optional parent window
  51. Return Value:
  52. None
  53. --*/
  54. : m_fWrite(fWrite),
  55. m_fEmpty(TRUE),
  56. m_fUseTable(TRUE),
  57. m_strMetaRoot(lpstrMetaRoot),
  58. m_strPropertyName(lpstrPropertyName ? lpstrPropertyName : _T("")),
  59. m_mk(pAuthInfo),
  60. CDialog(CInheritanceDlg::IDD, pParent)
  61. {
  62. m_strlMetaChildNodes = strlMetaChildNodes;
  63. VERIFY(CMetaKey::GetMDFieldDef(
  64. dwMetaID,
  65. m_dwMDIdentifier,
  66. m_dwMDAttributes,
  67. m_dwMDUserType,
  68. m_dwMDDataType
  69. ));
  70. Initialize();
  71. }
  72. CInheritanceDlg::CInheritanceDlg(
  73. IN DWORD dwMetaID,
  74. IN BOOL fWrite,
  75. IN CComAuthInfo * pAuthInfo, OPTIONAL
  76. IN LPCTSTR lpstrMetaRoot,
  77. IN LPCTSTR lpstrPropertyName, OPTIONAL
  78. IN CWnd * pParent OPTIONAL
  79. )
  80. /*++
  81. Routine Description:
  82. Inheritance dialog constructor. This constructor will call GetDataPaths().
  83. Arguments:
  84. DWORD dwMetaID : Meta ID
  85. BOOL fWrite : TRUE from write, FALSE from delete
  86. CComAuthInfo * pAuthInfo : Auth info or NULL
  87. LPCTSTR lpstrMetaRoot : Meta root
  88. LPCTSTR lpstrPropertyName : Optional text string for the property
  89. CWnd * pParent : Optional parent window
  90. Return Value:
  91. None
  92. --*/
  93. : m_fWrite(fWrite),
  94. m_fEmpty(TRUE),
  95. m_fUseTable(TRUE),
  96. m_strMetaRoot(lpstrMetaRoot),
  97. m_strlMetaChildNodes(),
  98. m_strPropertyName(lpstrPropertyName ? lpstrPropertyName : _T("")),
  99. m_mk(pAuthInfo),
  100. CDialog(CInheritanceDlg::IDD, pParent)
  101. {
  102. //
  103. // Specify the resources to use
  104. //
  105. HINSTANCE hOldRes = AfxGetResourceHandle();
  106. AfxSetResourceHandle(hDLLInstance);
  107. VERIFY(CMetaKey::GetMDFieldDef(
  108. dwMetaID,
  109. m_dwMDIdentifier,
  110. m_dwMDAttributes,
  111. m_dwMDUserType,
  112. m_dwMDDataType
  113. ));
  114. //
  115. // Need to do our own GetDataPaths()
  116. //
  117. CError err(GetDataPaths());
  118. if (!err.MessageBoxOnFailure(m_hWnd))
  119. {
  120. Initialize();
  121. }
  122. //
  123. // Restore the resources
  124. //
  125. AfxSetResourceHandle(hOldRes);
  126. }
  127. CInheritanceDlg::CInheritanceDlg(
  128. IN BOOL fTryToFindInTable,
  129. IN DWORD dwMDIdentifier,
  130. IN DWORD dwMDAttributes,
  131. IN DWORD dwMDUserType,
  132. IN DWORD dwMDDataType,
  133. IN LPCTSTR lpstrPropertyName,
  134. IN BOOL fWrite,
  135. IN CComAuthInfo * pAuthInfo, OPTIONAL
  136. IN LPCTSTR lpstrMetaRoot,
  137. IN CWnd * pParent OPTIONAL
  138. )
  139. /*++
  140. Routine Description:
  141. Inheritance dialog constructor. This constructor will call GetDataPaths(),
  142. and will use the specified parameters if the property ID does not exist
  143. in the property table
  144. Arguments:
  145. BOOL fTryToFindInTable : If TRUE, first look in table
  146. DWORD dwMDIdentifier : Metadata identifier
  147. DWORD dwMDAttributes : Metadata attributes
  148. DWORD dwMDUserType : Metadata user type
  149. DWORD dwMDDataType : Metadata data type
  150. LPCTSTR lpstrPropertyName : Text string for the property
  151. BOOL fWrite : TRUE from write, FALSE from delete
  152. CComAuthInfo * pAuthInfo : Authentication info or NULL.
  153. LPCTSTR lpstrMetaRoot : Meta root
  154. CWnd * pParent : Optional parent window
  155. Return Value:
  156. None
  157. --*/
  158. : m_fWrite(fWrite),
  159. m_fEmpty(TRUE),
  160. m_fUseTable(FALSE),
  161. m_strMetaRoot(lpstrMetaRoot),
  162. m_strlMetaChildNodes(),
  163. m_mk(pAuthInfo),
  164. CDialog(CInheritanceDlg::IDD, pParent)
  165. {
  166. //
  167. // Specify the resources to use
  168. //
  169. HINSTANCE hOldRes = AfxGetResourceHandle();
  170. AfxSetResourceHandle(hDLLInstance);
  171. if (fTryToFindInTable && !CMetaKey::GetMDFieldDef(
  172. dwMDIdentifier,
  173. m_dwMDIdentifier,
  174. m_dwMDAttributes,
  175. m_dwMDUserType,
  176. m_dwMDDataType
  177. ))
  178. {
  179. //
  180. // Did not exist in the table, use specified parameters
  181. //
  182. m_dwMDIdentifier = dwMDIdentifier;
  183. m_dwMDAttributes = dwMDAttributes;
  184. m_dwMDUserType = dwMDUserType;
  185. m_dwMDDataType = dwMDDataType;
  186. m_strPropertyName = lpstrPropertyName;
  187. }
  188. //
  189. // Need to do our own GetDataPaths()
  190. //
  191. CError err(GetDataPaths());
  192. if (!err.MessageBoxOnFailure(m_hWnd))
  193. {
  194. Initialize();
  195. }
  196. //
  197. // Restore the resources
  198. //
  199. AfxSetResourceHandle(hOldRes);
  200. }
  201. HRESULT
  202. CInheritanceDlg::GetDataPaths()
  203. /*++
  204. Routine Description:
  205. GetDataPaths()
  206. Arguments:
  207. None
  208. Return Value:
  209. HRESULT
  210. --*/
  211. {
  212. //ASSERT(!m_strServer.IsEmpty());
  213. CError err(m_mk.QueryResult());
  214. if (err.Succeeded())
  215. {
  216. err = m_mk.GetDataPaths(
  217. m_strlMetaChildNodes,
  218. m_dwMDIdentifier,
  219. m_dwMDDataType,
  220. m_strMetaRoot
  221. );
  222. }
  223. return err;
  224. }
  225. void
  226. CInheritanceDlg::Initialize()
  227. /*++
  228. Routine Description:
  229. Initialize data members. Set the m_fEmpty flag to determine if
  230. it is necessary to proceed.
  231. Arguments:
  232. None
  233. Return Value:
  234. None
  235. --*/
  236. {
  237. //{{AFX_DATA_INIT(CInheritanceDlg)
  238. //}}AFX_DATA_INIT
  239. CMetabasePath::CleanMetaPath(m_strMetaRoot);
  240. if (m_fUseTable && !CMetaKey::IsPropertyInheritable(m_dwMDIdentifier))
  241. {
  242. //
  243. // No point in displaying non-inheritable properties
  244. //
  245. return;
  246. }
  247. switch(m_dwMDIdentifier)
  248. {
  249. //
  250. // Ignore these properties, even though they are inheritable
  251. //
  252. case MD_VR_PATH:
  253. case MD_DOWNLEVEL_ADMIN_INSTANCE:
  254. case MD_APP_ISOLATED:
  255. case MD_APP_FRIENDLY_NAME:
  256. return;
  257. }
  258. //
  259. // Check to see if the current metabase path contains an instance
  260. //
  261. CString strTmp;
  262. m_fHasInstanceInMaster = FriendlyInstance(m_strMetaRoot, strTmp);
  263. //
  264. // If property name was not specified in the constructor, load default
  265. // one from table.
  266. //
  267. if (m_strPropertyName.IsEmpty())
  268. {
  269. ASSERT(m_fUseTable);
  270. //
  271. // Specify the resources to use
  272. //
  273. HINSTANCE hOldRes = AfxGetResourceHandle();
  274. AfxSetResourceHandle(hDLLInstance);
  275. VERIFY(CMetaKey::GetPropertyDescription(
  276. m_dwMDIdentifier,
  277. m_strPropertyName
  278. ));
  279. AfxSetResourceHandle(hOldRes);
  280. }
  281. //
  282. // Go through the list of metapaths, and clean them
  283. // up.
  284. //
  285. POSITION pos = m_strlMetaChildNodes.GetHeadPosition();
  286. while(pos)
  287. {
  288. CString & strMetaPath = m_strlMetaChildNodes.GetNext(pos);
  289. CMetabasePath::CleanMetaPath(strMetaPath);
  290. }
  291. //
  292. // If the special info key (lm/service/info) is in the list, remove it.
  293. // We only need to this if the key that is getting the
  294. // change (m_strMetaRoot) is the service master property (lm/service).
  295. // If it is anything else, then the special "info" key cannot be below
  296. // it so we don't need to check. Thus the first test is to see if there
  297. // is only one "/" character. If there is only one, then we know it is
  298. // the service and we can go ahead and do the test. In some ways,
  299. // mfc is a pain, so we limited to the CString methods to do this
  300. // copy the root into the temp string.
  301. //
  302. int iSlash = m_strMetaRoot.ReverseFind(SZ_MBN_SEP_CHAR);
  303. if (iSlash >= 0)
  304. {
  305. strTmp = m_strMetaRoot.Left(iSlash);
  306. //
  307. // Now make sure that there aren't any more slashes
  308. //
  309. if (strTmp.Find(SZ_MBN_SEP_CHAR) == -1)
  310. {
  311. //
  312. // Now build the path to the special info key by adding it
  313. // to the meta root
  314. //
  315. strTmp = m_strMetaRoot + SZ_MBN_SEP_CHAR + IIS_MD_SVC_INFO_PATH;
  316. TRACEEOLID("Removing any descendants of " << strTmp);
  317. //
  318. // Search the list for the info key and remove it if we find it
  319. //
  320. pos = m_strlMetaChildNodes.GetHeadPosition();
  321. while(pos)
  322. {
  323. POSITION pos2 = pos;
  324. CString & strMetaPath = m_strlMetaChildNodes.GetNext(pos);
  325. TRACEEOLID("Checking " << strMetaPath);
  326. if (strTmp.CompareNoCase(
  327. strMetaPath.Left(strTmp.GetLength())) == 0)
  328. {
  329. TRACEEOLID("Removing service/info metapath from list");
  330. m_strlMetaChildNodes.RemoveAt(pos2);
  331. }
  332. }
  333. }
  334. }
  335. //
  336. // Remove the first item if it's the current metapath
  337. //
  338. pos = m_strlMetaChildNodes.GetHeadPosition();
  339. if (pos)
  340. {
  341. TRACEEOLID("Stripping " << m_strMetaRoot);
  342. CString & strMetaPath = m_strlMetaChildNodes.GetAt(pos);
  343. if (strMetaPath.CompareNoCase(m_strMetaRoot) == 0)
  344. {
  345. TRACEEOLID("Removing current metapath from list");
  346. m_strlMetaChildNodes.RemoveHead();
  347. }
  348. }
  349. TRACEEOLID("ID=" << m_dwMDIdentifier << " Prop=" << m_strPropertyName);
  350. m_fEmpty = m_strlMetaChildNodes.GetCount() == 0;
  351. }
  352. /* virtual */
  353. INT_PTR
  354. //int
  355. CInheritanceDlg::DoModal()
  356. /*++
  357. Routine Description:
  358. Display the dialog.
  359. Arguments:
  360. None
  361. Return Value:
  362. IDOK if the OK button was pressed, IDCANCEL otherwise.
  363. --*/
  364. {
  365. //
  366. // Specify the resources to use
  367. //
  368. HINSTANCE hOldRes = AfxGetResourceHandle();
  369. AfxSetResourceHandle(hDLLInstance);
  370. INT_PTR answer = CDialog::DoModal();
  371. //
  372. // restore the resources
  373. //
  374. AfxSetResourceHandle(hOldRes);
  375. return answer;
  376. }
  377. void
  378. CInheritanceDlg::DoDataExchange(
  379. IN CDataExchange * pDX
  380. )
  381. /*++
  382. Routine Description:
  383. Initialise/Store control data
  384. Arguments:
  385. CDataExchange * pDX - DDX/DDV control structure
  386. Return Value:
  387. None
  388. --*/
  389. {
  390. CDialog::DoDataExchange(pDX);
  391. //{{AFX_DATA_MAP(CInheritanceDlg)
  392. DDX_Control(pDX, IDC_LIST_CHILD_NODES, m_list_ChildNodes);
  393. //}}AFX_DATA_MAP
  394. }
  395. //
  396. // Message Map
  397. //
  398. BEGIN_MESSAGE_MAP(CInheritanceDlg, CDialog)
  399. //{{AFX_MSG_MAP(CInheritanceDlg)
  400. ON_BN_CLICKED(IDC_BUTTON_SELECT_ALL, OnButtonSelectAll)
  401. ON_BN_CLICKED(ID_HELP, OnHelp)
  402. //}}AFX_MSG_MAP
  403. END_MESSAGE_MAP()
  404. BOOL
  405. CInheritanceDlg::FriendlyInstance(
  406. IN CString & strMetaRoot,
  407. OUT CString & strFriendly
  408. )
  409. /*++
  410. Routine Description:
  411. Replace the instance number with its descriptive name.
  412. Arguments:
  413. CString & strMetaRoot : Metabase path
  414. CString & strFriendly : Converted output friendly path.
  415. Return Value:
  416. TRUE if the path contained an instance number.
  417. --*/
  418. {
  419. //
  420. // Break into fields
  421. //
  422. // CODEWORK: make static like BuildMetaPath
  423. //
  424. LPCTSTR lp = _tcschr(strMetaRoot, SZ_MBN_SEP_CHAR); // lm
  425. if (lp != NULL)
  426. {
  427. LPCTSTR lp2 = lp;
  428. CString strService(++lp2);
  429. lp = _tcschr(++lp, SZ_MBN_SEP_CHAR); // service name
  430. if (lp == NULL)
  431. {
  432. //
  433. // Master Instance (can never be a descendant)
  434. //
  435. //strFriendly = m_strWebMaster;
  436. return FALSE;
  437. }
  438. else
  439. {
  440. strService.ReleaseBuffer(DIFF(lp - lp2));
  441. }
  442. TRACEEOLID(strService);
  443. CString keyType;
  444. HRESULT hr = m_mk.Open(METADATA_PERMISSION_READ, strMetaRoot);
  445. if (SUCCEEDED(hr))
  446. {
  447. hr = m_mk.QueryValue(MD_KEY_TYPE, keyType);
  448. if (FAILED(hr))
  449. {
  450. return FALSE;
  451. }
  452. else
  453. {
  454. // Succeeded,
  455. // but check if this is a keytype that
  456. // we want to get the friendlyname for
  457. if (
  458. 0 == keyType.CompareNoCase(IIS_CLASS_WEB_SERVER_W)
  459. && 0 == keyType.CompareNoCase(IIS_CLASS_FTP_SERVER_W)
  460. && 0 == keyType.CompareNoCase(IIS_CLASS_WEB_VDIR_W)
  461. && 0 == keyType.CompareNoCase(IIS_CLASS_WEB_DIR_W)
  462. && 0 == keyType.CompareNoCase(IIS_CLASS_WEB_FILE_W)
  463. && 0 == keyType.CompareNoCase(IIS_CLASS_FTP_VDIR_W)
  464. )
  465. {
  466. return FALSE;
  467. }
  468. }
  469. m_mk.Close();
  470. }
  471. DWORD dwInstance = _ttol(++lp);
  472. TRACEEOLID(dwInstance);
  473. lp = _tcschr(lp, SZ_MBN_SEP_CHAR); // Instance #
  474. BOOL bThisIsTheRootDir = FALSE;
  475. if (lp != NULL)
  476. {
  477. lp = _tcschr(++lp, SZ_MBN_SEP_CHAR); // Skip "ROOT"
  478. if (!lp)
  479. {
  480. bThisIsTheRootDir = TRUE;
  481. }
  482. }
  483. hr = m_mk.Open(
  484. METADATA_PERMISSION_READ,
  485. CMetabasePath(strService, dwInstance)
  486. );
  487. if (SUCCEEDED(hr))
  488. {
  489. CString strComment;
  490. hr = m_mk.QueryValue(MD_SERVER_COMMENT, strComment);
  491. m_mk.Close();
  492. if (FAILED(hr) || strComment.IsEmpty())
  493. {
  494. strFriendly.Format(
  495. SZ_MBN_MACHINE SZ_MBN_SEP_STR _T("%s") SZ_MBN_SEP_STR _T("%d"),
  496. (LPCTSTR)strService,
  497. dwInstance
  498. );
  499. }
  500. else
  501. {
  502. strFriendly.Format(
  503. SZ_MBN_MACHINE SZ_MBN_SEP_STR _T("%s") SZ_MBN_SEP_STR _T("%s"),
  504. (LPCTSTR)strService,
  505. (LPCTSTR)strComment
  506. );
  507. }
  508. TRACEEOLID(strFriendly);
  509. //
  510. // Append the rest of the path
  511. //
  512. if (lp != NULL)
  513. {
  514. strFriendly += lp;
  515. }
  516. else
  517. {
  518. if (bThisIsTheRootDir)
  519. {
  520. strFriendly += SZ_MBN_SEP_CHAR;
  521. }
  522. }
  523. return TRUE;
  524. }
  525. }
  526. return FALSE;
  527. }
  528. CString &
  529. CInheritanceDlg::CleanDescendantPath(
  530. IN OUT CString & strMetaPath
  531. )
  532. /*++
  533. Routine Description:
  534. Clean the descendant metabase path. The path is shown
  535. as a descendant of the current metabase root, and instance
  536. numbers are replaced with their description names.
  537. Arguments:
  538. CString & strMetaPath : Metabase path to be treated
  539. Return Value:
  540. Reference to the cleaned-up path.
  541. --*/
  542. {
  543. //
  544. // This better be a descendant!
  545. //
  546. ASSERT(strMetaPath.GetLength() >= m_strMetaRoot.GetLength());
  547. ASSERT(!::_tcsnicmp(strMetaPath, m_strMetaRoot, m_strMetaRoot.GetLength()));
  548. // we do care only about something below LM
  549. CString machine_path;
  550. CMetabasePath::GetMachinePath(strMetaPath, machine_path);
  551. if (machine_path.CompareNoCase(SZ_MBN_MACHINE) == 0)
  552. {
  553. if (!m_fHasInstanceInMaster)
  554. {
  555. //
  556. // Need to replace the instance number with the friendly
  557. // name.
  558. //
  559. CString strTmp;
  560. if (FriendlyInstance(strMetaPath, strTmp))
  561. {
  562. strMetaPath = strTmp;
  563. }
  564. }
  565. strMetaPath = strMetaPath.Mid(m_strMetaRoot.GetLength() + 1);
  566. }
  567. return strMetaPath;
  568. }
  569. //
  570. // Message Handlers
  571. //
  572. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  573. BOOL
  574. CInheritanceDlg::OnInitDialog()
  575. /*++
  576. Routine Description:
  577. WM_INITDIALOG handler. Initialize the dialog.
  578. Arguments:
  579. None.
  580. Return Value:
  581. TRUE if focus is to be set automatically, FALSE if the focus
  582. is already set.
  583. --*/
  584. {
  585. CDialog::OnInitDialog();
  586. //
  587. // Get friendly name for the property, and set the text.
  588. //
  589. CString strPrompt;
  590. CComBSTR bstrFmt;
  591. VERIFY(bstrFmt.LoadString(hDLLInstance, IDS_INHERITANCE_PROMPT));
  592. strPrompt.Format(bstrFmt, (LPCTSTR)m_strPropertyName);
  593. GetDlgItem(IDC_STATIC_PROMPT)->SetWindowText(strPrompt);
  594. //
  595. // Turn inherited nodes into friendly paths, and add them
  596. // to the listbox. Note the "current" node should have been
  597. // deleted at this stage.
  598. //
  599. POSITION pos = m_strlMetaChildNodes.GetHeadPosition();
  600. while(pos)
  601. {
  602. CString strNode = m_strlMetaChildNodes.GetNext(pos);
  603. m_list_ChildNodes.AddString(CleanDescendantPath(strNode));
  604. }
  605. return TRUE;
  606. }
  607. void
  608. CInheritanceDlg::OnButtonSelectAll()
  609. /*++
  610. Routine Description:
  611. 'Select All' button handler
  612. Arguments:
  613. None
  614. Return Value:
  615. None
  616. --*/
  617. {
  618. //
  619. // Select all entries
  620. //
  621. if (m_list_ChildNodes.GetCount() == 1)
  622. {
  623. //
  624. // SelItemRange refuses to do a single member
  625. //
  626. m_list_ChildNodes.SetSel(0, TRUE);
  627. }
  628. else
  629. {
  630. m_list_ChildNodes.SelItemRange(
  631. TRUE,
  632. 0,
  633. m_list_ChildNodes.GetCount() - 1
  634. );
  635. }
  636. }
  637. void
  638. CInheritanceDlg::OnOK()
  639. {
  640. //
  641. // Now delete the property for all selected child nodes.
  642. // Grab from the orginal list, and not the listbox
  643. // as the latter have been frienly-fied, and is no longer
  644. // usable.
  645. //
  646. int cItems = m_list_ChildNodes.GetCount();
  647. ASSERT(cItems > 0);
  648. CString strMetaPath;
  649. CError err(m_mk.QueryResult());
  650. if (err.Succeeded())
  651. {
  652. int i = 0;
  653. POSITION pos = m_strlMetaChildNodes.GetHeadPosition();
  654. while(pos)
  655. {
  656. strMetaPath = m_strlMetaChildNodes.GetNext(pos);
  657. if (m_list_ChildNodes.GetSel(i++) > 0)
  658. {
  659. TRACEEOLID("Deleting property on " << strMetaPath);
  660. err = m_mk.Open(METADATA_PERMISSION_WRITE, strMetaPath);
  661. if (err.Failed())
  662. {
  663. break;
  664. }
  665. err = m_mk.DeleteValue(m_dwMDIdentifier);
  666. m_mk.Close();
  667. if (err.Failed())
  668. {
  669. break;
  670. }
  671. }
  672. }
  673. }
  674. if (!err.MessageBoxOnFailure(m_hWnd))
  675. {
  676. //
  677. // Dialog can be dismissed
  678. //
  679. CDialog::OnOK();
  680. }
  681. }
  682. const LPCTSTR g_cszInetMGRBasePath = _T("Software\\Microsoft\\InetMGR");
  683. const LPCTSTR g_cszParameters = _T("Parameters");
  684. const LPCTSTR g_cszHelpPath = _T("HelpLocation");
  685. void
  686. CInheritanceDlg::OnHelp()
  687. {
  688. CString strKey, path;
  689. strKey.Format(_T("%s\\%s"), g_cszInetMGRBasePath, g_cszParameters);
  690. CRegKey rk;
  691. rk.Create(HKEY_LOCAL_MACHINE, strKey);
  692. DWORD len = MAX_PATH;
  693. rk.QueryValue(path.GetBuffer(len), g_cszHelpPath, &len);
  694. path.ReleaseBuffer(-1);
  695. path += _T("\\inetmgr.hlp");
  696. DebugTraceHelp(0x20000 + CInheritanceDlg::IDD);
  697. ::WinHelp(m_hWnd, path, HELP_CONTEXT, 0x20000 + CInheritanceDlg::IDD);
  698. }