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.

825 lines
17 KiB

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