Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3366 lines
92 KiB

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