Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1168 lines
35 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: createwiz.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. ////////////////////////////////////////////////
  11. // createwiz.cpp
  12. #include "pch.h"
  13. #include <SnapBase.h>
  14. #include "createwiz.h"
  15. #include "connection.h"
  16. #include "editorui.h"
  17. #include "query.h"
  18. #include "resource.h"
  19. #ifdef DEBUG_ALLOCATOR
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. #endif
  26. //////////////////////////////////////////////////////////////////////////////////////
  27. // CCreateClassPage
  28. BEGIN_MESSAGE_MAP(CCreateClassPage, CPropertyPageBase)
  29. //{{AFX_MSG_MAP(CADsObjectDialog)
  30. // ON_CBN_SELCHANGE(IDC_CLASS_LIST, OnSelChangeClassList)
  31. //}}AFX_MSG_MAP
  32. END_MESSAGE_MAP()
  33. CCreateClassPage::CCreateClassPage(CADSIEditContainerNode* pNode) : CPropertyPageBase(IDD_CREATE_CLASS_PAGE)
  34. {
  35. m_pCurrentNode = pNode;
  36. }
  37. CCreateClassPage::~CCreateClassPage()
  38. {
  39. }
  40. BOOL CCreateClassPage::OnInitDialog()
  41. {
  42. CPropertyPageBase::OnInitDialog();
  43. CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST);
  44. // disable IME support on numeric edit fields
  45. ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_NUMBER_VALUE_BOX), NULL);
  46. FillList();
  47. pClassList->SetCurSel(0);
  48. return TRUE;
  49. }
  50. void CCreateClassPage::FillList()
  51. {
  52. CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST);
  53. HRESULT hr, hCredResult;
  54. CString sPath, schema;
  55. m_pCurrentNode->GetADsObject()->GetPath(sPath);
  56. CConnectionData* pConnectData = m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData();
  57. // bind to Container for IPropertyList
  58. CComPtr<IADsPropertyList> spDSObject;
  59. hr = OpenObjectWithCredentials(
  60. pConnectData,
  61. pConnectData->GetCredentialObject()->UseCredentials(),
  62. sPath,
  63. IID_IADsPropertyList,
  64. (LPVOID*) &spDSObject,
  65. GetSafeHwnd(),
  66. hCredResult
  67. );
  68. if (FAILED(hr))
  69. {
  70. TRACE(_T("Bind to Container for IPropertyList failed: %lx.\n"), hr);
  71. return;
  72. }
  73. // need to do this hack to load the cache
  74. CComPtr<IADs> spIADs;
  75. hr = spDSObject->QueryInterface (IID_IADs, (LPVOID*)&spIADs);
  76. if (FAILED(hr))
  77. {
  78. TRACE(_T("QI to Container for IADs failed: %lx.\n"), hr);
  79. return;
  80. }
  81. PWSTR g_wzAllowedChildClassesEffective = L"allowedChildClassesEffective";
  82. CComVariant varHints;
  83. ADsBuildVarArrayStr (&g_wzAllowedChildClassesEffective, 1, &varHints);
  84. spIADs->GetInfoEx(varHints, 0);
  85. // get allowed child classes as VARIANT
  86. CComVariant VarProp;
  87. hr = spDSObject->GetPropertyItem(CComBSTR(g_wzAllowedChildClassesEffective),
  88. ADSTYPE_CASE_IGNORE_STRING, &VarProp);
  89. if (FAILED(hr))
  90. {
  91. TRACE(_T("GetPropertyItem failed: %lx.\n"), hr);
  92. return;
  93. }
  94. // extract the IADsPropertyEntry interface pointer
  95. IDispatch* pDisp = V_DISPATCH(&VarProp);
  96. CComPtr<IADsPropertyEntry> spPropEntry;
  97. hr = pDisp->QueryInterface(IID_IADsPropertyEntry, (void **)&spPropEntry);
  98. if (FAILED(hr))
  99. {
  100. return;
  101. }
  102. // get SAFEARRAY out of IADsPropertyEntry pointer
  103. CComVariant Var;
  104. hr = spPropEntry->get_Values(&Var);
  105. if (FAILED(hr))
  106. {
  107. return;
  108. }
  109. long uBound, lBound;
  110. hr = ::SafeArrayGetUBound(V_ARRAY(&Var), 1, &uBound);
  111. hr = ::SafeArrayGetLBound(V_ARRAY(&Var), 1, &lBound);
  112. VARIANT* pNames;
  113. hr = ::SafeArrayAccessData(V_ARRAY(&Var), (void **)&pNames);
  114. if (FAILED(hr))
  115. {
  116. TRACE(_T("Accessing safearray data failed: %lx.\n"), hr);
  117. SafeArrayUnaccessData(V_ARRAY(&Var));
  118. return;
  119. }
  120. // now got the array of items, loop through them
  121. WCHAR szFrendlyName[1024];
  122. HRESULT hrName;
  123. long nChildClassesCount = uBound - lBound + 1;
  124. for (long index = lBound; index <= uBound; index++)
  125. {
  126. CComPtr<IADsPropertyValue> spEntry;
  127. hr = (pNames[index].pdispVal)->QueryInterface (IID_IADsPropertyValue,
  128. (void **)&spEntry);
  129. if (SUCCEEDED(hr))
  130. {
  131. BSTR bsObject = NULL;
  132. hr = spEntry->get_CaseIgnoreString(&bsObject);
  133. if (SUCCEEDED(hr))
  134. {
  135. // hrName = ::DsGetFriendlyClassName(bsObject, szFrendlyName, 1024);
  136. // ASSERT(SUCCEEDED(hrName));
  137. pClassList->AddString(bsObject);
  138. } // if
  139. ::SysFreeString(bsObject);
  140. } // if
  141. } // for
  142. ::SafeArrayUnaccessData(V_ARRAY(&Var));
  143. }
  144. BOOL CCreateClassPage::OnSetActive()
  145. {
  146. GetHolder()->SetWizardButtonsFirst(TRUE);
  147. return TRUE;
  148. }
  149. LRESULT CCreateClassPage::OnWizardNext()
  150. {
  151. CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST);
  152. CCreatePageHolder* pHolder = dynamic_cast<CCreatePageHolder*>(GetHolder());
  153. ASSERT(pHolder != NULL);
  154. CString sClass;
  155. pClassList->GetText(pClassList->GetCurSel(), sClass);
  156. if (m_sClass != sClass)
  157. {
  158. m_sClass = sClass;
  159. pHolder->AddAttrPage(sClass);
  160. }
  161. return 0; //next page
  162. }
  163. /////////////////////////////////////////////////////////////////////////////////////////
  164. // CCreateAttributePage
  165. BEGIN_MESSAGE_MAP(CCreateAttributePage, CPropertyPageBase)
  166. //{{AFX_MSG_MAP(CADsObjectDialog)
  167. ON_EN_CHANGE(IDC_ATTR_VALUE_BOX, OnEditChangeValue)
  168. ON_EN_CHANGE(IDC_NUMBER_VALUE_BOX, OnEditChangeValue)
  169. //}}AFX_MSG_MAP
  170. END_MESSAGE_MAP()
  171. CCreateAttributePage::CCreateAttributePage(UINT nID, CADSIAttr* pAttr) : CPropertyPageBase(nID)
  172. {
  173. m_bInitialized = FALSE;
  174. m_bNumber = FALSE;
  175. m_pAttr = pAttr;
  176. }
  177. CCreateAttributePage::~CCreateAttributePage()
  178. {
  179. }
  180. BOOL CCreateAttributePage::OnInitDialog()
  181. {
  182. CPropertyPageBase::OnInitDialog();
  183. CEdit* pAttrBox = (CEdit*)GetDlgItem(IDC_ATTR_BOX);
  184. // disable IME support on numeric edit fields
  185. ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_NUMBER_VALUE_BOX), NULL);
  186. CString sAttr;
  187. m_pAttr->GetProperty(sAttr);
  188. pAttrBox->SetWindowText(sAttr);
  189. SetSyntax(sAttr);
  190. m_bInitialized = TRUE;
  191. return TRUE;
  192. }
  193. void CCreateAttributePage::GetValue(CString& sVal)
  194. {
  195. CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX);
  196. pValueBox->GetWindowText(sVal);
  197. }
  198. void CCreateAttributePage::SetSyntax(CString sAttr)
  199. {
  200. CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX);
  201. CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX);
  202. CEdit* pSyntaxBox = (CEdit*)GetDlgItem(IDC_SYNTAX_BOX);
  203. CCreatePageHolder* pHolder = dynamic_cast<CCreatePageHolder*>(GetHolder());
  204. ASSERT(pHolder != NULL);
  205. if (pHolder != NULL)
  206. {
  207. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(pHolder->GetTreeNode());
  208. ASSERT(pContNode != NULL);
  209. if (pContNode != NULL)
  210. {
  211. CConnectionData* pConnectData = pContNode->GetADsObject()->GetConnectionNode()->GetConnectionData();
  212. CString sPath, sSyntax;
  213. CComPtr<IADsProperty> pProp;
  214. pHolder->GetSchemaPath(sAttr, sPath);
  215. // bind to object with authentication
  216. //
  217. HRESULT hr, hCredResult;
  218. hr = OpenObjectWithCredentials(
  219. pConnectData,
  220. pConnectData->GetCredentialObject()->UseCredentials(),
  221. sPath,
  222. IID_IADsProperty,
  223. (LPVOID*) &pProp,
  224. GetSafeHwnd(),
  225. hCredResult
  226. );
  227. if ( FAILED(hr) )
  228. {
  229. if (SUCCEEDED(hCredResult))
  230. {
  231. ADSIEditErrorMessage(hr);
  232. }
  233. return;
  234. }
  235. BSTR bstr;
  236. hr = pProp->get_Syntax( &bstr );
  237. if ( SUCCEEDED(hr) )
  238. {
  239. sSyntax = bstr;
  240. }
  241. pSyntaxBox->SetWindowText(sSyntax);
  242. BOOL varType = VariantTypeFromSyntax(sSyntax);
  243. switch (varType)
  244. {
  245. case VT_BSTR :
  246. pNumberBox->ShowWindow(FALSE);
  247. pValueBox->ShowWindow(TRUE);
  248. m_bNumber = FALSE;
  249. break;
  250. case VT_I4 :
  251. case VT_I8 :
  252. pNumberBox->ShowWindow(TRUE);
  253. pValueBox->ShowWindow(FALSE);
  254. m_bNumber = TRUE;
  255. break;
  256. default :
  257. pNumberBox->ShowWindow(FALSE);
  258. pValueBox->ShowWindow(TRUE);
  259. m_bNumber = FALSE;
  260. break;
  261. }
  262. pProp->get_MaxRange(&m_lMaxRange);
  263. pProp->get_MinRange(&m_lMinRange);
  264. SetADsType(sAttr);
  265. }
  266. }
  267. }
  268. void CCreateAttributePage::SetADsType(CString sProp)
  269. {
  270. CString schema, sServer;
  271. BOOL bResult = FALSE;
  272. CConnectionData* pConnectData;
  273. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(GetHolder()->GetTreeNode());
  274. if (pContNode == NULL)
  275. {
  276. CADSIEditLeafNode* pLeafNode = dynamic_cast<CADSIEditLeafNode*>(GetHolder()->GetTreeNode());
  277. ASSERT(pLeafNode != NULL);
  278. bResult = pLeafNode->BuildSchemaPath(schema);
  279. pConnectData = pLeafNode->GetADsObject()->GetConnectionNode()->GetConnectionData();
  280. }
  281. else
  282. {
  283. bResult = pContNode->BuildSchemaPath(schema);
  284. pConnectData = pContNode->GetADsObject()->GetConnectionNode()->GetConnectionData();
  285. }
  286. if (!bResult)
  287. {
  288. return;
  289. }
  290. CADSIQueryObject schemaSearch;
  291. // Initialize search object with path, username and password
  292. //
  293. HRESULT hr = schemaSearch.Init(schema, pConnectData->GetCredentialObject());
  294. if (FAILED(hr))
  295. {
  296. ADSIEditErrorMessage(hr);
  297. return;
  298. }
  299. int cCols = 2;
  300. LPWSTR pszAttributes[] = {L"attributeSyntax", L"isSingleValued"};
  301. ADS_SEARCH_COLUMN ColumnData;
  302. hr = schemaSearch.SetSearchPrefs(ADS_SCOPE_ONELEVEL);
  303. if (FAILED(hr))
  304. {
  305. ADSIEditErrorMessage(hr);
  306. return;
  307. }
  308. CString csFilter = _T("(&(objectClass=attributeSchema)(lDAPDisplayName=") +
  309. sProp + _T("))");
  310. schemaSearch.SetFilterString((LPWSTR)(LPCWSTR)csFilter);
  311. schemaSearch.SetAttributeList (pszAttributes, cCols);
  312. hr = schemaSearch.DoQuery ();
  313. if (SUCCEEDED(hr))
  314. {
  315. hr = schemaSearch.GetNextRow();
  316. if (SUCCEEDED(hr))
  317. {
  318. hr = schemaSearch.GetColumn(pszAttributes[0],
  319. &ColumnData);
  320. if (SUCCEEDED(hr))
  321. {
  322. TRACE(_T("\t\tattributeSyntax: %s\n"),
  323. ColumnData.pADsValues->CaseIgnoreString);
  324. CString szSyntax;
  325. ADSTYPE dwType;
  326. dwType = GetADsTypeFromString(ColumnData.pADsValues->CaseIgnoreString, szSyntax);
  327. m_pAttr->SetADsType(dwType);
  328. m_pAttr->SetSyntax(szSyntax);
  329. }
  330. else
  331. {
  332. ADSIEditErrorMessage(hr);
  333. }
  334. hr = schemaSearch.GetColumn(pszAttributes[1], &ColumnData);
  335. if (SUCCEEDED(hr))
  336. {
  337. TRACE(_T("\t\tisSingleValued: %d\n"),
  338. ColumnData.pADsValues->Boolean);
  339. m_pAttr->SetMultivalued(!ColumnData.pADsValues->Boolean);
  340. }
  341. else
  342. {
  343. ADSIEditErrorMessage(hr);
  344. }
  345. }
  346. }
  347. }
  348. void CCreateAttributePage::OnEditChangeValue()
  349. {
  350. CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX);
  351. CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX);
  352. CString sValue, sAttr;
  353. CEdit* pBox;
  354. if (m_bNumber)
  355. {
  356. pBox = pNumberBox;
  357. }
  358. else
  359. {
  360. pBox = pValueBox;
  361. }
  362. pBox->GetWindowText(sValue);
  363. CCreatePageHolder* pHolder = dynamic_cast<CCreatePageHolder*>(GetHolder());
  364. ASSERT(pHolder != NULL);
  365. m_pAttr->GetProperty(sAttr);
  366. CString sNamingAttr;
  367. pHolder->GetNamingAttribute(sNamingAttr);
  368. if (sAttr == sNamingAttr)
  369. {
  370. pHolder->SetName(sValue);
  371. }
  372. if (sValue == _T(""))
  373. {
  374. GetHolder()->SetWizardButtons(PSWIZB_BACK);
  375. }
  376. else
  377. {
  378. GetHolder()->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
  379. }
  380. }
  381. BOOL CCreateAttributePage::OnSetActive()
  382. {
  383. if (m_bInitialized)
  384. {
  385. OnEditChangeValue();
  386. }
  387. else
  388. {
  389. GetHolder()->SetWizardButtonsMiddle(FALSE);
  390. }
  391. return TRUE;
  392. }
  393. LRESULT CCreateAttributePage::OnWizardNext()
  394. {
  395. CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX);
  396. CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX);
  397. m_pAttr->SetDirty(TRUE);
  398. CString sValue;
  399. CEdit* pBox;
  400. if (m_bNumber)
  401. {
  402. pBox = pNumberBox;
  403. }
  404. else
  405. {
  406. pBox = pValueBox;
  407. }
  408. pBox->GetWindowText(sValue);
  409. m_sAttrValue.RemoveAll();
  410. m_sAttrValue.AddTail(sValue);
  411. HRESULT hr = m_pAttr->SetValues(m_sAttrValue);
  412. if (FAILED(hr))
  413. {
  414. ADSIEditMessageBox(IDS_MSG_INCORRECT_FORMAT, MB_OK);
  415. return -1; //don't advance pages
  416. }
  417. return 0; //next page
  418. }
  419. /////////////////////////////////////////////////////////////////////////////////////////
  420. // CCreateFinishPage
  421. BEGIN_MESSAGE_MAP(CCreateFinishPage, CPropertyPageBase)
  422. //{{AFX_MSG_MAP(CADsObjectDialog)
  423. ON_BN_CLICKED(IDC_BUTTON_MORE, OnMore)
  424. //}}AFX_MSG_MAP
  425. END_MESSAGE_MAP()
  426. CCreateFinishPage::CCreateFinishPage(UINT nID) : CPropertyPageBase(nID)
  427. {
  428. m_bInitialized = FALSE;
  429. }
  430. CCreateFinishPage::~CCreateFinishPage()
  431. {
  432. }
  433. BOOL CCreateFinishPage::OnInitDialog()
  434. {
  435. CPropertyPageBase::OnInitDialog();
  436. GetHolder()->SetWizardButtons(PSWIZB_FINISH);
  437. m_bInitialized = TRUE;
  438. return TRUE;
  439. }
  440. void CCreateFinishPage::OnMore()
  441. {
  442. CCreatePageHolder* pHolder = dynamic_cast<CCreatePageHolder*>(GetHolder());
  443. ASSERT(pHolder != NULL);
  444. pHolder->OnMore();
  445. }
  446. BOOL CCreateFinishPage::OnSetActive()
  447. {
  448. GetHolder()->SetWizardButtons(PSWIZB_FINISH | PSWIZB_BACK);
  449. return TRUE;
  450. }
  451. BOOL CCreateFinishPage::OnWizardFinish()
  452. {
  453. CCreatePageHolder* pHolder = dynamic_cast<CCreatePageHolder*>(GetHolder());
  454. ASSERT(pHolder != NULL);
  455. return pHolder->OnFinish();
  456. }
  457. ////////////////////////////////////////////////////////////////////////////////////////
  458. // CCreatePageHolder
  459. CCreatePageHolder:: CCreatePageHolder(CContainerNode* pContNode, CADSIEditContainerNode* pNode,
  460. CComponentDataObject* pComponentData) : CPropertyPageHolderBase(pContNode, pNode, pComponentData)
  461. {
  462. ASSERT(pComponentData != NULL);
  463. ASSERT(pContNode != NULL);
  464. ASSERT(pContNode == GetContainerNode());
  465. m_pCurrentNode = pNode;
  466. m_pComponentData = pComponentData;
  467. m_bAutoDeletePages = FALSE; // we have the page as embedded member
  468. m_pClassPage = new CCreateClassPage(pNode);
  469. AddPageToList((CPropertyPageBase*)m_pClassPage);
  470. }
  471. CCreatePageHolder::~CCreatePageHolder()
  472. {
  473. m_pageList.RemoveAll();
  474. }
  475. void CCreatePageHolder::AddAttrPage(CString sClass)
  476. {
  477. RemoveAllPages();
  478. m_sClass = sClass;
  479. CStringList sMandList;
  480. GetMandatoryAttr(sClass, &sMandList);
  481. CString sAttr;
  482. if (!m_pCurrentNode->GetNamingAttribute(sClass, &m_sNamingAttr))
  483. {
  484. return;
  485. }
  486. // Remove attributes from list that do not need a page
  487. RemovePresetAttr(&sMandList);
  488. // find the naming attribute and put it first
  489. POSITION fpos = sMandList.Find(m_sNamingAttr.GetHead());
  490. if (fpos != NULL)
  491. {
  492. sMandList.AddHead(sMandList.GetAt(fpos));
  493. sMandList.RemoveAt(fpos);
  494. }
  495. else
  496. {
  497. sMandList.AddHead(m_sNamingAttr.GetHead());
  498. }
  499. POSITION pos = sMandList.GetHeadPosition();
  500. while (pos != NULL)
  501. {
  502. CCreateAttributePage* pAttrPage;
  503. sAttr = sMandList.GetNext(pos);
  504. // Maintain the list of attributes here so that we can pop up the prop page for more advanced editting
  505. CADSIAttr* pNewAttr = new CADSIAttr(sAttr);
  506. m_AttrList.AddTail(pNewAttr);
  507. pAttrPage = new CCreateAttributePage(IDD_CREATE_EMPTY_PAGE, pNewAttr);
  508. // Add the naming attribute as the first page so that they type the name first
  509. if (sAttr == m_sNamingAttr.GetHead())
  510. {
  511. m_pageList.AddHead(pAttrPage);
  512. }
  513. else
  514. {
  515. m_pageList.AddTail(pAttrPage);
  516. }
  517. }
  518. // Add the finish page to the end
  519. CCreateFinishPage* pFinishPage = new CCreateFinishPage(IDD_CREATE_LAST_PAGE);
  520. m_pageList.AddTail(pFinishPage);
  521. // Add the pages to the UI
  522. pos = m_pageList.GetHeadPosition();
  523. while (pos != NULL)
  524. {
  525. CPropertyPageBase* pAttrPage;
  526. pAttrPage = m_pageList.GetNext(pos);
  527. AddPageToList(pAttrPage);
  528. AddPageToSheet(pAttrPage);
  529. }
  530. }
  531. void CCreatePageHolder::RemovePresetAttr(CStringList* psMandList)
  532. {
  533. // this is a hack to keep from trying to set properties that are not allowed to be set.
  534. POSITION fpos = psMandList->Find(_T("nTSecurityDescriptor"));
  535. if (fpos != NULL)
  536. {
  537. psMandList->RemoveAt(fpos);
  538. }
  539. fpos = psMandList->Find(_T("instanceType"));
  540. if (fpos != NULL)
  541. {
  542. psMandList->RemoveAt(fpos);
  543. }
  544. fpos = psMandList->Find(_T("objectClass"));
  545. if (fpos != NULL)
  546. {
  547. psMandList->RemoveAt(fpos);
  548. }
  549. fpos = psMandList->Find(_T("objectCategory"));
  550. if (fpos != NULL)
  551. {
  552. psMandList->RemoveAt(fpos);
  553. }
  554. fpos = psMandList->Find(_T("objectSid"));
  555. if (fpos != NULL)
  556. {
  557. psMandList->RemoveAt(fpos);
  558. }
  559. fpos = psMandList->Find(_T("objectClassCategory"));
  560. if (fpos != NULL)
  561. {
  562. psMandList->RemoveAt(fpos);
  563. }
  564. fpos = psMandList->Find(_T("schemaIDGUID"));
  565. if (fpos != NULL)
  566. {
  567. psMandList->RemoveAt(fpos);
  568. }
  569. fpos = psMandList->Find(_T("defaultObjectCategory"));
  570. if (fpos != NULL)
  571. {
  572. psMandList->RemoveAt(fpos);
  573. }
  574. }
  575. void CCreatePageHolder::GetSchemaPath(CString sClass, CString& schema)
  576. {
  577. m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData()->GetAbstractSchemaPath(schema);
  578. schema += sClass;
  579. }
  580. void CCreatePageHolder::GetMandatoryAttr(CString sClass, CStringList* sMandList)
  581. {
  582. CComPtr<IADsClass> pClass;
  583. CString schema;
  584. HRESULT hr, hCredResult;
  585. GetSchemaPath(sClass, schema);
  586. CADSIEditContainerNode* pContNode = dynamic_cast<CADSIEditContainerNode*>(GetTreeNode());
  587. CConnectionData* pConnectData = m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData();
  588. hr = OpenObjectWithCredentials(
  589. pConnectData,
  590. pConnectData->GetCredentialObject()->UseCredentials(),
  591. schema,
  592. IID_IADsClass,
  593. (LPVOID*) &pClass,
  594. NULL,
  595. hCredResult
  596. );
  597. if ( FAILED(hr) )
  598. {
  599. if (SUCCEEDED(hCredResult))
  600. {
  601. ADSIEditErrorMessage(hr);
  602. }
  603. return;
  604. }
  605. VARIANT var;
  606. VariantInit(&var);
  607. pClass->get_MandatoryProperties(&var);
  608. VariantToStringList( var, *sMandList );
  609. VariantClear(&var);
  610. }
  611. void CCreatePageHolder::RemoveAllPages()
  612. {
  613. while (!m_pageList.IsEmpty())
  614. {
  615. CPropertyPageBase* pPropPage = m_pageList.RemoveTail();
  616. RemovePageFromSheet(pPropPage);
  617. RemovePageFromList(pPropPage, FALSE);
  618. delete pPropPage;
  619. }
  620. }
  621. BOOL CCreatePageHolder::OnFinish()
  622. {
  623. CWaitCursor cursor;
  624. CComPtr<IDirectoryObject> pDirObject;
  625. HRESULT hr, hCredResult;
  626. CString sContPath;
  627. m_pCurrentNode->GetADsObject()->GetPath(sContPath);
  628. CADSIEditContainerNode* pTreeNode = dynamic_cast<CADSIEditContainerNode*>(GetTreeNode());
  629. ASSERT(pTreeNode != NULL);
  630. CADSIEditConnectionNode* pConnectNode = pTreeNode->GetADsObject()->GetConnectionNode();
  631. CConnectionData* pConnectData = pConnectNode->GetConnectionData();
  632. hr = OpenObjectWithCredentials(
  633. pConnectData,
  634. pConnectData->GetCredentialObject()->UseCredentials(),
  635. sContPath,
  636. IID_IDirectoryObject,
  637. (LPVOID*) &pDirObject,
  638. NULL,
  639. hCredResult
  640. );
  641. if ( FAILED(hr) )
  642. {
  643. if (SUCCEEDED(hCredResult))
  644. {
  645. ADSIEditErrorMessage(hr);
  646. }
  647. return FALSE;
  648. }
  649. int iCount = m_AttrList.GetDirtyCount();
  650. ADS_ATTR_INFO* pAttrInfo;
  651. CComPtr<IDispatch> pDisp;
  652. do // false loop
  653. {
  654. pAttrInfo = new ADS_ATTR_INFO[iCount + 1]; // Add an extra to specify the class type
  655. if (NULL == pAttrInfo)
  656. {
  657. hr = E_OUTOFMEMORY;
  658. break;
  659. }
  660. int idx = 0;
  661. pAttrInfo[idx].pszAttrName = L"objectClass";
  662. pAttrInfo[idx].dwControlCode = ADS_ATTR_UPDATE;
  663. pAttrInfo[idx].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  664. pAttrInfo[idx].pADsValues = new ADSVALUE;
  665. if (NULL == pAttrInfo[idx].pADsValues)
  666. {
  667. hr = E_OUTOFMEMORY;
  668. break;
  669. }
  670. pAttrInfo[idx].pADsValues->dwType = ADSTYPE_CASE_IGNORE_STRING;
  671. int iLength = m_sClass.GetLength();
  672. // NOTICE-NTRAID#NTBUG9-562222-2002/03/04-artm Need to check if mem. allocation succeeded.
  673. pAttrInfo[idx].pADsValues->CaseIgnoreString = new WCHAR[iLength + 1];
  674. if (NULL == pAttrInfo[idx].pADsValues->CaseIgnoreString)
  675. {
  676. hr = E_OUTOFMEMORY;
  677. break;
  678. }
  679. // NOTICE-2002/03/04-artm wcscpy() used correctly
  680. // m_sClass will always be null terminated and has iLength characters
  681. // destination array has iLength + 1 space
  682. wcscpy(pAttrInfo[idx].pADsValues->CaseIgnoreString, m_sClass);
  683. pAttrInfo[idx].dwNumValues = 1;
  684. idx++;
  685. POSITION pos = m_AttrList.GetHeadPosition();
  686. while(pos != NULL)
  687. {
  688. CADSIAttr* pAttr = m_AttrList.GetNext(pos);
  689. if (pAttr->IsDirty())
  690. {
  691. pAttrInfo[idx] = *(pAttr->GetAttrInfo());
  692. idx++;
  693. }
  694. }
  695. // make the prefix uppercase
  696. CString sName(m_sName);
  697. int indx = sName.Find(L'=');
  698. if (indx != -1)
  699. {
  700. CString sPrefix, sRemaining;
  701. sPrefix = sName.Left(indx);
  702. sPrefix.MakeUpper();
  703. int iLen = sName.GetLength();
  704. sRemaining = sName.Right(iLen - indx);
  705. sName = sPrefix + sRemaining;
  706. }
  707. m_sName = sName;
  708. CString sEscapedName;
  709. hr = EscapePath(sEscapedName, sName);
  710. if (FAILED(hr))
  711. {
  712. break;
  713. }
  714. hr = pDirObject->CreateDSObject((LPWSTR)(LPCWSTR)sEscapedName, pAttrInfo, idx, &pDisp);
  715. if ( FAILED(hr) )
  716. {
  717. break;
  718. }
  719. }
  720. while (false); // end false loop
  721. // Clean up temporary variables.
  722. if (pAttrInfo)
  723. {
  724. if (pAttrInfo[0].pADsValues)
  725. {
  726. if (pAttrInfo[0].pADsValues->CaseIgnoreString)
  727. {
  728. delete [] pAttrInfo[0].pADsValues->CaseIgnoreString;
  729. }
  730. delete pAttrInfo[0].pADsValues;
  731. }
  732. delete [] pAttrInfo;
  733. pAttrInfo = NULL;
  734. }
  735. if (FAILED(hr))
  736. {
  737. // Format error message and pop up a dialog.
  738. ADSIEditErrorMessage(hr);
  739. return FALSE;
  740. }
  741. // Get the IDirectoryObject of the new node
  742. //
  743. CComPtr<IDirectoryObject> pNewDirObject;
  744. hr = pDisp->QueryInterface(IID_IDirectoryObject, (LPVOID*)&pNewDirObject);
  745. if ( FAILED(hr) )
  746. {
  747. //Format Error message and pop up a dialog
  748. ADSIEditErrorMessage(hr);
  749. return FALSE;
  750. }
  751. ADS_OBJECT_INFO* pInfo;
  752. hr = pNewDirObject->GetObjectInformation(&pInfo);
  753. if ( FAILED(hr) )
  754. {
  755. //Format Error message and pop up a dialog
  756. ADSIEditErrorMessage(hr);
  757. return FALSE;
  758. }
  759. CADsObject* pObject = new CADsObject();
  760. if (NULL == pObject)
  761. {
  762. ADSIEditErrorMessage(E_OUTOFMEMORY);
  763. return FALSE;
  764. }
  765. // Name
  766. CString sDN;
  767. pObject->SetName(m_sName);
  768. GetDN(pInfo->pszObjectDN, sDN);
  769. pObject->SetDN(sDN);
  770. pObject->SetPath(pInfo->pszObjectDN);
  771. // Class
  772. pObject->SetClass(pInfo->pszClassName);
  773. //Get the class object so that we can get the properties
  774. //
  775. CString sServer, schema;
  776. pConnectNode->GetConnectionData()->GetAbstractSchemaPath(schema);
  777. schema += CString(pInfo->pszClassName);
  778. do // false loop
  779. {
  780. // bind to object with authentication
  781. //
  782. CComPtr<IADsClass> pClass;
  783. hr = OpenObjectWithCredentials(
  784. pConnectData,
  785. pConnectData->GetCredentialObject()->UseCredentials(),
  786. schema,
  787. IID_IADsClass,
  788. (LPVOID*) &pClass,
  789. NULL,
  790. hCredResult
  791. );
  792. if ( FAILED(hr) )
  793. {
  794. if (SUCCEEDED(hCredResult))
  795. {
  796. ADSIEditErrorMessage(hr);
  797. }
  798. break;
  799. }
  800. pObject->SetComplete(TRUE);
  801. short bContainer;
  802. pClass->get_Container( &bContainer );
  803. if (bContainer == -1)
  804. {
  805. pObject->SetContainer(TRUE);
  806. CADSIEditContainerNode *pNewContNode = new CADSIEditContainerNode(pObject);
  807. if (pNewContNode)
  808. {
  809. // We don't want to free pObject since it was passed to a constructor. That
  810. // object is responsible for deleting that memory. Therefore, we set our
  811. // pointer to the memory to NULL so that we don't accidentally clean it
  812. // up.
  813. pObject = NULL;
  814. }
  815. else
  816. {
  817. hr = E_OUTOFMEMORY;
  818. ADSIEditErrorMessage(hr);
  819. break;
  820. }
  821. pNewContNode->SetDisplayName(m_sName);
  822. // Since we add pNewContNode to the list here we do not need to free
  823. // it before exiting function (it is freed when the list is freed).
  824. pNewContNode->GetADsObject()->SetConnectionNode(pConnectNode);
  825. VERIFY(pTreeNode->AddChildToListAndUI(pNewContNode, GetComponentData()));
  826. GetComponentData()->SetDescriptionBarText(pTreeNode);
  827. // Refresh any other subtrees of connections that contain this node
  828. //
  829. CList<CTreeNode*, CTreeNode*> foundNodeList;
  830. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(pTreeNode->GetRootContainer());
  831. if (pRootNode != NULL)
  832. {
  833. BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList);
  834. if (bFound)
  835. {
  836. POSITION posList = foundNodeList.GetHeadPosition();
  837. while (posList != NULL && SUCCEEDED(hr))
  838. {
  839. CADSIEditContainerNode* pFoundContNode = dynamic_cast<CADSIEditContainerNode*>(foundNodeList.GetNext(posList));
  840. if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode)
  841. {
  842. // Make a copy of the new container node and plug it into the list.
  843. CADSIEditContainerNode* pNewFoundNode = new CADSIEditContainerNode(pNewContNode);
  844. if (pNewFoundNode)
  845. {
  846. pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode());
  847. VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData()));
  848. GetComponentData()->SetDescriptionBarText(pFoundContNode);
  849. }
  850. else
  851. {
  852. hr = E_OUTOFMEMORY;
  853. ADSIEditErrorMessage(hr);
  854. }
  855. }
  856. }
  857. // Since the while() loop is last statement we do not
  858. // need to worry about breaking out of false loop if
  859. // we've hit an error condition (e.g. out of memory).
  860. }
  861. }
  862. }
  863. else
  864. {
  865. pObject->SetContainer(FALSE);
  866. CADSIEditLeafNode *pLeafNode = new CADSIEditLeafNode(pObject);
  867. if (pLeafNode)
  868. {
  869. // We don't want to free pObject since it was passed to a constructor. That
  870. // object is responsible for deleting that memory. Therefore, we set our
  871. // pointer to the memory to NULL so that we don't accidentally clean it
  872. // up.
  873. pObject = NULL;
  874. }
  875. else
  876. {
  877. hr = E_OUTOFMEMORY;
  878. ADSIEditErrorMessage(hr);
  879. break;
  880. }
  881. // Since we add pNewContNode to the list here we do not need to free
  882. // it before exiting function (it is freed when the list is freed).
  883. pLeafNode->SetDisplayName(m_sName);
  884. pLeafNode->GetADsObject()->SetConnectionNode(pConnectNode);
  885. VERIFY(pTreeNode->AddChildToListAndUI(pLeafNode, GetComponentData()));
  886. GetComponentData()->SetDescriptionBarText(pTreeNode);
  887. // Refresh any other subtrees of connections that contain this node
  888. //
  889. CList<CTreeNode*, CTreeNode*> foundNodeList;
  890. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(pTreeNode->GetRootContainer());
  891. if (pRootNode != NULL)
  892. {
  893. BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList);
  894. if (bFound)
  895. {
  896. POSITION posList = foundNodeList.GetHeadPosition();
  897. while (posList != NULL && SUCCEEDED(hr))
  898. {
  899. CADSIEditContainerNode* pFoundContNode = dynamic_cast<CADSIEditContainerNode*>(foundNodeList.GetNext(posList));
  900. if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode)
  901. {
  902. // Make a copy of the new leaf node and place it in the list.
  903. CADSIEditLeafNode* pNewFoundNode = new CADSIEditLeafNode(pLeafNode);
  904. if (pNewFoundNode)
  905. {
  906. pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode());
  907. VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData()));
  908. GetComponentData()->SetDescriptionBarText(pFoundContNode);
  909. }
  910. else
  911. {
  912. hr = E_OUTOFMEMORY;
  913. ADSIEditErrorMessage(hr);
  914. }
  915. }
  916. }
  917. // Since the while() loop is last statement we do not
  918. // need to worry about breaking out of false loop if
  919. // we've hit an error condition (e.g. out of memory).
  920. }
  921. }
  922. } // end else
  923. }
  924. while (false); // end false loop
  925. //
  926. // Clean up memory.
  927. //
  928. if (pObject)
  929. {
  930. delete pObject;
  931. }
  932. FreeADsMem(pInfo);
  933. return SUCCEEDED(hr);
  934. }
  935. HRESULT CCreatePageHolder::EscapePath(CString& sEscapedName, const CString& sName)
  936. {
  937. CComPtr<IADsPathname> pIADsPathname;
  938. HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  939. IID_IADsPathname, (PVOID *)&(pIADsPathname));
  940. ASSERT((S_OK == hr) && ((pIADsPathname) != NULL));
  941. CComBSTR bstrEscaped;
  942. hr = pIADsPathname->GetEscapedElement(0, //reserved
  943. (BSTR)(LPCWSTR)sName,
  944. &bstrEscaped);
  945. sEscapedName = bstrEscaped;
  946. return hr;
  947. }
  948. void CCreatePageHolder::GetDN(PWSTR pwszName, CString& sDN)
  949. {
  950. CComPtr<IADsPathname> pIADsPathname;
  951. HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  952. IID_IADsPathname, (PVOID *)&(pIADsPathname));
  953. ASSERT((S_OK == hr) && ((pIADsPathname) != NULL));
  954. hr = pIADsPathname->Set(CComBSTR(pwszName), ADS_SETTYPE_FULL);
  955. if (FAILED(hr))
  956. {
  957. sDN = L"";
  958. return;
  959. }
  960. // Get the leaf DN
  961. CComBSTR bstrDN;
  962. hr = pIADsPathname->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  963. if (FAILED(hr))
  964. {
  965. TRACE(_T("Failed to get element. %s"), hr);
  966. sDN = L"";
  967. }
  968. else
  969. {
  970. sDN = bstrDN;
  971. }
  972. }
  973. void CCreatePageHolder::OnMore()
  974. {
  975. CThemeContextActivator activator;
  976. CString sServer;
  977. m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData()->GetDomainServer(sServer);
  978. CCreateWizPropertyPageHolder propPage(m_pCurrentNode, m_pComponentData, m_sClass, sServer, &m_AttrList);
  979. if (propPage.DoModalDialog(m_sName) == IDOK)
  980. {
  981. }
  982. }