// Copyright (C) Microsoft Corporation, 1998 - 1999 // // create new site and new subnet wizards // // 4-24-98 sburns // 9-23-98 jonn Subclassed off New Subnet Wizard #include "stdafx.h" #include "resource.h" #include "dsutil.h" #include "newobj.h" #include "dlgcreat.h" #include "querysup.h" #pragma warning (disable: 4100) #include // pair<> #include #pragma warning (default: 4100) extern "C" { #include // DsValidateSubnetName } #define BREAK_ON_FAILED_HRESULT(hr) \ if (FAILED(hr)) \ { \ ASSERT(FALSE); \ break; \ } #define BREAK_ON_NULL(p) \ if (NULL == p) \ { \ ASSERT(FALSE); \ break; \ } // first in the pair is name of link, second is dn of the link typedef std::pair< CComBSTR, CComBSTR > TargetLinkInfo; typedef std::list< TargetLinkInfo > TargetLinkList; CreateNewSiteWizard::CreateNewSiteWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&page); } CreateNewSubnetWizard::CreateNewSubnetWizard( CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo) { AddPage(&page); } BEGIN_MESSAGE_MAP(CreateAndChoosePage, CCreateNewNamedObjectPage) ON_WM_DESTROY() END_MESSAGE_MAP() BEGIN_MESSAGE_MAP(CreateNewSubnetPage, CreateAndChoosePage) ON_EN_CHANGE(IDC_SUBNET_ADDRESS, OnSubnetMaskChange) ON_EN_CHANGE(IDC_SUBNET_MASK, OnSubnetMaskChange) END_MESSAGE_MAP() CreateAndChoosePage::CreateAndChoosePage(UINT nIDTemplate) : CCreateNewNamedObjectPage(nIDTemplate), listview(0), listview_imagelist(0) { } CreateNewSitePage::CreateNewSitePage() : CreateAndChoosePage(IDD_CREATE_NEW_SITE) { } CreateNewSubnetPage::CreateNewSubnetPage() : CreateAndChoosePage(IDD_CREATE_NEW_SUBNET) { } HRESULT CreateNewSitePage::SetData(BOOL bSilent) { if (0 < ListView_GetItemCount(listview)) { if (0 >= ListView_GetSelectedCount(listview)) { if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_NEW_SITE_SELECT_SITELINK,S_OK, MB_OK, NULL, 0); } (void) this->PostMessage( WM_NEXTDLGCTL, (WPARAM)listview, TRUE ); return E_FAIL; } } return CreateAndChoosePage::SetData(bSilent); } HRESULT CreateNewSubnetPage::SetData(BOOL bSilent) { CNewADsObjectCreateInfo* info = GetWiz()->GetInfo(); ASSERT(info); HRESULT hr = E_FAIL; if (!info) return hr; int count = ListView_GetItemCount(listview); if (count > 0) { if (0 >= ListView_GetSelectedCount(listview)) { if (!bSilent) { ReportErrorEx (::GetParent(m_hWnd),IDS_NEW_SUBNET_SELECT_SITE,S_OK, MB_OK, NULL, 0); } (void) this->PostMessage( WM_NEXTDLGCTL, (WPARAM)listview, TRUE ); return E_FAIL; } for (int i = 0; i < count; i++) { if (ListView_GetItemState(listview, i, LVIS_SELECTED)) { LVITEM item = {0}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(listview, &item)) { // the item.lParam field is the dn of the target site CComBSTR* dn = reinterpret_cast(item.lParam); hr = info->HrAddVariantBstrIfNotEmpty( const_cast(gsz_siteObject), *dn, TRUE ); // HrCreateNew has not been called yet if ( FAILED(hr) ) { ASSERT(FALSE); return hr; } // use the first site selected break; } } } ASSERT( i < count ); } return CreateAndChoosePage::SetData(bSilent); } HRESULT CreateNewSitePage::tweakSiteLink(LPCTSTR siteDN) { ASSERT(siteDN); HRESULT hr = S_OK; do { // get the DN of the new site // this is a pointer alias: no need to AddRef/Release hr = E_FAIL; CPathCracker pathCracker; CCreateNewObjectWizardBase* pwiz = GetWiz(); BREAK_ON_NULL(pwiz); CNewADsObjectCreateInfo* pinfo = pwiz->GetInfo(); BREAK_ON_NULL(pinfo); IADs* piadsSite = pinfo->PGetIADsPtr(); BREAK_ON_NULL(piadsSite); CComBSTR sbstrSitePath; hr = piadsSite->get_ADsPath( &sbstrSitePath ); BREAK_ON_FAILED_HRESULT(hr); hr = pathCracker.Set(sbstrSitePath, ADS_SETTYPE_FULL); BREAK_ON_FAILED_HRESULT(hr); CComBSTR sbstrSiteDN; hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL); BREAK_ON_FAILED_HRESULT(hr); hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &sbstrSiteDN); BREAK_ON_FAILED_HRESULT(hr); // munge together the path name of the site link object hr = pathCracker.Set( const_cast(siteDN), ADS_SETTYPE_DN); BREAK_ON_FAILED_HRESULT(hr); CComBSTR sbstrSiteLinkPath; hr = pathCracker.Retrieve(ADS_FORMAT_X500, &sbstrSiteLinkPath); BREAK_ON_FAILED_HRESULT(hr); // bind to the site link CComPtr link; hr = DSAdminOpenObject(sbstrSiteLinkPath, IID_IADs, (void**) &link, FALSE /*bServer*/); BREAK_ON_FAILED_HRESULT(hr); ASSERT(link); // Add the DN of the new site to the siteList attr of the link object // build the new value CComVariant var; hr = ADsBuildVarArrayStr(&sbstrSiteDN, 1, &var); BREAK_ON_FAILED_HRESULT(hr); // write it. whew. hr = link->PutEx( ADS_PROPERTY_APPEND, const_cast(gsz_siteList), var); BREAK_ON_FAILED_HRESULT(hr); hr = link->SetInfo(); BREAK_ON_FAILED_HRESULT(hr); } while (0); if (FAILED(hr)) { ReportError(hr, IDS_ERROR_TWEAKING_SITE_LINK, m_hWnd); } return hr; } HRESULT CreateNewSitePage::OnPostCommit(BOOL bSilent) { ASSERT(listview); int count = ListView_GetItemCount(listview); if (count > 0) { for (int i = 0; i < count; i++) { if (ListView_GetItemState(listview, i, LVIS_SELECTED)) { LVITEM item = {0}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(listview, &item)) { // the item.lParam field is the dn of the target link CComBSTR* dn = reinterpret_cast(item.lParam); tweakSiteLink(*dn); // only tweak the first site link selected return S_OK; } } } } if (!bSilent) { ReportMessageEx( m_hWnd, IDS_NEWSITE_WARNING, MB_OK | MB_ICONWARNING, NULL, 0, IDS_WARNING_TITLE); } return S_OK; } HRESULT RecursiveFind(const CString& lpcwszADsPathDirectory, LPCTSTR lpcwszTargetClass, TargetLinkList& links, LPWSTR pszAttribute = L"distinguishedName"); HRESULT RecursiveFind(const CString& lpcwszADsPathDirectory, LPCTSTR lpcwszTargetClass, TargetLinkList& links, LPWSTR pszAttribute) { links.clear(); CDSSearch Search; Search.Init(lpcwszADsPathDirectory); CString filter; filter.Format(L"(objectClass=%s)", lpcwszTargetClass); Search.SetFilterString(const_cast((LPCTSTR) filter)); LPWSTR pAttrs[2] = { L"name", pszAttribute }; Search.SetAttributeList(pAttrs, 2); Search.SetSearchScope(ADS_SCOPE_SUBTREE); HRESULT hr = Search.DoQuery(); while (SUCCEEDED(hr)) { hr = Search.GetNextRow(); if (S_ADS_NOMORE_ROWS == hr) { hr = S_OK; break; } BREAK_ON_FAILED_HRESULT(hr); ADS_SEARCH_COLUMN NameColumn; ::ZeroMemory(&NameColumn, sizeof(NameColumn)); hr = Search.GetColumn (pAttrs[0], &NameColumn); BREAK_ON_FAILED_HRESULT(hr); ASSERT(ADSTYPE_CASE_IGNORE_STRING == NameColumn.pADsValues->dwType); ADS_SEARCH_COLUMN DistinguishedNameColumn; ::ZeroMemory(&DistinguishedNameColumn, sizeof(DistinguishedNameColumn)); hr = Search.GetColumn (pAttrs[1], &DistinguishedNameColumn); BREAK_ON_FAILED_HRESULT(hr); ASSERT(ADSTYPE_DN_STRING == DistinguishedNameColumn.pADsValues->dwType || ADSTYPE_CASE_IGNORE_STRING == DistinguishedNameColumn.pADsValues->dwType); links.push_back( TargetLinkInfo( NameColumn.pADsValues->CaseIgnoreString, DistinguishedNameColumn.pADsValues->DNString)); Search.FreeColumn(&NameColumn); Search.FreeColumn(&DistinguishedNameColumn); } #ifdef DBG // dump the list to the debugger for ( TargetLinkList::iterator i = links.begin(); i != links.end(); i++) { OutputDebugString(i->first); OutputDebugString(L"\n"); OutputDebugString(i->second); OutputDebugString(L"\n"); } #endif return hr; } BOOL CreateAndChoosePage::OnSetActive() { CComQIPtr container(GetWiz()->GetInfo()->m_pIADsContainer); if (container) { CComBSTR container_path; container->get_ADsPath(&container_path); initListContents(container_path); } return Base::OnSetActive(); } void destroyListContents(HWND listview) { ASSERT(listview); for (int i = ListView_GetItemCount(listview) - 1; i >= 0; i--) { LVITEM item = {0}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(listview, &item)) { ASSERT(item.lParam); delete reinterpret_cast(item.lParam); ListView_DeleteItem(listview, i); return; } } } void CreateAndChoosePage::OnDestroy() { destroyListContents(listview); Base::OnDestroy(); } void CreateNewSitePage::initListContents(LPCWSTR containerPath) { ASSERT(listview); CWaitCursor cwait; TargetLinkList links; bool links_present = false; HRESULT hr = RecursiveFind(containerPath, gsz_siteLink, links); if (SUCCEEDED(hr)) { // walk the list and add nodes for ( TargetLinkList::iterator i = links.begin(); i != links.end(); i++) { LVITEM item = {0}; memset(&item, 0, sizeof(item)); // this is deleted in destroyListContents CComBSTR* dn = new CComBSTR(i->second); item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; item.pszText = static_cast(i->first); item.lParam = reinterpret_cast(dn); item.iImage = 0; // always the same, first image item.iItem = ListView_InsertItem(listview, &item); ASSERT(item.iItem >= 0); // add the transport sub-item to the list control CPathCracker pathCracker; hr = pathCracker.Set( static_cast(i->second), ADS_SETTYPE_DN); ASSERT(SUCCEEDED(hr)); hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY); ASSERT(SUCCEEDED(hr)); CComBSTR b; hr = pathCracker.GetElement(1, &b); ASSERT(SUCCEEDED(hr)); hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL); ASSERT(SUCCEEDED(hr)); item.mask = LVIF_TEXT; item.iSubItem = 1; item.pszText = b; ListView_SetItem(listview, &item); links_present = true; } if (!links_present) { ReportError(hr, IDS_WARNING_NO_SITE_LINKS, m_hWnd); } } else { ReportError(hr, IDS_CANT_FIND_SITE_LINKS, m_hWnd); } if (!links_present) { GetDlgItem(IDC_LINKS)->EnableWindow(FALSE); GetDlgItem(IDC_SITE_TEXT)->EnableWindow(FALSE); } else // JonN 3/28/01 319675 { ListView_SetItemState( listview, 0, LVIS_FOCUSED, LVIS_FOCUSED ); } } void CreateNewSubnetPage::initListContents(LPCWSTR containerPath) { ASSERT(listview); CWaitCursor cwait; TargetLinkList links; bool links_present = false; CComBSTR sbstrSites; CPathCracker pathCracker; HRESULT hr = pathCracker.Set( const_cast(containerPath), ADS_SETTYPE_FULL); if (SUCCEEDED(hr)) hr = pathCracker.RemoveLeafElement(); if (SUCCEEDED(hr)) hr = pathCracker.Retrieve(ADS_FORMAT_X500, &sbstrSites); if (SUCCEEDED(hr)) hr = RecursiveFind((LPCTSTR)sbstrSites, gsz_site, links); if (SUCCEEDED(hr)) { // walk the list and add nodes for ( TargetLinkList::iterator i = links.begin(); i != links.end(); i++) { LVITEM item; memset(&item, 0, sizeof(item)); // this is deleted in destroyListContents CComBSTR* dn = new CComBSTR(i->second); item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; item.pszText = static_cast(i->first); item.lParam = reinterpret_cast(dn); item.iImage = 0; // always the same, first image item.iItem = ListView_InsertItem(listview, &item); ASSERT(item.iItem >= 0); links_present = true; } if (!links_present) { ReportError(hr, IDS_NEWSUBNET_WARNING_NO_SITES, m_hWnd); } } else { ReportError(hr, IDS_NEWSUBNET_CANT_FIND_SITES, m_hWnd); } if (!links_present) { GetDlgItem(IDC_LINKS)->EnableWindow(FALSE); GetDlgItem(IDC_SITE_TEXT)->EnableWindow(FALSE); } } BOOL CreateNewSitePage::OnInitDialog() { Base::OnInitDialog(); MyBasePathsInfo* pBasePathsInfo = GetWiz()->GetInfo()->GetBasePathsInfo(); listview = ::GetDlgItem(m_hWnd, IDC_LINKS); ASSERT(listview); LVCOLUMN column = {0}; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_LEFT; { // open scope CString w; w.LoadString(IDS_NEW_SITE_NAME_COLUMN_WIDTH); w.TrimLeft(); w.TrimRight(); long width = _tcstol(w, 0, 10); ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN); column.cx = width; CString label; label.LoadString(IDS_NEW_SITE_NAME_COLUMN); column.pszText = const_cast((LPCTSTR) label); ListView_InsertColumn(listview, 0, &column); } // close scope // add a column to the list view for parent transport. { // open scope CString w; w.LoadString(IDS_NEW_SITE_XPORT_COLUMN_WIDTH); w.TrimLeft(); w.TrimRight(); long width = _tcstol(w, 0, 10); ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN); column.cx = width; CString label; label.LoadString(IDS_NEW_SITE_XPORT_COLUMN); column.pszText = const_cast((LPCTSTR) label); ListView_InsertColumn(listview, 1, &column); } // close scope // create the image list containing the site link icon int cx = ::GetSystemMetrics(SM_CXSMICON); int cy = ::GetSystemMetrics(SM_CYSMICON); ASSERT(cx && cy); // deleted in OnDestroy listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0); ASSERT(listview_imagelist); HICON icon = pBasePathsInfo->GetIcon( // someone really blew it with const correctness... const_cast(gsz_siteLink), DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON, 16, 16); ASSERT(icon); int i = ::ImageList_AddIcon(listview_imagelist, icon); ASSERT(i != -1); DestroyIcon(icon); ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL); ListView_SetExtendedListViewStyleEx( listview, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); return TRUE; } BOOL CreateNewSubnetPage::OnInitDialog() { Base::OnInitDialog(); MyBasePathsInfo* pBasePathsInfo = GetWiz()->GetInfo()->GetBasePathsInfo(); (void) SendDlgItemMessage( IDC_SUBNET_ADDRESS, IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(0,0,0,0) ); (void) SendDlgItemMessage( IDC_SUBNET_MASK, IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(0,0,0,0) ); listview = ::GetDlgItem(m_hWnd, IDC_LINKS); ASSERT(listview); { // open scope LVCOLUMN column = {0}; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_LEFT; CString w; w.LoadString(IDS_COLUMN_SITE_WIDTH); w.TrimLeft(); w.TrimRight(); long width = _tcstol(w, 0, 10); ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN); column.cx = width; CString label; label.LoadString(IDS_COLUMN_SITE_NAME); column.pszText = const_cast((LPCTSTR) label); ListView_InsertColumn(listview, 0, &column); } // close scope // create the image list containing the site link icon int cx = ::GetSystemMetrics(SM_CXSMICON); int cy = ::GetSystemMetrics(SM_CYSMICON); ASSERT(cx && cy); // deleted in OnDestroy listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0); ASSERT(listview_imagelist); HICON icon = pBasePathsInfo->GetIcon( // someone really blew it with const correctness... const_cast(gsz_site), DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON | DSGIF_DEFAULTISCONTAINER, 16, 16); ASSERT(icon); int i = ::ImageList_AddIcon(listview_imagelist, icon); ASSERT(i != -1); DestroyIcon(icon); ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL); ListView_SetExtendedListViewStyleEx( listview, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); return TRUE; } BOOL CreateNewSitePage::ValidateName(LPCTSTR pcszName) { BOOL fNonRfcSiteName = FALSE; BOOL fValidSiteName = IsValidSiteName( pcszName, &fNonRfcSiteName ); if ( !fValidSiteName ) { ReportErrorEx (::GetParent(m_hWnd),IDS_SITE_NAME,S_OK, MB_OK, NULL, 0); } else if ( fNonRfcSiteName ) { PVOID apv[1]; apv[0] = (PVOID)pcszName; if (IDYES != ReportMessageEx( ::GetParent(m_hWnd), IDS_1_NON_RFC_SITE_NAME, MB_YESNO | MB_ICONWARNING, apv, 1 ) ) { fValidSiteName = FALSE; } } if ( !fValidSiteName ) { // Yes, this really does have to be PostMessage, SendMessage doesn't work // It also has to come after ReportErrorEx or else it doesn't work (void) this->PostMessage( WM_NEXTDLGCTL, (WPARAM)::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME), TRUE ); (void) ::PostMessage( ::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME), EM_SETSEL, 0, -1 ); return FALSE; } return TRUE; } // JonN 5/11/01 251560 Disable OK until site link chosen BEGIN_MESSAGE_MAP(CreateNewSitePage, CreateAndChoosePage) ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnChange) ON_NOTIFY(LVN_ITEMCHANGED, IDC_LINKS, OnSelChange) END_MESSAGE_MAP() afx_msg void CreateNewSitePage::OnSelChange( NMHDR*, LRESULT* ) { OnChange(); } void CreateNewSitePage::OnChange() { if (0 >= ListView_GetSelectedCount(listview)) GetWiz()->SetWizardButtons(this, FALSE); else OnNameChange(); // Enable the OK button only if the name is not empty } // no need to validate subnet name, MapMaskAndAddress does this // return -32 for invalid mask int CountBits( DWORD dwOctet ) { if ( 0xff < dwOctet ) { ASSERT(FALSE); return -32; } for (int nBits = 0; dwOctet & 0x80; nBits++) dwOctet = (dwOctet & ~0x80) * 2; if (dwOctet != 0) return -32; // hole in the mask return nBits; } // returns <0 for invalid mask int CountMaskedBits( DWORD dwMask ) { int nFirstOctet = FIRST_IPADDRESS(dwMask); int nSecondOctet = SECOND_IPADDRESS(dwMask); int nThirdOctet = THIRD_IPADDRESS(dwMask); int nFourthOctet = FOURTH_IPADDRESS(dwMask); if (nFirstOctet < 255) { if (0 != nSecondOctet || 0 != nThirdOctet || 0 != nFourthOctet) return -1; return CountBits(nFirstOctet); } if (nSecondOctet < 255) { if (255 != nFirstOctet || 0 != nThirdOctet || 0 != nFourthOctet) return -1; return 8 + CountBits(nSecondOctet); } if (nThirdOctet < 255) { if (255 != nFirstOctet || 255 != nSecondOctet || 0 != nFourthOctet) return -1; return 16 + CountBits(nThirdOctet); } if (255 != nFirstOctet || 255 != nSecondOctet || 255 != nThirdOctet) return -1; return 24 + CountBits(nFourthOctet); } // returns empty string for invalid address+mask void MapMaskAndAddress( OUT CString& strrefSubnetName, IN DWORD dwAddress, IN DWORD dwMask ) { strrefSubnetName.Empty(); dwAddress &= dwMask; // clear all bits set in the address and not in the mask int nMaskedBits = CountMaskedBits( dwMask ); if (0 > nMaskedBits) return; // invalid mask strrefSubnetName.Format(L"%d.%d.%d.%d/%d", FIRST_IPADDRESS(dwAddress), SECOND_IPADDRESS(dwAddress), THIRD_IPADDRESS(dwAddress), FOURTH_IPADDRESS(dwAddress), nMaskedBits); // final test for edge cases such as "0.0.0.0/0" if (ERROR_SUCCESS != ::DsValidateSubnetName( strrefSubnetName )) strrefSubnetName.Empty(); } void CreateNewSubnetPage::OnSubnetMaskChange() { DWORD dwAddress, dwMask; CString strSubnetName; // IPM_GETADDRESS returns the number of octets filled in. Address is // invalid if any of the four is left blank. if ( 4 == SendDlgItemMessage( IDC_SUBNET_ADDRESS, IPM_GETADDRESS, 0, (LPARAM)&dwAddress ) && 4 == SendDlgItemMessage( IDC_SUBNET_MASK, IPM_GETADDRESS, 0, (LPARAM)&dwMask ) ) { MapMaskAndAddress( strSubnetName, dwAddress, dwMask ); } SetDlgItemText(IDC_EDIT_OBJECT_NAME, strSubnetName); OnNameChange(); } BEGIN_MESSAGE_MAP(CMoveServerDialog, CDialog) //{{AFX_MSG_MAP(CMoveServerDialog) ON_WM_DESTROY() ON_NOTIFY(NM_DBLCLK, IDC_LINKS, OnDblclkListview) //}}AFX_MSG_MAP END_MESSAGE_MAP() CMoveServerDialog::CMoveServerDialog(LPCTSTR lpcszBrowseRootPath, HICON hIcon, CWnd* pParent /*=NULL*/) : CDialog(CMoveServerDialog::IDD, pParent) , m_strTargetContainer() , m_strBrowseRootPath(lpcszBrowseRootPath) , m_hIcon(hIcon) , listview(0) , listview_imagelist(0) {} BOOL CMoveServerDialog::OnInitDialog() { CDialog::OnInitDialog(); CWaitCursor cwait; listview = ::GetDlgItem(m_hWnd, IDC_LINKS); ASSERT(listview); { // open scope LVCOLUMN column = {0}; column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; column.fmt = LVCFMT_LEFT; CString w; w.LoadString(IDS_COLUMN_SITE_WIDTH); w.TrimLeft(); w.TrimRight(); long width = _tcstol(w, 0, 10); ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN); column.cx = width; CString label; label.LoadString(IDS_COLUMN_SITE_NAME); column.pszText = const_cast((LPCTSTR) label); ListView_InsertColumn(listview, 0, &column); } // close scope // create the image list containing the site link icon int cx = ::GetSystemMetrics(SM_CXSMICON); int cy = ::GetSystemMetrics(SM_CYSMICON); ASSERT(cx && cy); // deleted in OnDestroy listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0); ASSERT(listview_imagelist); ASSERT(m_hIcon != NULL); int i = ::ImageList_AddIcon(listview_imagelist, m_hIcon); ASSERT(i != -1); ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL); ListView_SetExtendedListViewStyleEx( listview, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); // add sites to listview TargetLinkList links; bool links_present = false; HRESULT hr = RecursiveFind(m_strBrowseRootPath, gsz_serversContainer, links, L"aDSPath"); if (SUCCEEDED(hr)) { // walk the list and add nodes for ( TargetLinkList::iterator itr = links.begin(); itr != links.end(); ++itr) { LVITEM item; memset(&item, 0, sizeof(item)); // Since the enumerated objects are of type serversContainer, // we display the name of the parent. Also, the aDSPath attribute may // contain a server indication, which must be removed. CPathCracker pathCracker; hr = pathCracker.Set( itr->second, ADS_SETTYPE_FULL ); BREAK_ON_FAILED_HRESULT(hr); hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY); BREAK_ON_FAILED_HRESULT(hr); CComBSTR sbstrName; hr = pathCracker.GetElement( 1L, &sbstrName ); BREAK_ON_FAILED_HRESULT(hr); hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL); BREAK_ON_FAILED_HRESULT(hr); CComBSTR sbstrDN; hr = pathCracker.Retrieve( ADS_FORMAT_X500, &sbstrDN ); BREAK_ON_FAILED_HRESULT(hr); // this is deleted in destroyListContents CComBSTR* dn = new CComBSTR(sbstrDN); item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.iItem = 0; item.iSubItem = 0; item.pszText = static_cast(sbstrName); item.lParam = reinterpret_cast(dn); item.iImage = 0; // always the same, first image item.iItem = ListView_InsertItem(listview, &item); ASSERT(item.iItem >= 0); links_present = true; } if (!links_present) { ReportError(hr, IDS_MOVESERVER_ERROR_NO_SITES, m_hWnd); OnCancel(); } } if ( FAILED(hr) ) { ReportError(hr, IDS_MOVESERVER_ERROR_ENUMERATING_SITES, m_hWnd); OnCancel(); } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CMoveServerDialog::OnDestroy() { destroyListContents(listview); CDialog::OnDestroy(); } void CMoveServerDialog::OnOK() { int count = ListView_GetItemCount(listview); if (count > 0) { if (0 >= ListView_GetSelectedCount(listview)) { ReportErrorEx (m_hWnd,IDS_MOVESERVER_SELECT_SITE,S_OK, MB_OK, NULL, 0); (void) this->PostMessage( WM_NEXTDLGCTL, (WPARAM)listview, TRUE ); return; } for (int i = 0; i < count; i++) { if (ListView_GetItemState(listview, i, LVIS_SELECTED)) { LVITEM item = {0}; item.mask = LVIF_PARAM; item.iItem = i; if (ListView_GetItem(listview, &item)) { // the item.lParam field is the dn of the target site CComBSTR* dn = reinterpret_cast(item.lParam); m_strTargetContainer = *dn; // use the first site selected break; } } } ASSERT( i < count ); } CDialog::OnOK(); } void CMoveServerDialog::OnDblclkListview(NMHDR*, LRESULT*) { OnOK(); }