Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

573 lines
14 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // grouppage.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class ServerGroupPage.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/20/2000 Original version.
  16. // 04/19/2000 Marshall SDOs across apartments.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include <proxypch.h>
  20. #include <grouppage.h>
  21. #include <serverprop.h>
  22. CSysColorImageList::CSysColorImageList(
  23. HINSTANCE hInst,
  24. UINT nID
  25. )
  26. : m_hInst(hInst),
  27. m_hRsrc(::FindResource(m_hInst, MAKEINTRESOURCE(nID), RT_BITMAP))
  28. {
  29. CreateSysColorImageList();
  30. }
  31. void CSysColorImageList::OnSysColorChange()
  32. {
  33. DeleteImageList();
  34. CreateSysColorImageList();
  35. }
  36. void CSysColorImageList::CreateSysColorImageList()
  37. {
  38. CBitmap bmp;
  39. bmp.Attach(AfxLoadSysColorBitmap(m_hInst, m_hRsrc));
  40. // Get the dimensions of the bitmap.
  41. BITMAP bm;
  42. bmp.GetBitmap(&bm);
  43. // Assume square images (cx == cy).
  44. Create(bm.bmHeight, bm.bmHeight, ILC_COLORDDB, bm.bmWidth / bm.bmHeight, 2);
  45. Add(&bmp, CLR_NONE);
  46. }
  47. ///////////////////////////////////////////////////////////////////////////////
  48. //
  49. // Functions for sorting each column.
  50. //
  51. ///////////////////////////////////////////////////////////////////////////////
  52. int compareAddress(Sdo& s1, Sdo& s2)
  53. {
  54. CComBSTR v1, v2;
  55. s1.getValue(PROPERTY_RADIUSSERVER_ADDRESS, v1, L"");
  56. s2.getValue(PROPERTY_RADIUSSERVER_ADDRESS, v2, L"");
  57. return wcscmp(v1, v2);
  58. }
  59. int comparePriority(Sdo& s1, Sdo& s2)
  60. {
  61. LONG v1, v2;
  62. s1.getValue(PROPERTY_RADIUSSERVER_PRIORITY, v1, 1);
  63. s2.getValue(PROPERTY_RADIUSSERVER_PRIORITY, v2, 1);
  64. return (int)(v1 - v2);
  65. }
  66. int compareWeight(Sdo& s1, Sdo& s2)
  67. {
  68. LONG v1, v2;
  69. s1.getValue(PROPERTY_RADIUSSERVER_WEIGHT, v1, 50);
  70. s2.getValue(PROPERTY_RADIUSSERVER_WEIGHT, v2, 50);
  71. return (int)(v1 - v2);
  72. }
  73. //////////
  74. // CompareProc for sorting the ListCtrl.
  75. //////////
  76. int
  77. CALLBACK
  78. CompareProc(
  79. LPARAM lParam1,
  80. LPARAM lParam2,
  81. LPARAM lParamSort
  82. )
  83. {
  84. Sdo s1((ISdo*)lParam1), s2((ISdo*)lParam2);
  85. switch (lParamSort)
  86. {
  87. case 0:
  88. return compareAddress(s1, s2);
  89. case 1:
  90. return comparePriority(s1, s2);
  91. case 2:
  92. return compareWeight(s1, s2);
  93. case 3:
  94. return -compareAddress(s1, s2);
  95. case 4:
  96. return -comparePriority(s1, s2);
  97. case 5:
  98. return -compareWeight(s1, s2);
  99. }
  100. return 0;
  101. }
  102. ServerList::ServerList()
  103. : removeButton(NULL),
  104. editButton(NULL),
  105. sortIcons(AfxGetResourceHandle(), IDB_PROXY_SORT),
  106. sortColumn(0)
  107. {
  108. // All columns are initially in ascending order.
  109. descending[0] = descending[1] = descending[2] = false;
  110. }
  111. void ServerList::onInitDialog(HWND dialog, Sdo& serverGroup)
  112. {
  113. /////////
  114. // Get the servers collection.
  115. /////////
  116. serverGroup.getValue(
  117. PROPERTY_RADIUSSERVERGROUP_SERVERS_COLLECTION,
  118. servers
  119. );
  120. /////////
  121. // Subclass the list control and save the button handles.
  122. /////////
  123. if (!serverList.SubclassWindow(::GetDlgItem(dialog, IDC_LIST_SERVERS)))
  124. {
  125. AfxThrowNotSupportedException();
  126. }
  127. removeButton = GetDlgItem(dialog, IDC_BUTTON_REMOVE);
  128. editButton = GetDlgItem(dialog, IDC_BUTTON_EDIT);
  129. /////////
  130. // Load the image strip with the server icon.
  131. /////////
  132. serverIcons.Create(IDB_PROXY_SMALL_ICONS, 16, 0, RGB(255, 0, 255));
  133. serverList.SetImageList(&serverIcons, LVSIL_SMALL);
  134. /////////
  135. // Set the column headers.
  136. /////////
  137. RECT rect;
  138. serverList.GetClientRect(&rect);
  139. LONG width = rect.right - rect.left;
  140. ResourceString nameCol(IDS_SERVER_COLUMN_NAME);
  141. serverList.InsertColumn(0, nameCol, LVCFMT_LEFT, width - 150);
  142. ResourceString priorityCol(IDS_SERVER_COLUMN_PRIORITY);
  143. serverList.InsertColumn(1, priorityCol, LVCFMT_LEFT, 75);
  144. ResourceString weightCol(IDS_SERVER_COLUMN_WEIGHT);
  145. serverList.InsertColumn(2, weightCol, LVCFMT_LEFT, 75);
  146. serverList.SetExtendedStyle(
  147. serverList.GetExtendedStyle() | LVS_EX_FULLROWSELECT
  148. );
  149. CHeaderCtrl* hdr = serverList.GetHeaderCtrl();
  150. if (hdr) { hdr->SetImageList(&sortIcons); }
  151. }
  152. void ServerList::onSysColorChange()
  153. {
  154. sortIcons.OnSysColorChange();
  155. CHeaderCtrl* hdr = serverList.GetHeaderCtrl();
  156. if (hdr)
  157. {
  158. hdr->SetImageList(&sortIcons);
  159. }
  160. }
  161. void ServerList::onColumnClick(int column)
  162. {
  163. LVCOLUMN lvcol;
  164. memset(&lvcol, 0, sizeof(lvcol));
  165. lvcol.mask = LVCF_FMT | LVCF_IMAGE;
  166. lvcol.fmt = LVCFMT_IMAGE | LVCFMT_BITMAP_ON_RIGHT;
  167. // Reset the previous column's sort icon with blank icon.
  168. lvcol.iImage = -1;
  169. serverList.SetColumn(sortColumn, &lvcol);
  170. // If the user clicked on a new column, ...
  171. if (column != sortColumn)
  172. {
  173. // ... we use the existing sort order ...
  174. sortColumn = column;
  175. }
  176. else
  177. {
  178. // ... otherwise we flip it.
  179. descending[column] = !descending[column];
  180. }
  181. // Set the sort icon for new column.
  182. lvcol.iImage = (descending[sortColumn]) ? 1 : 0;
  183. serverList.SetColumn(sortColumn, &lvcol);
  184. sort();
  185. }
  186. void ServerList::onServerChanged()
  187. {
  188. // We only enable remove and edit when a server is selected.
  189. BOOL enable = serverList.GetSelectedCount() > 0;
  190. EnableWindow(removeButton, enable);
  191. EnableWindow(editButton, enable);
  192. }
  193. bool ServerList::onAdd()
  194. {
  195. bool modified = false;
  196. // Create a new server ...
  197. Sdo sdo = servers.create();
  198. // ... and a new server property sheet.
  199. ServerProperties props(sdo, IDS_SERVER_CAPTION_ADD);
  200. if (props.DoModal() == IDOK)
  201. {
  202. // Add this to the added list ...
  203. added.push_back(sdo);
  204. // ... and the list control.
  205. updateServer(sdo, 0, true);
  206. // Re-sort the list.
  207. sort();
  208. modified = true;
  209. }
  210. else
  211. {
  212. // User never applied the new server, so remove it.
  213. servers.remove(sdo);
  214. }
  215. return modified;
  216. }
  217. bool ServerList::onEdit()
  218. {
  219. bool modified = false;
  220. LVITEM lvi;
  221. memset(&lvi, 0, sizeof(lvi));
  222. // Get the item selected.
  223. lvi.iItem = serverList.GetNextItem(-1, LVNI_SELECTED);
  224. if (lvi.iItem >= 0)
  225. {
  226. // Get the lParam that contains the ISdo pointer.
  227. lvi.mask = LVIF_PARAM;
  228. if (serverList.GetItem(&lvi) && lvi.lParam)
  229. {
  230. // Create an Sdo ...
  231. Sdo sdo((ISdo*)lvi.lParam);
  232. // ... and a property sheet.
  233. ServerProperties props(sdo);
  234. if (props.DoModal() == IDOK)
  235. {
  236. // Add it to the dirty list if it's not already there.
  237. if (!dirty.contains(sdo) && !added.contains(sdo))
  238. {
  239. dirty.push_back(sdo);
  240. }
  241. // Update the entry in the list control.
  242. updateServer(sdo, lvi.iItem, false);
  243. // Re-sort the list.
  244. sort();
  245. modified = true;
  246. }
  247. }
  248. }
  249. return modified;
  250. }
  251. bool ServerList::onRemove()
  252. {
  253. bool modified = false;
  254. LVITEM lvi;
  255. memset(&lvi, 0, sizeof(lvi));
  256. // Get the selected item ...
  257. lvi.iItem = serverList.GetNextItem(-1, LVNI_SELECTED);
  258. if (lvi.iItem >= 0)
  259. {
  260. // ... and the associated SDO.
  261. lvi.mask = LVIF_PARAM;
  262. if (serverList.GetItem(&lvi) && lvi.lParam)
  263. {
  264. // Add to the removed list ...
  265. removed.push_back((ISdo*)lvi.lParam);
  266. // ... and remove from the list control.
  267. serverList.DeleteItem(lvi.iItem);
  268. modified = true;
  269. }
  270. }
  271. return modified;
  272. }
  273. void ServerList::setData()
  274. {
  275. serverList.DeleteAllItems();
  276. serverList.SetItemCount(servers.count());
  277. original.clear();
  278. original.reserve(servers.count());
  279. Sdo server;
  280. SdoEnum sdoEnum(servers.getNewEnum());
  281. for (UINT nItem = 0; sdoEnum.next(server); ++nItem)
  282. {
  283. updateServer(server, nItem, true);
  284. // We add each server to the 'original' vector solely to hold a reference
  285. // to the COM proxy.
  286. original.push_back(server);
  287. }
  288. sort();
  289. }
  290. void ServerList::saveChanges(bool apply)
  291. {
  292. SdoIterator i;
  293. if (apply)
  294. {
  295. // Persist all the dirty servers.
  296. for (i = dirty.begin(); i != dirty.end(); ++i)
  297. {
  298. Sdo(*i).apply();
  299. }
  300. // Persist all the added servers.
  301. for (i = added.begin(); i != added.end(); ++i)
  302. {
  303. Sdo(*i).apply();
  304. }
  305. }
  306. // Remove all the deleted servers.
  307. for (i = removed.begin(); i != removed.end(); ++i)
  308. {
  309. servers.remove(*i);
  310. }
  311. // Clear the collections.
  312. dirty.clear();
  313. added.clear();
  314. removed.clear();
  315. }
  316. void ServerList::discardChanges()
  317. {
  318. // Restore the dirty servers.
  319. SdoIterator i;
  320. for (i = dirty.begin(); i != dirty.end(); ++i)
  321. {
  322. Sdo(*i).restore();
  323. }
  324. dirty.clear();
  325. // Remove the added servers.
  326. for (i = added.begin(); i != added.end(); ++i)
  327. {
  328. servers.remove(*i);
  329. }
  330. added.clear();
  331. // Clear the deleted servers.
  332. removed.clear();
  333. }
  334. void ServerList::sort()
  335. {
  336. int column = sortColumn;
  337. if (descending[column]) { column += 3; }
  338. serverList.SortItems(CompareProc, column);
  339. }
  340. void ServerList::updateServer(
  341. Sdo& server,
  342. UINT nItem,
  343. bool create
  344. )
  345. {
  346. // Get the server's name.
  347. CComBSTR name;
  348. server.getValue(PROPERTY_RADIUSSERVER_ADDRESS, name);
  349. // Initialize an LVITEM.
  350. LVITEM lvi;
  351. memset(&lvi, 0, sizeof(LVITEM));
  352. lvi.iItem = nItem;
  353. lvi.pszText = name;
  354. if (create)
  355. {
  356. // If we're creating, we have to set everything.
  357. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  358. lvi.iImage = IMAGE_RADIUS_SERVER;
  359. lvi.lParam = (LPARAM)(ISdo*)server;
  360. lvi.iItem = serverList.InsertItem(&lvi);
  361. }
  362. else
  363. {
  364. // Otherwise we just set the text.
  365. lvi.mask = LVIF_TEXT;
  366. serverList.SetItem(&lvi);
  367. }
  368. LONG value;
  369. WCHAR sz[12];
  370. // Update priority ...
  371. server.getValue(PROPERTY_RADIUSSERVER_PRIORITY, value);
  372. serverList.SetItemText(lvi.iItem, 1, _ltow(value, sz, 10));
  373. // ... and weight.
  374. server.getValue(PROPERTY_RADIUSSERVER_WEIGHT, value);
  375. serverList.SetItemText(lvi.iItem, 2, _ltow(value, sz, 10));
  376. }
  377. ServerGroupPage::ServerGroupPage(
  378. LONG_PTR notifyHandle,
  379. LPARAM notifyParam,
  380. Sdo& groupSdo,
  381. bool useName
  382. )
  383. : SnapInPropertyPage(notifyHandle, notifyParam, true, IDD_SERVER_GROUP),
  384. selfStream(groupSdo)
  385. {
  386. if (useName) { groupSdo.getName(name); }
  387. }
  388. BOOL ServerGroupPage::OnInitDialog()
  389. {
  390. // Unmarshal the server group SDO.
  391. selfStream.get(self);
  392. // Initialize the server list control.
  393. servers.onInitDialog(m_hWnd, self);
  394. // Let our base class initialize.
  395. return SnapInPropertyPage::OnInitDialog();
  396. }
  397. void ServerGroupPage::OnSysColorChange()
  398. {
  399. servers.onSysColorChange();
  400. }
  401. void ServerGroupPage::onAdd()
  402. {
  403. if (servers.onAdd()) { SetModified(); }
  404. }
  405. void ServerGroupPage::onEdit()
  406. {
  407. if (servers.onEdit()) { SetModified(); }
  408. }
  409. void ServerGroupPage::onRemove()
  410. {
  411. if (servers.onRemove()) { SetModified(); }
  412. }
  413. void ServerGroupPage::onColumnClick(
  414. NMLISTVIEW *pNMListView,
  415. LRESULT* pResult
  416. )
  417. {
  418. servers.onColumnClick(pNMListView->iSubItem);
  419. }
  420. void ServerGroupPage::onItemActivate(
  421. NMITEMACTIVATE* pNMItemAct,
  422. LRESULT* pResult
  423. )
  424. {
  425. if (servers.onEdit()) { SetModified(); }
  426. }
  427. void ServerGroupPage::onServerChanged(
  428. NMLISTVIEW* pNMListView,
  429. LRESULT* pResult
  430. )
  431. {
  432. servers.onServerChanged();
  433. }
  434. void ServerGroupPage::getData()
  435. {
  436. // There must be at least one server.
  437. if (servers.isEmpty())
  438. {
  439. fail(IDC_LIST_SERVERS, IDS_GROUP_E_NO_SERVERS, false);
  440. }
  441. getValue(IDC_EDIT_NAME, name);
  442. // The user must specify a name ...
  443. if (name.Length() == 0)
  444. {
  445. fail(IDC_EDIT_NAME, IDS_GROUP_E_NAME_EMPTY);
  446. }
  447. // The name must be unique.
  448. if (!self.setName(name))
  449. {
  450. fail(IDC_EDIT_NAME, IDS_GROUP_E_NOT_UNIQUE);
  451. }
  452. }
  453. void ServerGroupPage::setData()
  454. {
  455. setValue(IDC_EDIT_NAME, name);
  456. servers.setData();
  457. }
  458. void ServerGroupPage::saveChanges()
  459. {
  460. // We have to update ourself first otherwise we won't be able to update
  461. // our children when creating a new group.
  462. self.apply();
  463. servers.saveChanges();
  464. }
  465. void ServerGroupPage::discardChanges()
  466. {
  467. // Restore ourself.
  468. self.restore();
  469. // Restore the servers.
  470. servers.discardChanges();
  471. }
  472. BEGIN_MESSAGE_MAP(ServerGroupPage, SnapInPropertyPage)
  473. ON_BN_CLICKED(IDC_BUTTON_ADD, onAdd)
  474. ON_BN_CLICKED(IDC_BUTTON_EDIT, onEdit)
  475. ON_BN_CLICKED(IDC_BUTTON_REMOVE, onRemove)
  476. ON_EN_CHANGE(IDC_EDIT_NAME, onChange)
  477. ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST_SERVERS, onColumnClick)
  478. ON_NOTIFY(LVN_ITEMACTIVATE, IDC_LIST_SERVERS, onItemActivate)
  479. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_SERVERS, onServerChanged)
  480. END_MESSAGE_MAP()