#include "pch.h" #include #include "resource.h" #include "query.h" #include "attrres.h" #include "editui.h" #include "common.h" #include "attrqry.h" #include "editorui.h" /////////////////////////////////////////////////////////////////////////////////////// // CValueEditDialog BEGIN_MESSAGE_MAP(CValueEditDialog, CDialog) END_MESSAGE_MAP() HRESULT CValueEditDialog::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; m_pOldADsValue = pAttributeEditorInfo->pADsValue; m_dwOldNumValues = pAttributeEditorInfo->dwNumValues; m_szClass = pAttributeEditorInfo->lpszClass; m_szAttribute = pAttributeEditorInfo->lpszAttribute; m_bMultivalued = pAttributeEditorInfo->bMultivalued; m_pfnBindingFunction = pAttributeEditorInfo->lpfnBind; m_lParam = pAttributeEditorInfo->lParam; return hr; } HRESULT CValueEditDialog::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } *ppADsValue = NULL; *pdwNumValues = 0; return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CSingleStringEditor CValueEditDialog* CreateSingleStringEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CSingleStringEditor; } BEGIN_MESSAGE_MAP(CSingleStringEditor, CValueEditDialog) ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear) END_MESSAGE_MAP() BOOL CSingleStringEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Initialize the edit box with the value // if (m_szOldValue.IsEmpty()) { CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); } else { SetDlgItemText(IDC_VALUE_EDIT, m_szOldValue); } // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); return CDialog::OnInitDialog(); } void CSingleStringEditor::OnOK() { GetDlgItemText(IDC_VALUE_EDIT, m_szNewValue); CDialog::OnOK(); } HRESULT CSingleStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_CASE_IGNORE_STRING: m_szOldValue = pAttributeEditorInfo->pADsValue->CaseIgnoreString; break; case ADSTYPE_CASE_EXACT_STRING: m_szOldValue = pAttributeEditorInfo->pADsValue->CaseExactString; break; case ADSTYPE_PRINTABLE_STRING: m_szOldValue = pAttributeEditorInfo->pADsValue->PrintableString; break; case ADSTYPE_DN_STRING: m_szOldValue = pAttributeEditorInfo->pADsValue->DNString; break; default: ASSERT(FALSE); break; } } } return hr; } void CSingleStringEditor::OnClear() { // // Change the text in the edit box to "" // CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); // // Change the focus to the edit box // GetDlgItem(IDC_VALUE_EDIT)->SetFocus(); // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); } HRESULT CSingleStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); if (m_szNewValue == szNotSet) { *ppADsValue = NULL; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE; if (*ppADsValue != NULL) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_CASE_IGNORE_STRING: (*ppADsValue)->CaseIgnoreString = new WCHAR[wcslen(m_szNewValue) + 1]; if ((*ppADsValue)->CaseIgnoreString != NULL) { wcscpy((*ppADsValue)->CaseIgnoreString, m_szNewValue); } else { delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_CASE_EXACT_STRING: (*ppADsValue)->CaseExactString = new WCHAR[wcslen(m_szNewValue) + 1]; if ((*ppADsValue)->CaseExactString != NULL) { wcscpy((*ppADsValue)->CaseExactString, m_szNewValue); } else { delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_PRINTABLE_STRING: (*ppADsValue)->PrintableString = new WCHAR[wcslen(m_szNewValue) + 1]; if ((*ppADsValue)->PrintableString != NULL) { wcscpy((*ppADsValue)->PrintableString, m_szNewValue); } else { delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_DN_STRING: (*ppADsValue)->DNString = new WCHAR[wcslen(m_szNewValue) + 1]; if ((*ppADsValue)->DNString != NULL) { wcscpy((*ppADsValue)->DNString, m_szNewValue); } else { delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CMultiStringEditor CValueEditDialog* CreateMultiStringEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CMultiStringEditor; } BEGIN_MESSAGE_MAP(CMultiStringEditor, CValueEditDialog) ON_BN_CLICKED(IDC_ATTR_ADD_BUTTON, OnAddButton) ON_BN_CLICKED(IDC_ATTR_REMOVE_BUTTON, OnRemoveButton) ON_LBN_SELCHANGE(IDC_VALUE_LIST, OnListSelChange) ON_EN_CHANGE(IDC_VALUE_EDIT, OnEditChange) END_MESSAGE_MAP() BOOL CMultiStringEditor::OnInitDialog() { CDialog::OnInitDialog(); // // Set the attribute name static // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Fill the list box with the current values // POSITION pos = m_szOldValueList.GetHeadPosition(); while (pos != NULL) { CString szValue = m_szOldValueList.GetNext(pos); if (!szValue.IsEmpty()) { SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szValue); } } // // The remove button should be disabled until something is selected in the listbox // GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE); GetDlgItem(IDC_VALUE_EDIT)->SetFocus(); ManageButtonStates(); // // Update the width of the list box // UpdateListboxHorizontalExtent(); // // NOTE: I have explicitly set the focus so return 0 // return FALSE; } void CMultiStringEditor::OnOK() { // // Get the values out of the list box // m_szNewValueList.RemoveAll(); CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { int iCount = pListBox->GetCount(); for (int idx = 0; idx < iCount; idx++) { CString szNewValue; pListBox->GetText(idx, szNewValue); m_szNewValueList.AddTail(szNewValue); } } CDialog::OnOK(); } void CMultiStringEditor::OnAddButton() { // // Add the value to the list box and clear the edit field // CString szNewValue; GetDlgItemText(IDC_VALUE_EDIT, szNewValue); if (!szNewValue.IsEmpty()) { LRESULT lFind = SendDlgItemMessage(IDC_VALUE_LIST, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(PCWSTR)szNewValue); if (lFind != LB_ERR) { // // Ask them if they really want to add the duplicate value // UINT nResult = ADSIEditMessageBox(IDS_ATTREDIT_DUPLICATE_VALUE, MB_YESNO); lFind = (nResult == IDYES) ? LB_ERR : 1; } if (lFind == LB_ERR) { SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szNewValue); } } SetDlgItemText(IDC_VALUE_EDIT, L""); ManageButtonStates(); // // Update the width of the list box // UpdateListboxHorizontalExtent(); } void CMultiStringEditor::OnRemoveButton() { CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { int iCurSel = pListBox->GetCurSel(); if (iCurSel != LB_ERR) { // // Put the old value into the edit box // CString szOldValue; pListBox->GetText(iCurSel, szOldValue); SetDlgItemText(IDC_VALUE_EDIT, szOldValue); // // Delete the item from the list box // pListBox->DeleteString(iCurSel); } } // // Manage Button States // ManageButtonStates(); // // Update the width of the list box // UpdateListboxHorizontalExtent(); } void CMultiStringEditor::ManageButtonStates() { // // Change the default button to the Add button // CString szValue; GetDlgItemText(IDC_VALUE_EDIT, szValue); if (szValue.IsEmpty()) { // // Set the default button to OK // SendMessage(DM_SETDEFID, (WPARAM)IDOK, 0); SendDlgItemMessage(IDC_ATTR_ADD_BUTTON, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendDlgItemMessage(IDOK, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); } else { // // Set the default button to the Add button // SendMessage(DM_SETDEFID, (WPARAM)IDC_ATTR_ADD_BUTTON, 0); SendDlgItemMessage(IDOK, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendDlgItemMessage(IDC_ATTR_ADD_BUTTON, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); } LRESULT lSelection = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0); if (lSelection != LB_ERR) { GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(TRUE); } else { GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE); } } void CMultiStringEditor::OnListSelChange() { ManageButtonStates(); } void CMultiStringEditor::OnEditChange() { ManageButtonStates(); } void CMultiStringEditor::UpdateListboxHorizontalExtent() { int nHorzExtent = 0; CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { CClientDC dc(pListBox); int nItems = pListBox->GetCount(); for (int i=0; i < nItems; i++) { TEXTMETRIC tm; VERIFY(dc.GetTextMetrics(&tm)); CString szBuffer; pListBox->GetText(i, szBuffer); CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength()); nHorzExtent = max(ext.cx ,nHorzExtent); } pListBox->SetHorizontalExtent(nHorzExtent); } } HRESULT CMultiStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { for (int idx = 0; idx < pAttributeEditorInfo->dwNumValues; idx++) { switch (pAttributeEditorInfo->pADsValue[idx].dwType) { case ADSTYPE_CASE_IGNORE_STRING: m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].CaseIgnoreString); break; case ADSTYPE_CASE_EXACT_STRING: m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].CaseExactString); break; case ADSTYPE_PRINTABLE_STRING: m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].PrintableString); break; case ADSTYPE_DN_STRING: m_szOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].DNString); break; default: ASSERT(FALSE); break; } } } } return hr; } HRESULT CMultiStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } int iCount = m_szNewValueList.GetCount(); if (iCount == 0) { *ppADsValue = NULL; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE[iCount]; if (*ppADsValue != NULL) { *pdwNumValues = iCount; int idx = 0; POSITION pos = m_szNewValueList.GetHeadPosition(); while (pos != NULL) { CString szNewValue = m_szNewValueList.GetNext(pos); (*ppADsValue)[idx].dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_CASE_IGNORE_STRING: (*ppADsValue)[idx].CaseIgnoreString = new WCHAR[wcslen(szNewValue) + 1]; if ((*ppADsValue)[idx].CaseIgnoreString != NULL) { wcscpy((*ppADsValue)[idx].CaseIgnoreString, szNewValue); } else { delete[] *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_CASE_EXACT_STRING: (*ppADsValue)[idx].CaseExactString = new WCHAR[wcslen(szNewValue) + 1]; if ((*ppADsValue)[idx].CaseExactString != NULL) { wcscpy((*ppADsValue)[idx].CaseExactString, szNewValue); } else { delete[] *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_PRINTABLE_STRING: (*ppADsValue)[idx].PrintableString = new WCHAR[wcslen(szNewValue) + 1]; if ((*ppADsValue)[idx].PrintableString != NULL) { wcscpy((*ppADsValue)[idx].PrintableString, szNewValue); } else { delete[] *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; case ADSTYPE_DN_STRING: (*ppADsValue)[idx].DNString = new WCHAR[wcslen(szNewValue) + 1]; if ((*ppADsValue)[idx].DNString != NULL) { wcscpy((*ppADsValue)[idx].DNString, szNewValue); } else { delete[] *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; default: ASSERT(FALSE); delete[] *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } idx++; } } else { *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CSingleIntEditor CValueEditDialog* CreateSingleIntEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CSingleIntEditor; } BEGIN_MESSAGE_MAP(CSingleIntEditor, CValueEditDialog) ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear) END_MESSAGE_MAP() BOOL CSingleIntEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Initialize the edit box with the value // if (!m_bValueSet) { CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); } else { SetDlgItemInt(IDC_VALUE_EDIT, m_dwOldValue, FALSE); } // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); // // Disable IME support on the edit box // ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_VALUE_EDIT), NULL); return CDialog::OnInitDialog(); } void CSingleIntEditor::OnOK() { m_dwNewValue = GetDlgItemInt(IDC_VALUE_EDIT, &m_bValueSet, FALSE); CDialog::OnOK(); } HRESULT CSingleIntEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_INTEGER: m_dwOldValue = pAttributeEditorInfo->pADsValue->Integer; m_bValueSet = TRUE; break; default: ASSERT(FALSE); break; } } } return hr; } void CSingleIntEditor::OnClear() { // // Change the text in the edit box to "" // CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); // // Change the focus to the edit box // GetDlgItem(IDC_VALUE_EDIT)->SetFocus(); // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); m_bValueSet = FALSE; } HRESULT CSingleIntEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); if (!m_bValueSet) { *ppADsValue = NULL; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE; if (*ppADsValue != NULL) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_INTEGER: (*ppADsValue)->Integer = m_dwNewValue; break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CSingleLargeIntEditor CValueEditDialog* CreateSingleLargeIntEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CSingleLargeIntEditor; } BEGIN_MESSAGE_MAP(CSingleLargeIntEditor, CValueEditDialog) ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear) END_MESSAGE_MAP() BOOL CSingleLargeIntEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Initialize the edit box with the value // if (!m_bValueSet) { CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); } else { CString szOldValue; litow(m_liOldValue, szOldValue); SetDlgItemText(IDC_VALUE_EDIT, szOldValue); } // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); // // Disable IME support on the edit box // ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_VALUE_EDIT), NULL); return CDialog::OnInitDialog(); } void CSingleLargeIntEditor::OnOK() { CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); CString szNewValue; GetDlgItemText(IDC_VALUE_EDIT, szNewValue); if (szNewValue == szNotSet) { m_bValueSet = FALSE; } else { wtoli(szNewValue, m_liNewValue); m_bValueSet = TRUE; } CDialog::OnOK(); } HRESULT CSingleLargeIntEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_LARGE_INTEGER: m_liOldValue = pAttributeEditorInfo->pADsValue->LargeInteger; m_bValueSet = TRUE; break; default: ASSERT(FALSE); break; } } else { m_bValueSet = FALSE; } } return hr; } void CSingleLargeIntEditor::OnClear() { // // Change the text in the edit box to "" // CString szNotSet; VERIFY(szNotSet.LoadString(IDS_NOTSET)); SetDlgItemText(IDC_VALUE_EDIT, szNotSet); // // Change the focus to the edit box // GetDlgItem(IDC_VALUE_EDIT)->SetFocus(); // // Select the text in the edit box // SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETSEL, 0, -1); m_bValueSet = FALSE; } HRESULT CSingleLargeIntEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } if (!m_bValueSet) { *ppADsValue = NULL; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE; if (*ppADsValue != NULL) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_LARGE_INTEGER: (*ppADsValue)->LargeInteger = m_liNewValue; break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CSingleBooleanEditor CValueEditDialog* CreateSingleBooleanEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CSingleBooleanEditor; } BEGIN_MESSAGE_MAP(CSingleBooleanEditor, CValueEditDialog) END_MESSAGE_MAP() BOOL CSingleBooleanEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Initialize the edit box with the value // if (!m_bValueSet) { SendDlgItemMessage(IDC_NOTSET_RADIO, BM_SETCHECK, BST_CHECKED, 0); } else { if (m_bOldValue) { SendDlgItemMessage(IDC_TRUE_RADIO, BM_SETCHECK, BST_CHECKED, 0); } else { SendDlgItemMessage(IDC_FALSE_RADIO, BM_SETCHECK, BST_CHECKED, 0); } } return CDialog::OnInitDialog(); } void CSingleBooleanEditor::OnOK() { LRESULT lTrueCheck = SendDlgItemMessage(IDC_TRUE_RADIO, BM_GETCHECK, 0, 0); LRESULT lFalseCheck = SendDlgItemMessage(IDC_FALSE_RADIO, BM_GETCHECK, 0, 0); LRESULT lNotSetCheck = SendDlgItemMessage(IDC_NOTSET_RADIO, BM_GETCHECK, 0, 0); if (lTrueCheck == BST_CHECKED) { m_bNewValue = TRUE; m_bValueSet = TRUE; } if (lFalseCheck == BST_CHECKED) { m_bNewValue = FALSE; m_bValueSet = TRUE; } if (lNotSetCheck == BST_CHECKED) { m_bValueSet = FALSE; } CDialog::OnOK(); } HRESULT CSingleBooleanEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_BOOLEAN: m_bOldValue = pAttributeEditorInfo->pADsValue->Boolean; m_bValueSet = TRUE; break; default: ASSERT(FALSE); break; } } else { m_bValueSet = FALSE; } } return hr; } HRESULT CSingleBooleanEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } if (!m_bValueSet) { *ppADsValue = NULL; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE; if (*ppADsValue != NULL) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_BOOLEAN: (*ppADsValue)->Boolean = m_bNewValue; break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CSingleBooleanEditor CValueEditDialog* CreateSingleTimeEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CSingleTimeEditor; } BEGIN_MESSAGE_MAP(CSingleTimeEditor, CValueEditDialog) END_MESSAGE_MAP() BOOL CSingleTimeEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); if (m_bValueSet) { SendDlgItemMessage(IDC_DATE_PICKER, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&m_stOldValue); SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&m_stOldValue); } else { SendDlgItemMessage(IDC_DATE_PICKER, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&m_stOldValue); SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&m_stOldValue); } return CDialog::OnInitDialog(); } void CSingleTimeEditor::OnOK() { SYSTEMTIME stDateResult = {0}; SYSTEMTIME stTimeResult = {0}; LRESULT lDateRes = SendDlgItemMessage(IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stDateResult); LRESULT lTimeRes = SendDlgItemMessage(IDC_TIME_PICKER, DTM_SETSYSTEMTIME, 0, (LPARAM)&stTimeResult); if (lDateRes == GDT_VALID && lTimeRes == GDT_VALID) { memcpy(&m_stNewValue, &stDateResult, sizeof(SYSTEMTIME)); m_stNewValue.wHour = stTimeResult.wHour; m_stNewValue.wMinute = stTimeResult.wMinute; m_stNewValue.wSecond = stTimeResult.wSecond; m_stNewValue.wMilliseconds = stTimeResult.wMilliseconds; } CDialog::OnOK(); } HRESULT CSingleTimeEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_UTC_TIME: memcpy(&m_stOldValue, &(pAttributeEditorInfo->pADsValue->UTCTime), sizeof(SYSTEMTIME)); m_bValueSet = TRUE; break; default: ASSERT(FALSE); break; } } else { m_bValueSet = FALSE; } } return hr; } HRESULT CSingleTimeEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } *ppADsValue = new ADSVALUE; if (*ppADsValue != NULL) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_UTC_TIME: memcpy(&((*ppADsValue)->UTCTime), &m_stNewValue, sizeof(SYSTEMTIME)); break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = NULL; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // COctetStringEditor CValueEditDialog* CreateSingleOctetStringEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new COctetStringEditor; } BEGIN_MESSAGE_MAP(COctetStringEditor, CValueEditDialog) ON_EN_CHANGE(IDC_PROCESS_EDIT, OnProcessEdit) ON_BN_CLICKED(IDC_ATTR_EDIT_BUTTON, OnEditButton) ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClearButton) END_MESSAGE_MAP() BOOL COctetStringEditor::OnInitDialog() { // // Initialize the static control with the attribute name // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); DWORD dwDisplayFlags = BYTE_ARRAY_DISPLAY_HEX | BYTE_ARRAY_DISPLAY_DEC | BYTE_ARRAY_DISPLAY_OCT | BYTE_ARRAY_DISPLAY_BIN; VERIFY(m_display.Initialize(IDC_VALUE_EDIT, IDC_VIEW_TYPE_COMBO, dwDisplayFlags, BYTE_ARRAY_DISPLAY_HEX, // default display this, 1024, IDS_OCTET_DISPLAY_SIZE_EXCEEDED)); // Only show 1K of data in the edit box m_display.SetData(m_pOldValue, m_dwOldLength); return CDialog::OnInitDialog(); } void COctetStringEditor::OnOK() { // // Retrieve the new values from the control // if (m_pNewValue) { delete[] m_pNewValue; m_pNewValue = 0; m_dwNewLength = 0; } m_dwNewLength = m_display.GetData(&m_pNewValue); CDialog::OnOK(); } void COctetStringEditor::OnProcessEdit() { CString szProcess; GetDlgItemText(IDC_PROCESS_EDIT, szProcess); if (szProcess.IsEmpty()) { GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(FALSE); // // Set the default button to OK // SendMessage(DM_SETDEFID, (WPARAM)IDOK, 0); SendDlgItemMessage(IDC_ATTR_EDIT_BUTTON, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendDlgItemMessage(IDOK, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); } else { GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(TRUE); // // Set the default button to the Edit button // SendMessage(DM_SETDEFID, (WPARAM)IDC_ATTR_EDIT_BUTTON, 0); SendDlgItemMessage(IDOK, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); SendDlgItemMessage(IDC_ATTR_EDIT_BUTTON, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0)); } } void COctetStringEditor::OnEditButton() { CString szProcess; GetDlgItemText(IDC_PROCESS_EDIT, szProcess); // // Create a temp file and write out the contents of the octet string // WCHAR szTempPath[MAX_PATH]; if (!::GetTempPath(MAX_PATH, szTempPath)) { ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK); return; } CString szDataPath; if (!::GetTempFileName(szTempPath, _T("attredit"), 0x0, szDataPath.GetBuffer(MAX_PATH))) { ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK); return; } szDataPath.ReleaseBuffer(); // // Open the temp file so we can write out the data // CFile tempDataFile; if (!tempDataFile.Open(szDataPath, CFile::modeCreate | CFile::modeReadWrite |CFile::shareExclusive | CFile::typeBinary)) { // // Failed to open temp file, display error message // ADSIEditMessageBox(IDS_MSG_FAIL_CREATE_TEMPFILE, MB_OK); return; } // // Write the byte array to a temp file // BYTE* pData = 0; DWORD dwDataLength = m_display.GetData(&pData); if (dwDataLength != 0 && pData) { tempDataFile.Write(pData, dwDataLength); } tempDataFile.Close(); if (pData) { delete[] pData; pData = 0; } dwDataLength = 0; // // Construct the command line from the executable and the temp file // CString szCommandLine = szProcess + L" " + szDataPath; // // Launch the process with the temp file as an argument // STARTUPINFO si; PROCESS_INFORMATION pi; ::ZeroMemory(&pi,sizeof(PROCESS_INFORMATION)); ::ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb = sizeof (STARTUPINFO); if(CreateProcess( NULL, (LPWSTR)(LPCWSTR)szCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi) ) { // wait to finish the runing setup process WaitForSingleObject(pi.hProcess,INFINITE); // close process handle if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE) { CloseHandle (pi.hProcess) ; } if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE) { CloseHandle (pi.hThread) ; } } else { ADSIEditMessageBox(IDS_MSG_FAIL_LAUNCH_PROCESS, MB_OK); return; } // // Load the data from the saved temp file // if (!LoadFileAsByteArray(szDataPath, &pData, &dwDataLength)) { ADSIEditMessageBox(IDS_MSG_FAIL_RETRIEVE_SAVED_DATA, MB_OK); return; } // // Delete temp file after picture is displayed // CFile::Remove(szDataPath); // // Update the UI with the new data // m_display.SetData(pData, dwDataLength); } void COctetStringEditor::OnClearButton() { m_display.ClearData(); } HRESULT COctetStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue) { switch (pAttributeEditorInfo->pADsValue->dwType) { case ADSTYPE_OCTET_STRING: m_dwOldLength = pAttributeEditorInfo->pADsValue->OctetString.dwLength; m_pOldValue = new BYTE[m_dwOldLength]; if (m_pOldValue) { memcpy(m_pOldValue, pAttributeEditorInfo->pADsValue->OctetString.lpValue, m_dwOldLength); } else { hr = E_OUTOFMEMORY; } m_bValueSet = TRUE; break; default: ASSERT(FALSE); break; } } else { m_bValueSet = FALSE; } } return hr; } HRESULT COctetStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (ppADsValue == NULL || pdwNumValues == NULL) { return E_OUTOFMEMORY; } if (m_dwNewLength > 0 && m_pNewValue) { *ppADsValue = new ADSVALUE; if (*ppADsValue) { *pdwNumValues = 1; (*ppADsValue)->dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_OCTET_STRING: (*ppADsValue)->OctetString.dwLength = m_dwNewLength; (*ppADsValue)->OctetString.lpValue = new BYTE[m_dwNewLength]; if ((*ppADsValue)->OctetString.lpValue) { memcpy((*ppADsValue)->OctetString.lpValue, m_pNewValue, m_dwNewLength); } else { hr = E_OUTOFMEMORY; } break; default: ASSERT(FALSE); delete *ppADsValue; *ppADsValue = 0; *pdwNumValues = 0; hr = E_FAIL; break; } } else { *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } else { *ppADsValue = 0; *pdwNumValues = 0; } return hr; } CValueEditDialog* CreateMultiOctetStringEditor(PCWSTR pszClass, PCWSTR pszAttribute, ADSTYPE adsType, BOOL bMultivalued) { return new CMultiOctetStringEditor; } BEGIN_MESSAGE_MAP(CMultiOctetStringEditor, CValueEditDialog) ON_BN_CLICKED(IDC_ATTR_ADD_BUTTON, OnAddButton) ON_BN_CLICKED(IDC_ATTR_REMOVE_BUTTON, OnRemoveButton) ON_BN_CLICKED(IDC_EDIT_BUTTON, OnEditButton) ON_LBN_SELCHANGE(IDC_VALUE_LIST, OnListSelChange) END_MESSAGE_MAP() BOOL CMultiOctetStringEditor::OnInitDialog() { CDialog::OnInitDialog(); // // Set the attribute name static // SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute); // // Fill the list box with the current values // POSITION pos = m_OldValueList.GetHeadPosition(); while (pos) { PADSVALUE pADsValue = m_OldValueList.GetNext(pos); if (pADsValue) { CString szValue; GetStringFromADsValue(pADsValue, szValue, MAX_OCTET_STRING_VALUE_LENGTH); LRESULT lIdx = SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szValue); if (lIdx != LB_ERR || lIdx != LB_ERRSPACE) { LRESULT lSetData = SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lIdx, (LPARAM)pADsValue); if (lSetData == LB_ERR) { ASSERT(lSetData != LB_ERR); continue; } } } } // // The remove button should be disabled until something is selected in the listbox // GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE); SendDlgItemMessage(IDC_VALUE_LIST, LB_SETCURSEL, 0, 0); ManageButtonStates(); // // Update the width of the list box // UpdateListboxHorizontalExtent(); // // NOTE: I have explicitly set the focus so return 0 // return FALSE; } void CMultiOctetStringEditor::OnOK() { // // Get the values out of the list box // m_NewValueList.RemoveAll(); CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { int iCount = pListBox->GetCount(); for (int idx = 0; idx < iCount; idx++) { CString szNewValue; LRESULT lData = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETITEMDATA, (WPARAM)idx, 0); if (lData == LB_ERR) { ASSERT(lData != LB_ERR); continue; } m_NewValueList.AddTail(reinterpret_cast(lData)); } } CDialog::OnOK(); } void CMultiOctetStringEditor::OnEditButton() { LRESULT lIdx = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0); if (lIdx == LB_ERR) { ASSERT(lIdx != LB_ERR); return; } LRESULT lData = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETITEMDATA, (WPARAM)lIdx, 0); if (lData == LB_ERR) { ASSERT(lIdx != LB_ERR); return; } PADSVALUE pADsValue = reinterpret_cast(lData); if (!pADsValue) { ASSERT(pADsValue); return; } DS_ATTRIBUTE_EDITORINFO attrEditInfo; ::ZeroMemory(&attrEditInfo, sizeof(DS_ATTRIBUTE_EDITORINFO)); attrEditInfo.pADsValue = pADsValue; attrEditInfo.dwNumValues = 1; attrEditInfo.lpszClass = (PWSTR)(PCWSTR)m_szClass; attrEditInfo.lpszAttribute = (PWSTR)(PCWSTR)m_szAttribute; attrEditInfo.bMultivalued = FALSE; attrEditInfo.lpfnBind = m_pfnBindingFunction; attrEditInfo.lParam = m_lParam; COctetStringEditor dlg; HRESULT hr = dlg.Initialize(&attrEditInfo); if (FAILED(hr)) { ADSIEditErrorMessage(hr, IDS_FAILED_INITIALIZE_EDITOR, MB_OK | MB_ICONEXCLAMATION); return; } if (dlg.DoModal() == IDOK) { PADSVALUE pNewADsValue = 0; DWORD dwNumNewValues = 0; hr = dlg.GetNewValue(&pNewADsValue, &dwNumNewValues); if (FAILED(hr)) { ADSIEditErrorMessage(hr, IDS_FAILED_GET_NEW_VALUE_EDITOR, MB_OK | MB_ICONEXCLAMATION); return; } ASSERT(pNewADsValue); ASSERT(dwNumNewValues == 1); CString szNewValue; GetStringFromADsValue(pNewADsValue, szNewValue, MAX_OCTET_STRING_VALUE_LENGTH); ASSERT(!szNewValue.IsEmpty()); LRESULT lNewIdx = SendDlgItemMessage(IDC_VALUE_LIST, LB_INSERTSTRING, lIdx + 1, (LPARAM)(PCWSTR)szNewValue); if (lNewIdx != LB_ERR) { // // Update the new item and delete the old // SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lNewIdx, (LPARAM)pNewADsValue); SendDlgItemMessage(IDC_VALUE_LIST, LB_DELETESTRING, (WPARAM)lIdx, 0); } else { // // Since we had trouble adding the new item just update the old one. The string // will be incorrect but the value will be fine. // SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lIdx, (LPARAM)pNewADsValue); } } } void CMultiOctetStringEditor::OnRemoveButton() { CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { int iCurSel = pListBox->GetCurSel(); if (iCurSel != LB_ERR) { // // Delete the item from the list box // pListBox->DeleteString(iCurSel); } } // // Manage Button States // ManageButtonStates(); // // Update the width of the list box // UpdateListboxHorizontalExtent(); } void CMultiOctetStringEditor::OnAddButton() { DS_ATTRIBUTE_EDITORINFO attrEditInfo; ZeroMemory(&attrEditInfo, sizeof(DS_ATTRIBUTE_EDITORINFO)); attrEditInfo.pADsValue = new ADSVALUE; if (attrEditInfo.pADsValue) { ::ZeroMemory(attrEditInfo.pADsValue, sizeof(ADSVALUE)); } attrEditInfo.pADsValue->dwType = ADSTYPE_OCTET_STRING; attrEditInfo.dwNumValues = 0; attrEditInfo.lpszClass = (PWSTR)(PCWSTR)m_szClass; attrEditInfo.lpszAttribute = (PWSTR)(PCWSTR)m_szAttribute; attrEditInfo.bMultivalued = FALSE; attrEditInfo.lpfnBind = m_pfnBindingFunction; attrEditInfo.lParam = m_lParam; COctetStringEditor dlg; HRESULT hr = dlg.Initialize(&attrEditInfo); if (FAILED(hr)) { ADSIEditErrorMessage(hr, IDS_FAILED_INITIALIZE_EDITOR, MB_OK | MB_ICONEXCLAMATION); return; } if (dlg.DoModal() == IDOK) { PADSVALUE pNewADsValue = 0; DWORD dwNumNewValues = 0; hr = dlg.GetNewValue(&pNewADsValue, &dwNumNewValues); if (FAILED(hr)) { ADSIEditErrorMessage(hr, IDS_FAILED_GET_NEW_VALUE_EDITOR, MB_OK | MB_ICONEXCLAMATION); return; } ASSERT(pNewADsValue); ASSERT(dwNumNewValues == 1); CString szNewValue; GetStringFromADsValue(pNewADsValue, szNewValue, MAX_OCTET_STRING_VALUE_LENGTH); if (!szNewValue.IsEmpty()) { LRESULT lNewIdx = SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (WPARAM)(PCWSTR)szNewValue); if (lNewIdx != LB_ERR) { SendDlgItemMessage(IDC_VALUE_LIST, LB_SETITEMDATA, (WPARAM)lNewIdx, (LPARAM)pNewADsValue); } } } } void CMultiOctetStringEditor::ManageButtonStates() { LRESULT lSelection = SendDlgItemMessage(IDC_VALUE_LIST, LB_GETCURSEL, 0, 0); if (lSelection != LB_ERR) { GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(TRUE); GetDlgItem(IDC_EDIT_BUTTON)->EnableWindow(TRUE); } else { GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE); GetDlgItem(IDC_EDIT_BUTTON)->EnableWindow(FALSE); } } void CMultiOctetStringEditor::OnListSelChange() { ManageButtonStates(); } void CMultiOctetStringEditor::UpdateListboxHorizontalExtent() { // // Note if the size passed to SetHorizontalExtent is less than the width of the control // then the scroll bar will be removed // int nHorzExtent = 0; CListBox* pListBox = reinterpret_cast(GetDlgItem(IDC_VALUE_LIST)); if (pListBox != NULL) { CClientDC dc(pListBox); int nItems = pListBox->GetCount(); for (int i=0; i < nItems; i++) { TEXTMETRIC tm; VERIFY(dc.GetTextMetrics(&tm)); CString szBuffer; pListBox->GetText(i, szBuffer); CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength()); nHorzExtent = max(ext.cx ,nHorzExtent); } pListBox->SetHorizontalExtent(nHorzExtent); } } HRESULT CMultiOctetStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { HRESULT hr = S_OK; if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo))) { if (pAttributeEditorInfo->dwNumValues > 0 && pAttributeEditorInfo->pADsValue != NULL) { for (int idx = 0; idx < pAttributeEditorInfo->dwNumValues; idx++) { switch (pAttributeEditorInfo->pADsValue[idx].dwType) { case ADSTYPE_OCTET_STRING: m_OldValueList.AddTail(&(pAttributeEditorInfo->pADsValue[idx])); break; default: ASSERT(FALSE); break; } } } } return hr; } HRESULT CMultiOctetStringEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues) { HRESULT hr = S_OK; if (!ppADsValue || !pdwNumValues) { return E_OUTOFMEMORY; } int iCount = m_NewValueList.GetCount(); if (iCount == 0) { *ppADsValue = 0; *pdwNumValues = 0; } else { *ppADsValue = new ADSVALUE[iCount]; if (*ppADsValue) { *pdwNumValues = iCount; int idx = 0; POSITION pos = m_NewValueList.GetHeadPosition(); while (pos) { PADSVALUE pADsValue = m_NewValueList.GetNext(pos); (*ppADsValue)[idx].dwType = m_pOldADsValue->dwType; switch (m_pOldADsValue->dwType) { case ADSTYPE_OCTET_STRING: (*ppADsValue)[idx].OctetString.dwLength = pADsValue->OctetString.dwLength; (*ppADsValue)[idx].OctetString.lpValue = new BYTE[pADsValue->OctetString.dwLength]; if ((*ppADsValue)[idx].OctetString.lpValue) { memcpy((*ppADsValue)[idx].OctetString.lpValue, pADsValue->OctetString.lpValue, pADsValue->OctetString.dwLength); } else { for (int i = 0; i < idx; i++) { if ((*ppADsValue)[i].OctetString.lpValue) { delete[] (*ppADsValue)[i].OctetString.lpValue; (*ppADsValue)[i].OctetString.lpValue = 0; } } delete[] *ppADsValue; *ppADsValue = 0; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } break; default: ASSERT(FALSE); for (int i = 0; i < idx; i++) { if ((*ppADsValue)[i].OctetString.lpValue) { delete[] (*ppADsValue)[i].OctetString.lpValue; (*ppADsValue)[i].OctetString.lpValue = 0; } } delete[] *ppADsValue; *ppADsValue = 0; *pdwNumValues = 0; hr = E_FAIL; break; } if (FAILED(hr)) { return hr; } idx++; } } else { *ppADsValue = NULL; *pdwNumValues = 0; hr = E_OUTOFMEMORY; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////// // CAttributeEditorPropertyPage BEGIN_MESSAGE_MAP(CAttributeEditorPropertyPage, CPropertyPage) ON_BN_CLICKED(IDC_MANDATORY_CHECK, OnMandatoryCheck) ON_BN_CLICKED(IDC_OPTIONAL_CHECK, OnOptionalCheck) ON_BN_CLICKED(IDC_SET_CHECK, OnValueSetCheck) ON_BN_CLICKED(IDC_ATTR_EDIT_BUTTON,OnEditAttribute) ON_NOTIFY(LVN_ITEMACTIVATE, IDC_ATTRIBUTE_LIST, OnNotifyEditAttribute) ON_NOTIFY(LVN_ITEMCHANGED, IDC_ATTRIBUTE_LIST, OnListItemChanged) ON_NOTIFY(LVN_COLUMNCLICK, IDC_ATTRIBUTE_LIST, OnSortList) END_MESSAGE_MAP() CAttributeEditorPropertyPage::CAttributeEditorPropertyPage(IADs* pIADs, IADsClass* pIADsClass, LPDS_ATTREDITOR_BINDINGINFO pBindingInfo, CADSIEditPropertyPageHolder* pHolder) : CPropertyPage(IDD_ATTRIBUTE_EDITOR_DIALOG) { m_spIADs = pIADs; m_spIADsClass = pIADsClass; m_bMandatory = TRUE; m_bOptional = TRUE; m_bSet = FALSE; m_nSortColumn = 0; ASSERT(pBindingInfo != NULL); ASSERT(pBindingInfo->dwSize == sizeof(DS_ATTREDITOR_BINDINGINFO)); ASSERT(pBindingInfo->lpfnBind != NULL); ASSERT(pBindingInfo->lpszProviderServer != NULL); m_szPrefix = pBindingInfo->lpszProviderServer; m_pfnBind = pBindingInfo->lpfnBind; m_BindLPARAM = pBindingInfo->lParam; m_dwBindFlags = pBindingInfo->dwFlags; m_pHolder = pHolder; ASSERT(m_pHolder); } CAttributeEditorPropertyPage::~CAttributeEditorPropertyPage() { } BOOL CAttributeEditorPropertyPage::OnInitDialog() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CWaitCursor cursor; // Set the hwnd in the property page holder so that we can // be activated when necessary m_pHolder->SetSheetWindow(GetParent()->GetSafeHwnd()); ((CButton*)GetDlgItem(IDC_MANDATORY_CHECK))->SetCheck(TRUE); ((CButton*)GetDlgItem(IDC_OPTIONAL_CHECK))->SetCheck(TRUE); ((CButton*)GetDlgItem(IDC_SET_CHECK))->SetCheck(FALSE); GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(FALSE); HRESULT hr = GetSchemaNamingContext(); ShowListCtrl(); hr = RetrieveAttributes(); if (FAILED(hr)) { TRACE(_T("OnInitDialog() : error returned from RetrieveAttributes() = 0x%x\n"), hr); } CComBSTR bstr; hr = m_spIADs->get_Class(&bstr); if (FAILED(hr)) { TRACE(_T("OnInitDialog() : error returned from m_pIADs->get_Class() = 0x%x\n"), hr); } else { m_szClass = bstr; } FillListControl(); return FALSE; } HRESULT CAttributeEditorPropertyPage::GetSchemaNamingContext() { HRESULT hr = S_OK; CComPtr spIADs; CString m_szPath = m_szPrefix + _T("RootDSE"); hr = m_pfnBind(m_szPath, ADS_SECURE_AUTHENTICATION, IID_IADs, (PVOID*)&spIADs, m_BindLPARAM); if (SUCCEEDED(hr)) { CComVariant var; hr = spIADs->Get(L"schemaNamingContext", &var); if (SUCCEEDED(hr)) { m_szSchemaNamingContext = var.bstrVal; } } m_szSchemaNamingContext = m_szPrefix + m_szSchemaNamingContext; return hr; } BOOL CAttributeEditorPropertyPage::OnApply() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); if (m_AttrList.HasDirty()) { CComPtr spDirObject; // bind to object with authentication // HRESULT hr = S_OK; hr = m_spIADs->QueryInterface(IID_IDirectoryObject, (PVOID*) &spDirObject); if (FAILED(hr)) { AfxMessageBox(L"Failed to QI the IDirectoryObject from the IADs."); return FALSE; } // Change or add values to ADSI cache that have changed // hr = CADSIAttribute::SetValuesInDS(&m_AttrList, spDirObject); if (FAILED(hr)) { ADSIEditErrorMessage(hr); // // Instead of removing all the attributes we need to query for the ones that failed // or something to that effect. // // m_AttrList.RemoveAllAttr(); return FALSE; } } return TRUE; } void CAttributeEditorPropertyPage::OnMandatoryCheck() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TRACE(_T("OnMandatoryCheck()\n")); m_bMandatory = ((CButton*)GetDlgItem(IDC_MANDATORY_CHECK))->GetCheck(); FillListControl(); } void CAttributeEditorPropertyPage::OnOptionalCheck() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TRACE(_T("OnOptionalCheck()\n")); m_bOptional = ((CButton*)GetDlgItem(IDC_OPTIONAL_CHECK))->GetCheck(); FillListControl(); } void CAttributeEditorPropertyPage::OnValueSetCheck() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TRACE(_T("OnValueSetCheck()\n")); m_bSet = ((CButton*)GetDlgItem(IDC_SET_CHECK))->GetCheck(); FillListControl(); } // // Callback function used by CListCtrl::SortItems the items by the column that was clicked // static int CALLBACK CompareAttrColumns(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CAttributeEditorPropertyPage* pProppage = reinterpret_cast(lParamSort); if (!pProppage) { ASSERT(pProppage); return 0; } UINT nColumn = pProppage->GetSortColumn(); CListCtrl* pListCtrl = (CListCtrl*)pProppage->GetDlgItem(IDC_ATTRIBUTE_LIST); if (!pListCtrl) { ASSERT(pListCtrl); return 0; } // // Since lParam1 and lParam2 are pointers to the data we have to search for each item // in the list and remember their index // int iItem1 = -1; int iItem2 = -1; LVFINDINFO findInfo; ZeroMemory(&findInfo, sizeof(LVFINDINFO)); findInfo.flags = LVFI_PARAM; findInfo.lParam = lParam1; iItem1 = pListCtrl->FindItem(&findInfo); findInfo.lParam = lParam2; iItem2 = pListCtrl->FindItem(&findInfo); // // Put any items with values above those that don't have values // int iRetVal = 0; if (iItem1 != -1 && iItem2 == -1) { iRetVal = -1; } else if (iItem1 == -1 && iItem2 != -1) { iRetVal = 1; } else if (iItem1 == -1 && iItem2 == -1) { iRetVal = 0; } else { CString szItem1 = pListCtrl->GetItemText(iItem1, nColumn); CString szItem2 = pListCtrl->GetItemText(iItem2, nColumn); // // Have to put this in so that empty strings end up at the bottom // if (szItem1.IsEmpty() && !szItem2.IsEmpty()) { iRetVal = 1; } else if (!szItem1.IsEmpty() && szItem2.IsEmpty()) { iRetVal = -1; } else { iRetVal = _wcsicmp(szItem1, szItem2); } } return iRetVal; } void CAttributeEditorPropertyPage::OnSortList(NMHDR* pNotifyStruct, LRESULT* result) { if (!result || !pNotifyStruct) { return; } *result = 0; // // Get the list view notify struct // LPNMLISTVIEW pnmv = (LPNMLISTVIEW)pNotifyStruct; if (!pnmv) { return; } // // Right now I only have 3 columns // if (pnmv->iSubItem < 0 || pnmv->iSubItem >= 3) { return; } // // Store the sort column // m_nSortColumn = pnmv->iSubItem; CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl); pAttrListCtrl->SortItems(CompareAttrColumns, reinterpret_cast(this)); } void CAttributeEditorPropertyPage::OnListItemChanged(NMHDR* /*pNotifyStruct*/, LRESULT* result) { if (!result) { return; } *result = 0; SetEditButton(); } void CAttributeEditorPropertyPage::SetEditButton() { // // Enable the edit button if something is selected in the ListCtrl // BOOL bEnableEdit = FALSE; if (!(m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)) { CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED); if (nSelectedItem != -1) { bEnableEdit = TRUE; } } GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(bEnableEdit); } void CAttributeEditorPropertyPage::OnNotifyEditAttribute(NMHDR* pNotifyStruct, LRESULT* result) { if (result == NULL || pNotifyStruct == NULL) { return; } // // Don't allow editing on the RootDSE // if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE) { *result = 0; return; } LPNMITEMACTIVATE pnmia = (LPNMITEMACTIVATE)pNotifyStruct; ASSERT(pnmia != NULL); if (pnmia != NULL) { int iSelectedItem = pnmia->iItem; if (iSelectedItem != -1) { CADSIAttribute* pSelectedAttr = GetAttributeFromList(iSelectedItem); if (pSelectedAttr != NULL) { EditAttribute(pSelectedAttr); } else { // // REVIEW_JEFFJON : display an appropriate error message // } } } *result = 0; } void CAttributeEditorPropertyPage::OnEditAttribute() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); TRACE(_T("OnEditAttribute()\n")); CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED); if (nSelectedItem == -1) { return; } CADSIAttribute* pSelectedAttr = GetAttributeFromList(nSelectedItem); ASSERT(pSelectedAttr != NULL); EditAttribute(pSelectedAttr); } void CAttributeEditorPropertyPage::EditAttribute(CADSIAttribute* pSelectedAttr) { HRESULT hr = S_OK; // // Retrieve all necessary info for initializing the appropriate editor // LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo = NULL; BOOL bOwnValueMemory = FALSE; GetAttributeInfo(pSelectedAttr, &pAttributeEditorInfo, &bOwnValueMemory); if (pAttributeEditorInfo == NULL) { ADSIEditMessageBox(IDS_NO_ATTRIBUTE_INFO, MB_OK); return; } // // Obtain the editor from the attribute and syntax map // CValueEditDialog* pEditorDialog = RetrieveEditor(pAttributeEditorInfo); if (pEditorDialog) { hr = pEditorDialog->Initialize(pAttributeEditorInfo); if (SUCCEEDED(hr)) { if (pEditorDialog->DoModal() == IDOK) { PADSVALUE pNewValue = 0; DWORD dwNumValues = 0; hr = pEditorDialog->GetNewValue(&pNewValue, &dwNumValues); if (SUCCEEDED(hr)) { // // Do what ever needs done with the new value // hr = pSelectedAttr->SetValues(pNewValue, dwNumValues); // // REVIEW_JEFFJON : what should be done here if that failed? // pSelectedAttr->SetDirty(TRUE); CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED); if (nSelectedItem != -1) { if (dwNumValues > 0) { // // Get the new values (limit each individual value to MAX_OCTET_STRING_VALUE_LENGTH characters) // CStringList szValuesList; pSelectedAttr->GetValues(szValuesList, MAX_OCTET_STRING_VALUE_LENGTH); CString szCombinedString; POSITION pos = szValuesList.GetHeadPosition(); while (pos != NULL) { CString szTemp = szValuesList.GetNext(pos); szCombinedString += szTemp; if (pos != NULL) { szCombinedString += L";"; } } VERIFY(-1 != pAttrListCtrl->SetItemText(nSelectedItem, 2, szCombinedString)); } else { CString szNotSet; VERIFY(szNotSet.LoadString(IDS_ATTR_NOTSET)); VERIFY(-1 != pAttrListCtrl->SetItemText(nSelectedItem, 2, szNotSet)); } } SetModified(); } else { // // REVIEW_JEFFJON : handle the GetNewValue() failure // ASSERT(FALSE); ADSIEditErrorMessage(hr); } } } else { // // REVIEW_JEFFJON : Handle the error Initialize // ASSERT(FALSE); ADSIEditErrorMessage(hr); } if (pEditorDialog) { delete pEditorDialog; pEditorDialog = 0; } } else { // // Unable to retrieve an appropriate editor for this attribute // ADSIEditMessageBox(IDS_NO_EDITOR, MB_OK); } if (pAttributeEditorInfo) { if (pAttributeEditorInfo->lpszAttribute) { delete[] pAttributeEditorInfo->lpszAttribute; } if (pAttributeEditorInfo->lpszClass) { delete[] pAttributeEditorInfo->lpszClass; } if (pAttributeEditorInfo->pADsValue && bOwnValueMemory) { delete pAttributeEditorInfo->pADsValue; pAttributeEditorInfo->pADsValue = 0; } delete pAttributeEditorInfo; pAttributeEditorInfo = 0; } } CADSIAttribute* CAttributeEditorPropertyPage::GetAttributeFromList(int iSelectedItem) { if (iSelectedItem == -1) { return NULL; } CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); return (CADSIAttribute*)pAttrListCtrl->GetItemData(iSelectedItem); } void CAttributeEditorPropertyPage::GetAttributeInfo(CADSIAttribute* pAttr, LPDS_ATTRIBUTE_EDITORINFO* ppAttributeEditorInfo, BOOL* pbOwnValueMemory) { // // Get the attribute to be edited // CString szAttribute = _T(""); pAttr->GetProperty(szAttribute); // // Get the type and whether it is multi-valued or not by the syntax // of the attribute // CString szSyntax; BOOL bMultiValued = FALSE; ADSTYPE adsType = RetrieveADsTypeFromSyntax(szAttribute, &bMultiValued, szSyntax); *pbOwnValueMemory = FALSE; DWORD dwNumValues = 0; PADSVALUE pADsValue = pAttr->GetADsValues(); if (!pADsValue) { // // Value for attribute was not set so we have to // create an empty ADSVALUE to pass the type // pADsValue = new ADSVALUE; ASSERT(pADsValue != NULL); pADsValue->dwType = adsType; dwNumValues = 0; *pbOwnValueMemory = TRUE; } else { // // Get the number of values in the attribute // dwNumValues = pAttr->GetNumValues(); } // // Figure out how much space we need // DWORD dwStructSize = sizeof(DS_ATTRIBUTE_EDITORINFO); DWORD dwClassSize = m_szClass.GetLength() + 1; DWORD dwAttrSize = szAttribute.GetLength() + 1; try { *ppAttributeEditorInfo = new DS_ATTRIBUTE_EDITORINFO; ASSERT(*ppAttributeEditorInfo != NULL); if (*ppAttributeEditorInfo != NULL) { (*ppAttributeEditorInfo)->lpszClass = new WCHAR[dwClassSize]; if (m_szClass != _T("")) { wcscpy((*ppAttributeEditorInfo)->lpszClass, m_szClass); } (*ppAttributeEditorInfo)->lpszAttribute = new WCHAR[dwAttrSize]; if (szAttribute != _T("")) { wcscpy((*ppAttributeEditorInfo)->lpszAttribute, szAttribute); } (*ppAttributeEditorInfo)->adsType = adsType; (*ppAttributeEditorInfo)->bMultivalued = bMultiValued; (*ppAttributeEditorInfo)->dwNumValues = dwNumValues; (*ppAttributeEditorInfo)->pADsValue = pADsValue; (*ppAttributeEditorInfo)->dwSize = sizeof(DS_ATTRIBUTE_EDITORINFO); } else { delete pADsValue; pADsValue = 0; } } catch (...) { if (pADsValue) { delete pADsValue; pADsValue = 0; } } } void CAttributeEditorPropertyPage::ShowListCtrl() { CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); // Set full row select ListView_SetExtendedListViewStyle( pAttrListCtrl->GetSafeHwnd(), LVS_EX_FULLROWSELECT); // // Insert the Attribute column // CString szAttribute; VERIFY(szAttribute.LoadString(IDS_ATTR_COL_ATTRIBUTE)); int iRet = pAttrListCtrl->InsertColumn(0, szAttribute, LVCFMT_LEFT, 120); if (iRet == -1) { TRACE(_T("Failed to insert the \"Attribute\" column.\n")); } // // Insert the Syntax column // This column will be hidden by default // CString szSyntax; VERIFY(szSyntax.LoadString(IDS_ATTR_COL_SYNTAX)); iRet = pAttrListCtrl->InsertColumn(1, szSyntax, LVCFMT_LEFT, 90); if (iRet == -1) { TRACE(_T("Failed to insert the \"Syntax\" column.\n")); } // // Insert the Value column // CString szValue; VERIFY(szValue.LoadString(IDS_ATTR_COL_VALUE)); iRet = pAttrListCtrl->InsertColumn(2, szValue, LVCFMT_LEFT, 400); if (iRet == -1) { TRACE(_T("Failed to insert the \"Value\" column.\n")); } } void CAttributeEditorPropertyPage::FillListControl() { TRACE(_T("FillListControl()\n")); CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST); ASSERT(pAttrListCtrl != NULL); CString szNotSet; VERIFY(szNotSet.LoadString(IDS_ATTR_NOTSET)); // // Clear the list control // pAttrListCtrl->DeleteAllItems(); // // Add the attributes and their values into the list control // UINT nState = 0; int nIndex = 0; POSITION pos = m_AttrList.GetHeadPosition(); while (pos != NULL) { CADSIAttribute* pAttr = m_AttrList.GetNext(pos); ASSERT(pAttr != NULL); CString szProperty; pAttr->GetProperty(szProperty); // // Don't add the nTSecurityDescriptor, we use the ACL UI instead // if (szProperty.CompareNoCase(L"nTSecurityDescriptor") == 0) { continue; } if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE) { int iNewIndex = pAttrListCtrl->InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex, szProperty, nState, 0, 0, (LPARAM)pAttr); if (iNewIndex != -1) { CString szValue; szValue = m_RootDSEValueList.GetAt(m_RootDSEValueList.FindIndex(nIndex)); if (!szValue.IsEmpty()) { VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szValue)); } else { VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szNotSet)); } } nIndex++; } else // not RootDSE { if ((m_bMandatory && pAttr->IsMandatory()) || (m_bOptional && !pAttr->IsMandatory())) { if (!m_bSet || (m_bSet && pAttr->IsValueSet())) { int iNewIndex = pAttrListCtrl->InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex, szProperty, nState, 0, 0, (LPARAM)pAttr); if (iNewIndex != -1) { // Insert the syntax VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 1, pAttr->GetSyntax())); // Insert the value if (pAttr->IsValueSet()) { // // Retrieve the values // CStringList szValuesList; pAttr->GetValues(szValuesList); CString szCombinedString; POSITION posList = szValuesList.GetHeadPosition(); while (posList) { CString szTemp = szValuesList.GetNext(posList); szCombinedString += szTemp; if (posList) { szCombinedString += L";"; } } VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szCombinedString)); } else { VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 2, szNotSet)); } } nIndex++; } } } } TRACE(_T("Added %u properties\n"), nIndex); // // Select the first attribute in the list // pAttrListCtrl->SetItemState(0, 1, LVIS_SELECTED); SetEditButton(); } HRESULT CAttributeEditorPropertyPage::RetrieveAttributes() { TRACE(_T("RetrieveAttributes()\n")); HRESULT hr = S_OK; CWaitCursor cursor; if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE) { CStringList sMandList; m_spIADs->GetInfo(); CComPtr spPropList; hr = m_spIADs->QueryInterface(IID_IADsPropertyList, (PVOID*)&spPropList); if (SUCCEEDED(hr)) { LONG lCount = 0; hr = spPropList->get_PropertyCount(&lCount); if (SUCCEEDED(hr) && lCount > 0) { CComVariant var; while (hr == S_OK) { hr = spPropList->Next(&var); if (hr == S_OK) { ASSERT(var.vt == VT_DISPATCH); CComPtr spEntry; hr = V_DISPATCH(&var)->QueryInterface(IID_IADsPropertyEntry, (PVOID*)&spEntry); if (SUCCEEDED(hr)) { CComBSTR bstrName; hr = spEntry->get_Name(&bstrName); if (SUCCEEDED(hr)) { sMandList.AddTail(bstrName); } } } } } } hr = CreateAttributeList(sMandList, TRUE); } else { // // Retrieve mandatory properties // CStringList sMandList; VARIANT varMand; VariantInit(&varMand); hr = m_spIADsClass->get_MandatoryProperties(&varMand); if (SUCCEEDED(hr)) { VariantToStringList( varMand, sMandList ); } VariantClear(&varMand); // // Retrieve optional properties // CStringList sOptionalList; VARIANT varOpt; VariantInit(&varOpt); hr = m_spIADsClass->get_OptionalProperties(&varOpt); if (SUCCEEDED(hr)) { VariantToStringList( varOpt, sOptionalList ); } VariantClear(&varOpt); hr = CreateAttributeList(sMandList, TRUE); if (FAILED(hr)) { return hr; } hr = CreateAttributeList(sOptionalList, FALSE); if (FAILED(hr)) { return hr; } } return hr; } HRESULT CAttributeEditorPropertyPage::CreateAttributeList(CStringList& sAttrList, BOOL bMandatory) { HRESULT hr = S_OK; LPWSTR* lpszAttrArray; UINT nCount = 0; GetStringArrayFromStringList(sAttrList, &lpszAttrArray, &nCount); TRACE(_T("There are %u properties to add\n"), nCount); for (UINT idx = 0; idx < nCount; idx++) { CADSIAttribute* pNewAttr = new CADSIAttribute(lpszAttrArray[idx]); ASSERT(pNewAttr != NULL); pNewAttr->SetMandatory(bMandatory); // Get the syntax BOOL bMultivalued = FALSE; CString szSyntax; ADSTYPE adstype = RetrieveADsTypeFromSyntax(lpszAttrArray[idx], &bMultivalued, szSyntax); pNewAttr->SetADsType(adstype); pNewAttr->SetMultivalued(bMultivalued); pNewAttr->SetSyntax(szSyntax); m_AttrList.AddTail(pNewAttr); } // // Retrieve the values that are set // #define RETRIEVESET #ifdef RETRIEVESET if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE) { // // Special case RootDSE because it does not support IDirectoryObject // hr = m_spIADs->GetInfo(); for (UINT idx = 0; idx < nCount; idx++) { VARIANT var; hr = m_spIADs->GetEx( lpszAttrArray[idx] , &var ); if ( FAILED(hr) ) { m_RootDSEValueList.AddTail(L" "); continue; } ///////////////////////////////////////// // Convert and populate /////////////////////////////////////////// CStringList sList; hr = VariantToStringList( var, sList ); if (SUCCEEDED(hr)) { CString szTempValue; POSITION pos = sList.GetHeadPosition(); while (pos != NULL) { CString szValue = sList.GetNext(pos); if (szTempValue.IsEmpty()) { szTempValue += szValue; } else { szTempValue += L";" + szValue; } } m_RootDSEValueList.AddTail(szTempValue); } } } else { CComPtr spDirObject; hr = m_spIADs->QueryInterface(IID_IDirectoryObject, (PVOID*)&spDirObject); if (FAILED(hr)) { return hr; } PADS_ATTR_INFO pAttrInfo = NULL; DWORD dwReturned = 0; hr = spDirObject->GetObjectAttributes(lpszAttrArray, nCount, &pAttrInfo, &dwReturned); if (SUCCEEDED(hr)) { // // Save the attribute info pointer for later deletion // if (bMandatory) { m_AttrList.SaveMandatoryValuesPointer(pAttrInfo); } else { m_AttrList.SaveOptionalValuesPointer(pAttrInfo); } for (DWORD idx = 0; idx < dwReturned; idx++) { POSITION pos = m_AttrList.FindProperty(pAttrInfo[idx].pszAttrName); CADSIAttribute* pNewAttr = m_AttrList.GetAt(pos); ASSERT(pNewAttr != NULL); pNewAttr->SetValueSet(TRUE); pNewAttr->SetAttrInfo(&(pAttrInfo[idx])); } TRACE(_T("Added %u properties to the list\nThe list has %u total properties\n"), dwReturned, m_AttrList.GetCount()); } else { ADSIEditErrorMessage(hr, IDS_MSG_FAIL_LOAD_VALUES, MB_OK); } for (UINT nIndex = 0; nIndex < nCount; nIndex++) { delete lpszAttrArray[nIndex]; lpszAttrArray[nIndex] = NULL; } delete[] lpszAttrArray; lpszAttrArray = NULL; } #endif //RETRIEVESET return hr; } ATTR_EDITOR_MAP g_attrEditorMap[] = { // Class, Attribute, ADSTYPE, Multivalued, Creation function { NULL, NULL, ADSTYPE_DN_STRING, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_DN_STRING, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_CASE_IGNORE_STRING, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_CASE_IGNORE_STRING, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_CASE_EXACT_STRING, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_CASE_EXACT_STRING, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_PRINTABLE_STRING, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_PRINTABLE_STRING, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_NUMERIC_STRING, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_NUMERIC_STRING, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_OBJECT_CLASS, FALSE, CreateSingleStringEditor }, { NULL, NULL, ADSTYPE_OBJECT_CLASS, TRUE, CreateMultiStringEditor }, { NULL, NULL, ADSTYPE_INTEGER, FALSE, CreateSingleIntEditor }, { NULL, NULL, ADSTYPE_LARGE_INTEGER, FALSE, CreateSingleLargeIntEditor }, { NULL, NULL, ADSTYPE_BOOLEAN, FALSE, CreateSingleBooleanEditor }, { NULL, NULL, ADSTYPE_UTC_TIME, FALSE, CreateSingleTimeEditor }, { NULL, NULL, ADSTYPE_TIMESTAMP, FALSE, CreateSingleTimeEditor }, { NULL, NULL, ADSTYPE_OCTET_STRING, FALSE, CreateSingleOctetStringEditor }, { NULL, NULL, ADSTYPE_OCTET_STRING, TRUE, CreateMultiOctetStringEditor }, }; size_t g_attrEditMapCount = sizeof(g_attrEditorMap)/sizeof(ATTR_EDITOR_MAP); CValueEditDialog* CAttributeEditorPropertyPage::RetrieveEditor(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo) { CValueEditDialog* pNewDialog = NULL; if (pAttributeEditorInfo != NULL) { int iMultivalued = 0; CString szSyntax; ADSTYPE adsType = RetrieveADsTypeFromSyntax(pAttributeEditorInfo->lpszAttribute, &iMultivalued, szSyntax); for (size_t idx = 0; idx < g_attrEditMapCount; idx++) { // // REVIEW_JEFFJON : for now I am just looking at ADSTYPE and single/multivalued // if (g_attrEditorMap[idx].adsType == adsType && g_attrEditorMap[idx].bMultivalued == pAttributeEditorInfo->bMultivalued) { pNewDialog = g_attrEditorMap[idx].pfnCreateFunc(pAttributeEditorInfo->lpszClass, pAttributeEditorInfo->lpszAttribute, adsType, pAttributeEditorInfo->bMultivalued); break; } } } return pNewDialog; } ADSTYPE CAttributeEditorPropertyPage::RetrieveADsTypeFromSyntax(LPCWSTR lpszAttribute, BOOL* pbMulti, CString& szSyntax) { ADSTYPE adsType = ADSTYPE_INVALID; CADSIQueryObject schemaSearch; HRESULT hr = S_OK; CComPtr spDirSearch; // REVIEW_JEFFJON : this needs to be replaced with proper binding calls // REVIEW_JEFFJON : maybe this interface pointer should be retained for future use hr = m_pfnBind(m_szSchemaNamingContext, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (PVOID*)&spDirSearch, m_BindLPARAM); if (FAILED(hr)) { return ADSTYPE_INVALID; } // // Initialize search object with IDirectorySearch // hr = schemaSearch.Init(spDirSearch); if (FAILED(hr)) { return ADSTYPE_INVALID; } int cCols = 2; LPWSTR pszAttributes[] = {L"isSingleValued", L"attributeSyntax"}; ADS_SEARCH_COLUMN ColumnData; hr = schemaSearch.SetSearchPrefs(ADS_SCOPE_ONELEVEL); if (FAILED(hr)) { return ADSTYPE_INVALID; } CString csFilter; csFilter.Format(L"(&(objectClass=attributeSchema)(lDAPDisplayName=%s))", lpszAttribute); 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\tisSingleValued: %d\n"), ColumnData.pADsValues->Boolean); *pbMulti = !ColumnData.pADsValues->Boolean; schemaSearch.FreeColumn(&ColumnData); } hr = schemaSearch.GetColumn(pszAttributes[1], &ColumnData); if (SUCCEEDED(hr)) { TRACE(_T("\t\tattributeSyntax: %s\n"), ColumnData.pADsValues->CaseIgnoreString); adsType = GetADsTypeFromString(ColumnData.pADsValues->CaseIgnoreString, szSyntax); schemaSearch.FreeColumn(&ColumnData); } } } return adsType; }