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.

619 lines
16 KiB

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