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.

611 lines
16 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // SYNOPSIS
  6. //
  7. // Declares the classes that make up the proxy profile property sheet.
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include <proxypch.h>
  11. #include <profileprop.h>
  12. #include <condlist.h>
  13. void ProfileProvPage::getData()
  14. {
  15. if (groupsCombo.IsWindowEnabled())
  16. {
  17. if (groupsCombo.GetCurSel() == invalidGroup)
  18. {
  19. fail(IDC_COMBO_GROUP, IDS_POLICY_E_GROUP_INVALID);
  20. }
  21. getValue(IDC_COMBO_GROUP, providerName);
  22. }
  23. else
  24. {
  25. providerName.Empty();
  26. }
  27. }
  28. void ProfileProvPage::setData()
  29. {
  30. initControl(IDC_COMBO_GROUP, groupsCombo);
  31. groupsCombo.ResetContent();
  32. // Make sure that the provider name is specified if and only if the provider
  33. // type is RADIUS. In theory, we should never break this constraint, but we
  34. // may as well repair it just in case.
  35. if (providerType == 2)
  36. {
  37. if (!providerName) { providerType = 1; }
  38. }
  39. else
  40. {
  41. providerName.Empty();
  42. }
  43. // Flag indicating whether the group specified in providerName exists.
  44. bool groupExists = false;
  45. // Get the server groups.
  46. SdoCollection serverGroups = cxn.getServerGroups();
  47. // Are there any server groups configured?
  48. if (serverGroups.count())
  49. {
  50. // Yes, so add them to the combo box.
  51. Sdo group;
  52. SdoEnum sdoEnum = serverGroups.getNewEnum();
  53. while (sdoEnum.next(group))
  54. {
  55. CComBSTR name;
  56. group.getName(name);
  57. int index = groupsCombo.AddString(name);
  58. // We'll also look for our provider. We can't use
  59. // CComboBox::FindStringExact because it's not case-sensitive.
  60. if (providerName && !wcscmp(name, providerName))
  61. {
  62. // Select it in the combo box.
  63. groupsCombo.SetCurSel(index);
  64. // Set the flag.
  65. groupExists = true;
  66. }
  67. }
  68. }
  69. if (providerName && !groupExists)
  70. {
  71. // The provider name is no longer a valid server group. We'll add it in
  72. // anyway, so we don't change the existing policy.
  73. invalidGroup = groupsCombo.AddString(providerName);
  74. groupsCombo.SetCurSel(invalidGroup);
  75. }
  76. // If there aren't groups, ...
  77. if (!groupsCombo.GetCount())
  78. {
  79. // ... add the <None configured> string, and ..
  80. groupsCombo.AddString(ResourceString(IDS_POLICY_NO_GROUPS));
  81. // ... don't let the user choose RADIUS.
  82. enableControl(IDC_RADIO_RADIUS, false);
  83. }
  84. // If the provider isn't RADIUS, disable the combo box.
  85. if (providerType != 2)
  86. {
  87. groupsCombo.EnableWindow(FALSE);
  88. }
  89. // Make sure something is selected.
  90. if (groupsCombo.GetCurSel() == CB_ERR)
  91. {
  92. groupsCombo.SetCurSel(0);
  93. }
  94. }
  95. ProfileAuthPage::ProfileAuthPage(SdoConnection& connection, SdoProfile& p)
  96. : ProfileProvPage(IDD_PROXY_PROFILE_AUTH, connection),
  97. profile(p)
  98. {
  99. profile.getValue(IAS_ATTRIBUTE_AUTH_PROVIDER_TYPE, providerType);
  100. profile.getValue(IAS_ATTRIBUTE_AUTH_PROVIDER_NAME, providerName);
  101. }
  102. void ProfileAuthPage::onProviderClick()
  103. {
  104. groupsCombo.EnableWindow(IsDlgButtonChecked(IDC_RADIO_RADIUS));
  105. SetModified();
  106. }
  107. void ProfileAuthPage::getData()
  108. {
  109. ProfileProvPage::getData();
  110. getRadio(IDC_RADIO_NONE, IDC_RADIO_RADIUS, providerType);
  111. }
  112. void ProfileAuthPage::setData()
  113. {
  114. ProfileProvPage::setData();
  115. setRadio(IDC_RADIO_NONE, IDC_RADIO_RADIUS, providerType);
  116. }
  117. void ProfileAuthPage::saveChanges()
  118. {
  119. profile.setValue(IAS_ATTRIBUTE_AUTH_PROVIDER_TYPE, providerType);
  120. if (providerName)
  121. {
  122. profile.setValue(IAS_ATTRIBUTE_AUTH_PROVIDER_NAME, providerName);
  123. }
  124. else
  125. {
  126. profile.clearValue(IAS_ATTRIBUTE_AUTH_PROVIDER_NAME);
  127. }
  128. }
  129. BEGIN_MESSAGE_MAP(ProfileAuthPage, SnapInPropertyPage)
  130. ON_BN_CLICKED(IDC_RADIO_NONE, onProviderClick)
  131. ON_BN_CLICKED(IDC_RADIO_WINDOWS, onProviderClick)
  132. ON_BN_CLICKED(IDC_RADIO_RADIUS, onProviderClick)
  133. ON_CBN_SELCHANGE(IDC_COMBO_GROUP, onChange)
  134. END_MESSAGE_MAP()
  135. ProfileAcctPage::ProfileAcctPage(SdoConnection& connection, SdoProfile& p)
  136. : ProfileProvPage(IDD_PROXY_PROFILE_ACCT, connection),
  137. profile(p)
  138. {
  139. profile.getValue(IAS_ATTRIBUTE_ACCT_PROVIDER_TYPE, providerType);
  140. record = (providerType == 2);
  141. profile.getValue(IAS_ATTRIBUTE_ACCT_PROVIDER_NAME, providerName);
  142. }
  143. void ProfileAcctPage::onCheckRecord()
  144. {
  145. groupsCombo.EnableWindow(IsDlgButtonChecked(IDC_CHECK_RECORD_ACCT));
  146. SetModified();
  147. }
  148. void ProfileAcctPage::getData()
  149. {
  150. ProfileProvPage::getData();
  151. getValue(IDC_CHECK_RECORD_ACCT, record);
  152. providerType = record ? 2 : 1;
  153. }
  154. void ProfileAcctPage::setData()
  155. {
  156. ProfileProvPage::setData();
  157. setValue(IDC_CHECK_RECORD_ACCT, record);
  158. }
  159. void ProfileAcctPage::saveChanges()
  160. {
  161. if (record)
  162. {
  163. profile.setValue(IAS_ATTRIBUTE_ACCT_PROVIDER_TYPE, 2L);
  164. profile.setValue(IAS_ATTRIBUTE_ACCT_PROVIDER_NAME, providerName);
  165. }
  166. else
  167. {
  168. profile.clearValue(IAS_ATTRIBUTE_ACCT_PROVIDER_TYPE);
  169. profile.clearValue(IAS_ATTRIBUTE_ACCT_PROVIDER_NAME);
  170. }
  171. }
  172. BEGIN_MESSAGE_MAP(ProfileAcctPage, SnapInPropertyPage)
  173. ON_BN_CLICKED(IDC_CHECK_RECORD_ACCT, onCheckRecord)
  174. ON_CBN_SELCHANGE(IDC_COMBO_GROUP, onChange)
  175. END_MESSAGE_MAP()
  176. ProfileAttrPage::ProfileAttrPage(SdoConnection& cxn, SdoProfile& p)
  177. : SnapInPropertyPage(IDD_PROXY_PROFILE_ATTR),
  178. profile(p),
  179. targetId(RADIUS_ATTRIBUTE_USER_NAME)
  180. {
  181. numTargets = cxn.getDictionary().enumAttributeValues(
  182. IAS_ATTRIBUTE_MANIPULATION_TARGET,
  183. targets
  184. );
  185. profile.getValue(IAS_ATTRIBUTE_MANIPULATION_TARGET, targetId);
  186. profile.getValue(IAS_ATTRIBUTE_MANIPULATION_RULE, rules);
  187. }
  188. ProfileAttrPage::~ProfileAttrPage() throw ()
  189. {
  190. delete[] targets;
  191. }
  192. BOOL ProfileAttrPage::OnInitDialog()
  193. {
  194. // Initialize the controls.
  195. initControl(IDC_COMBO_TARGET, ruleTarget);
  196. initControl(IDC_LIST_RULES, ruleList);
  197. /////////
  198. // Populate the target combo box.
  199. /////////
  200. for (ULONG i = 0; i < numTargets; ++i)
  201. {
  202. int index = ruleTarget.AddString(targets[i].name);
  203. ruleTarget.SetItemData(index, targets[i].id);
  204. }
  205. ruleTarget.SetCurSel(0);
  206. /////////
  207. // Set the column headers for the rules list.
  208. /////////
  209. RECT rect;
  210. ruleList.GetClientRect(&rect);
  211. LONG width = rect.right - rect.left;
  212. ResourceString findCol(IDS_RULE_COLUMN_FIND);
  213. ruleList.InsertColumn(0, findCol, LVCFMT_LEFT, (width + 1) / 2);
  214. ResourceString replaceCol(IDS_RULE_COLUMN_REPLACE);
  215. ruleList.InsertColumn(1, replaceCol, LVCFMT_LEFT, width / 2);
  216. ruleList.SetExtendedStyle(
  217. ruleList.GetExtendedStyle() | LVS_EX_FULLROWSELECT
  218. );
  219. return SnapInPropertyPage::OnInitDialog();
  220. }
  221. void ProfileAttrPage::onAdd()
  222. {
  223. RuleEditor editor;
  224. if (editor.DoModal() == IDOK)
  225. {
  226. int index = ruleList.InsertItem(
  227. ruleList.GetItemCount(),
  228. editor.getFindString()
  229. );
  230. ruleList.SetItemText(index, 1, editor.getReplaceString());
  231. SetModified();
  232. }
  233. onRuleChanged(NULL, NULL);
  234. }
  235. void ProfileAttrPage::onEdit()
  236. {
  237. int item = ruleList.GetNextItem(-1, LVNI_SELECTED);
  238. if (item != -1)
  239. {
  240. RuleEditor editor(
  241. ruleList.GetItemText(item, 0),
  242. ruleList.GetItemText(item, 1)
  243. );
  244. if (editor.DoModal() == IDOK)
  245. {
  246. ruleList.SetItemText(item, 0, editor.getFindString());
  247. ruleList.SetItemText(item, 1, editor.getReplaceString());
  248. SetModified();
  249. }
  250. }
  251. }
  252. void ProfileAttrPage::onRemove()
  253. {
  254. int item = ruleList.GetNextItem(-1, LVNI_SELECTED);
  255. if (item != -1)
  256. {
  257. ruleList.DeleteItem(item);
  258. SetModified();
  259. }
  260. }
  261. void ProfileAttrPage::onMoveUp()
  262. {
  263. int item = ruleList.GetNextItem(-1, LVNI_SELECTED);
  264. if (item > 0)
  265. {
  266. swapItems(item, item - 1);
  267. }
  268. }
  269. void ProfileAttrPage::onMoveDown()
  270. {
  271. int item = ruleList.GetNextItem(-1, LVNI_SELECTED);
  272. if (item >= 0 && item < ruleList.GetItemCount() - 1)
  273. {
  274. swapItems(item, item + 1);
  275. }
  276. }
  277. void ProfileAttrPage::onRuleActivate(NMITEMACTIVATE*, LRESULT*)
  278. {
  279. onEdit();
  280. }
  281. void ProfileAttrPage::onRuleChanged(NMLISTVIEW*, LRESULT*)
  282. {
  283. int item = ruleList.GetNextItem(-1, LVNI_SELECTED);
  284. enableControl(
  285. IDC_BUTTON_MOVE_UP,
  286. (item > 0)
  287. );
  288. enableControl(
  289. IDC_BUTTON_MOVE_DOWN,
  290. (item >= 0 && item < ruleList.GetItemCount() - 1)
  291. );
  292. enableControl(
  293. IDC_BUTTON_REMOVE,
  294. (item != -1)
  295. );
  296. enableControl(
  297. IDC_BUTTON_EDIT,
  298. (item != -1)
  299. );
  300. }
  301. void ProfileAttrPage::getData()
  302. {
  303. targetId = ruleTarget.GetItemData(ruleTarget.GetCurSel());
  304. rules.Clear();
  305. int nelem = ruleList.GetItemCount();
  306. if (nelem)
  307. {
  308. SAFEARRAYBOUND rgsabound = { 2 * nelem, 0 };
  309. V_VT(&rules) = VT_ARRAY | VT_VARIANT;
  310. V_ARRAY(&rules) = SafeArrayCreate(VT_VARIANT, 1, &rgsabound);
  311. if (!V_ARRAY(&rules)) { AfxThrowOleException(E_OUTOFMEMORY); }
  312. VARIANT* v = (VARIANT*)V_ARRAY(&rules)->pvData;
  313. for (int i = 0; i < nelem; i++)
  314. {
  315. V_VT(v) = VT_BSTR;
  316. V_BSTR(v) = SysAllocString(ruleList.GetItemText(i, 0));
  317. if (!V_BSTR(v)) { AfxThrowOleException(E_OUTOFMEMORY); }
  318. ++v;
  319. V_VT(v) = VT_BSTR;
  320. V_BSTR(v) = SysAllocString(ruleList.GetItemText(i, 1));
  321. if (!V_BSTR(v)) { AfxThrowOleException(E_OUTOFMEMORY); }
  322. ++v;
  323. }
  324. }
  325. }
  326. void ProfileAttrPage::setData()
  327. {
  328. for (ULONG i = 0; i < numTargets; ++i)
  329. {
  330. if (targets[i].id == targetId)
  331. {
  332. ruleTarget.SelectString(-1, targets[i].name);
  333. break;
  334. }
  335. }
  336. /////////
  337. // Populate the existing rules.
  338. /////////
  339. ruleList.DeleteAllItems();
  340. if (V_VT(&rules) != VT_EMPTY)
  341. {
  342. ULONG nelem = V_ARRAY(&rules)->rgsabound[0].cElements / 2;
  343. VARIANT* v = (VARIANT*)V_ARRAY(&rules)->pvData;
  344. ruleList.SetItemCount(nelem);
  345. // Initialize an LVITEM.
  346. LVITEM lvi;
  347. memset(&lvi, 0, sizeof(LVITEM));
  348. lvi.mask = LVIF_TEXT;
  349. for (ULONG i = 0; i < nelem; ++i)
  350. {
  351. lvi.iItem = i;
  352. lvi.iSubItem = 0;
  353. lvi.pszText = V_BSTR(&v[i * 2]);
  354. lvi.iItem = ruleList.InsertItem(&lvi);
  355. lvi.iSubItem = 1;
  356. lvi.pszText = V_BSTR(&v[i * 2 + 1]);
  357. ruleList.SetItem(&lvi);
  358. }
  359. }
  360. onRuleChanged(NULL, NULL);
  361. }
  362. void ProfileAttrPage::saveChanges()
  363. {
  364. if (V_VT(&rules) != VT_EMPTY)
  365. {
  366. profile.setValue(IAS_ATTRIBUTE_MANIPULATION_RULE, rules);
  367. profile.setValue(IAS_ATTRIBUTE_MANIPULATION_TARGET, targetId);
  368. }
  369. else
  370. {
  371. profile.clearValue(IAS_ATTRIBUTE_MANIPULATION_RULE);
  372. profile.clearValue(IAS_ATTRIBUTE_MANIPULATION_TARGET);
  373. }
  374. }
  375. BEGIN_MESSAGE_MAP(ProfileAttrPage, SnapInPropertyPage)
  376. ON_BN_CLICKED(IDC_BUTTON_ADD, onAdd)
  377. ON_BN_CLICKED(IDC_BUTTON_REMOVE, onRemove)
  378. ON_BN_CLICKED(IDC_BUTTON_EDIT, onEdit)
  379. ON_BN_CLICKED(IDC_BUTTON_MOVE_UP, onMoveUp)
  380. ON_BN_CLICKED(IDC_BUTTON_MOVE_DOWN, onMoveDown)
  381. ON_NOTIFY(LVN_ITEMACTIVATE, IDC_LIST_RULES, onRuleActivate)
  382. ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_RULES, onRuleChanged)
  383. ON_CBN_SELCHANGE(IDC_COMBO_TARGET, onChange)
  384. END_MESSAGE_MAP()
  385. void ProfileAttrPage::swapItems(int item1, int item2)
  386. {
  387. ::CString find = ruleList.GetItemText(item1, 0);
  388. ::CString replace = ruleList.GetItemText(item1, 1);
  389. ruleList.SetItemText(item1, 0, ruleList.GetItemText(item2, 0));
  390. ruleList.SetItemText(item1, 1, ruleList.GetItemText(item2, 1));
  391. ruleList.SetItemText(item2, 0, find);
  392. ruleList.SetItemText(item2, 1, replace);
  393. ruleList.SetItemState(item2, LVIS_SELECTED, LVIS_SELECTED);
  394. SetModified();
  395. }
  396. /////////
  397. // Various definitions for the advanced page API exported from rasuser.dll
  398. /////////
  399. const WCHAR RASUSER_DLL[] = L"rasuser.dll";
  400. const CHAR CREATE_PROC[] = "IASCreateProfileAdvancedPage";
  401. const CHAR DELETE_PROC[] = "IASDeleteProfileAdvancedPage";
  402. typedef HPROPSHEETPAGE (WINAPI *IASCreateProfileAdvancedPage_t)(
  403. ISdo* pProfile,
  404. ISdoDictionaryOld* pDictionary,
  405. LONG lFilter,
  406. void* pvData
  407. );
  408. typedef BOOL (WINAPI *IASDeleteProfileAdvancedPage_t)(
  409. HPROPSHEETPAGE hPage
  410. );
  411. ProxyProfileProperties::ProxyProfileProperties(
  412. Sdo& profileSdo,
  413. SdoConnection& connection
  414. )
  415. : CPropertySheet(IDS_PROFILE_CAPTION),
  416. profile(connection, profileSdo),
  417. profileStream(profile),
  418. auth(connection, profile),
  419. acct(connection, profile),
  420. attr(connection, profile),
  421. rasuser(NULL),
  422. advanced(NULL),
  423. applied(false),
  424. modified(false)
  425. {
  426. AddPage(&auth);
  427. AddPage(&acct);
  428. AddPage(&attr);
  429. // Load the DLL with the advanced page.
  430. rasuser = LoadLibraryW(RASUSER_DLL);
  431. if (!rasuser) { AfxThrowLastError(); }
  432. // Look up the create proc.
  433. IASCreateProfileAdvancedPage_t IASCreateProfileAdvancedPage =
  434. (IASCreateProfileAdvancedPage_t)GetProcAddress(rasuser, CREATE_PROC);
  435. if (!IASCreateProfileAdvancedPage) { AfxThrowLastError(); }
  436. // Create the property page.
  437. advanced = IASCreateProfileAdvancedPage(
  438. profileSdo,
  439. connection.getDictionary(),
  440. ALLOWEDINPROXYPROFILE,
  441. ExtractCIASAttrList(connection.getCIASAttrList())
  442. );
  443. if (!advanced) { AfxThrowLastError(); }
  444. }
  445. ProxyProfileProperties::~ProxyProfileProperties() throw ()
  446. {
  447. if (rasuser)
  448. {
  449. // Look up the delete proc.
  450. IASDeleteProfileAdvancedPage_t IASDeleteProfileAdvancedPage =
  451. (IASDeleteProfileAdvancedPage_t)GetProcAddress(rasuser, DELETE_PROC);
  452. if (IASDeleteProfileAdvancedPage)
  453. {
  454. // Delete the property page.
  455. IASDeleteProfileAdvancedPage(advanced);
  456. }
  457. // Free the DLL.
  458. FreeLibrary(rasuser);
  459. }
  460. }
  461. BOOL ProxyProfileProperties::OnInitDialog()
  462. {
  463. // Unmarshal the profile.
  464. profileStream.get(profile);
  465. // We use PostMessage since we can't add the page while handling WM_INIT.
  466. PostMessage(PSM_ADDPAGE, 0, (LPARAM)advanced);
  467. BOOL bResult = CPropertySheet::OnInitDialog();
  468. ModifyStyleEx(0, WS_EX_CONTEXTHELP);
  469. return bResult;
  470. }
  471. INT_PTR ProxyProfileProperties::DoModal()
  472. {
  473. CPropertySheet::DoModal();
  474. return applied ? IDOK : IDCANCEL;
  475. }
  476. LRESULT ProxyProfileProperties::onChanged(WPARAM wParam, LPARAM lParam)
  477. {
  478. // One of our pages sent the PSM_CHANGED message.
  479. modified = true;
  480. // Forward to the PropertySheet.
  481. return Default();
  482. }
  483. void ProxyProfileProperties::onOkOrApply()
  484. {
  485. // The user clicked OK or Apply.
  486. if (modified)
  487. {
  488. // The modified pages have now been written.
  489. applied = true;
  490. modified = false;
  491. }
  492. Default();
  493. }
  494. BEGIN_MESSAGE_MAP(ProxyProfileProperties, CPropertySheet)
  495. ON_BN_CLICKED(IDOK, onOkOrApply)
  496. ON_BN_CLICKED(ID_APPLY_NOW, onOkOrApply)
  497. ON_MESSAGE(PSM_CHANGED, onChanged)
  498. END_MESSAGE_MAP()
  499. RuleEditor::RuleEditor(PCWSTR szFind, PCWSTR szReplace)
  500. : CHelpDialog(IDD_EDIT_RULE),
  501. find(szFind),
  502. replace(szReplace)
  503. { }
  504. void RuleEditor::DoDataExchange(CDataExchange* pDX)
  505. {
  506. DDX_Text(pDX, IDC_EDIT_RULE_FIND, find);
  507. if (pDX->m_bSaveAndValidate && find.IsEmpty())
  508. {
  509. MessageBox(
  510. ResourceString(IDS_POLICY_E_FIND_EMPTY),
  511. ResourceString(IDS_POLICY_E_CAPTION),
  512. MB_ICONWARNING
  513. );
  514. pDX->Fail();
  515. }
  516. DDX_Text(pDX, IDC_EDIT_RULE_REPLACE, replace);
  517. }