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.

1113 lines
28 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: browser.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "preDNSsn.h"
  11. #include <SnapBase.h>
  12. #include "resource.h"
  13. #include "dnsutil.h"
  14. #include "DNSSnap.h"
  15. #include "snapdata.h"
  16. #include "server.h"
  17. #include "domain.h"
  18. #include "record.h"
  19. #include "zone.h"
  20. #include "browser.h"
  21. #ifdef DEBUG_ALLOCATOR
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. #endif
  28. /////////////////////////////////////////////////////////////////////////////////
  29. #define N_TOOLBAR_COMMAND_GO_UP IDC_TOOLBAR_CTRL
  30. ////////////////////////////////////////////////////////////////////////
  31. // CDNSComboBoxEx
  32. inline CImageList* CDNSComboBoxEx::SetImageList(CImageList* pImageList)
  33. {
  34. ASSERT(::IsWindow(m_hWnd));
  35. return CImageList::FromHandle((HIMAGELIST)
  36. ::SendMessage(m_hWnd, CBEM_SETIMAGELIST,
  37. 0, (LPARAM)pImageList->GetSafeHandle()));
  38. }
  39. inline int CDNSComboBoxEx::GetCount() const
  40. {
  41. ASSERT(::IsWindow(m_hWnd));
  42. return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0);
  43. }
  44. inline int CDNSComboBoxEx::GetCurSel() const
  45. {
  46. ASSERT(::IsWindow(m_hWnd));
  47. return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0);
  48. }
  49. inline int CDNSComboBoxEx::SetCurSel(int nSelect)
  50. {
  51. ASSERT(::IsWindow(m_hWnd));
  52. return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0);
  53. }
  54. inline int CDNSComboBoxEx::InsertItem(const COMBOBOXEXITEM* pItem)
  55. {
  56. ASSERT(::IsWindow(m_hWnd));
  57. return (int) ::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)pItem);
  58. }
  59. LPARAM CDNSComboBoxEx::GetItemData(int nIndex) const
  60. {
  61. COMBOBOXEXITEM item;
  62. item.iItem = nIndex;
  63. item.mask = CBEIF_LPARAM;
  64. ASSERT(::IsWindow(m_hWnd));
  65. if (::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&item))
  66. {
  67. return item.lParam;
  68. }
  69. return NULL;
  70. }
  71. BOOL CDNSComboBoxEx::SetItemData(int nIndex, LPARAM lParam)
  72. {
  73. COMBOBOXEXITEM item;
  74. item.iItem = nIndex;
  75. item.mask = CBEIF_LPARAM;
  76. item.lParam = lParam;
  77. ASSERT(::IsWindow(m_hWnd));
  78. return (::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&item) != 0);
  79. }
  80. inline void CDNSComboBoxEx::ResetContent()
  81. {
  82. ASSERT(::IsWindow(m_hWnd));
  83. ::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0);
  84. }
  85. inline DWORD CDNSComboBoxEx::GetExtendedStyle() const
  86. {
  87. ASSERT(::IsWindow(m_hWnd));
  88. return (DWORD) ::SendMessage(m_hWnd, CBEM_GETEXSTYLE, 0, 0);
  89. }
  90. inline DWORD CDNSComboBoxEx::SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
  91. {
  92. ASSERT(::IsWindow(m_hWnd));
  93. return (DWORD) ::SendMessage(m_hWnd, CBEM_SETEXSTYLE, (WPARAM)dwExMask, (LPARAM)dwExStyle);
  94. }
  95. inline BOOL CDNSComboBoxEx::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT)
  96. {
  97. return CreateEx(0, // extended style
  98. WC_COMBOBOXEX, // window class
  99. NULL, // window name
  100. dwStyle, // window style
  101. rect.left, rect.top, // x,y
  102. rect.right - rect.left, rect.bottom - rect.top, // width, height
  103. pParentWnd->GetSafeHwnd(), // parent window
  104. NULL, // menu
  105. NULL); // lpParam for window creation
  106. }
  107. //////////////////////////////////////////////////////////////////////////
  108. // CDNSBrowseItem
  109. inline int CDNSBrowseItem::GetImageIndex(BOOL bOpenImage)
  110. {
  111. if (m_pTreeNode == NULL)
  112. return 0; // error
  113. return m_pTreeNode->GetImageIndex(bOpenImage);
  114. }
  115. inline LPCWSTR CDNSBrowseItem::GetString(int nCol)
  116. {
  117. if (m_pTreeNode == NULL)
  118. return L"ERROR"; // error
  119. return m_pTreeNode->GetString(nCol);
  120. }
  121. inline BOOL CDNSBrowseItem::AddChild(CDNSBrowseItem* pChildBrowseItem)
  122. {
  123. ASSERT(m_pTreeNode != NULL);
  124. if (!m_pTreeNode->IsContainer())
  125. return FALSE;
  126. pChildBrowseItem->m_pParent = this;
  127. m_childList.AddTail(pChildBrowseItem);
  128. return TRUE;
  129. }
  130. inline BOOL CDNSBrowseItem::IsContainer()
  131. {
  132. ASSERT(m_pTreeNode != NULL);
  133. return m_pTreeNode->IsContainer();
  134. }
  135. BOOL CDNSBrowseItem::RemoveChildren(CDNSBrowseItem* pNotThisItem)
  136. {
  137. BOOL bFound = FALSE;
  138. while (!m_childList.IsEmpty())
  139. {
  140. CDNSBrowseItem* pItem = m_childList.RemoveTail();
  141. ASSERT(pItem != NULL);
  142. if (pItem == pNotThisItem)
  143. {
  144. ASSERT(!bFound);
  145. bFound = TRUE;
  146. }
  147. else
  148. {
  149. delete pItem;
  150. }
  151. }
  152. if (bFound)
  153. {
  154. m_childList.AddTail(pNotThisItem);
  155. }
  156. return bFound;
  157. }
  158. void CDNSBrowseItem::AddTreeNodeChildren(CDNSFilterCombo* pFilter,
  159. CComponentDataObject*)
  160. {
  161. ASSERT(m_pTreeNode != NULL);
  162. if (!m_pTreeNode->IsContainer())
  163. return;
  164. CContainerNode* pContNode = (CContainerNode*)m_pTreeNode;
  165. CNodeList* pChildList = pContNode->GetContainerChildList();
  166. POSITION pos;
  167. for (pos = pChildList->GetHeadPosition(); pos != NULL; )
  168. {
  169. CTreeNode* pCurrChildNode = pChildList->GetNext(pos);
  170. if (pFilter->IsValidTreeNode(pCurrChildNode))
  171. {
  172. CDNSBrowseItem* pItem = new CDNSBrowseItem;
  173. pItem->SetTreeNode(pCurrChildNode);
  174. AddChild(pItem);
  175. }
  176. }
  177. pChildList = pContNode->GetLeafChildList();
  178. POSITION pos2;
  179. for (pos2 = pChildList->GetHeadPosition(); pos2 != NULL; )
  180. {
  181. CTreeNode* pCurrChildNode = pChildList->GetNext(pos2);
  182. if (pFilter->IsValidTreeNode(pCurrChildNode))
  183. {
  184. CDNSBrowseItem* pItem = new CDNSBrowseItem;
  185. pItem->SetTreeNode(pCurrChildNode);
  186. AddChild(pItem);
  187. }
  188. }
  189. }
  190. void CDNSBrowseItem::AddToContainerCombo(CDNSCurrContainerCombo* pCtrl,
  191. CDNSBrowseItem* pSelectedBrowseItem,
  192. int nIndent,int* pNCurrIndex)
  193. {
  194. // add itself
  195. pCtrl->InsertBrowseItem(this, *pNCurrIndex, nIndent);
  196. if (this == pSelectedBrowseItem)
  197. {
  198. pCtrl->SetCurSel(*pNCurrIndex);
  199. return;
  200. }
  201. m_nIndex = *pNCurrIndex; // index in the combobox, for lookup
  202. (*pNCurrIndex)++;
  203. // depth first on children
  204. POSITION pos;
  205. for( pos = m_childList.GetHeadPosition(); pos != NULL; )
  206. {
  207. CDNSBrowseItem* pCurrentChild = m_childList.GetNext(pos);
  208. if (pCurrentChild->IsContainer())
  209. pCurrentChild->AddToContainerCombo(pCtrl, pSelectedBrowseItem,
  210. (nIndent+1), pNCurrIndex);
  211. }
  212. }
  213. //////////////////////////////////////////////////////////////////////////
  214. // CDNSFilterCombo
  215. BOOL CDNSFilterCombo::Initialize(UINT nCtrlID, UINT nIDFilterString, CDNSBrowserDlg* pDlg)
  216. {
  217. ASSERT(m_option != LAST); // must have a filter selected
  218. if (!SubclassDlgItem(nCtrlID,pDlg))
  219. return FALSE;
  220. // load string with '\n' separated string options
  221. int nMaxLen = 512;
  222. WCHAR* szBuf = 0;
  223. szBuf = (WCHAR*)malloc(sizeof(WCHAR)*nMaxLen);
  224. if (!szBuf)
  225. {
  226. return FALSE;
  227. }
  228. if ( ::LoadString(_Module.GetModuleInstance(), nIDFilterString, szBuf, nMaxLen) == 0)
  229. {
  230. free(szBuf);
  231. return FALSE;
  232. }
  233. // parse and get an array of pointers to each potential
  234. // entry in the combobox
  235. LPWSTR* lpszArr = 0;
  236. lpszArr = (LPWSTR*)malloc(sizeof(LPWSTR*)*nMaxLen);
  237. if (!lpszArr)
  238. {
  239. free(szBuf);
  240. return FALSE;
  241. }
  242. UINT nArrEntries;
  243. ParseNewLineSeparatedString(szBuf,lpszArr, &nArrEntries);
  244. // determine which entries are actually inserted
  245. int nEntry = 0;
  246. int nSelEntry = -1;
  247. for (UINT k=0; k<nArrEntries; k++)
  248. {
  249. if (CanAddToUIString(k))
  250. {
  251. if (k == (UINT)m_option)
  252. nSelEntry = nEntry;
  253. AddString(lpszArr[k]);
  254. SetItemData(nEntry,(DWORD)k);
  255. nEntry++;
  256. }
  257. }
  258. ASSERT( (nSelEntry > -1) && (nSelEntry < nEntry));
  259. SetCurSel(nSelEntry);
  260. if (szBuf)
  261. {
  262. free(szBuf);
  263. }
  264. if (lpszArr)
  265. {
  266. free(lpszArr);
  267. }
  268. return TRUE;
  269. }
  270. void CDNSFilterCombo::OnSelectionChange()
  271. {
  272. int nSel = GetCurSel();
  273. ASSERT(nSel != -1);
  274. if (nSel == -1)
  275. return;
  276. ASSERT(((DNSBrowseFilterOptionType)nSel) <= LAST);
  277. m_option = (DNSBrowseFilterOptionType)GetItemData(nSel);
  278. }
  279. BOOL CDNSFilterCombo::CanAddToUIString(UINT n)
  280. {
  281. switch(m_option)
  282. {
  283. case SERVER:
  284. return (n == (UINT)SERVER);
  285. case ZONE_FWD:
  286. return (n == (UINT)ZONE_FWD);
  287. case ZONE_REV:
  288. return (n == (UINT)ZONE_REV);
  289. case RECORD_A:
  290. return (n == (UINT)RECORD_A) || (n == (UINT)RECORD_ALL);
  291. case RECORD_CNAME:
  292. return (n == (UINT)RECORD_CNAME) || (n == (UINT)RECORD_ALL);
  293. case RECORD_A_AND_CNAME:
  294. return (n == (UINT)RECORD_A) ||
  295. (n == (UINT)RECORD_CNAME) ||
  296. (n == (UINT)RECORD_A_AND_CNAME) ||
  297. (n == (UINT)RECORD_ALL);
  298. case RECORD_RP:
  299. return (n == (UINT)RECORD_RP) || (n == (UINT)RECORD_ALL);
  300. case RECORD_TEXT:
  301. return (n == (UINT)RECORD_TEXT) || (n == (UINT)RECORD_ALL);
  302. case RECORD_MB:
  303. return (n == (UINT)RECORD_MB) || (n == (UINT)RECORD_ALL);
  304. case RECORD_ALL:
  305. return (n == (UINT)RECORD_ALL);
  306. };
  307. return FALSE;
  308. }
  309. BOOL CDNSFilterCombo::IsValidTreeNode(CTreeNode* pTreeNode)
  310. {
  311. BOOL bValid = FALSE; // by default, filter out
  312. if (pTreeNode->IsContainer())
  313. {
  314. if (IS_CLASS(*pTreeNode, CDNSServerNode))
  315. {
  316. if (m_szExcludeServerName.IsEmpty())
  317. bValid = TRUE;
  318. else
  319. bValid = m_szExcludeServerName != pTreeNode->GetDisplayName();
  320. }
  321. else if (IS_CLASS(*pTreeNode, CDNSForwardZonesNode ))
  322. {
  323. bValid = (m_option != ZONE_REV);
  324. }
  325. else if (IS_CLASS(*pTreeNode, CDNSReverseZonesNode ))
  326. {
  327. bValid = (m_option == ZONE_REV);
  328. }
  329. else if (IS_CLASS(*pTreeNode, CDNSZoneNode))
  330. {
  331. bValid = TRUE; // already screened at the auth. zones folder
  332. }
  333. else if (IS_CLASS(*pTreeNode, CDNSDomainNode))
  334. {
  335. // zone filtering stops at the zone level
  336. bValid = (m_option != ZONE_FWD) && (m_option != ZONE_REV);
  337. }
  338. }
  339. else // it is a record
  340. {
  341. WORD wType = ((CDNSRecordNodeBase*)pTreeNode)->GetType();
  342. switch(m_option)
  343. {
  344. case RECORD_A:
  345. bValid = (wType == DNS_TYPE_A);
  346. break;
  347. case RECORD_CNAME:
  348. bValid = (wType == DNS_TYPE_CNAME);
  349. break;
  350. case RECORD_A_AND_CNAME:
  351. bValid = (wType == DNS_TYPE_A) || (wType == DNS_TYPE_CNAME);
  352. break;
  353. case RECORD_RP:
  354. bValid = (wType == DNS_TYPE_RP);
  355. break;
  356. case RECORD_TEXT:
  357. bValid = (wType == DNS_TYPE_TEXT);
  358. break;
  359. case RECORD_MB:
  360. bValid = (wType == DNS_TYPE_MB);
  361. break;
  362. case RECORD_ALL:
  363. bValid = TRUE;
  364. }; // switch
  365. } //if else
  366. return bValid;
  367. }
  368. BOOL CDNSFilterCombo::IsValidResult(CDNSBrowseItem* pBrowseItem)
  369. {
  370. if (pBrowseItem == NULL)
  371. return FALSE;
  372. CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
  373. if (pTreeNode == NULL)
  374. return FALSE;
  375. BOOL bValid = FALSE;
  376. if (pTreeNode->IsContainer())
  377. {
  378. CDNSMTContainerNode* pContainer = (CDNSMTContainerNode*)pTreeNode;
  379. if ( (m_option == ZONE_FWD) || (m_option == ZONE_REV) )
  380. {
  381. bValid = IS_CLASS(*pContainer, CDNSZoneNode);
  382. }
  383. else if (m_option == SERVER)
  384. {
  385. bValid = IS_CLASS(*pContainer, CDNSServerNode);
  386. }
  387. }
  388. else // it is a record
  389. {
  390. WORD wType = ((CDNSRecordNodeBase*)pTreeNode)->GetType();
  391. switch(m_option)
  392. {
  393. case RECORD_ALL:
  394. bValid = TRUE;
  395. break;
  396. case RECORD_A:
  397. bValid = (wType == DNS_TYPE_A);
  398. break;
  399. case RECORD_CNAME:
  400. bValid = (wType == DNS_TYPE_CNAME);
  401. break;
  402. case RECORD_A_AND_CNAME:
  403. bValid = (wType == DNS_TYPE_A) || (wType == DNS_TYPE_CNAME);
  404. break;
  405. case RECORD_RP:
  406. bValid = (wType == DNS_TYPE_RP);
  407. break;
  408. case RECORD_TEXT:
  409. bValid = (wType == DNS_TYPE_TEXT);
  410. break;
  411. case RECORD_MB:
  412. bValid = (wType == DNS_TYPE_MB);
  413. break;
  414. };
  415. }
  416. return bValid;
  417. }
  418. void CDNSFilterCombo::GetStringOf(CDNSBrowseItem* pBrowseItem,
  419. CString& szResult)
  420. {
  421. if (pBrowseItem == NULL)
  422. return;
  423. CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
  424. if (pTreeNode == NULL)
  425. return;
  426. if (pTreeNode->IsContainer())
  427. {
  428. CDNSMTContainerNode* pContainer = (CDNSMTContainerNode*)pTreeNode;
  429. if (IS_CLASS(*pTreeNode, CDNSZoneNode))
  430. {
  431. szResult = (dynamic_cast<CDNSZoneNode*>(pContainer))->GetFullName();
  432. }
  433. else if (IS_CLASS(*pTreeNode , CDNSServerNode))
  434. {
  435. szResult = pContainer->GetDisplayName();
  436. }
  437. else
  438. {
  439. szResult.Empty();
  440. }
  441. }
  442. else // it is a record
  443. {
  444. CDNSRecordNodeBase* pRecordNode = (CDNSRecordNodeBase*)pTreeNode;
  445. WORD wType = pRecordNode->GetType();
  446. if (wType == DNS_TYPE_MB)
  447. {
  448. szResult = ((CDNS_MB_RecordNode*)pRecordNode)->GetNameNodeString();
  449. }
  450. //else if (wType == DNS_TYPE_RP)
  451. //{
  452. //}
  453. else
  454. {
  455. // for generic RR's we just get the FQDN
  456. pRecordNode->GetFullName(szResult);
  457. }
  458. }
  459. }
  460. //////////////////////////////////////////////////////////////////////////
  461. // CDNSCurrContainerCombo
  462. BOOL CDNSCurrContainerCombo::Initialize(UINT nCtrlID, UINT nBitmapID, CDNSBrowserDlg* pDlg)
  463. {
  464. if (!SubclassDlgItem(nCtrlID,pDlg))
  465. return FALSE;
  466. if (!m_imageList.Create(nBitmapID, 16, 1, BMP_COLOR_MASK))
  467. return FALSE;
  468. SetImageList(&m_imageList);
  469. return TRUE;
  470. }
  471. CDNSBrowseItem* CDNSCurrContainerCombo::GetSelection()
  472. {
  473. CDNSBrowseItem* pBrowseItem = NULL;
  474. int nSel = GetCurSel();
  475. if (nSel >= 0)
  476. {
  477. pBrowseItem = reinterpret_cast<CDNSBrowseItem*>(GetItemData(nSel));
  478. }
  479. return pBrowseItem;
  480. }
  481. void CDNSCurrContainerCombo::InsertBrowseItem(CDNSBrowseItem* pBrowseItem,
  482. int nIndex,
  483. int nIndent)
  484. {
  485. ASSERT(pBrowseItem != NULL);
  486. LPCWSTR lpszString = pBrowseItem->GetString(N_HEADER_NAME);
  487. COMBOBOXEXITEM cbei;
  488. cbei.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
  489. // Initialize the COMBOBOXEXITEM struct.
  490. cbei.iItem = nIndex;
  491. cbei.pszText = (LPWSTR)lpszString;
  492. cbei.cchTextMax = static_cast<int>(wcslen(lpszString));
  493. cbei.iImage = pBrowseItem->GetImageIndex(FALSE);
  494. cbei.iSelectedImage = pBrowseItem->GetImageIndex(TRUE);
  495. cbei.iIndent = nIndent;
  496. VERIFY(InsertItem(&cbei) != -1);
  497. SetItemData(nIndex,reinterpret_cast<LPARAM>(pBrowseItem));
  498. }
  499. void CDNSCurrContainerCombo::SetTree(CDNSBrowseItem* pRootBrowseItem,
  500. CDNSBrowseItem* pSelectedBrowseItem)
  501. {
  502. ASSERT(pRootBrowseItem != NULL);
  503. ASSERT(pSelectedBrowseItem != NULL);
  504. // remove all the contents
  505. ResetContent();
  506. // add depth first to the listbox
  507. int nCurrIndex = 0;
  508. int nIndent = 0;
  509. pRootBrowseItem->AddToContainerCombo(this, pSelectedBrowseItem,
  510. nIndent, &nCurrIndex);
  511. }
  512. //////////////////////////////////////////////////////////////////////////
  513. // CDNSChildrenListView
  514. BOOL CDNSChildrenListView::Initialize(UINT nCtrlID, UINT nBitmapID, CDNSBrowserDlg* pDlg)
  515. {
  516. m_pDlg = pDlg;
  517. if (!SubclassDlgItem(nCtrlID,pDlg))
  518. return FALSE;
  519. if (!m_imageList.Create(nBitmapID, 16, 1, BMP_COLOR_MASK))
  520. return FALSE;
  521. SetImageList(&m_imageList, LVSIL_SMALL);
  522. //
  523. // get width of control, width of potential scrollbar, width needed for sub-item
  524. // string
  525. // get size of control to help set the column widths
  526. CRect controlRect;
  527. GetClientRect(controlRect);
  528. int controlWidth = controlRect.Width();
  529. int scrollThumbWidth = ::GetSystemMetrics(SM_CXHTHUMB);
  530. // clean net width
  531. int nNetControlWidth = controlWidth - scrollThumbWidth -
  532. 12 * ::GetSystemMetrics(SM_CXBORDER);
  533. // fields widths
  534. int nTotalUnscaledWidth = 0;
  535. for (int iCol = 0; iCol < N_DEFAULT_HEADER_COLS; iCol++)
  536. nTotalUnscaledWidth += _DefaultHeaderStrings[iCol].nWidth;
  537. // set up columns
  538. for (iCol = 0; iCol < N_DEFAULT_HEADER_COLS; iCol++)
  539. {
  540. int nWidth = nNetControlWidth *
  541. _DefaultHeaderStrings[iCol].nWidth / nTotalUnscaledWidth;
  542. InsertColumn(iCol, _DefaultHeaderStrings[iCol].szBuffer,
  543. _DefaultHeaderStrings[iCol].nFormat,
  544. nWidth);
  545. }
  546. return TRUE;
  547. }
  548. void CDNSChildrenListView::SetChildren(CDNSBrowseItem* pBrowseItem)
  549. {
  550. // clear the listview
  551. DeleteAllItems();
  552. if (pBrowseItem == NULL)
  553. return;
  554. // add all the children that satisfy the filtering option
  555. POSITION pos;
  556. int itemIndex = 0;
  557. CDNSBrowseItem* pSelection = NULL;
  558. for( pos = pBrowseItem->m_childList.GetHeadPosition(); pos != NULL; )
  559. {
  560. CDNSBrowseItem* pCurrentChild = pBrowseItem->m_childList.GetNext(pos);
  561. // insert the name into the list view item, clear the subitem text
  562. UINT nState = 0;
  563. if (itemIndex == 0 )
  564. {
  565. nState = LVIS_SELECTED | LVIS_FOCUSED; // have at lest one item, select it
  566. pSelection = pCurrentChild;
  567. }
  568. VERIFY(-1 != InsertItem(LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE,
  569. itemIndex,
  570. pCurrentChild->GetString(N_HEADER_NAME),
  571. nState,
  572. 0,
  573. pCurrentChild->GetImageIndex(FALSE),
  574. (LPARAM)pCurrentChild));
  575. // set the text for subitems
  576. for (int iCol = N_HEADER_TYPE; iCol<N_DEFAULT_HEADER_COLS; iCol++)
  577. VERIFY(SetItemText(itemIndex, iCol, pCurrentChild->GetString(iCol)));
  578. // move to next index into the collection
  579. itemIndex++;
  580. }
  581. m_pDlg->UpdateSelectionEdit(pSelection);
  582. // enable/disable the OK button
  583. GetParent()->GetDlgItem(IDOK)->EnableWindow(FALSE);
  584. // enable/disable "UP" button
  585. m_pDlg->m_toolbar.EnableButton(N_TOOLBAR_COMMAND_GO_UP, pBrowseItem->m_pParent != NULL);
  586. }
  587. CDNSBrowseItem* CDNSChildrenListView::GetSelection()
  588. {
  589. int nSel = GetNextItem(-1, LVIS_SELECTED);
  590. return (nSel >= 0) ? (CDNSBrowseItem*)GetItemData(nSel) : NULL;
  591. }
  592. ///////////////////////////////////////////////////////////////////////////////
  593. // CDNSBrowserDlg
  594. BEGIN_MESSAGE_MAP(CDNSBrowserDlg, CHelpDialog)
  595. ON_COMMAND(N_TOOLBAR_COMMAND_GO_UP, OnButtonUp)
  596. ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnTooltip)
  597. ON_CBN_SELCHANGE(IDC_COMBO_SEL_NODE, OnSelchangeComboSelNode)
  598. ON_NOTIFY(NM_DBLCLK, IDC_LIST_NODE_ITEMS, OnDblclkListNodeItems)
  599. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_NODE_ITEMS, OnItemchangedListNodeItems)
  600. ON_CBN_SELCHANGE(IDC_COMBO_FILTER, OnSelchangeComboFilter)
  601. END_MESSAGE_MAP()
  602. CDNSBrowserDlg::CDNSBrowserDlg(CComponentDataObject* pComponentDataObject,
  603. CPropertyPageHolderBase* pHolder,
  604. DNSBrowseFilterOptionType option, BOOL bEnableEdit,
  605. LPCTSTR lpszExcludeServerName)
  606. : CHelpDialog(IDD_BROWSE_DIALOG, pComponentDataObject)
  607. {
  608. ASSERT(pComponentDataObject != NULL);
  609. m_pComponentDataObject = pComponentDataObject;
  610. m_pHolder = pHolder;
  611. m_filter.Set(option, lpszExcludeServerName);
  612. m_bEnableEdit = bEnableEdit;
  613. // point to the DNS snapin static folder
  614. m_pMasterRootNode = m_pComponentDataObject->GetRootData();
  615. // create a browse root item
  616. m_pBrowseRootItem = new CDNSBrowseItem;
  617. m_pBrowseRootItem->SetTreeNode(m_pMasterRootNode);
  618. m_pCurrSelContainer = NULL;
  619. m_pFinalSelection = NULL;
  620. }
  621. INT_PTR CDNSBrowserDlg::DoModal()
  622. {
  623. // make sure commoncontrolex initialized (for ComboBoxEx)
  624. INITCOMMONCONTROLSEX icex;
  625. icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
  626. icex.dwICC = ICC_USEREX_CLASSES;
  627. if (!InitCommonControlsEx(&icex))
  628. return -1;
  629. return CHelpDialog::DoModal();
  630. }
  631. void CDNSBrowserDlg::OnCancel()
  632. {
  633. if (m_pHolder != NULL)
  634. m_pHolder->PopDialogHWnd();
  635. CHelpDialog::OnCancel();
  636. }
  637. CDNSBrowserDlg::~CDNSBrowserDlg()
  638. {
  639. if (m_pBrowseRootItem != NULL)
  640. {
  641. delete m_pBrowseRootItem;
  642. m_pBrowseRootItem = NULL;
  643. }
  644. }
  645. CEdit* CDNSBrowserDlg::GetSelectionEdit()
  646. {
  647. return (CEdit*)GetDlgItem(IDC_SELECTION_EDIT);
  648. }
  649. CTreeNode* CDNSBrowserDlg::GetSelection()
  650. {
  651. if (m_pFinalSelection == NULL)
  652. return NULL;
  653. return m_pFinalSelection->GetTreeNode();
  654. }
  655. LPCTSTR CDNSBrowserDlg::GetSelectionString()
  656. {
  657. return m_szSelectionString;
  658. }
  659. BOOL CDNSBrowserDlg::OnInitDialog()
  660. {
  661. CHelpDialog::OnInitDialog();
  662. if (m_pHolder != NULL)
  663. m_pHolder->PushDialogHWnd(m_hWnd);
  664. InitializeControls();
  665. InitBrowseTree();
  666. m_pCurrSelContainer = m_pBrowseRootItem;
  667. m_currContainer.SetTree(m_pBrowseRootItem, m_pBrowseRootItem);
  668. m_childrenList.SetChildren(m_pBrowseRootItem);
  669. return TRUE;
  670. }
  671. //////////// CBrowseDlg : message handlers ////////////////
  672. void CDNSBrowserDlg::OnButtonUp()
  673. {
  674. CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
  675. ASSERT(pSelectedBrowseItem != NULL);
  676. if (pSelectedBrowseItem == NULL)
  677. return;
  678. ASSERT(pSelectedBrowseItem->m_pParent != NULL);
  679. if (pSelectedBrowseItem->m_pParent == NULL)
  680. return;
  681. MoveUpHelper(pSelectedBrowseItem->m_pParent);
  682. }
  683. BOOL CDNSBrowserDlg::OnTooltip(UINT, NMHDR* pHdr, LRESULT* plRes)
  684. {
  685. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  686. ASSERT(pHdr->code == TTN_NEEDTEXT);
  687. LPTOOLTIPTEXT pTT = (LPTOOLTIPTEXT)(pHdr);
  688. pTT->lpszText = (LPTSTR)IDS_BROWSE_TOOLTIP;
  689. pTT->hinst = AfxGetApp()->m_hInstance;
  690. *plRes = 0;
  691. return TRUE;
  692. }
  693. void CDNSBrowserDlg::OnSelchangeComboSelNode()
  694. {
  695. CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
  696. ASSERT(pSelectedBrowseItem != NULL);
  697. if (pSelectedBrowseItem == NULL)
  698. return;
  699. MoveUpHelper(pSelectedBrowseItem);
  700. }
  701. void CDNSBrowserDlg::OnDblclkListNodeItems(NMHDR* pNMHDR, LRESULT* pResult)
  702. {
  703. *pResult = 0;
  704. ASSERT(pNMHDR->code == NM_DBLCLK);
  705. HandleOkOrDblClick();
  706. }
  707. void CDNSBrowserDlg::OnOK()
  708. {
  709. HandleOkOrDblClick();
  710. }
  711. void CDNSBrowserDlg::OnItemchangedListNodeItems(NMHDR*, LRESULT*)
  712. {
  713. //EnableOkButton(m_filter.IsValidResult(pSelectedBrowseItem));
  714. CDNSBrowseItem* pSelectedBrowseItem = m_childrenList.GetSelection();
  715. BOOL bEnable = pSelectedBrowseItem != NULL;
  716. if (bEnable)
  717. bEnable = m_filter.IsValidResult(pSelectedBrowseItem) ||
  718. pSelectedBrowseItem->IsContainer();
  719. EnableOkButton(bEnable);
  720. UpdateSelectionEdit(pSelectedBrowseItem);
  721. }
  722. void CDNSBrowserDlg::OnSelchangeComboFilter()
  723. {
  724. m_filter.OnSelectionChange();
  725. ReEnumerateChildren();
  726. GetSelectionEdit()->EnableWindow(m_bEnableEdit);//m_filter.Get() == SERVER);
  727. }
  728. ////////////// CBrowseDlg : internal helpers //////////////////////
  729. void CDNSBrowserDlg::InitializeToolbar()
  730. {
  731. CWnd* pWnd = GetDlgItem(IDC_TOOLBAR_CTRL);
  732. CRect r;
  733. pWnd->GetWindowRect(r);
  734. ScreenToClient(r);
  735. pWnd->DestroyWindow();
  736. DWORD dwStyle = WS_CHILD | WS_VISIBLE | CCS_NORESIZE | CCS_TOP | CCS_NODIVIDER | TBSTYLE_TOOLTIPS ;
  737. m_toolbar.Create(dwStyle,r,this, IDC_TOOLBAR_CTRL);
  738. m_toolbar.AddBitmap(1, IDB_BROWSE_TOOLBAR);
  739. TBBUTTON btn[2];
  740. btn[0].iBitmap = 0; // zero-based index of button image
  741. btn[0].idCommand = 0; // command to be sent when button pressed
  742. btn[0].fsState = 0; // button state--see below
  743. btn[0].fsStyle = TBSTYLE_SEP; // button style--see below
  744. btn[0].dwData = 0; // application-defined value
  745. btn[0].iString = NULL; // zero-based index of button label string
  746. btn[1].iBitmap = 0; // zero-based index of button image
  747. btn[1].idCommand = N_TOOLBAR_COMMAND_GO_UP; // command to be sent when button pressed
  748. btn[1].fsState = TBSTATE_ENABLED; // button state--see below
  749. btn[1].fsStyle = TBSTYLE_BUTTON; // button style--see below
  750. btn[1].dwData = 0; // application-defined value
  751. btn[1].iString = NULL; // zero-based index of button label string
  752. m_toolbar.AddButtons(2, btn);
  753. }
  754. void CDNSBrowserDlg::InitializeControls()
  755. {
  756. // init the controls
  757. VERIFY(m_currContainer.Initialize(IDC_COMBO_SEL_NODE, IDB_16x16, this));
  758. VERIFY(m_childrenList.Initialize(IDC_LIST_NODE_ITEMS, IDB_16x16, this));
  759. VERIFY(m_filter.Initialize(IDC_COMBO_FILTER, IDS_BROWSE_FILTER_OPTIONS, this));
  760. InitializeToolbar();
  761. GetSelectionEdit()->EnableWindow(m_bEnableEdit);//m_filter.Get() == SERVER);
  762. }
  763. void CDNSBrowserDlg::EnableOkButton(BOOL bEnable)
  764. {
  765. GetDlgItem(IDOK)->EnableWindow(bEnable);
  766. }
  767. void CDNSBrowserDlg::HandleOkOrDblClick()
  768. {
  769. CDNSBrowseItem* pSelectedBrowseItem = m_childrenList.GetSelection();
  770. ASSERT(pSelectedBrowseItem != NULL);
  771. if (pSelectedBrowseItem == NULL)
  772. return;
  773. if (m_filter.IsValidResult(pSelectedBrowseItem))
  774. {
  775. if (m_bEnableEdit)
  776. {
  777. GetSelectionEdit()->GetWindowText(m_szSelectionString);
  778. m_szSelectionString.TrimLeft();
  779. m_szSelectionString.TrimRight();
  780. }
  781. m_pFinalSelection = pSelectedBrowseItem;
  782. if (m_pHolder != NULL)
  783. m_pHolder->PopDialogHWnd();
  784. CHelpDialog::OnOK();
  785. }
  786. else
  787. {
  788. MoveDownHelper();
  789. }
  790. }
  791. void CDNSBrowserDlg::UpdateSelectionEdit(CDNSBrowseItem* pBrowseItem)
  792. {
  793. if (pBrowseItem == NULL)
  794. m_szSelectionString.Empty();
  795. else
  796. m_filter.GetStringOf(pBrowseItem, m_szSelectionString);
  797. GetSelectionEdit()->SetWindowText(m_szSelectionString);
  798. }
  799. void CDNSBrowserDlg::InitBrowseTree()
  800. {
  801. ASSERT(m_pMasterRootNode != NULL);
  802. ASSERT(m_pBrowseRootItem != NULL);
  803. // assume we have no children
  804. //ASSERT(m_pBrowseRootItem->m_childList.GetCount() == 0);
  805. // get all the child nodes of the snapin root
  806. AddTreeNodeChildrenHelper(m_pBrowseRootItem, &m_filter);
  807. }
  808. void CDNSBrowserDlg::ReEnumerateChildren()
  809. {
  810. ASSERT(m_pMasterRootNode != NULL);
  811. ASSERT(m_pBrowseRootItem != NULL);
  812. ASSERT(m_pCurrSelContainer != NULL);
  813. m_pCurrSelContainer->RemoveChildren(NULL);
  814. AddTreeNodeChildrenHelper(m_pCurrSelContainer, &m_filter);
  815. m_childrenList.SetChildren(m_pCurrSelContainer);
  816. }
  817. void CDNSBrowserDlg::ExpandBrowseTree(CDNSBrowseItem* pCurrBrowseItem,
  818. CDNSBrowseItem* pChildBrowseItem)
  819. {
  820. ASSERT(m_pMasterRootNode != NULL);
  821. ASSERT(m_pBrowseRootItem != NULL);
  822. ASSERT(pCurrBrowseItem != NULL);
  823. ASSERT(pChildBrowseItem != NULL);
  824. ASSERT(pChildBrowseItem->m_pParent == pCurrBrowseItem);
  825. // we are going down one level:
  826. // 1. remove all the children of the current item but the specified child
  827. VERIFY(pCurrBrowseItem->RemoveChildren(pChildBrowseItem));
  828. // 2. move down to the child
  829. // 3. enumerate all the children of the specified child (filtering)
  830. AddTreeNodeChildrenHelper(pChildBrowseItem, &m_filter);
  831. }
  832. void CDNSBrowserDlg::ContractBrowseTree(CDNSBrowseItem* pParentBrowseItem)
  833. {
  834. ASSERT(m_pMasterRootNode != NULL);
  835. ASSERT(m_pBrowseRootItem != NULL);
  836. ASSERT(pParentBrowseItem != NULL);
  837. // we are going up one of more levels (possibly up to the root)
  838. // 1. remove all the children below the specified item
  839. pParentBrowseItem->RemoveChildren(NULL);
  840. // 3. enumerate all the children of the specified item (filtering)
  841. AddTreeNodeChildrenHelper(pParentBrowseItem, &m_filter);
  842. }
  843. void CDNSBrowserDlg::MoveUpHelper(CDNSBrowseItem* pNewBrowseItem)
  844. {
  845. ASSERT(m_pCurrSelContainer != NULL);
  846. ASSERT(pNewBrowseItem != NULL);
  847. if (m_pCurrSelContainer == pNewBrowseItem)
  848. return; // the same was picked, nothing to do
  849. #ifdef _DEBUG
  850. // we assume that the new item is NOT a child of the current selection
  851. CDNSBrowseItem* pItem = pNewBrowseItem;
  852. BOOL bFound = FALSE;
  853. while (pItem != NULL)
  854. {
  855. bFound = (pItem == m_pCurrSelContainer);
  856. if (bFound)
  857. break;
  858. pItem = pItem->m_pParent;
  859. }
  860. ASSERT(!bFound);
  861. #endif
  862. ContractBrowseTree(pNewBrowseItem);
  863. m_currContainer.SetTree(m_pBrowseRootItem, pNewBrowseItem);
  864. m_childrenList.SetChildren(pNewBrowseItem);
  865. // set new selection
  866. m_pCurrSelContainer = pNewBrowseItem;
  867. }
  868. void CDNSBrowserDlg::MoveDownHelper()
  869. {
  870. CDNSBrowseItem* pChildBrowseItem = m_childrenList.GetSelection();
  871. if (pChildBrowseItem == NULL)
  872. {
  873. return;
  874. }
  875. //
  876. // If it is not a container we should do something else, for now we will just return
  877. //
  878. if (!pChildBrowseItem->IsContainer())
  879. {
  880. return;
  881. }
  882. //
  883. // get the selection in the combobox
  884. //
  885. CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
  886. ASSERT(pSelectedBrowseItem != NULL);
  887. if (pSelectedBrowseItem == NULL)
  888. {
  889. return;
  890. }
  891. ExpandBrowseTree(pSelectedBrowseItem, pChildBrowseItem);
  892. m_currContainer.SetTree(m_pBrowseRootItem, pChildBrowseItem);
  893. m_childrenList.SetChildren(pChildBrowseItem);
  894. m_pCurrSelContainer = pChildBrowseItem;
  895. SetForegroundWindow();
  896. }
  897. class CBrowseExecContext : public CExecContext
  898. {
  899. public:
  900. virtual void Execute(LPARAM arg)
  901. {
  902. m_dlg->AddTreeNodeChildrenHelper(m_pBrowseItem, m_pFilter, (BOOL)arg);
  903. }
  904. CDNSBrowserDlg* m_dlg;
  905. CDNSBrowseItem* m_pBrowseItem;
  906. CDNSFilterCombo* m_pFilter;
  907. };
  908. void CDNSBrowserDlg::AddTreeNodeChildrenHelper(CDNSBrowseItem* pBrowseItem,
  909. CDNSFilterCombo* pFilter, BOOL bExpand)
  910. {
  911. if (bExpand)
  912. {
  913. // need to do this always from the UI thread (main for Wiz, 2nd for prop pages)
  914. CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
  915. if (!pTreeNode->IsContainer())
  916. return;
  917. CContainerNode* pContNode = (CContainerNode*)pTreeNode;
  918. if ( (pContNode->GetContainer() != NULL) && (!pContNode->IsEnumerated()) )
  919. {
  920. EnumerateMTNodeHelper((CMTContainerNode*)pContNode,
  921. m_pComponentDataObject);
  922. }
  923. }
  924. // have to figure out if we are running in the main thread
  925. if (_MainThreadId == ::GetCurrentThreadId())
  926. {
  927. pBrowseItem->AddTreeNodeChildren(pFilter, m_pComponentDataObject);
  928. return;
  929. }
  930. // we are from a secondary thread, execute in the context for the main
  931. // thread by posting a message and waiting
  932. ASSERT(m_pComponentDataObject != NULL);
  933. CBrowseExecContext ctx;
  934. ctx.m_dlg = this;
  935. ctx.m_pBrowseItem = pBrowseItem;
  936. ctx.m_pFilter = pFilter;
  937. TRACE(_T("before post message()\n"));
  938. VERIFY(m_pComponentDataObject->PostExecMessage(&ctx,(WPARAM)FALSE));
  939. ctx.Wait();
  940. TRACE(_T("after wait()\n"));
  941. }