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