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.

1037 lines
26 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. (LPWSTR)(LPCWSTR)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(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. (LPWSTR)(LPCWSTR)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. (LPWSTR)(LPCWSTR)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. (LPWSTR)(LPCWSTR)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. pAttrInfo = new ADS_ATTR_INFO[iCount + 1]; // Add an extra to specify the class type
  652. int idx = 0;
  653. pAttrInfo[idx].pszAttrName = L"objectClass";
  654. pAttrInfo[idx].dwControlCode = ADS_ATTR_UPDATE;
  655. pAttrInfo[idx].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  656. pAttrInfo[idx].pADsValues = new ADSVALUE;
  657. pAttrInfo[idx].pADsValues->dwType = ADSTYPE_CASE_IGNORE_STRING;
  658. int iLength = m_sClass.GetLength();
  659. pAttrInfo[idx].pADsValues->CaseIgnoreString = new WCHAR[iLength + 1];
  660. wcscpy(pAttrInfo[idx].pADsValues->CaseIgnoreString, m_sClass);
  661. pAttrInfo[idx].dwNumValues = 1;
  662. idx++;
  663. POSITION pos = m_AttrList.GetHeadPosition();
  664. while(pos != NULL)
  665. {
  666. CADSIAttr* pAttr = m_AttrList.GetNext(pos);
  667. if (pAttr->IsDirty())
  668. {
  669. pAttrInfo[idx] = *(pAttr->GetAttrInfo());
  670. idx++;
  671. }
  672. }
  673. // make the prefix uppercase
  674. CString sName(m_sName);
  675. int indx = sName.Find(L'=');
  676. if (indx != -1)
  677. {
  678. CString sPrefix, sRemaining;
  679. sPrefix = sName.Left(indx);
  680. sPrefix.MakeUpper();
  681. int iLen = sName.GetLength();
  682. sRemaining = sName.Right(iLen - indx);
  683. sName = sPrefix + sRemaining;
  684. }
  685. m_sName = sName;
  686. CString sEscapedName;
  687. hr = EscapePath(sEscapedName, sName);
  688. if (FAILED(hr))
  689. {
  690. ADSIEditErrorMessage(hr);
  691. return FALSE;
  692. }
  693. CComPtr<IDispatch> pDisp;
  694. hr = pDirObject->CreateDSObject((LPWSTR)(LPCWSTR)sEscapedName, pAttrInfo, idx, &pDisp);
  695. if ( FAILED(hr) )
  696. {
  697. //Format Error message and pop up a dialog
  698. ADSIEditErrorMessage(hr);
  699. return FALSE;
  700. }
  701. delete pAttrInfo[0].pADsValues->CaseIgnoreString;
  702. delete pAttrInfo[0].pADsValues;
  703. delete[] pAttrInfo;
  704. // Get the IDirectoryObject of the new node
  705. //
  706. CComPtr<IDirectoryObject> pNewDirObject;
  707. hr = pDisp->QueryInterface(IID_IDirectoryObject, (LPVOID*)&pNewDirObject);
  708. if ( FAILED(hr) )
  709. {
  710. //Format Error message and pop up a dialog
  711. ADSIEditErrorMessage(hr);
  712. return FALSE;
  713. }
  714. ADS_OBJECT_INFO* pInfo;
  715. hr = pNewDirObject->GetObjectInformation(&pInfo);
  716. if ( FAILED(hr) )
  717. {
  718. //Format Error message and pop up a dialog
  719. ADSIEditErrorMessage(hr);
  720. return FALSE;
  721. }
  722. CADsObject* pObject = new CADsObject();
  723. // Name
  724. CString sDN;
  725. pObject->SetName(m_sName);
  726. GetDN(pInfo->pszObjectDN, sDN);
  727. pObject->SetDN(sDN);
  728. pObject->SetPath(pInfo->pszObjectDN);
  729. // Class
  730. pObject->SetClass(pInfo->pszClassName);
  731. //Get the class object so that we can get the properties
  732. //
  733. CString sServer, schema;
  734. pConnectNode->GetConnectionData()->GetAbstractSchemaPath(schema);
  735. schema += CString(pInfo->pszClassName);
  736. // bind to object with authentication
  737. //
  738. CComPtr<IADsClass> pClass;
  739. hr = OpenObjectWithCredentials(
  740. pConnectData,
  741. pConnectData->GetCredentialObject()->UseCredentials(),
  742. (LPWSTR)(LPCWSTR)schema,
  743. IID_IADsClass,
  744. (LPVOID*) &pClass,
  745. NULL,
  746. hCredResult
  747. );
  748. if ( FAILED(hr) )
  749. {
  750. if (SUCCEEDED(hCredResult))
  751. {
  752. ADSIEditErrorMessage(hr);
  753. }
  754. return FALSE;
  755. }
  756. pObject->SetComplete(TRUE);
  757. short bContainer;
  758. pClass->get_Container( &bContainer );
  759. if (bContainer == -1)
  760. {
  761. pObject->SetContainer(TRUE);
  762. CADSIEditContainerNode *pNewContNode = new CADSIEditContainerNode(pObject);
  763. pNewContNode->SetDisplayName(m_sName);
  764. pNewContNode->GetADsObject()->SetConnectionNode(pConnectNode);
  765. VERIFY(pTreeNode->AddChildToListAndUI(pNewContNode, GetComponentData()));
  766. GetComponentData()->SetDescriptionBarText(pTreeNode);
  767. // Refresh any other subtrees of connections that contain this node
  768. //
  769. CList<CTreeNode*, CTreeNode*> foundNodeList;
  770. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(pTreeNode->GetRootContainer());
  771. if (pRootNode != NULL)
  772. {
  773. BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList);
  774. if (bFound)
  775. {
  776. POSITION posList = foundNodeList.GetHeadPosition();
  777. while (posList != NULL)
  778. {
  779. CADSIEditContainerNode* pFoundContNode = dynamic_cast<CADSIEditContainerNode*>(foundNodeList.GetNext(posList));
  780. if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode)
  781. {
  782. CADSIEditContainerNode* pNewFoundNode = new CADSIEditContainerNode(pNewContNode);
  783. pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode());
  784. VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData()));
  785. GetComponentData()->SetDescriptionBarText(pFoundContNode);
  786. }
  787. }
  788. }
  789. }
  790. }
  791. else
  792. {
  793. pObject->SetContainer(FALSE);
  794. CADSIEditLeafNode *pLeafNode = new CADSIEditLeafNode(pObject);
  795. pLeafNode->SetDisplayName(m_sName);
  796. pLeafNode->GetADsObject()->SetConnectionNode(pConnectNode);
  797. VERIFY(pTreeNode->AddChildToListAndUI(pLeafNode, GetComponentData()));
  798. GetComponentData()->SetDescriptionBarText(pTreeNode);
  799. // Refresh any other subtrees of connections that contain this node
  800. //
  801. CList<CTreeNode*, CTreeNode*> foundNodeList;
  802. CADSIEditRootData* pRootNode = dynamic_cast<CADSIEditRootData*>(pTreeNode->GetRootContainer());
  803. if (pRootNode != NULL)
  804. {
  805. BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList);
  806. if (bFound)
  807. {
  808. POSITION posList = foundNodeList.GetHeadPosition();
  809. while (posList != NULL)
  810. {
  811. CADSIEditContainerNode* pFoundContNode = dynamic_cast<CADSIEditContainerNode*>(foundNodeList.GetNext(posList));
  812. if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode)
  813. {
  814. CADSIEditLeafNode* pNewFoundNode = new CADSIEditLeafNode(pLeafNode);
  815. pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode());
  816. VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData()));
  817. GetComponentData()->SetDescriptionBarText(pFoundContNode);
  818. }
  819. }
  820. }
  821. }
  822. }
  823. FreeADsMem(pInfo);
  824. return TRUE;
  825. }
  826. HRESULT CCreatePageHolder::EscapePath(CString& sEscapedName, const CString& sName)
  827. {
  828. CComPtr<IADsPathname> pIADsPathname;
  829. HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  830. IID_IADsPathname, (PVOID *)&(pIADsPathname));
  831. ASSERT((S_OK == hr) && ((pIADsPathname) != NULL));
  832. CComBSTR bstrEscaped;
  833. hr = pIADsPathname->GetEscapedElement(0, //reserved
  834. (BSTR)(LPCWSTR)sName,
  835. &bstrEscaped);
  836. sEscapedName = bstrEscaped;
  837. return hr;
  838. }
  839. void CCreatePageHolder::GetDN(PWSTR pwszName, CString& sDN)
  840. {
  841. CComPtr<IADsPathname> pIADsPathname;
  842. HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
  843. IID_IADsPathname, (PVOID *)&(pIADsPathname));
  844. ASSERT((S_OK == hr) && ((pIADsPathname) != NULL));
  845. hr = pIADsPathname->Set(pwszName, ADS_SETTYPE_FULL);
  846. if (FAILED(hr))
  847. {
  848. sDN = L"";
  849. return;
  850. }
  851. // Get the leaf DN
  852. CComBSTR bstrDN;
  853. hr = pIADsPathname->Retrieve(ADS_FORMAT_X500_DN, &bstrDN);
  854. if (FAILED(hr))
  855. {
  856. TRACE(_T("Failed to get element. %s"), hr);
  857. sDN = L"";
  858. }
  859. else
  860. {
  861. sDN = bstrDN;
  862. }
  863. }
  864. void CCreatePageHolder::OnMore()
  865. {
  866. CString sServer;
  867. m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData()->GetDomainServer(sServer);
  868. CCreateWizPropertyPageHolder propPage(m_pCurrentNode, m_pComponentData, m_sClass, sServer, &m_AttrList);
  869. if (propPage.DoModalDialog(m_sName) == IDOK)
  870. {
  871. }
  872. }