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.

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