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.

3721 lines
105 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 2002
  6. //
  7. // File: dlgcreat.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////
  11. // dlgcreat.cpp
  12. //
  13. // Implementation of dialogs that create new ADs objects.
  14. //
  15. // DIALOGS SUPPORTED
  16. // CCreateNewObjectCnDlg - Dialog asking for "cn" attribute.
  17. // CCreateNewVolumeDlg - Create a new volume "shared folder" object
  18. // CCreateNewComputerDlg - Create a new computer object.
  19. // CCreateNewSiteLinkDlg - Create a new Site Link.
  20. // CCreateNewSiteLinkBridgeDlg - Create a new Site Link Bridge.
  21. //
  22. // DIALOGS NOT YET IMPLEMENTED
  23. // site (validation only)
  24. // organizationalUnit
  25. // localPolicy
  26. // auditingPolicy
  27. //
  28. // HISTORY
  29. // 24-Aug-97 Dan Morin Creation.
  30. //
  31. /////////////////////////////////////////////////////////////////////
  32. #include "stdafx.h"
  33. #include "dsutil.h"
  34. #include "uiutil.h"
  35. #include <windowsx.h>
  36. #include <lmaccess.h>
  37. #include <dnsapi.h> // DnsValidateName_W
  38. #include "winsprlp.h" //PublishPrinter
  39. #include "newobj.h" // CNewADsObjectCreateInfo
  40. #include "dlgcreat.h"
  41. extern "C"
  42. {
  43. #include "lmerr.h" // NET_API_STATUS
  44. #include "icanon.h" // I_NetPathType
  45. }
  46. static const PWSTR g_pszDefaultSecurityDescriptor = L"defaultSecurityDescriptor";
  47. ///////////////////////////////////////////////////////////////////////////
  48. // CHPropSheetPageArr
  49. CHPropSheetPageArr::CHPropSheetPageArr()
  50. {
  51. m_nCount = 0;
  52. m_nSize = 4;
  53. ULONG nBytes = sizeof(HPROPSHEETPAGE)*m_nSize;
  54. m_pArr = (HPROPSHEETPAGE*)malloc(nBytes);
  55. if (m_pArr != NULL)
  56. {
  57. ZeroMemory(m_pArr, nBytes);
  58. }
  59. }
  60. void CHPropSheetPageArr::AddHPage(HPROPSHEETPAGE hPage)
  61. {
  62. // see if there is space in the array
  63. if (m_nCount == m_nSize)
  64. {
  65. // grow the array
  66. int nAlloc = m_nSize*2;
  67. HPROPSHEETPAGE* temp = (HPROPSHEETPAGE*)realloc(m_pArr, sizeof(HPROPSHEETPAGE)*nAlloc);
  68. if (temp)
  69. {
  70. m_pArr = temp;
  71. ::ZeroMemory(&m_pArr[m_nSize], sizeof(HPROPSHEETPAGE)*m_nSize);
  72. m_nSize = nAlloc;
  73. }
  74. else
  75. {
  76. m_nSize = 0;
  77. }
  78. }
  79. m_pArr[m_nCount] = hPage;
  80. m_nCount++;
  81. }
  82. ///////////////////////////////////////////////////////////////////////////
  83. // CDsAdminNewObjSiteImpl
  84. BOOL CDsAdminNewObjSiteImpl::_IsPrimarySite()
  85. {
  86. return (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() == m_pSite);
  87. }
  88. STDMETHODIMP CDsAdminNewObjSiteImpl::SetButtons(ULONG nCurrIndex, BOOL bValid)
  89. {
  90. CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz();
  91. return pWiz->SetWizardButtons(m_pSite, nCurrIndex, bValid);
  92. }
  93. STDMETHODIMP CDsAdminNewObjSiteImpl::GetPageCounts(/*OUT*/ LONG* pnTotal,
  94. /*OUT*/ LONG* pnStartIndex)
  95. {
  96. if ( (pnTotal == NULL) || (pnStartIndex == NULL) )
  97. return E_INVALIDARG;
  98. m_pSite->GetSiteManager()->GetWiz()->GetPageCounts(m_pSite, pnTotal,pnStartIndex);
  99. return S_OK;
  100. }
  101. STDMETHODIMP CDsAdminNewObjSiteImpl::CreateNew(LPCWSTR pszName)
  102. {
  103. if (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() != m_pSite)
  104. {
  105. // cannot do if not a primary extension
  106. return E_FAIL;
  107. }
  108. CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz();
  109. return pWiz->CreateNewFromPrimaryExtension(pszName);
  110. }
  111. STDMETHODIMP CDsAdminNewObjSiteImpl::Commit()
  112. {
  113. if (m_pSite->GetSiteManager()->GetPrimaryExtensionSite() != m_pSite)
  114. {
  115. // cannot do if not a primary extension
  116. return E_FAIL;
  117. }
  118. if (m_pSite->GetHPageArr()->GetCount() > 1)
  119. {
  120. // valid only if the primary extension has one page only
  121. return E_FAIL;
  122. }
  123. CCreateNewObjectWizardBase* pWiz = m_pSite->GetSiteManager()->GetWiz();
  124. if (pWiz->HasFinishPage())
  125. {
  126. // if we have the finish page, the finish page must handle it
  127. return E_FAIL;
  128. }
  129. // trigger the finish code
  130. return (pWiz->OnFinish() ? S_OK : E_FAIL);
  131. }
  132. ///////////////////////////////////////////////////////////////////////////
  133. // CWizExtensionSite
  134. // static function
  135. BOOL CALLBACK FAR CWizExtensionSite::_OnAddPage(HPROPSHEETPAGE hsheetpage, LPARAM lParam)
  136. {
  137. TRACE(L"CWizExtensionSite::_OnAddPage(HPROPSHEETPAGE = 0x%x, lParam = 0x%x)\n",
  138. hsheetpage, lParam);
  139. CWizExtensionSite* pThis = (CWizExtensionSite*)lParam;
  140. pThis->m_pageArray.AddHPage(hsheetpage);
  141. return TRUE;
  142. }
  143. HRESULT CWizExtensionSite::InitializeExtension(GUID* pGuid)
  144. {
  145. ASSERT(m_pSiteImplComObject == NULL);
  146. ASSERT(pGuid != NULL);
  147. WCHAR szBuf[256];
  148. StringFromGUID2(*(pGuid), szBuf, 256);
  149. TRACE(L"CWizExtensionSite::InitializeExtension( Guid = %s,\n", szBuf);
  150. // create extension COM object
  151. HRESULT hr = ::CoCreateInstance(*pGuid, NULL, CLSCTX_INPROC_SERVER,
  152. IID_IDsAdminNewObjExt, (void**)(&m_spIDsAdminNewObjExt));
  153. if (FAILED(hr))
  154. {
  155. TRACE(L"CoCreateInstance() failed, hr = 0x%x\n", hr);
  156. return hr;
  157. }
  158. // create a CDsAdminNewObjSiteImpl COM object
  159. ASSERT(m_pSiteImplComObject == NULL);
  160. CComObject<CDsAdminNewObjSiteImpl>::CreateInstance(&m_pSiteImplComObject);
  161. if (m_pSiteImplComObject == NULL)
  162. {
  163. TRACE(L"CComObject<CDsAdminNewObjSiteImpl>::CreateInstance() failed\n");
  164. return E_OUTOFMEMORY;
  165. }
  166. // fully construct the object
  167. hr = m_pSiteImplComObject->FinalConstruct();
  168. if (FAILED(hr))
  169. {
  170. TRACE(L"CComObject<CDsAdminNewObjSiteImpl>::FinalConstruct failed hr = 0x%x\n", hr);
  171. // ref counting not yet into play, just use operator delete
  172. delete m_pSiteImplComObject;
  173. m_pSiteImplComObject = NULL;
  174. return hr;
  175. }
  176. // object has ref count == 0, need to add ref
  177. // no smart pointer, ref counting on m_pSiteImplComObject
  178. IDsAdminNewObj* pDsAdminNewObj = NULL;
  179. m_pSiteImplComObject->QueryInterface(IID_IDsAdminNewObj, (void**)&pDsAdminNewObj);
  180. ASSERT(pDsAdminNewObj != NULL);
  181. // now ref count == 1
  182. // set back pointer to ourselves
  183. m_pSiteImplComObject->Init(this);
  184. // initialize the object
  185. CCreateNewObjectWizardBase* pWiz = GetSiteManager()->GetWiz();
  186. ASSERT(pWiz != NULL);
  187. CNewADsObjectCreateInfo* pInfo = pWiz->GetInfo();
  188. ASSERT(pInfo != NULL);
  189. // create a temporary struct on the stack
  190. DSA_NEWOBJ_DISPINFO dispinfo;
  191. ZeroMemory(&dispinfo, sizeof(DSA_NEWOBJ_DISPINFO));
  192. dispinfo.dwSize = sizeof(DSA_NEWOBJ_DISPINFO);
  193. dispinfo.hObjClassIcon = pWiz->GetClassIcon();
  194. dispinfo.lpszWizTitle = const_cast<LPTSTR>(pWiz->GetCaption());
  195. dispinfo.lpszContDisplayName = const_cast<LPTSTR>(pWiz->GetInfo()->GetContainerCanonicalName());
  196. TRACE(_T("dispinfo.dwSize = %d\n"), dispinfo.dwSize);
  197. TRACE(_T("dispinfo.hObjClassIcon = 0x%x\n"), dispinfo.hObjClassIcon);
  198. TRACE(_T("dispinfo.lpszWizTitle = <%s>\n"), dispinfo.lpszWizTitle);
  199. TRACE(_T("dispinfo.lpszContDisplayName = <%s>\n"), dispinfo.lpszContDisplayName);
  200. TRACE(L"\ncalling m_spIDsAdminWizExt->Initialize()\n");
  201. hr = m_spIDsAdminNewObjExt->Initialize(
  202. pInfo->m_pIADsContainer,
  203. pInfo->GetCopyFromObject(),
  204. pInfo->m_pszObjectClass,
  205. pDsAdminNewObj,
  206. &dispinfo
  207. );
  208. if (FAILED(hr))
  209. {
  210. TRACE(L"m_spIDsAdminNewObjExt->Initialize() failed hr = 0x%x\n", hr);
  211. return hr;
  212. }
  213. // collect property pages
  214. return m_spIDsAdminNewObjExt->AddPages(_OnAddPage, (LPARAM)this);
  215. }
  216. BOOL CWizExtensionSite::GetSummaryInfo(CString& s)
  217. {
  218. CComBSTR bstr;
  219. HRESULT hr = GetNewObjExt()->GetSummaryInfo(&bstr);
  220. if (SUCCEEDED(hr) && bstr != NULL)
  221. {
  222. s += bstr;
  223. s += L"\n";
  224. return TRUE;
  225. }
  226. return FALSE;
  227. }
  228. ///////////////////////////////////////////////////////////////////////////
  229. // CWizExtensionSiteManager
  230. HRESULT CWizExtensionSiteManager::CreatePrimaryExtension(GUID* pGuid,
  231. IADsContainer*,
  232. LPCWSTR)
  233. {
  234. ASSERT(m_pPrimaryExtensionSite == NULL);
  235. m_pPrimaryExtensionSite = new CWizExtensionSite(this);
  236. if (m_pPrimaryExtensionSite == NULL)
  237. return E_OUTOFMEMORY;
  238. // initialize COM object
  239. HRESULT hr = m_pPrimaryExtensionSite->InitializeExtension(pGuid);
  240. if (FAILED(hr))
  241. {
  242. delete m_pPrimaryExtensionSite;
  243. m_pPrimaryExtensionSite = NULL;
  244. return hr;
  245. }
  246. // make sure it provided at least a page
  247. if (m_pPrimaryExtensionSite->GetHPageArr()->GetCount() == 0)
  248. {
  249. hr = E_INVALIDARG;
  250. delete m_pPrimaryExtensionSite;
  251. m_pPrimaryExtensionSite = NULL;
  252. }
  253. return hr;
  254. }
  255. HRESULT CWizExtensionSiteManager::CreateExtensions(GUID* aCreateWizExtGUIDArr, ULONG nCount,
  256. IADsContainer*,
  257. LPCWSTR lpszClassName)
  258. {
  259. HRESULT hr;
  260. TRACE(L"CWizExtensionSiteManager::CreateExtensions(_, nCount = %d, _ , lpszClassName = %s\n",
  261. nCount,lpszClassName);
  262. for (ULONG i=0; i<nCount; i++)
  263. {
  264. CWizExtensionSite* pSite = new CWizExtensionSite(this);
  265. if (pSite == NULL)
  266. {
  267. hr = E_OUTOFMEMORY;
  268. break;
  269. }
  270. hr = pSite->InitializeExtension(&(aCreateWizExtGUIDArr[i]));
  271. if (FAILED(hr))
  272. {
  273. TRACE(L"pSite->InitializeExtension() failed hr = 0x%x", hr);
  274. delete pSite;
  275. }
  276. else
  277. {
  278. m_extensionSiteList.AddTail(pSite);
  279. }
  280. }
  281. TRACE(L"m_extensionSiteList.GetCount() returned %d\n", m_extensionSiteList.GetCount());
  282. return S_OK;
  283. }
  284. UINT CWizExtensionSiteManager::GetTotalHPageCount()
  285. {
  286. UINT nCount = 0;
  287. for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; )
  288. {
  289. CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos);
  290. nCount += pSite->GetHPageArr()->GetCount();
  291. } // for
  292. return nCount;
  293. }
  294. void CWizExtensionSiteManager::SetObject(IADs* pADsObj)
  295. {
  296. CWizExtensionSite* pPrimarySite = GetPrimaryExtensionSite();
  297. if (pPrimarySite != NULL)
  298. {
  299. pPrimarySite->GetNewObjExt()->SetObject(pADsObj);
  300. }
  301. for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; )
  302. {
  303. CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos);
  304. HRESULT hr = pSite->GetNewObjExt()->SetObject(pADsObj);
  305. ASSERT(SUCCEEDED(hr));
  306. }
  307. }
  308. HRESULT CWizExtensionSiteManager::WriteExtensionData(HWND hWnd, ULONG uContext)
  309. {
  310. for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; )
  311. {
  312. CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos);
  313. HRESULT hr = pSite->GetNewObjExt()->WriteData(hWnd, uContext);
  314. if (FAILED(hr))
  315. return hr;
  316. } // for
  317. return S_OK;
  318. }
  319. HRESULT CWizExtensionSiteManager::NotifyExtensionsOnError(HWND hWnd, HRESULT hr, ULONG uContext)
  320. {
  321. for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; )
  322. {
  323. CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos);
  324. pSite->GetNewObjExt()->OnError(hWnd, hr, uContext);
  325. } // for
  326. return S_OK;
  327. }
  328. void CWizExtensionSiteManager::GetExtensionsSummaryInfo(CString& s)
  329. {
  330. // just go through regular extensions
  331. for (POSITION pos = m_extensionSiteList.GetHeadPosition(); pos != NULL; )
  332. {
  333. CWizExtensionSite* pSite = m_extensionSiteList.GetNext(pos);
  334. pSite->GetSummaryInfo(s);
  335. } // for
  336. }
  337. /////////////////////////////////////////////////////////////////////
  338. // CCreateNewObjectWizardBase
  339. HWND g_hWndHack = NULL;
  340. int CALLBACK CCreateNewObjectWizardBase::PropSheetProc(HWND hwndDlg, UINT uMsg, LPARAM)
  341. {
  342. if (uMsg == PSCB_INITIALIZED)
  343. {
  344. ASSERT(::IsWindow(hwndDlg));
  345. g_hWndHack = hwndDlg;
  346. DWORD dwStyle = GetWindowLong (hwndDlg, GWL_EXSTYLE);
  347. dwStyle &= ~WS_EX_CONTEXTHELP;
  348. SetWindowLong (hwndDlg, GWL_EXSTYLE, dwStyle);
  349. }
  350. return 0;
  351. }
  352. CCreateNewObjectWizardBase::CCreateNewObjectWizardBase(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo)
  353. : m_siteManager(this)
  354. {
  355. memset(&m_psh, 0x0, sizeof(PROPSHEETHEADER));
  356. m_psh.dwSize = sizeof( m_psh );
  357. m_psh.dwFlags = PSH_WIZARD | PSH_PROPTITLE | PSH_USECALLBACK;
  358. m_psh.hInstance = _Module.GetModuleInstance();
  359. m_psh.pszCaption = NULL; // will set later on per page
  360. ASSERT(pNewADsObjectCreateInfo != NULL);
  361. m_pNewADsObjectCreateInfo = pNewADsObjectCreateInfo;
  362. m_psh.hwndParent = m_pNewADsObjectCreateInfo->GetParentHwnd();
  363. m_psh.pfnCallback = PropSheetProc;
  364. m_hWnd = NULL;
  365. m_pFinishPage = NULL;
  366. m_hrReturnValue = S_FALSE; // default is cancel
  367. m_hClassIcon = NULL;
  368. }
  369. CCreateNewObjectWizardBase::~CCreateNewObjectWizardBase()
  370. {
  371. if (m_pFinishPage != NULL)
  372. delete m_pFinishPage;
  373. if (m_hClassIcon)
  374. {
  375. DestroyIcon(m_hClassIcon);
  376. }
  377. }
  378. HRESULT CCreateNewObjectWizardBase::DoModal()
  379. {
  380. TRACE(L"CCreateNewObjectWizardBase::DoModal()\n");
  381. ASSERT(m_pNewADsObjectCreateInfo != NULL);
  382. // load the sheet caption
  383. LoadCaptions();
  384. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  385. // load the extensions, if any
  386. HRESULT hr = m_siteManager.CreateExtensions(
  387. m_pNewADsObjectCreateInfo->GetCreateInfo()->aWizardExtensions,
  388. m_pNewADsObjectCreateInfo->GetCreateInfo()->cWizardExtensions,
  389. m_pNewADsObjectCreateInfo->m_pIADsContainer,
  390. m_pNewADsObjectCreateInfo->m_pszObjectClass);
  391. if (FAILED(hr))
  392. return (hr);
  393. // get the # of primary property pages (excluding the Finish Page)
  394. UINT nBasePagesCount = 0;
  395. if (pPrimarySite != NULL)
  396. {
  397. nBasePagesCount += pPrimarySite->GetHPageArr()->GetCount();
  398. }
  399. else
  400. {
  401. nBasePagesCount += (UINT)m_pages.GetSize();
  402. }
  403. ASSERT(nBasePagesCount > 0);
  404. // get the handle count for the extensions (total for extension property pages)
  405. UINT nExtensionHPagesCount = m_siteManager.GetTotalHPageCount();
  406. // if we have more than one page, add the finish page
  407. UINT nTotalPageCount = nBasePagesCount + nExtensionHPagesCount;
  408. if ( (nBasePagesCount + nExtensionHPagesCount) > 1)
  409. {
  410. m_pFinishPage = new CCreateNewObjectFinishPage;
  411. AddPage(m_pFinishPage);
  412. nTotalPageCount++;
  413. }
  414. // need to allocate a contiguous chunk of memory to pack
  415. // all the property sheet handles
  416. m_psh.nPages = nTotalPageCount;
  417. m_psh.phpage = new HPROPSHEETPAGE[nTotalPageCount];
  418. if (m_psh.phpage)
  419. {
  420. UINT nOffset = 0; // offset where to write to
  421. // add the primary pages first
  422. if (pPrimarySite != NULL)
  423. {
  424. ASSERT(nBasePagesCount > 0);
  425. memcpy(&(m_psh.phpage[nOffset]), pPrimarySite->GetHPageArr()->GetArr(),
  426. sizeof(HPROPSHEETPAGE)*nBasePagesCount);
  427. nOffset += nBasePagesCount;
  428. }
  429. else
  430. {
  431. for (UINT i = 0; i < nBasePagesCount; i++)
  432. {
  433. CCreateNewObjectPageBase* pPage = m_pages[i];
  434. m_psh.phpage[nOffset] = ::MyCreatePropertySheetPage(&(pPage->m_psp));
  435. nOffset++;
  436. } // for
  437. }
  438. // add the extension pages
  439. CWizExtensionSiteList* pSiteList = m_siteManager.GetExtensionSiteList();
  440. for (POSITION pos = pSiteList->GetHeadPosition(); pos != NULL; )
  441. {
  442. CWizExtensionSite* pSite = pSiteList->GetNext(pos);
  443. UINT nCurrCount = pSite->GetHPageArr()->GetCount();
  444. if (nCurrCount > 0)
  445. {
  446. memcpy(&(m_psh.phpage[nOffset]), pSite->GetHPageArr()->GetArr(),
  447. sizeof(HPROPSHEETPAGE)*nCurrCount);
  448. nOffset += nCurrCount;
  449. } // if
  450. } // for
  451. // add the finish page last, if any
  452. if (m_pFinishPage != NULL)
  453. {
  454. ASSERT( nOffset == (nTotalPageCount-1) );
  455. m_psh.phpage[nOffset] = ::MyCreatePropertySheetPage(&(m_pFinishPage->m_psp));
  456. }
  457. // finally, invoke the modal sheet
  458. TRACE(L"::PropertySheet(&m_psh) called with m_psh.nPages = %d\n", m_psh.nPages);
  459. ::PropertySheet(&m_psh);
  460. delete[] m_psh.phpage;
  461. m_psh.phpage = 0;
  462. }
  463. return m_hrReturnValue;
  464. }
  465. void CCreateNewObjectWizardBase::GetPageCounts(CWizExtensionSite* pSite,
  466. /*OUT*/ LONG* pnTotal,
  467. /*OUT*/ LONG* pnStartIndex)
  468. {
  469. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  470. *pnTotal = 0;
  471. // get the # of primary property pages (excluding the Finish Page)
  472. UINT nBasePagesCount = 0;
  473. if (pPrimarySite != NULL)
  474. {
  475. nBasePagesCount += pPrimarySite->GetHPageArr()->GetCount();
  476. }
  477. else
  478. {
  479. nBasePagesCount += (UINT)(m_pages.GetSize()-1); // -1 because we exclude finish page
  480. }
  481. *pnTotal = nBasePagesCount + m_siteManager.GetTotalHPageCount();
  482. if (m_pFinishPage != NULL)
  483. {
  484. (*pnTotal)++;
  485. }
  486. if (pPrimarySite == pSite)
  487. {
  488. *pnStartIndex = 0;
  489. }
  490. else
  491. {
  492. // which site is it?
  493. *pnStartIndex = nBasePagesCount;
  494. CWizExtensionSiteList* pSiteList = m_siteManager.GetExtensionSiteList();
  495. for (POSITION pos = pSiteList->GetHeadPosition(); pos != NULL; )
  496. {
  497. CWizExtensionSite* pCurrSite = pSiteList->GetNext(pos);
  498. if (pCurrSite == pSite)
  499. break; // got it, we are done
  500. // keep adding the previous counts
  501. UINT nCurrCount = pCurrSite->GetHPageArr()->GetCount();
  502. (*pnStartIndex) += nCurrCount;
  503. } // for
  504. } // else
  505. }
  506. HWND CCreateNewObjectWizardBase::GetWnd()
  507. {
  508. if (m_hWnd == NULL)
  509. {
  510. for (int i = 0; i < m_pages.GetSize(); i++)
  511. {
  512. CCreateNewObjectPageBase* pPage = m_pages[i];
  513. if (pPage->m_hWnd != NULL)
  514. {
  515. m_hWnd = ::GetParent(pPage->m_hWnd);
  516. break;
  517. }
  518. } // for
  519. } // if
  520. if (m_hWnd == NULL)
  521. {
  522. m_hWnd = g_hWndHack;
  523. g_hWndHack = NULL;
  524. }
  525. ASSERT(m_hWnd != NULL);
  526. ASSERT(::IsWindow(m_hWnd));
  527. return m_hWnd;
  528. }
  529. void CCreateNewObjectWizardBase::AddPage(CCreateNewObjectPageBase* pPage)
  530. {
  531. m_pages.Add(pPage);
  532. pPage->m_pWiz = this;
  533. }
  534. HRESULT CCreateNewObjectWizardBase::CreateNewFromPrimaryExtension(LPCWSTR pszName)
  535. {
  536. // NOTICE: we call with bAllowCopy = FALSE because
  537. // primary extensions will have to handle the copy semantics
  538. // by themselves
  539. // NOTICE: we pass bSilentError = TRUE because
  540. // primary extensions will have to handle the message for
  541. // creation failure
  542. HRESULT hr = GetInfo()->HrCreateNew(pszName, TRUE /* bSilentError */, FALSE /* bAllowCopy */);
  543. GetInfo()->PGetIADsPtr();
  544. m_siteManager.SetObject(GetInfo()->PGetIADsPtr());
  545. return hr;
  546. }
  547. void CCreateNewObjectWizardBase::SetWizardButtons(
  548. CCreateNewObjectPageBase* pPage, BOOL bValid)
  549. {
  550. ASSERT(pPage != NULL);
  551. if (m_pFinishPage != NULL)
  552. {
  553. ASSERT(m_pages.GetSize() >= 1); // at least finish page
  554. if (pPage == (CCreateNewObjectPageBase*)m_pFinishPage)
  555. {
  556. SetWizardButtonsLast(bValid);
  557. }
  558. else
  559. {
  560. if (m_pages[0] == pPage)
  561. SetWizardButtonsFirst(bValid);
  562. else
  563. SetWizardButtonsMiddle(bValid);
  564. }
  565. }
  566. else
  567. {
  568. // single page wizard
  569. ASSERT(m_pages.GetSize() == 1);
  570. SetWizardOKCancel();
  571. EnableOKButton(bValid);
  572. }
  573. }
  574. HRESULT CCreateNewObjectWizardBase::SetWizardButtons(CWizExtensionSite* pSite,
  575. ULONG nCurrIndex, BOOL bValid)
  576. {
  577. UINT nSitePagesCount = pSite->GetHPageArr()->GetCount();
  578. if (nSitePagesCount == 0)
  579. {
  580. // cannot call from UI less extension
  581. return E_INVALIDARG;
  582. }
  583. if (nCurrIndex >= nSitePagesCount)
  584. {
  585. // out of range
  586. return E_INVALIDARG;
  587. }
  588. // get the handle count for the secondary extensions (total for extension property pages)
  589. UINT nExtensionHPagesCount = m_siteManager.GetTotalHPageCount();
  590. if (m_siteManager.GetPrimaryExtensionSite() == pSite)
  591. {
  592. // called from the primary extension
  593. if ((nSitePagesCount == 1) && (nExtensionHPagesCount == 0))
  594. {
  595. // single page, so we have the OK/Cancel buttons
  596. SetWizardOKCancel();
  597. EnableOKButton(bValid);
  598. }
  599. else
  600. {
  601. // multiple pages
  602. if (nCurrIndex == 0)
  603. SetWizardButtonsFirst(bValid);
  604. else
  605. SetWizardButtonsMiddle(bValid);
  606. }
  607. }
  608. else
  609. {
  610. // called from a secondary extension, we must have the finish page and
  611. // some primary extension or primary page(s), so we are always in the middle
  612. ASSERT(m_pFinishPage != NULL);
  613. SetWizardButtonsMiddle(bValid);
  614. }
  615. return S_OK;
  616. }
  617. void CCreateNewObjectWizardBase::SetObjectForExtensions(CCreateNewObjectPageBase* pPage)
  618. {
  619. ASSERT(pPage != NULL);
  620. ASSERT(pPage != m_pFinishPage);
  621. UINT nPages = (UINT)m_pages.GetSize();
  622. if (m_pFinishPage != NULL)
  623. {
  624. ASSERT(nPages > 1); // at least 1 page + finish
  625. if (pPage == m_pages[nPages-2])
  626. {
  627. // this is the last primary page
  628. // give the ADSI object pointer to all the extensions
  629. m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr());
  630. }
  631. }
  632. else
  633. {
  634. // this is the case of a single primary page, but at least one
  635. // UI-less extension (i.e. no finish page)
  636. ASSERT(nPages == 1); // just this page, no finish page
  637. if (pPage == m_pages[0])
  638. {
  639. // this is the only primary page
  640. // give the ADSI object pointer to all the extensions
  641. m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr());
  642. }
  643. } // if
  644. }
  645. HRESULT CCreateNewObjectWizardBase::WriteData(ULONG uContext)
  646. {
  647. HRESULT hr = S_OK;
  648. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  649. if (uContext == DSA_NEWOBJ_CTX_POSTCOMMIT)
  650. {
  651. // call the post commit on all the data primary pages
  652. if (pPrimarySite != NULL)
  653. {
  654. hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), uContext);
  655. if (FAILED(hr))
  656. hr = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, uContext);
  657. }
  658. else
  659. {
  660. for (int i = 0; i < m_pages.GetSize(); i++)
  661. {
  662. CCreateNewObjectPageBase* pPage = m_pages[i];
  663. if (pPage != m_pFinishPage)
  664. {
  665. CCreateNewObjectDataPage* pDataPage = dynamic_cast<CCreateNewObjectDataPage*>(pPage);
  666. ASSERT(pDataPage != NULL);
  667. hr = pDataPage->OnPostCommit();
  668. if (FAILED(hr))
  669. {
  670. m_siteManager.NotifyExtensionsOnError(GetWnd(), hr, uContext);
  671. break;
  672. }
  673. }
  674. } // for
  675. } // if
  676. } // if
  677. if (uContext == DSA_NEWOBJ_CTX_PRECOMMIT)
  678. {
  679. // call the pre commit on all the data primary pages
  680. // (As per Exchange request)
  681. if (pPrimarySite != NULL)
  682. {
  683. hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), uContext);
  684. if (FAILED(hr))
  685. hr = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, uContext);
  686. }
  687. }
  688. if (SUCCEEDED(hr))
  689. {
  690. // call the extensions to write data
  691. hr = m_siteManager.WriteExtensionData(GetWnd(), uContext);
  692. if (FAILED(hr))
  693. {
  694. if (pPrimarySite != NULL)
  695. {
  696. pPrimarySite->GetNewObjExt()->OnError(GetWnd(),hr, uContext);
  697. }
  698. m_siteManager.NotifyExtensionsOnError(GetWnd(), hr, uContext);
  699. }
  700. }
  701. return hr;
  702. }
  703. void CCreateNewObjectWizardBase::GetSummaryInfoHeader(CString& s)
  704. {
  705. // by default, add just the name of object
  706. CString szFmt;
  707. szFmt.LoadString(IDS_s_CREATE_NEW_SUMMARY_NAME);
  708. CString szBuffer;
  709. szBuffer.Format((LPCWSTR)szFmt, GetInfo()->GetName());
  710. s += szBuffer;
  711. }
  712. void CCreateNewObjectWizardBase::GetSummaryInfo(CString& s)
  713. {
  714. // if we have a primary site, tell it to do it all
  715. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  716. if (pPrimarySite != NULL)
  717. {
  718. // the primary extension has a chance to override
  719. // the default behavior
  720. if (!pPrimarySite->GetSummaryInfo(s))
  721. {
  722. // failed, we put up the default header
  723. GetSummaryInfoHeader(s);
  724. }
  725. }
  726. else
  727. {
  728. GetSummaryInfoHeader(s);
  729. // go first through our pages
  730. for (int i = 0; i < m_pages.GetSize(); i++)
  731. {
  732. CCreateNewObjectPageBase* pPage = m_pages[i];
  733. if (pPage != m_pFinishPage)
  734. {
  735. CString szTemp;
  736. pPage->GetSummaryInfo(szTemp);
  737. if (!szTemp.IsEmpty())
  738. {
  739. s += L"\n";
  740. s += szTemp;
  741. }
  742. }
  743. } // for
  744. s += L"\n";
  745. } // if
  746. // go through the extension pages
  747. m_siteManager.GetExtensionsSummaryInfo(s);
  748. }
  749. HRESULT CCreateNewObjectWizardBase::RecreateObject()
  750. {
  751. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  752. // remove object from backend
  753. HRESULT hr = m_pNewADsObjectCreateInfo->HrDeleteFromBackend();
  754. if (FAILED(hr))
  755. {
  756. ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() != NULL);
  757. // could not delete from backend (possibly for lack of delete right)
  758. HRESULT hrDeleteFail = E_FAIL;
  759. if (pPrimarySite != NULL)
  760. {
  761. hrDeleteFail = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, DSA_NEWOBJ_CTX_CLEANUP);
  762. }
  763. if (FAILED(hrDeleteFail))
  764. {
  765. // put out a warning
  766. ReportErrorEx(m_hWnd,IDS_CANT_DELETE_BAD_NEW_OBJECT,S_OK,
  767. MB_OK, NULL, 0);
  768. }
  769. return hr;
  770. }
  771. // tell all the extensions to release the temporary object
  772. ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() == NULL);
  773. m_siteManager.SetObject(NULL);
  774. if (pPrimarySite != NULL)
  775. {
  776. hr = pPrimarySite->GetNewObjExt()->WriteData(GetWnd(), DSA_NEWOBJ_CTX_CLEANUP);
  777. ASSERT(SUCCEEDED(hr));
  778. if (FAILED(hr))
  779. return hr;
  780. }
  781. else
  782. {
  783. // collect data from the primary pages
  784. // the first of them will do a create new
  785. for (int i = 0; i < m_pages.GetSize(); i++)
  786. {
  787. CCreateNewObjectPageBase* pPage = m_pages[i];
  788. if (pPage != m_pFinishPage)
  789. {
  790. hr = ((CCreateNewObjectDataPage*)pPage)->OnPreCommit(TRUE);
  791. ASSERT(SUCCEEDED(hr));
  792. if (FAILED(hr))
  793. return hr; // some of the primary pages failed
  794. }
  795. } // for
  796. }
  797. // tell the extensions about the new object
  798. ASSERT(m_pNewADsObjectCreateInfo->PGetIADsPtr() != NULL);
  799. m_siteManager.SetObject(m_pNewADsObjectCreateInfo->PGetIADsPtr());
  800. // collect data from extensions
  801. hr = WriteData(DSA_NEWOBJ_CTX_CLEANUP);
  802. return hr;
  803. }
  804. BOOL CCreateNewObjectWizardBase::OnFinish()
  805. {
  806. CWaitCursor wait;
  807. BOOL bRetVal = TRUE; // default is dismiss
  808. // before doing the commit give the extensions a chance to
  809. // write their data
  810. BOOL bPostCommit = FALSE;
  811. HRESULT hr = WriteData(DSA_NEWOBJ_CTX_PRECOMMIT);
  812. if (FAILED(hr))
  813. return FALSE; // do not dismiss
  814. // do the commit to the backend
  815. hr = m_pNewADsObjectCreateInfo->HrSetInfo(TRUE /*fSilentError*/);
  816. if (FAILED(hr))
  817. {
  818. // if present, the primary extension will have to handle the failure
  819. // by displaying an error message
  820. HRESULT hrSetInfoFail = E_FAIL;
  821. CWizExtensionSite* pPrimarySite = m_siteManager.GetPrimaryExtensionSite();
  822. if (pPrimarySite != NULL)
  823. {
  824. hrSetInfoFail = pPrimarySite->GetNewObjExt()->OnError(GetWnd(), hr, DSA_NEWOBJ_CTX_COMMIT);
  825. }
  826. if (FAILED(hrSetInfoFail))
  827. {
  828. // either no primary extension or not handled by it,
  829. // use the internal handler
  830. OnFinishSetInfoFailed(hr);
  831. }
  832. return FALSE; // do not dismiss
  833. }
  834. // start the post commit phase
  835. bPostCommit = TRUE;
  836. m_pNewADsObjectCreateInfo->SetPostCommit(bPostCommit);
  837. hr = m_pNewADsObjectCreateInfo->HrAddDefaultAttributes();
  838. if (FAILED(hr))
  839. return FALSE; // do not dismiss
  840. BOOL bNeedDeleteFromBackend = FALSE;
  841. if (SUCCEEDED(hr))
  842. {
  843. // the commit went well, need to tell the primary pages and
  844. // the extensions to write
  845. hr = WriteData(DSA_NEWOBJ_CTX_POSTCOMMIT);
  846. if (FAILED(hr))
  847. {
  848. bNeedDeleteFromBackend = TRUE;
  849. }
  850. }
  851. m_pNewADsObjectCreateInfo->SetPostCommit(/*bPostCommit*/FALSE); // restore
  852. // failed the post commit, try to remove from
  853. // the backend and recreate a valid temporary object
  854. if (bNeedDeleteFromBackend)
  855. {
  856. ASSERT(bRetVal); // the wizard would be hosed
  857. hr = RecreateObject();
  858. if (FAILED(hr))
  859. {
  860. // we are really up creek
  861. bRetVal = TRUE; //bail out, the m_hrReturnValue will be set below
  862. hr = S_FALSE; // avoid error message in the snapin
  863. }
  864. else
  865. {
  866. // we deleted the committed object, we can keep the wizard up
  867. return FALSE;
  868. }
  869. }
  870. if (bRetVal)
  871. {
  872. // we are actually dismissing the wizard,
  873. // set the hr value that will be returned by the modal wizard call itself
  874. m_hrReturnValue = hr;
  875. }
  876. return bRetVal;
  877. }
  878. void CCreateNewObjectWizardBase::OnFinishSetInfoFailed(HRESULT hr)
  879. {
  880. PVOID apv[1] = {(LPWSTR)m_pNewADsObjectCreateInfo->GetName()};
  881. ReportErrorEx(GetWnd(),IDS_12_GENERIC_CREATION_FAILURE,hr,
  882. MB_OK | MB_ICONERROR, apv, 1);
  883. }
  884. void CCreateNewObjectWizardBase::LoadCaptions()
  885. {
  886. // compute the caption only the first time
  887. if (m_szCaption.IsEmpty())
  888. {
  889. LPCTSTR pszObjectClass = GetInfo()->m_pszObjectClass;
  890. ASSERT(pszObjectClass != NULL);
  891. ASSERT(lstrlen(pszObjectClass) > 0);
  892. WCHAR szFriendlyName[256];
  893. GetInfo()->GetBasePathsInfo()->GetFriendlyClassName(pszObjectClass, szFriendlyName, 256);
  894. UINT nCaptionRes = (GetInfo()->GetCopyFromObject() == NULL) ?
  895. IDS_s_CREATE_NEW : IDS_s_COPY;
  896. m_szCaption.Format(nCaptionRes, szFriendlyName);
  897. ASSERT(!m_szCaption.IsEmpty());
  898. }
  899. if (m_szOKButtonCaption.IsEmpty())
  900. {
  901. m_szOKButtonCaption.LoadString(IDS_WIZARD_OK);
  902. }
  903. }
  904. HICON CCreateNewObjectWizardBase::GetClassIcon()
  905. {
  906. if (m_hClassIcon == NULL)
  907. {
  908. DWORD dwFlags = DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON;
  909. if (GetInfo()->IsContainer())
  910. dwFlags |= DSGIF_DEFAULTISCONTAINER;
  911. m_hClassIcon = GetInfo()->GetBasePathsInfo()->GetIcon(GetInfo()->m_pszObjectClass,
  912. dwFlags, 32,32);
  913. }
  914. return m_hClassIcon;
  915. }
  916. HRESULT CCreateNewObjectWizardBase::InitPrimaryExtension()
  917. {
  918. ASSERT(m_pNewADsObjectCreateInfo != NULL);
  919. HRESULT hr = m_siteManager.CreatePrimaryExtension(
  920. &(m_pNewADsObjectCreateInfo->GetCreateInfo()->clsidWizardPrimaryPage),
  921. m_pNewADsObjectCreateInfo->m_pIADsContainer,
  922. m_pNewADsObjectCreateInfo->m_pszObjectClass);
  923. return hr;
  924. }
  925. /////////////////////////////////////////////////////////////////////
  926. // CIconCtrl
  927. BEGIN_MESSAGE_MAP(CIconCtrl, CStatic)
  928. ON_WM_PAINT()
  929. END_MESSAGE_MAP()
  930. void CIconCtrl::OnPaint()
  931. {
  932. PAINTSTRUCT ps;
  933. CDC* pDC = BeginPaint(&ps);
  934. if (m_hIcon != NULL)
  935. pDC->DrawIcon(0, 0, m_hIcon);
  936. EndPaint(&ps);
  937. }
  938. /////////////////////////////////////////////////////////////////////
  939. // CCreateNewObjectPageBase
  940. #define WM_FORMAT_CAPTION (WM_USER+1)
  941. BEGIN_MESSAGE_MAP(CCreateNewObjectPageBase, CPropertyPageEx_Mine)
  942. ON_MESSAGE(WM_FORMAT_CAPTION, OnFormatCaption )
  943. END_MESSAGE_MAP()
  944. CCreateNewObjectPageBase::CCreateNewObjectPageBase(UINT nIDTemplate)
  945. : CPropertyPageEx_Mine(nIDTemplate)
  946. {
  947. m_pWiz = NULL;
  948. }
  949. BOOL CCreateNewObjectPageBase::OnInitDialog()
  950. {
  951. CPropertyPageEx_Mine::OnInitDialog();
  952. // set the name of the container
  953. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  954. SetDlgItemText(IDC_EDIT_CONTAINER,
  955. pNewADsObjectCreateInfo->GetContainerCanonicalName());
  956. // set the class icon
  957. VERIFY(m_iconCtrl.SubclassDlgItem(IDC_STATIC_ICON, this));
  958. m_iconCtrl.SetIcon(GetWiz()->GetClassIcon());
  959. return TRUE;
  960. }
  961. BOOL CCreateNewObjectPageBase::OnSetActive()
  962. {
  963. BOOL bRet = CPropertyPageEx_Mine::OnSetActive();
  964. PostMessage(WM_FORMAT_CAPTION);
  965. return bRet;
  966. }
  967. LONG CCreateNewObjectPageBase::OnFormatCaption(WPARAM, LPARAM)
  968. {
  969. // set the title of the Wizard window
  970. HWND hWndSheet = ::GetParent(m_hWnd);
  971. ASSERT(::IsWindow(hWndSheet));
  972. ::SetWindowText(hWndSheet, (LPCWSTR)GetWiz()->GetCaption());
  973. return 0;
  974. }
  975. /////////////////////////////////////////////////////////////////////
  976. // CCreateNewObjectDataPage
  977. CCreateNewObjectDataPage::CCreateNewObjectDataPage(UINT nIDTemplate)
  978. : CCreateNewObjectPageBase(nIDTemplate)
  979. {
  980. m_bFirstTimeGetDataCalled = TRUE;
  981. }
  982. BOOL CCreateNewObjectDataPage::OnSetActive()
  983. {
  984. BOOL bValid = FALSE;
  985. if (m_bFirstTimeGetDataCalled)
  986. {
  987. // first time we call, pass the IADs* pIADsCopyFrom pointer we copy from
  988. IADs* pIADsCopyFrom = GetWiz()->GetInfo()->GetCopyFromObject();
  989. bValid = GetData(pIADsCopyFrom);
  990. m_bFirstTimeGetDataCalled = FALSE;
  991. }
  992. else
  993. {
  994. bValid = GetData(NULL);
  995. }
  996. GetWiz()->SetWizardButtons(this, bValid);
  997. return CCreateNewObjectPageBase::OnSetActive();
  998. }
  999. LRESULT CCreateNewObjectDataPage::OnWizardNext()
  1000. {
  1001. CWaitCursor wait;
  1002. // move to next page only if SetData() succeeded
  1003. if (SUCCEEDED(SetData()))
  1004. {
  1005. // if this is the last primary page, notify the extensions
  1006. GetWiz()->SetObjectForExtensions(this);
  1007. return 0; // move to the next page
  1008. }
  1009. return -1; // do not advance
  1010. }
  1011. LRESULT CCreateNewObjectDataPage::OnWizardBack()
  1012. {
  1013. // move to prev page only if SetData() succeeded
  1014. return SUCCEEDED(SetData()) ? 0 : -1;
  1015. }
  1016. BOOL CCreateNewObjectDataPage::OnKillActive()
  1017. {
  1018. // we do not know what page it will jump to, so we
  1019. // set it to the most sensible choice for an extension
  1020. GetWiz()->SetWizardButtonsMiddle(TRUE);
  1021. return CCreateNewObjectPageBase::OnKillActive();
  1022. }
  1023. BOOL CCreateNewObjectDataPage::OnWizardFinish()
  1024. {
  1025. // this method is called only if this page is the
  1026. // last one (that is this is the only primary native page
  1027. // and there are no pages from secondary extensions)
  1028. if (FAILED(SetData()))
  1029. return FALSE;
  1030. // notify the extensions of a new IADs* pointer
  1031. GetWiz()->SetObjectForExtensions(this);
  1032. return GetWiz()->OnFinish();
  1033. }
  1034. /////////////////////////////////////////////////////////////////////
  1035. // CCreateNewObjectFinishPage
  1036. BEGIN_MESSAGE_MAP(CCreateNewObjectFinishPage, CCreateNewObjectPageBase)
  1037. ON_EN_SETFOCUS(IDC_EDIT_SUMMARY, OnSetFocusEdit)
  1038. END_MESSAGE_MAP()
  1039. CCreateNewObjectFinishPage::CCreateNewObjectFinishPage()
  1040. : CCreateNewObjectPageBase(CCreateNewObjectFinishPage::IDD)
  1041. {
  1042. m_bNeedSetFocus = FALSE;
  1043. }
  1044. BOOL CCreateNewObjectFinishPage::OnSetActive()
  1045. {
  1046. // need to collect all info from pages
  1047. // and put it in the summary info edit box
  1048. CString szBuf;
  1049. GetWiz()->GetSummaryInfo(szBuf);
  1050. WriteSummary(szBuf);
  1051. m_bNeedSetFocus = TRUE;
  1052. GetWiz()->SetWizardButtons(this, TRUE);
  1053. return CCreateNewObjectPageBase::OnSetActive();
  1054. }
  1055. BOOL CCreateNewObjectFinishPage::OnKillActive()
  1056. {
  1057. GetWiz()->SetWizardButtonsMiddle(TRUE);
  1058. return CCreateNewObjectPageBase::OnKillActive();
  1059. }
  1060. BOOL CCreateNewObjectFinishPage::OnWizardFinish()
  1061. {
  1062. return GetWiz()->OnFinish();
  1063. }
  1064. void CCreateNewObjectFinishPage::OnSetFocusEdit()
  1065. {
  1066. CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SUMMARY);
  1067. pEdit->SetSel(-1,0, TRUE);
  1068. if (m_bNeedSetFocus)
  1069. {
  1070. m_bNeedSetFocus = FALSE;
  1071. TRACE(_T("Resetting Focus\n"));
  1072. HWND hwndSheet = ::GetParent(m_hWnd);
  1073. ASSERT(::IsWindow(hwndSheet));
  1074. HWND hWndFinishCtrl =::GetDlgItem(hwndSheet, 0x3025);
  1075. ASSERT(::IsWindow(hWndFinishCtrl));
  1076. ::SetFocus(hWndFinishCtrl);
  1077. }
  1078. }
  1079. void CCreateNewObjectFinishPage::WriteSummary(LPCWSTR lpszSummaryText)
  1080. {
  1081. // allocate temporary buffer
  1082. size_t nLen = wcslen(lpszSummaryText) + 1;
  1083. WCHAR* pBuf = new WCHAR[nLen*2];
  1084. if (!pBuf)
  1085. {
  1086. return;
  1087. }
  1088. // change '\n' into '\r\n' sequence
  1089. LPCTSTR pSrc = lpszSummaryText;
  1090. TCHAR* pDest = pBuf;
  1091. while (*pSrc != NULL)
  1092. {
  1093. if ( ( pSrc != lpszSummaryText) &&
  1094. (*(pSrc-1) != TEXT('\r')) && (*pSrc == TEXT('\n')) )
  1095. {
  1096. *(pDest++) = '\r';
  1097. }
  1098. *(pDest++) = *(pSrc++);
  1099. }
  1100. *pDest = NULL; // NULL terminate the destination buffer
  1101. CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SUMMARY);
  1102. pEdit->SetWindowText(pBuf);
  1103. delete[] pBuf;
  1104. pBuf = 0;
  1105. }
  1106. ///////////////////////////////////////////////////////////////////
  1107. // CCreateNewNamedObjectPage
  1108. BEGIN_MESSAGE_MAP(CCreateNewNamedObjectPage, CCreateNewObjectDataPage)
  1109. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange)
  1110. END_MESSAGE_MAP()
  1111. BOOL CCreateNewNamedObjectPage::ValidateName(LPCTSTR)
  1112. {
  1113. return TRUE;
  1114. }
  1115. BOOL CCreateNewNamedObjectPage::OnInitDialog()
  1116. {
  1117. CCreateNewObjectDataPage::OnInitDialog();
  1118. Edit_LimitText (GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, MAX_RDN_SIZE);
  1119. SetDlgItemText(IDC_EDIT_OBJECT_NAME, GetWiz()->GetInfo()->m_strDefaultObjectName);
  1120. return TRUE;
  1121. }
  1122. BOOL CCreateNewNamedObjectPage::GetData(IADs*)
  1123. {
  1124. return !m_strName.IsEmpty();
  1125. }
  1126. void CCreateNewNamedObjectPage::OnNameChange()
  1127. {
  1128. GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strName);
  1129. m_strName.TrimLeft();
  1130. m_strName.TrimRight();
  1131. // Enable the OK button only if the name is not empty
  1132. GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty());
  1133. }
  1134. HRESULT CCreateNewNamedObjectPage::SetData(BOOL)
  1135. {
  1136. if ( !ValidateName( m_strName ) )
  1137. return E_INVALIDARG;
  1138. // Store the object name in the temporary storage
  1139. HRESULT hr = GetWiz()->GetInfo()->HrCreateNew(m_strName);
  1140. return hr;
  1141. }
  1142. ///////////////////////////////////////////////////////////////
  1143. ///////////////////////////////////////////////////////////////
  1144. // NEW CN UNC WIZARD
  1145. BEGIN_MESSAGE_MAP(CCreateNewVolumePage, CCreateNewObjectDataPage)
  1146. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange)
  1147. ON_EN_CHANGE(IDC_EDIT_UNC_PATH, OnPathChange)
  1148. END_MESSAGE_MAP()
  1149. CCreateNewVolumePage::CCreateNewVolumePage()
  1150. : CCreateNewObjectDataPage(CCreateNewVolumePage::IDD)
  1151. {
  1152. }
  1153. BOOL CCreateNewVolumePage::OnInitDialog()
  1154. {
  1155. CCreateNewObjectDataPage::OnInitDialog();
  1156. SetDlgItemText(IDC_EDIT_OBJECT_NAME, GetWiz()->GetInfo()->m_strDefaultObjectName);
  1157. Edit_LimitText(GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, 64);
  1158. Edit_LimitText (GetDlgItem(IDC_EDIT_UNC_PATH)->m_hWnd, MAX_PATH - 1);
  1159. return TRUE;
  1160. }
  1161. void CCreateNewVolumePage::OnNameChange()
  1162. {
  1163. GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strName);
  1164. m_strName.TrimLeft();
  1165. m_strName.TrimRight();
  1166. _UpdateUI();
  1167. }
  1168. void CCreateNewVolumePage::OnPathChange()
  1169. {
  1170. GetDlgItemText(IDC_EDIT_UNC_PATH, OUT m_strUncPath);
  1171. m_strUncPath.TrimLeft();
  1172. m_strUncPath.TrimRight();
  1173. _UpdateUI();
  1174. }
  1175. void CCreateNewVolumePage::_UpdateUI()
  1176. {
  1177. //
  1178. // Enable the OK button only if both name and path are not empty and it is a valid
  1179. // UNC path
  1180. //
  1181. BOOL bIsValidShare = FALSE;
  1182. DWORD dwPathType = 0;
  1183. if (!I_NetPathType(NULL, (PWSTR)(PCWSTR)m_strUncPath, &dwPathType, 0) && dwPathType == ITYPE_UNC)
  1184. {
  1185. bIsValidShare = TRUE;
  1186. }
  1187. GetWiz()->SetWizardButtons(this, !m_strName.IsEmpty() && bIsValidShare);
  1188. }
  1189. BOOL CCreateNewVolumePage::GetData(IADs*)
  1190. {
  1191. return !m_strName.IsEmpty() && !m_strUncPath.IsEmpty();
  1192. }
  1193. HRESULT CCreateNewVolumePage::SetData(BOOL)
  1194. {
  1195. // Store the object name in the temporary storage
  1196. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  1197. HRESULT hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName);
  1198. if (FAILED(hr))
  1199. {
  1200. return hr;
  1201. }
  1202. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_uNCName), m_strUncPath);
  1203. ASSERT(SUCCEEDED(hr));
  1204. return hr;
  1205. }
  1206. CCreateNewVolumeWizard:: CCreateNewVolumeWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) :
  1207. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  1208. {
  1209. AddPage(&m_page1);
  1210. }
  1211. ///////////////////////////////////////////////////////////////
  1212. ///////////////////////////////////////////////////////////////
  1213. // NEW PRINT QUEUE WIZARD
  1214. BEGIN_MESSAGE_MAP(CCreateNewPrintQPage, CCreateNewObjectDataPage)
  1215. ON_EN_CHANGE(IDC_EDIT_UNC_PATH, OnPathChange)
  1216. END_MESSAGE_MAP()
  1217. CCreateNewPrintQPage::CCreateNewPrintQPage()
  1218. : CCreateNewObjectDataPage(CCreateNewPrintQPage::IDD)
  1219. {
  1220. }
  1221. BOOL CCreateNewPrintQPage::GetData(IADs*)
  1222. {
  1223. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  1224. CComPtr<IADs> spObj;
  1225. HRESULT hr = pNewADsObjectCreateInfo->m_pIADsContainer->QueryInterface(
  1226. IID_IADs, (void **)&spObj);
  1227. if (SUCCEEDED(hr))
  1228. {
  1229. CComBSTR bsPath;
  1230. spObj->get_ADsPath (&bsPath);
  1231. m_strContainer = bsPath;
  1232. }
  1233. return FALSE;
  1234. }
  1235. void CCreateNewPrintQPage::OnPathChange()
  1236. {
  1237. GetDlgItemText(IDC_EDIT_UNC_PATH, OUT m_strUncPath);
  1238. m_strUncPath.TrimLeft();
  1239. m_strUncPath.TrimRight();
  1240. _UpdateUI();
  1241. }
  1242. void CCreateNewPrintQPage::_UpdateUI()
  1243. {
  1244. // Enable the OK button only if both name and path are not empty
  1245. GetWiz()->SetWizardButtons(this, !m_strUncPath.IsEmpty());
  1246. }
  1247. HRESULT CCreateNewPrintQPage::SetData(BOOL bSilent)
  1248. {
  1249. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  1250. CWaitCursor CWait;
  1251. HINSTANCE hWinspool = NULL;
  1252. BOOL (*pfnPublishPrinter)(HWND, PCWSTR, PCWSTR, PCWSTR, PWSTR *, DWORD);
  1253. hWinspool = LoadLibrary(L"Winspool.drv");
  1254. if (!hWinspool)
  1255. {
  1256. INT Result2 = GetLastError();
  1257. if (!bSilent)
  1258. {
  1259. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath};
  1260. ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2),
  1261. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1262. }
  1263. return HRESULT_FROM_WIN32(Result2);
  1264. }
  1265. pfnPublishPrinter = (BOOL (*)(HWND, PCWSTR, PCWSTR, PCWSTR, PWSTR *, DWORD))
  1266. GetProcAddress(hWinspool, (LPCSTR) 217);
  1267. if (!pfnPublishPrinter)
  1268. {
  1269. INT Result2 = GetLastError();
  1270. if (!bSilent)
  1271. {
  1272. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath};
  1273. ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2),
  1274. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1275. }
  1276. FreeLibrary(hWinspool);
  1277. return HRESULT_FROM_WIN32(Result2);
  1278. }
  1279. BOOL Result = pfnPublishPrinter ( m_hWnd,
  1280. (LPCWSTR)m_strUncPath,
  1281. (LPCWSTR)m_strContainer,
  1282. (LPCWSTR)NULL,
  1283. &m_pwszNewObj,
  1284. PUBLISHPRINTER_QUERY);
  1285. FreeLibrary(hWinspool);
  1286. if (!Result)
  1287. {
  1288. INT Result2 = GetLastError();
  1289. if (Result2 == ERROR_INVALID_LEVEL)
  1290. {
  1291. if (!bSilent)
  1292. {
  1293. ReportErrorEx (::GetParent(m_hWnd),IDS_CANT_CREATE_NT5_PRINTERS,S_OK,
  1294. MB_OK, NULL, 0);
  1295. }
  1296. }
  1297. else
  1298. {
  1299. if (!bSilent)
  1300. {
  1301. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath};
  1302. ReportErrorEx (::GetParent(m_hWnd),IDS_12_FAILED_TO_CREATE_PRINTER,HRESULT_FROM_WIN32(Result2),
  1303. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1304. }
  1305. }
  1306. return HRESULT_FROM_WIN32(Result2);
  1307. }
  1308. else
  1309. {
  1310. IADs* pIADs = NULL;
  1311. HRESULT hr = DSAdminOpenObject(m_pwszNewObj,
  1312. IID_IADs,
  1313. (void **)&pIADs,
  1314. TRUE /*bServer*/);
  1315. GlobalFree(m_pwszNewObj);
  1316. m_pwszNewObj = NULL;
  1317. if (SUCCEEDED(hr))
  1318. {
  1319. pNewADsObjectCreateInfo->SetIADsPtr(pIADs);
  1320. pIADs->Release(); // addref'd by the above Set()
  1321. }
  1322. else
  1323. {
  1324. if (!bSilent)
  1325. {
  1326. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strUncPath};
  1327. ReportErrorEx (m_hWnd,IDS_12_FAILED_TO_ACCESS_PRINTER,hr,
  1328. MB_OK | MB_ICONERROR, apv, 1);
  1329. }
  1330. return hr;
  1331. }
  1332. }
  1333. return S_OK;
  1334. }
  1335. CCreateNewPrintQWizard:: CCreateNewPrintQWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) :
  1336. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  1337. {
  1338. AddPage(&m_page1);
  1339. }
  1340. ///////////////////////////////////////////////////////////////
  1341. ///////////////////////////////////////////////////////////////
  1342. // NEW COMPUTER WIZARD
  1343. BEGIN_MESSAGE_MAP(CCreateNewComputerPage, CCreateNewObjectDataPage)
  1344. ON_EN_CHANGE(IDC_EDIT_DNS_NAME, OnNameChange)
  1345. ON_EN_CHANGE(IDC_EDIT_SAM_NAME, OnSamNameChange)
  1346. ON_BN_CLICKED(IDC_CHANGE_PRINCIPAL_BUTTON, OnChangePrincipalButton)
  1347. END_MESSAGE_MAP()
  1348. CCreateNewComputerPage::CCreateNewComputerPage()
  1349. : CCreateNewObjectDataPage(CCreateNewComputerPage::IDD)
  1350. {
  1351. }
  1352. BOOL CCreateNewComputerPage::OnInitDialog()
  1353. {
  1354. Edit_LimitText (GetDlgItem(IDC_EDIT_DNS_NAME)->m_hWnd, 63);
  1355. Edit_LimitText (GetDlgItem(IDC_EDIT_SAM_NAME)->m_hWnd, 15);
  1356. CCreateNewObjectDataPage::OnInitDialog();
  1357. CString szDefault;
  1358. szDefault.LoadString(IDS_NEW_COMPUTER_PRINCIPAL_DEFAULT);
  1359. SetDlgItemText(IDC_PRINCIPAL_EDIT, szDefault);
  1360. return TRUE;
  1361. }
  1362. BOOL CCreateNewComputerPage::GetData(IADs*)
  1363. {
  1364. return !m_strName.IsEmpty(); //we need a computer name
  1365. }
  1366. inline LPWSTR WINAPI MyA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
  1367. {
  1368. ATLASSERT(lpa != NULL);
  1369. ATLASSERT(lpw != NULL);
  1370. // verify that no illegal character present
  1371. // since lpw was allocated based on the size of lpa
  1372. // don't worry about the number of chars
  1373. lpw[0] = '\0';
  1374. MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
  1375. return lpw;
  1376. }
  1377. #define A2W_OEM(lpa) (\
  1378. ((_lpaMine = lpa) == NULL) ? NULL : (\
  1379. _convert = (lstrlenA(_lpaMine)+1),\
  1380. MyA2WHelper((LPWSTR) alloca(_convert*2), _lpaMine, _convert, CP_OEMCP)))
  1381. void _UnicodeToOemConvert(IN PCWSTR pszUnicode, OUT CString& szOemUnicode)
  1382. {
  1383. USES_CONVERSION;
  1384. // add this for the macro to work
  1385. PCSTR _lpaMine = NULL;
  1386. // convert to CHAR OEM
  1387. int nLen = lstrlen(pszUnicode);
  1388. PSTR pszOemAnsi = new CHAR[3*(nLen+1)]; // more, to be sure...
  1389. if (pszOemAnsi)
  1390. {
  1391. CharToOem(pszUnicode, pszOemAnsi);
  1392. // convert it back to WCHAR on OEM CP
  1393. szOemUnicode = A2W_OEM(pszOemAnsi);
  1394. delete[] pszOemAnsi;
  1395. pszOemAnsi = 0;
  1396. }
  1397. }
  1398. void CCreateNewComputerPage::OnNameChange()
  1399. {
  1400. GetDlgItemText(IDC_EDIT_DNS_NAME, OUT m_strName);
  1401. m_strName.TrimLeft();
  1402. m_strName.TrimRight();
  1403. // generate a SAM account name from the name
  1404. CONST DWORD computerNameLen = 32;
  1405. DWORD Len = computerNameLen;
  1406. WCHAR szDownLevel[computerNameLen];
  1407. if (m_strName.IsEmpty())
  1408. {
  1409. Len = 0;
  1410. }
  1411. else
  1412. {
  1413. // generate the SAM account name from CN
  1414. // run through the OEM conversion, just to
  1415. // behave the same way as typing in the OEM
  1416. // edit box
  1417. CString szOemUnicode;
  1418. _UnicodeToOemConvert(m_strName, szOemUnicode);
  1419. //TRACE(L"szOemUnicode = %s\n", (LPCWSTR)szOemUnicode);
  1420. // run through the DNS validation
  1421. if (!DnsHostnameToComputerName((LPWSTR)(LPCWSTR)szOemUnicode, szDownLevel, &Len))
  1422. {
  1423. Len = 0;
  1424. }
  1425. }
  1426. if (Len > 0)
  1427. {
  1428. m_strSamName = szDownLevel;
  1429. }
  1430. else
  1431. {
  1432. m_strSamName.Empty();
  1433. }
  1434. SetDlgItemText(IDC_EDIT_SAM_NAME, m_strSamName);
  1435. GetWiz()->SetWizardButtons(this,
  1436. !m_strName.IsEmpty() && !m_strSamName.IsEmpty());
  1437. }
  1438. void CCreateNewComputerPage::OnSamNameChange()
  1439. {
  1440. GetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strSamName);
  1441. GetWiz()->SetWizardButtons(this,
  1442. !m_strName.IsEmpty() && !m_strSamName.IsEmpty());
  1443. }
  1444. HRESULT CCreateNewComputerPage::_ValidateSamName()
  1445. {
  1446. ASSERT(!m_strSamName.IsEmpty());
  1447. // prep name for error if needed
  1448. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName};
  1449. CONST DWORD computerNameLen = 32;
  1450. DWORD Len = computerNameLen;
  1451. WCHAR szDownLevel[computerNameLen];
  1452. UINT status = 0;
  1453. UINT answer = IDNO;
  1454. NET_API_STATUS netstatus = I_NetNameValidate( 0,
  1455. (LPWSTR)(LPCWSTR)m_strSamName,
  1456. NAMETYPE_COMPUTER,
  1457. 0);
  1458. if (netstatus != NERR_Success) {
  1459. ReportErrorEx(m_hWnd,IDS_12_INVALID_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(netstatus),
  1460. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1461. return HRESULT_FROM_WIN32(netstatus);
  1462. }
  1463. // NTRAID#NTBUG9-472020-2002/01/16-ronmart-switched from DnsValidateDnsName to DnsValidateName
  1464. // NTRAID#NTBUG9-651865-2002/07/16-JeffJon-When Ron made the switch to use DnsValidateName
  1465. // the DnsNameHostnameLabel flag should have been used instead of the DnsNameDomainLabel flag
  1466. status = DnsValidateName_W((LPWSTR)(LPCWSTR)m_strSamName, DnsNameHostnameLabel);
  1467. if (status == DNS_ERROR_NON_RFC_NAME) {
  1468. answer = ReportErrorEx(m_hWnd,IDS_12_NON_RFC_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(status),
  1469. MB_YESNO | MB_ICONWARNING, apv, 1, 0, FALSE);
  1470. if (answer == IDNO) {
  1471. return HRESULT_FROM_WIN32(status);
  1472. }
  1473. } else {
  1474. if (status != ERROR_SUCCESS) {
  1475. ReportErrorEx(m_hWnd,IDS_12_INVALID_SAM_COMPUTER_NAME,HRESULT_FROM_WIN32(status),
  1476. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1477. return HRESULT_FROM_WIN32(status);
  1478. }
  1479. }
  1480. if (m_strSamName.Find(L".") >= 0) {
  1481. ReportErrorEx(m_hWnd,IDS_12_SAM_COMPUTER_NAME_DOTTED,S_OK/*ignored*/,
  1482. MB_OK | MB_ICONERROR, apv, 1);
  1483. return HRESULT_FROM_WIN32(DNS_STATUS_DOTTED_NAME);
  1484. }
  1485. // further validate the SAM account name, to make sure it did not get changed
  1486. BOOL bValidSamName =
  1487. DnsHostnameToComputerName((LPWSTR)(LPCWSTR)m_strSamName, szDownLevel, &Len);
  1488. TRACE(L"DnsHostnameToComputerName(%s) returned szDownLevel = %s and bValidSamName = 0x%x\n",
  1489. (LPCWSTR)m_strSamName, szDownLevel, bValidSamName);
  1490. if (!bValidSamName || (_wcsicmp(m_strSamName, szDownLevel) != 0))
  1491. {
  1492. ReportErrorEx(m_hWnd,IDS_12_SAM_COMPUTER_NAME_NOT_VALIDATED, S_OK/*ignored*/,
  1493. MB_OK | MB_ICONERROR, apv, 1);
  1494. return E_FAIL;
  1495. }
  1496. return S_OK;
  1497. }
  1498. HRESULT CCreateNewComputerPage::_ValidateName()
  1499. {
  1500. // prep name for error if needed
  1501. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName};
  1502. UINT status = 0;
  1503. UINT answer = IDNO;
  1504. NET_API_STATUS netstatus = I_NetNameValidate( 0,
  1505. (LPWSTR)(LPCWSTR)m_strName,
  1506. NAMETYPE_COMPUTER,
  1507. 0);
  1508. if (netstatus != NERR_Success) {
  1509. ReportErrorEx(m_hWnd,IDS_12_INVALID_COMPUTER_NAME,HRESULT_FROM_WIN32(netstatus),
  1510. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1511. return HRESULT_FROM_WIN32(netstatus);
  1512. }
  1513. // NTRAID#NTBUG9-472020-2002/01/16-ronmart-switched from DnsValidateDnsName to DnsValidateName
  1514. // NTRAID#NTBUG9-651865-2002/07/16-JeffJon-When Ron made the switch to use DnsValidateName
  1515. // the DnsNameHostnameLabel flag should have been used instead of the DnsNameDomainLabel flag
  1516. status = DnsValidateName_W((LPWSTR)(LPCWSTR)m_strName, DnsNameHostnameLabel);
  1517. if (status == DNS_ERROR_NON_RFC_NAME) {
  1518. answer = ReportErrorEx(m_hWnd,IDS_12_NON_RFC_COMPUTER_NAME,HRESULT_FROM_WIN32(status),
  1519. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2, apv, 1, 0, FALSE);
  1520. if (answer == IDNO) {
  1521. return HRESULT_FROM_WIN32(status);
  1522. }
  1523. } else {
  1524. if (status != ERROR_SUCCESS) {
  1525. ReportErrorEx(m_hWnd,IDS_12_INVALID_COMPUTER_NAME,HRESULT_FROM_WIN32(status),
  1526. MB_OK | MB_ICONERROR, apv, 1, 0, FALSE);
  1527. return HRESULT_FROM_WIN32(status);
  1528. }
  1529. }
  1530. if (m_strName.Find(L".") >= 0) {
  1531. ReportErrorEx(m_hWnd,IDS_12_COMPUTER_NAME_DOTTED,S_OK/*ignored*/,
  1532. MB_OK | MB_ICONERROR, apv, 1);
  1533. return HRESULT_FROM_WIN32(DNS_STATUS_DOTTED_NAME);
  1534. }
  1535. return S_OK;
  1536. }
  1537. HRESULT CCreateNewComputerPage::SetData(BOOL)
  1538. {
  1539. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  1540. // name validation
  1541. HRESULT hr = _ValidateName();
  1542. if (FAILED(hr))
  1543. {
  1544. TRACE(L"_ValidateName() failed\n");
  1545. return hr;
  1546. }
  1547. hr = _ValidateSamName();
  1548. if (FAILED(hr))
  1549. {
  1550. TRACE(L"_ValidateSamName() failed\n");
  1551. return hr;
  1552. }
  1553. // do object creation
  1554. hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName);
  1555. if (FAILED(hr))
  1556. {
  1557. return hr;
  1558. }
  1559. // create the ADSI attribute by adding $ at the end
  1560. CString szTemp = m_strSamName + L"$";
  1561. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_samAccountName), szTemp);
  1562. // set the account type and the desired flags
  1563. LONG lFlags = UF_ACCOUNTDISABLE | UF_PASSWD_NOTREQD;
  1564. if (IsDlgButtonChecked(IDC_NT4_BDC_CHECK))
  1565. {
  1566. lFlags |= UF_SERVER_TRUST_ACCOUNT;
  1567. }
  1568. else
  1569. {
  1570. lFlags |= UF_WORKSTATION_TRUST_ACCOUNT;
  1571. }
  1572. hr = pNewADsObjectCreateInfo->HrAddVariantLong(CComBSTR(gsz_userAccountControl), lFlags);
  1573. ASSERT(SUCCEEDED(hr));
  1574. return hr;
  1575. }
  1576. HRESULT CCreateNewComputerPage::OnPostCommit(BOOL bSilent)
  1577. {
  1578. HRESULT hr;
  1579. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  1580. IADs * pIADs = NULL;
  1581. IADsUser * pIADsUser = NULL;
  1582. BOOL bSetPasswordOK = FALSE;
  1583. BOOL bSetSecurityOK = FALSE;
  1584. //prepare for error message, if needed
  1585. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName};
  1586. // The object was created successfully, so try to update some other attributes
  1587. // try to set the password
  1588. pIADs = pNewADsObjectCreateInfo->PGetIADsPtr();
  1589. ASSERT(pIADs != NULL);
  1590. hr = pIADs->QueryInterface(IID_IADsUser, OUT (void **)&pIADsUser);
  1591. if (FAILED(hr) && !bSilent)
  1592. {
  1593. ASSERT(FALSE); // should never get here in normal operations
  1594. ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr,
  1595. MB_OK | MB_ICONERROR, NULL, 0);
  1596. }
  1597. else
  1598. {
  1599. ASSERT(pIADsUser != NULL);
  1600. if (IsDlgButtonChecked(IDC_NT4_CHECK))
  1601. {
  1602. // NT 4 password, "$<computername>"
  1603. CString szPassword;
  1604. szPassword = m_strSamName;
  1605. szPassword = szPassword.Left(14);
  1606. INT loc = szPassword.Find(L"$");
  1607. if (loc > 0) {
  1608. szPassword = szPassword.Left(loc);
  1609. }
  1610. // NTRAID#NTBUG9-483038-10/18/2001-JeffJon
  1611. // CString::MakeLower() doesn't lower case German characters
  1612. // correctly. Using _wcslwr instead. setlocale must be
  1613. // called before calling _wcslwr so that it properly lowercases
  1614. // extended characters. Store the result and call setlocale
  1615. // again when done to set it back to the original so as not
  1616. // to affect other snapins in the process.
  1617. PWSTR oldLocale = _wsetlocale(LC_ALL, L"");
  1618. CString lowerCaseNewPwd = _wcslwr((LPWSTR)(LPCWSTR)szPassword);
  1619. _wsetlocale(LC_ALL, oldLocale);
  1620. CWaitCursor cwait;
  1621. TRACE(L"Setting NT 4 style password\n");
  1622. hr = pIADsUser->SetPassword(CComBSTR(lowerCaseNewPwd));
  1623. }
  1624. else
  1625. {
  1626. // W2K password, randomly generated. The generated password
  1627. // is not necessarily readable
  1628. CWaitCursor cwait;
  1629. HCRYPTPROV hCryptProv = NULL;
  1630. if (::CryptAcquireContext(&hCryptProv, NULL, NULL,
  1631. PROV_RSA_FULL,
  1632. CRYPT_SILENT|CRYPT_VERIFYCONTEXT))
  1633. {
  1634. int nChars = 14; // password length
  1635. WCHAR* pszPassword = new WCHAR[nChars+1]; // allow one more for NULL
  1636. if (!pszPassword)
  1637. {
  1638. return E_OUTOFMEMORY;
  1639. }
  1640. if (::CryptGenRandom(hCryptProv, (nChars*sizeof(WCHAR)), (BYTE*)pszPassword))
  1641. {
  1642. // there is a VERY REMOTE possibility of a 16 bit
  1643. // pattern of all zeroes that looks like a WCHAR NULL
  1644. // so we check this and we substitute an arbitrary value
  1645. for (int k=0; k<nChars; k++)
  1646. {
  1647. if (pszPassword[k] == NULL)
  1648. pszPassword[k] = 0x1; // arbitrary
  1649. }
  1650. // put a NULL at the end
  1651. pszPassword[nChars] = NULL;
  1652. ASSERT(lstrlen(pszPassword) == nChars);
  1653. TRACE(L"Setting W2K random password\n");
  1654. hr = pIADsUser->SetPassword(CComBSTR(pszPassword));
  1655. }
  1656. else
  1657. {
  1658. // CryptGenRandom() failed
  1659. hr = HRESULT_FROM_WIN32(::GetLastError());
  1660. }
  1661. ::CryptReleaseContext(hCryptProv, 0x0);
  1662. delete[] pszPassword;
  1663. pszPassword = 0;
  1664. }
  1665. else
  1666. {
  1667. // CryptAcquireContext() failed
  1668. hr = HRESULT_FROM_WIN32(::GetLastError());
  1669. }
  1670. } // QI
  1671. if (SUCCEEDED(hr))
  1672. {
  1673. bSetPasswordOK = TRUE;
  1674. }
  1675. else
  1676. {
  1677. if (!bSilent)
  1678. {
  1679. ReportErrorEx (::GetParent(m_hWnd),IDS_12_CANT_SET_COMP_PWD,hr,
  1680. MB_OK | MB_ICONWARNING, apv, 1);
  1681. }
  1682. }
  1683. pIADsUser->Release();
  1684. }
  1685. // try to write ACL
  1686. hr = S_OK;
  1687. if (m_securityPrincipalSidHolder.Get() == NULL)
  1688. {
  1689. // no need to set the ACL, we are fine
  1690. bSetSecurityOK = TRUE;
  1691. }
  1692. else
  1693. {
  1694. CWaitCursor cwait;
  1695. hr = SetSecurity();
  1696. }
  1697. if (SUCCEEDED(hr))
  1698. {
  1699. bSetSecurityOK = TRUE;
  1700. }
  1701. else
  1702. {
  1703. TRACE1("INFO: Unable to set security for computer %s.\n", (LPCTSTR)m_strName);
  1704. if (!bSilent)
  1705. {
  1706. ReportErrorEx (::GetParent(m_hWnd),IDS_12_UNABLE_TO_WRITE_COMP_ACL,hr,
  1707. MB_OK | MB_ICONWARNING, apv, 1);
  1708. }
  1709. }
  1710. hr = S_OK;
  1711. if (bSetPasswordOK && bSetSecurityOK)
  1712. {
  1713. // success on the first steps, finally can enable the account
  1714. CComVariant varAccount;
  1715. hr = pNewADsObjectCreateInfo->HrGetAttributeVariant(CComBSTR(gsz_userAccountControl), OUT &varAccount);
  1716. if (SUCCEEDED(hr))
  1717. {
  1718. // got user account control, can change flag
  1719. ASSERT(varAccount.vt == VT_I4);
  1720. varAccount.lVal &= ~UF_ACCOUNTDISABLE;
  1721. hr = pNewADsObjectCreateInfo->HrAddVariantLong(CComBSTR(gsz_userAccountControl), varAccount.lVal);
  1722. if (SUCCEEDED(hr))
  1723. {
  1724. // Try to persist the changes
  1725. CWaitCursor cwait;
  1726. hr = pNewADsObjectCreateInfo->HrSetInfo(TRUE /* fSilentError */);
  1727. }
  1728. }
  1729. // handle errors, if any
  1730. if (FAILED(hr))
  1731. {
  1732. TRACE1("INFO: Unable to commit account control for computer %s.\n", (LPCTSTR)m_strName);
  1733. if (!bSilent)
  1734. {
  1735. ReportErrorEx (::GetParent(m_hWnd),IDS_12_UNABLE_TO_WRITE_ACCT_CTRL,hr,
  1736. MB_OK | MB_ICONWARNING, apv, 1);
  1737. }
  1738. hr = S_OK; // treat as a warning, the account is left disabled
  1739. }
  1740. }
  1741. return hr;
  1742. }
  1743. #define FILTER_ONE (UGOP_USERS | \
  1744. UGOP_ACCOUNT_GROUPS_SE | \
  1745. UGOP_RESOURCE_GROUPS_SE | \
  1746. UGOP_UNIVERSAL_GROUPS_SE | \
  1747. UGOP_BUILTIN_GROUPS | \
  1748. UGOP_WELL_KNOWN_PRINCIPALS_USERS \
  1749. )
  1750. #define FILTER_TWO (UGOP_USERS | \
  1751. UGOP_ACCOUNT_GROUPS_SE | \
  1752. UGOP_UNIVERSAL_GROUPS_SE | \
  1753. UGOP_WELL_KNOWN_PRINCIPALS_USERS | \
  1754. UGOP_USERS | \
  1755. UGOP_GLOBAL_GROUPS | \
  1756. UGOP_ALL_NT4_WELLKNOWN_SIDS \
  1757. )
  1758. void CCreateNewComputerPage::GetSummaryInfo(CString& s)
  1759. {
  1760. if (IsDlgButtonChecked(IDC_NT4_CHECK))
  1761. {
  1762. CString sz;
  1763. sz.LoadString(IDS_COMPUTER_CREATE_DLG_NT4_ACCOUNT);
  1764. s += sz;
  1765. s += L"\n";
  1766. }
  1767. if (IsDlgButtonChecked(IDC_NT4_BDC_CHECK))
  1768. {
  1769. CString sz;
  1770. sz.LoadString(IDS_COMPUTER_CREATE_DLG_NT4_BDC);
  1771. s += sz;
  1772. s += L"\n";
  1773. }
  1774. }
  1775. HRESULT CCreateNewComputerPage::_LookupSamAccountNameFromSid(PSID pSid,
  1776. CString& szSamAccountName)
  1777. {
  1778. HRESULT hr = S_OK;
  1779. // need to use the SID and lookup the SAM account name
  1780. WCHAR szName[MAX_PATH], szDomain[MAX_PATH];
  1781. DWORD cchName = MAX_PATH-1, cchDomain = MAX_PATH-1;
  1782. SID_NAME_USE sne;
  1783. LPCWSTR lpszServerName = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName();
  1784. if (!LookupAccountSid(lpszServerName, pSid, szName, &cchName, szDomain, &cchDomain, &sne))
  1785. {
  1786. DWORD dwErr = GetLastError();
  1787. TRACE(_T("LookupAccountSid failed with error %d\n"), dwErr);
  1788. return HRESULT_FROM_WIN32(dwErr);
  1789. }
  1790. szSamAccountName = szDomain;
  1791. szSamAccountName += L"\\";
  1792. szSamAccountName += szName;
  1793. return hr;
  1794. }
  1795. DSOP_SCOPE_INIT_INFO g_aComputerPrincipalDSOPScopes[] =
  1796. {
  1797. #if 0
  1798. {
  1799. cbSize,
  1800. flType,
  1801. flScope,
  1802. {
  1803. { flBothModes, flMixedModeOnly, flNativeModeOnly },
  1804. flDownlevel,
  1805. },
  1806. pwzDcName,
  1807. pwzADsPath,
  1808. hr // OUT
  1809. },
  1810. #endif
  1811. // The Global Catalog
  1812. {
  1813. sizeof(DSOP_SCOPE_INIT_INFO),
  1814. DSOP_SCOPE_TYPE_GLOBAL_CATALOG,
  1815. DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS,
  1816. {
  1817. { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
  1818. DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE |
  1819. DSOP_FILTER_WELL_KNOWN_PRINCIPALS, 0, 0 },
  1820. 0,
  1821. },
  1822. NULL,
  1823. NULL,
  1824. S_OK
  1825. },
  1826. // The domain to which the target computer is joined.
  1827. {
  1828. sizeof(DSOP_SCOPE_INIT_INFO),
  1829. DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN,
  1830. DSOP_SCOPE_FLAG_STARTING_SCOPE |
  1831. DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS,
  1832. {
  1833. // joined domain is always NT5 for DS ACLs Editor
  1834. { 0,
  1835. //mixed: users, well known SIDs, local groups, builtin groups, global groups, computers
  1836. DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
  1837. DSOP_FILTER_WELL_KNOWN_PRINCIPALS | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE |
  1838. DSOP_FILTER_BUILTIN_GROUPS | DSOP_FILTER_GLOBAL_GROUPS_SE,
  1839. //native users, well known SIDs, local groups, builtin groups, global groups, universal groups, computers
  1840. DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS |
  1841. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_BUILTIN_GROUPS |
  1842. DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE
  1843. },
  1844. 0, // zero for downlevel joined domain, should be DS-aware
  1845. },
  1846. NULL,
  1847. NULL,
  1848. S_OK
  1849. },
  1850. // The domains in the same forest (enterprise) as the domain to which
  1851. // the target machine is joined. Note these can only be DS-aware
  1852. {
  1853. sizeof(DSOP_SCOPE_INIT_INFO),
  1854. DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN,
  1855. DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS,
  1856. {
  1857. { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
  1858. DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0},
  1859. 0,
  1860. },
  1861. NULL,
  1862. NULL,
  1863. S_OK
  1864. },
  1865. // Uplevel domains external to the enterprise but trusted directly by the
  1866. // domain to which the target machine is joined.
  1867. {
  1868. sizeof(DSOP_SCOPE_INIT_INFO),
  1869. DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN,
  1870. DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS,
  1871. {
  1872. { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
  1873. DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0},
  1874. DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS,
  1875. },
  1876. NULL,
  1877. NULL,
  1878. S_OK
  1879. },
  1880. // Downlevel domains external to the enterprise but trusted directly by the
  1881. // domain to which the target machine is joined.
  1882. {
  1883. sizeof(DSOP_SCOPE_INIT_INFO),
  1884. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN,
  1885. DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS | DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS,
  1886. {
  1887. { DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
  1888. DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE, 0, 0},
  1889. DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS,
  1890. },
  1891. NULL,
  1892. NULL,
  1893. S_OK
  1894. },
  1895. };
  1896. void CCreateNewComputerPage::OnChangePrincipalButton()
  1897. {
  1898. static UINT cfDsObjectPicker = 0;
  1899. if (cfDsObjectPicker == 0)
  1900. cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  1901. // create object picker COM object
  1902. CComPtr<IDsObjectPicker> spDsObjectPicker;
  1903. HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER,
  1904. IID_IDsObjectPicker, (void**)&spDsObjectPicker);
  1905. if (FAILED(hr))
  1906. return;
  1907. // set init info
  1908. DSOP_INIT_INFO InitInfo;
  1909. ZeroMemory(&InitInfo, sizeof(InitInfo));
  1910. InitInfo.cbSize = sizeof(DSOP_INIT_INFO);
  1911. InitInfo.pwzTargetComputer = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName();
  1912. InitInfo.cDsScopeInfos = sizeof(g_aComputerPrincipalDSOPScopes)/sizeof(DSOP_SCOPE_INIT_INFO);
  1913. InitInfo.aDsScopeInfos = g_aComputerPrincipalDSOPScopes;
  1914. InitInfo.flOptions = 0;
  1915. InitInfo.cAttributesToFetch = 1;
  1916. LPCWSTR lpszObjectSID = L"objectSid";
  1917. InitInfo.apwzAttributeNames = const_cast<LPCTSTR *>(&lpszObjectSID);
  1918. //
  1919. // Loop through the scopes assigning the DC name
  1920. //
  1921. for (UINT idx = 0; idx < InitInfo.cDsScopeInfos; idx++)
  1922. {
  1923. // Don't set the DC name for external downlevel trusts. This may cause connection
  1924. // problems in Object Picker
  1925. if (!(InitInfo.aDsScopeInfos->flScope & DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN))
  1926. {
  1927. InitInfo.aDsScopeInfos[idx].pwzDcName = GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName();
  1928. }
  1929. }
  1930. //
  1931. // initialize object picker
  1932. //
  1933. hr = spDsObjectPicker->Initialize(&InitInfo);
  1934. if (FAILED(hr))
  1935. return;
  1936. // invoke the dialog
  1937. CComPtr<IDataObject> spdoSelections;
  1938. hr = spDsObjectPicker->InvokeDialog(m_hWnd, &spdoSelections);
  1939. if (hr == S_FALSE || !spdoSelections)
  1940. {
  1941. return;
  1942. }
  1943. // retrieve data from data object
  1944. FORMATETC fmte = {(CLIPFORMAT)cfDsObjectPicker, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  1945. STGMEDIUM medium = {TYMED_NULL, NULL, NULL};
  1946. PDS_SELECTION_LIST pDsSelList = NULL;
  1947. hr = spdoSelections->GetData(&fmte, &medium);
  1948. if (FAILED(hr))
  1949. return;
  1950. pDsSelList = (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal);
  1951. CComBSTR bsDN;
  1952. if (pDsSelList != NULL)
  1953. {
  1954. ASSERT(pDsSelList->cItems == 1); // single selection
  1955. TRACE(_T("pwzName = %s\n"), pDsSelList->aDsSelection[0].pwzName);
  1956. TRACE(_T("pwzADsPath = %s\n"), pDsSelList->aDsSelection[0].pwzADsPath);
  1957. TRACE(_T("pwzClass = %s\n"), pDsSelList->aDsSelection[0].pwzClass);
  1958. TRACE(_T("pwzUPN = %s\n"), pDsSelList->aDsSelection[0].pwzUPN);
  1959. // get the SID
  1960. ASSERT(pDsSelList->aDsSelection[0].pvarFetchedAttributes != NULL);
  1961. if (pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].vt != VT_EMPTY)
  1962. {
  1963. ASSERT(pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].vt == (VT_ARRAY | VT_UI1));
  1964. PSID pSid = pDsSelList->aDsSelection[0].pvarFetchedAttributes[0].parray->pvData;
  1965. ASSERT(IsValidSid(pSid));
  1966. // deep copy SID
  1967. if (!m_securityPrincipalSidHolder.Copy(pSid))
  1968. {
  1969. ASSERT(FALSE); // should never get here in normal operations
  1970. ReportErrorEx(::GetParent(m_hWnd),IDS_ERR_FATAL,hr,
  1971. MB_OK | MB_ICONERROR, NULL, 0);
  1972. goto Exit;
  1973. }
  1974. }
  1975. UpdateSecurityPrincipalUI(&(pDsSelList->aDsSelection[0]));
  1976. }
  1977. else
  1978. {
  1979. PVOID apv[1] = {(LPWSTR)(pDsSelList->aDsSelection[0].pwzName)};
  1980. ReportErrorEx(::GetParent(m_hWnd),IDS_12_CANT_GET_SAM_ACCNT_NAME,hr,
  1981. MB_OK | MB_ICONERROR, apv, 1);
  1982. goto Exit;
  1983. }
  1984. Exit:
  1985. GlobalUnlock(medium.hGlobal);
  1986. ReleaseStgMedium(&medium);
  1987. }
  1988. void CCreateNewComputerPage::UpdateSecurityPrincipalUI(PDS_SELECTION pDsSelection)
  1989. {
  1990. TRACE(L"CCreateNewComputerPage::UpdateSecurityPrincipalUI()\n");
  1991. HRESULT hr = S_OK;
  1992. CString szText;
  1993. LPWSTR pwzADsPath = pDsSelection->pwzADsPath;
  1994. TRACE(L"pDsSelection->pwzADsPath = %s\n", pDsSelection->pwzADsPath);
  1995. // get the X500 name (remove the provider ("LDAP://") in front of the name
  1996. if ((pwzADsPath != NULL) && (pwzADsPath[0] != NULL))
  1997. {
  1998. CComBSTR bstrProvider;
  1999. // need a fresh instance because we can set it to WINNT provider
  2000. // and pretty much trash it (oh boy!!!)
  2001. CPathCracker pathCracker;
  2002. hr = pathCracker.Set(CComBSTR(pwzADsPath), ADS_SETTYPE_FULL);
  2003. if (FAILED(hr))
  2004. {
  2005. goto End;
  2006. }
  2007. hr = pathCracker.Retrieve(ADS_FORMAT_PROVIDER, &bstrProvider);
  2008. TRACE(L"bstrProvider = %s\n", bstrProvider);
  2009. if (FAILED(hr))
  2010. {
  2011. goto End;
  2012. }
  2013. if (_wcsicmp(bstrProvider, L"LDAP") == 0)
  2014. {
  2015. // it is an LDAP path, get the DN out of it
  2016. // get the DN
  2017. CComBSTR bstrDN;
  2018. hr = pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  2019. if (FAILED(hr))
  2020. {
  2021. goto End;
  2022. }
  2023. // get the canonical name out of the DN
  2024. LPWSTR pszCanonical = NULL;
  2025. hr = ::CrackName((LPWSTR)bstrDN, &pszCanonical, GET_OBJ_CAN_NAME, NULL);
  2026. if (pszCanonical != NULL)
  2027. {
  2028. szText = pszCanonical;
  2029. ::LocalFreeStringW(&pszCanonical);
  2030. }
  2031. }
  2032. else if (_wcsicmp(bstrProvider, L"WinNT") == 0)
  2033. {
  2034. // we got an NT 4.0 user or group,
  2035. // the mpath is something like: "WinNT://mydomain/JoeB"
  2036. CComBSTR bstrWindows;
  2037. // get "mydomain/JoeB"
  2038. hr = pathCracker.Retrieve(ADS_FORMAT_WINDOWS_DN, &bstrWindows);
  2039. if (FAILED(hr))
  2040. {
  2041. goto End;
  2042. }
  2043. szText = bstrWindows;
  2044. // flip the slash to reverse slash
  2045. int nCh = szText.Find(L'/');
  2046. if (nCh != -1)
  2047. {
  2048. szText.SetAt(nCh, L'\\');
  2049. }
  2050. }
  2051. }
  2052. End:
  2053. if (szText.IsEmpty())
  2054. {
  2055. szText = pDsSelection->pwzName;
  2056. }
  2057. SetDlgItemText(IDC_PRINCIPAL_EDIT, szText);
  2058. }
  2059. HRESULT
  2060. CCreateNewComputerPage::GetDefaultSecurityDescriptorFromSchema(
  2061. CSimpleSecurityDescriptorHolder& sdHolder)
  2062. {
  2063. HRESULT hr = S_OK;
  2064. do
  2065. {
  2066. // Get the schema path
  2067. CString schemaPath;
  2068. GetWiz()->GetInfo()->GetBasePathsInfo()->GetSchemaPath(schemaPath);
  2069. if (schemaPath.IsEmpty())
  2070. {
  2071. TRACE(L"Failed to get the schema path");
  2072. hr = E_FAIL;
  2073. break;
  2074. }
  2075. // Initialize the search object
  2076. CDSSearch schemaSearcher;
  2077. hr = InitializeSchemaSearcher(schemaPath, schemaSearcher);
  2078. if (FAILED(hr))
  2079. {
  2080. TRACE(L"Failed to initialize schema searcher: hr = 0x%x", hr);
  2081. break;
  2082. }
  2083. // Run the query
  2084. hr = schemaSearcher.DoQuery();
  2085. if (FAILED(hr))
  2086. {
  2087. TRACE(L"Failed DoQuery on schema searcher: hr = 0x%x", hr);
  2088. break;
  2089. }
  2090. hr = schemaSearcher.GetNextRow();
  2091. if (FAILED(hr))
  2092. {
  2093. TRACE(L"Failed to get a row from the schema search object: hr = 0x%x", hr);
  2094. break;
  2095. }
  2096. // Get the value from the search object
  2097. ADS_SEARCH_COLUMN searchColumn;
  2098. ZeroMemory(&searchColumn, sizeof(ADS_SEARCH_COLUMN));
  2099. hr = schemaSearcher.GetColumn(g_pszDefaultSecurityDescriptor, &searchColumn);
  2100. if (FAILED(hr))
  2101. {
  2102. TRACE(L"Failed to get the defaultSecurityDescriptor column from search object: hr = 0x%x", hr);
  2103. break;
  2104. }
  2105. // Initialize the SD from the SDDL
  2106. if (searchColumn.dwNumValues > 0 &&
  2107. searchColumn.pADsValues &&
  2108. searchColumn.pADsValues->CaseIgnoreString)
  2109. {
  2110. hr = sdHolder.InitializeFromSDDL(
  2111. GetWiz()->GetInfo()->GetBasePathsInfo()->GetServerName(),
  2112. searchColumn.pADsValues->CaseIgnoreString);
  2113. }
  2114. hr = schemaSearcher.FreeColumn(&searchColumn);
  2115. if (FAILED(hr))
  2116. {
  2117. TRACE(L"Failed to free the search column: hr = 0x%x", hr);
  2118. }
  2119. } while (false);
  2120. return hr;
  2121. }
  2122. HRESULT CCreateNewComputerPage::InitializeSchemaSearcher(
  2123. const CString& schemaPath,
  2124. CDSSearch& schemaSearcher)
  2125. {
  2126. HRESULT hr = S_OK;
  2127. do
  2128. {
  2129. hr = schemaSearcher.Init(schemaPath);
  2130. if (FAILED(hr))
  2131. {
  2132. TRACE(L"Failed to initialize the schema search object: hr = 0x%x", hr);
  2133. break;
  2134. }
  2135. PWSTR pszFilter = L"(&(objectCategory=classSchema)(ldapDisplayName=computer))";
  2136. PWSTR pszAttrs[] = { g_pszDefaultSecurityDescriptor };
  2137. hr = schemaSearcher.SetAttributeList(pszAttrs, sizeof(pszAttrs)/sizeof(PWSTR));
  2138. if (FAILED(hr))
  2139. {
  2140. TRACE(L"Failed to set the attribute list in the schema search object: hr = 0x%x", hr);
  2141. break;
  2142. }
  2143. hr = schemaSearcher.SetFilterString(pszFilter);
  2144. if (FAILED(hr))
  2145. {
  2146. TRACE(L"Failed to set the filter string in the schema search object: hr = 0x%x", hr);
  2147. break;
  2148. }
  2149. hr = schemaSearcher.SetSearchScope(ADS_SCOPE_ONELEVEL);
  2150. if (FAILED(hr))
  2151. {
  2152. TRACE(L"Failed to set the search scope in the schema search object: hr = 0x%x", hr);
  2153. break;
  2154. }
  2155. } while (false);
  2156. return hr;
  2157. }
  2158. // DESCRIPTION : this function gives the specified SID the same rights as
  2159. // creator owner in the given ACL.
  2160. //
  2161. // NOTE: Due to the memory management constraints of all the security APIs
  2162. // this turns out to be a huge function. Functions like BuildTrusteeWithObjectAndSid()
  2163. // don't allocate any memory and instead just set pointers to existing memory in the
  2164. // structure, so if I use any locals they must remain in the scope of the constructed
  2165. // Trustee object or else I could run into failures.
  2166. HRESULT CCreateNewComputerPage::AddCreatorOwnerAccessForSID(
  2167. PACL defaultAcl,
  2168. PACL acl,
  2169. PSID securityPrincipalSID,
  2170. CSimpleAclHolder& newDacl)
  2171. {
  2172. HRESULT hr = S_OK;
  2173. PEXPLICIT_ACCESS completeAccessList = 0;
  2174. PEXPLICIT_ACCESS creatorOwnerAccessList = 0;
  2175. ULONG entries = 0;
  2176. ULONG emptyObjectsAndSidsUsed = 0;
  2177. // We need to dynamically allocate the emptyObjectsAndSid because
  2178. // there needs to be one for each time its used in BuildTrusteeWithObjectsAndSid
  2179. POBJECTS_AND_SID emptyObjectsAndSid = 0;
  2180. do
  2181. {
  2182. if (!defaultAcl ||
  2183. !acl ||
  2184. !securityPrincipalSID)
  2185. {
  2186. ASSERT(defaultAcl);
  2187. ASSERT(acl);
  2188. ASSERT(securityPrincipalSID);
  2189. hr = E_INVALIDARG;
  2190. break;
  2191. }
  2192. // Get all the entries from the ACL
  2193. ULONG totalEntries = 0;
  2194. DWORD error =
  2195. GetExplicitEntriesFromAcl(
  2196. defaultAcl,
  2197. &totalEntries,
  2198. &completeAccessList);
  2199. if (ERROR_SUCCESS != error)
  2200. {
  2201. hr = HRESULT_FROM_WIN32(error);
  2202. TRACE(L"Failed to GetExplicitEntriesFromAcl: hr = 0x%x", hr);
  2203. break;
  2204. }
  2205. if (totalEntries <= 0)
  2206. {
  2207. hr = E_FAIL;
  2208. TRACE(L"No entries were returned from GetExplicitEntriesFromAcl");
  2209. break;
  2210. }
  2211. // We know that there will be no more entries for creator/owner
  2212. // than are already present, so allocate the new array with
  2213. // the max and then entries will be the number the array
  2214. // actually contains
  2215. creatorOwnerAccessList = new EXPLICIT_ACCESS[totalEntries];
  2216. if (!creatorOwnerAccessList)
  2217. {
  2218. hr = E_OUTOFMEMORY;
  2219. break;
  2220. }
  2221. ::ZeroMemory(creatorOwnerAccessList, totalEntries * sizeof(EXPLICIT_ACCESS));
  2222. emptyObjectsAndSid = new OBJECTS_AND_SID[totalEntries];
  2223. if (!emptyObjectsAndSid)
  2224. {
  2225. hr = E_OUTOFMEMORY;
  2226. break;
  2227. }
  2228. ::ZeroMemory(emptyObjectsAndSid, totalEntries * sizeof(OBJECTS_AND_SID));
  2229. // Loop through all the entries and copy over any for creator/owner
  2230. static SID creatorOwnerSID =
  2231. {SID_REVISION,1,SECURITY_CREATOR_SID_AUTHORITY,{SECURITY_CREATOR_OWNER_RID}};
  2232. for (ULONG index = 0; index < totalEntries; ++index)
  2233. {
  2234. if (completeAccessList[index].Trustee.TrusteeForm == TRUSTEE_IS_OBJECTS_AND_SID)
  2235. {
  2236. POBJECTS_AND_SID objectsAndSid =
  2237. reinterpret_cast<POBJECTS_AND_SID>(completeAccessList[index].Trustee.ptstrName);
  2238. if (objectsAndSid &&
  2239. EqualSid(&creatorOwnerSID, objectsAndSid->pSid))
  2240. {
  2241. // Fill in the Trustee member of the new entry in the creatorOwnerAccessList
  2242. // with the SID of the new security principal
  2243. creatorOwnerAccessList[entries] = completeAccessList[index];
  2244. BuildTrusteeWithObjectsAndSid(
  2245. &(creatorOwnerAccessList[entries].Trustee),
  2246. &(emptyObjectsAndSid[emptyObjectsAndSidsUsed++]),
  2247. &objectsAndSid->ObjectTypeGuid,
  2248. &objectsAndSid->InheritedObjectTypeGuid,
  2249. securityPrincipalSID);
  2250. ++entries;
  2251. }
  2252. }
  2253. else if (completeAccessList[index].Trustee.TrusteeForm == TRUSTEE_IS_SID)
  2254. {
  2255. PSID currentSID =
  2256. reinterpret_cast<PSID>(completeAccessList[index].Trustee.ptstrName);
  2257. if (currentSID &&
  2258. EqualSid(&creatorOwnerSID, currentSID))
  2259. {
  2260. // Fill in the Trustee member of the new entry in the creatorOwnerAccessList
  2261. // with the SID of the new security principal
  2262. creatorOwnerAccessList[entries] = completeAccessList[index];
  2263. BuildTrusteeWithSid(
  2264. &(creatorOwnerAccessList[entries].Trustee),
  2265. securityPrincipalSID);
  2266. ++entries;
  2267. }
  2268. }
  2269. else
  2270. {
  2271. // REVIEW_JEFFJON : Can we get any of the other forms here?
  2272. // If so, what do we do with them?
  2273. ASSERT(FALSE);
  2274. continue;
  2275. }
  2276. }
  2277. error = SetEntriesInAcl(
  2278. entries,
  2279. creatorOwnerAccessList,
  2280. acl,
  2281. &(newDacl.m_pAcl));
  2282. if (ERROR_SUCCESS != error)
  2283. {
  2284. hr = HRESULT_FROM_WIN32(error);
  2285. TRACE(L"Failed to SetEntriesInAcl: hr = 0x%x", hr);
  2286. break;
  2287. }
  2288. } while (false);
  2289. if (completeAccessList)
  2290. {
  2291. LocalFree(completeAccessList);
  2292. completeAccessList = 0;
  2293. }
  2294. if (creatorOwnerAccessList)
  2295. {
  2296. delete[] creatorOwnerAccessList;
  2297. creatorOwnerAccessList = 0;
  2298. }
  2299. if (emptyObjectsAndSid)
  2300. {
  2301. delete[] emptyObjectsAndSid;
  2302. emptyObjectsAndSid = 0;
  2303. }
  2304. return hr;
  2305. }
  2306. HRESULT CCreateNewComputerPage::BuildNewAccessList(PACL pDacl, CSimpleAclHolder& Dacl)
  2307. {
  2308. // NTRAID#NTBUG-509482-2002/03/05-JeffJon-We need to read the default
  2309. // security descriptor for computer objects from the schema and apply
  2310. // all the ACEs for the creator/owner to the selected object
  2311. HRESULT hr = S_OK;
  2312. do
  2313. {
  2314. // Get the defaultSecurityDescriptor from the schema
  2315. CSimpleSecurityDescriptorHolder sdHolder;
  2316. hr = GetDefaultSecurityDescriptorFromSchema(sdHolder);
  2317. if (FAILED(hr))
  2318. {
  2319. TRACE(L"Failed to get the default security descriptor from the schema: hr = %x", hr);
  2320. break;
  2321. }
  2322. if (!sdHolder.m_pSD)
  2323. {
  2324. TRACE(L"Failed to get the default security descriptor from the schema.");
  2325. hr = E_FAIL;
  2326. break;
  2327. }
  2328. // Pull out the DACL from the SD
  2329. BOOL daclPresent = TRUE;
  2330. BOOL daclDefaulted = FALSE;
  2331. PACL pDefaultDacl = 0;
  2332. BOOL result =
  2333. GetSecurityDescriptorDacl(
  2334. sdHolder.m_pSD,
  2335. &daclPresent,
  2336. &pDefaultDacl,
  2337. &daclDefaulted);
  2338. if (!result)
  2339. {
  2340. DWORD error = GetLastError();
  2341. hr = HRESULT_FROM_WIN32(error);
  2342. TRACE(L"Failed to GetSecurityDescriptorDacl: hr = 0x%x", hr);
  2343. break;
  2344. }
  2345. if (!daclPresent)
  2346. {
  2347. TRACE(L"GetSecurityDescriptorDacl returned no DACL");
  2348. hr = E_FAIL;
  2349. break;
  2350. }
  2351. PSID securityPrincipalSID = m_securityPrincipalSidHolder.Get();
  2352. ASSERT(securityPrincipalSID);
  2353. hr = AddCreatorOwnerAccessForSID(pDefaultDacl, pDacl, securityPrincipalSID, Dacl);
  2354. if (FAILED(hr))
  2355. {
  2356. TRACE(L"Failed AddCreatorOwnerAccessToSID: hr = 0x%x", hr);
  2357. break;
  2358. }
  2359. } while (false);
  2360. return hr;
  2361. }
  2362. HRESULT CCreateNewComputerPage::SetSecurity()
  2363. {
  2364. // get the ADSI object pointer
  2365. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2366. IADs* pObj = pNewADsObjectCreateInfo->PGetIADsPtr();
  2367. // get the full LDAP path of the object
  2368. CComBSTR bstrObjectLdapPath;
  2369. HRESULT hr = pObj->get_ADsPath(&bstrObjectLdapPath);
  2370. ASSERT (SUCCEEDED(hr));
  2371. if (FAILED(hr))
  2372. {
  2373. return hr;
  2374. }
  2375. UnescapePath(bstrObjectLdapPath, /*bDN*/ FALSE, bstrObjectLdapPath);
  2376. PACL pAcl = NULL;
  2377. CSimpleSecurityDescriptorHolder SDHolder;
  2378. TRACE(_T("GetDsObjectSD(%s)\n"), bstrObjectLdapPath);
  2379. // read info
  2380. DWORD dwErr =
  2381. ::GetDsObjectSD(
  2382. bstrObjectLdapPath,
  2383. &pAcl,
  2384. &(SDHolder.m_pSD));
  2385. TRACE(L"GetDsObjectSD() returned dwErr = 0x%x\n", dwErr);
  2386. hr = HRESULT_FROM_WIN32(dwErr);
  2387. if (FAILED(hr))
  2388. {
  2389. TRACE(_T("failed on GetDsObjectSD()\n"));
  2390. return hr;
  2391. }
  2392. // build the new DACL
  2393. CSimpleAclHolder Dacl;
  2394. hr = BuildNewAccessList(pAcl, Dacl);
  2395. if (FAILED(hr))
  2396. {
  2397. TRACE(_T("failed on BuildNewAccessList()\n"));
  2398. return hr;
  2399. }
  2400. // commit changes
  2401. dwErr =
  2402. ::SetDsObjectDacl(
  2403. (LPCWSTR)(BSTR)bstrObjectLdapPath,
  2404. Dacl.m_pAcl);
  2405. TRACE(L"SetDsObjectDacl() returned dwErr = 0x%x\n", dwErr);
  2406. hr = HRESULT_FROM_WIN32(dwErr);
  2407. return hr;
  2408. }
  2409. BOOL CCreateNewComputerPage::OnError(HRESULT hr)
  2410. {
  2411. BOOL bRetVal = FALSE;
  2412. if( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS )
  2413. {
  2414. HRESULT Localhr;
  2415. DWORD LastError;
  2416. WCHAR Buf1[256], Buf2[256];
  2417. Localhr = ADsGetLastError (&LastError,
  2418. Buf1, 256, Buf2, 256);
  2419. switch( LastError )
  2420. {
  2421. case ERROR_USER_EXISTS:
  2422. {
  2423. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName};
  2424. ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_COMPUTER_EXISTS,hr,
  2425. MB_OK|MB_ICONWARNING , apv, 1);
  2426. bRetVal = TRUE;
  2427. }
  2428. break;
  2429. case ERROR_DS_OBJ_STRING_NAME_EXISTS:
  2430. {
  2431. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strName};
  2432. ReportErrorEx (::GetParent(m_hWnd),IDS_ERROR_COMPUTER_DS_OBJ_STRING_NAME_EXISTS,hr,
  2433. MB_OK|MB_ICONWARNING , apv, 1);
  2434. bRetVal = TRUE;
  2435. }
  2436. break;
  2437. }
  2438. }
  2439. return bRetVal;
  2440. }
  2441. CCreateNewComputerWizard:: CCreateNewComputerWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) :
  2442. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  2443. {
  2444. AddPage(&m_page1);
  2445. }
  2446. void CCreateNewComputerWizard::OnFinishSetInfoFailed(HRESULT hr)
  2447. {
  2448. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  2449. if ( !( HRESULT_CODE(hr) == ERROR_OBJECT_ALREADY_EXISTS &&
  2450. m_page1.OnError( hr ) ) )
  2451. {
  2452. // everything else is handled by the base class
  2453. CCreateNewObjectWizardBase::OnFinishSetInfoFailed(hr);
  2454. }
  2455. }
  2456. ///////////////////////////////////////////////////////////////
  2457. // NEW OU WIZARD
  2458. BEGIN_MESSAGE_MAP(CCreateNewOUPage, CCreateNewObjectDataPage)
  2459. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange)
  2460. END_MESSAGE_MAP()
  2461. CCreateNewOUPage::CCreateNewOUPage()
  2462. : CCreateNewObjectDataPage(CCreateNewOUPage::IDD)
  2463. {
  2464. }
  2465. BOOL CCreateNewOUPage::OnInitDialog()
  2466. {
  2467. Edit_LimitText (GetDlgItem(IDC_EDIT_OBJECT_NAME)->m_hWnd, 64);
  2468. CCreateNewObjectDataPage::OnInitDialog();
  2469. return TRUE;
  2470. }
  2471. BOOL CCreateNewOUPage::GetData(IADs*)
  2472. {
  2473. return !m_strOUName.IsEmpty();
  2474. }
  2475. void CCreateNewOUPage::OnNameChange()
  2476. {
  2477. GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strOUName);
  2478. m_strOUName.TrimLeft();
  2479. m_strOUName.TrimRight();
  2480. GetWiz()->SetWizardButtons(this, !m_strOUName.IsEmpty());
  2481. }
  2482. HRESULT CCreateNewOUPage::SetData(BOOL)
  2483. {
  2484. // Store the object name in the temporary storage
  2485. HRESULT hr = GetWiz()->GetInfo()->HrCreateNew(m_strOUName);
  2486. return hr;
  2487. }
  2488. BOOL CCreateNewOUPage::OnSetActive()
  2489. {
  2490. BOOL bRet = CCreateNewObjectDataPage::OnSetActive();
  2491. SetDlgItemFocus(IDC_EDIT_OBJECT_NAME);
  2492. SendDlgItemMessage(IDC_EDIT_OBJECT_NAME, EM_SETSEL, 0, -1);
  2493. return bRet;
  2494. }
  2495. BOOL CCreateNewOUPage::OnWizardFinish()
  2496. {
  2497. BOOL bFinish = CCreateNewObjectDataPage::OnWizardFinish();
  2498. if (!bFinish)
  2499. {
  2500. SetDlgItemFocus(IDC_EDIT_OBJECT_NAME);
  2501. SendDlgItemMessage(IDC_EDIT_OBJECT_NAME, EM_SETSEL, 0, -1);
  2502. }
  2503. return bFinish;
  2504. }
  2505. CCreateNewOUWizard:: CCreateNewOUWizard(CNewADsObjectCreateInfo* pNewADsObjectCreateInfo) :
  2506. CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  2507. {
  2508. AddPage(&m_page1);
  2509. }
  2510. ///////////////////////////////////////////////////////////////
  2511. ///////////////////////////////////////////////////////////////
  2512. // NEW GROUP WIZARD
  2513. BEGIN_MESSAGE_MAP(CCreateNewGroupPage, CCreateNewObjectDataPage)
  2514. ON_EN_CHANGE(IDC_EDIT_OBJECT_NAME, OnNameChange)
  2515. ON_EN_CHANGE(IDC_EDIT_SAM_NAME, OnSamNameChange)
  2516. ON_BN_CLICKED(IDC_RADIO_SEC_GROUP, OnSecurityOrTypeChange)
  2517. ON_BN_CLICKED(IDC_RADIO_DISTRIBUTION_GROUP, OnSecurityOrTypeChange)
  2518. ON_BN_CLICKED(IDC_RADIO_RESOURCE, OnSecurityOrTypeChange)
  2519. ON_BN_CLICKED(IDC_RADIO_ACCOUNT, OnSecurityOrTypeChange)
  2520. ON_BN_CLICKED(IDC_RADIO_UNIVERSAL, OnSecurityOrTypeChange)
  2521. END_MESSAGE_MAP()
  2522. CCreateNewGroupPage::CCreateNewGroupPage() :
  2523. CCreateNewObjectDataPage(CCreateNewGroupPage::IDD)
  2524. {
  2525. m_fMixed = FALSE;
  2526. m_SAMLength = 256;
  2527. }
  2528. BOOL CCreateNewGroupPage::OnInitDialog()
  2529. {
  2530. CCreateNewObjectDataPage::OnInitDialog();
  2531. VERIFY(_InitUI());
  2532. return TRUE;
  2533. }
  2534. BOOL CCreateNewGroupPage::OnSetActive()
  2535. {
  2536. BOOL ret = CCreateNewObjectDataPage::OnSetActive();
  2537. // Set the focus to the first name field
  2538. GetParent()->PostMessage(
  2539. WM_NEXTDLGCTL,
  2540. (WPARAM)GetDlgItem(IDC_EDIT_OBJECT_NAME)->GetSafeHwnd(),
  2541. (LPARAM)TRUE);
  2542. GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() &&
  2543. !m_strSamName.IsEmpty()));
  2544. return ret;
  2545. }
  2546. BOOL CCreateNewGroupPage::_InitUI()
  2547. {
  2548. // set limit to edit boxes
  2549. Edit_LimitText(::GetDlgItem(m_hWnd, IDC_EDIT_OBJECT_NAME), 64);
  2550. Edit_LimitText(::GetDlgItem(m_hWnd, IDC_EDIT_SAM_NAME), m_SAMLength);
  2551. // determine if we are in mixed mode by
  2552. // retriving the domain we are bound to
  2553. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2554. CComPtr<IADs> spContainerObj;
  2555. HRESULT hr = pNewADsObjectCreateInfo->m_pIADsContainer->QueryInterface(
  2556. IID_IADs, (void **)&spContainerObj);
  2557. if (SUCCEEDED(hr))
  2558. {
  2559. // retrieve the DN of the container
  2560. CComBSTR bstrPath, bstrDN;
  2561. spContainerObj->get_ADsPath(&bstrPath);
  2562. CPathCracker pathCracker;
  2563. pathCracker.Set(bstrPath, ADS_SETTYPE_FULL);
  2564. pathCracker.SetDisplayType(ADS_DISPLAY_FULL);
  2565. pathCracker.Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  2566. // get the 1779 name of the domain
  2567. LPWSTR pszDomain1779 = NULL;
  2568. hr = CrackName (bstrDN, &pszDomain1779, GET_FQDN_DOMAIN_NAME, NULL);
  2569. if (SUCCEEDED(hr))
  2570. {
  2571. // build LDAP path for domain
  2572. CString strDomObj;
  2573. pNewADsObjectCreateInfo->GetBasePathsInfo()->ComposeADsIPath(strDomObj, pszDomain1779);
  2574. LocalFreeStringW(&pszDomain1779);
  2575. // bind to the domain object
  2576. CComPtr<IADs> spDomainObj;
  2577. hr = DSAdminOpenObject(strDomObj,
  2578. IID_IADs,
  2579. (void **) &spDomainObj,
  2580. TRUE /*bServer*/);
  2581. if (SUCCEEDED(hr))
  2582. {
  2583. // retrieve the mixed node attribute
  2584. CComVariant Mixed;
  2585. CComBSTR bsMixed(L"nTMixedDomain");
  2586. spDomainObj->Get(bsMixed, &Mixed);
  2587. m_fMixed = (BOOL)Mixed.bVal;
  2588. }
  2589. }
  2590. }
  2591. // initial setup of radiobutton state
  2592. if (m_fMixed) {
  2593. EnableDlgItem (IDC_RADIO_UNIVERSAL, FALSE); // no universal groups allowed
  2594. }
  2595. // default is global security group
  2596. ((CButton *)GetDlgItem(IDC_RADIO_ACCOUNT))->SetCheck(1);
  2597. ((CButton *)GetDlgItem(IDC_RADIO_SEC_GROUP))->SetCheck(1);
  2598. return TRUE;
  2599. }
  2600. HRESULT CCreateNewGroupPage::SetData(BOOL)
  2601. {
  2602. HRESULT hr;
  2603. //
  2604. // First check for illegal characters
  2605. //
  2606. int iFind = m_strSamName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS);
  2607. if (iFind != -1 && !m_strSamName.IsEmpty())
  2608. {
  2609. PVOID apv[1] = {(LPWSTR)(LPCWSTR)m_strSamName};
  2610. if (IDYES == ReportErrorEx (m_hWnd,IDS_GROUP_SAMNAME_ILLEGAL,S_OK,
  2611. MB_YESNO | MB_ICONWARNING, apv, 1))
  2612. {
  2613. while (iFind != -1)
  2614. {
  2615. m_strSamName.SetAt(iFind, L'_');
  2616. iFind = m_strSamName.FindOneOf(INVALID_ACCOUNT_NAME_CHARS);
  2617. }
  2618. SetDlgItemText(IDC_EDIT_SAM_NAME, m_strSamName);
  2619. }
  2620. else
  2621. {
  2622. //
  2623. // Set the focus to the edit box and select the text
  2624. //
  2625. GetDlgItem(IDC_EDIT_SAM_NAME)->SetFocus();
  2626. SendDlgItemMessage(IDC_EDIT_SAM_NAME, EM_SETSEL, 0 , -1);
  2627. return E_INVALIDARG;
  2628. }
  2629. }
  2630. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2631. // Store the object name in the temporary storage
  2632. hr = pNewADsObjectCreateInfo->HrCreateNew(m_strGroupName);
  2633. if (FAILED(hr))
  2634. {
  2635. return hr;
  2636. }
  2637. // Create and persist the object
  2638. // Store the object name in the temporary storage
  2639. hr = pNewADsObjectCreateInfo->HrAddVariantBstr(CComBSTR(gsz_samAccountName),
  2640. m_strSamName);
  2641. ASSERT(SUCCEEDED(hr));
  2642. CComVariant varGroupType;
  2643. varGroupType.vt = VT_I4;
  2644. BOOL Account = IsDlgButtonChecked (IDC_RADIO_ACCOUNT);
  2645. BOOL Resource = IsDlgButtonChecked (IDC_RADIO_RESOURCE);
  2646. BOOL Security = IsDlgButtonChecked (IDC_RADIO_SEC_GROUP);
  2647. if (Security)
  2648. varGroupType.lVal = GROUP_TYPE_SECURITY_ENABLED;
  2649. else
  2650. varGroupType.lVal = 0;
  2651. if (Resource)
  2652. varGroupType.lVal |= GROUP_TYPE_RESOURCE_GROUP;
  2653. else
  2654. if (Account)
  2655. varGroupType.lVal |= GROUP_TYPE_ACCOUNT_GROUP;
  2656. else
  2657. varGroupType.lVal |= GROUP_TYPE_UNIVERSAL_GROUP;
  2658. // Update the GroupType
  2659. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(CComBSTR(gsz_groupType), varGroupType);
  2660. ASSERT(SUCCEEDED(hr));
  2661. return hr;
  2662. }
  2663. BOOL CCreateNewGroupPage::GetData(IADs*)
  2664. {
  2665. return !m_strGroupName.IsEmpty();
  2666. }
  2667. void CCreateNewGroupPage::OnNameChange()
  2668. {
  2669. GetDlgItemText(IDC_EDIT_OBJECT_NAME, OUT m_strGroupName);
  2670. m_strGroupName.TrimLeft();
  2671. m_strGroupName.TrimRight();
  2672. SetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strGroupName.Left(m_SAMLength));
  2673. GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() &&
  2674. !m_strSamName.IsEmpty()));
  2675. }
  2676. void CCreateNewGroupPage::OnSamNameChange()
  2677. {
  2678. GetDlgItemText(IDC_EDIT_SAM_NAME, OUT m_strSamName);
  2679. m_strSamName.TrimLeft();
  2680. m_strSamName.TrimRight();
  2681. GetWiz()->SetWizardButtons(this,(!m_strGroupName.IsEmpty() &&
  2682. !m_strSamName.IsEmpty()));
  2683. }
  2684. void CCreateNewGroupPage::OnSecurityOrTypeChange()
  2685. {
  2686. if (!IsDlgButtonChecked (IDC_RADIO_SEC_GROUP)) {
  2687. EnableDlgItem (IDC_RADIO_UNIVERSAL, TRUE);
  2688. } else {
  2689. if (m_fMixed) {
  2690. if (IsDlgButtonChecked (IDC_RADIO_UNIVERSAL)) {
  2691. ((CButton *)GetDlgItem(IDC_RADIO_ACCOUNT))->SetCheck(1);
  2692. ((CButton *)GetDlgItem(IDC_RADIO_UNIVERSAL))->SetCheck(0);
  2693. }
  2694. EnableDlgItem (IDC_RADIO_UNIVERSAL, FALSE);
  2695. }
  2696. }
  2697. }
  2698. CCreateNewGroupWizard::CCreateNewGroupWizard(
  2699. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo)
  2700. : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  2701. {
  2702. AddPage(&m_page1);
  2703. }
  2704. ///////////////////////////////////////////////////////////////
  2705. ///////////////////////////////////////////////////////////////
  2706. // NEW CONTACT WIZARD
  2707. BEGIN_MESSAGE_MAP(CCreateNewContactPage, CCreateNewObjectDataPage)
  2708. ON_EN_CHANGE(IDC_EDIT_FIRST_NAME, OnNameChange)
  2709. ON_EN_CHANGE(IDC_EDIT_INITIALS, OnNameChange)
  2710. ON_EN_CHANGE(IDC_EDIT_LAST_NAME, OnNameChange)
  2711. ON_EN_CHANGE(IDC_EDIT_FULL_NAME, OnFullNameChange)
  2712. ON_EN_CHANGE(IDC_EDIT_DISP_NAME, OnDispNameChange)
  2713. END_MESSAGE_MAP()
  2714. CCreateNewContactPage::CCreateNewContactPage() :
  2715. CCreateNewObjectDataPage(CCreateNewContactPage::IDD)
  2716. {
  2717. }
  2718. BOOL CCreateNewContactPage::OnInitDialog()
  2719. {
  2720. CCreateNewObjectDataPage::OnInitDialog();
  2721. Edit_LimitText (GetDlgItem(IDC_EDIT_FULL_NAME)->m_hWnd, 64);
  2722. Edit_LimitText (GetDlgItem(IDC_EDIT_LAST_NAME)->m_hWnd, 29);
  2723. Edit_LimitText (GetDlgItem(IDC_EDIT_FIRST_NAME)->m_hWnd, 28);
  2724. // NTRAID#NTBUG9-522001-2002/01/17-JeffJon
  2725. // Initials should be limited to 6 characters.
  2726. Edit_LimitText (GetDlgItem(IDC_EDIT_INITIALS)->m_hWnd, 6);
  2727. Edit_LimitText (GetDlgItem(IDC_EDIT_DISP_NAME)->m_hWnd, 256);
  2728. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2729. m_nameFormatter.Initialize(pNewADsObjectCreateInfo->GetBasePathsInfo(),
  2730. pNewADsObjectCreateInfo->m_pszObjectClass);
  2731. return TRUE;
  2732. }
  2733. HRESULT CCreateNewContactPage::SetData(BOOL)
  2734. {
  2735. HRESULT hr;
  2736. // Store the object name in the temporary storage
  2737. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2738. // create a new temporary ADs object
  2739. hr = pNewADsObjectCreateInfo->HrCreateNew(m_strFullName);
  2740. if (FAILED(hr)) {
  2741. return hr;
  2742. }
  2743. // set the attributes in the cache
  2744. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"givenName"), m_strFirstName);
  2745. ASSERT(SUCCEEDED(hr));
  2746. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"initials"), m_strInitials);
  2747. ASSERT(SUCCEEDED(hr));
  2748. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"sn"), m_strLastName);
  2749. ASSERT(SUCCEEDED(hr));
  2750. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty(CComBSTR(L"displayName"), m_strDispName);
  2751. ASSERT(SUCCEEDED(hr));
  2752. return hr;
  2753. }
  2754. BOOL CCreateNewContactPage::GetData(IADs*)
  2755. {
  2756. return !m_strFullName.IsEmpty();
  2757. }
  2758. void CCreateNewContactPage::OnNameChange()
  2759. {
  2760. GetDlgItemText(IDC_EDIT_FIRST_NAME, OUT m_strFirstName);
  2761. GetDlgItemText(IDC_EDIT_INITIALS, OUT m_strInitials);
  2762. GetDlgItemText(IDC_EDIT_LAST_NAME, OUT m_strLastName);
  2763. m_strFirstName.TrimLeft();
  2764. m_strFirstName.TrimRight();
  2765. m_strInitials.TrimLeft();
  2766. m_strInitials.TrimRight();
  2767. m_strLastName.TrimLeft();
  2768. m_strLastName.TrimRight();
  2769. m_nameFormatter.FormatName(m_strFullName,
  2770. m_strFirstName.IsEmpty() ? NULL : (LPCWSTR)m_strFirstName,
  2771. m_strInitials.IsEmpty() ? NULL : (LPCWSTR)m_strInitials,
  2772. m_strLastName.IsEmpty() ? NULL : (LPCWSTR)m_strLastName);
  2773. SetDlgItemText(IDC_EDIT_FULL_NAME,
  2774. IN m_strFullName);
  2775. GetWiz()->SetWizardButtons(this, !m_strFullName.IsEmpty());
  2776. }
  2777. void CCreateNewContactPage::OnFullNameChange()
  2778. {
  2779. GetDlgItemText(IDC_EDIT_FULL_NAME, OUT m_strFullName);
  2780. GetWiz()->SetWizardButtons(this, !m_strFullName.IsEmpty());
  2781. }
  2782. void CCreateNewContactPage::OnDispNameChange()
  2783. {
  2784. GetDlgItemText(IDC_EDIT_DISP_NAME, OUT m_strDispName);
  2785. m_strDispName.TrimLeft();
  2786. m_strDispName.TrimRight();
  2787. }
  2788. CCreateNewContactWizard::CCreateNewContactWizard(
  2789. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo)
  2790. : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  2791. {
  2792. AddPage(&m_page1);
  2793. }
  2794. #ifdef FRS_CREATE
  2795. ///////////////////////////////////////////////////////////////
  2796. ///////////////////////////////////////////////////////////////
  2797. // NEW FRS SUBSCRIBER WIZARD
  2798. HRESULT CCreateNewFrsSubscriberPage::SetData(BOOL bSilent)
  2799. {
  2800. CString strRootPath;
  2801. CString strStagingPath;
  2802. if ( !ReadAbsolutePath( IDC_FRS_ROOT_PATH, strRootPath) ||
  2803. !ReadAbsolutePath( IDC_FRS_STAGING_PATH, strStagingPath ) )
  2804. {
  2805. return E_INVALIDARG;
  2806. }
  2807. HRESULT hr = S_OK;
  2808. // Add more properties, we don't want to create it unless all of these work
  2809. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2810. ASSERT( NULL != pNewADsObjectCreateInfo );
  2811. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty( gsz_fRSRootPath,
  2812. strRootPath,
  2813. TRUE );
  2814. ASSERT(SUCCEEDED(hr));
  2815. hr = pNewADsObjectCreateInfo->HrAddVariantBstrIfNotEmpty( gsz_fRSStagingPath,
  2816. strStagingPath,
  2817. TRUE );
  2818. ASSERT(SUCCEEDED(hr));
  2819. // no need to commit here, wait until after extensions have had a shot
  2820. return CCreateNewNamedObjectPage::SetData(bSilent);
  2821. }
  2822. BOOL CCreateNewFrsSubscriberPage::ReadAbsolutePath( int ctrlID, OUT CString& strrefValue )
  2823. {
  2824. // CODEWORK this should also select the text in this field
  2825. GetDlgItemText(ctrlID, OUT strrefValue);
  2826. DWORD PathType = 0;
  2827. if ( NERR_Success != I_NetPathType(
  2828. NULL,
  2829. const_cast<LPTSTR>((LPCTSTR)strrefValue),
  2830. &PathType,
  2831. 0 ) ||
  2832. ITYPE_PATH_ABSD != PathType )
  2833. {
  2834. PVOID apv[1] = {(LPWSTR)(LPCWSTR)strrefValue};
  2835. ReportErrorEx (::GetParent(m_hWnd),IDS_2_INVALID_ABSOLUTE_PATH,S_OK,
  2836. MB_OK, apv, 1);
  2837. SetDlgItemFocus(ctrlID);
  2838. return FALSE;
  2839. }
  2840. return TRUE;
  2841. }
  2842. #endif // FRS_CREATE
  2843. ///////////////////////////////////////////////////////////////
  2844. ///////////////////////////////////////////////////////////////
  2845. // NEW SITE LINKWIZARD
  2846. BEGIN_MESSAGE_MAP(CCreatePageWithDuellingListboxes, CCreateNewObjectDataPage)
  2847. ON_EN_CHANGE(IDC_NEW_OBJECT_NAME, OnNameChange)
  2848. ON_BN_CLICKED(IDC_DUELLING_RB_ADD, OnDuellingButtonAdd)
  2849. ON_BN_CLICKED(IDC_DUELLING_RB_REMOVE, OnDuellingButtonRemove)
  2850. ON_LBN_SELCHANGE(IDC_DUELLING_LB_OUT, OnDuellingListboxSelchange)
  2851. ON_LBN_SELCHANGE(IDC_DUELLING_LB_IN, OnDuellingListboxSelchange)
  2852. ON_WM_DESTROY()
  2853. END_MESSAGE_MAP()
  2854. CCreatePageWithDuellingListboxes::CCreatePageWithDuellingListboxes(
  2855. UINT nIDTemplate,
  2856. LPCWSTR lpcwszAttrName,
  2857. const DSPROP_BSTR_BLOCK& bstrblock )
  2858. : CCreateNewObjectDataPage(nIDTemplate)
  2859. , m_strAttrName( lpcwszAttrName )
  2860. , m_bstrblock( bstrblock )
  2861. {
  2862. }
  2863. BOOL CCreatePageWithDuellingListboxes::GetData(IADs*)
  2864. {
  2865. return FALSE; // start disabled
  2866. }
  2867. void CCreatePageWithDuellingListboxes::OnNameChange()
  2868. {
  2869. GetDlgItemText(IDC_NEW_OBJECT_NAME, OUT m_strName);
  2870. m_strName.TrimLeft();
  2871. m_strName.TrimRight();
  2872. SetWizardButtons();
  2873. }
  2874. void CCreatePageWithDuellingListboxes::SetWizardButtons()
  2875. {
  2876. BOOL fAllowApply = !(m_strName.IsEmpty());
  2877. GetWiz()->SetWizardButtons(this, fAllowApply);
  2878. }
  2879. HRESULT CCreatePageWithDuellingListboxes::SetData(BOOL)
  2880. {
  2881. HRESULT hr = S_OK;
  2882. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo = GetWiz()->GetInfo();
  2883. // Store the object name in the temporary storage
  2884. hr = pNewADsObjectCreateInfo->HrCreateNew(m_strName);
  2885. if (FAILED(hr))
  2886. {
  2887. return hr;
  2888. }
  2889. // build the siteList attribute
  2890. CStringList strlist;
  2891. int cItems = ListBox_GetCount( m_hwndInListbox );
  2892. ASSERT( 0 <= cItems );
  2893. for (int i = cItems-1; i >= 0; i--)
  2894. {
  2895. BSTR bstrDN = (BSTR)ListBox_GetItemData( m_hwndInListbox, i );
  2896. ASSERT( NULL != bstrDN );
  2897. strlist.AddHead( bstrDN );
  2898. }
  2899. ASSERT( strlist.GetCount() > 0 );
  2900. CComVariant svar;
  2901. hr = HrStringListToVariant( OUT svar, IN strlist );
  2902. ASSERT( SUCCEEDED(hr) );
  2903. //
  2904. // set the siteList attribute
  2905. //
  2906. hr = pNewADsObjectCreateInfo->HrAddVariantCopyVar(CComBSTR(m_strAttrName), svar);
  2907. ASSERT(SUCCEEDED(hr));
  2908. //
  2909. // no need to commit here, wait until after extensions have had a shot
  2910. //
  2911. return hr;
  2912. }
  2913. //
  2914. // The duelling listbox support uses exports from DSPROP.DLL. Correct
  2915. // functioning requires that the control IDs be numbered correctly.
  2916. // JonN 8/31/98
  2917. //
  2918. void CCreatePageWithDuellingListboxes::OnDuellingButtonAdd()
  2919. {
  2920. DSPROP_Duelling_ButtonClick(
  2921. m_hWnd,
  2922. IDC_DUELLING_RB_ADD );
  2923. SetWizardButtons();
  2924. }
  2925. void CCreatePageWithDuellingListboxes::OnDuellingButtonRemove()
  2926. {
  2927. DSPROP_Duelling_ButtonClick(
  2928. m_hWnd,
  2929. IDC_DUELLING_RB_REMOVE );
  2930. SetWizardButtons();
  2931. }
  2932. void CCreatePageWithDuellingListboxes::OnDuellingListboxSelchange()
  2933. {
  2934. // don't allow Add/Remove if there are <3 sites
  2935. if (2 < (ListBox_GetCount(m_hwndInListbox)
  2936. + ListBox_GetCount(m_hwndOutListbox)) )
  2937. {
  2938. DSPROP_Duelling_UpdateButtons( m_hWnd, IDC_DUELLING_RB_ADD );
  2939. }
  2940. }
  2941. void CCreatePageWithDuellingListboxes::OnDestroy()
  2942. {
  2943. DSPROP_Duelling_ClearListbox( m_hwndInListbox );
  2944. DSPROP_Duelling_ClearListbox( m_hwndOutListbox );
  2945. CCreateNewObjectDataPage::OnDestroy();
  2946. }
  2947. BOOL CCreatePageWithDuellingListboxes::OnSetActive()
  2948. {
  2949. m_hwndInListbox = ::GetDlgItem( m_hWnd, IDC_DUELLING_LB_IN );
  2950. m_hwndOutListbox = ::GetDlgItem( m_hWnd, IDC_DUELLING_LB_OUT );
  2951. ASSERT( NULL != m_hwndInListbox && NULL != m_hwndOutListbox );
  2952. HWND hwndInitial = m_hwndOutListbox;
  2953. if (3 > m_bstrblock.QueryCount())
  2954. {
  2955. // move all sitelinks to "in"
  2956. // Add/Remove will never be enabled
  2957. hwndInitial = m_hwndInListbox;
  2958. }
  2959. HRESULT hr = DSPROP_Duelling_Populate(
  2960. hwndInitial,
  2961. m_bstrblock
  2962. );
  2963. if ( FAILED(hr) )
  2964. return FALSE;
  2965. return CCreateNewObjectDataPage::OnSetActive();
  2966. }
  2967. CCreateNewSiteLinkPage::CCreateNewSiteLinkPage(
  2968. const DSPROP_BSTR_BLOCK& bstrblock )
  2969. : CCreatePageWithDuellingListboxes(
  2970. CCreateNewSiteLinkPage::IDD,
  2971. gsz_siteList,
  2972. bstrblock)
  2973. {
  2974. }
  2975. BOOL CCreateNewSiteLinkPage::OnInitDialog()
  2976. {
  2977. CCreatePageWithDuellingListboxes::OnInitDialog();
  2978. // NTRAID#NTBUG9-477962-2001/10/09-jeffjon
  2979. // Limit the sitelink name to MAX_RDN_SIZE characters to avoid overflow
  2980. SendDlgItemMessage(IDC_NEW_OBJECT_NAME, EM_SETLIMITTEXT, (WPARAM)MAX_RDN_SIZE, 0);
  2981. return FALSE;
  2982. }
  2983. BOOL CCreateNewSiteLinkPage::OnSetActive()
  2984. {
  2985. if (m_bstrblock.QueryCount() < 2)
  2986. {
  2987. // change "must contain two sites" text
  2988. CString sz;
  2989. sz.LoadString(IDS_SITELINK_DLGTEXT_ONE_SITE);
  2990. ::SetDlgItemText( m_hWnd, IDC_STATIC_MESSAGE, sz );
  2991. }
  2992. return CCreatePageWithDuellingListboxes::OnSetActive();
  2993. }
  2994. HRESULT CCreateNewSiteLinkPage::SetData(BOOL bSilent)
  2995. {
  2996. BOOL fAllowApply = TRUE;
  2997. int cIn = ListBox_GetCount(m_hwndInListbox);
  2998. if (1 > cIn)
  2999. fAllowApply = FALSE; // zero sites is a constraint violation
  3000. else if (2 > cIn)
  3001. {
  3002. int cOut = ListBox_GetCount(m_hwndOutListbox);
  3003. if (1 <= cOut) // allow one site if the "out" listbox is empty
  3004. fAllowApply = FALSE;
  3005. }
  3006. if (fAllowApply)
  3007. return CCreatePageWithDuellingListboxes::SetData(bSilent);
  3008. if (!bSilent)
  3009. {
  3010. ReportMessageEx(m_hWnd,
  3011. IDS_SITELINK_NEEDS_TWO_SITES,
  3012. MB_OK | MB_ICONSTOP);
  3013. }
  3014. return E_FAIL;
  3015. }
  3016. CCreateNewSiteLinkWizard::CCreateNewSiteLinkWizard(
  3017. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo,
  3018. const DSPROP_BSTR_BLOCK& bstrblock )
  3019. : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  3020. , m_page1( bstrblock )
  3021. {
  3022. AddPage(&m_page1);
  3023. }
  3024. CCreateNewSiteLinkBridgePage::CCreateNewSiteLinkBridgePage(
  3025. const DSPROP_BSTR_BLOCK& bstrblock )
  3026. : CCreatePageWithDuellingListboxes(
  3027. CCreateNewSiteLinkBridgePage::IDD,
  3028. gsz_siteLinkList,
  3029. bstrblock)
  3030. {
  3031. }
  3032. BOOL CCreateNewSiteLinkBridgePage::OnInitDialog()
  3033. {
  3034. CCreatePageWithDuellingListboxes::OnInitDialog();
  3035. // NTRAID#NTBUG9-477962-2001/10/09-jeffjon
  3036. // Limit the site link bridge name to MAX_RDN_SIZE characters to avoid overflow
  3037. SendDlgItemMessage(IDC_NEW_OBJECT_NAME, EM_SETLIMITTEXT, (WPARAM)MAX_RDN_SIZE, 0);
  3038. return FALSE;
  3039. }
  3040. HRESULT CCreateNewSiteLinkBridgePage::SetData(BOOL bSilent)
  3041. {
  3042. BOOL fAllowApply = TRUE;
  3043. int cIn = ListBox_GetCount(m_hwndInListbox);
  3044. if (2 > cIn)
  3045. {
  3046. fAllowApply = FALSE;
  3047. }
  3048. if (fAllowApply)
  3049. return CCreatePageWithDuellingListboxes::SetData(bSilent);
  3050. if (!bSilent)
  3051. {
  3052. ReportMessageEx(m_hWnd,
  3053. IDS_SITELINKBRIDGE_NEEDS_TWO_SITELINKS,
  3054. MB_OK | MB_ICONSTOP);
  3055. }
  3056. return E_FAIL;
  3057. }
  3058. CCreateNewSiteLinkBridgeWizard:: CCreateNewSiteLinkBridgeWizard(
  3059. CNewADsObjectCreateInfo* pNewADsObjectCreateInfo,
  3060. const DSPROP_BSTR_BLOCK& bstrblockSiteLinks )
  3061. : CCreateNewObjectWizardBase(pNewADsObjectCreateInfo)
  3062. , m_page1( bstrblockSiteLinks )
  3063. {
  3064. AddPage(&m_page1);
  3065. }
  3066. // NTRAID#NTBUG9-283026-2001/06/13-lucios - Begin
  3067. // Extending the detection of <automatically generated>
  3068. // for object creation from JonN's original code inserted in
  3069. // rename.cpp, CDSRenameNTDSConnection::DoRename()
  3070. BOOL CCreateNewObjectConnectionWizard::OnFinish()
  3071. {
  3072. CString strNewName;
  3073. m_page1.GetDlgItemText(IDC_EDIT_OBJECT_NAME,strNewName);
  3074. strNewName.TrimLeft();
  3075. strNewName.TrimRight();
  3076. CString strKCCGenerated;
  3077. strKCCGenerated.LoadString (IDS_CONNECTION_KCC_GENERATED);
  3078. if ( !strNewName.CompareNoCase(strKCCGenerated) )
  3079. {
  3080. TRACE (_T("CCreateNewObjectCnWizard::OnFinish blocked creation of object"));
  3081. ReportErrorEx (m_page1.m_hWnd,IDS_CONNECTION_RENAME_KCCSTRING,S_OK,
  3082. MB_OK | MB_ICONWARNING, NULL, 0);
  3083. return false;
  3084. }
  3085. return CCreateNewObjectCnWizard::OnFinish();
  3086. }
  3087. // NTRAID#NTBUG9-283026-2001/06/13-lucios - End