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
1144 lines
30 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
|
//
|
|
// File: browser.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include "preDNSsn.h"
|
|
#include <SnapBase.h>
|
|
|
|
#include "resource.h"
|
|
#include "dnsutil.h"
|
|
#include "DNSSnap.h"
|
|
#include "snapdata.h"
|
|
|
|
#include "server.h"
|
|
#include "domain.h"
|
|
#include "record.h"
|
|
#include "zone.h"
|
|
|
|
#include "browser.h"
|
|
|
|
#ifdef DEBUG_ALLOCATOR
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
#define N_TOOLBAR_COMMAND_GO_UP IDC_TOOLBAR_CTRL
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CDNSComboBoxEx
|
|
|
|
inline HIMAGELIST CDNSComboBoxEx::SetImageList(HIMAGELIST himl)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (HIMAGELIST) ::SendMessage(m_hWnd, CBEM_SETIMAGELIST,
|
|
0, (LPARAM)himl);
|
|
}
|
|
|
|
inline int CDNSComboBoxEx::GetCount() const
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (int)::SendMessage(m_hWnd, CB_GETCOUNT, 0, 0);
|
|
}
|
|
|
|
inline int CDNSComboBoxEx::GetCurSel() const
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (int)::SendMessage(m_hWnd, CB_GETCURSEL, 0, 0);
|
|
}
|
|
|
|
|
|
inline int CDNSComboBoxEx::SetCurSel(int nSelect)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (int)::SendMessage(m_hWnd, CB_SETCURSEL, nSelect, 0);
|
|
}
|
|
|
|
inline int CDNSComboBoxEx::InsertItem(const COMBOBOXEXITEM* pItem)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (int) ::SendMessage(m_hWnd, CBEM_INSERTITEM, 0, (LPARAM)pItem);
|
|
}
|
|
|
|
|
|
LPARAM CDNSComboBoxEx::GetItemData(int nIndex) const
|
|
{
|
|
COMBOBOXEXITEM item;
|
|
item.iItem = nIndex;
|
|
item.mask = CBEIF_LPARAM;
|
|
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
if (::SendMessage(m_hWnd, CBEM_GETITEM, 0, (LPARAM)&item))
|
|
{
|
|
return item.lParam;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
BOOL CDNSComboBoxEx::SetItemData(int nIndex, LPARAM lParam)
|
|
{
|
|
COMBOBOXEXITEM item;
|
|
item.iItem = nIndex;
|
|
item.mask = CBEIF_LPARAM;
|
|
item.lParam = lParam;
|
|
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (::SendMessage(m_hWnd, CBEM_SETITEM, 0, (LPARAM)&item) != 0);
|
|
}
|
|
|
|
inline void CDNSComboBoxEx::ResetContent()
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
::SendMessage(m_hWnd, CB_RESETCONTENT, 0, 0);
|
|
}
|
|
|
|
|
|
|
|
inline DWORD CDNSComboBoxEx::GetExtendedStyle() const
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (DWORD) ::SendMessage(m_hWnd, CBEM_GETEXSTYLE, 0, 0);
|
|
}
|
|
|
|
inline DWORD CDNSComboBoxEx::SetExtendedStyle(DWORD dwExMask, DWORD dwExStyle)
|
|
{
|
|
ASSERT(::IsWindow(m_hWnd));
|
|
return (DWORD) ::SendMessage(m_hWnd, CBEM_SETEXSTYLE, (WPARAM)dwExMask, (LPARAM)dwExStyle);
|
|
}
|
|
|
|
|
|
inline BOOL CDNSComboBoxEx::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT)
|
|
{
|
|
return CreateEx(0, // extended style
|
|
WC_COMBOBOXEX, // window class
|
|
NULL, // window name
|
|
dwStyle, // window style
|
|
rect.left, rect.top, // x,y
|
|
rect.right - rect.left, rect.bottom - rect.top, // width, height
|
|
pParentWnd->GetSafeHwnd(), // parent window
|
|
NULL, // menu
|
|
NULL); // lpParam for window creation
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CDNSBrowseItem
|
|
|
|
inline int CDNSBrowseItem::GetImageIndex(BOOL bOpenImage)
|
|
{
|
|
if (m_pTreeNode == NULL)
|
|
return 0; // error
|
|
return m_pTreeNode->GetImageIndex(bOpenImage);
|
|
}
|
|
|
|
inline LPCWSTR CDNSBrowseItem::GetString(int nCol)
|
|
{
|
|
if (m_pTreeNode == NULL)
|
|
return L"ERROR"; // error
|
|
return m_pTreeNode->GetString(nCol);
|
|
}
|
|
|
|
inline BOOL CDNSBrowseItem::AddChild(CDNSBrowseItem* pChildBrowseItem)
|
|
{
|
|
ASSERT(m_pTreeNode != NULL);
|
|
if (!m_pTreeNode->IsContainer())
|
|
return FALSE;
|
|
pChildBrowseItem->m_pParent = this;
|
|
m_childList.AddTail(pChildBrowseItem);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
inline BOOL CDNSBrowseItem::IsContainer()
|
|
{
|
|
ASSERT(m_pTreeNode != NULL);
|
|
return m_pTreeNode->IsContainer();
|
|
}
|
|
|
|
BOOL CDNSBrowseItem::RemoveChildren(CDNSBrowseItem* pNotThisItem)
|
|
{
|
|
BOOL bFound = FALSE;
|
|
while (!m_childList.IsEmpty())
|
|
{
|
|
CDNSBrowseItem* pItem = m_childList.RemoveTail();
|
|
ASSERT(pItem != NULL);
|
|
if (pItem == pNotThisItem)
|
|
{
|
|
ASSERT(!bFound);
|
|
bFound = TRUE;
|
|
}
|
|
else
|
|
{
|
|
delete pItem;
|
|
}
|
|
}
|
|
if (bFound)
|
|
{
|
|
m_childList.AddTail(pNotThisItem);
|
|
}
|
|
return bFound;
|
|
}
|
|
|
|
|
|
void CDNSBrowseItem::AddTreeNodeChildren(CDNSFilterCombo* pFilter,
|
|
CComponentDataObject*)
|
|
{
|
|
ASSERT(m_pTreeNode != NULL);
|
|
if (!m_pTreeNode->IsContainer())
|
|
return;
|
|
|
|
CContainerNode* pContNode = (CContainerNode*)m_pTreeNode;
|
|
CNodeList* pChildList = pContNode->GetContainerChildList();
|
|
POSITION pos;
|
|
for (pos = pChildList->GetHeadPosition(); pos != NULL; )
|
|
{
|
|
CTreeNode* pCurrChildNode = pChildList->GetNext(pos);
|
|
if (pFilter->IsValidTreeNode(pCurrChildNode))
|
|
{
|
|
CDNSBrowseItem* pItem = new CDNSBrowseItem;
|
|
if (pItem)
|
|
{
|
|
pItem->SetTreeNode(pCurrChildNode);
|
|
AddChild(pItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
pChildList = pContNode->GetLeafChildList();
|
|
POSITION pos2;
|
|
for (pos2 = pChildList->GetHeadPosition(); pos2 != NULL; )
|
|
{
|
|
CTreeNode* pCurrChildNode = pChildList->GetNext(pos2);
|
|
if (pFilter->IsValidTreeNode(pCurrChildNode))
|
|
{
|
|
CDNSBrowseItem* pItem = new CDNSBrowseItem;
|
|
if (pItem)
|
|
{
|
|
pItem->SetTreeNode(pCurrChildNode);
|
|
AddChild(pItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CDNSBrowseItem::AddToContainerCombo(CDNSCurrContainerCombo* pCtrl,
|
|
CDNSBrowseItem* pSelectedBrowseItem,
|
|
int nIndent,int* pNCurrIndex)
|
|
{
|
|
// add itself
|
|
pCtrl->InsertBrowseItem(this, *pNCurrIndex, nIndent);
|
|
if (this == pSelectedBrowseItem)
|
|
{
|
|
pCtrl->SetCurSel(*pNCurrIndex);
|
|
return;
|
|
}
|
|
|
|
m_nIndex = *pNCurrIndex; // index in the combobox, for lookup
|
|
(*pNCurrIndex)++;
|
|
|
|
// depth first on children
|
|
POSITION pos;
|
|
for( pos = m_childList.GetHeadPosition(); pos != NULL; )
|
|
{
|
|
CDNSBrowseItem* pCurrentChild = m_childList.GetNext(pos);
|
|
if (pCurrentChild->IsContainer())
|
|
pCurrentChild->AddToContainerCombo(pCtrl, pSelectedBrowseItem,
|
|
(nIndent+1), pNCurrIndex);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CDNSFilterCombo
|
|
|
|
BOOL CDNSFilterCombo::Initialize(UINT nCtrlID, UINT nIDFilterString, CDNSBrowserDlg* pDlg)
|
|
{
|
|
ASSERT(m_option != LAST); // must have a filter selected
|
|
|
|
if (!SubclassDlgItem(nCtrlID,pDlg))
|
|
return FALSE;
|
|
|
|
// load string with '\n' separated string options
|
|
int nMaxLen = 512;
|
|
WCHAR* szBuf = 0;
|
|
|
|
szBuf = (WCHAR*)malloc(sizeof(WCHAR)*nMaxLen);
|
|
if (!szBuf)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ( ::LoadString(_Module.GetModuleInstance(), nIDFilterString, szBuf, nMaxLen) == 0)
|
|
{
|
|
free(szBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
// parse and get an array of pointers to each potential
|
|
// entry in the combobox
|
|
LPWSTR* lpszArr = 0;
|
|
lpszArr = (LPWSTR*)malloc(sizeof(LPWSTR*)*nMaxLen);
|
|
if (!lpszArr)
|
|
{
|
|
free(szBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
UINT nArrEntries;
|
|
ParseNewLineSeparatedString(szBuf,lpszArr, &nArrEntries);
|
|
|
|
// determine which entries are actually inserted
|
|
int nEntry = 0;
|
|
int nSelEntry = -1;
|
|
for (UINT k=0; k<nArrEntries; k++)
|
|
{
|
|
if (CanAddToUIString(k))
|
|
{
|
|
if (k == (UINT)m_option)
|
|
nSelEntry = nEntry;
|
|
AddString(lpszArr[k]);
|
|
SetItemData(nEntry,(DWORD)k);
|
|
nEntry++;
|
|
}
|
|
}
|
|
ASSERT( (nSelEntry > -1) && (nSelEntry < nEntry));
|
|
SetCurSel(nSelEntry);
|
|
|
|
if (szBuf)
|
|
{
|
|
free(szBuf);
|
|
}
|
|
|
|
if (lpszArr)
|
|
{
|
|
free(lpszArr);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CDNSFilterCombo::OnSelectionChange()
|
|
{
|
|
int nSel = GetCurSel();
|
|
ASSERT(nSel != -1);
|
|
if (nSel == -1)
|
|
return;
|
|
ASSERT(((DNSBrowseFilterOptionType)nSel) <= LAST);
|
|
m_option = (DNSBrowseFilterOptionType)GetItemData(nSel);
|
|
}
|
|
|
|
BOOL CDNSFilterCombo::CanAddToUIString(UINT n)
|
|
{
|
|
switch(m_option)
|
|
{
|
|
case SERVER:
|
|
return (n == (UINT)SERVER);
|
|
case ZONE_FWD:
|
|
return (n == (UINT)ZONE_FWD);
|
|
case ZONE_REV:
|
|
return (n == (UINT)ZONE_REV);
|
|
case RECORD_A:
|
|
return (n == (UINT)RECORD_A) || (n == (UINT)RECORD_ALL);
|
|
case RECORD_CNAME:
|
|
return (n == (UINT)RECORD_CNAME) || (n == (UINT)RECORD_ALL);
|
|
case RECORD_A_AND_CNAME:
|
|
return (n == (UINT)RECORD_A) ||
|
|
(n == (UINT)RECORD_CNAME) ||
|
|
(n == (UINT)RECORD_A_AND_CNAME) ||
|
|
(n == (UINT)RECORD_ALL);
|
|
case RECORD_RP:
|
|
return (n == (UINT)RECORD_RP) || (n == (UINT)RECORD_ALL);
|
|
case RECORD_TEXT:
|
|
return (n == (UINT)RECORD_TEXT) || (n == (UINT)RECORD_ALL);
|
|
case RECORD_MB:
|
|
return (n == (UINT)RECORD_MB) || (n == (UINT)RECORD_ALL);
|
|
case RECORD_ALL:
|
|
return (n == (UINT)RECORD_ALL);
|
|
};
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CDNSFilterCombo::IsValidTreeNode(CTreeNode* pTreeNode)
|
|
{
|
|
BOOL bValid = FALSE; // by default, filter out
|
|
if (pTreeNode->IsContainer())
|
|
{
|
|
if (IS_CLASS(*pTreeNode, CDNSServerNode))
|
|
{
|
|
if (m_szExcludeServerName.IsEmpty())
|
|
bValid = TRUE;
|
|
else
|
|
bValid = m_szExcludeServerName != pTreeNode->GetDisplayName();
|
|
}
|
|
else if (IS_CLASS(*pTreeNode, CDNSForwardZonesNode ))
|
|
{
|
|
bValid = (m_option != ZONE_REV);
|
|
}
|
|
else if (IS_CLASS(*pTreeNode, CDNSReverseZonesNode ))
|
|
{
|
|
bValid = (m_option == ZONE_REV);
|
|
}
|
|
else if (IS_CLASS(*pTreeNode, CDNSZoneNode))
|
|
{
|
|
bValid = TRUE; // already screened at the auth. zones folder
|
|
}
|
|
else if (IS_CLASS(*pTreeNode, CDNSDomainNode))
|
|
{
|
|
// zone filtering stops at the zone level
|
|
bValid = (m_option != ZONE_FWD) && (m_option != ZONE_REV);
|
|
}
|
|
}
|
|
else // it is a record or a root hints or forwarder node
|
|
{
|
|
// This will see if we have a record node. If so, continue on. If not,
|
|
// return false
|
|
|
|
CDNSRecordNodeBase* pRecordNode = dynamic_cast<CDNSRecordNodeBase*>(pTreeNode);
|
|
if (pRecordNode)
|
|
{
|
|
WORD wType = pRecordNode->GetType();
|
|
switch(m_option)
|
|
{
|
|
case RECORD_A:
|
|
bValid = (wType == DNS_TYPE_A);
|
|
break;
|
|
case RECORD_CNAME:
|
|
bValid = (wType == DNS_TYPE_CNAME);
|
|
break;
|
|
case RECORD_A_AND_CNAME:
|
|
bValid = (wType == DNS_TYPE_A) || (wType == DNS_TYPE_CNAME);
|
|
break;
|
|
case RECORD_RP:
|
|
bValid = (wType == DNS_TYPE_RP);
|
|
break;
|
|
case RECORD_TEXT:
|
|
bValid = (wType == DNS_TYPE_TEXT);
|
|
break;
|
|
case RECORD_MB:
|
|
bValid = (wType == DNS_TYPE_MB);
|
|
break;
|
|
case RECORD_ALL:
|
|
bValid = TRUE;
|
|
}; // switch
|
|
}
|
|
} //if else
|
|
return bValid;
|
|
}
|
|
|
|
BOOL CDNSFilterCombo::IsValidResult(CDNSBrowseItem* pBrowseItem)
|
|
{
|
|
if (pBrowseItem == NULL)
|
|
return FALSE;
|
|
|
|
CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
|
|
if (pTreeNode == NULL)
|
|
return FALSE;
|
|
|
|
BOOL bValid = FALSE;
|
|
if (pTreeNode->IsContainer())
|
|
{
|
|
CDNSMTContainerNode* pContainer = (CDNSMTContainerNode*)pTreeNode;
|
|
if ( (m_option == ZONE_FWD) || (m_option == ZONE_REV) )
|
|
{
|
|
bValid = IS_CLASS(*pContainer, CDNSZoneNode);
|
|
}
|
|
else if (m_option == SERVER)
|
|
{
|
|
bValid = IS_CLASS(*pContainer, CDNSServerNode);
|
|
}
|
|
}
|
|
else // it is a record
|
|
{
|
|
CDNSRecordNodeBase* pRecordNode = dynamic_cast<CDNSRecordNodeBase*>(pTreeNode);
|
|
if (pRecordNode)
|
|
{
|
|
WORD wType = pRecordNode->GetType();
|
|
switch(m_option)
|
|
{
|
|
case RECORD_ALL:
|
|
bValid = TRUE;
|
|
break;
|
|
case RECORD_A:
|
|
bValid = (wType == DNS_TYPE_A);
|
|
break;
|
|
case RECORD_CNAME:
|
|
bValid = (wType == DNS_TYPE_CNAME);
|
|
break;
|
|
case RECORD_A_AND_CNAME:
|
|
bValid = (wType == DNS_TYPE_A) || (wType == DNS_TYPE_CNAME);
|
|
break;
|
|
case RECORD_RP:
|
|
bValid = (wType == DNS_TYPE_RP);
|
|
break;
|
|
case RECORD_TEXT:
|
|
bValid = (wType == DNS_TYPE_TEXT);
|
|
break;
|
|
case RECORD_MB:
|
|
bValid = (wType == DNS_TYPE_MB);
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
return bValid;
|
|
}
|
|
|
|
void CDNSFilterCombo::GetStringOf(CDNSBrowseItem* pBrowseItem,
|
|
CString& szResult)
|
|
{
|
|
if (pBrowseItem == NULL)
|
|
return;
|
|
|
|
CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
|
|
if (pTreeNode == NULL)
|
|
return;
|
|
|
|
if (pTreeNode->IsContainer())
|
|
{
|
|
CDNSMTContainerNode* pContainer = (CDNSMTContainerNode*)pTreeNode;
|
|
if (IS_CLASS(*pTreeNode, CDNSZoneNode))
|
|
{
|
|
szResult = (dynamic_cast<CDNSZoneNode*>(pContainer))->GetFullName();
|
|
}
|
|
else if (IS_CLASS(*pTreeNode , CDNSServerNode))
|
|
{
|
|
szResult = pContainer->GetDisplayName();
|
|
}
|
|
else
|
|
{
|
|
szResult.Empty();
|
|
}
|
|
}
|
|
else // it is a record
|
|
{
|
|
CDNSRecordNodeBase* pRecordNode = dynamic_cast<CDNSRecordNodeBase*>(pTreeNode);
|
|
if (pRecordNode)
|
|
{
|
|
WORD wType = pRecordNode->GetType();
|
|
if (wType == DNS_TYPE_MB)
|
|
{
|
|
szResult = ((CDNS_MB_RecordNode*)pRecordNode)->GetNameNodeString();
|
|
}
|
|
//else if (wType == DNS_TYPE_RP)
|
|
//{
|
|
//}
|
|
else
|
|
{
|
|
// for generic RR's we just get the FQDN
|
|
pRecordNode->GetFullName(szResult);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CDNSCurrContainerCombo
|
|
|
|
BOOL CDNSCurrContainerCombo::Initialize(UINT nCtrlID, UINT nBitmapID, CDNSBrowserDlg* pDlg)
|
|
{
|
|
if (!SubclassDlgItem(nCtrlID,pDlg))
|
|
return FALSE;
|
|
|
|
if (!m_imageList.Create(nBitmapID, 16, 1, BMP_COLOR_MASK))
|
|
return FALSE;
|
|
SetImageList((HIMAGELIST)m_imageList);
|
|
return TRUE;
|
|
}
|
|
|
|
CDNSBrowseItem* CDNSCurrContainerCombo::GetSelection()
|
|
{
|
|
CDNSBrowseItem* pBrowseItem = NULL;
|
|
int nSel = GetCurSel();
|
|
if (nSel >= 0)
|
|
{
|
|
pBrowseItem = reinterpret_cast<CDNSBrowseItem*>(GetItemData(nSel));
|
|
}
|
|
return pBrowseItem;
|
|
}
|
|
|
|
|
|
void CDNSCurrContainerCombo::InsertBrowseItem(CDNSBrowseItem* pBrowseItem,
|
|
int nIndex,
|
|
int nIndent)
|
|
{
|
|
ASSERT(pBrowseItem != NULL);
|
|
LPCWSTR lpszString = pBrowseItem->GetString(N_HEADER_NAME);
|
|
|
|
COMBOBOXEXITEM cbei;
|
|
cbei.mask = CBEIF_TEXT | CBEIF_INDENT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE;
|
|
// Initialize the COMBOBOXEXITEM struct.
|
|
cbei.iItem = nIndex;
|
|
cbei.pszText = (LPWSTR)lpszString;
|
|
cbei.cchTextMax = static_cast<int>(wcslen(lpszString));
|
|
cbei.iImage = pBrowseItem->GetImageIndex(FALSE);
|
|
cbei.iSelectedImage = pBrowseItem->GetImageIndex(TRUE);
|
|
cbei.iIndent = nIndent;
|
|
|
|
VERIFY(InsertItem(&cbei) != -1);
|
|
SetItemData(nIndex,reinterpret_cast<LPARAM>(pBrowseItem));
|
|
}
|
|
|
|
void CDNSCurrContainerCombo::SetTree(CDNSBrowseItem* pRootBrowseItem,
|
|
CDNSBrowseItem* pSelectedBrowseItem)
|
|
{
|
|
ASSERT(pRootBrowseItem != NULL);
|
|
ASSERT(pSelectedBrowseItem != NULL);
|
|
|
|
// remove all the contents
|
|
ResetContent();
|
|
|
|
// add depth first to the listbox
|
|
int nCurrIndex = 0;
|
|
int nIndent = 0;
|
|
pRootBrowseItem->AddToContainerCombo(this, pSelectedBrowseItem,
|
|
nIndent, &nCurrIndex);
|
|
}
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CDNSChildrenListView
|
|
|
|
BOOL CDNSChildrenListView::Initialize(UINT nCtrlID, UINT nBitmapID, CDNSBrowserDlg* pDlg)
|
|
{
|
|
m_pDlg = pDlg;
|
|
if (!SubclassDlgItem(nCtrlID,pDlg))
|
|
return FALSE;
|
|
|
|
if (!m_imageList.Create(nBitmapID, 16, 1, BMP_COLOR_MASK))
|
|
return FALSE;
|
|
::SendMessage(GetSafeHwnd(), LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)(HIMAGELIST)m_imageList);
|
|
|
|
//
|
|
// get width of control, width of potential scrollbar, width needed for sub-item
|
|
// string
|
|
// get size of control to help set the column widths
|
|
CRect controlRect;
|
|
GetClientRect(controlRect);
|
|
|
|
int controlWidth = controlRect.Width();
|
|
int scrollThumbWidth = ::GetSystemMetrics(SM_CXHTHUMB);
|
|
|
|
// clean net width
|
|
int nNetControlWidth = controlWidth - scrollThumbWidth -
|
|
12 * ::GetSystemMetrics(SM_CXBORDER);
|
|
|
|
// fields widths
|
|
int nTotalUnscaledWidth = 0;
|
|
for (int iCol = 0; iCol < N_DEFAULT_HEADER_COLS; iCol++)
|
|
nTotalUnscaledWidth += _DefaultHeaderStrings[iCol].nWidth;
|
|
|
|
// set up columns
|
|
for (iCol = 0; iCol < N_DEFAULT_HEADER_COLS; iCol++)
|
|
{
|
|
int nWidth = nNetControlWidth *
|
|
_DefaultHeaderStrings[iCol].nWidth / nTotalUnscaledWidth;
|
|
InsertColumn(iCol, _DefaultHeaderStrings[iCol].szBuffer,
|
|
_DefaultHeaderStrings[iCol].nFormat,
|
|
nWidth);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CDNSChildrenListView::SetChildren(CDNSBrowseItem* pBrowseItem)
|
|
{
|
|
// clear the listview
|
|
DeleteAllItems();
|
|
if (pBrowseItem == NULL)
|
|
return;
|
|
|
|
// add all the children that satisfy the filtering option
|
|
POSITION pos;
|
|
int itemIndex = 0;
|
|
CDNSBrowseItem* pSelection = NULL;
|
|
for( pos = pBrowseItem->m_childList.GetHeadPosition(); pos != NULL; )
|
|
{
|
|
CDNSBrowseItem* pCurrentChild = pBrowseItem->m_childList.GetNext(pos);
|
|
|
|
// insert the name into the list view item, clear the subitem text
|
|
UINT nState = 0;
|
|
if (itemIndex == 0 )
|
|
{
|
|
nState = LVIS_SELECTED | LVIS_FOCUSED; // have at lest one item, select it
|
|
pSelection = pCurrentChild;
|
|
}
|
|
VERIFY(-1 != InsertItem(LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE,
|
|
itemIndex,
|
|
pCurrentChild->GetString(N_HEADER_NAME),
|
|
nState,
|
|
0,
|
|
pCurrentChild->GetImageIndex(FALSE),
|
|
(LPARAM)pCurrentChild));
|
|
// set the text for subitems
|
|
for (int iCol = N_HEADER_TYPE; iCol<N_DEFAULT_HEADER_COLS; iCol++)
|
|
VERIFY(SetItemText(itemIndex, iCol, pCurrentChild->GetString(iCol)));
|
|
|
|
// move to next index into the collection
|
|
itemIndex++;
|
|
}
|
|
m_pDlg->UpdateSelectionEdit(pSelection);
|
|
// enable/disable the OK button
|
|
GetParent()->GetDlgItem(IDOK)->EnableWindow(FALSE);
|
|
// enable/disable "UP" button
|
|
m_pDlg->m_toolbar.EnableButton(N_TOOLBAR_COMMAND_GO_UP, pBrowseItem->m_pParent != NULL);
|
|
}
|
|
|
|
CDNSBrowseItem* CDNSChildrenListView::GetSelection()
|
|
{
|
|
int nSel = GetNextItem(-1, LVIS_SELECTED);
|
|
return (nSel >= 0) ? (CDNSBrowseItem*)GetItemData(nSel) : NULL;
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// CDNSBrowserDlg
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CDNSBrowserDlg, CHelpDialog)
|
|
ON_COMMAND(N_TOOLBAR_COMMAND_GO_UP, OnButtonUp)
|
|
ON_NOTIFY_EX( TTN_NEEDTEXT, 0, OnTooltip)
|
|
ON_CBN_SELCHANGE(IDC_COMBO_SEL_NODE, OnSelchangeComboSelNode)
|
|
ON_NOTIFY(NM_DBLCLK, IDC_LIST_NODE_ITEMS, OnDblclkListNodeItems)
|
|
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_NODE_ITEMS, OnItemchangedListNodeItems)
|
|
ON_CBN_SELCHANGE(IDC_COMBO_FILTER, OnSelchangeComboFilter)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
CDNSBrowserDlg::CDNSBrowserDlg(CComponentDataObject* pComponentDataObject,
|
|
CPropertyPageHolderBase* pHolder,
|
|
DNSBrowseFilterOptionType option, BOOL bEnableEdit,
|
|
LPCTSTR lpszExcludeServerName)
|
|
: CHelpDialog(IDD_BROWSE_DIALOG, pComponentDataObject)
|
|
{
|
|
ASSERT(pComponentDataObject != NULL);
|
|
m_pComponentDataObject = pComponentDataObject;
|
|
m_pHolder = pHolder;
|
|
m_filter.Set(option, lpszExcludeServerName);
|
|
m_bEnableEdit = bEnableEdit;
|
|
|
|
// point to the DNS snapin static folder
|
|
m_pMasterRootNode = m_pComponentDataObject->GetRootData();
|
|
|
|
// create a browse root item
|
|
m_pBrowseRootItem = new CDNSBrowseItem;
|
|
if (m_pBrowseRootItem)
|
|
{
|
|
m_pBrowseRootItem->SetTreeNode(m_pMasterRootNode);
|
|
}
|
|
|
|
m_pCurrSelContainer = NULL;
|
|
m_pFinalSelection = NULL;
|
|
}
|
|
|
|
INT_PTR CDNSBrowserDlg::DoModal()
|
|
{
|
|
// make sure commoncontrolex initialized (for ComboBoxEx)
|
|
INITCOMMONCONTROLSEX icex;
|
|
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
icex.dwICC = ICC_USEREX_CLASSES;
|
|
if (!InitCommonControlsEx(&icex))
|
|
return -1;
|
|
|
|
return CHelpDialog::DoModal();
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnCancel()
|
|
{
|
|
if (m_pHolder != NULL)
|
|
m_pHolder->PopDialogHWnd();
|
|
CHelpDialog::OnCancel();
|
|
}
|
|
|
|
CDNSBrowserDlg::~CDNSBrowserDlg()
|
|
{
|
|
if (m_pBrowseRootItem != NULL)
|
|
{
|
|
delete m_pBrowseRootItem;
|
|
m_pBrowseRootItem = NULL;
|
|
}
|
|
}
|
|
|
|
CEdit* CDNSBrowserDlg::GetSelectionEdit()
|
|
{
|
|
return (CEdit*)GetDlgItem(IDC_SELECTION_EDIT);
|
|
}
|
|
|
|
|
|
CTreeNode* CDNSBrowserDlg::GetSelection()
|
|
{
|
|
if (m_pFinalSelection == NULL)
|
|
return NULL;
|
|
return m_pFinalSelection->GetTreeNode();
|
|
}
|
|
|
|
LPCTSTR CDNSBrowserDlg::GetSelectionString()
|
|
{
|
|
return m_szSelectionString;
|
|
}
|
|
|
|
|
|
BOOL CDNSBrowserDlg::OnInitDialog()
|
|
{
|
|
CHelpDialog::OnInitDialog();
|
|
if (m_pHolder != NULL)
|
|
m_pHolder->PushDialogHWnd(m_hWnd);
|
|
|
|
InitializeControls();
|
|
|
|
InitBrowseTree();
|
|
|
|
m_pCurrSelContainer = m_pBrowseRootItem;
|
|
m_currContainer.SetTree(m_pBrowseRootItem, m_pBrowseRootItem);
|
|
m_childrenList.SetChildren(m_pBrowseRootItem);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//////////// CBrowseDlg : message handlers ////////////////
|
|
|
|
void CDNSBrowserDlg::OnButtonUp()
|
|
{
|
|
CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
|
|
ASSERT(pSelectedBrowseItem != NULL);
|
|
if (pSelectedBrowseItem == NULL)
|
|
return;
|
|
ASSERT(pSelectedBrowseItem->m_pParent != NULL);
|
|
if (pSelectedBrowseItem->m_pParent == NULL)
|
|
return;
|
|
MoveUpHelper(pSelectedBrowseItem->m_pParent);
|
|
}
|
|
|
|
BOOL CDNSBrowserDlg::OnTooltip(UINT, NMHDR* pHdr, LRESULT* plRes)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
ASSERT(pHdr->code == TTN_NEEDTEXT);
|
|
LPTOOLTIPTEXT pTT = (LPTOOLTIPTEXT)(pHdr);
|
|
|
|
pTT->lpszText = (LPTSTR)IDS_BROWSE_TOOLTIP;
|
|
pTT->hinst = AfxGetApp()->m_hInstance;
|
|
*plRes = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnSelchangeComboSelNode()
|
|
{
|
|
CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
|
|
ASSERT(pSelectedBrowseItem != NULL);
|
|
if (pSelectedBrowseItem == NULL)
|
|
return;
|
|
MoveUpHelper(pSelectedBrowseItem);
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnDblclkListNodeItems(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
*pResult = 0;
|
|
ASSERT(pNMHDR->code == NM_DBLCLK);
|
|
HandleOkOrDblClick(reinterpret_cast<NMITEMACTIVATE*>(pNMHDR));
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnOK()
|
|
{
|
|
HandleOkOrDblClick();
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnItemchangedListNodeItems(NMHDR*, LRESULT*)
|
|
{
|
|
//EnableOkButton(m_filter.IsValidResult(pSelectedBrowseItem));
|
|
CDNSBrowseItem* pSelectedBrowseItem = m_childrenList.GetSelection();
|
|
BOOL bEnable = pSelectedBrowseItem != NULL;
|
|
if (bEnable)
|
|
bEnable = m_filter.IsValidResult(pSelectedBrowseItem) ||
|
|
pSelectedBrowseItem->IsContainer();
|
|
EnableOkButton(bEnable);
|
|
|
|
UpdateSelectionEdit(pSelectedBrowseItem);
|
|
}
|
|
|
|
void CDNSBrowserDlg::OnSelchangeComboFilter()
|
|
{
|
|
m_filter.OnSelectionChange();
|
|
ReEnumerateChildren();
|
|
|
|
GetSelectionEdit()->EnableWindow(m_bEnableEdit);//m_filter.Get() == SERVER);
|
|
}
|
|
|
|
////////////// CBrowseDlg : internal helpers //////////////////////
|
|
|
|
void CDNSBrowserDlg::InitializeToolbar()
|
|
{
|
|
CWnd* pWnd = GetDlgItem(IDC_TOOLBAR_CTRL);
|
|
CRect r;
|
|
pWnd->GetWindowRect(r);
|
|
ScreenToClient(r);
|
|
pWnd->DestroyWindow();
|
|
|
|
DWORD dwStyle = WS_CHILD | WS_VISIBLE | CCS_NORESIZE | CCS_TOP | CCS_NODIVIDER | TBSTYLE_TOOLTIPS ;
|
|
m_toolbar.Create(dwStyle,r,this, IDC_TOOLBAR_CTRL);
|
|
m_toolbar.AddBitmap(1, IDB_BROWSE_TOOLBAR);
|
|
TBBUTTON btn[2];
|
|
|
|
btn[0].iBitmap = 0; // zero-based index of button image
|
|
btn[0].idCommand = 0; // command to be sent when button pressed
|
|
btn[0].fsState = 0; // button state--see below
|
|
btn[0].fsStyle = TBSTYLE_SEP; // button style--see below
|
|
btn[0].dwData = 0; // application-defined value
|
|
btn[0].iString = NULL; // zero-based index of button label string
|
|
|
|
btn[1].iBitmap = 0; // zero-based index of button image
|
|
btn[1].idCommand = N_TOOLBAR_COMMAND_GO_UP; // command to be sent when button pressed
|
|
btn[1].fsState = TBSTATE_ENABLED; // button state--see below
|
|
btn[1].fsStyle = TBSTYLE_BUTTON; // button style--see below
|
|
btn[1].dwData = 0; // application-defined value
|
|
btn[1].iString = NULL; // zero-based index of button label string
|
|
|
|
m_toolbar.AddButtons(2, btn);
|
|
}
|
|
|
|
|
|
void CDNSBrowserDlg::InitializeControls()
|
|
{
|
|
// init the controls
|
|
VERIFY(m_currContainer.Initialize(IDC_COMBO_SEL_NODE, IDB_16x16, this));
|
|
VERIFY(m_childrenList.Initialize(IDC_LIST_NODE_ITEMS, IDB_16x16, this));
|
|
VERIFY(m_filter.Initialize(IDC_COMBO_FILTER, IDS_BROWSE_FILTER_OPTIONS, this));
|
|
|
|
InitializeToolbar();
|
|
|
|
GetSelectionEdit()->EnableWindow(m_bEnableEdit);//m_filter.Get() == SERVER);
|
|
}
|
|
|
|
void CDNSBrowserDlg::EnableOkButton(BOOL bEnable)
|
|
{
|
|
GetDlgItem(IDOK)->EnableWindow(bEnable);
|
|
}
|
|
|
|
void CDNSBrowserDlg::HandleOkOrDblClick(NMITEMACTIVATE* pItemActivate)
|
|
{
|
|
CDNSBrowseItem* pSelectedBrowseItem = NULL;
|
|
|
|
if (pItemActivate)
|
|
{
|
|
pSelectedBrowseItem = reinterpret_cast<CDNSBrowseItem*>(m_childrenList.GetItemData(pItemActivate->iItem));
|
|
}
|
|
else
|
|
{
|
|
pSelectedBrowseItem = m_childrenList.GetSelection();
|
|
}
|
|
ASSERT(pSelectedBrowseItem != NULL);
|
|
if (pSelectedBrowseItem == NULL)
|
|
return;
|
|
|
|
if (m_filter.IsValidResult(pSelectedBrowseItem))
|
|
{
|
|
if (m_bEnableEdit)
|
|
{
|
|
GetSelectionEdit()->GetWindowText(m_szSelectionString);
|
|
m_szSelectionString.TrimLeft();
|
|
m_szSelectionString.TrimRight();
|
|
}
|
|
m_pFinalSelection = pSelectedBrowseItem;
|
|
if (m_pHolder != NULL)
|
|
m_pHolder->PopDialogHWnd();
|
|
CHelpDialog::OnOK();
|
|
}
|
|
else
|
|
{
|
|
MoveDownHelper();
|
|
}
|
|
}
|
|
|
|
void CDNSBrowserDlg::UpdateSelectionEdit(CDNSBrowseItem* pBrowseItem)
|
|
{
|
|
if (pBrowseItem == NULL)
|
|
m_szSelectionString.Empty();
|
|
else
|
|
m_filter.GetStringOf(pBrowseItem, m_szSelectionString);
|
|
GetSelectionEdit()->SetWindowText(m_szSelectionString);
|
|
}
|
|
|
|
|
|
void CDNSBrowserDlg::InitBrowseTree()
|
|
{
|
|
ASSERT(m_pMasterRootNode != NULL);
|
|
ASSERT(m_pBrowseRootItem != NULL);
|
|
|
|
// assume we have no children
|
|
//ASSERT(m_pBrowseRootItem->m_childList.GetCount() == 0);
|
|
|
|
// get all the child nodes of the snapin root
|
|
AddTreeNodeChildrenHelper(m_pBrowseRootItem, &m_filter);
|
|
}
|
|
|
|
void CDNSBrowserDlg::ReEnumerateChildren()
|
|
{
|
|
ASSERT(m_pMasterRootNode != NULL);
|
|
ASSERT(m_pBrowseRootItem != NULL);
|
|
ASSERT(m_pCurrSelContainer != NULL);
|
|
m_pCurrSelContainer->RemoveChildren(NULL);
|
|
AddTreeNodeChildrenHelper(m_pCurrSelContainer, &m_filter);
|
|
m_childrenList.SetChildren(m_pCurrSelContainer);
|
|
}
|
|
|
|
void CDNSBrowserDlg::ExpandBrowseTree(CDNSBrowseItem* pCurrBrowseItem,
|
|
CDNSBrowseItem* pChildBrowseItem)
|
|
{
|
|
ASSERT(m_pMasterRootNode != NULL);
|
|
ASSERT(m_pBrowseRootItem != NULL);
|
|
ASSERT(pCurrBrowseItem != NULL);
|
|
ASSERT(pChildBrowseItem != NULL);
|
|
ASSERT(pChildBrowseItem->m_pParent == pCurrBrowseItem);
|
|
|
|
// we are going down one level:
|
|
// 1. remove all the children of the current item but the specified child
|
|
VERIFY(pCurrBrowseItem->RemoveChildren(pChildBrowseItem));
|
|
// 2. move down to the child
|
|
|
|
// 3. enumerate all the children of the specified child (filtering)
|
|
AddTreeNodeChildrenHelper(pChildBrowseItem, &m_filter);
|
|
}
|
|
|
|
void CDNSBrowserDlg::ContractBrowseTree(CDNSBrowseItem* pParentBrowseItem)
|
|
{
|
|
ASSERT(m_pMasterRootNode != NULL);
|
|
ASSERT(m_pBrowseRootItem != NULL);
|
|
ASSERT(pParentBrowseItem != NULL);
|
|
|
|
// we are going up one of more levels (possibly up to the root)
|
|
// 1. remove all the children below the specified item
|
|
pParentBrowseItem->RemoveChildren(NULL);
|
|
// 3. enumerate all the children of the specified item (filtering)
|
|
AddTreeNodeChildrenHelper(pParentBrowseItem, &m_filter);
|
|
}
|
|
|
|
|
|
void CDNSBrowserDlg::MoveUpHelper(CDNSBrowseItem* pNewBrowseItem)
|
|
{
|
|
ASSERT(m_pCurrSelContainer != NULL);
|
|
ASSERT(pNewBrowseItem != NULL);
|
|
|
|
if (m_pCurrSelContainer == pNewBrowseItem)
|
|
return; // the same was picked, nothing to do
|
|
|
|
#ifdef _DEBUG
|
|
// we assume that the new item is NOT a child of the current selection
|
|
CDNSBrowseItem* pItem = pNewBrowseItem;
|
|
BOOL bFound = FALSE;
|
|
while (pItem != NULL)
|
|
{
|
|
bFound = (pItem == m_pCurrSelContainer);
|
|
if (bFound)
|
|
break;
|
|
pItem = pItem->m_pParent;
|
|
}
|
|
ASSERT(!bFound);
|
|
#endif
|
|
|
|
ContractBrowseTree(pNewBrowseItem);
|
|
m_currContainer.SetTree(m_pBrowseRootItem, pNewBrowseItem);
|
|
m_childrenList.SetChildren(pNewBrowseItem);
|
|
|
|
// set new selection
|
|
m_pCurrSelContainer = pNewBrowseItem;
|
|
}
|
|
|
|
void CDNSBrowserDlg::MoveDownHelper()
|
|
{
|
|
CDNSBrowseItem* pChildBrowseItem = m_childrenList.GetSelection();
|
|
if (pChildBrowseItem == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// If it is not a container we should do something else, for now we will just return
|
|
//
|
|
if (!pChildBrowseItem->IsContainer())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// get the selection in the combobox
|
|
//
|
|
CDNSBrowseItem* pSelectedBrowseItem = m_currContainer.GetSelection();
|
|
ASSERT(pSelectedBrowseItem != NULL);
|
|
if (pSelectedBrowseItem == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ExpandBrowseTree(pSelectedBrowseItem, pChildBrowseItem);
|
|
m_currContainer.SetTree(m_pBrowseRootItem, pChildBrowseItem);
|
|
m_childrenList.SetChildren(pChildBrowseItem);
|
|
m_pCurrSelContainer = pChildBrowseItem;
|
|
SetForegroundWindow();
|
|
}
|
|
|
|
|
|
class CBrowseExecContext : public CExecContext
|
|
{
|
|
public:
|
|
virtual void Execute(LPARAM arg)
|
|
{
|
|
m_dlg->AddTreeNodeChildrenHelper(m_pBrowseItem, m_pFilter, (BOOL)arg);
|
|
}
|
|
CDNSBrowserDlg* m_dlg;
|
|
CDNSBrowseItem* m_pBrowseItem;
|
|
CDNSFilterCombo* m_pFilter;
|
|
};
|
|
|
|
void CDNSBrowserDlg::AddTreeNodeChildrenHelper(CDNSBrowseItem* pBrowseItem,
|
|
CDNSFilterCombo* pFilter, BOOL bExpand)
|
|
{
|
|
if (bExpand)
|
|
{
|
|
// need to do this always from the UI thread (main for Wiz, 2nd for prop pages)
|
|
CTreeNode* pTreeNode = pBrowseItem->GetTreeNode();
|
|
if (!pTreeNode->IsContainer())
|
|
return;
|
|
|
|
CContainerNode* pContNode = (CContainerNode*)pTreeNode;
|
|
if ( (pContNode->GetContainer() != NULL) && (!pContNode->IsEnumerated()) )
|
|
{
|
|
EnumerateMTNodeHelper((CMTContainerNode*)pContNode,
|
|
m_pComponentDataObject);
|
|
}
|
|
}
|
|
|
|
// have to figure out if we are running in the main thread
|
|
if (_MainThreadId == ::GetCurrentThreadId())
|
|
{
|
|
pBrowseItem->AddTreeNodeChildren(pFilter, m_pComponentDataObject);
|
|
return;
|
|
}
|
|
// we are from a secondary thread, execute in the context for the main
|
|
// thread by posting a message and waiting
|
|
ASSERT(m_pComponentDataObject != NULL);
|
|
CBrowseExecContext ctx;
|
|
ctx.m_dlg = this;
|
|
ctx.m_pBrowseItem = pBrowseItem;
|
|
ctx.m_pFilter = pFilter;
|
|
|
|
TRACE(_T("before post message()\n"));
|
|
VERIFY(m_pComponentDataObject->PostExecMessage(&ctx,(WPARAM)FALSE));
|
|
ctx.Wait();
|
|
|
|
TRACE(_T("after wait()\n"));
|
|
}
|
|
|