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.

445 lines
11 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: proppage.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "resource.h"
  12. #include "proppage.h"
  13. #include "domobj.h"
  14. #include "cdomain.h"
  15. #include "helparr.h"
  16. ////////////////////////////////////////////////////////////////////////////////
  17. // CUpnSuffixPropertyPage
  18. // hook the property sheet callback to allow
  19. // C++ object destruction
  20. // static callback override function
  21. UINT CALLBACK CUpnSuffixPropertyPage::PropSheetPageProc(
  22. HWND hwnd,
  23. UINT uMsg,
  24. LPPROPSHEETPAGE ppsp)
  25. {
  26. CUpnSuffixPropertyPage* pPage = (CUpnSuffixPropertyPage*)(ppsp->lParam);
  27. ASSERT(pPage != NULL);
  28. UINT nResult = (*(pPage->m_pfnOldPropCallback))(hwnd, uMsg, ppsp);
  29. if (uMsg == PSPCB_RELEASE)
  30. {
  31. delete pPage;
  32. }
  33. return nResult;
  34. }
  35. BEGIN_MESSAGE_MAP(CUpnSuffixPropertyPage, CPropertyPage)
  36. ON_BN_CLICKED(IDC_ADD_BTN, OnAddButton)
  37. ON_BN_CLICKED(IDC_DELETE_BTN, OnDeleteButton)
  38. ON_EN_CHANGE(IDC_EDIT, OnEditChange)
  39. ON_WM_HELPINFO()
  40. END_MESSAGE_MAP()
  41. CUpnSuffixPropertyPage::CUpnSuffixPropertyPage() :
  42. CPropertyPage(IDD_UPN_SUFFIX),
  43. m_nPreviousDefaultButtonID(0)
  44. {
  45. m_pfnOldPropCallback = m_psp.pfnCallback;
  46. m_psp.pfnCallback = PropSheetPageProc;
  47. m_bDirty = FALSE;
  48. m_pIADsPartitionsCont = NULL;
  49. }
  50. CUpnSuffixPropertyPage::~CUpnSuffixPropertyPage()
  51. {
  52. if (m_pIADsPartitionsCont != NULL)
  53. {
  54. m_pIADsPartitionsCont->Release();
  55. m_pIADsPartitionsCont = NULL;
  56. }
  57. }
  58. BOOL CUpnSuffixPropertyPage::OnInitDialog()
  59. {
  60. CPropertyPage::OnInitDialog();
  61. VERIFY(m_listBox.SubclassDlgItem(IDC_LIST, this));
  62. ((CEdit*)GetDlgItem(IDC_EDIT))->SetLimitText(MAX_UPN_SUFFIX_LEN);
  63. HRESULT hr = _GetPartitionsContainer();
  64. if (SUCCEEDED(hr))
  65. {
  66. _Read();
  67. GetDlgItem(IDC_ADD_BTN)->EnableWindow(FALSE);
  68. }
  69. else
  70. {
  71. // failed to contact DC, disable the whole UI
  72. GetDlgItem(IDC_ADD_BTN)->EnableWindow(FALSE);
  73. GetDlgItem(IDC_DELETE_BTN)->EnableWindow(FALSE);
  74. GetDlgItem(IDC_LIST)->EnableWindow(FALSE);
  75. GetDlgItem(IDC_EDIT)->EnableWindow(FALSE);
  76. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  77. ReportError(::GetParent(m_hWnd), IDS_CANT_GET_PARTITIONS_INFORMATION, hr);
  78. }
  79. LRESULT lDefID = ::SendMessage(GetParent()->GetSafeHwnd(), DM_GETDEFID, 0, 0);
  80. if (lDefID != 0)
  81. {
  82. m_nPreviousDefaultButtonID = LOWORD(lDefID);
  83. }
  84. _SetDirty(FALSE);
  85. return TRUE;
  86. }
  87. BOOL CUpnSuffixPropertyPage::OnApply()
  88. {
  89. if (!_IsDirty())
  90. return TRUE;
  91. HRESULT hr = _Write();
  92. if (SUCCEEDED(hr))
  93. {
  94. _SetDirty(FALSE);
  95. return TRUE;
  96. }
  97. ReportError(::GetParent(m_hWnd),IDS_ERROR_WRITE_UPN_SUFFIXES, hr);
  98. return FALSE;
  99. }
  100. void CUpnSuffixPropertyPage::OnEditChange()
  101. {
  102. GetDlgItemText(IDC_EDIT, m_szEditText);
  103. m_szEditText.TrimRight();
  104. m_szEditText.TrimLeft();
  105. BOOL bEnable = !m_szEditText.IsEmpty();
  106. CWnd* pWndFocus = CWnd::GetFocus();
  107. CWnd* pAddBtnWnd = GetDlgItem(IDC_ADD_BTN);
  108. if (!bEnable && (pAddBtnWnd == pWndFocus) )
  109. {
  110. GetDlgItem(IDC_EDIT)->SetFocus();
  111. }
  112. GetDlgItem(IDC_ADD_BTN)->EnableWindow(bEnable);
  113. if (bEnable)
  114. {
  115. //
  116. // Set the add button as the default button
  117. //
  118. ::SendMessage(GetParent()->GetSafeHwnd(), DM_SETDEFID, (WPARAM)IDC_ADD_BTN, 0);
  119. //
  120. // Force the Add button to redraw itself
  121. //
  122. ::SendDlgItemMessage(GetSafeHwnd(),
  123. IDC_ADD_BTN,
  124. BM_SETSTYLE,
  125. BS_DEFPUSHBUTTON,
  126. MAKELPARAM(TRUE, 0));
  127. //
  128. // Force the previous default button to redraw itself
  129. //
  130. ::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
  131. m_nPreviousDefaultButtonID,
  132. BM_SETSTYLE,
  133. BS_PUSHBUTTON,
  134. MAKELPARAM(TRUE, 0));
  135. }
  136. else
  137. {
  138. //
  139. // Set the previous button as the default button
  140. //
  141. ::SendMessage(GetParent()->GetSafeHwnd(), DM_SETDEFID, (WPARAM)m_nPreviousDefaultButtonID, 0);
  142. //
  143. // Force the previous default button to redraw itself
  144. //
  145. ::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
  146. m_nPreviousDefaultButtonID,
  147. BM_SETSTYLE,
  148. BS_DEFPUSHBUTTON,
  149. MAKELPARAM(TRUE, 0));
  150. //
  151. // Force the Add button to redraw itself
  152. //
  153. ::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
  154. IDC_ADD_BTN,
  155. BM_SETSTYLE,
  156. BS_PUSHBUTTON,
  157. MAKELPARAM(TRUE, 0));
  158. }
  159. }
  160. void CUpnSuffixPropertyPage::OnAddButton()
  161. {
  162. // cannot add duplicated items
  163. int nCount = m_listBox.GetCount();
  164. CString szItem;
  165. for (int i=0; i<nCount; i++)
  166. {
  167. m_listBox.GetItem(i, szItem);
  168. if (_wcsicmp((LPCWSTR)szItem, (LPCWSTR)m_szEditText) == 0)
  169. {
  170. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  171. AfxMessageBox(IDS_ERROR_ADD_UPN_NO_DUPLICATE, MB_OK|MB_ICONINFORMATION);
  172. return;
  173. }
  174. }
  175. m_listBox.AddItem(m_szEditText);
  176. m_listBox.UpdateHorizontalExtent();
  177. SetDlgItemText(IDC_EDIT, NULL);
  178. if (1 == m_listBox.GetCount())
  179. {
  180. // we did not have any item in the list
  181. // need to set the selection on the first one
  182. VERIFY(m_listBox.SetSelection(0));
  183. // need to enable buttons
  184. GetDlgItem(IDC_DELETE_BTN)->EnableWindow(TRUE);
  185. }
  186. _SetDirty(TRUE);
  187. }
  188. void CUpnSuffixPropertyPage::OnDeleteButton()
  189. {
  190. int nCount = m_listBox.GetCount();
  191. int nSel = m_listBox.GetSelection();
  192. ASSERT(nCount > 0);
  193. ASSERT((nSel >= 0) && (nSel < nCount));
  194. // ask the user for confirmation
  195. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  196. if (IDNO == AfxMessageBox(IDS_WARNING_DELETE_UPN_SUFFIX, MB_YESNO|MB_ICONQUESTION))
  197. return;
  198. // save the value and put it back in the edit control
  199. CString szText;
  200. m_listBox.GetItem(nSel, szText);
  201. GetDlgItem(IDC_EDIT)->SetWindowText(szText);
  202. // delete the item in the list
  203. VERIFY(m_listBox.DeleteItem(nSel));
  204. m_listBox.UpdateHorizontalExtent();
  205. // handle UI changes
  206. if (nCount == 1)
  207. {
  208. // removed the last one, lost the selection
  209. CWnd* pWndFocus = CWnd::GetFocus();
  210. CWnd* pDelBtnWnd = GetDlgItem(IDC_DELETE_BTN);
  211. if (pDelBtnWnd == pWndFocus)
  212. {
  213. GetDlgItem(IDC_EDIT)->SetFocus();
  214. }
  215. GetDlgItem(IDC_DELETE_BTN)->EnableWindow(FALSE);
  216. }
  217. else
  218. {
  219. // need to select again: is it the last one or not
  220. int nNewSel = (nSel == nCount-1) ? nSel-1 : nSel;
  221. VERIFY(m_listBox.SetSelection(nNewSel));
  222. ASSERT(m_listBox.GetSelection() == nNewSel);
  223. }
  224. _SetDirty(TRUE);
  225. }
  226. BOOL CUpnSuffixPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
  227. {
  228. DialogContextHelp((DWORD*)&g_aHelpIDs_IDD_UPN_SUFFIX, pHelpInfo);
  229. return TRUE;
  230. }
  231. //////////////////////////////////////////////////////////
  232. // CUpnSuffixPropertyPage internal implementation methods
  233. LPWSTR g_lpszRootDSE = L"LDAP://RootDSE";
  234. LPWSTR g_lpszConfigurationNamingContext = L"configurationNamingContext";
  235. LPWSTR g_lpszPartitionsFormat = L"LDAP://CN=Partitions,%s";
  236. LPWSTR g_lpszPartitionsFormatWithServer = L"LDAP://%s/CN=Partitions,%s";
  237. LPWSTR g_lpszUpnSuffixes = L"uPNSuffixes";
  238. HRESULT CUpnSuffixPropertyPage::_GetPartitionsContainer()
  239. {
  240. if (m_pIADsPartitionsCont != NULL)
  241. {
  242. m_pIADsPartitionsCont->Release();
  243. m_pIADsPartitionsCont = NULL;
  244. }
  245. // get the root of the enterprise
  246. IADs* pADs;
  247. HRESULT hr = ::ADsGetObject(g_lpszRootDSE,
  248. IID_IADs, (void **)&pADs);
  249. if (!(SUCCEEDED(hr)))
  250. {
  251. return hr;
  252. }
  253. //
  254. // Get the server name so we can bind with ADS_SERVER_BIND
  255. //
  256. CString szServerName;
  257. hr = GetADSIServerName(szServerName, pADs);
  258. if (FAILED(hr))
  259. {
  260. szServerName.Empty();
  261. }
  262. // get the configuration naming context container
  263. VARIANT configVar;
  264. ::VariantInit(&configVar);
  265. hr = pADs->Get(g_lpszConfigurationNamingContext,
  266. &configVar);
  267. if (SUCCEEDED(hr))
  268. {
  269. // get the partitions container
  270. DWORD dwFlags = ADS_SECURE_AUTHENTICATION;
  271. CString szPartitionsPath;
  272. if (szServerName.IsEmpty())
  273. {
  274. szPartitionsPath.Format(g_lpszPartitionsFormat, configVar.bstrVal);
  275. }
  276. else
  277. {
  278. szPartitionsPath.Format(g_lpszPartitionsFormatWithServer, szServerName, configVar.bstrVal);
  279. dwFlags |= ADS_SERVER_BIND;
  280. }
  281. IADsContainer* pIADsContainer;
  282. hr = ::ADsOpenObject((LPWSTR)(LPCWSTR)szPartitionsPath,
  283. NULL, // username
  284. NULL, // password
  285. dwFlags,
  286. IID_IDirectoryObject,
  287. (void **)&m_pIADsPartitionsCont);
  288. if (hr == E_INVALIDARG &&
  289. (dwFlags & ADS_SERVER_BIND))
  290. {
  291. //
  292. // Trying again without the ADS_SERVER_BIND flag
  293. //
  294. dwFlags &= ~ADS_SERVER_BIND;
  295. hr = ::ADsOpenObject((LPWSTR)(LPCWSTR)szPartitionsPath,
  296. NULL, // username
  297. NULL, // password
  298. dwFlags,
  299. IID_IDirectoryObject,
  300. (void **)&m_pIADsPartitionsCont);
  301. }
  302. }
  303. ::VariantClear(&configVar);
  304. pADs->Release();
  305. return hr;
  306. }
  307. void CUpnSuffixPropertyPage::_Read()
  308. {
  309. ASSERT(m_pIADsPartitionsCont != NULL);
  310. PADS_ATTR_INFO pAttrs = NULL;
  311. LPWSTR lpszArr[1];
  312. DWORD cAttrs;
  313. BOOL bHaveItems = FALSE;
  314. HRESULT hr = m_pIADsPartitionsCont->GetObjectAttributes(
  315. &g_lpszUpnSuffixes, 1, &pAttrs, &cAttrs);
  316. if (SUCCEEDED(hr) && (pAttrs != NULL) && (cAttrs == 1) )
  317. {
  318. ASSERT(pAttrs->dwADsType == ADSTYPE_CASE_IGNORE_STRING);
  319. ASSERT(cAttrs == 1);
  320. for (DWORD i=0; i<pAttrs->dwNumValues; i++)
  321. {
  322. m_listBox.AddItem(pAttrs->pADsValues[i].CaseIgnoreString);
  323. //TRACE(_T("i=%d, %s\n"), i, pAttrs->pADsValues[i].CaseIgnoreString);
  324. }
  325. bHaveItems = pAttrs->dwNumValues > 0;
  326. }
  327. if (bHaveItems)
  328. {
  329. m_listBox.UpdateHorizontalExtent();
  330. VERIFY(m_listBox.SetSelection(0));
  331. }
  332. GetDlgItem(IDC_DELETE_BTN)->EnableWindow(bHaveItems);
  333. if (pAttrs != NULL)
  334. {
  335. ::FreeADsMem(pAttrs);
  336. }
  337. }
  338. HRESULT CUpnSuffixPropertyPage::_Write()
  339. {
  340. ASSERT(m_pIADsPartitionsCont != NULL);
  341. DWORD cModified;
  342. CString* pStringArr = NULL;
  343. ADSVALUE* pValues = NULL;
  344. // set the update struct
  345. ADS_ATTR_INFO info;
  346. info.pszAttrName = g_lpszUpnSuffixes;
  347. info.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  348. info.dwControlCode = ADS_ATTR_CLEAR;
  349. info.pADsValues = NULL;
  350. info.dwNumValues = 0;
  351. int nCount = m_listBox.GetCount();
  352. if (nCount > 0)
  353. {
  354. info.dwControlCode = ADS_ATTR_UPDATE;
  355. info.dwNumValues = (DWORD)nCount;
  356. pStringArr = new CString[nCount];
  357. ADSVALUE* pValues = new ADSVALUE[nCount];
  358. info.pADsValues = pValues;
  359. for (int i=0; i<nCount; i++)
  360. {
  361. m_listBox.GetItem(i,pStringArr[i]);
  362. pValues[i].dwType = ADSTYPE_CASE_IGNORE_STRING;
  363. pValues[i].CaseIgnoreString = (LPWSTR)(LPCWSTR)pStringArr[i];
  364. }
  365. }
  366. HRESULT hr = m_pIADsPartitionsCont->SetObjectAttributes(
  367. &info, 1, &cModified);
  368. if (pStringArr != NULL)
  369. delete[] pStringArr;
  370. if (pValues != NULL)
  371. delete[] pValues;
  372. return hr;
  373. }