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.

1802 lines
48 KiB

  1. /*++
  2. Module Name:
  3. CusTop.cpp
  4. Abstract:
  5. This module contains the Implementation of CCustomTopology.
  6. This class displays the Customize Topology Dialog.
  7. */
  8. #include "stdafx.h"
  9. #include "CusTop.h"
  10. #include "utils.h"
  11. #include "dfshelp.h"
  12. #include "ldaputils.h"
  13. int g_FRS_CUSTOP_Last_SortColumn = 1;
  14. #define NUM_OF_FRS_CUSTOP_COLUMNS 5
  15. RSTOPOLOGYPREF_STRING g_TopologyPref[] = {
  16. {FRS_RSTOPOLOGYPREF_RING, IDS_FRSPROP_RING},
  17. {FRS_RSTOPOLOGYPREF_HUBSPOKE, IDS_FRSPROP_HUBSPOKE},
  18. {FRS_RSTOPOLOGYPREF_FULLMESH, IDS_FRSPROP_FULLMESH},
  19. {FRS_RSTOPOLOGYPREF_CUSTOM, IDS_FRSPROP_CUSTOM}
  20. };
  21. /////////////////////////////////////////////////////////////////////////////
  22. //
  23. // CCustomTopology
  24. //
  25. CCustomTopology::CCustomTopology()
  26. {
  27. }
  28. CCustomTopology::~CCustomTopology()
  29. {
  30. }
  31. HRESULT CCustomTopology::_GetMemberList()
  32. {
  33. FreeCusTopMembers(&m_MemberList);
  34. RETURN_INVALIDARG_IF_NULL((IReplicaSet *)m_piReplicaSet);
  35. VARIANT var;
  36. VariantInit(&var);
  37. HRESULT hr = m_piReplicaSet->GetMemberListEx(&var);
  38. RETURN_IF_FAILED(hr);
  39. if (V_VT(&var) != (VT_ARRAY | VT_VARIANT))
  40. return E_INVALIDARG;
  41. SAFEARRAY *psa_1 = V_ARRAY(&var);
  42. if (!psa_1) // no member at all
  43. return hr;
  44. long lLowerBound_1 = 0;
  45. long lUpperBound_1 = 0;
  46. long lCount_1 = 0;
  47. SafeArrayGetLBound(psa_1, 1, &lLowerBound_1);
  48. SafeArrayGetUBound(psa_1, 1, &lUpperBound_1);
  49. lCount_1 = lUpperBound_1 - lLowerBound_1 + 1;
  50. VARIANT HUGEP *pArray_1;
  51. SafeArrayAccessData(psa_1, (void HUGEP **) &pArray_1);
  52. for (long i = 0; i < lCount_1; i++)
  53. {
  54. if (V_VT(&(pArray_1[i])) != (VT_ARRAY | VT_VARIANT))
  55. {
  56. hr = E_INVALIDARG;
  57. break;
  58. }
  59. SAFEARRAY *psa_0 = V_ARRAY(&(pArray_1[i]));
  60. if (!psa_0)
  61. {
  62. hr = E_INVALIDARG;
  63. break;
  64. }
  65. long lLowerBound_0 = 0;
  66. long lUpperBound_0 = 0;
  67. long lCount_0 = 0;
  68. SafeArrayGetLBound(psa_0, 1, &lLowerBound_0);
  69. SafeArrayGetUBound(psa_0, 1, &lUpperBound_0);
  70. lCount_0 = lUpperBound_0 - lLowerBound_0 + 1;
  71. if (NUM_OF_FRSMEMBER_ATTRS != lCount_0)
  72. {
  73. hr = E_INVALIDARG;
  74. break;
  75. }
  76. VARIANT HUGEP *pArray_0;
  77. SafeArrayAccessData(psa_0, (void HUGEP **) &pArray_0);
  78. do {
  79. CCusTopMember* pNew = new CCusTopMember;
  80. BREAK_OUTOFMEMORY_IF_NULL(pNew, &hr);
  81. hr = pNew->Init(
  82. pArray_0[2].bstrVal, //bstrMemberDN,
  83. pArray_0[4].bstrVal, //bstrServer,
  84. pArray_0[6].bstrVal //bstrSite
  85. );
  86. if (SUCCEEDED(hr))
  87. m_MemberList.push_back(pNew);
  88. else
  89. delete pNew;
  90. } while (0);
  91. SafeArrayUnaccessData(psa_0);
  92. }
  93. SafeArrayUnaccessData(psa_1);
  94. if (SUCCEEDED(hr))
  95. hr = _SortMemberList();
  96. if (FAILED(hr))
  97. FreeCusTopMembers(&m_MemberList);
  98. SafeArrayDestroy(psa_1); // it should free psa_0 as well
  99. return hr;
  100. }
  101. HRESULT CCustomTopology::_GetConnectionList()
  102. {
  103. FreeCusTopConnections(&m_ConnectionList);
  104. RETURN_INVALIDARG_IF_NULL((IReplicaSet *)m_piReplicaSet);
  105. VARIANT var;
  106. VariantInit(&var);
  107. HRESULT hr = m_piReplicaSet->GetConnectionListEx(&var);
  108. RETURN_IF_FAILED(hr);
  109. if (V_VT(&var) != (VT_ARRAY | VT_VARIANT))
  110. return E_INVALIDARG;
  111. SAFEARRAY *psa_1 = V_ARRAY(&var);
  112. if (!psa_1) // no connection at all
  113. return hr;
  114. long lLowerBound_1 = 0;
  115. long lUpperBound_1 = 0;
  116. long lCount_1 = 0;
  117. SafeArrayGetLBound(psa_1, 1, &lLowerBound_1);
  118. SafeArrayGetUBound(psa_1, 1, &lUpperBound_1);
  119. lCount_1 = lUpperBound_1 - lLowerBound_1 + 1;
  120. VARIANT HUGEP *pArray_1;
  121. SafeArrayAccessData(psa_1, (void HUGEP **) &pArray_1);
  122. for (long i = 0; i < lCount_1; i++)
  123. {
  124. if (V_VT(&(pArray_1[i])) != (VT_ARRAY | VT_VARIANT))
  125. {
  126. hr = E_INVALIDARG;
  127. break;
  128. }
  129. SAFEARRAY *psa_0 = V_ARRAY(&(pArray_1[i]));
  130. if (!psa_0)
  131. {
  132. hr = E_INVALIDARG;
  133. break;
  134. }
  135. long lLowerBound_0 = 0;
  136. long lUpperBound_0 = 0;
  137. long lCount_0 = 0;
  138. SafeArrayGetLBound(psa_0, 1, &lLowerBound_0);
  139. SafeArrayGetUBound(psa_0, 1, &lUpperBound_0);
  140. lCount_0 = lUpperBound_0 - lLowerBound_0 + 1;
  141. if (NUM_OF_FRSCONNECTION_ATTRS != lCount_0)
  142. {
  143. hr = E_INVALIDARG;
  144. break;
  145. }
  146. VARIANT HUGEP *pArray_0;
  147. SafeArrayAccessData(psa_0, (void HUGEP **) &pArray_0);
  148. do {
  149. CComBSTR bstrFromServer;
  150. CComBSTR bstrFromSite;
  151. hr = _GetMemberDNInfo(pArray_0[1].bstrVal, &bstrFromServer, &bstrFromSite);
  152. BREAK_IF_FAILED(hr);
  153. CComBSTR bstrToServer;
  154. CComBSTR bstrToSite;
  155. hr = _GetMemberDNInfo(pArray_0[2].bstrVal, &bstrToServer, &bstrToSite);
  156. BREAK_IF_FAILED(hr);
  157. CCusTopConnection* pNew = new CCusTopConnection;
  158. BREAK_OUTOFMEMORY_IF_NULL(pNew, &hr);
  159. hr = pNew->Init(
  160. pArray_0[1].bstrVal, //bstrFromDN,
  161. bstrFromServer,
  162. bstrFromSite,
  163. pArray_0[2].bstrVal, //bstrToDN,
  164. bstrToServer,
  165. bstrToSite,
  166. (BOOL)(pArray_0[3].lVal) //bEnable
  167. ); // CONNECTION_OPTYPE_OTHERS
  168. if (SUCCEEDED(hr))
  169. m_ConnectionList.push_back(pNew);
  170. else
  171. delete pNew;
  172. } while (0);
  173. SafeArrayUnaccessData(psa_0);
  174. }
  175. SafeArrayUnaccessData(psa_1);
  176. if (FAILED(hr))
  177. FreeCusTopConnections(&m_ConnectionList);
  178. SafeArrayDestroy(psa_1);
  179. return hr;
  180. }
  181. void CCustomTopology::_Reset()
  182. {
  183. m_bstrTopologyPref.Empty();
  184. m_bstrHubMemberDN.Empty();
  185. FreeCusTopMembers(&m_MemberList);
  186. FreeCusTopConnections(&m_ConnectionList);
  187. m_piReplicaSet = NULL;
  188. }
  189. HRESULT CCustomTopology::put_ReplicaSet
  190. (
  191. IReplicaSet* i_piReplicaSet
  192. )
  193. {
  194. RETURN_INVALIDARG_IF_NULL(i_piReplicaSet);
  195. _Reset();
  196. m_piReplicaSet = i_piReplicaSet;
  197. HRESULT hr = S_OK;
  198. do {
  199. hr = m_piReplicaSet->get_TopologyPref(&m_bstrTopologyPref);
  200. BREAK_IF_FAILED(hr);
  201. hr = m_piReplicaSet->get_HubMemberDN(&m_bstrHubMemberDN);
  202. BREAK_IF_FAILED(hr);
  203. hr = _GetMemberList();
  204. BREAK_IF_FAILED(hr);
  205. hr = _GetConnectionList();
  206. BREAK_IF_FAILED(hr);
  207. } while (0);
  208. if (FAILED(hr))
  209. _Reset();
  210. return hr;
  211. }
  212. int __cdecl CompareCusTopMembers(const void *arg1, const void *arg2 )
  213. {
  214. return lstrcmpi(
  215. (*(CCusTopMember**)arg1)->m_bstrServer,
  216. (*(CCusTopMember**)arg2)->m_bstrServer
  217. );
  218. }
  219. HRESULT CCustomTopology::_SortMemberList()
  220. {
  221. HRESULT hr = S_OK;
  222. int cMembers = m_MemberList.size();
  223. if (2 > cMembers)
  224. return hr;
  225. CCusTopMember** ppMember = (CCusTopMember **)calloc(cMembers, sizeof(CCusTopMember *));
  226. RETURN_OUTOFMEMORY_IF_NULL(ppMember);
  227. int i = 0;
  228. for (CCusTopMemberList::iterator it = m_MemberList.begin(); it != m_MemberList.end(); it++, i++)
  229. {
  230. ppMember[i] = (*it);
  231. }
  232. qsort((void *)ppMember, cMembers, sizeof(CCusTopMember *), CompareCusTopMembers);
  233. m_MemberList.clear(); // without deleting the object
  234. for (i = 0; i < cMembers; i++)
  235. {
  236. m_MemberList.push_back(ppMember[i]);
  237. }
  238. free((void *)ppMember);
  239. return hr;
  240. }
  241. HRESULT CCustomTopology::_GetMemberDNInfo(
  242. IN BSTR i_bstrMemberDN,
  243. OUT BSTR* o_pbstrServer,
  244. OUT BSTR* o_pbstrSite
  245. )
  246. {
  247. RETURN_INVALIDARG_IF_NULL(i_bstrMemberDN);
  248. RETURN_INVALIDARG_IF_NULL(o_pbstrServer);
  249. RETURN_INVALIDARG_IF_NULL(o_pbstrSite);
  250. for (CCusTopMemberList::iterator i = m_MemberList.begin(); i != m_MemberList.end(); i++)
  251. {
  252. if (!lstrcmpi(i_bstrMemberDN, (*i)->m_bstrMemberDN))
  253. break;
  254. }
  255. if (i == m_MemberList.end())
  256. return S_FALSE;
  257. *o_pbstrServer = (*i)->m_bstrServer.Copy();
  258. RETURN_OUTOFMEMORY_IF_NULL(*o_pbstrServer);
  259. *o_pbstrSite = (*i)->m_bstrSite.Copy();
  260. if (!*o_pbstrSite)
  261. {
  262. SysFreeString(*o_pbstrServer);
  263. return E_OUTOFMEMORY;
  264. }
  265. return S_OK;
  266. }
  267. HRESULT CCustomTopology::_GetHubMember(
  268. OUT CCusTopMember** o_ppHubMember
  269. )
  270. {
  271. RETURN_INVALIDARG_IF_NULL(o_ppHubMember);
  272. int index = SendDlgItemMessage(IDC_FRS_CUSTOP_HUBSERVER, CB_GETCURSEL, 0, 0);
  273. int len = SendDlgItemMessage(IDC_FRS_CUSTOP_HUBSERVER, CB_GETLBTEXTLEN, index, 0);
  274. PTSTR pszServer = (PTSTR)calloc(len + 1, sizeof(TCHAR));
  275. RETURN_OUTOFMEMORY_IF_NULL(pszServer);
  276. SendDlgItemMessage(IDC_FRS_CUSTOP_HUBSERVER, CB_GETLBTEXT, index, (LPARAM)pszServer);
  277. CCusTopMemberList::iterator i;
  278. for (i = m_MemberList.begin(); i != m_MemberList.end(); i++)
  279. {
  280. if (!lstrcmpi(pszServer, (*i)->m_bstrServer))
  281. break;
  282. }
  283. free(pszServer);
  284. if (i == m_MemberList.end())
  285. return E_INVALIDARG;
  286. *o_ppHubMember = (*i);
  287. return S_OK;
  288. }
  289. LRESULT CCustomTopology::OnInitDialog
  290. (
  291. UINT uMsg,
  292. WPARAM wParam,
  293. LPARAM lParam,
  294. BOOL& bHandled
  295. )
  296. {
  297. int i = 0;
  298. int nControlID = 0;
  299. //
  300. // set IDC_FRS_CUSTOP_TOPOLOGYPREF
  301. //
  302. nControlID = IDC_FRS_CUSTOP_TOPOLOGYPREF;
  303. for (i = 0; i < 4; i++)
  304. {
  305. CComBSTR bstrTopologyPref;
  306. LoadStringFromResource(g_TopologyPref[i].nStringID, &bstrTopologyPref);
  307. SendDlgItemMessage(nControlID, CB_INSERTSTRING, i, (LPARAM)(BSTR)bstrTopologyPref);
  308. if (!lstrcmpi(m_bstrTopologyPref, g_TopologyPref[i].pszTopologyPref))
  309. {
  310. SendDlgItemMessage(nControlID, CB_SETCURSEL, i, 0);
  311. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_REBUILD), (0 != lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_CUSTOM)));
  312. }
  313. }
  314. //
  315. // set IDC_FRS_CUSTOP_HUBSERVER
  316. //
  317. nControlID = IDC_FRS_CUSTOP_HUBSERVER;
  318. int index = 0;
  319. CCusTopMemberList::iterator itMem;
  320. for (i = 0, itMem = m_MemberList.begin(); itMem != m_MemberList.end(); i++, itMem++)
  321. {
  322. SendDlgItemMessage(nControlID, CB_INSERTSTRING, i, (LPARAM)(BSTR)(*itMem)->m_bstrServer);
  323. if (!lstrcmpi(m_bstrHubMemberDN, (*itMem)->m_bstrMemberDN))
  324. index = i;
  325. }
  326. SendDlgItemMessage(nControlID, CB_SETCURSEL, index, 0);
  327. if (lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  328. {
  329. MyShowWindow(GetDlgItem(IDC_FRS_CUSTOP_HUBSERVER_LABEL), FALSE);
  330. MyShowWindow(GetDlgItem(IDC_FRS_CUSTOP_HUBSERVER), FALSE);
  331. }
  332. //
  333. // set IDC_FRS_CUSTOP_CONNECTIONS
  334. //
  335. nControlID = IDC_FRS_CUSTOP_CONNECTIONS;
  336. HWND hwndControl = GetDlgItem(nControlID);
  337. AddLVColumns(hwndControl, IDS_FRS_CUSTOP_COL_ENABLE, NUM_OF_FRS_CUSTOP_COLUMNS);
  338. ListView_SetExtendedListViewStyle(hwndControl, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
  339. CCusTopConnectionList::iterator itConn;
  340. for (itConn = m_ConnectionList.begin(); itConn != m_ConnectionList.end(); itConn++)
  341. _InsertConnection(*itConn);
  342. ListView_SortItems( hwndControl,
  343. ConnectionsListCompareProc,
  344. (LPARAM)g_FRS_CUSTOP_Last_SortColumn);
  345. _EnableButtonsForConnectionList();
  346. return TRUE; // Let the system set the focus
  347. }
  348. void CCustomTopology::_EnableButtonsForConnectionList()
  349. {
  350. //
  351. // enable New/Delete/Schedule buttons accordingly
  352. //
  353. int nCount = ListView_GetSelectedCount(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS));
  354. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_SCHEDULE), (nCount >= 1));
  355. int index = SendDlgItemMessage(IDC_FRS_CUSTOP_TOPOLOGYPREF, CB_GETCURSEL, 0, 0);
  356. if (3 == index) // bCustomTopology
  357. {
  358. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS_NEW), TRUE);
  359. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS_DELETE), (nCount >= 1));
  360. } else
  361. {
  362. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS_NEW), FALSE);
  363. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS_DELETE), FALSE);
  364. }
  365. }
  366. /*++
  367. This function is called when a user clicks the ? in the top right of a property sheet
  368. and then clciks a control, or when they hit F1 in a control.
  369. --*/
  370. LRESULT CCustomTopology::OnCtxHelp(
  371. IN UINT i_uMsg,
  372. IN WPARAM i_wParam,
  373. IN LPARAM i_lParam,
  374. IN OUT BOOL& io_bHandled
  375. )
  376. {
  377. LPHELPINFO lphi = (LPHELPINFO) i_lParam;
  378. if (!lphi || lphi->iContextType != HELPINFO_WINDOW || lphi->iCtrlId < 0)
  379. return FALSE;
  380. ::WinHelp((HWND)(lphi->hItemHandle),
  381. DFS_CTX_HELP_FILE,
  382. HELP_WM_HELP,
  383. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_FRS_CUSTOP);
  384. return TRUE;
  385. }
  386. /*++
  387. This function handles "What's This" help when a user right clicks the control
  388. --*/
  389. LRESULT CCustomTopology::OnCtxMenuHelp(
  390. IN UINT i_uMsg,
  391. IN WPARAM i_wParam,
  392. IN LPARAM i_lParam,
  393. IN OUT BOOL& io_bHandled
  394. )
  395. {
  396. ::WinHelp((HWND)i_wParam,
  397. DFS_CTX_HELP_FILE,
  398. HELP_CONTEXTMENU,
  399. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_FRS_CUSTOP);
  400. return TRUE;
  401. }
  402. BOOL CCustomTopology::_EnableRebuild()
  403. {
  404. BOOL bSameTopologyPref = FALSE;
  405. int index = SendDlgItemMessage(IDC_FRS_CUSTOP_TOPOLOGYPREF, CB_GETCURSEL, 0, 0);
  406. if (lstrcmpi(FRS_RSTOPOLOGYPREF_CUSTOM, g_TopologyPref[index].pszTopologyPref) &&
  407. !lstrcmpi(m_bstrTopologyPref, g_TopologyPref[index].pszTopologyPref))
  408. {
  409. bSameTopologyPref = TRUE;
  410. }
  411. if (!bSameTopologyPref || 0 != lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  412. return bSameTopologyPref;
  413. BOOL bSameHub = FALSE;
  414. CCusTopMember* pHubMember = NULL;
  415. HRESULT hr = _GetHubMember(&pHubMember);
  416. if (SUCCEEDED(hr))
  417. bSameHub = (!lstrcmpi(m_bstrHubMemberDN, pHubMember->m_bstrMemberDN));
  418. return bSameHub;
  419. }
  420. LRESULT CCustomTopology::OnTopologyPref
  421. (
  422. WORD wNotifyCode,
  423. WORD wID,
  424. HWND hWndCtl,
  425. BOOL& bHandled
  426. )
  427. {
  428. HRESULT hr = S_OK;
  429. if (CBN_SELCHANGE == wNotifyCode)
  430. {
  431. int index = SendDlgItemMessage(wID, CB_GETCURSEL, 0, 0);
  432. BOOL bCmdShow = (1 == index);
  433. MyShowWindow(GetDlgItem(IDC_FRS_CUSTOP_HUBSERVER_LABEL), bCmdShow);
  434. MyShowWindow(GetDlgItem(IDC_FRS_CUSTOP_HUBSERVER), bCmdShow);
  435. if (1 == index)
  436. {
  437. CCusTopMember* pHubMember = NULL;
  438. hr = _GetHubMember(&pHubMember);
  439. if (SUCCEEDED(hr))
  440. hr = _RebuildConnections(FRS_RSTOPOLOGYPREF_HUBSPOKE, pHubMember);
  441. } else
  442. hr = _RebuildConnections(g_TopologyPref[index].pszTopologyPref, NULL);
  443. _EnableButtonsForConnectionList();
  444. BOOL bSameTopology = _EnableRebuild();
  445. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_REBUILD), bSameTopology);
  446. }
  447. return (SUCCEEDED(hr));
  448. }
  449. LRESULT CCustomTopology::OnHubServer
  450. (
  451. WORD wNotifyCode,
  452. WORD wID,
  453. HWND hWndCtl,
  454. BOOL& bHandled
  455. )
  456. {
  457. HRESULT hr = S_OK;
  458. if (CBN_SELCHANGE == wNotifyCode)
  459. {
  460. CCusTopMember* pHubMember = NULL;
  461. hr = _GetHubMember(&pHubMember);
  462. if (SUCCEEDED(hr))
  463. hr = _RebuildConnections(FRS_RSTOPOLOGYPREF_HUBSPOKE, pHubMember);
  464. BOOL bSameTopology = _EnableRebuild();
  465. ::EnableWindow(GetDlgItem(IDC_FRS_CUSTOP_REBUILD), bSameTopology);
  466. }
  467. return (SUCCEEDED(hr));
  468. }
  469. LRESULT CCustomTopology::OnRebuild
  470. (
  471. WORD wNotifyCode,
  472. WORD wID,
  473. HWND hWndCtl,
  474. BOOL& bHandled
  475. )
  476. {
  477. HRESULT hr = S_OK;
  478. if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  479. {
  480. CCusTopMember* pHubMember = NULL;
  481. hr = _GetHubMember(&pHubMember);
  482. if (SUCCEEDED(hr))
  483. hr = _RebuildConnections(m_bstrTopologyPref, pHubMember);
  484. } else
  485. hr = _RebuildConnections(m_bstrTopologyPref, NULL);
  486. return (SUCCEEDED(hr));
  487. }
  488. HRESULT CCustomTopology::_RebuildConnections(
  489. IN BSTR i_bstrTopologyPref,
  490. IN CCusTopMember* i_pHubMember)
  491. {
  492. HRESULT hr = S_OK;
  493. //
  494. // delete all existing connections from list and view
  495. //
  496. CCusTopConnectionList::iterator it = m_ConnectionList.begin();
  497. while (it != m_ConnectionList.end())
  498. {
  499. CCusTopConnectionList::iterator itConn = it++;
  500. if (CONNECTION_OPTYPE_ADD == (*itConn)->m_opType)
  501. {
  502. delete (*itConn);
  503. m_ConnectionList.erase(itConn);
  504. } else
  505. {
  506. (*itConn)->m_opType = CONNECTION_OPTYPE_DEL;
  507. }
  508. }
  509. ListView_DeleteAllItems(GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS));
  510. //
  511. // re-create the connections as specified
  512. //
  513. if (m_MemberList.size() == 1)
  514. return hr;
  515. CCusTopMemberList::iterator n1;
  516. CCusTopMemberList::iterator n2;
  517. CCusTopConnection Conn;
  518. if (!lstrcmpi(i_bstrTopologyPref, FRS_RSTOPOLOGYPREF_RING))
  519. {
  520. CCusTopMemberList::iterator head;
  521. head = n1 = m_MemberList.begin();
  522. while (n1 != m_MemberList.end())
  523. {
  524. n2 = n1++;
  525. if (n1 == m_MemberList.end())
  526. {
  527. if (m_MemberList.size() == 2)
  528. break;
  529. n1 = head;
  530. }
  531. hr = Conn.Init((*n1)->m_bstrMemberDN, (*n1)->m_bstrServer, (*n1)->m_bstrSite,
  532. (*n2)->m_bstrMemberDN, (*n2)->m_bstrServer, (*n2)->m_bstrSite,
  533. TRUE, CONNECTION_OPTYPE_ADD);
  534. BREAK_IF_FAILED(hr);
  535. hr = _AddToConnectionListAndView(&Conn);
  536. BREAK_IF_FAILED(hr);
  537. hr = Conn.Init((*n2)->m_bstrMemberDN, (*n2)->m_bstrServer, (*n2)->m_bstrSite,
  538. (*n1)->m_bstrMemberDN, (*n1)->m_bstrServer, (*n1)->m_bstrSite,
  539. TRUE, CONNECTION_OPTYPE_ADD);
  540. BREAK_IF_FAILED(hr);
  541. hr = _AddToConnectionListAndView(&Conn);
  542. BREAK_IF_FAILED(hr);
  543. if (n1 == head)
  544. break;
  545. }
  546. } else if (!lstrcmpi(i_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  547. {
  548. for (n1 = m_MemberList.begin(); n1 != m_MemberList.end(); n1++)
  549. {
  550. if (!lstrcmpi((*n1)->m_bstrMemberDN, i_pHubMember->m_bstrMemberDN))
  551. continue;
  552. hr = Conn.Init((*n1)->m_bstrMemberDN, (*n1)->m_bstrServer, (*n1)->m_bstrSite,
  553. i_pHubMember->m_bstrMemberDN, i_pHubMember->m_bstrServer, i_pHubMember->m_bstrSite,
  554. TRUE, CONNECTION_OPTYPE_ADD);
  555. BREAK_IF_FAILED(hr);
  556. hr = _AddToConnectionListAndView(&Conn);
  557. BREAK_IF_FAILED(hr);
  558. hr = Conn.Init(i_pHubMember->m_bstrMemberDN, i_pHubMember->m_bstrServer, i_pHubMember->m_bstrSite,
  559. (*n1)->m_bstrMemberDN, (*n1)->m_bstrServer, (*n1)->m_bstrSite,
  560. TRUE, CONNECTION_OPTYPE_ADD);
  561. BREAK_IF_FAILED(hr);
  562. hr = _AddToConnectionListAndView(&Conn);
  563. BREAK_IF_FAILED(hr);
  564. }
  565. } else if (!lstrcmpi(i_bstrTopologyPref, FRS_RSTOPOLOGYPREF_FULLMESH))
  566. {
  567. for (n1 = m_MemberList.begin(); n1 != m_MemberList.end(); n1++)
  568. {
  569. for (n2 = m_MemberList.begin(); n2 != m_MemberList.end(); n2++)
  570. {
  571. if (!lstrcmpi((*n1)->m_bstrMemberDN, (*n2)->m_bstrMemberDN))
  572. continue;
  573. hr = Conn.Init((*n1)->m_bstrMemberDN, (*n1)->m_bstrServer, (*n1)->m_bstrSite,
  574. (*n2)->m_bstrMemberDN, (*n2)->m_bstrServer, (*n2)->m_bstrSite,
  575. TRUE, CONNECTION_OPTYPE_ADD);
  576. BREAK_IF_FAILED(hr);
  577. hr = _AddToConnectionListAndView(&Conn);
  578. BREAK_IF_FAILED(hr);
  579. }
  580. BREAK_IF_FAILED(hr);
  581. }
  582. }
  583. return hr;
  584. }
  585. HRESULT CCustomTopology::_SetConnectionState(CCusTopConnection *pConn)
  586. {
  587. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  588. int nIndex = ListView_GetNextItem(hwnd, -1, LVNI_ALL);
  589. while (-1 != nIndex)
  590. {
  591. if (pConn == (CCusTopConnection *)GetListViewItemData(hwnd, nIndex))
  592. break;
  593. nIndex = ListView_GetNextItem(hwnd, nIndex, LVNI_ALL);
  594. }
  595. if (-1 != nIndex)
  596. {
  597. ListView_SetCheckState(hwnd, nIndex, pConn->m_bStateNew);
  598. ListView_Update(hwnd, nIndex);
  599. }
  600. return S_OK;
  601. }
  602. HRESULT CCustomTopology::_InsertConnection(CCusTopConnection *pConn)
  603. {
  604. RETURN_INVALIDARG_IF_NULL(pConn);
  605. HWND hwndControl = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  606. LVITEM lvItem;
  607. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  608. lvItem.lParam = (LPARAM)pConn;
  609. lvItem.pszText = _T("");
  610. lvItem.iSubItem = 0;
  611. int iItemIndex = ListView_InsertItem(hwndControl, &lvItem);
  612. lvItem.mask = LVIF_TEXT;
  613. lvItem.iItem = iItemIndex;
  614. lvItem.pszText = pConn->m_bstrFromServer;
  615. lvItem.iSubItem = 1;
  616. ListView_SetItem(hwndControl, &lvItem);
  617. lvItem.mask = LVIF_TEXT;
  618. lvItem.iItem = iItemIndex;
  619. lvItem.pszText = pConn->m_bstrToServer;
  620. lvItem.iSubItem = 2;
  621. ListView_SetItem(hwndControl, &lvItem);
  622. lvItem.mask = LVIF_TEXT;
  623. lvItem.iItem = iItemIndex;
  624. lvItem.pszText = pConn->m_bstrFromSite;
  625. lvItem.iSubItem = 3;
  626. ListView_SetItem(hwndControl, &lvItem);
  627. lvItem.mask = LVIF_TEXT;
  628. lvItem.iItem = iItemIndex;
  629. lvItem.pszText = pConn->m_bstrToSite;
  630. lvItem.iSubItem = 4;
  631. ListView_SetItem(hwndControl, &lvItem);
  632. ListView_SetCheckState(hwndControl, iItemIndex, pConn->m_bStateNew);
  633. ListView_Update(hwndControl, iItemIndex);
  634. return S_OK;
  635. }
  636. LRESULT CCustomTopology::OnConnectionsNew
  637. (
  638. WORD wNotifyCode,
  639. WORD wID,
  640. HWND hWndCtl,
  641. BOOL& bHandled
  642. )
  643. {
  644. HRESULT hr = S_OK;
  645. CNewConnections NewConnDlg;
  646. hr = NewConnDlg.Initialize(&m_MemberList);
  647. if (SUCCEEDED(hr))
  648. {
  649. hr = NewConnDlg.DoModal();
  650. if (S_OK == hr)
  651. {
  652. CCusTopConnectionList* pNewConnectionList = NULL;
  653. hr = NewConnDlg.get_NewConnections(&pNewConnectionList);
  654. if (SUCCEEDED(hr))
  655. {
  656. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  657. int nCount = ListView_GetItemCount(hwnd);
  658. CCusTopConnectionList::iterator it;
  659. for (it = pNewConnectionList->begin(); it != pNewConnectionList->end(); it++)
  660. {
  661. hr = _AddToConnectionListAndView(*it);
  662. BREAK_IF_FAILED(hr);
  663. }
  664. if (ListView_GetItemCount(hwnd) > nCount)
  665. ListView_SortItems(hwnd, ConnectionsListCompareProc, (LPARAM)g_FRS_CUSTOP_Last_SortColumn);
  666. }
  667. }
  668. }
  669. // if FAILED, display msg?
  670. return (SUCCEEDED(hr));
  671. }
  672. LRESULT CCustomTopology::OnConnectionsDelete
  673. (
  674. WORD wNotifyCode,
  675. WORD wID,
  676. HWND hWndCtl,
  677. BOOL& bHandled
  678. )
  679. {
  680. CCusTopConnection* pConn;
  681. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  682. int nIndex = ListView_GetNextItem(hwnd, -1, LVNI_ALL | LVNI_SELECTED);
  683. while (-1 != nIndex &&
  684. (pConn = (CCusTopConnection *)GetListViewItemData(hwnd, nIndex)))
  685. {
  686. _RemoveFromConnectionList(pConn);
  687. ListView_DeleteItem(hwnd, nIndex);
  688. nIndex = ListView_GetNextItem(hwnd, -1, LVNI_ALL | LVNI_SELECTED);
  689. }
  690. return TRUE;
  691. }
  692. HRESULT CCustomTopology::_InitScheduleOnSelectedConnections()
  693. {
  694. HRESULT hr = S_OK;
  695. int nIndex = -1;
  696. CCusTopConnection* pConn = NULL;
  697. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  698. while ( -1 != (nIndex = ListView_GetNextItem(hwnd, nIndex, LVNI_ALL | LVNI_SELECTED)) &&
  699. NULL != (pConn = (CCusTopConnection *)GetListViewItemData(hwnd, nIndex)))
  700. {
  701. if (!pConn->m_pScheduleNew)
  702. {
  703. if (pConn->m_pScheduleOld)
  704. {
  705. hr = CopySchedule(pConn->m_pScheduleOld, &pConn->m_pScheduleNew);
  706. RETURN_IF_FAILED(hr);
  707. } else
  708. {
  709. if (CONNECTION_OPTYPE_OTHERS == pConn->m_opType)
  710. {
  711. //
  712. // read schedule on an existing connection for the very first time
  713. //
  714. VARIANT var;
  715. VariantInit(&var);
  716. hr = m_piReplicaSet->GetConnectionScheduleEx(pConn->m_bstrFromMemberDN, pConn->m_bstrToMemberDN, &var);
  717. RETURN_IF_FAILED(hr);
  718. hr = VariantToSchedule(&var, &pConn->m_pScheduleOld);
  719. VariantClear(&var);
  720. if (SUCCEEDED(hr))
  721. hr = CopySchedule(pConn->m_pScheduleOld, &pConn->m_pScheduleNew);
  722. RETURN_IF_FAILED(hr);
  723. } else
  724. { // must be ADD operation
  725. hr = GetDefaultSchedule(&pConn->m_pScheduleNew);
  726. RETURN_IF_FAILED(hr);
  727. }
  728. }
  729. }
  730. }
  731. return hr;
  732. }
  733. HRESULT CCustomTopology::_UpdateScheduleOnSelectedConnections(IN SCHEDULE* i_pSchedule)
  734. {
  735. HRESULT hr = S_OK;
  736. int nIndex = -1;
  737. CCusTopConnection* pConn = NULL;
  738. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  739. while ( -1 != (nIndex = ListView_GetNextItem(hwnd, nIndex, LVNI_ALL | LVNI_SELECTED)) &&
  740. NULL != (pConn = (CCusTopConnection *)GetListViewItemData(hwnd, nIndex)))
  741. {
  742. if (pConn->m_pScheduleNew)
  743. {
  744. free(pConn->m_pScheduleNew);
  745. pConn->m_pScheduleNew = NULL;
  746. }
  747. hr = CopySchedule(i_pSchedule, &pConn->m_pScheduleNew);
  748. BREAK_IF_FAILED(hr);
  749. }
  750. return hr;
  751. }
  752. LRESULT CCustomTopology::OnSchedule
  753. (
  754. WORD wNotifyCode,
  755. WORD wID,
  756. HWND hWndCtl,
  757. BOOL& bHandled
  758. )
  759. {
  760. HRESULT hr = S_OK;
  761. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  762. int nCount = ListView_GetSelectedCount(hwnd);
  763. if (nCount < 1)
  764. {
  765. DisplayMessageBoxWithOK(IDS_FRS_CUSTOP_NOSELECTION);
  766. return FALSE;
  767. }
  768. do {
  769. //
  770. // get schedule info on each selected connections
  771. //
  772. hr = _InitScheduleOnSelectedConnections();
  773. BREAK_IF_FAILED(hr);
  774. //
  775. // get schedule of the first selected item
  776. //
  777. int nIndex = ListView_GetNextItem(hwnd, -1, LVNI_ALL | LVNI_SELECTED);
  778. if (-1 == nIndex)
  779. {
  780. hr = E_INVALIDARG;
  781. break;
  782. }
  783. CCusTopConnection* pConn = (CCusTopConnection *)GetListViewItemData(hwnd, nIndex);
  784. if (!pConn)
  785. {
  786. hr = E_INVALIDARG;
  787. break;
  788. }
  789. SCHEDULE* pSchedule = NULL;
  790. hr = CopySchedule(pConn->m_pScheduleNew, &pSchedule);
  791. BREAK_IF_FAILED(hr);
  792. hr = InvokeScheduleDlg(m_hWnd, pSchedule);
  793. if (S_OK == hr)
  794. hr = _UpdateScheduleOnSelectedConnections(pSchedule);
  795. free(pSchedule);
  796. } while (0);
  797. if (FAILED(hr))
  798. DisplayMessageBoxForHR(hr);
  799. return (SUCCEEDED(hr));
  800. }
  801. LRESULT CCustomTopology::OnOK
  802. (
  803. WORD wNotifyCode,
  804. WORD wID,
  805. HWND hWndCtl,
  806. BOOL& bHandled
  807. )
  808. {
  809. CWaitCursor wait;
  810. BOOL bValidInput = FALSE;
  811. int idString = 0;
  812. HRESULT hr = S_OK;
  813. do {
  814. //
  815. // if changed, update TopologyPref
  816. //
  817. int index = SendDlgItemMessage(IDC_FRS_CUSTOP_TOPOLOGYPREF, CB_GETCURSEL, 0, 0);
  818. if (0 != lstrcmpi(m_bstrTopologyPref, g_TopologyPref[index].pszTopologyPref))
  819. {
  820. hr = m_piReplicaSet->put_TopologyPref(g_TopologyPref[index].pszTopologyPref);
  821. BREAK_IF_FAILED(hr);
  822. }
  823. //
  824. // if changed, update HubServer
  825. //
  826. if (!lstrcmpi(m_bstrTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE) &&
  827. 0 != lstrcmpi(g_TopologyPref[index].pszTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  828. {
  829. hr = m_piReplicaSet->put_HubMemberDN(NULL);
  830. BREAK_IF_FAILED(hr);
  831. } else if (!lstrcmpi(g_TopologyPref[index].pszTopologyPref, FRS_RSTOPOLOGYPREF_HUBSPOKE))
  832. {
  833. CCusTopMember* pHubMember = NULL;
  834. hr = _GetHubMember(&pHubMember);
  835. BREAK_IF_FAILED(hr);
  836. if (0 != lstrcmpi(m_bstrHubMemberDN, pHubMember->m_bstrMemberDN))
  837. hr = m_piReplicaSet->put_HubMemberDN(pHubMember->m_bstrMemberDN);
  838. BREAK_IF_FAILED(hr);
  839. }
  840. //
  841. // if changed, update connections
  842. //
  843. CCusTopConnection* pConn = NULL;
  844. HWND hwnd = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  845. index = -1;
  846. while (-1 != (index = ListView_GetNextItem(hwnd, index, LVNI_ALL)))
  847. {
  848. pConn = (CCusTopConnection *)GetListViewItemData(hwnd, index);
  849. if (pConn)
  850. pConn->m_bStateNew = ListView_GetCheckState(hwnd, index);
  851. }
  852. hr = _MakeConnections();
  853. BREAK_IF_FAILED(hr);
  854. bValidInput = TRUE;
  855. } while (0);
  856. if (FAILED(hr))
  857. {
  858. DisplayMessageBoxForHR(hr);
  859. return FALSE;
  860. } else if (bValidInput)
  861. {
  862. EndDialog(S_OK);
  863. return TRUE;
  864. }
  865. else
  866. {
  867. if (idString)
  868. DisplayMessageBoxWithOK(idString);
  869. return FALSE;
  870. }
  871. }
  872. LRESULT CCustomTopology::OnCancel
  873. (
  874. WORD wNotifyCode,
  875. WORD wID,
  876. HWND hWndCtl,
  877. BOOL& bHandled
  878. )
  879. {
  880. /*++
  881. Routine Description:
  882. Called OnCancel. Ends the dialog with S_FALSE;
  883. */
  884. EndDialog(S_FALSE);
  885. return(true);
  886. }
  887. int CALLBACK ConnectionsListCompareProc(
  888. IN LPARAM lParam1,
  889. IN LPARAM lParam2,
  890. IN LPARAM lParamColumn)
  891. {
  892. CCusTopConnection* pItem1 = (CCusTopConnection *)lParam1;
  893. CCusTopConnection* pItem2 = (CCusTopConnection *)lParam2;
  894. int iResult = 0;
  895. if (pItem1 && pItem2)
  896. {
  897. g_FRS_CUSTOP_Last_SortColumn = lParamColumn;
  898. switch (lParamColumn)
  899. {
  900. case 0: // Sort by bStateNew.
  901. iResult = pItem1->m_bStateNew - pItem2->m_bStateNew;
  902. break;
  903. case 1: // Sort by From Server.
  904. iResult = lstrcmpi(pItem1->m_bstrFromServer, pItem2->m_bstrFromServer);
  905. break;
  906. case 2: // Sort by To Server.
  907. iResult = lstrcmpi(pItem1->m_bstrToServer, pItem2->m_bstrToServer);
  908. break;
  909. case 3: // Sort by From Site.
  910. iResult = lstrcmpi(pItem1->m_bstrFromSite, pItem2->m_bstrFromSite);
  911. break;
  912. case 4: // Sort by To Site.
  913. iResult = lstrcmpi(pItem1->m_bstrToSite, pItem2->m_bstrToSite);
  914. break;
  915. default:
  916. iResult = 0;
  917. break;
  918. }
  919. }
  920. return(iResult);
  921. }
  922. LRESULT
  923. CCustomTopology::OnNotify(
  924. IN UINT i_uMsg,
  925. IN WPARAM i_wParam,
  926. IN LPARAM i_lParam,
  927. IN OUT BOOL& io_bHandled
  928. )
  929. {
  930. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)i_lParam;
  931. io_bHandled = FALSE; // So that the base class gets this notify too
  932. if (IDC_FRS_CUSTOP_CONNECTIONS == pNMListView->hdr.idFrom)
  933. {
  934. HWND hwndList = GetDlgItem(IDC_FRS_CUSTOP_CONNECTIONS);
  935. if (LVN_COLUMNCLICK == pNMListView->hdr.code)
  936. {
  937. // sort items
  938. ListView_SortItems( hwndList,
  939. ConnectionsListCompareProc,
  940. (LPARAM)(pNMListView->iSubItem));
  941. io_bHandled = TRUE;
  942. } else if (LVN_ITEMCHANGED == pNMListView->hdr.code)
  943. {
  944. _EnableButtonsForConnectionList();
  945. }
  946. }
  947. return io_bHandled;
  948. }
  949. //
  950. // Update the connection objects in the DS
  951. //
  952. HRESULT CCustomTopology::_MakeConnections()
  953. {
  954. HRESULT hr = S_OK;
  955. CCusTopConnectionList::iterator it;
  956. for (it = m_ConnectionList.begin(); it != m_ConnectionList.end(); it++)
  957. {
  958. switch ((*it)->m_opType)
  959. {
  960. case CONNECTION_OPTYPE_ADD:
  961. hr = m_piReplicaSet->AddConnection(
  962. (*it)->m_bstrFromMemberDN,
  963. (*it)->m_bstrToMemberDN,
  964. (*it)->m_bStateNew,
  965. NULL
  966. );
  967. BREAK_IF_FAILED(hr);
  968. if ((*it)->m_pScheduleNew)
  969. {
  970. VARIANT var;
  971. VariantInit(&var);
  972. hr = ScheduleToVariant((*it)->m_pScheduleNew, &var);
  973. BREAK_IF_FAILED(hr);
  974. hr = m_piReplicaSet->SetConnectionScheduleEx(
  975. (*it)->m_bstrFromMemberDN,
  976. (*it)->m_bstrToMemberDN,
  977. &var);
  978. VariantClear(&var);
  979. }
  980. break;
  981. case CONNECTION_OPTYPE_DEL:
  982. hr = m_piReplicaSet->RemoveConnectionEx(
  983. (*it)->m_bstrFromMemberDN,
  984. (*it)->m_bstrToMemberDN
  985. );
  986. break;
  987. default:
  988. if ((*it)->m_bStateNew != (*it)->m_bStateOld)
  989. {
  990. hr = m_piReplicaSet->EnableConnectionEx(
  991. (*it)->m_bstrFromMemberDN,
  992. (*it)->m_bstrToMemberDN,
  993. (*it)->m_bStateNew
  994. );
  995. BREAK_IF_FAILED(hr);
  996. }
  997. if (S_OK == CompareSchedules((*it)->m_pScheduleNew, (*it)->m_pScheduleOld))
  998. break; // no change on shcedule
  999. if ((*it)->m_pScheduleNew)
  1000. {
  1001. VARIANT var;
  1002. VariantInit(&var);
  1003. hr = ScheduleToVariant((*it)->m_pScheduleNew, &var);
  1004. BREAK_IF_FAILED(hr);
  1005. hr = m_piReplicaSet->SetConnectionScheduleEx(
  1006. (*it)->m_bstrFromMemberDN,
  1007. (*it)->m_bstrToMemberDN,
  1008. &var);
  1009. VariantClear(&var);
  1010. }
  1011. break;
  1012. }
  1013. BREAK_IF_FAILED(hr);
  1014. }
  1015. return hr;
  1016. }
  1017. //////////////////////////////////////////////////////////
  1018. //
  1019. //
  1020. void FreeCusTopMembers(CCusTopMemberList* pList)
  1021. {
  1022. if (pList && !pList->empty())
  1023. {
  1024. for (CCusTopMemberList::iterator i = pList->begin(); i != pList->end(); i++)
  1025. delete (*i);
  1026. pList->clear();
  1027. }
  1028. }
  1029. void FreeCusTopConnections(CCusTopConnectionList* pList)
  1030. {
  1031. if (pList && !pList->empty())
  1032. {
  1033. for (CCusTopConnectionList::iterator i = pList->begin(); i != pList->end(); i++)
  1034. delete (*i);
  1035. pList->clear();
  1036. }
  1037. }
  1038. //////////////////////////////////////////////////////////
  1039. //
  1040. // CCusTopMember
  1041. //
  1042. CCusTopMember::~CCusTopMember()
  1043. {
  1044. _Reset();
  1045. }
  1046. HRESULT CCusTopMember::Init(BSTR bstrMemberDN, BSTR bstrServer, BSTR bstrSite)
  1047. {
  1048. RETURN_INVALIDARG_IF_NULL(bstrMemberDN);
  1049. RETURN_INVALIDARG_IF_NULL(bstrServer);
  1050. RETURN_INVALIDARG_IF_NULL(bstrSite);
  1051. _Reset();
  1052. HRESULT hr = S_OK;
  1053. do {
  1054. m_bstrMemberDN = bstrMemberDN;
  1055. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrMemberDN, &hr);
  1056. m_bstrServer = bstrServer;
  1057. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrServer, &hr);
  1058. m_bstrSite = bstrSite;
  1059. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrSite, &hr);
  1060. } while (0);
  1061. if (FAILED(hr))
  1062. _Reset();
  1063. return hr;
  1064. }
  1065. void CCusTopMember::_Reset()
  1066. {
  1067. m_bstrMemberDN.Empty();
  1068. m_bstrServer.Empty();
  1069. m_bstrSite.Empty();
  1070. }
  1071. //////////////////////////////////////////////////////////
  1072. //
  1073. // CCusTopConnection
  1074. //
  1075. CCusTopConnection::CCusTopConnection()
  1076. {
  1077. m_bStateOld = m_bStateNew = TRUE;
  1078. m_pScheduleOld = m_pScheduleNew = NULL;
  1079. m_opType = CONNECTION_OPTYPE_OTHERS;
  1080. }
  1081. CCusTopConnection::~CCusTopConnection()
  1082. {
  1083. _Reset();
  1084. }
  1085. HRESULT CCusTopConnection::Init(
  1086. BSTR bstrFromMemberDN, BSTR bstrFromServer, BSTR bstrFromSite,
  1087. BSTR bstrToMemberDN, BSTR bstrToServer, BSTR bstrToSite,
  1088. BOOL bState, // = TRUE
  1089. CONNECTION_OPTYPE opType // = CONNECTION_OPTYPE_OTHERS
  1090. )
  1091. {
  1092. RETURN_INVALIDARG_IF_NULL(bstrFromMemberDN);
  1093. RETURN_INVALIDARG_IF_NULL(bstrFromServer);
  1094. RETURN_INVALIDARG_IF_NULL(bstrFromSite);
  1095. RETURN_INVALIDARG_IF_NULL(bstrToMemberDN);
  1096. RETURN_INVALIDARG_IF_NULL(bstrToServer);
  1097. RETURN_INVALIDARG_IF_NULL(bstrToSite);
  1098. _Reset();
  1099. HRESULT hr = S_OK;
  1100. do {
  1101. m_bstrFromMemberDN = bstrFromMemberDN;
  1102. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromMemberDN, &hr);
  1103. m_bstrFromServer = bstrFromServer;
  1104. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromServer, &hr);
  1105. m_bstrFromSite = bstrFromSite;
  1106. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromSite, &hr);
  1107. m_bstrToMemberDN = bstrToMemberDN;
  1108. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToMemberDN, &hr);
  1109. m_bstrToServer = bstrToServer;
  1110. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToServer, &hr);
  1111. m_bstrToSite = bstrToSite;
  1112. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToSite, &hr);
  1113. m_bStateNew = m_bStateOld = bState;
  1114. m_opType = opType;
  1115. m_pScheduleOld = m_pScheduleNew = NULL;
  1116. } while (0);
  1117. if (FAILED(hr))
  1118. _Reset();
  1119. return hr;
  1120. }
  1121. void CCusTopConnection::_Reset()
  1122. {
  1123. m_bstrFromMemberDN.Empty();
  1124. m_bstrFromServer.Empty();
  1125. m_bstrFromSite.Empty();
  1126. m_bstrToMemberDN.Empty();
  1127. m_bstrToServer.Empty();
  1128. m_bstrToSite.Empty();
  1129. m_bStateOld = TRUE;
  1130. m_bStateNew = TRUE;
  1131. m_opType = CONNECTION_OPTYPE_OTHERS;
  1132. if (m_pScheduleOld)
  1133. {
  1134. free(m_pScheduleOld);
  1135. m_pScheduleOld = NULL;
  1136. }
  1137. if (m_pScheduleNew)
  1138. {
  1139. free(m_pScheduleNew);
  1140. m_pScheduleNew = NULL;
  1141. }
  1142. }
  1143. HRESULT CCusTopConnection::Copy(CCusTopConnection* pConn)
  1144. {
  1145. if (!pConn || !(pConn->m_bstrFromMemberDN) || !*(pConn->m_bstrFromMemberDN))
  1146. return E_INVALIDARG;
  1147. _Reset();
  1148. HRESULT hr = S_OK;
  1149. do {
  1150. m_bstrFromMemberDN = pConn->m_bstrFromMemberDN;
  1151. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromMemberDN, &hr);
  1152. m_bstrFromServer = pConn->m_bstrFromServer;
  1153. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromServer, &hr);
  1154. m_bstrFromSite = pConn->m_bstrFromSite;
  1155. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrFromSite, &hr);
  1156. m_bstrToMemberDN = pConn->m_bstrToMemberDN;
  1157. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToMemberDN, &hr);
  1158. m_bstrToServer = pConn->m_bstrToServer;
  1159. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToServer, &hr);
  1160. m_bstrToSite = pConn->m_bstrToSite;
  1161. BREAK_OUTOFMEMORY_IF_NULL((BSTR)m_bstrToSite, &hr);
  1162. m_bStateOld = pConn->m_bStateOld;
  1163. m_bStateNew = pConn->m_bStateNew;
  1164. m_opType = pConn->m_opType;
  1165. if (pConn->m_pScheduleOld)
  1166. {
  1167. hr = CopySchedule(pConn->m_pScheduleOld, &m_pScheduleOld);
  1168. BREAK_IF_FAILED(hr);
  1169. }
  1170. if (pConn->m_pScheduleNew)
  1171. {
  1172. hr = CopySchedule(pConn->m_pScheduleNew, &m_pScheduleNew);
  1173. BREAK_IF_FAILED(hr);
  1174. }
  1175. } while (0);
  1176. if (FAILED(hr))
  1177. _Reset();
  1178. return hr;
  1179. }
  1180. HRESULT CCustomTopology::_AddToConnectionListAndView(CCusTopConnection* pConn)
  1181. {
  1182. RETURN_INVALIDARG_IF_NULL(pConn);
  1183. BOOL bFound = FALSE;
  1184. CCusTopConnectionList::iterator it;
  1185. for (it = m_ConnectionList.begin(); it != m_ConnectionList.end(); it++)
  1186. {
  1187. if (!lstrcmpi((*it)->m_bstrFromMemberDN, pConn->m_bstrFromMemberDN) &&
  1188. !lstrcmpi((*it)->m_bstrToMemberDN, pConn->m_bstrToMemberDN))
  1189. {
  1190. bFound = TRUE;
  1191. break;
  1192. }
  1193. }
  1194. HRESULT hr = S_OK;
  1195. if (!bFound)
  1196. {
  1197. CCusTopConnection* pNew = new CCusTopConnection;
  1198. RETURN_OUTOFMEMORY_IF_NULL(pNew);
  1199. hr = pNew->Copy(pConn);
  1200. if (FAILED(hr))
  1201. delete pNew;
  1202. else
  1203. {
  1204. m_ConnectionList.push_back(pNew);
  1205. hr = _InsertConnection(pNew);
  1206. }
  1207. } else
  1208. {
  1209. (*it)->m_bStateNew = TRUE;
  1210. if ((*it)->m_opType == CONNECTION_OPTYPE_DEL)
  1211. {
  1212. (*it)->m_opType = CONNECTION_OPTYPE_OTHERS;
  1213. hr = _InsertConnection(*it);
  1214. } else
  1215. {
  1216. (*it)->m_opType = CONNECTION_OPTYPE_OTHERS;
  1217. hr = _SetConnectionState(*it);
  1218. }
  1219. }
  1220. return hr;
  1221. }
  1222. HRESULT CCustomTopology::_RemoveFromConnectionList(CCusTopConnection* pConn)
  1223. {
  1224. RETURN_INVALIDARG_IF_NULL(pConn);
  1225. BOOL bFound = FALSE;
  1226. CCusTopConnectionList::iterator it;
  1227. for (it = m_ConnectionList.begin(); it != m_ConnectionList.end(); it++)
  1228. {
  1229. if (!lstrcmpi((*it)->m_bstrFromMemberDN, pConn->m_bstrFromMemberDN) &&
  1230. !lstrcmpi((*it)->m_bstrToMemberDN, pConn->m_bstrToMemberDN))
  1231. {
  1232. bFound = TRUE;
  1233. break;
  1234. }
  1235. }
  1236. if (it != m_ConnectionList.end())
  1237. {
  1238. if (CONNECTION_OPTYPE_ADD == (*it)->m_opType)
  1239. {
  1240. delete (*it);
  1241. m_ConnectionList.erase(it);
  1242. } else
  1243. {
  1244. (*it)->m_opType = CONNECTION_OPTYPE_DEL;
  1245. }
  1246. }
  1247. return S_OK;
  1248. }
  1249. /////////////////////////////////////////////////////////////////////////////
  1250. //
  1251. // CNewConnections
  1252. //
  1253. CNewConnections::CNewConnections() : m_pMemberList(NULL)
  1254. {
  1255. }
  1256. CNewConnections::~CNewConnections()
  1257. {
  1258. FreeCusTopConnections(&m_NewConnectionList);
  1259. }
  1260. HRESULT CNewConnections::Initialize
  1261. (
  1262. CCusTopMemberList* i_pMemberList
  1263. )
  1264. {
  1265. RETURN_INVALIDARG_IF_NULL(i_pMemberList);
  1266. m_pMemberList = i_pMemberList;
  1267. return S_OK;
  1268. }
  1269. #define NUM_OF_FRS_NEWCONN_COLUMNS 2
  1270. LRESULT CNewConnections::OnInitDialog
  1271. (
  1272. UINT uMsg,
  1273. WPARAM wParam,
  1274. LPARAM lParam,
  1275. BOOL& bHandled
  1276. )
  1277. {
  1278. int nControlID[] = {IDC_FRS_NEWCONN_FROM, IDC_FRS_NEWCONN_TO};
  1279. int nColStringID[] = {IDS_FRS_NEWCONN_COL_FROMSERVER, IDS_FRS_NEWCONN_COL_TOSERVER};
  1280. HWND hwndControl = NULL;
  1281. CCusTopMemberList::iterator it;
  1282. for (int i = 0; i < 2; i++)
  1283. {
  1284. hwndControl = GetDlgItem(nControlID[i]);
  1285. AddLVColumns(hwndControl, nColStringID[i], NUM_OF_FRS_NEWCONN_COLUMNS);
  1286. ListView_SetExtendedListViewStyle(hwndControl, LVS_EX_FULLROWSELECT);
  1287. for (it = m_pMemberList->begin(); it != m_pMemberList->end(); it++)
  1288. {
  1289. LVITEM lvItem;
  1290. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  1291. lvItem.lParam = (LPARAM)(*it);
  1292. lvItem.pszText = (*it)->m_bstrServer;
  1293. lvItem.iSubItem = 0;
  1294. int iItemIndex = ListView_InsertItem(hwndControl, &lvItem);
  1295. lvItem.mask = LVIF_TEXT;
  1296. lvItem.iItem = iItemIndex;
  1297. lvItem.pszText = (*it)->m_bstrSite;
  1298. lvItem.iSubItem = 1;
  1299. ListView_SetItem(hwndControl, &lvItem);
  1300. }
  1301. }
  1302. return TRUE; // Let the system set the focus
  1303. }
  1304. /*++
  1305. This function is called when a user clicks the ? in the top right of a property sheet
  1306. and then clciks a control, or when they hit F1 in a control.
  1307. --*/
  1308. LRESULT CNewConnections::OnCtxHelp(
  1309. IN UINT i_uMsg,
  1310. IN WPARAM i_wParam,
  1311. IN LPARAM i_lParam,
  1312. IN OUT BOOL& io_bHandled
  1313. )
  1314. {
  1315. LPHELPINFO lphi = (LPHELPINFO) i_lParam;
  1316. if (!lphi || lphi->iContextType != HELPINFO_WINDOW || lphi->iCtrlId < 0)
  1317. return FALSE;
  1318. ::WinHelp((HWND)(lphi->hItemHandle),
  1319. DFS_CTX_HELP_FILE,
  1320. HELP_WM_HELP,
  1321. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_FRS_NEWCONN);
  1322. return TRUE;
  1323. }
  1324. /*++
  1325. This function handles "What's This" help when a user right clicks the control
  1326. --*/
  1327. LRESULT CNewConnections::OnCtxMenuHelp(
  1328. IN UINT i_uMsg,
  1329. IN WPARAM i_wParam,
  1330. IN LPARAM i_lParam,
  1331. IN OUT BOOL& io_bHandled
  1332. )
  1333. {
  1334. ::WinHelp((HWND)i_wParam,
  1335. DFS_CTX_HELP_FILE,
  1336. HELP_CONTEXTMENU,
  1337. (DWORD_PTR)(PVOID)g_aHelpIDs_IDD_FRS_NEWCONN);
  1338. return TRUE;
  1339. }
  1340. HRESULT CNewConnections::get_NewConnections(CCusTopConnectionList** ppConnectionList)
  1341. {
  1342. RETURN_INVALIDARG_IF_NULL(ppConnectionList);
  1343. *ppConnectionList = &m_NewConnectionList;
  1344. return S_OK;
  1345. }
  1346. LRESULT CNewConnections::OnOK
  1347. (
  1348. WORD wNotifyCode,
  1349. WORD wID,
  1350. HWND hWndCtl,
  1351. BOOL& bHandled
  1352. )
  1353. {
  1354. BOOL bValidInput = FALSE;
  1355. int idString = 0;
  1356. HRESULT hr = S_OK;
  1357. do {
  1358. idString = IDS_FRS_NEWCONN_NOSELECTION;
  1359. //
  1360. // get all selected From servers
  1361. //
  1362. CCusTopMember* pMember;
  1363. CCusTopMemberList fromMemberList;
  1364. HWND hwndFrom = GetDlgItem(IDC_FRS_NEWCONN_FROM);
  1365. int nIndexFrom = ListView_GetNextItem(hwndFrom, -1, LVNI_ALL | LVNI_SELECTED);
  1366. while (-1 != nIndexFrom &&
  1367. (pMember = (CCusTopMember *)GetListViewItemData(hwndFrom, nIndexFrom)))
  1368. {
  1369. fromMemberList.push_back(pMember);
  1370. nIndexFrom = ListView_GetNextItem(hwndFrom, nIndexFrom, LVNI_ALL | LVNI_SELECTED);
  1371. }
  1372. if (fromMemberList.empty())
  1373. break;
  1374. //
  1375. // get all selected To servers
  1376. //
  1377. CCusTopMemberList toMemberList;
  1378. HWND hwndTo = GetDlgItem(IDC_FRS_NEWCONN_TO);
  1379. int nIndexTo = ListView_GetNextItem(hwndTo, -1, LVNI_ALL | LVNI_SELECTED);
  1380. while (-1 != nIndexTo &&
  1381. (pMember = (CCusTopMember *)GetListViewItemData(hwndTo, nIndexTo)))
  1382. {
  1383. toMemberList.push_back(pMember);
  1384. nIndexTo = ListView_GetNextItem(hwndTo, nIndexTo, LVNI_ALL | LVNI_SELECTED);
  1385. }
  1386. if (toMemberList.empty())
  1387. break;
  1388. //
  1389. // init the list
  1390. //
  1391. FreeCusTopConnections(&m_NewConnectionList);
  1392. //
  1393. // build the connection list
  1394. //
  1395. CCusTopMemberList::iterator from, to;
  1396. for (from = fromMemberList.begin(); from != fromMemberList.end(); from++)
  1397. {
  1398. for (to = toMemberList.begin(); to != toMemberList.end(); to++)
  1399. {
  1400. if (!lstrcmpi((*from)->m_bstrServer, (*to)->m_bstrServer))
  1401. continue;
  1402. CCusTopConnection* pNew = new CCusTopConnection;
  1403. BREAK_OUTOFMEMORY_IF_NULL(pNew, &hr);
  1404. hr = pNew->Init(
  1405. (*from)->m_bstrMemberDN, (*from)->m_bstrServer, (*from)->m_bstrSite,
  1406. (*to)->m_bstrMemberDN, (*to)->m_bstrServer, (*to)->m_bstrSite,
  1407. TRUE, CONNECTION_OPTYPE_ADD);
  1408. BREAK_IF_FAILED(hr);
  1409. m_NewConnectionList.push_back(pNew);
  1410. }
  1411. BREAK_IF_FAILED(hr);
  1412. }
  1413. if (SUCCEEDED(hr))
  1414. bValidInput = TRUE;
  1415. } while (0);
  1416. if (FAILED(hr))
  1417. {
  1418. DisplayMessageBoxForHR(hr);
  1419. return FALSE;
  1420. } else if (bValidInput)
  1421. {
  1422. EndDialog(S_OK);
  1423. return TRUE;
  1424. }
  1425. else
  1426. {
  1427. if (idString)
  1428. DisplayMessageBoxWithOK(idString);
  1429. return FALSE;
  1430. }
  1431. }
  1432. LRESULT CNewConnections::OnCancel
  1433. (
  1434. WORD wNotifyCode,
  1435. WORD wID,
  1436. HWND hWndCtl,
  1437. BOOL& bHandled
  1438. )
  1439. {
  1440. /*++
  1441. Routine Description:
  1442. Called OnCancel. Ends the dialog with S_FALSE;
  1443. */
  1444. EndDialog(S_FALSE);
  1445. return(true);
  1446. }
  1447. int CALLBACK MembersListCompareProc(
  1448. IN LPARAM lParam1,
  1449. IN LPARAM lParam2,
  1450. IN LPARAM lParamColumn)
  1451. {
  1452. CCusTopMember* pItem1 = (CCusTopMember *)lParam1;
  1453. CCusTopMember* pItem2 = (CCusTopMember *)lParam2;
  1454. int iResult = 0;
  1455. if (pItem1 && pItem2)
  1456. {
  1457. switch( lParamColumn)
  1458. {
  1459. case 0: // Sort by Server.
  1460. iResult = lstrcmpi(pItem1->m_bstrServer, pItem2->m_bstrServer);
  1461. break;
  1462. case 1: // Sort by Site.
  1463. iResult = lstrcmpi(pItem1->m_bstrSite, pItem2->m_bstrSite);
  1464. break;
  1465. default:
  1466. iResult = 0;
  1467. break;
  1468. }
  1469. }
  1470. return(iResult);
  1471. }
  1472. LRESULT
  1473. CNewConnections::OnNotify(
  1474. IN UINT i_uMsg,
  1475. IN WPARAM i_wParam,
  1476. IN LPARAM i_lParam,
  1477. IN OUT BOOL& io_bHandled
  1478. )
  1479. {
  1480. NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)i_lParam;
  1481. io_bHandled = FALSE; // So that the base class gets this notify too
  1482. if (IDC_FRS_NEWCONN_FROM == pNMListView->hdr.idFrom ||
  1483. IDC_FRS_NEWCONN_TO == pNMListView->hdr.idFrom)
  1484. {
  1485. HWND hwndList = GetDlgItem(pNMListView->hdr.idFrom);
  1486. if (LVN_COLUMNCLICK == pNMListView->hdr.code)
  1487. {
  1488. // sort items
  1489. ListView_SortItems( hwndList,
  1490. MembersListCompareProc,
  1491. (LPARAM)(pNMListView->iSubItem));
  1492. io_bHandled = TRUE;
  1493. }
  1494. }
  1495. return io_bHandled;
  1496. }