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

5118 lines
136 KiB

#include "pch.h"
#include <SnapBase.h>
#include "resource.h"
#include "query.h"
#include "attrres.h"
#include "editui.h"
#include "common.h"
#include "attrqry.h"
#include "editorui.h"
////////////////////////////////////////////////////////////////////////////
// this is used to fill in the attributes for RootDSE
//
typedef struct tagRootDSEAttr
{
LPCWSTR lpszAttr;
LPCWSTR lpszSyntax;
BOOL bMulti;
} SYNTAXMAP;
extern SYNTAXMAP g_ldapRootDSESyntax[];
// Helper function to delete a set of ADSVALUEs
void DeleteADsValues(PADSVALUE pADsValue, DWORD valueCount)
{
if (!pADsValue)
{
return;
}
for (DWORD idx = 0; idx < valueCount; ++idx)
{
switch (pADsValue[idx].dwType)
{
case ADSTYPE_DN_STRING:
if (pADsValue[idx].DNString)
{
delete[] pADsValue[idx].DNString;
}
break;
case ADSTYPE_CASE_EXACT_STRING:
if (pADsValue[idx].CaseExactString)
{
delete[] pADsValue[idx].CaseExactString;
}
break;
case ADSTYPE_CASE_IGNORE_STRING:
if (pADsValue[idx].CaseIgnoreString)
{
delete[] pADsValue[idx].CaseIgnoreString;
}
break;
case ADSTYPE_PRINTABLE_STRING:
if (pADsValue[idx].PrintableString)
{
delete[] pADsValue[idx].PrintableString;
}
break;
case ADSTYPE_NUMERIC_STRING:
if (pADsValue[idx].NumericString)
{
delete[] pADsValue[idx].NumericString;
}
break;
case ADSTYPE_OCTET_STRING:
if (pADsValue[idx].OctetString.lpValue)
{
delete[] pADsValue[idx].OctetString.lpValue;
}
break;
case ADSTYPE_DN_WITH_STRING:
if (pADsValue[idx].pDNWithString)
{
if (pADsValue[idx].pDNWithString->pszStringValue)
{
delete[] pADsValue[idx].pDNWithString->pszStringValue;
}
if (pADsValue[idx].pDNWithString->pszDNString)
{
delete[] pADsValue[idx].pDNWithString->pszDNString;
}
delete pADsValue[idx].pDNWithString;
}
break;
case ADSTYPE_BOOLEAN:
case ADSTYPE_INTEGER:
case ADSTYPE_UTC_TIME:
case ADSTYPE_LARGE_INTEGER:
case ADSTYPE_CASEIGNORE_LIST:
case ADSTYPE_OCTET_LIST:
case ADSTYPE_PATH:
case ADSTYPE_POSTALADDRESS:
case ADSTYPE_TIMESTAMP:
case ADSTYPE_BACKLINK:
case ADSTYPE_TYPEDNAME:
case ADSTYPE_HOLD:
case ADSTYPE_NETADDRESS:
case ADSTYPE_REPLICAPOINTER:
case ADSTYPE_FAXNUMBER:
case ADSTYPE_EMAIL:
case ADSTYPE_DN_WITH_BINARY:
default:
// Do nothing, we didn't allocate any memory for these other types
break;
}
}
if (valueCount < 2)
{
delete pADsValue;
}
else
{
delete[] pADsValue;
}
}
///////////////////////////////////////////////////////////////////////////////////////
// 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_bReadOnly = pAttributeEditorInfo->bReadOnly;
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);
if (m_bReadOnly)
{
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
}
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 "<not set>"
//
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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)->CaseIgnoreString, m_szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)->CaseExactString, m_szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
case ADSTYPE_PRINTABLE_STRING:
(*ppADsValue)->PrintableString = new WCHAR[wcslen(m_szNewValue) + 1];
if ((*ppADsValue)->PrintableString != NULL)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)->PrintableString, m_szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
case ADSTYPE_DN_STRING:
(*ppADsValue)->DNString = new WCHAR[wcslen(m_szNewValue) + 1];
if ((*ppADsValue)->DNString != NULL)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)->DNString, m_szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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();
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
}
//
// NOTE: I have explicitly set the focus so return 0
//
return FALSE;
}
void CMultiStringEditor::OnOK()
{
if (!m_bReadOnly)
{
//
// Get the values out of the list box
//
m_szNewValueList.RemoveAll();
CListBox* pListBox = reinterpret_cast<CListBox*>(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()
{
if (!m_bReadOnly)
{
//
// 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()
{
if (!m_bReadOnly)
{
CListBox* pListBox = reinterpret_cast<CListBox*>(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()
{
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
}
else
{
//
// 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<CListBox*>(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;
}
// FUTURE-2002/03/05-artm Very similar functionality in CSingleStringEditor
// and CMultiStringEditor classes. Perhaps there is a way to combine the
// classes into a single class....or have one class inherit from the other.
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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)[idx].CaseIgnoreString, szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)[idx].CaseExactString, szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)[idx].PrintableString, szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)[idx].DNString, szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
case ADSTYPE_NUMERIC_STRING:
(*ppADsValue)[idx].NumericString = new WCHAR[wcslen(szNewValue) + 1];
if ((*ppADsValue)[idx].NumericString != NULL)
{
// NOTICE-2002/03/05-artm wcscpy() OK.
// Both args are allocated the same amount of memory.
wcscpy((*ppADsValue)[idx].NumericString, szNewValue);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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, TRUE);
}
//
// 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);
if (m_bReadOnly)
{
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
GetDlgItem(IDC_CLEAR_BUTTON)->EnableWindow(FALSE);
}
return CDialog::OnInitDialog();
}
void CSingleIntEditor::OnOK()
{
if (!m_bReadOnly)
{
BOOL bTranslated = FALSE;
m_dwNewValue = GetDlgItemInt(IDC_VALUE_EDIT, &bTranslated, TRUE);
if (!bTranslated)
{
// The translation will always fail if we are in the <not set> state
CString szNotSet;
VERIFY(szNotSet.LoadString(IDS_NOTSET));
CString value;
GetDlgItemText(IDC_VALUE_EDIT, value);
if (value.CompareNoCase(szNotSet) != 0)
{
// The user probably entered some non-numeric characters
ADSIEditMessageBox(IDS_ERR_MUST_BE_NUMERIC, MB_OK | MB_ICONEXCLAMATION);
}
else
{
CDialog::OnOK();
}
}
else
{
m_bValueSet = TRUE;
CDialog::OnOK();
}
}
else
{
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;
}
// FUTURE-2002/03/05-artm Identical OnClear() functions...
// The OnClear() method for all of the classes that extend CValueEditDialog
// is implemented identically (or so it seems on first glance). Perhaps
// the implementation should be placed in the base class to reduce
// code size, complexity, and maintenance.
void CSingleIntEditor::OnClear()
{
if (!m_bReadOnly)
{
//
// Change the text in the edit box to "<not set>"
//
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);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
}
else
{
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// CMultiIntEditor
CValueEditDialog* CreateMultiIntEditor(PCWSTR pszClass,
PCWSTR pszAttribute,
ADSTYPE adsType,
BOOL bMultivalued)
{
return new CMultiIntEditor;
}
BEGIN_MESSAGE_MAP(CMultiIntEditor, 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 CMultiIntEditor::OnInitDialog()
{
CDialog::OnInitDialog();
//
// Set the attribute name static
//
SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
//
// Disable IME support on the edit box
//
ImmAssociateContext(::GetDlgItem(GetSafeHwnd(), IDC_VALUE_EDIT), NULL);
//
// Fill the list box with the current values
//
POSITION pos = m_oldValueList.GetHeadPosition();
while (pos != NULL)
{
int value = m_oldValueList.GetNext(pos);
// Convert value to string
CString stringValue;
stringValue.Format(L"%d", value);
// Add string to list box
LRESULT index =
SendDlgItemMessage(
IDC_VALUE_LIST,
LB_ADDSTRING,
0,
(LPARAM)(LPCWSTR)stringValue);
// Attach the int value to the list box item
if (index != LB_ERR)
{
SendDlgItemMessage(
IDC_VALUE_LIST,
LB_SETITEMDATA,
(WPARAM)index,
(LPARAM)value);
}
}
//
// 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();
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
}
//
// NOTE: I have explicitly set the focus so return 0
//
return FALSE;
}
void CMultiIntEditor::OnOK()
{
if (!m_bReadOnly)
{
//
// Get the values out of the list box
//
m_newValueList.RemoveAll();
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
int iCount = pListBox->GetCount();
for (int idx = 0; idx < iCount; idx++)
{
int newValue;
newValue = static_cast<int>(pListBox->GetItemData(idx));
m_newValueList.AddTail(newValue);
}
}
}
CDialog::OnOK();
}
void CMultiIntEditor::OnAddButton()
{
if (!m_bReadOnly)
{
//
// Add the value to the list box and clear the edit field
//
int newValue = 0;
BOOL trans = FALSE;
newValue = GetDlgItemInt(IDC_VALUE_EDIT, &trans, TRUE);
CString szNewValue;
GetDlgItemText(IDC_VALUE_EDIT, szNewValue);
if (trans && !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)
{
// Add the string to the list box
LRESULT index =
SendDlgItemMessage(
IDC_VALUE_LIST,
LB_ADDSTRING,
0,
(LPARAM)(LPCWSTR)szNewValue);
if (index != LB_ERR)
{
// Set the item data to the integer value
SendDlgItemMessage(
IDC_VALUE_LIST,
LB_SETITEMDATA,
(WPARAM)index,
(LPARAM)newValue);
}
}
SetDlgItemText(IDC_VALUE_EDIT, L"");
}
else
{
//
// I was unable to convert the value to an integer so tell
// the user they can only enter digits from 0 to 9 and the
// - (negative) sign
//
ADSIEditMessageBox(IDS_ERR_MUST_BE_NUMERIC, MB_OK);
}
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
}
}
void CMultiIntEditor::OnRemoveButton()
{
if (!m_bReadOnly)
{
CListBox* pListBox = reinterpret_cast<CListBox*>(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 CMultiIntEditor::ManageButtonStates()
{
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
}
else
{
//
// Change the default button to the Add button
//
int value = 0;
BOOL trans = FALSE;
value = GetDlgItemInt(IDC_VALUE_EDIT, &trans, TRUE);
if (!trans)
{
//
// 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 CMultiIntEditor::OnListSelChange()
{
ManageButtonStates();
}
void CMultiIntEditor::OnEditChange()
{
ManageButtonStates();
}
void CMultiIntEditor::UpdateListboxHorizontalExtent()
{
int nHorzExtent = 0;
CListBox* pListBox = reinterpret_cast<CListBox*>(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 CMultiIntEditor::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_INTEGER:
m_oldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].Integer);
break;
default:
ASSERT(FALSE);
break;
}
}
}
}
return hr;
}
// FUTURE-2002/03/05-artm Very similar functionality in CSingleIntEditor
// and CMultiStringEditor classes. Perhaps there is a way to combine the
// classes into a single class....or have one class inherit from the other.
HRESULT CMultiIntEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
{
HRESULT hr = S_OK;
if (ppADsValue == NULL ||
pdwNumValues == NULL)
{
return E_OUTOFMEMORY;
}
int iCount = m_newValueList.GetCount();
if (iCount == 0)
{
*ppADsValue = NULL;
*pdwNumValues = 0;
}
else
{
*ppADsValue = new ADSVALUE[iCount];
if (*ppADsValue != NULL)
{
*pdwNumValues = iCount;
int idx = 0;
POSITION pos = m_newValueList.GetHeadPosition();
while (pos != NULL)
{
int newValue = m_newValueList.GetNext(pos);
(*ppADsValue)[idx].dwType = m_pOldADsValue->dwType;
switch (m_pOldADsValue->dwType)
{
case ADSTYPE_INTEGER:
(*ppADsValue)[idx].Integer = newValue;
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
idx++;
}
}
else
{
*ppADsValue = NULL;
*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);
if (m_bReadOnly)
{
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
GetDlgItem(IDC_CLEAR_BUTTON)->EnableWindow(FALSE);
}
return CDialog::OnInitDialog();
}
void CSingleLargeIntEditor::OnOK()
{
if (!m_bReadOnly)
{
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()
{
if (!m_bReadOnly)
{
//
// Change the text in the edit box to "<not set>"
//
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);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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);
}
}
if (m_bReadOnly)
{
GetDlgItem(IDC_TRUE_RADIO)->EnableWindow(FALSE);
GetDlgItem(IDC_FALSE_RADIO)->EnableWindow(FALSE);
}
return CDialog::OnInitDialog();
}
void CSingleBooleanEditor::OnOK()
{
if (!m_bReadOnly)
{
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);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
}
else
{
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// CMultiBooleanEditor
CValueEditDialog* CreateMultiBooleanEditor(PCWSTR pszClass,
PCWSTR pszAttribute,
ADSTYPE adsType,
BOOL bMultivalued)
{
return new CMultiBooleanEditor;
}
BEGIN_MESSAGE_MAP(CMultiBooleanEditor, 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_BN_CLICKED(IDC_TRUE_RADIO, OnRadioChange)
ON_BN_CLICKED(IDC_FALSE_RADIO, OnRadioChange)
END_MESSAGE_MAP()
BOOL CMultiBooleanEditor::OnInitDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog::OnInitDialog();
//
// Set the attribute name static
//
SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
//
// Fill the list box with the current values
//
CString szTrue;
szTrue.LoadString(IDS_TRUE);
CString szFalse;
szFalse.LoadString(IDS_FALSE);
POSITION pos = m_bOldValueList.GetHeadPosition();
while (pos != NULL)
{
BOOL bValue = m_bOldValueList.GetNext(pos);
SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)(bValue ? szTrue : szFalse));
}
//
// The remove button should be disabled until something is selected in the listbox
//
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
if (m_bReadOnly)
{
GetDlgItem(IDC_TRUE_RADIO)->EnableWindow(FALSE);
GetDlgItem(IDC_FALSE_RADIO)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
}
//
// NOTE: I have explicitly set the focus so return 0
//
return FALSE;
}
void CMultiBooleanEditor::OnOK()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
//
// Get the values out of the list box
//
m_bNewValueList.RemoveAll();
CString szTrue;
szTrue.LoadString(IDS_TRUE);
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
int iCount = pListBox->GetCount();
for (int idx = 0; idx < iCount; idx++)
{
CString szNewValue;
pListBox->GetText(idx, szNewValue);
if (szNewValue.CompareNoCase(szTrue) == 0)
{
m_bNewValueList.AddTail(TRUE);
}
else
{
m_bNewValueList.AddTail(FALSE);
}
}
}
}
CDialog::OnOK();
}
void CMultiBooleanEditor::OnAddButton()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
//
// Add the value to the list box and clear the edit field
//
CString szNewValue;
LRESULT result = SendDlgItemMessage(IDC_TRUE_RADIO, BM_GETCHECK, 0, 0);
if (result == BST_CHECKED)
{
szNewValue.LoadString(IDS_TRUE);
}
else
{
szNewValue.LoadString(IDS_FALSE);
}
SendDlgItemMessage(IDC_VALUE_LIST, LB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szNewValue);
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
}
}
void CMultiBooleanEditor::OnRemoveButton()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
int iCurSel = pListBox->GetCurSel();
if (iCurSel != LB_ERR)
{
//
// Put the old value into the radio buttons
//
CString szOldValue;
pListBox->GetText(iCurSel, szOldValue);
SetDlgItemText(IDC_VALUE_EDIT, szOldValue);
CString szTrue;
szTrue.LoadString(IDS_TRUE);
if (szOldValue.CompareNoCase(szTrue) == 0)
{
SendDlgItemMessage(IDC_TRUE_RADIO, BM_SETCHECK, BST_CHECKED, 0);
SendDlgItemMessage(IDC_FALSE_RADIO, BM_SETCHECK, BST_UNCHECKED, 0);
}
else
{
SendDlgItemMessage(IDC_TRUE_RADIO, BM_SETCHECK, BST_UNCHECKED, 0);
SendDlgItemMessage(IDC_FALSE_RADIO, BM_SETCHECK, BST_CHECKED, 0);
}
//
// Delete the item from the list box
//
pListBox->DeleteString(iCurSel);
}
}
//
// Manage Button States
//
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
}
}
void CMultiBooleanEditor::ManageButtonStates()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_bReadOnly)
{
GetDlgItem(IDC_TRUE_RADIO)->EnableWindow(FALSE);
GetDlgItem(IDC_FALSE_RADIO)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
}
else
{
//
// Change the default button to the Add button
//
LRESULT trueResult = SendDlgItemMessage(IDC_TRUE_RADIO, BM_GETCHECK, 0, 0);
LRESULT falseResult = SendDlgItemMessage(IDC_FALSE_RADIO, BM_GETCHECK, 0, 0);
if (trueResult != BST_CHECKED &&
falseResult != BST_CHECKED)
{
//
// 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 CMultiBooleanEditor::OnListSelChange()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ManageButtonStates();
}
void CMultiBooleanEditor::OnRadioChange()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ManageButtonStates();
}
void CMultiBooleanEditor::UpdateListboxHorizontalExtent()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
int nHorzExtent = 0;
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
CClientDC dc(pListBox);
int nItems = pListBox->GetCount();
for (int i=0; i < nItems; i++)
{
TEXTMETRIC tm = {0};
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 CMultiBooleanEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
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_BOOLEAN:
m_bOldValueList.AddTail(pAttributeEditorInfo->pADsValue[idx].Boolean);
break;
default:
ASSERT(FALSE);
break;
}
}
}
}
return hr;
}
HRESULT CMultiBooleanEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
if (ppADsValue == NULL ||
pdwNumValues == NULL)
{
return E_OUTOFMEMORY;
}
int iCount = m_bNewValueList.GetCount();
if (iCount == 0)
{
*ppADsValue = NULL;
*pdwNumValues = 0;
}
else
{
*ppADsValue = new ADSVALUE[iCount];
if (*ppADsValue != NULL)
{
*pdwNumValues = iCount;
int idx = 0;
POSITION pos = m_bNewValueList.GetHeadPosition();
while (pos != NULL)
{
BOOL bNewValue = m_bNewValueList.GetNext(pos);
(*ppADsValue)[idx].dwType = m_pOldADsValue->dwType;
switch (m_pOldADsValue->dwType)
{
case ADSTYPE_BOOLEAN:
(*ppADsValue)[idx].Boolean = bNewValue;
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
idx++;
}
}
else
{
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// CSingleTimeEditor
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);
}
if (m_bReadOnly)
{
GetDlgItem(IDC_DATE_PICKER)->EnableWindow(FALSE);
GetDlgItem(IDC_TIME_PICKER)->EnableWindow(FALSE);
}
return CDialog::OnInitDialog();
}
void CSingleTimeEditor::OnOK()
{
if (!m_bReadOnly)
{
SYSTEMTIME stDateResult = {0};
SYSTEMTIME stTimeResult = {0};
LRESULT lDateRes = SendDlgItemMessage(IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stDateResult);
LRESULT lTimeRes = SendDlgItemMessage(IDC_TIME_PICKER, DTM_GETSYSTEMTIME, 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:
// NOTICE-2002/03/05-artm memcpy() OK...
// arg1 always valid pointer; arg2 valid ptr if
// pAttributeEditorInfo->pADsValue not NULL
// (which is the case if we've gotten this far)
memcpy(&m_stOldValue, &(pAttributeEditorInfo->pADsValue->UTCTime), sizeof(SYSTEMTIME));
m_bValueSet = TRUE;
break;
default:
ASSERT(FALSE);
// NTRAID#NTBUG9-565760-2002/03/05-artm Release code should return error code,
// not S_OK.
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);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
}
else
{
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////
// CMultiTimeEditor
CValueEditDialog* CreateMultiTimeEditor(PCWSTR pszClass,
PCWSTR pszAttribute,
ADSTYPE adsType,
BOOL bMultivalued)
{
return new CMultiTimeEditor;
}
BEGIN_MESSAGE_MAP(CMultiTimeEditor, CValueEditDialog)
ON_BN_CLICKED(IDC_ATTR_ADD_BUTTON, OnAddButton)
ON_BN_CLICKED(IDC_ATTR_REMOVE_BUTTON, OnRemoveButton)
ON_LBN_SELCHANGE(IDC_VALUE_LIST, OnListSelChange)
END_MESSAGE_MAP()
BOOL CMultiTimeEditor::OnInitDialog()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDialog::OnInitDialog();
//
// Set the attribute name static
//
SetDlgItemText(IDC_ATTRIBUTE_STATIC, m_szAttribute);
//
// Fill the list box with the current values
//
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
POSITION pos = m_stOldValueList.GetHeadPosition();
while (pos != NULL)
{
SYSTEMTIME* pstValue = m_stOldValueList.GetNext(pos);
CString szValue = GetStringValueFromSystemTime(pstValue);
int index = pListBox->AddString(szValue);
if (LB_ERR != index)
{
pListBox->SetItemDataPtr(index, pstValue);
}
}
//
// The remove button should be disabled until something is selected in the listbox
//
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_DATE_PICKER)->EnableWindow(FALSE);
GetDlgItem(IDC_TIME_PICKER)->EnableWindow(FALSE);
}
//
// NOTE: I have explicitly set the focus so return 0
//
return FALSE;
}
void CMultiTimeEditor::OnOK()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
//
// Get the values out of the list box
//
m_stNewValueList.RemoveAll();
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
int iCount = pListBox->GetCount();
for (int idx = 0; idx < iCount; idx++)
{
SYSTEMTIME* pstValue = reinterpret_cast<SYSTEMTIME*>(pListBox->GetItemDataPtr(idx));
m_stNewValueList.AddTail(pstValue);
}
}
}
CDialog::OnOK();
}
void CMultiTimeEditor::OnAddButton()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
//
// Add the value to the list box and clear the edit field
//
SYSTEMTIME stDateResult = {0};
SYSTEMTIME stTimeResult = {0};
SYSTEMTIME* pstFullResult = new SYSTEMTIME;
if (!pstFullResult)
{
return;
}
ZeroMemory(pstFullResult, sizeof(SYSTEMTIME));
LRESULT lDateRes = SendDlgItemMessage(IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stDateResult);
LRESULT lTimeRes = SendDlgItemMessage(IDC_TIME_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stTimeResult);
if (lDateRes == GDT_VALID ||
lTimeRes == GDT_VALID)
{
memcpy(pstFullResult, &stDateResult, sizeof(SYSTEMTIME));
pstFullResult->wHour = stTimeResult.wHour;
pstFullResult->wMinute = stTimeResult.wMinute;
pstFullResult->wSecond = stTimeResult.wSecond;
pstFullResult->wMilliseconds = stTimeResult.wMilliseconds;
// Convert into a string that can be added to the list
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
CString szValue = GetStringValueFromSystemTime(pstFullResult);
int index = pListBox->AddString(szValue);
if (LB_ERR != index)
{
pListBox->SetItemDataPtr(index, pstFullResult);
}
}
}
ManageButtonStates();
//
// Update the width of the list box
//
UpdateListboxHorizontalExtent();
}
}
void CMultiTimeEditor::OnRemoveButton()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (!m_bReadOnly)
{
CListBox* pListBox = reinterpret_cast<CListBox*>(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 CMultiTimeEditor::ManageButtonStates()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_DATE_PICKER)->EnableWindow(FALSE);
GetDlgItem(IDC_TIME_PICKER)->EnableWindow(FALSE);
}
else
{
//
// Change the default button to the Add button
//
SYSTEMTIME stDateResult = {0};
SYSTEMTIME stTimeResult = {0};
LRESULT lDateRes = SendDlgItemMessage(IDC_DATE_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stDateResult);
LRESULT lTimeRes = SendDlgItemMessage(IDC_TIME_PICKER, DTM_GETSYSTEMTIME, 0, (LPARAM)&stTimeResult);
if (lDateRes == GDT_VALID &&
lTimeRes == GDT_VALID)
{
//
// 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 CMultiTimeEditor::OnListSelChange()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ManageButtonStates();
}
void CMultiTimeEditor::UpdateListboxHorizontalExtent()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
int nHorzExtent = 0;
CListBox* pListBox = reinterpret_cast<CListBox*>(GetDlgItem(IDC_VALUE_LIST));
if (pListBox != NULL)
{
CClientDC dc(pListBox);
int nItems = pListBox->GetCount();
for (int i=0; i < nItems; i++)
{
TEXTMETRIC tm = {0};
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 CMultiTimeEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
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_UTC_TIME:
m_stOldValueList.AddTail(&(pAttributeEditorInfo->pADsValue[idx].UTCTime));
break;
default:
ASSERT(FALSE);
break;
}
}
}
}
return hr;
}
HRESULT CMultiTimeEditor::GetNewValue(PADSVALUE* ppADsValue, DWORD* pdwNumValues)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = S_OK;
if (ppADsValue == NULL ||
pdwNumValues == NULL)
{
return E_OUTOFMEMORY;
}
int iCount = m_stNewValueList.GetCount();
if (iCount == 0)
{
*ppADsValue = NULL;
*pdwNumValues = 0;
}
else
{
*ppADsValue = new ADSVALUE[iCount];
if (*ppADsValue != NULL)
{
*pdwNumValues = iCount;
int idx = 0;
POSITION pos = m_stNewValueList.GetHeadPosition();
while (pos != NULL)
{
SYSTEMTIME* pstNewValue = m_stNewValueList.GetNext(pos);
(*ppADsValue)[idx].dwType = m_pOldADsValue->dwType;
switch (m_pOldADsValue->dwType)
{
case ADSTYPE_UTC_TIME:
memcpy(&((*ppADsValue)[idx].UTCTime), pstNewValue, sizeof(SYSTEMTIME));
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
idx++;
}
}
else
{
*ppADsValue = NULL;
*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);
if (m_bReadOnly)
{
SendDlgItemMessage(IDC_VALUE_EDIT, EM_SETREADONLY, TRUE, 0);
GetDlgItem(IDC_CLEAR_BUTTON)->EnableWindow(FALSE);
CString szView;
BOOL bResult = szView.LoadString(IDS_VIEW);
ASSERT(bResult);
SetDlgItemText(IDC_ATTR_EDIT_BUTTON, szView);
}
return CDialog::OnInitDialog();
}
void COctetStringEditor::OnOK()
{
if (!m_bReadOnly)
{
//
// 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);
// NTRAID#NTBUG9-566011-2002/03/05-artm CreateProcess() incorrectly used.
// Vulnerability exists b/c application name is NULL, meaning that
// the first whitespace delimited token in the command line is the
// executable name. This opens up a hole for trojan programs
// (e.g. C:\Program.exe).
//
// Since we have the process name separate from data path,
// fix is to pass szProcess as first argument and szDataPath
// as command line argument.
//
// I couldn't tell if the program name and data path were
// complete paths or not---but they should be if they are not!
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;
}
if (!m_bReadOnly)
{
//
// 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()
{
if (!m_bReadOnly)
{
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)
{
// NOTICE-2002/03/05-artm memcpy() OK.
// arg1 is same size as lpValue
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)
{
// NOTICE-2002/03/05-artm memcpy() OK.
// arg1 and arg2 both m_dwNewLength in size.
memcpy((*ppADsValue)->OctetString.lpValue, m_pNewValue, m_dwNewLength);
}
else
{
hr = E_OUTOFMEMORY;
}
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*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();
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_ATTR_ADD_BUTTON)->EnableWindow(FALSE);
CString szView;
BOOL bResult = szView.LoadString(IDS_VIEW);
ASSERT(bResult);
SetDlgItemText(IDC_EDIT_BUTTON, szView);
}
//
// NOTE: I have explicitly set the focus so return 0
//
return FALSE;
}
void CMultiOctetStringEditor::OnOK()
{
if (!m_bReadOnly)
{
//
// Get the values out of the list box
//
m_NewValueList.RemoveAll();
CListBox* pListBox = reinterpret_cast<CListBox*>(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<PADSVALUE>(lData));
}
}
}
CDialog::OnOK();
}
void CMultiOctetStringEditor::OnEditButton()
{
CThemeContextActivator activator;
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<PADSVALUE>(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.bReadOnly = m_bReadOnly;
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 &&
!m_bReadOnly)
{
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()
{
if (!m_bReadOnly)
{
CListBox* pListBox = reinterpret_cast<CListBox*>(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()
{
CThemeContextActivator activator;
if (!m_bReadOnly)
{
DS_ATTRIBUTE_EDITORINFO attrEditInfo;
ZeroMemory(&attrEditInfo, sizeof(DS_ATTRIBUTE_EDITORINFO));
attrEditInfo.pADsValue = new ADSVALUE;
if (attrEditInfo.pADsValue)
{
::ZeroMemory(attrEditInfo.pADsValue, sizeof(ADSVALUE));
}
else
{
// NOTICE-NTRAID#NTBUG9-566088-2002/03/05-artm If mem. allocation fails, short circuit function.
// If we cannot allocate enough memory inform the user and return w/out
// performing the rest of the operation.
ADSIEditErrorMessage(E_OUTOFMEMORY);
return;
}
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.bReadOnly = m_bReadOnly;
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()
{
if (m_bReadOnly)
{
GetDlgItem(IDC_ATTR_REMOVE_BUTTON)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT_BUTTON)->EnableWindow(FALSE);
}
else
{
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<CListBox*>(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)
{
// NOTICE-2002/03/05-artm memcpy() OK.
// arg1 and arg2 are both dwLength in size.
memcpy((*ppADsValue)[idx].OctetString.lpValue,
pADsValue->OctetString.lpValue,
pADsValue->OctetString.dwLength);
}
else
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = 0;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
break;
default:
ASSERT(FALSE);
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = 0;
*pdwNumValues = 0;
hr = E_FAIL;
break;
}
if (FAILED(hr))
{
return hr;
}
idx++;
}
}
else
{
*ppADsValue = NULL;
*pdwNumValues = 0;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////
// CDNWithStringEditor
CValueEditDialog* CreateDNWithStringEditor(PCWSTR pszClass,
PCWSTR pszAttribute,
ADSTYPE adsType,
BOOL bMultivalued)
{
return new CDNWithStringEditor;
}
BEGIN_MESSAGE_MAP(CDNWithStringEditor, CValueEditDialog)
ON_BN_CLICKED(IDC_CLEAR_BUTTON, OnClear)
END_MESSAGE_MAP()
BOOL CDNWithStringEditor::OnInitDialog()
{
CDialog::OnInitDialog();
return TRUE;
}
void CDNWithStringEditor::OnOK()
{
if (!m_bReadOnly)
{
GetDlgItemText(IDC_VALUE_EDIT, m_NewDNValue);
GetDlgItemText(IDC_STRING_VALUE_EDIT, m_NewStringValue);
}
CDialog::OnOK();
}
HRESULT CDNWithStringEditor::Initialize(LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo)
{
HRESULT hr = S_OK;
if (SUCCEEDED(CValueEditDialog::Initialize(pAttributeEditorInfo)))
{
if (pAttributeEditorInfo->dwNumValues > 0 &&
pAttributeEditorInfo->pADsValue != NULL)
{
ASSERT(pAttributeEditorInfo->dwNumValues == 1);
ASSERT(pAttributeEditorInfo->pADsValue->dwType == ADSTYPE_DN_WITH_STRING);
m_OldDNValue = pAttributeEditorInfo->pADsValue->pDNWithString->pszDNString;
m_OldStringValue = pAttributeEditorInfo->pADsValue->pDNWithString->pszStringValue;
}
}
return hr;
}
void CDNWithStringEditor::OnClear()
{
//
// Change the text in the edit box to "<not set>"
//
CString szNotSet;
VERIFY(szNotSet.LoadString(IDS_NOTSET));
SetDlgItemText(IDC_VALUE_EDIT, szNotSet);
SetDlgItemText(IDC_STRING_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 CDNWithStringEditor::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_NewDNValue == szNotSet ||
m_NewStringValue == szNotSet)
{
// User is clearing the attribute
*ppADsValue = NULL;
*pdwNumValues = 0;
return hr;
}
if (!m_NewDNValue.IsEmpty() ||
!m_NewStringValue.IsEmpty())
{
*ppADsValue = new ADSVALUE;
if (*ppADsValue)
{
*pdwNumValues = 1;
(*ppADsValue)->dwType = m_pOldADsValue->dwType;
ASSERT((*ppADsValue)->dwType == ADSTYPE_DN_WITH_STRING);
(*ppADsValue)->pDNWithString = new ADS_DN_WITH_STRING;
if ((*ppADsValue)->pDNWithString)
{
ZeroMemory((*ppADsValue)->pDNWithString, sizeof (ADS_DN_WITH_STRING));
int length = m_NewStringValue.GetLength();
(*ppADsValue)->pDNWithString->pszStringValue = new WCHAR[length + 1];
if ((*ppADsValue)->pDNWithString->pszStringValue)
{
ZeroMemory((*ppADsValue)->pDNWithString->pszStringValue, sizeof(WCHAR) * (length + 1));
wcsncpy((*ppADsValue)->pDNWithString->pszStringValue, m_NewStringValue, length);
length = m_NewDNValue.GetLength();
(*ppADsValue)->pDNWithString->pszDNString = new WCHAR[length + 1];
if ((*ppADsValue)->pDNWithString->pszDNString)
{
ZeroMemory((*ppADsValue)->pDNWithString->pszDNString, sizeof(WCHAR) * (length + 1));
wcsncpy((*ppADsValue)->pDNWithString->pszDNString, m_NewDNValue, length);
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
// Set an empty value
*ppADsValue = new ADSVALUE;
if (*ppADsValue)
{
*pdwNumValues = 1;
(*ppADsValue)->dwType = m_pOldADsValue->dwType;
ASSERT((*ppADsValue)->dwType == ADSTYPE_DN_WITH_STRING);
(*ppADsValue)->pDNWithString = new ADS_DN_WITH_STRING;
if ((*ppADsValue)->pDNWithString)
{
ZeroMemory((*ppADsValue)->pDNWithString, sizeof (ADS_DN_WITH_STRING));
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (FAILED(hr))
{
DeleteADsValues(*ppADsValue, *pdwNumValues);
*ppADsValue = 0;
*pdwNumValues = 0;
}
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_WM_CREATE()
ON_WM_DESTROY()
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;
}
int CAttributeEditorPropertyPage::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
m_pHolder->AddRef();
int res = CPropertyPage::OnCreate(lpCreateStruct);
ASSERT(res == 0);
ASSERT(m_hWnd != NULL);
ASSERT(::IsWindow(m_hWnd));
HWND hParent = ::GetParent(m_hWnd);
ASSERT(hParent);
m_pHolder->SetSheetWindow(hParent);
return res;
}
void CAttributeEditorPropertyPage::OnDestroy()
{
ASSERT(m_hWnd != NULL);
CPropertyPage::OnDestroy();
m_pHolder->Release();
}
HRESULT CAttributeEditorPropertyPage::GetSchemaNamingContext()
{
HRESULT hr = S_OK;
CComPtr<IADs> 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(CComBSTR(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());
CThemeContextActivator activator;
if (m_AttrList.HasDirty())
{
CComPtr<IDirectoryObject> 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<CAttributeEditorPropertyPage*>(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
{
// NOTICE-2002/03/05-artm _wcsicmp() okay since comparing 2 CStrings.
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<LPARAM>(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;
CListCtrl* pAttrListCtrl = (CListCtrl*)GetDlgItem(IDC_ATTRIBUTE_LIST);
ASSERT(pAttrListCtrl != NULL);
int nSelectedItem = pAttrListCtrl->GetNextItem(-1, LVIS_SELECTED);
if (nSelectedItem != -1 &&
!(m_dwBindFlags & DSATTR_EDITOR_ROOTDSE))
{
bEnableEdit = TRUE;
}
GetDlgItem(IDC_ATTR_EDIT_BUTTON)->EnableWindow(bEnableEdit);
}
void CAttributeEditorPropertyPage::OnNotifyEditAttribute(NMHDR* pNotifyStruct, LRESULT* result)
{
if (result == NULL ||
pNotifyStruct == NULL)
{
return;
}
// No editing values on RootDSE (for now)
if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
{
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);
if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
{
// We have add the value to the attribute holder from
// the RootDSE list
// CString szValue;
// szValue = m_RootDSEValueList.GetAt(m_RootDSEValueList.FindIndex(nSelectedItem));
}
EditAttribute(pSelectedAttr);
}
void CAttributeEditorPropertyPage::EditAttribute(CADSIAttribute* pSelectedAttr)
{
HRESULT hr = S_OK;
CThemeContextActivator activator;
//
// Retrieve all necessary info for initializing the appropriate editor
//
LPDS_ATTRIBUTE_EDITORINFO pAttributeEditorInfo = NULL;
BOOL bOwnValueMemory = FALSE;
hr = GetAttributeInfo(*pSelectedAttr, &pAttributeEditorInfo, &bOwnValueMemory);
if (hr == E_OUTOFMEMORY)
{
ADSIEditErrorMessage(hr);
return;
}
if (pAttributeEditorInfo == NULL || FAILED(hr))
{
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);
}
HRESULT CAttributeEditorPropertyPage::GetAttributeInfo(CADSIAttribute& attr,
LPDS_ATTRIBUTE_EDITORINFO* ppAttributeEditorInfo,
BOOL* pbOwnValueMemory)
{
HRESULT err = S_OK;
ASSERT(ppAttributeEditorInfo != NULL);
ASSERT(pbOwnValueMemory != NULL);
if (!ppAttributeEditorInfo || !pbOwnValueMemory)
{
return E_POINTER;
}
// Temporary variable to hold values that will be passed out of
// function. We use this instead of *ppAttributeEditorInfo to remove
// a level of indirection while we are collecting the information.
LPDS_ATTRIBUTE_EDITORINFO attributeEditorInfo;
// Set initial default (error) values.
attributeEditorInfo = NULL;
*pbOwnValueMemory = FALSE;
//
// Set read-only if necessary
//
bool readOnly = false;
if ( m_dwBindFlags & DSATTR_EDITOR_ROOTDSE
|| m_dwBindFlags & DSATTR_EDITOR_GC)
{
readOnly = true;
}
//
// Get the attribute to be edited
//
CString szAttribute = _T("");
attr.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);
DWORD dwNumValues = 0;
PADSVALUE pADsValue = attr.GetADsValues();
if (!pADsValue)
{
//
// Value for attribute was not set so we have to
// create an empty ADSVALUE to pass the type
//
pADsValue = new ADSVALUE;
if (pADsValue)
{
::ZeroMemory(pADsValue, sizeof(ADSVALUE));
pADsValue->dwType = adsType;
dwNumValues = 0;
*pbOwnValueMemory = TRUE;
}
else
{
return E_OUTOFMEMORY;
}
}
else
{
//
// Get the number of values in the attribute
//
dwNumValues = attr.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;
do // false loop
{
attributeEditorInfo = new DS_ATTRIBUTE_EDITORINFO;
if (!attributeEditorInfo)
{
err = E_OUTOFMEMORY;
break;
}
::ZeroMemory(attributeEditorInfo, sizeof(DS_ATTRIBUTE_EDITORINFO));
// NOTICE-NTRAID#NTBUG9-566199-2002/03/05-artm Check mem. alloc. succeeded.
attributeEditorInfo->lpszClass = new WCHAR[dwClassSize];
if (!attributeEditorInfo->lpszClass)
{
err = E_OUTOFMEMORY;
break;
}
wcscpy(attributeEditorInfo->lpszClass, m_szClass);
// NOTICE-NTRAID#NTBUG9-566199-2002/03/05-artm Check mem. alloc. succeeded.
attributeEditorInfo->lpszAttribute = new WCHAR[dwAttrSize];
if (!attributeEditorInfo->lpszAttribute)
{
err = E_OUTOFMEMORY;
break;
}
wcscpy(attributeEditorInfo->lpszAttribute, szAttribute);
attributeEditorInfo->adsType = adsType;
attributeEditorInfo->bMultivalued = bMultiValued;
attributeEditorInfo->bReadOnly = readOnly;
attributeEditorInfo->dwNumValues = dwNumValues;
attributeEditorInfo->pADsValue = pADsValue;
attributeEditorInfo->dwSize = sizeof(DS_ATTRIBUTE_EDITORINFO);
}
while (false); // end false loop
// If we were unable to get all the information, clean up memory.
if (FAILED(err))
{
// Only delete the value structure if we allocated it.
if (*pbOwnValueMemory)
{
delete pADsValue;
pADsValue = NULL;
*pbOwnValueMemory = FALSE;
}
if (attributeEditorInfo)
{
if (attributeEditorInfo->lpszClass)
{
delete [] attributeEditorInfo->lpszClass;
}
if (attributeEditorInfo->lpszAttribute)
{
delete [] attributeEditorInfo->lpszAttribute;
}
delete attributeEditorInfo;
attributeEditorInfo = NULL;
}
}
*ppAttributeEditorInfo = attributeEditorInfo;
return err;
}
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)
{
// Insert the syntax
VERIFY(-1 != pAttrListCtrl->SetItemText(iNewIndex, 1, pAttr->GetSyntax()));
// Insert the value
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<IADsPropertyList> 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<IADsPropertyEntry> 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;
}
// The function checks to see if the pszAttrName contains ";range="
// If it does that means the attribute contains a range of values.
// We will return the attribute name (without the range), and the start
// and end of the range.
bool CAttributeEditorPropertyPage::IsRangeOfValues(PCWSTR pszAttrName,
CString& szAttrBase,
DWORD& rangeStart,
DWORD& rangeEnd)
{
bool result = false;
CString szAttrName = pszAttrName;
int iFind = szAttrName.Find(L";range=");
if (iFind != -1)
{
// This is a range, get the start and end
result = true;
szAttrBase = szAttrName.Left(iFind);
int length = szAttrName.GetLength();
// The range start is the value between the = and -
iFind = szAttrName.ReverseFind(L'=');
if (iFind != -1)
{
CString szStart = szAttrName.Right(length - iFind - 1);
long start = _wtol(szStart);
rangeStart = static_cast<DWORD>(start);
}
// The range end is the last value after the -.
// This could be * so a return value of 0 for this
// means we have the entire range
iFind = szAttrName.ReverseFind(L'-');
if (iFind != -1)
{
CString szEnd = szAttrName.Right(length - iFind - 1);
long end = _wtol(szEnd);
rangeEnd = static_cast<DWORD>(end);
}
}
return result;
}
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( CComBSTR(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<IDirectoryObject> 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);
if (pos)
{
CADSIAttribute* pNewAttr = m_AttrList.GetAt(pos);
ASSERT(pNewAttr != NULL);
pNewAttr->SetValueSet(TRUE);
pNewAttr->SetAttrInfo(&(pAttrInfo[idx]));
}
else
{
// See if this is just a range of values for the attribute
CString szAttributeBase;
DWORD rangeStart = 0;
DWORD rangeEnd = static_cast<DWORD>(-1);
CADSIAttribute* pNewAttr = 0;
PADS_ATTR_INFO pCurrentInfo = &(pAttrInfo[idx]);
ASSERT(pCurrentInfo);
bool currentInMasterList = true;
// If we were sent only a portion of the values
// we have to loop through and get the rest
while (IsRangeOfValues(pCurrentInfo->pszAttrName,
szAttributeBase,
rangeStart,
rangeEnd))
{
if (!pNewAttr)
{
POSITION rangePos = m_AttrList.FindProperty(szAttributeBase);
if (rangePos)
{
pNewAttr = m_AttrList.GetAt(rangePos);
}
}
ASSERT(pNewAttr);
if (!pNewAttr)
{
break;
}
if (pNewAttr->IsValueSet())
{
hr = pNewAttr->AppendValues(pCurrentInfo->pADsValues,
pCurrentInfo->dwNumValues);
}
else
{
pNewAttr->SetValueSet(TRUE);
pNewAttr->SetAttrInfo(pCurrentInfo);
}
// If the current attribute info was not in the array
// of information from the initial request, release
// it here now that we are done with it.
if (!currentInMasterList)
{
::FreeADsMem(pCurrentInfo);
pCurrentInfo = NULL;
}
if (rangeEnd == 0)
{
break;
}
// Request next batch of values for the attribute.
CString szNextAttribute = szAttributeBase;
CString szNextRange;
szNextRange.Format(L";range=%ld-*", rangeEnd);
szNextAttribute += szNextRange;
DWORD dwNextReturned = 0;
PWSTR pszAttrs = (PWSTR)(PCWSTR)szNextAttribute;
hr = spDirObject->GetObjectAttributes(&pszAttrs,
1,
&pCurrentInfo,
&dwNextReturned);
if (FAILED(hr))
{
break;
}
if (dwNextReturned != 1 ||
!pCurrentInfo)
{
ASSERT(dwNextReturned == 1);
ASSERT(pCurrentInfo);
break;
}
// Since this pointer comes from an additional request to ADSI,
// we'll need to free it when we are done with it.
currentInMasterList = false;
rangeEnd = static_cast<DWORD>(-1);
}
}
}
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_INTEGER, TRUE, CreateMultiIntEditor },
{ NULL, NULL, ADSTYPE_LARGE_INTEGER, FALSE, CreateSingleLargeIntEditor },
{ NULL, NULL, ADSTYPE_BOOLEAN, FALSE, CreateSingleBooleanEditor },
{ NULL, NULL, ADSTYPE_BOOLEAN, TRUE, CreateMultiBooleanEditor },
{ NULL, NULL, ADSTYPE_UTC_TIME, FALSE, CreateSingleTimeEditor },
{ NULL, NULL, ADSTYPE_UTC_TIME, TRUE, CreateMultiTimeEditor },
{ NULL, NULL, ADSTYPE_TIMESTAMP, FALSE, CreateSingleTimeEditor },
{ NULL, NULL, ADSTYPE_TIMESTAMP, TRUE, CreateMultiTimeEditor },
{ NULL, NULL, ADSTYPE_OCTET_STRING, FALSE, CreateSingleOctetStringEditor },
{ NULL, NULL, ADSTYPE_OCTET_STRING, TRUE, CreateMultiOctetStringEditor },
{ NULL, NULL, ADSTYPE_DN_WITH_STRING, FALSE, CreateDNWithStringEditor },
};
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;
if (!pbMulti ||
!lpszAttribute)
{
ASSERT(pbMulti);
ASSERT(lpszAttribute);
return adsType;
}
if (m_dwBindFlags & DSATTR_EDITOR_ROOTDSE)
{
int idx=0, iCount = 0;
// NTRAID#NTBUG9-563093-2002/03/05-artm If lpszAttribute not null terminated,
// this will blow up.
iCount = wcslen(lpszAttribute);
while( g_ldapRootDSESyntax[idx].lpszAttr)
{
// NOTICE-2002/03/05-artm _wcsnicmp() OK.
// arg1 is global var that should be null terminated;
// arg2 is null terminated or we wouldn't have gotten this far.
if ( _wcsnicmp(g_ldapRootDSESyntax[idx].lpszAttr, lpszAttribute, iCount) == 0)
{
*pbMulti = g_ldapRootDSESyntax[idx].bMulti;
szSyntax = g_ldapRootDSESyntax[idx].lpszSyntax;
break;
}
idx++;
}
adsType = GetADsTypeFromString(szSyntax, szSyntax);
}
else
{
CADSIQueryObject schemaSearch;
HRESULT hr = S_OK;
CComPtr<IDirectorySearch> spDirSearch;
CString schemaBindPath(m_szSchemaNamingContext);
if (m_dwBindFlags & DSATTR_EDITOR_GC)
{
// GC by default does not have 'attributeSyntax' or 'isSingleValued'
// in the partial attribute set. To ensure we can get these attributes,
// we'll bind with LDAP instead of GC. This is ok b/c we are searching
// the schema, which is the same on the GC and all DC's.
// NTRAID#NTBUG9-762158-2003/01/15-artm
int numReplaced = schemaBindPath.Replace(L"GC://", L"LDAP://");
if (numReplaced != 1)
{
ASSERT(numReplaced == 1);
// fall back to connecting to the GC, since the path wasn't
// adapted the way we expected
schemaBindPath = m_szSchemaNamingContext;
}
}
// 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(schemaBindPath,
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)(!isDefunct=TRUE))", 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;
}