//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1998 - 1999 // // File: createwiz.cpp // //-------------------------------------------------------------------------- //////////////////////////////////////////////// // createwiz.cpp #include "pch.h" #include #include "createwiz.h" #include "connection.h" #include "editorui.h" #include "query.h" #include "resource.h" #ifdef DEBUG_ALLOCATOR #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #endif ////////////////////////////////////////////////////////////////////////////////////// // CCreateClassPage BEGIN_MESSAGE_MAP(CCreateClassPage, CPropertyPageBase) //{{AFX_MSG_MAP(CADsObjectDialog) // ON_CBN_SELCHANGE(IDC_CLASS_LIST, OnSelChangeClassList) //}}AFX_MSG_MAP END_MESSAGE_MAP() CCreateClassPage::CCreateClassPage(CADSIEditContainerNode* pNode) : CPropertyPageBase(IDD_CREATE_CLASS_PAGE) { m_pCurrentNode = pNode; } CCreateClassPage::~CCreateClassPage() { } BOOL CCreateClassPage::OnInitDialog() { CPropertyPageBase::OnInitDialog(); CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST); // disable IME support on numeric edit fields ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_NUMBER_VALUE_BOX), NULL); FillList(); pClassList->SetCurSel(0); return TRUE; } void CCreateClassPage::FillList() { CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST); HRESULT hr, hCredResult; CString sPath, schema; m_pCurrentNode->GetADsObject()->GetPath(sPath); CConnectionData* pConnectData = m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData(); // bind to Container for IPropertyList CComPtr spDSObject; hr = OpenObjectWithCredentials( pConnectData, pConnectData->GetCredentialObject()->UseCredentials(), sPath, IID_IADsPropertyList, (LPVOID*) &spDSObject, GetSafeHwnd(), hCredResult ); if (FAILED(hr)) { TRACE(_T("Bind to Container for IPropertyList failed: %lx.\n"), hr); return; } // need to do this hack to load the cache CComPtr spIADs; hr = spDSObject->QueryInterface (IID_IADs, (LPVOID*)&spIADs); if (FAILED(hr)) { TRACE(_T("QI to Container for IADs failed: %lx.\n"), hr); return; } PWSTR g_wzAllowedChildClassesEffective = L"allowedChildClassesEffective"; CComVariant varHints; ADsBuildVarArrayStr (&g_wzAllowedChildClassesEffective, 1, &varHints); spIADs->GetInfoEx(varHints, 0); // get allowed child classes as VARIANT CComVariant VarProp; hr = spDSObject->GetPropertyItem(CComBSTR(g_wzAllowedChildClassesEffective), ADSTYPE_CASE_IGNORE_STRING, &VarProp); if (FAILED(hr)) { TRACE(_T("GetPropertyItem failed: %lx.\n"), hr); return; } // extract the IADsPropertyEntry interface pointer IDispatch* pDisp = V_DISPATCH(&VarProp); CComPtr spPropEntry; hr = pDisp->QueryInterface(IID_IADsPropertyEntry, (void **)&spPropEntry); if (FAILED(hr)) { return; } // get SAFEARRAY out of IADsPropertyEntry pointer CComVariant Var; hr = spPropEntry->get_Values(&Var); if (FAILED(hr)) { return; } long uBound, lBound; hr = ::SafeArrayGetUBound(V_ARRAY(&Var), 1, &uBound); hr = ::SafeArrayGetLBound(V_ARRAY(&Var), 1, &lBound); VARIANT* pNames; hr = ::SafeArrayAccessData(V_ARRAY(&Var), (void **)&pNames); if (FAILED(hr)) { TRACE(_T("Accessing safearray data failed: %lx.\n"), hr); SafeArrayUnaccessData(V_ARRAY(&Var)); return; } // now got the array of items, loop through them WCHAR szFrendlyName[1024]; HRESULT hrName; long nChildClassesCount = uBound - lBound + 1; for (long index = lBound; index <= uBound; index++) { CComPtr spEntry; hr = (pNames[index].pdispVal)->QueryInterface (IID_IADsPropertyValue, (void **)&spEntry); if (SUCCEEDED(hr)) { BSTR bsObject = NULL; hr = spEntry->get_CaseIgnoreString(&bsObject); if (SUCCEEDED(hr)) { // hrName = ::DsGetFriendlyClassName(bsObject, szFrendlyName, 1024); // ASSERT(SUCCEEDED(hrName)); pClassList->AddString(bsObject); } // if ::SysFreeString(bsObject); } // if } // for ::SafeArrayUnaccessData(V_ARRAY(&Var)); } BOOL CCreateClassPage::OnSetActive() { GetHolder()->SetWizardButtonsFirst(TRUE); return TRUE; } LRESULT CCreateClassPage::OnWizardNext() { CListBox* pClassList = (CListBox*)GetDlgItem(IDC_CLASS_LIST); CCreatePageHolder* pHolder = dynamic_cast(GetHolder()); ASSERT(pHolder != NULL); CString sClass; pClassList->GetText(pClassList->GetCurSel(), sClass); if (m_sClass != sClass) { m_sClass = sClass; pHolder->AddAttrPage(sClass); } return 0; //next page } ///////////////////////////////////////////////////////////////////////////////////////// // CCreateAttributePage BEGIN_MESSAGE_MAP(CCreateAttributePage, CPropertyPageBase) //{{AFX_MSG_MAP(CADsObjectDialog) ON_EN_CHANGE(IDC_ATTR_VALUE_BOX, OnEditChangeValue) ON_EN_CHANGE(IDC_NUMBER_VALUE_BOX, OnEditChangeValue) //}}AFX_MSG_MAP END_MESSAGE_MAP() CCreateAttributePage::CCreateAttributePage(UINT nID, CADSIAttr* pAttr) : CPropertyPageBase(nID) { m_bInitialized = FALSE; m_bNumber = FALSE; m_pAttr = pAttr; } CCreateAttributePage::~CCreateAttributePage() { } BOOL CCreateAttributePage::OnInitDialog() { CPropertyPageBase::OnInitDialog(); CEdit* pAttrBox = (CEdit*)GetDlgItem(IDC_ATTR_BOX); // disable IME support on numeric edit fields ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_NUMBER_VALUE_BOX), NULL); CString sAttr; m_pAttr->GetProperty(sAttr); pAttrBox->SetWindowText(sAttr); SetSyntax(sAttr); m_bInitialized = TRUE; return TRUE; } void CCreateAttributePage::GetValue(CString& sVal) { CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX); pValueBox->GetWindowText(sVal); } void CCreateAttributePage::SetSyntax(CString sAttr) { CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX); CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX); CEdit* pSyntaxBox = (CEdit*)GetDlgItem(IDC_SYNTAX_BOX); CCreatePageHolder* pHolder = dynamic_cast(GetHolder()); ASSERT(pHolder != NULL); if (pHolder != NULL) { CADSIEditContainerNode* pContNode = dynamic_cast(pHolder->GetTreeNode()); ASSERT(pContNode != NULL); if (pContNode != NULL) { CConnectionData* pConnectData = pContNode->GetADsObject()->GetConnectionNode()->GetConnectionData(); CString sPath, sSyntax; CComPtr pProp; pHolder->GetSchemaPath(sAttr, sPath); // bind to object with authentication // HRESULT hr, hCredResult; hr = OpenObjectWithCredentials( pConnectData, pConnectData->GetCredentialObject()->UseCredentials(), sPath, IID_IADsProperty, (LPVOID*) &pProp, GetSafeHwnd(), hCredResult ); if ( FAILED(hr) ) { if (SUCCEEDED(hCredResult)) { ADSIEditErrorMessage(hr); } return; } BSTR bstr; hr = pProp->get_Syntax( &bstr ); if ( SUCCEEDED(hr) ) { sSyntax = bstr; } pSyntaxBox->SetWindowText(sSyntax); BOOL varType = VariantTypeFromSyntax(sSyntax); switch (varType) { case VT_BSTR : pNumberBox->ShowWindow(FALSE); pValueBox->ShowWindow(TRUE); m_bNumber = FALSE; break; case VT_I4 : case VT_I8 : pNumberBox->ShowWindow(TRUE); pValueBox->ShowWindow(FALSE); m_bNumber = TRUE; break; default : pNumberBox->ShowWindow(FALSE); pValueBox->ShowWindow(TRUE); m_bNumber = FALSE; break; } pProp->get_MaxRange(&m_lMaxRange); pProp->get_MinRange(&m_lMinRange); SetADsType(sAttr); } } } void CCreateAttributePage::SetADsType(CString sProp) { CString schema, sServer; BOOL bResult = FALSE; CConnectionData* pConnectData; CADSIEditContainerNode* pContNode = dynamic_cast(GetHolder()->GetTreeNode()); if (pContNode == NULL) { CADSIEditLeafNode* pLeafNode = dynamic_cast(GetHolder()->GetTreeNode()); ASSERT(pLeafNode != NULL); bResult = pLeafNode->BuildSchemaPath(schema); pConnectData = pLeafNode->GetADsObject()->GetConnectionNode()->GetConnectionData(); } else { bResult = pContNode->BuildSchemaPath(schema); pConnectData = pContNode->GetADsObject()->GetConnectionNode()->GetConnectionData(); } if (!bResult) { return; } CADSIQueryObject schemaSearch; // Initialize search object with path, username and password // HRESULT hr = schemaSearch.Init(schema, pConnectData->GetCredentialObject()); if (FAILED(hr)) { ADSIEditErrorMessage(hr); return; } int cCols = 2; LPWSTR pszAttributes[] = {L"attributeSyntax", L"isSingleValued"}; ADS_SEARCH_COLUMN ColumnData; hr = schemaSearch.SetSearchPrefs(ADS_SCOPE_ONELEVEL); if (FAILED(hr)) { ADSIEditErrorMessage(hr); return; } CString csFilter = _T("(&(objectClass=attributeSchema)(lDAPDisplayName=") + sProp + _T("))"); schemaSearch.SetFilterString((LPWSTR)(LPCWSTR)csFilter); schemaSearch.SetAttributeList (pszAttributes, cCols); hr = schemaSearch.DoQuery (); if (SUCCEEDED(hr)) { hr = schemaSearch.GetNextRow(); if (SUCCEEDED(hr)) { hr = schemaSearch.GetColumn(pszAttributes[0], &ColumnData); if (SUCCEEDED(hr)) { TRACE(_T("\t\tattributeSyntax: %s\n"), ColumnData.pADsValues->CaseIgnoreString); CString szSyntax; ADSTYPE dwType; dwType = GetADsTypeFromString(ColumnData.pADsValues->CaseIgnoreString, szSyntax); m_pAttr->SetADsType(dwType); m_pAttr->SetSyntax(szSyntax); } else { ADSIEditErrorMessage(hr); } hr = schemaSearch.GetColumn(pszAttributes[1], &ColumnData); if (SUCCEEDED(hr)) { TRACE(_T("\t\tisSingleValued: %d\n"), ColumnData.pADsValues->Boolean); m_pAttr->SetMultivalued(!ColumnData.pADsValues->Boolean); } else { ADSIEditErrorMessage(hr); } } } } void CCreateAttributePage::OnEditChangeValue() { CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX); CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX); CString sValue, sAttr; CEdit* pBox; if (m_bNumber) { pBox = pNumberBox; } else { pBox = pValueBox; } pBox->GetWindowText(sValue); CCreatePageHolder* pHolder = dynamic_cast(GetHolder()); ASSERT(pHolder != NULL); m_pAttr->GetProperty(sAttr); CString sNamingAttr; pHolder->GetNamingAttribute(sNamingAttr); if (sAttr == sNamingAttr) { pHolder->SetName(sValue); } if (sValue == _T("")) { GetHolder()->SetWizardButtons(PSWIZB_BACK); } else { GetHolder()->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT); } } BOOL CCreateAttributePage::OnSetActive() { if (m_bInitialized) { OnEditChangeValue(); } else { GetHolder()->SetWizardButtonsMiddle(FALSE); } return TRUE; } LRESULT CCreateAttributePage::OnWizardNext() { CEdit* pValueBox = (CEdit*)GetDlgItem(IDC_ATTR_VALUE_BOX); CEdit* pNumberBox = (CEdit*)GetDlgItem(IDC_NUMBER_VALUE_BOX); m_pAttr->SetDirty(TRUE); CString sValue; CEdit* pBox; if (m_bNumber) { pBox = pNumberBox; } else { pBox = pValueBox; } pBox->GetWindowText(sValue); m_sAttrValue.RemoveAll(); m_sAttrValue.AddTail(sValue); HRESULT hr = m_pAttr->SetValues(m_sAttrValue); if (FAILED(hr)) { ADSIEditMessageBox(IDS_MSG_INCORRECT_FORMAT, MB_OK); return -1; //don't advance pages } return 0; //next page } ///////////////////////////////////////////////////////////////////////////////////////// // CCreateFinishPage BEGIN_MESSAGE_MAP(CCreateFinishPage, CPropertyPageBase) //{{AFX_MSG_MAP(CADsObjectDialog) ON_BN_CLICKED(IDC_BUTTON_MORE, OnMore) //}}AFX_MSG_MAP END_MESSAGE_MAP() CCreateFinishPage::CCreateFinishPage(UINT nID) : CPropertyPageBase(nID) { m_bInitialized = FALSE; } CCreateFinishPage::~CCreateFinishPage() { } BOOL CCreateFinishPage::OnInitDialog() { CPropertyPageBase::OnInitDialog(); GetHolder()->SetWizardButtons(PSWIZB_FINISH); m_bInitialized = TRUE; return TRUE; } void CCreateFinishPage::OnMore() { CCreatePageHolder* pHolder = dynamic_cast(GetHolder()); ASSERT(pHolder != NULL); pHolder->OnMore(); } BOOL CCreateFinishPage::OnSetActive() { GetHolder()->SetWizardButtons(PSWIZB_FINISH | PSWIZB_BACK); return TRUE; } BOOL CCreateFinishPage::OnWizardFinish() { CCreatePageHolder* pHolder = dynamic_cast(GetHolder()); ASSERT(pHolder != NULL); return pHolder->OnFinish(); } //////////////////////////////////////////////////////////////////////////////////////// // CCreatePageHolder CCreatePageHolder:: CCreatePageHolder(CContainerNode* pContNode, CADSIEditContainerNode* pNode, CComponentDataObject* pComponentData) : CPropertyPageHolderBase(pContNode, pNode, pComponentData) { ASSERT(pComponentData != NULL); ASSERT(pContNode != NULL); ASSERT(pContNode == GetContainerNode()); m_pCurrentNode = pNode; m_pComponentData = pComponentData; m_bAutoDeletePages = FALSE; // we have the page as embedded member m_pClassPage = new CCreateClassPage(pNode); AddPageToList((CPropertyPageBase*)m_pClassPage); } CCreatePageHolder::~CCreatePageHolder() { m_pageList.RemoveAll(); } void CCreatePageHolder::AddAttrPage(CString sClass) { RemoveAllPages(); m_sClass = sClass; CStringList sMandList; GetMandatoryAttr(sClass, &sMandList); CString sAttr; if (!m_pCurrentNode->GetNamingAttribute(sClass, &m_sNamingAttr)) { return; } // Remove attributes from list that do not need a page RemovePresetAttr(&sMandList); // find the naming attribute and put it first POSITION fpos = sMandList.Find(m_sNamingAttr.GetHead()); if (fpos != NULL) { sMandList.AddHead(sMandList.GetAt(fpos)); sMandList.RemoveAt(fpos); } else { sMandList.AddHead(m_sNamingAttr.GetHead()); } POSITION pos = sMandList.GetHeadPosition(); while (pos != NULL) { CCreateAttributePage* pAttrPage; sAttr = sMandList.GetNext(pos); // Maintain the list of attributes here so that we can pop up the prop page for more advanced editting CADSIAttr* pNewAttr = new CADSIAttr(sAttr); m_AttrList.AddTail(pNewAttr); pAttrPage = new CCreateAttributePage(IDD_CREATE_EMPTY_PAGE, pNewAttr); // Add the naming attribute as the first page so that they type the name first if (sAttr == m_sNamingAttr.GetHead()) { m_pageList.AddHead(pAttrPage); } else { m_pageList.AddTail(pAttrPage); } } // Add the finish page to the end CCreateFinishPage* pFinishPage = new CCreateFinishPage(IDD_CREATE_LAST_PAGE); m_pageList.AddTail(pFinishPage); // Add the pages to the UI pos = m_pageList.GetHeadPosition(); while (pos != NULL) { CPropertyPageBase* pAttrPage; pAttrPage = m_pageList.GetNext(pos); AddPageToList(pAttrPage); AddPageToSheet(pAttrPage); } } void CCreatePageHolder::RemovePresetAttr(CStringList* psMandList) { // this is a hack to keep from trying to set properties that are not allowed to be set. POSITION fpos = psMandList->Find(_T("nTSecurityDescriptor")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("instanceType")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("objectClass")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("objectCategory")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("objectSid")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("objectClassCategory")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("schemaIDGUID")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } fpos = psMandList->Find(_T("defaultObjectCategory")); if (fpos != NULL) { psMandList->RemoveAt(fpos); } } void CCreatePageHolder::GetSchemaPath(CString sClass, CString& schema) { m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData()->GetAbstractSchemaPath(schema); schema += sClass; } void CCreatePageHolder::GetMandatoryAttr(CString sClass, CStringList* sMandList) { CComPtr pClass; CString schema; HRESULT hr, hCredResult; GetSchemaPath(sClass, schema); CADSIEditContainerNode* pContNode = dynamic_cast(GetTreeNode()); CConnectionData* pConnectData = m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData(); hr = OpenObjectWithCredentials( pConnectData, pConnectData->GetCredentialObject()->UseCredentials(), schema, IID_IADsClass, (LPVOID*) &pClass, NULL, hCredResult ); if ( FAILED(hr) ) { if (SUCCEEDED(hCredResult)) { ADSIEditErrorMessage(hr); } return; } VARIANT var; VariantInit(&var); pClass->get_MandatoryProperties(&var); VariantToStringList( var, *sMandList ); VariantClear(&var); } void CCreatePageHolder::RemoveAllPages() { while (!m_pageList.IsEmpty()) { CPropertyPageBase* pPropPage = m_pageList.RemoveTail(); RemovePageFromSheet(pPropPage); RemovePageFromList(pPropPage, FALSE); delete pPropPage; } } BOOL CCreatePageHolder::OnFinish() { CWaitCursor cursor; CComPtr pDirObject; HRESULT hr, hCredResult; CString sContPath; m_pCurrentNode->GetADsObject()->GetPath(sContPath); CADSIEditContainerNode* pTreeNode = dynamic_cast(GetTreeNode()); ASSERT(pTreeNode != NULL); CADSIEditConnectionNode* pConnectNode = pTreeNode->GetADsObject()->GetConnectionNode(); CConnectionData* pConnectData = pConnectNode->GetConnectionData(); hr = OpenObjectWithCredentials( pConnectData, pConnectData->GetCredentialObject()->UseCredentials(), sContPath, IID_IDirectoryObject, (LPVOID*) &pDirObject, NULL, hCredResult ); if ( FAILED(hr) ) { if (SUCCEEDED(hCredResult)) { ADSIEditErrorMessage(hr); } return FALSE; } int iCount = m_AttrList.GetDirtyCount(); ADS_ATTR_INFO* pAttrInfo; CComPtr pDisp; do // false loop { pAttrInfo = new ADS_ATTR_INFO[iCount + 1]; // Add an extra to specify the class type if (NULL == pAttrInfo) { hr = E_OUTOFMEMORY; break; } int idx = 0; pAttrInfo[idx].pszAttrName = L"objectClass"; pAttrInfo[idx].dwControlCode = ADS_ATTR_UPDATE; pAttrInfo[idx].dwADsType = ADSTYPE_CASE_IGNORE_STRING; pAttrInfo[idx].pADsValues = new ADSVALUE; if (NULL == pAttrInfo[idx].pADsValues) { hr = E_OUTOFMEMORY; break; } pAttrInfo[idx].pADsValues->dwType = ADSTYPE_CASE_IGNORE_STRING; int iLength = m_sClass.GetLength(); // NOTICE-NTRAID#NTBUG9-562222-2002/03/04-artm Need to check if mem. allocation succeeded. pAttrInfo[idx].pADsValues->CaseIgnoreString = new WCHAR[iLength + 1]; if (NULL == pAttrInfo[idx].pADsValues->CaseIgnoreString) { hr = E_OUTOFMEMORY; break; } // NOTICE-2002/03/04-artm wcscpy() used correctly // m_sClass will always be null terminated and has iLength characters // destination array has iLength + 1 space wcscpy(pAttrInfo[idx].pADsValues->CaseIgnoreString, m_sClass); pAttrInfo[idx].dwNumValues = 1; idx++; POSITION pos = m_AttrList.GetHeadPosition(); while(pos != NULL) { CADSIAttr* pAttr = m_AttrList.GetNext(pos); if (pAttr->IsDirty()) { pAttrInfo[idx] = *(pAttr->GetAttrInfo()); idx++; } } // make the prefix uppercase CString sName(m_sName); int indx = sName.Find(L'='); if (indx != -1) { CString sPrefix, sRemaining; sPrefix = sName.Left(indx); sPrefix.MakeUpper(); int iLen = sName.GetLength(); sRemaining = sName.Right(iLen - indx); sName = sPrefix + sRemaining; } m_sName = sName; CString sEscapedName; hr = EscapePath(sEscapedName, sName); if (FAILED(hr)) { break; } hr = pDirObject->CreateDSObject((LPWSTR)(LPCWSTR)sEscapedName, pAttrInfo, idx, &pDisp); if ( FAILED(hr) ) { break; } } while (false); // end false loop // Clean up temporary variables. if (pAttrInfo) { if (pAttrInfo[0].pADsValues) { if (pAttrInfo[0].pADsValues->CaseIgnoreString) { delete [] pAttrInfo[0].pADsValues->CaseIgnoreString; } delete pAttrInfo[0].pADsValues; } delete [] pAttrInfo; pAttrInfo = NULL; } if (FAILED(hr)) { // Format error message and pop up a dialog. ADSIEditErrorMessage(hr); return FALSE; } // Get the IDirectoryObject of the new node // CComPtr pNewDirObject; hr = pDisp->QueryInterface(IID_IDirectoryObject, (LPVOID*)&pNewDirObject); if ( FAILED(hr) ) { //Format Error message and pop up a dialog ADSIEditErrorMessage(hr); return FALSE; } ADS_OBJECT_INFO* pInfo; hr = pNewDirObject->GetObjectInformation(&pInfo); if ( FAILED(hr) ) { //Format Error message and pop up a dialog ADSIEditErrorMessage(hr); return FALSE; } CADsObject* pObject = new CADsObject(); if (NULL == pObject) { ADSIEditErrorMessage(E_OUTOFMEMORY); return FALSE; } // Name CString sDN; pObject->SetName(m_sName); GetDN(pInfo->pszObjectDN, sDN); pObject->SetDN(sDN); pObject->SetPath(pInfo->pszObjectDN); // Class pObject->SetClass(pInfo->pszClassName); //Get the class object so that we can get the properties // CString sServer, schema; pConnectNode->GetConnectionData()->GetAbstractSchemaPath(schema); schema += CString(pInfo->pszClassName); do // false loop { // bind to object with authentication // CComPtr pClass; hr = OpenObjectWithCredentials( pConnectData, pConnectData->GetCredentialObject()->UseCredentials(), schema, IID_IADsClass, (LPVOID*) &pClass, NULL, hCredResult ); if ( FAILED(hr) ) { if (SUCCEEDED(hCredResult)) { ADSIEditErrorMessage(hr); } break; } pObject->SetComplete(TRUE); short bContainer; pClass->get_Container( &bContainer ); if (bContainer == -1) { pObject->SetContainer(TRUE); CADSIEditContainerNode *pNewContNode = new CADSIEditContainerNode(pObject); if (pNewContNode) { // We don't want to free pObject since it was passed to a constructor. That // object is responsible for deleting that memory. Therefore, we set our // pointer to the memory to NULL so that we don't accidentally clean it // up. pObject = NULL; } else { hr = E_OUTOFMEMORY; ADSIEditErrorMessage(hr); break; } pNewContNode->SetDisplayName(m_sName); // Since we add pNewContNode to the list here we do not need to free // it before exiting function (it is freed when the list is freed). pNewContNode->GetADsObject()->SetConnectionNode(pConnectNode); VERIFY(pTreeNode->AddChildToListAndUI(pNewContNode, GetComponentData())); GetComponentData()->SetDescriptionBarText(pTreeNode); // Refresh any other subtrees of connections that contain this node // CList foundNodeList; CADSIEditRootData* pRootNode = dynamic_cast(pTreeNode->GetRootContainer()); if (pRootNode != NULL) { BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList); if (bFound) { POSITION posList = foundNodeList.GetHeadPosition(); while (posList != NULL && SUCCEEDED(hr)) { CADSIEditContainerNode* pFoundContNode = dynamic_cast(foundNodeList.GetNext(posList)); if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode) { // Make a copy of the new container node and plug it into the list. CADSIEditContainerNode* pNewFoundNode = new CADSIEditContainerNode(pNewContNode); if (pNewFoundNode) { pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode()); VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData())); GetComponentData()->SetDescriptionBarText(pFoundContNode); } else { hr = E_OUTOFMEMORY; ADSIEditErrorMessage(hr); } } } // Since the while() loop is last statement we do not // need to worry about breaking out of false loop if // we've hit an error condition (e.g. out of memory). } } } else { pObject->SetContainer(FALSE); CADSIEditLeafNode *pLeafNode = new CADSIEditLeafNode(pObject); if (pLeafNode) { // We don't want to free pObject since it was passed to a constructor. That // object is responsible for deleting that memory. Therefore, we set our // pointer to the memory to NULL so that we don't accidentally clean it // up. pObject = NULL; } else { hr = E_OUTOFMEMORY; ADSIEditErrorMessage(hr); break; } // Since we add pNewContNode to the list here we do not need to free // it before exiting function (it is freed when the list is freed). pLeafNode->SetDisplayName(m_sName); pLeafNode->GetADsObject()->SetConnectionNode(pConnectNode); VERIFY(pTreeNode->AddChildToListAndUI(pLeafNode, GetComponentData())); GetComponentData()->SetDescriptionBarText(pTreeNode); // Refresh any other subtrees of connections that contain this node // CList foundNodeList; CADSIEditRootData* pRootNode = dynamic_cast(pTreeNode->GetRootContainer()); if (pRootNode != NULL) { BOOL bFound = pRootNode->FindNode(sContPath, foundNodeList); if (bFound) { POSITION posList = foundNodeList.GetHeadPosition(); while (posList != NULL && SUCCEEDED(hr)) { CADSIEditContainerNode* pFoundContNode = dynamic_cast(foundNodeList.GetNext(posList)); if (pFoundContNode != NULL && pFoundContNode != pTreeNode && pFoundContNode != pConnectNode) { // Make a copy of the new leaf node and place it in the list. CADSIEditLeafNode* pNewFoundNode = new CADSIEditLeafNode(pLeafNode); if (pNewFoundNode) { pNewFoundNode->GetADsObject()->SetConnectionNode(pFoundContNode->GetADsObject()->GetConnectionNode()); VERIFY(pFoundContNode->AddChildToListAndUI(pNewFoundNode, GetComponentData())); GetComponentData()->SetDescriptionBarText(pFoundContNode); } else { hr = E_OUTOFMEMORY; ADSIEditErrorMessage(hr); } } } // Since the while() loop is last statement we do not // need to worry about breaking out of false loop if // we've hit an error condition (e.g. out of memory). } } } // end else } while (false); // end false loop // // Clean up memory. // if (pObject) { delete pObject; } FreeADsMem(pInfo); return SUCCEEDED(hr); } HRESULT CCreatePageHolder::EscapePath(CString& sEscapedName, const CString& sName) { CComPtr pIADsPathname; HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&(pIADsPathname)); ASSERT((S_OK == hr) && ((pIADsPathname) != NULL)); CComBSTR bstrEscaped; hr = pIADsPathname->GetEscapedElement(0, //reserved (BSTR)(LPCWSTR)sName, &bstrEscaped); sEscapedName = bstrEscaped; return hr; } void CCreatePageHolder::GetDN(PWSTR pwszName, CString& sDN) { CComPtr pIADsPathname; HRESULT hr = ::CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (PVOID *)&(pIADsPathname)); ASSERT((S_OK == hr) && ((pIADsPathname) != NULL)); hr = pIADsPathname->Set(CComBSTR(pwszName), ADS_SETTYPE_FULL); if (FAILED(hr)) { sDN = L""; return; } // Get the leaf DN CComBSTR bstrDN; hr = pIADsPathname->Retrieve(ADS_FORMAT_X500_DN, &bstrDN); if (FAILED(hr)) { TRACE(_T("Failed to get element. %s"), hr); sDN = L""; } else { sDN = bstrDN; } } void CCreatePageHolder::OnMore() { CThemeContextActivator activator; CString sServer; m_pCurrentNode->GetADsObject()->GetConnectionNode()->GetConnectionData()->GetDomainServer(sServer); CCreateWizPropertyPageHolder propPage(m_pCurrentNode, m_pComponentData, m_sClass, sServer, &m_AttrList); if (propPage.DoModalDialog(m_sName) == IDOK) { } }