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.

1266 lines
37 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: newuser.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. ////////////////////////////////////////////////////////////////////////////////////
  11. // newuser.cpp
  12. #include "stdafx.h"
  13. #include "dsutil.h"
  14. #include "newobj.h" // CNewADsObjectCreateInfo
  15. #include "dlgcreat.h"
  16. #include "querysup.h"
  17. #include <windowsx.h>
  18. #include <lmaccess.h>
  19. ///////////////////////////////////////////////////////////////
  20. ///////////////////////////////////////////////////////////////
  21. // NEW USER WIZARD
  22. ///////////////////////////////////////////////////////////////
  23. // CCreateNewUserPage1
  24. BEGIN_MESSAGE_MAP(CCreateNewUserPage1, CCreateNewObjectDataPage)
  25. ON_EN_CHANGE(IDC_EDIT_FIRST_NAME, OnNameChange)
  26. ON_EN_CHANGE(IDC_EDIT_INITIALS, OnNameChange)
  27. ON_EN_CHANGE(IDC_EDIT_LAST_NAME, OnNameChange)
  28. ON_EN_CHANGE(IDC_NT5_USER_EDIT, OnLoginNameChange)
  29. ON_EN_CHANGE(IDC_NT4_USER_EDIT, OnSAMNameChange)
  30. ON_EN_CHANGE(IDC_EDIT_FULL_NAME, OnFullNameChange)
  31. END_MESSAGE_MAP()
  32. CCreateNewUserPage1::CCreateNewUserPage1() :
  33. CCreateNewObjectDataPage(CCreateNewUserPage1::IDD)
  34. {
  35. m_bForcingNameChange = FALSE;
  36. }
  37. BOOL CCreateNewUserPage1::OnInitDialog()
  38. {
  39. CCreateNewObjectDataPage::OnInitDialog();
  40. VERIFY(_InitUI());
  41. return TRUE;
  42. }
  43. void CCreateNewUserPage1::GetSummaryInfo(CString& s)
  44. {
  45. // get the UPN name
  46. CString strDomain;
  47. GetDlgItemText (IDC_NT5_DOMAIN_COMBO, OUT strDomain);
  48. CString strUPN = m_strLoginName + strDomain;
  49. // format the line
  50. CString szFmt;
  51. szFmt.LoadString(IDS_s_CREATE_NEW_SUMMARY_USER_UPN);
  52. CString szBuffer;
  53. szBuffer.Format((LPCWSTR)szFmt, (LPCWSTR)strUPN);
  54. s += szBuffer;
  55. }
  56. HRESULT CCreateNewUserPage1::SetData(BOOL bSilent)
  57. {
  58. //
  59. // start with a new temporary object
  60. //
  61. HRESULT hr;
  62. CString strDomain;
  63. GetDlgItemText (IDC_EDIT_FULL_NAME, OUT m_strFullName);
  64. GetDlgItemText (IDC_NT5_DOMAIN_COMBO, OUT strDomain);
  65. m_strLoginName.TrimRight();
  66. m_strLoginName.TrimLeft();
  67. //
  68. // First check for illegal characters
  69. //
  70. int iFind = m_strLoginName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS);
  71. if (iFind != -1 && !m_strLoginName.IsEmpty())
  72. {
  73. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strLoginName};
  74. if (!bSilent && IDYES == ReportErrorEx (::GetParent(m_hWnd),IDS_LOGINNAME_ILLEGAL,S_OK,
  75. MB_YESNO | MB_ICONWARNING, apv, 1))
  76. {
  77. while (iFind != -1)
  78. {
  79. m_strLoginName.SetAt(iFind, L'_');
  80. iFind = m_strLoginName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS);
  81. }
  82. m_bForcingNameChange = TRUE;
  83. SetDlgItemText(IDC_NT5_USER_EDIT, m_strLoginName);
  84. m_bForcingNameChange = FALSE;
  85. }
  86. else
  87. {
  88. //
  89. // Set the focus to the edit box and select the text
  90. //
  91. GetDlgItem(IDC_NT5_USER_EDIT)->SetFocus();
  92. SendDlgItemMessage(IDC_NT5_USER_EDIT, EM_SETSEL, 0 , -1);
  93. return E_INVALIDARG;
  94. }
  95. }
  96. CString strUPN = m_strLoginName + strDomain;
  97. CString strDomainDNS = strDomain;
  98. CString strFilter;
  99. //
  100. // Store the object name in the temporary storage
  101. //
  102. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  103. //
  104. // create a new temporary ADs object
  105. //
  106. hr = pNewADsObjectCreateInfo->HrCreateNew(m_strFullName);
  107. if (FAILED(hr))
  108. {
  109. return hr;
  110. }
  111. BOOL fDomainSearchFailed = FALSE;
  112. BOOL fGCSearchFailed = FALSE;
  113. //
  114. // now validate UPN with current domain before doing the put.
  115. //
  116. CDSSearch DSS;
  117. IDirectorySearch *pGCObj = NULL;
  118. //
  119. // validate UPN with GC before doing the put.
  120. //
  121. CString strDomainName = m_LocalDomain.Right (m_LocalDomain.GetLength() - 1);
  122. hr = DSPROP_GetGCSearchOnDomain((LPWSTR)(LPCWSTR)strDomainName,
  123. IID_IDirectorySearch, (void **)&pGCObj);
  124. if (SUCCEEDED(hr))
  125. {
  126. hr = DSS.Init (pGCObj);
  127. if (SUCCEEDED(hr))
  128. {
  129. //
  130. // NTRAID#NTBUG9-257580-2000/12/14-jeffjon,
  131. // We must get an escaped filter because the UPN may contain "special" characters
  132. //
  133. CString szEscapedUPN;
  134. EscapeFilterElement(strUPN, szEscapedUPN);
  135. LPWSTR pAttributes[1] = {L"cn"};
  136. strFilter = L"(userPrincipalName=";
  137. strFilter += szEscapedUPN;
  138. strFilter += L")";
  139. TRACE(_T("searching global catalog for %s...\n"), strUPN);
  140. DSS.SetFilterString ((LPWSTR)(LPCWSTR)strFilter);
  141. DSS.SetAttributeList (pAttributes, 1);
  142. DSS.SetSearchScope (ADS_SCOPE_SUBTREE);
  143. DSS.DoQuery();
  144. hr = DSS.GetNextRow();
  145. TRACE(_T("done searching global catalog for %s...\n"), strUPN);
  146. }
  147. }
  148. if (hr == S_OK) // this means a row was returned, so we're dup
  149. {
  150. if (!bSilent)
  151. {
  152. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strLoginName};
  153. ReportErrorEx (::GetParent(m_hWnd),IDS_UPN_DUP,hr,
  154. MB_OK | MB_ICONWARNING, apv, 1);
  155. }
  156. return E_INVALIDARG;
  157. }
  158. if (hr != S_ADS_NOMORE_ROWS) // oops, had another problem
  159. {
  160. fGCSearchFailed = TRUE;
  161. }
  162. CString strInitPath = L"LDAP://";
  163. strInitPath += m_LocalDomain.Right (m_LocalDomain.GetLength() - 1);
  164. TRACE(_T("Initialize Domain search object with: %s...\n"), strInitPath);
  165. HRESULT hr2 = DSS.Init (strInitPath);
  166. if (SUCCEEDED(hr2))
  167. {
  168. CString szEscapedUPN;
  169. EscapeFilterElement(strUPN, szEscapedUPN);
  170. LPWSTR pAttributes2[1] = {L"cn"};
  171. strFilter = L"(userPrincipalName=";
  172. strFilter += szEscapedUPN;
  173. strFilter += L")";
  174. TRACE(_T("searching current domain for %s...\n"), strUPN);
  175. DSS.SetAttributeList (pAttributes2, 1);
  176. DSS.SetFilterString ((LPWSTR)(LPCWSTR)strFilter);
  177. DSS.SetSearchScope (ADS_SCOPE_SUBTREE);
  178. DSS.DoQuery();
  179. hr2 = DSS.GetNextRow();
  180. TRACE(_T("done searching current domain for %s...\n"), strUPN);
  181. }
  182. if (hr2 == S_OK) // this means a row was returned, so we're dup
  183. {
  184. if (!bSilent)
  185. {
  186. ReportErrorEx (::GetParent(m_hWnd),IDS_UPN_DUP,hr2,
  187. MB_OK | MB_ICONWARNING, NULL, 0);
  188. }
  189. return E_INVALIDARG;
  190. }
  191. if (hr2 != S_ADS_NOMORE_ROWS) // oops, had another problem
  192. {
  193. fDomainSearchFailed = TRUE;
  194. }
  195. if (fDomainSearchFailed || fGCSearchFailed)
  196. {
  197. HRESULT hrSearch = S_OK;
  198. if (fDomainSearchFailed)
  199. {
  200. hrSearch = hr2;
  201. }
  202. else
  203. {
  204. hrSearch = hr;
  205. }
  206. if (!bSilent)
  207. {
  208. ReportErrorEx (::GetParent(m_hWnd),IDS_UPN_SEARCH_FAILED,hrSearch,
  209. MB_OK | MB_ICONWARNING, NULL, 0);
  210. }
  211. }
  212. if (pGCObj)
  213. {
  214. pGCObj->Release();
  215. pGCObj = NULL;
  216. }
  217. GetDlgItemText (IDC_NT4_USER_EDIT, OUT m_strSAMName);
  218. m_strSAMName.TrimLeft();
  219. m_strSAMName.TrimRight();
  220. //
  221. // First check for illegal characters
  222. //
  223. iFind = m_strSAMName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS_WITH_AT);
  224. if (iFind != -1 && !m_strSAMName.IsEmpty())
  225. {
  226. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSAMName};
  227. if (!bSilent && IDYES == ReportErrorEx (::GetParent(m_hWnd),IDS_SAMNAME_ILLEGAL,S_OK,
  228. MB_YESNO | MB_ICONWARNING, apv, 1))
  229. {
  230. while (iFind != -1)
  231. {
  232. m_strSAMName.SetAt(iFind, L'_');
  233. iFind = m_strSAMName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS_WITH_AT);
  234. }
  235. m_bForcingNameChange = TRUE;
  236. SetDlgItemText(IDC_NT4_USER_EDIT, m_strSAMName);
  237. m_bForcingNameChange = FALSE;
  238. }
  239. else
  240. {
  241. //
  242. // Set the focus to the edit box and select the text
  243. //
  244. GetDlgItem(IDC_NT4_USER_EDIT)->SetFocus();
  245. SendDlgItemMessage(IDC_NT4_USER_EDIT, EM_SETSEL, 0 , -1);
  246. return E_INVALIDARG;
  247. }
  248. }
  249. //
  250. // validate samAccountName with domain before doing the put.
  251. // There is no reason to verify the uniqueness against the GC
  252. // since sAMAccountName only has to be unique within the domain
  253. //
  254. CDSSearch DSSSAM;
  255. if (!fDomainSearchFailed && !fGCSearchFailed)
  256. {
  257. fDomainSearchFailed = FALSE;
  258. fGCSearchFailed = FALSE;
  259. hr2 = DSSSAM.Init (strInitPath);
  260. if (SUCCEEDED(hr2))
  261. {
  262. CString szEscapedSAMName;
  263. EscapeFilterElement(m_strSAMName, szEscapedSAMName);
  264. LPWSTR pAttributes2[1] = {L"cn"};
  265. strFilter = L"(samAccountName=";
  266. strFilter += szEscapedSAMName;
  267. strFilter += L")";
  268. TRACE(_T("searching current domain for %s...\n"), strUPN);
  269. DSSSAM.SetAttributeList (pAttributes2, 1);
  270. DSSSAM.SetFilterString ((LPWSTR)(LPCWSTR)strFilter);
  271. DSSSAM.SetSearchScope (ADS_SCOPE_SUBTREE);
  272. DSSSAM.DoQuery();
  273. hr2 = DSSSAM.GetNextRow();
  274. TRACE(_T("done searching current domain for %s...\n"), strUPN);
  275. }
  276. if (hr2 == S_OK) // this means a row was returned, so we're dup
  277. {
  278. if (!bSilent)
  279. {
  280. ReportErrorEx (::GetParent(m_hWnd),IDS_SAMNAME_DUP,hr2,
  281. MB_OK | MB_ICONWARNING, NULL, 0);
  282. }
  283. return E_INVALIDARG;
  284. }
  285. if (hr2 != S_ADS_NOMORE_ROWS) // oops, had another problem
  286. {
  287. fDomainSearchFailed = TRUE;
  288. }
  289. if (fDomainSearchFailed)
  290. {
  291. HRESULT hrSearch = S_OK;
  292. if (fDomainSearchFailed)
  293. {
  294. hrSearch = hr2;
  295. }
  296. else
  297. {
  298. hrSearch = hr;
  299. }
  300. if (!bSilent)
  301. {
  302. ReportErrorEx (::GetParent(m_hWnd),IDS_UPN_SEARCH_FAILED,hrSearch,
  303. MB_OK | MB_ICONWARNING, NULL, 0);
  304. }
  305. }
  306. }
  307. if (pGCObj)
  308. {
  309. pGCObj->Release();
  310. }
  311. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(const_cast<PWSTR>(gsz_samAccountName), m_strSAMName);
  312. ASSERT(SUCCEEDED(hr));
  313. strUPN.TrimRight();
  314. strUPN.TrimLeft();
  315. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(L"userPrincipalName", strUPN);
  316. ASSERT(SUCCEEDED(hr));
  317. m_strFullName.TrimLeft();
  318. m_strFullName.TrimRight();
  319. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(L"displayName", m_strFullName);
  320. ASSERT(SUCCEEDED(hr));
  321. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(L"givenName", m_strFirstName);
  322. ASSERT(SUCCEEDED(hr));
  323. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(L"initials", m_strInitials);
  324. ASSERT(SUCCEEDED(hr));
  325. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(L"sn", m_strLastName);
  326. ASSERT(SUCCEEDED(hr));
  327. return hr;
  328. }
  329. BOOL CCreateNewUserPage1::_InitUI()
  330. {
  331. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  332. IADs * pObj = NULL;
  333. CComBSTR bsPath;
  334. CComBSTR bsDN;
  335. LPWSTR pwzDomain = NULL;
  336. Edit_LimitText (GetDlgItem(IDC_EDIT_FULL_NAME)->m_hWnd, 64);
  337. Edit_LimitText (GetDlgItem(IDC_EDIT_LAST_NAME)->m_hWnd, 29);
  338. Edit_LimitText (GetDlgItem(IDC_EDIT_FIRST_NAME)->m_hWnd, 28);
  339. Edit_LimitText (GetDlgItem(IDC_EDIT_INITIALS)->m_hWnd, 4);
  340. Edit_LimitText (GetDlgItem(IDC_NT4_USER_EDIT)->m_hWnd, 20);
  341. Edit_LimitText (GetDlgItem(IDC_NT5_USER_EDIT)->m_hWnd, 256);
  342. HRESULT hr = pNewADsObjectCreateInfo->m_pIADsContainer->QueryInterface(
  343. IID_IADs, (void **)&pObj);
  344. if (SUCCEEDED(hr))
  345. {
  346. // get the DN of the container from its LDAP path
  347. pObj->get_ADsPath (&bsPath);
  348. { // scope for smart pointer
  349. CPathCracker pathCracker;
  350. pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  351. pathCracker.Set(bsPath, ADS_SETTYPE_FULL);
  352. pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bsDN);
  353. }
  354. // get the NT 5 (dns) domain name
  355. TRACE(L"CrackName(%s, &pwzDomain, GET_DNS_DOMAIN_NAME, NULL);\n", bsDN);
  356. hr = CrackName(bsDN, &pwzDomain, GET_DNS_DOMAIN_NAME, NULL);
  357. TRACE(L"CrackName returned hr = 0x%x, pwzDomain = <%s>\n", hr, pwzDomain);
  358. // get the NT 4 domain name from the DN
  359. LPWSTR pwzNT4Domain = NULL;
  360. TRACE(L"CrackName (%s, &pwzNT4Domain, GET_NT4_DOMAIN_NAME, NULL);\n", bsDN);
  361. hr = CrackName(bsDN, &pwzNT4Domain, GET_NT4_DOMAIN_NAME, NULL);
  362. TRACE(L"CrackName returned hr = 0x%x, pwzNT4Domain = <%s>\n", hr, pwzNT4Domain);
  363. // set the NT 4 domain name read only edit box
  364. if (pwzNT4Domain != NULL)
  365. {
  366. CString szBuffer;
  367. szBuffer.Format(L"%s\\", pwzNT4Domain);
  368. SetDlgItemText(IDC_NT4_DOMAIN_EDIT, szBuffer);
  369. LocalFreeStringW(&pwzNT4Domain);
  370. }
  371. }
  372. TRACE(L"After CrackName() calls, pwzDomain = <%s>\n", pwzDomain);
  373. // if we do not have a domain name, we cannot proceed further,
  374. // this is a catastrophic failure
  375. if (pwzDomain == NULL)
  376. {
  377. // should never get here in normal operations
  378. HWND hWndWiz = ::GetParent(m_hWnd);
  379. ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr,
  380. MB_OK | MB_ICONERROR, NULL, 0);
  381. // bail out of the wizard
  382. VERIFY(::PostMessage(hWndWiz, WM_COMMAND, IDCANCEL, 0));
  383. return TRUE;
  384. }
  385. m_LocalDomain = L"@";
  386. m_LocalDomain += pwzDomain;
  387. CComboBox * pCC = (CComboBox *)GetDlgItem (IDC_NT5_DOMAIN_COMBO);
  388. // get the current domain (only present if we're going around a second time
  389. // due an error.) need this to prevent dups when on second trip.
  390. CString strDomain;
  391. GetDlgItemText (IDC_NT5_DOMAIN_COMBO, OUT strDomain);
  392. CStringList UPNs;
  393. // get UPN suffixes from this OU, if present
  394. CComVariant Var;
  395. hr = pObj->Get ( L"uPNSuffixes", &Var);
  396. if (SUCCEEDED(hr)) {
  397. hr = HrVariantToStringList (IN Var, UPNs);
  398. if (SUCCEEDED(hr)) {
  399. POSITION pos = UPNs.GetHeadPosition();
  400. CString csSuffix;
  401. while (pos != NULL) {
  402. csSuffix = L"@";
  403. csSuffix += UPNs.GetNext(INOUT pos);
  404. TRACE(_T("UPN suffix: %s\n"), csSuffix);
  405. pCC->AddString (csSuffix);
  406. }
  407. }
  408. } else {
  409. CString csPartitions;
  410. IADs * pPartitions = NULL;
  411. // get config path from main object
  412. csPartitions.Format(L"%sCN=Partitions,%s",
  413. pNewADsObjectCreateInfo->GetBasePathsInfo()->GetProviderAndServerName(),
  414. pNewADsObjectCreateInfo->GetBasePathsInfo()->GetConfigNamingContext());
  415. hr = DSAdminOpenObject(csPartitions,
  416. IID_IADs,
  417. (void **)&pPartitions,
  418. TRUE /*bServer*/);
  419. if (SUCCEEDED(hr)) {
  420. CComVariant sVar;
  421. hr = pPartitions->Get ( L"uPNSuffixes", &sVar);
  422. if (SUCCEEDED(hr)) {
  423. hr = HrVariantToStringList (IN sVar, UPNs);
  424. if (SUCCEEDED(hr)) {
  425. POSITION pos = UPNs.GetHeadPosition();
  426. CString csSuffix;
  427. while (pos != NULL) {
  428. csSuffix = L"@";
  429. csSuffix += UPNs.GetNext(INOUT pos);
  430. TRACE(_T("UPN suffix: %s\n"), csSuffix);
  431. if (wcscmp (strDomain, csSuffix)) {
  432. pCC->AddString (csSuffix);
  433. }
  434. }
  435. }
  436. }
  437. pPartitions->Release();
  438. }
  439. // get rest of domains in this tree
  440. CComPtr <IDsBrowseDomainTree> spDsDomains;
  441. hr = ::CoCreateInstance(CLSID_DsDomainTreeBrowser,
  442. NULL,
  443. CLSCTX_INPROC_SERVER,
  444. IID_IDsBrowseDomainTree,
  445. (LPVOID*)&spDsDomains);
  446. if (FAILED(hr)) {
  447. LocalFreeStringW(&pwzDomain);
  448. return FALSE;
  449. }
  450. LPCWSTR lpszServerName = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName();
  451. hr = spDsDomains->SetComputer(lpszServerName, NULL, NULL);
  452. ASSERT(SUCCEEDED(hr));
  453. TRACE(L"returned from SetComputer(%s). hr is %lx\n", lpszServerName, hr);
  454. PDOMAIN_TREE pNewDomains = NULL;
  455. hr = spDsDomains->GetDomains(&pNewDomains, 0);
  456. TRACE(L"returned from GetDomains(), hr is %lx\n", hr);
  457. CString csRootDomain = L"@";
  458. INT pos;
  459. UINT iRoot;
  460. if (SUCCEEDED(hr) && pNewDomains) {
  461. TRACE(L"pNewDomains->dwCount = %d\n", pNewDomains->dwCount);
  462. for (UINT index = 0; index < pNewDomains->dwCount; index++) {
  463. TRACE(L"pNewDomains->aDomains[%d].pszName = <%s>\n", index, pNewDomains->aDomains[index].pszName);
  464. if (pNewDomains->aDomains[index].pszTrustParent == NULL) {
  465. //
  466. // Add the root domain only if it is a substring of the current
  467. // domain.
  468. //
  469. size_t cchRoot = wcslen(pNewDomains->aDomains[index].pszName);
  470. PWSTR pRoot = pwzDomain + wcslen(pwzDomain) - cchRoot;
  471. if (!_wcsicmp(pRoot, pNewDomains->aDomains[index].pszName))
  472. {
  473. csRootDomain += pNewDomains->aDomains[index].pszName;
  474. if (_wcsicmp (strDomain, csRootDomain)) {
  475. pos = pCC->AddString (csRootDomain);
  476. }
  477. iRoot = index;
  478. }
  479. }
  480. }
  481. }
  482. // If the local domain is not the root, add it as well.
  483. //
  484. CString csOtherDomain = L"@";
  485. if (_wcsicmp(csRootDomain, m_LocalDomain))
  486. {
  487. if (_wcsicmp (strDomain, m_LocalDomain)) {
  488. pos = pCC->AddString(m_LocalDomain);
  489. }
  490. }
  491. if (pNewDomains) {
  492. spDsDomains->FreeDomains(&pNewDomains);
  493. }
  494. LocalFreeStringW(&pwzDomain);
  495. }
  496. if (pObj) {
  497. pObj->Release();
  498. pObj = NULL;
  499. }
  500. //
  501. // If the local domain is not already in the list then add it
  502. //
  503. int iFind = pCC->FindStringExact(-1, m_LocalDomain);
  504. if (iFind == CB_ERR)
  505. {
  506. pCC->InsertString(0, m_LocalDomain);
  507. pCC->SetCurSel(0);
  508. }
  509. else
  510. {
  511. pCC->SetCurSel(iFind);
  512. }
  513. m_nameFormatter.Initialize(pNewADsObjectCreateInfo->GetBasePathsInfo(),
  514. pNewADsObjectCreateInfo->m_pszObjectClass);
  515. return TRUE;
  516. }
  517. BOOL CCreateNewUserPage1::GetData(IADs* pIADsCopyFrom)
  518. {
  519. HRESULT hr = S_OK;
  520. if (pIADsCopyFrom != NULL)
  521. {
  522. // copy operation
  523. // we copy the UPN suffix
  524. CComVariant varData;
  525. hr = pIADsCopyFrom->Get(L"userPrincipalName", &varData);
  526. if (SUCCEEDED(hr))
  527. {
  528. // got something like "[email protected]."
  529. TRACE(L"source userPrincipalName: %s\n", varData.bstrVal);
  530. // need to get the suffix "@acme.com."
  531. for (LPWSTR lpszUPNSuffix = varData.bstrVal; lpszUPNSuffix != NULL; lpszUPNSuffix++)
  532. {
  533. if ((*lpszUPNSuffix) == L'@')
  534. {
  535. break;
  536. }
  537. }
  538. if (lpszUPNSuffix != NULL)
  539. {
  540. TRACE(L"source UPN suffix: %s\n", lpszUPNSuffix);
  541. // need to find out of the suffix is already there
  542. CComboBox * pDomainCombo = (CComboBox *)GetDlgItem(IDC_NT5_DOMAIN_COMBO);
  543. int iIndex = pDomainCombo->FindString(-1, lpszUPNSuffix);
  544. if (iIndex == CB_ERR)
  545. {
  546. // not found, just add at the top
  547. pDomainCombo->InsertString(0, lpszUPNSuffix);
  548. iIndex = 0;
  549. }
  550. ASSERT( (iIndex >= 0) && (iIndex < pDomainCombo->GetCount()));
  551. // set the selection to the source UPN suffix
  552. pDomainCombo->SetCurSel(iIndex);
  553. }
  554. }
  555. return FALSE;
  556. }
  557. return (!m_strLoginName.IsEmpty() &&!m_strFullName.IsEmpty());
  558. }
  559. void CCreateNewUserPage1::OnNameChange()
  560. {
  561. GetDlgItemText(IDC_EDIT_FIRST_NAME, OUT m_strFirstName);
  562. GetDlgItemText(IDC_EDIT_INITIALS, OUT m_strInitials);
  563. GetDlgItemText(IDC_EDIT_LAST_NAME, OUT m_strLastName);
  564. m_strFirstName.TrimLeft();
  565. m_strFirstName.TrimRight();
  566. m_strInitials.TrimLeft();
  567. m_strInitials.TrimRight();
  568. m_strLastName.TrimLeft();
  569. m_strLastName.TrimRight();
  570. m_nameFormatter.FormatName(m_strFullName,
  571. m_strFirstName.IsEmpty() ? NULL : (LPCWSTR)m_strFirstName,
  572. m_strInitials.IsEmpty() ? NULL : (LPCWSTR)m_strInitials,
  573. m_strLastName.IsEmpty() ? NULL : (LPCWSTR)m_strLastName);
  574. SetDlgItemText (IDC_EDIT_FULL_NAME,
  575. IN m_strFullName);
  576. GetDlgItemText(IDC_NT5_USER_EDIT, OUT m_strLoginName);
  577. GetWiz()->SetWizardButtons(this, (!m_strLoginName.IsEmpty() &&
  578. !m_strFullName.IsEmpty() &&
  579. !m_strSAMName.IsEmpty()));
  580. }
  581. void CCreateNewUserPage1::OnLoginNameChange()
  582. {
  583. if (!m_bForcingNameChange)
  584. {
  585. CString csSamName;
  586. GetDlgItemText(IDC_NT5_USER_EDIT, OUT m_strLoginName);
  587. csSamName = m_strLoginName.Left(20);
  588. SetDlgItemText (IDC_NT4_USER_EDIT, OUT csSamName);
  589. }
  590. GetWiz()->SetWizardButtons(this, (!m_strLoginName.IsEmpty() &&
  591. !m_strFullName.IsEmpty() &&
  592. !m_strSAMName.IsEmpty()));
  593. }
  594. void CCreateNewUserPage1::OnSAMNameChange()
  595. {
  596. GetDlgItemText (IDC_NT4_USER_EDIT, OUT m_strSAMName);
  597. GetWiz()->SetWizardButtons(this, (!m_strLoginName.IsEmpty() &&
  598. !m_strFullName.IsEmpty() &&
  599. !m_strSAMName.IsEmpty()));
  600. }
  601. void CCreateNewUserPage1::OnFullNameChange()
  602. {
  603. GetDlgItemText (IDC_EDIT_FULL_NAME, OUT m_strFullName);
  604. GetWiz()->SetWizardButtons(this, (!m_strLoginName.IsEmpty() &&
  605. !m_strFullName.IsEmpty() &&
  606. !m_strSAMName.IsEmpty()));
  607. }
  608. //
  609. BOOL CCreateNewUserPage1::OnError( HRESULT hr )
  610. {
  611. BOOL bRetVal = FALSE;
  612. if( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
  613. {
  614. HRESULT Localhr;
  615. DWORD LastError;
  616. WCHAR Buf1[256], Buf2[256];
  617. Localhr = ADsGetLastError (&LastError,
  618. Buf1, 256, Buf2, 256);
  619. switch( LastError )
  620. {
  621. case ERROR_USER_EXISTS:
  622. {
  623. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSAMName};
  624. ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_USER_EXISTS,hr,
  625. MB_OK|MB_ICONWARNING , apv, 1);
  626. bRetVal = TRUE;
  627. }
  628. break;
  629. case ERROR_DS_OBJ_STRING_NAME_EXISTS:
  630. {
  631. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strFullName};
  632. ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_USER_DS_OBJ_STRING_NAME_EXISTS,hr,
  633. MB_OK|MB_ICONWARNING , apv, 1);
  634. bRetVal = TRUE;
  635. }
  636. break;
  637. }
  638. }
  639. return bRetVal;
  640. }
  641. ///////////////////////////////////////////////////////////////
  642. // CCreateNewUserPage2
  643. BEGIN_MESSAGE_MAP(CCreateNewUserPage2, CCreateNewObjectDataPage)
  644. ON_BN_CLICKED (IDC_CHECK_PASSWORD_MUST_CHANGE, OnPasswordPropsClick)
  645. ON_BN_CLICKED (IDC_CHECK_PASSWORD_NEVER_EXPIRES, OnPasswordPropsClick)
  646. ON_BN_CLICKED (IDC_CHECK_PASSWORD_CANNOT_CHANGE, OnPasswordPropsClick)
  647. END_MESSAGE_MAP()
  648. CCreateNewUserPage2::CCreateNewUserPage2() :
  649. CCreateNewObjectDataPage(CCreateNewUserPage2::IDD)
  650. {
  651. m_pPage1 = NULL;
  652. }
  653. BOOL CCreateNewUserPage2::OnInitDialog()
  654. {
  655. CCreateNewObjectDataPage::OnInitDialog();
  656. SendDlgItemMessage(IDC_EDIT_PASSWORD, EM_LIMITTEXT, (WPARAM)127, 0);
  657. SendDlgItemMessage(IDC_EDIT_PASSWORD_CONFIRM, EM_LIMITTEXT, (WPARAM)127, 0);
  658. return TRUE;
  659. }
  660. void CCreateNewUserPage2::_GetCheckBoxSummaryInfo(UINT nCtrlID, UINT nStringID, CString& s)
  661. {
  662. if (IsDlgButtonChecked(nCtrlID))
  663. {
  664. CString sz;
  665. sz.LoadString(nStringID);
  666. s += sz;
  667. s += L"\n";
  668. }
  669. }
  670. void CCreateNewUserPage2::GetSummaryInfo(CString& s)
  671. {
  672. _GetCheckBoxSummaryInfo(IDC_CHECK_PASSWORD_MUST_CHANGE, IDS_USER_CREATE_DLG_PASSWORD_MUST_CHANGE, s);
  673. _GetCheckBoxSummaryInfo(IDC_CHECK_PASSWORD_CANNOT_CHANGE, IDS_USER_CREATE_DLG_PASSWORD_CANNOT_CHANGE, s);
  674. _GetCheckBoxSummaryInfo(IDC_CHECK_PASSWORD_NEVER_EXPIRES, IDS_USER_CREATE_DLG_PASSWORD_NEVER_EXPIRES, s);
  675. _GetCheckBoxSummaryInfo(IDC_CHECK_ACCOUNT_DISABLED, IDS_USER_CREATE_DLG_ACCOUNT_DISABLED, s);
  676. }
  677. void
  678. CCreateNewUserPage2::OnPasswordPropsClick()
  679. {
  680. BOOL fPasswordMustChange = IsDlgButtonChecked(IDC_CHECK_PASSWORD_MUST_CHANGE);
  681. BOOL fPasswordCannotChange = IsDlgButtonChecked(IDC_CHECK_PASSWORD_CANNOT_CHANGE);
  682. BOOL fPasswordNeverExpires = IsDlgButtonChecked(IDC_CHECK_PASSWORD_NEVER_EXPIRES);
  683. if (fPasswordMustChange && fPasswordNeverExpires)
  684. {
  685. ReportErrorEx (::GetParent(m_hWnd),IDS_PASSWORD_MUTEX,S_OK,
  686. MB_OK, NULL, 0);
  687. CheckDlgButton(IDC_CHECK_PASSWORD_MUST_CHANGE, FALSE);
  688. fPasswordMustChange = FALSE;
  689. }
  690. if (fPasswordMustChange && fPasswordCannotChange)
  691. {
  692. ReportErrorEx (::GetParent(m_hWnd),IDS_ERR_BOTH_PW_BTNS,S_OK,
  693. MB_OK, NULL, 0);
  694. CheckDlgButton(IDC_CHECK_PASSWORD_CANNOT_CHANGE, FALSE);
  695. }
  696. }
  697. HRESULT CCreateNewUserPage2::SetData(BOOL bSilent)
  698. {
  699. CString strPassword;
  700. CString strPasswordConfirm;
  701. GetDlgItemText(IDC_EDIT_PASSWORD, OUT strPassword);
  702. GetDlgItemText(IDC_EDIT_PASSWORD_CONFIRM, OUT strPasswordConfirm);
  703. if (strPassword != strPasswordConfirm)
  704. {
  705. if (!bSilent)
  706. {
  707. ReportErrorEx (::GetParent(m_hWnd),IDS_PASSWORDS_DONT_MATCH,S_OK,
  708. MB_OK, NULL, 0);
  709. }
  710. SetDlgItemText(IDC_EDIT_PASSWORD, L"");
  711. SetDlgItemText(IDC_EDIT_PASSWORD_CONFIRM, L"");
  712. SetDlgItemFocus(IDC_EDIT_PASSWORD);
  713. return E_INVALIDARG;
  714. }
  715. HRESULT hr = S_OK;
  716. // intelligent copy of path info, it if is a copy operation
  717. {
  718. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  719. CCopyObjectHandlerBase* pCopyHandler = pNewADsObjectCreateInfo->GetCopyHandler();
  720. if (pCopyHandler != NULL)
  721. {
  722. IADs * pIADs = pNewADsObjectCreateInfo->PGetIADsPtr();
  723. ASSERT(pIADs != NULL);
  724. hr = pCopyHandler->Copy(pIADs, FALSE /*bPostCommit*/, ::GetParent(m_hWnd),
  725. m_pPage1->GetFullName());
  726. }
  727. }
  728. return hr;
  729. }
  730. //+----------------------------------------------------------------------------
  731. //
  732. // Method: _RevokeChangePasswordPrivilege
  733. //
  734. // Purpose: Revoke the user's change password privilege.
  735. //
  736. //-----------------------------------------------------------------------------
  737. HRESULT RevokeChangePasswordPrivilege(IADs * pIADs)
  738. {
  739. CChangePasswordPrivilegeAction ChangePasswordPrivilegeAction;
  740. HRESULT hr = ChangePasswordPrivilegeAction.Load(pIADs);
  741. if (FAILED(hr))
  742. {
  743. TRACE(L"ChangePasswordPrivilegeAction.Load() failed with hr = 0x%x\n", hr);
  744. return hr;
  745. }
  746. hr = ChangePasswordPrivilegeAction.Revoke();
  747. if (FAILED(hr))
  748. {
  749. TRACE(L"ChangePasswordPrivilegeAction.Revoke() failed with hr = 0x%x\n", hr);
  750. return hr;
  751. }
  752. return S_OK;
  753. }
  754. HRESULT CCreateNewUserPage2::OnPostCommit(BOOL bSilent)
  755. {
  756. // local variables
  757. HRESULT hr = E_FAIL;
  758. PVOID apv[1] = {(LPWSTR)(m_pPage1->GetFullName())};
  759. CWaitCursor Wait;
  760. CComPtr <IDirectoryObject> pIDSObject; // smart pointer, no need to release
  761. CComPtr <IADsUser> pIADsUser; // smart pointer, no need to release
  762. BOOL bCanEnable = TRUE;
  763. CString strPassword;
  764. GetDlgItemText(IDC_EDIT_PASSWORD, OUT strPassword);
  765. BOOL fPasswordMustChange = IsDlgButtonChecked(IDC_CHECK_PASSWORD_MUST_CHANGE);
  766. BOOL fPasswordCannotChange = IsDlgButtonChecked(IDC_CHECK_PASSWORD_CANNOT_CHANGE);
  767. BOOL fPasswordNeverExpires = IsDlgButtonChecked(IDC_CHECK_PASSWORD_NEVER_EXPIRES);
  768. BOOL fAccountEnabled = !IsDlgButtonChecked(IDC_CHECK_ACCOUNT_DISABLED);
  769. CComVariant varAccountFlags;
  770. // get object info and useful interfaces
  771. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  772. ASSERT(pNewADsObjectCreateInfo != NULL);
  773. IADs * pIADs = pNewADsObjectCreateInfo->PGetIADsPtr();
  774. ASSERT(pIADs != NULL);
  775. // get the IDirectoryObject interface
  776. hr = pIADs->QueryInterface(IID_IDirectoryObject, OUT (void **)&pIDSObject);
  777. ASSERT(pIDSObject != NULL);
  778. if (FAILED(hr))
  779. {
  780. ASSERT(FALSE); // should never get here in normal operations
  781. if (!bSilent)
  782. {
  783. ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr,
  784. MB_OK | MB_ICONERROR, NULL, 0);
  785. }
  786. goto ExitCleanup;
  787. }
  788. // get the IADsUser interface
  789. hr = pIADs->QueryInterface(IID_IADsUser, OUT (void **)&pIADsUser);
  790. ASSERT(pIDSObject != NULL);
  791. if (FAILED(hr))
  792. {
  793. ASSERT(FALSE); // should never get here in normal operations
  794. if (!bSilent)
  795. {
  796. ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr,
  797. MB_OK | MB_ICONERROR, NULL, 0);
  798. }
  799. goto ExitCleanup;
  800. }
  801. // try to set password
  802. ASSERT(pIADsUser != NULL);
  803. hr = pIADsUser->SetPassword(const_cast<LPTSTR>((LPCTSTR)strPassword));
  804. if (FAILED(hr))
  805. {
  806. if (hr != E_ACCESSDENIED)
  807. {
  808. if (!bSilent)
  809. {
  810. // fatal error, put up error message
  811. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_SET_PASSWORD,hr,
  812. MB_OK | MB_ICONWARNING, apv, 1);
  813. }
  814. bCanEnable = FALSE;
  815. goto ExitCleanup;
  816. }
  817. else
  818. {
  819. if (!bSilent)
  820. {
  821. ReportErrorEx(::GetParent(m_hWnd),IDS_12_ACCESS_DENIED_SET_PASSWORD,hr,
  822. MB_OK | MB_ICONWARNING, apv, 1);
  823. }
  824. bCanEnable = FALSE;
  825. }
  826. }
  827. if (fPasswordMustChange)
  828. {
  829. LPWSTR szPwdLastSet = L"pwdLastSet";
  830. ADSVALUE ADsValuePwdLastSet = {ADSTYPE_LARGE_INTEGER, NULL};
  831. ADS_ATTR_INFO AttrInfoPwdLastSet = {szPwdLastSet, ADS_ATTR_UPDATE,
  832. ADSTYPE_LARGE_INTEGER,
  833. &ADsValuePwdLastSet, 1};
  834. ADsValuePwdLastSet.LargeInteger.QuadPart = 0;
  835. ASSERT(pIDSObject != NULL);
  836. DWORD cAttrModified = 0;
  837. hr = pIDSObject->SetObjectAttributes(&AttrInfoPwdLastSet, 1, &cAttrModified);
  838. if (FAILED(hr))
  839. {
  840. ASSERT(cAttrModified == 0);
  841. // fatal error, put up error message and bail out
  842. if (!bSilent)
  843. {
  844. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_SET_PWD_MUST_CHANGE,hr,
  845. MB_OK | MB_ICONERROR, apv, 1);
  846. }
  847. bCanEnable = FALSE;
  848. }
  849. ASSERT(cAttrModified == 1);
  850. } // if (fPasswordMustChange)
  851. if (fPasswordCannotChange)
  852. {
  853. hr = RevokeChangePasswordPrivilege(pIADs);
  854. if (FAILED(hr))
  855. {
  856. if (!bSilent)
  857. {
  858. // warning ad go on
  859. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_SET_PWD_CANNOT_CHANGE,hr,
  860. MB_OK | MB_ICONWARNING, apv, 1);
  861. }
  862. bCanEnable = FALSE;
  863. hr = S_OK;
  864. }
  865. }
  866. // Set userAccountControl
  867. hr = pNewADsObjectCreateInfo->HrGetAttributeVariant(const_cast<PWSTR>(gsz_userAccountControl), OUT &varAccountFlags);
  868. { // scope for local variables
  869. // if copy operation, makes sure we get the right set of bits copied over
  870. CCopyUserHandler* pCopyUserHandler =
  871. dynamic_cast<CCopyUserHandler*>(GetWiz()->GetInfo()->GetCopyHandler());
  872. if (pCopyUserHandler != NULL)
  873. {
  874. CComVariant varAccountControlSource;
  875. hr = pCopyUserHandler->GetCopyFrom()->Get((LPWSTR)gsz_userAccountControl, &varAccountControlSource);
  876. if (SUCCEEDED(hr))
  877. {
  878. ASSERT(varAccountControlSource.vt == VT_I4);
  879. // some bits are already set in the UI and the user can change them,
  880. // we will get them later on
  881. varAccountControlSource.vt &= ~UF_DONT_EXPIRE_PASSWD;
  882. varAccountControlSource.vt &= ~UF_ACCOUNTDISABLE;
  883. // add the remaining bits to the default ones after creation
  884. varAccountFlags.vt |= varAccountControlSource.vt;
  885. }
  886. }
  887. }
  888. if (SUCCEEDED(hr))
  889. {
  890. ASSERT(varAccountFlags.vt == VT_I4);
  891. if (fPasswordNeverExpires)
  892. varAccountFlags.lVal |= UF_DONT_EXPIRE_PASSWD;
  893. varAccountFlags.lVal &= ~UF_PASSWD_NOTREQD;
  894. // Update the userAccountControl attribute
  895. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(const_cast<PWSTR>(gsz_userAccountControl), varAccountFlags);
  896. ASSERT(SUCCEEDED(hr));
  897. hr = pNewADsObjectCreateInfo->HrSetInfo(bSilent /* fSilentError */ );
  898. if (FAILED(hr))
  899. {
  900. if (HRESULT_CODE(hr) == ERROR_DS_UNWILLING_TO_PERFORM)
  901. {
  902. DWORD status;
  903. WCHAR Buf1[256], Buf2[256];
  904. ADsGetLastError (&status, Buf1, 256, Buf2, 256);
  905. TRACE(_T("ADsGetLastError returned status of %lx, error: %s, name %s\n"),
  906. status, Buf1, Buf2);
  907. if ((status == ERROR_PASSWORD_RESTRICTION) &&
  908. strPassword.IsEmpty())
  909. {
  910. if (!bSilent)
  911. {
  912. ReportErrorEx(::GetParent(m_hWnd),IDS_NULL_PASSWORD,hr,
  913. MB_OK | MB_ICONERROR, NULL, 0);
  914. }
  915. goto ExitCleanup;
  916. }
  917. }
  918. // we failed, so we put up a warning and leave the object intact
  919. if (!bSilent)
  920. {
  921. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_GET_USERACCOUNTCONTROL,hr,
  922. MB_OK | MB_ICONERROR, apv, 1);
  923. }
  924. // reset error code, just a warning
  925. bCanEnable = FALSE;
  926. hr = S_OK;
  927. }
  928. }
  929. else
  930. {
  931. TRACE1("INFO: Unable to get userAccountControl for user %s.\n",
  932. m_pPage1->GetFullName());
  933. // put up message box, but continue
  934. if (!bSilent)
  935. {
  936. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_GET_USERACCOUNTCONTROL,hr,
  937. MB_OK | MB_ICONERROR, apv, 1);
  938. }
  939. // reset error code, just a warning
  940. hr = S_OK;
  941. }
  942. // finally, if all went well, we can enable the user account
  943. hr = S_OK;
  944. if (bCanEnable & fAccountEnabled)
  945. {
  946. hr = pNewADsObjectCreateInfo->HrGetAttributeVariant(const_cast<PWSTR>(gsz_userAccountControl), OUT &varAccountFlags);
  947. varAccountFlags.lVal &= ~UF_ACCOUNTDISABLE;
  948. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(const_cast<PWSTR>(gsz_userAccountControl), varAccountFlags);
  949. hr = pNewADsObjectCreateInfo->HrSetInfo(bSilent /* fSilentError */ );
  950. if (FAILED(hr))
  951. {
  952. if (HRESULT_CODE(hr) == ERROR_DS_UNWILLING_TO_PERFORM)
  953. {
  954. DWORD status;
  955. WCHAR Buf1[256], Buf2[256];
  956. ADsGetLastError (&status, Buf1, 256, Buf2, 256);
  957. TRACE(_T("ADsGetLastError returned status of %lx, error: %s, name %s\n"),
  958. status, Buf1, Buf2);
  959. if ((status == ERROR_PASSWORD_RESTRICTION) &&
  960. strPassword.IsEmpty())
  961. {
  962. //
  963. // NTRAID#Windows Bugs-367611-2001/04/14-jeffjon
  964. // DsAdmin: When password policy set, create usr with blank psswrd
  965. // and 2 error msgs appear. One msg is enough
  966. //
  967. // This message is being handled from within the HrSetInfo above
  968. // and is actually more descriptive. Probably a change to winerror.mc
  969. //
  970. /*
  971. if (!bSilent)
  972. {
  973. ReportErrorEx(::GetParent(m_hWnd),IDS_NULL_PASSWORD,hr,
  974. MB_OK | MB_ICONERROR, NULL, 0);
  975. }
  976. */
  977. goto ExitCleanup;
  978. }
  979. }
  980. // we failed, so we put up a warning and leave the object intact
  981. if (!bSilent)
  982. {
  983. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_GET_USERACCOUNTCONTROL,hr,
  984. MB_OK | MB_ICONERROR, apv, 1);
  985. }
  986. // reset error code, just a warning
  987. hr = S_OK;
  988. }
  989. }
  990. // try to set group membership, it if is a copy operation
  991. {
  992. CCopyObjectHandlerBase* pCopyHandler = GetWiz()->GetInfo()->GetCopyHandler();
  993. if (pCopyHandler != NULL)
  994. {
  995. hr = pCopyHandler->Copy(pIADs, TRUE /*bPostCommit*/,::GetParent(m_hWnd),
  996. m_pPage1->GetFullName());
  997. if (SUCCEEDED(hr))
  998. {
  999. hr = pNewADsObjectCreateInfo->HrSetInfo(bSilent/* fSilentError */ );
  1000. }
  1001. if (FAILED(hr))
  1002. {
  1003. // we failed, so we put up a warning and leave the object intact
  1004. if (!bSilent)
  1005. {
  1006. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_SET_GROUP_MEMBERSHIP,hr,
  1007. MB_OK | MB_ICONERROR, apv, 1);
  1008. }
  1009. // reset error code, just a warning
  1010. hr = S_OK;
  1011. }
  1012. }
  1013. }
  1014. ExitCleanup:
  1015. return hr;
  1016. }
  1017. BOOL CCreateNewUserPage2::GetData(IADs* pIADsCopyFrom)
  1018. {
  1019. if (pIADsCopyFrom != NULL)
  1020. {
  1021. CString szFmt;
  1022. szFmt.LoadString(IDS_s_COPY_SUMMARY_NAME);
  1023. // we just get the CN of the object
  1024. CComVariant varAccountControl;
  1025. HRESULT hr = pIADsCopyFrom->Get((LPWSTR)gsz_userAccountControl, &varAccountControl);
  1026. if (SUCCEEDED(hr))
  1027. {
  1028. BOOL bPasswordNeverExpires = (varAccountControl.lVal & UF_DONT_EXPIRE_PASSWD) != 0;
  1029. BOOL bDisabled = (varAccountControl.lVal & UF_ACCOUNTDISABLE) != 0;
  1030. CheckDlgButton(IDC_CHECK_PASSWORD_NEVER_EXPIRES, bPasswordNeverExpires);
  1031. CheckDlgButton(IDC_CHECK_ACCOUNT_DISABLED, bDisabled);
  1032. } // if
  1033. CCopyUserHandler* pCopyUserHandler =
  1034. dynamic_cast<CCopyUserHandler*>(GetWiz()->GetInfo()->GetCopyHandler());
  1035. ASSERT(pCopyUserHandler != NULL);
  1036. if (pCopyUserHandler != NULL)
  1037. {
  1038. // set the cannot change password checkbox
  1039. BOOL bPasswordCannotChange = pCopyUserHandler->PasswordCannotChange();
  1040. CheckDlgButton(IDC_CHECK_PASSWORD_CANNOT_CHANGE, bPasswordCannotChange);
  1041. if (!bPasswordCannotChange)
  1042. {
  1043. // set the must change password checkbox
  1044. BOOL bPasswordMustChange = pCopyUserHandler->PasswordMustChange();
  1045. CheckDlgButton(IDC_CHECK_PASSWORD_MUST_CHANGE, bPasswordMustChange);
  1046. }
  1047. }
  1048. } // if
  1049. return TRUE;
  1050. }
  1051. ///////////////////////////////////////////////////////////////
  1052. // CCreateNewUserWizard
  1053. CCreateNewUserWizard::CCreateNewUserWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) :
  1054. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  1055. {
  1056. AddPage(&m_page1);
  1057. AddPage(&m_page2);
  1058. m_page2.SetPage1(&m_page1);
  1059. }
  1060. void CCreateNewUserWizard::GetSummaryInfoHeader(CString& s)
  1061. {
  1062. IADs* pIADsCopyFrom = GetInfo()->GetCopyFromObject();
  1063. if (pIADsCopyFrom != NULL)
  1064. {
  1065. CString szFmt;
  1066. szFmt.LoadString(IDS_s_COPY_SUMMARY_NAME);
  1067. // we just get the CN of the object
  1068. CComVariant varName;
  1069. HRESULT hr = pIADsCopyFrom->Get(L"cn", &varName);
  1070. if (SUCCEEDED(hr))
  1071. {
  1072. CString szTmp;
  1073. szTmp.Format((LPCWSTR)szFmt, varName.bstrVal);
  1074. s += szTmp;
  1075. s += L"\n";
  1076. }
  1077. }
  1078. CCreateNewObjectWizardBase::GetSummaryInfoHeader(s);
  1079. }
  1080. void CCreateNewUserWizard::OnFinishSetInfoFailed(HRESULT hr)
  1081. {
  1082. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1083. if ( !( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS &&
  1084. m_page1.OnError( hr ) ) )
  1085. {
  1086. // everything else is handled by the base class
  1087. CCreateNewObjectWizardBase::OnFinishSetInfoFailed(hr);
  1088. }
  1089. }