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.

1065 lines
28 KiB

  1. // Copyright (C) Microsoft Corporation, 1998 - 1999
  2. //
  3. // create new site and new subnet wizards
  4. //
  5. // 4-24-98 sburns
  6. // 9-23-98 jonn Subclassed off New Subnet Wizard
  7. #include "stdafx.h"
  8. #include "resource.h"
  9. #include "dsutil.h"
  10. #include "newobj.h"
  11. #include "dlgcreat.h"
  12. #include "querysup.h"
  13. #pragma warning (disable: 4100)
  14. #include <utility> // pair<>
  15. #include <list>
  16. #pragma warning (default: 4100)
  17. extern "C"
  18. {
  19. #include <dsgetdc.h> // DsValidateSubnetName
  20. }
  21. #define BREAK_ON_FAILED_HRESULT(hr) \
  22. if (FAILED(hr)) \
  23. { \
  24. ASSERT(FALSE); \
  25. break; \
  26. }
  27. #define BREAK_ON_NULL(p) \
  28. if (NULL == p) \
  29. { \
  30. ASSERT(FALSE); \
  31. break; \
  32. }
  33. // first in the pair is name of link, second is dn of the link
  34. typedef std::pair< CComBSTR, CComBSTR > TargetLinkInfo;
  35. typedef std::list< TargetLinkInfo > TargetLinkList;
  36. CreateNewSiteWizard::CreateNewSiteWizard(
  37. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo)
  38. :
  39. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  40. {
  41. AddPage(&page);
  42. }
  43. CreateNewSubnetWizard::CreateNewSubnetWizard(
  44. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo)
  45. :
  46. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  47. {
  48. AddPage(&page);
  49. }
  50. BEGIN_MESSAGE_MAP(CreateAndChoosePage, CCreateNewNamedObjectPage)
  51. ON_WM_DESTROY()
  52. END_MESSAGE_MAP()
  53. BEGIN_MESSAGE_MAP(CreateNewSubnetPage, CreateAndChoosePage)
  54. ON_EN_CHANGE(IDC_SUBNET_ADDRESS, OnSubnetMaskChange)
  55. ON_EN_CHANGE(IDC_SUBNET_MASK, OnSubnetMaskChange)
  56. END_MESSAGE_MAP()
  57. CreateAndChoosePage::CreateAndChoosePage(UINT nIDTemplate)
  58. :
  59. CCreateNewNamedObjectPage(nIDTemplate),
  60. listview(0),
  61. listview_imagelist(0)
  62. {
  63. }
  64. CreateNewSitePage::CreateNewSitePage()
  65. :
  66. CreateAndChoosePage(IDD_CREATE_NEW_SITE)
  67. {
  68. }
  69. CreateNewSubnetPage::CreateNewSubnetPage()
  70. :
  71. CreateAndChoosePage(IDD_CREATE_NEW_SUBNET)
  72. {
  73. }
  74. HRESULT
  75. CreateNewSitePage::SetData(BOOL bSilent)
  76. {
  77. if (0 < ListView_GetItemCount(listview))
  78. {
  79. if (0 >= ListView_GetSelectedCount(listview))
  80. {
  81. if (!bSilent)
  82. {
  83. ReportErrorEx (::GetParent(m_hWnd),IDS_NEW_SITE_SELECT_SITELINK,S_OK,
  84. MB_OK, NULL, 0);
  85. }
  86. (void) this->PostMessage( WM_NEXTDLGCTL,
  87. (WPARAM)listview,
  88. TRUE );
  89. return E_FAIL;
  90. }
  91. }
  92. return CreateAndChoosePage::SetData(bSilent);
  93. }
  94. HRESULT
  95. CreateNewSubnetPage::SetData(BOOL bSilent)
  96. {
  97. CNewADsObjectCreateInfo* info = GetWiz()->GetInfo();
  98. ASSERT(info);
  99. HRESULT hr = E_FAIL;
  100. if (!info)
  101. return hr;
  102. int count = ListView_GetItemCount(listview);
  103. if (count > 0)
  104. {
  105. if (0 >= ListView_GetSelectedCount(listview))
  106. {
  107. if (!bSilent)
  108. {
  109. ReportErrorEx (::GetParent(m_hWnd),IDS_NEW_SUBNET_SELECT_SITE,S_OK,
  110. MB_OK, NULL, 0);
  111. }
  112. (void) this->PostMessage( WM_NEXTDLGCTL,
  113. (WPARAM)listview,
  114. TRUE );
  115. return E_FAIL;
  116. }
  117. for (int i = 0; i < count; i++)
  118. {
  119. if (ListView_GetItemState(listview, i, LVIS_SELECTED))
  120. {
  121. LVITEM item = {0};
  122. item.mask = LVIF_PARAM;
  123. item.iItem = i;
  124. if (ListView_GetItem(listview, &item))
  125. {
  126. // the item.lParam field is the dn of the target site
  127. CComBSTR* dn = reinterpret_cast<CComBSTR*>(item.lParam);
  128. hr = info->HrAddVariantBstrIfNotEmpty(
  129. const_cast<PWSTR>(gsz_siteObject),
  130. *dn,
  131. TRUE ); // HrCreateNew has not been called yet
  132. if ( FAILED(hr) )
  133. {
  134. ASSERT(FALSE);
  135. return hr;
  136. }
  137. // use the first site selected
  138. break;
  139. }
  140. }
  141. }
  142. ASSERT( i < count );
  143. }
  144. return CreateAndChoosePage::SetData(bSilent);
  145. }
  146. HRESULT
  147. CreateNewSitePage::tweakSiteLink(LPCTSTR siteDN)
  148. {
  149. ASSERT(siteDN);
  150. HRESULT hr = S_OK;
  151. do
  152. {
  153. // get the DN of the new site
  154. // this is a pointer alias: no need to AddRef/Release
  155. hr = E_FAIL;
  156. CPathCracker pathCracker;
  157. CCreateNewObjectWizardBase* pwiz = GetWiz();
  158. BREAK_ON_NULL(pwiz);
  159. CNewADsObjectCreateInfo* pinfo = pwiz->GetInfo();
  160. BREAK_ON_NULL(pinfo);
  161. IADs* piadsSite = pinfo->PGetIADsPtr();
  162. BREAK_ON_NULL(piadsSite);
  163. CComBSTR sbstrSitePath;
  164. hr = piadsSite->get_ADsPath( &sbstrSitePath );
  165. BREAK_ON_FAILED_HRESULT(hr);
  166. hr = pathCracker.Set(sbstrSitePath, ADS_SETTYPE_FULL);
  167. BREAK_ON_FAILED_HRESULT(hr);
  168. CComBSTR sbstrSiteDN;
  169. hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  170. BREAK_ON_FAILED_HRESULT(hr);
  171. hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &sbstrSiteDN);
  172. BREAK_ON_FAILED_HRESULT(hr);
  173. // munge together the path name of the site link object
  174. hr = pathCracker.Set( const_cast<LPTSTR>(siteDN), ADS_SETTYPE_DN);
  175. BREAK_ON_FAILED_HRESULT(hr);
  176. CComBSTR sbstrSiteLinkPath;
  177. hr = pathCracker.Retrieve(ADS_FORMAT_X500, &sbstrSiteLinkPath);
  178. BREAK_ON_FAILED_HRESULT(hr);
  179. // bind to the site link
  180. CComPtr<IADs> link;
  181. hr = DSAdminOpenObject(sbstrSiteLinkPath,
  182. IID_IADs,
  183. (void**) &link,
  184. FALSE /*bServer*/);
  185. BREAK_ON_FAILED_HRESULT(hr);
  186. ASSERT(link);
  187. // Add the DN of the new site to the siteList attr of the link object
  188. // build the new value
  189. CComVariant var;
  190. hr = ADsBuildVarArrayStr(&sbstrSiteDN, 1, &var);
  191. BREAK_ON_FAILED_HRESULT(hr);
  192. // write it. whew.
  193. hr =
  194. link->PutEx(
  195. ADS_PROPERTY_APPEND,
  196. const_cast<LPTSTR>(gsz_siteList),
  197. var);
  198. BREAK_ON_FAILED_HRESULT(hr);
  199. hr = link->SetInfo();
  200. BREAK_ON_FAILED_HRESULT(hr);
  201. }
  202. while (0);
  203. if (FAILED(hr))
  204. {
  205. ReportError(hr, IDS_ERROR_TWEAKING_SITE_LINK, m_hWnd);
  206. }
  207. return hr;
  208. }
  209. HRESULT
  210. CreateNewSitePage::OnPostCommit(BOOL bSilent)
  211. {
  212. ASSERT(listview);
  213. int count = ListView_GetItemCount(listview);
  214. if (count > 0)
  215. {
  216. for (int i = 0; i < count; i++)
  217. {
  218. if (ListView_GetItemState(listview, i, LVIS_SELECTED))
  219. {
  220. LVITEM item = {0};
  221. item.mask = LVIF_PARAM;
  222. item.iItem = i;
  223. if (ListView_GetItem(listview, &item))
  224. {
  225. // the item.lParam field is the dn of the target link
  226. CComBSTR* dn = reinterpret_cast<CComBSTR*>(item.lParam);
  227. tweakSiteLink(*dn);
  228. // only tweak the first site link selected
  229. return S_OK;
  230. }
  231. }
  232. }
  233. }
  234. if (!bSilent)
  235. {
  236. ReportMessageEx(
  237. m_hWnd,
  238. IDS_NEWSITE_WARNING,
  239. MB_OK | MB_ICONWARNING,
  240. NULL,
  241. 0,
  242. IDS_WARNING_TITLE);
  243. }
  244. return S_OK;
  245. }
  246. HRESULT
  247. RecursiveFind(const CString& lpcwszADsPathDirectory,
  248. LPCTSTR lpcwszTargetClass,
  249. TargetLinkList& links,
  250. LPWSTR pszAttribute = L"distinguishedName");
  251. HRESULT
  252. RecursiveFind(const CString& lpcwszADsPathDirectory,
  253. LPCTSTR lpcwszTargetClass,
  254. TargetLinkList& links,
  255. LPWSTR pszAttribute)
  256. {
  257. links.clear();
  258. CDSSearch Search;
  259. Search.Init(lpcwszADsPathDirectory);
  260. CString filter;
  261. filter.Format(L"(objectClass=%s)", lpcwszTargetClass);
  262. Search.SetFilterString(const_cast<LPTSTR>((LPCTSTR) filter));
  263. LPWSTR pAttrs[2] =
  264. {
  265. L"name",
  266. pszAttribute
  267. };
  268. Search.SetAttributeList(pAttrs, 2);
  269. Search.SetSearchScope(ADS_SCOPE_SUBTREE);
  270. HRESULT hr = Search.DoQuery();
  271. while (SUCCEEDED(hr))
  272. {
  273. hr = Search.GetNextRow();
  274. if (S_ADS_NOMORE_ROWS == hr)
  275. {
  276. hr = S_OK;
  277. break;
  278. }
  279. BREAK_ON_FAILED_HRESULT(hr);
  280. ADS_SEARCH_COLUMN NameColumn;
  281. ::ZeroMemory(&NameColumn, sizeof(NameColumn));
  282. hr = Search.GetColumn (pAttrs[0], &NameColumn);
  283. BREAK_ON_FAILED_HRESULT(hr);
  284. ASSERT(ADSTYPE_CASE_IGNORE_STRING == NameColumn.pADsValues->dwType);
  285. ADS_SEARCH_COLUMN DistinguishedNameColumn;
  286. ::ZeroMemory(&DistinguishedNameColumn, sizeof(DistinguishedNameColumn));
  287. hr = Search.GetColumn (pAttrs[1], &DistinguishedNameColumn);
  288. BREAK_ON_FAILED_HRESULT(hr);
  289. ASSERT(ADSTYPE_DN_STRING == DistinguishedNameColumn.pADsValues->dwType
  290. || ADSTYPE_CASE_IGNORE_STRING == DistinguishedNameColumn.pADsValues->dwType);
  291. links.push_back(
  292. TargetLinkInfo(
  293. NameColumn.pADsValues->CaseIgnoreString,
  294. DistinguishedNameColumn.pADsValues->DNString));
  295. Search.FreeColumn(&NameColumn);
  296. Search.FreeColumn(&DistinguishedNameColumn);
  297. }
  298. #ifdef DBG
  299. // dump the list to the debugger
  300. for (
  301. TargetLinkList::iterator i = links.begin();
  302. i != links.end();
  303. i++)
  304. {
  305. OutputDebugString(i->first);
  306. OutputDebugString(L"\n");
  307. OutputDebugString(i->second);
  308. OutputDebugString(L"\n");
  309. }
  310. #endif
  311. return hr;
  312. }
  313. BOOL
  314. CreateAndChoosePage::OnSetActive()
  315. {
  316. CComQIPtr<IADs, &IID_IADs> container(GetWiz()->GetInfo()->m_pIADsContainer);
  317. if (container)
  318. {
  319. CComBSTR container_path;
  320. container->get_ADsPath(&container_path);
  321. initListContents(container_path);
  322. }
  323. return Base::OnSetActive();
  324. }
  325. void
  326. destroyListContents(HWND listview)
  327. {
  328. ASSERT(listview);
  329. for (int i = ListView_GetItemCount(listview) - 1; i >= 0; i--)
  330. {
  331. LVITEM item = {0};
  332. item.mask = LVIF_PARAM;
  333. item.iItem = i;
  334. if (ListView_GetItem(listview, &item))
  335. {
  336. ASSERT(item.lParam);
  337. delete reinterpret_cast<CComBSTR*>(item.lParam);
  338. ListView_DeleteItem(listview, i);
  339. return;
  340. }
  341. }
  342. }
  343. void
  344. CreateAndChoosePage::OnDestroy()
  345. {
  346. destroyListContents(listview);
  347. Base::OnDestroy();
  348. }
  349. void
  350. CreateNewSitePage::initListContents(LPCWSTR containerPath)
  351. {
  352. ASSERT(listview);
  353. CWaitCursor cwait;
  354. TargetLinkList links;
  355. bool links_present = false;
  356. HRESULT hr = RecursiveFind(containerPath, gsz_siteLink, links);
  357. if (SUCCEEDED(hr))
  358. {
  359. // walk the list and add nodes
  360. for (
  361. TargetLinkList::iterator i = links.begin();
  362. i != links.end();
  363. i++)
  364. {
  365. LVITEM item = {0};
  366. memset(&item, 0, sizeof(item));
  367. // this is deleted in destroyListContents
  368. CComBSTR* dn = new CComBSTR(i->second);
  369. item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  370. item.iItem = 0;
  371. item.iSubItem = 0;
  372. item.pszText = static_cast<LPTSTR>(i->first);
  373. item.lParam = reinterpret_cast<LPARAM>(dn);
  374. item.iImage = 0; // always the same, first image
  375. item.iItem = ListView_InsertItem(listview, &item);
  376. ASSERT(item.iItem >= 0);
  377. // add the transport sub-item to the list control
  378. CPathCracker pathCracker;
  379. hr =
  380. pathCracker.Set(
  381. static_cast<LPTSTR>(i->second),
  382. ADS_SETTYPE_DN);
  383. ASSERT(SUCCEEDED(hr));
  384. hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
  385. ASSERT(SUCCEEDED(hr));
  386. CComBSTR b;
  387. hr = pathCracker.GetElement(1, &b);
  388. ASSERT(SUCCEEDED(hr));
  389. hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  390. ASSERT(SUCCEEDED(hr));
  391. item.mask = LVIF_TEXT;
  392. item.iSubItem = 1;
  393. item.pszText = b;
  394. ListView_SetItem(listview, &item);
  395. links_present = true;
  396. }
  397. if (!links_present)
  398. {
  399. ReportError(hr, IDS_WARNING_NO_SITE_LINKS, m_hWnd);
  400. }
  401. }
  402. else
  403. {
  404. ReportError(hr, IDS_CANT_FIND_SITE_LINKS, m_hWnd);
  405. }
  406. if (!links_present)
  407. {
  408. GetDlgItem(IDC_LINKS)->EnableWindow(FALSE);
  409. GetDlgItem(IDC_SITE_TEXT)->EnableWindow(FALSE);
  410. }
  411. else // JonN 3/28/01 319675
  412. {
  413. ListView_SetItemState( listview, 0, LVIS_FOCUSED, LVIS_FOCUSED );
  414. }
  415. }
  416. void
  417. CreateNewSubnetPage::initListContents(LPCWSTR containerPath)
  418. {
  419. ASSERT(listview);
  420. CWaitCursor cwait;
  421. TargetLinkList links;
  422. bool links_present = false;
  423. CComBSTR sbstrSites;
  424. CPathCracker pathCracker;
  425. HRESULT hr = pathCracker.Set(
  426. const_cast<LPTSTR>(containerPath),
  427. ADS_SETTYPE_FULL);
  428. if (SUCCEEDED(hr))
  429. hr = pathCracker.RemoveLeafElement();
  430. if (SUCCEEDED(hr))
  431. hr = pathCracker.Retrieve(ADS_FORMAT_X500, &sbstrSites);
  432. if (SUCCEEDED(hr))
  433. hr = RecursiveFind((LPCTSTR)sbstrSites, gsz_site, links);
  434. if (SUCCEEDED(hr))
  435. {
  436. // walk the list and add nodes
  437. for (
  438. TargetLinkList::iterator i = links.begin();
  439. i != links.end();
  440. i++)
  441. {
  442. LVITEM item;
  443. memset(&item, 0, sizeof(item));
  444. // this is deleted in destroyListContents
  445. CComBSTR* dn = new CComBSTR(i->second);
  446. item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  447. item.iItem = 0;
  448. item.iSubItem = 0;
  449. item.pszText = static_cast<LPTSTR>(i->first);
  450. item.lParam = reinterpret_cast<LPARAM>(dn);
  451. item.iImage = 0; // always the same, first image
  452. item.iItem = ListView_InsertItem(listview, &item);
  453. ASSERT(item.iItem >= 0);
  454. links_present = true;
  455. }
  456. if (!links_present)
  457. {
  458. ReportError(hr, IDS_NEWSUBNET_WARNING_NO_SITES, m_hWnd);
  459. }
  460. }
  461. else
  462. {
  463. ReportError(hr, IDS_NEWSUBNET_CANT_FIND_SITES, m_hWnd);
  464. }
  465. if (!links_present)
  466. {
  467. GetDlgItem(IDC_LINKS)->EnableWindow(FALSE);
  468. GetDlgItem(IDC_SITE_TEXT)->EnableWindow(FALSE);
  469. }
  470. }
  471. BOOL
  472. CreateNewSitePage::OnInitDialog()
  473. {
  474. Base::OnInitDialog();
  475. MyBasePathsInfo* pBasePathsInfo = GetWiz()->GetInfo()->GetBasePathsInfo();
  476. listview = ::GetDlgItem(m_hWnd, IDC_LINKS);
  477. ASSERT(listview);
  478. LVCOLUMN column = {0};
  479. column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  480. column.fmt = LVCFMT_LEFT;
  481. { // open scope
  482. CString w;
  483. w.LoadString(IDS_NEW_SITE_NAME_COLUMN_WIDTH);
  484. w.TrimLeft();
  485. w.TrimRight();
  486. long width = _tcstol(w, 0, 10);
  487. ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN);
  488. column.cx = width;
  489. CString label;
  490. label.LoadString(IDS_NEW_SITE_NAME_COLUMN);
  491. column.pszText = const_cast<LPTSTR>((LPCTSTR) label);
  492. ListView_InsertColumn(listview, 0, &column);
  493. } // close scope
  494. // add a column to the list view for parent transport.
  495. { // open scope
  496. CString w;
  497. w.LoadString(IDS_NEW_SITE_XPORT_COLUMN_WIDTH);
  498. w.TrimLeft();
  499. w.TrimRight();
  500. long width = _tcstol(w, 0, 10);
  501. ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN);
  502. column.cx = width;
  503. CString label;
  504. label.LoadString(IDS_NEW_SITE_XPORT_COLUMN);
  505. column.pszText = const_cast<LPTSTR>((LPCTSTR) label);
  506. ListView_InsertColumn(listview, 1, &column);
  507. } // close scope
  508. // create the image list containing the site link icon
  509. int cx = ::GetSystemMetrics(SM_CXSMICON);
  510. int cy = ::GetSystemMetrics(SM_CYSMICON);
  511. ASSERT(cx && cy);
  512. // deleted in OnDestroy
  513. listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0);
  514. ASSERT(listview_imagelist);
  515. HICON icon = pBasePathsInfo->GetIcon(
  516. // someone really blew it with const correctness...
  517. const_cast<LPTSTR>(gsz_siteLink),
  518. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON,
  519. 16,
  520. 16);
  521. ASSERT(icon);
  522. int i = ::ImageList_AddIcon(listview_imagelist, icon);
  523. ASSERT(i != -1);
  524. DestroyIcon(icon);
  525. ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL);
  526. ListView_SetExtendedListViewStyleEx(
  527. listview,
  528. LVS_EX_FULLROWSELECT,
  529. LVS_EX_FULLROWSELECT);
  530. return TRUE;
  531. }
  532. BOOL
  533. CreateNewSubnetPage::OnInitDialog()
  534. {
  535. Base::OnInitDialog();
  536. MyBasePathsInfo* pBasePathsInfo = GetWiz()->GetInfo()->GetBasePathsInfo();
  537. (void) SendDlgItemMessage( IDC_SUBNET_ADDRESS,
  538. IPM_SETADDRESS,
  539. 0,
  540. (LPARAM)MAKEIPADDRESS(0,0,0,0) );
  541. (void) SendDlgItemMessage( IDC_SUBNET_MASK,
  542. IPM_SETADDRESS,
  543. 0,
  544. (LPARAM)MAKEIPADDRESS(0,0,0,0) );
  545. listview = ::GetDlgItem(m_hWnd, IDC_LINKS);
  546. ASSERT(listview);
  547. { // open scope
  548. LVCOLUMN column = {0};
  549. column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  550. column.fmt = LVCFMT_LEFT;
  551. CString w;
  552. w.LoadString(IDS_COLUMN_SITE_WIDTH);
  553. w.TrimLeft();
  554. w.TrimRight();
  555. long width = _tcstol(w, 0, 10);
  556. ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN);
  557. column.cx = width;
  558. CString label;
  559. label.LoadString(IDS_COLUMN_SITE_NAME);
  560. column.pszText = const_cast<LPTSTR>((LPCTSTR) label);
  561. ListView_InsertColumn(listview, 0, &column);
  562. } // close scope
  563. // create the image list containing the site link icon
  564. int cx = ::GetSystemMetrics(SM_CXSMICON);
  565. int cy = ::GetSystemMetrics(SM_CYSMICON);
  566. ASSERT(cx && cy);
  567. // deleted in OnDestroy
  568. listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0);
  569. ASSERT(listview_imagelist);
  570. HICON icon = pBasePathsInfo->GetIcon(
  571. // someone really blew it with const correctness...
  572. const_cast<LPTSTR>(gsz_site),
  573. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON | DSGIF_DEFAULTISCONTAINER,
  574. 16,
  575. 16);
  576. ASSERT(icon);
  577. int i = ::ImageList_AddIcon(listview_imagelist, icon);
  578. ASSERT(i != -1);
  579. DestroyIcon(icon);
  580. ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL);
  581. ListView_SetExtendedListViewStyleEx(
  582. listview,
  583. LVS_EX_FULLROWSELECT,
  584. LVS_EX_FULLROWSELECT);
  585. return TRUE;
  586. }
  587. BOOL CreateNewSitePage::ValidateName(LPCTSTR pcszName)
  588. {
  589. BOOL fNonRfcSiteName = FALSE;
  590. BOOL fValidSiteName = IsValidSiteName( pcszName, &fNonRfcSiteName );
  591. if ( !fValidSiteName )
  592. {
  593. ReportErrorEx (::GetParent(m_hWnd),IDS_SITE_NAME,S_OK,
  594. MB_OK, NULL, 0);
  595. }
  596. else if ( fNonRfcSiteName )
  597. {
  598. PVOID apv[1];
  599. apv[0] = (PVOID)pcszName;
  600. if (IDYES != ReportMessageEx( ::GetParent(m_hWnd),
  601. IDS_1_NON_RFC_SITE_NAME,
  602. MB_YESNO | MB_ICONWARNING,
  603. apv,
  604. 1 ) )
  605. {
  606. fValidSiteName = FALSE;
  607. }
  608. }
  609. if ( !fValidSiteName )
  610. {
  611. // Yes, this really does have to be PostMessage, SendMessage doesn't work
  612. // It also has to come after ReportErrorEx or else it doesn't work
  613. (void) this->PostMessage( WM_NEXTDLGCTL,
  614. (WPARAM)::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME),
  615. TRUE );
  616. (void) ::PostMessage( ::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME), EM_SETSEL, 0, -1 );
  617. return FALSE;
  618. }
  619. return TRUE;
  620. }
  621. // JonN 5/11/01 251560 Disable OK until site link chosen
  622. BEGIN_MESSAGE_MAP(CreateNewSitePage, CreateAndChoosePage)
  623. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnChange)
  624. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LINKS, OnSelChange)
  625. END_MESSAGE_MAP()
  626. afx_msg void CreateNewSitePage::OnSelChange( NMHDR*, LRESULT* )
  627. {
  628. OnChange();
  629. }
  630. void CreateNewSitePage::OnChange()
  631. {
  632. if (0 >= ListView_GetSelectedCount(listview))
  633. GetWiz()->SetWizardButtons(this, FALSE);
  634. else
  635. OnNameChange(); // Enable the OK button only if the name is not empty
  636. }
  637. // no need to validate subnet name, MapMaskAndAddress does this
  638. // return -32 for invalid mask
  639. int CountBits( DWORD dwOctet )
  640. {
  641. if ( 0xff < dwOctet )
  642. {
  643. ASSERT(FALSE);
  644. return -32;
  645. }
  646. for (int nBits = 0; dwOctet & 0x80; nBits++)
  647. dwOctet = (dwOctet & ~0x80) * 2;
  648. if (dwOctet != 0)
  649. return -32; // hole in the mask
  650. return nBits;
  651. }
  652. // returns <0 for invalid mask
  653. int CountMaskedBits( DWORD dwMask )
  654. {
  655. int nFirstOctet = FIRST_IPADDRESS(dwMask);
  656. int nSecondOctet = SECOND_IPADDRESS(dwMask);
  657. int nThirdOctet = THIRD_IPADDRESS(dwMask);
  658. int nFourthOctet = FOURTH_IPADDRESS(dwMask);
  659. if (nFirstOctet < 255)
  660. {
  661. if (0 != nSecondOctet || 0 != nThirdOctet || 0 != nFourthOctet)
  662. return -1;
  663. return CountBits(nFirstOctet);
  664. }
  665. if (nSecondOctet < 255)
  666. {
  667. if (255 != nFirstOctet || 0 != nThirdOctet || 0 != nFourthOctet)
  668. return -1;
  669. return 8 + CountBits(nSecondOctet);
  670. }
  671. if (nThirdOctet < 255)
  672. {
  673. if (255 != nFirstOctet || 255 != nSecondOctet || 0 != nFourthOctet)
  674. return -1;
  675. return 16 + CountBits(nThirdOctet);
  676. }
  677. if (255 != nFirstOctet || 255 != nSecondOctet || 255 != nThirdOctet)
  678. return -1;
  679. return 24 + CountBits(nFourthOctet);
  680. }
  681. // returns empty string for invalid address+mask
  682. void MapMaskAndAddress(
  683. OUT CString& strrefSubnetName,
  684. IN DWORD dwAddress,
  685. IN DWORD dwMask )
  686. {
  687. strrefSubnetName.Empty();
  688. dwAddress &= dwMask; // clear all bits set in the address and not in the mask
  689. int nMaskedBits = CountMaskedBits( dwMask );
  690. if (0 > nMaskedBits)
  691. return; // invalid mask
  692. strrefSubnetName.Format(L"%d.%d.%d.%d/%d",
  693. FIRST_IPADDRESS(dwAddress),
  694. SECOND_IPADDRESS(dwAddress),
  695. THIRD_IPADDRESS(dwAddress),
  696. FOURTH_IPADDRESS(dwAddress),
  697. nMaskedBits);
  698. // final test for edge cases such as "0.0.0.0/0"
  699. if (ERROR_SUCCESS != ::DsValidateSubnetName( strrefSubnetName ))
  700. strrefSubnetName.Empty();
  701. }
  702. void CreateNewSubnetPage::OnSubnetMaskChange()
  703. {
  704. DWORD dwAddress, dwMask;
  705. CString strSubnetName;
  706. // IPM_GETADDRESS returns the number of octets filled in. Address is
  707. // invalid if any of the four is left blank.
  708. if ( 4 == SendDlgItemMessage( IDC_SUBNET_ADDRESS,
  709. IPM_GETADDRESS,
  710. 0,
  711. (LPARAM)&dwAddress )
  712. && 4 == SendDlgItemMessage( IDC_SUBNET_MASK,
  713. IPM_GETADDRESS,
  714. 0,
  715. (LPARAM)&dwMask ) )
  716. {
  717. MapMaskAndAddress( strSubnetName, dwAddress, dwMask );
  718. }
  719. SetDlgItemText(IDC_EDIT_OBJECT_NAME, strSubnetName);
  720. OnNameChange();
  721. }
  722. BEGIN_MESSAGE_MAP(CMoveServerDialog, CDialog)
  723. //{{AFX_MSG_MAP(CMoveServerDialog)
  724. ON_WM_DESTROY()
  725. ON_NOTIFY(NM_DBLCLK, IDC_LINKS, OnDblclkListview)
  726. //}}AFX_MSG_MAP
  727. END_MESSAGE_MAP()
  728. CMoveServerDialog::CMoveServerDialog(LPCTSTR lpcszBrowseRootPath, HICON hIcon, CWnd* pParent /*=NULL*/)
  729. : CDialog(CMoveServerDialog::IDD, pParent)
  730. , m_strTargetContainer()
  731. , m_strBrowseRootPath(lpcszBrowseRootPath)
  732. , m_hIcon(hIcon)
  733. , listview(0)
  734. , listview_imagelist(0)
  735. {}
  736. BOOL
  737. CMoveServerDialog::OnInitDialog()
  738. {
  739. CDialog::OnInitDialog();
  740. CWaitCursor cwait;
  741. listview = ::GetDlgItem(m_hWnd, IDC_LINKS);
  742. ASSERT(listview);
  743. { // open scope
  744. LVCOLUMN column = {0};
  745. column.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  746. column.fmt = LVCFMT_LEFT;
  747. CString w;
  748. w.LoadString(IDS_COLUMN_SITE_WIDTH);
  749. w.TrimLeft();
  750. w.TrimRight();
  751. long width = _tcstol(w, 0, 10);
  752. ASSERT(width != 0 && width != LONG_MAX && width != LONG_MIN);
  753. column.cx = width;
  754. CString label;
  755. label.LoadString(IDS_COLUMN_SITE_NAME);
  756. column.pszText = const_cast<LPTSTR>((LPCTSTR) label);
  757. ListView_InsertColumn(listview, 0, &column);
  758. } // close scope
  759. // create the image list containing the site link icon
  760. int cx = ::GetSystemMetrics(SM_CXSMICON);
  761. int cy = ::GetSystemMetrics(SM_CYSMICON);
  762. ASSERT(cx && cy);
  763. // deleted in OnDestroy
  764. listview_imagelist = ::ImageList_Create(cx, cy, ILC_MASK, 1, 0);
  765. ASSERT(listview_imagelist);
  766. ASSERT(m_hIcon != NULL);
  767. int i = ::ImageList_AddIcon(listview_imagelist, m_hIcon);
  768. ASSERT(i != -1);
  769. ListView_SetImageList(listview, listview_imagelist, LVSIL_SMALL);
  770. ListView_SetExtendedListViewStyleEx(
  771. listview,
  772. LVS_EX_FULLROWSELECT,
  773. LVS_EX_FULLROWSELECT);
  774. // add sites to listview
  775. TargetLinkList links;
  776. bool links_present = false;
  777. HRESULT hr = RecursiveFind(m_strBrowseRootPath, gsz_serversContainer, links, L"aDSPath");
  778. if (SUCCEEDED(hr))
  779. {
  780. // walk the list and add nodes
  781. for (
  782. TargetLinkList::iterator itr = links.begin();
  783. itr != links.end();
  784. ++itr)
  785. {
  786. LVITEM item;
  787. memset(&item, 0, sizeof(item));
  788. // Since the enumerated objects are of type serversContainer,
  789. // we display the name of the parent. Also, the aDSPath attribute may
  790. // contain a server indication, which must be removed.
  791. CPathCracker pathCracker;
  792. hr = pathCracker.Set( itr->second, ADS_SETTYPE_FULL );
  793. BREAK_ON_FAILED_HRESULT(hr);
  794. hr = pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
  795. BREAK_ON_FAILED_HRESULT(hr);
  796. CComBSTR sbstrName;
  797. hr = pathCracker.GetElement( 1L, &sbstrName );
  798. BREAK_ON_FAILED_HRESULT(hr);
  799. hr = pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  800. BREAK_ON_FAILED_HRESULT(hr);
  801. CComBSTR sbstrDN;
  802. hr = pathCracker.Retrieve( ADS_FORMAT_X500, &sbstrDN );
  803. BREAK_ON_FAILED_HRESULT(hr);
  804. // this is deleted in destroyListContents
  805. CComBSTR* dn = new CComBSTR(sbstrDN);
  806. item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  807. item.iItem = 0;
  808. item.iSubItem = 0;
  809. item.pszText = static_cast<LPTSTR>(sbstrName);
  810. item.lParam = reinterpret_cast<LPARAM>(dn);
  811. item.iImage = 0; // always the same, first image
  812. item.iItem = ListView_InsertItem(listview, &item);
  813. ASSERT(item.iItem >= 0);
  814. links_present = true;
  815. }
  816. if (!links_present)
  817. {
  818. ReportError(hr, IDS_MOVESERVER_ERROR_NO_SITES, m_hWnd);
  819. OnCancel();
  820. }
  821. }
  822. if ( FAILED(hr) )
  823. {
  824. ReportError(hr, IDS_MOVESERVER_ERROR_ENUMERATING_SITES, m_hWnd);
  825. OnCancel();
  826. }
  827. return TRUE; // return TRUE unless you set the focus to a control
  828. // EXCEPTION: OCX Property Pages should return FALSE
  829. }
  830. void
  831. CMoveServerDialog::OnDestroy()
  832. {
  833. destroyListContents(listview);
  834. CDialog::OnDestroy();
  835. }
  836. void CMoveServerDialog::OnOK()
  837. {
  838. int count = ListView_GetItemCount(listview);
  839. if (count > 0)
  840. {
  841. if (0 >= ListView_GetSelectedCount(listview))
  842. {
  843. ReportErrorEx (m_hWnd,IDS_MOVESERVER_SELECT_SITE,S_OK,
  844. MB_OK, NULL, 0);
  845. (void) this->PostMessage( WM_NEXTDLGCTL,
  846. (WPARAM)listview,
  847. TRUE );
  848. return;
  849. }
  850. for (int i = 0; i < count; i++)
  851. {
  852. if (ListView_GetItemState(listview, i, LVIS_SELECTED))
  853. {
  854. LVITEM item = {0};
  855. item.mask = LVIF_PARAM;
  856. item.iItem = i;
  857. if (ListView_GetItem(listview, &item))
  858. {
  859. // the item.lParam field is the dn of the target site
  860. CComBSTR* dn = reinterpret_cast<CComBSTR*>(item.lParam);
  861. m_strTargetContainer = *dn;
  862. // use the first site selected
  863. break;
  864. }
  865. }
  866. }
  867. ASSERT( i < count );
  868. }
  869. CDialog::OnOK();
  870. }
  871. void CMoveServerDialog::OnDblclkListview(NMHDR*, LRESULT*)
  872. {
  873. OnOK();
  874. }