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.

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