windows-nt/Source/XPSP1/NT/admin/snapin/domain/proppage.cpp
2020-09-26 16:20:57 +08:00

446 lines
11 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: proppage.cpp
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "proppage.h"
#include "domobj.h"
#include "cdomain.h"
#include "helparr.h"
////////////////////////////////////////////////////////////////////////////////
// CUpnSuffixPropertyPage
// hook the property sheet callback to allow
// C++ object destruction
// static callback override function
UINT CALLBACK CUpnSuffixPropertyPage::PropSheetPageProc(
HWND hwnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
CUpnSuffixPropertyPage* pPage = (CUpnSuffixPropertyPage*)(ppsp->lParam);
ASSERT(pPage != NULL);
UINT nResult = (*(pPage->m_pfnOldPropCallback))(hwnd, uMsg, ppsp);
if (uMsg == PSPCB_RELEASE)
{
delete pPage;
}
return nResult;
}
BEGIN_MESSAGE_MAP(CUpnSuffixPropertyPage, CPropertyPage)
ON_BN_CLICKED(IDC_ADD_BTN, OnAddButton)
ON_BN_CLICKED(IDC_DELETE_BTN, OnDeleteButton)
ON_EN_CHANGE(IDC_EDIT, OnEditChange)
ON_WM_HELPINFO()
END_MESSAGE_MAP()
CUpnSuffixPropertyPage::CUpnSuffixPropertyPage() :
CPropertyPage(IDD_UPN_SUFFIX),
m_nPreviousDefaultButtonID(0)
{
m_pfnOldPropCallback = m_psp.pfnCallback;
m_psp.pfnCallback = PropSheetPageProc;
m_bDirty = FALSE;
m_pIADsPartitionsCont = NULL;
}
CUpnSuffixPropertyPage::~CUpnSuffixPropertyPage()
{
if (m_pIADsPartitionsCont != NULL)
{
m_pIADsPartitionsCont->Release();
m_pIADsPartitionsCont = NULL;
}
}
BOOL CUpnSuffixPropertyPage::OnInitDialog()
{
CPropertyPage::OnInitDialog();
VERIFY(m_listBox.SubclassDlgItem(IDC_LIST, this));
((CEdit*)GetDlgItem(IDC_EDIT))->SetLimitText(MAX_UPN_SUFFIX_LEN);
HRESULT hr = _GetPartitionsContainer();
if (SUCCEEDED(hr))
{
_Read();
GetDlgItem(IDC_ADD_BTN)->EnableWindow(FALSE);
}
else
{
// failed to contact DC, disable the whole UI
GetDlgItem(IDC_ADD_BTN)->EnableWindow(FALSE);
GetDlgItem(IDC_DELETE_BTN)->EnableWindow(FALSE);
GetDlgItem(IDC_LIST)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT)->EnableWindow(FALSE);
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ReportError(::GetParent(m_hWnd), IDS_CANT_GET_PARTITIONS_INFORMATION, hr);
}
LRESULT lDefID = ::SendMessage(GetParent()->GetSafeHwnd(), DM_GETDEFID, 0, 0);
if (lDefID != 0)
{
m_nPreviousDefaultButtonID = LOWORD(lDefID);
}
_SetDirty(FALSE);
return TRUE;
}
BOOL CUpnSuffixPropertyPage::OnApply()
{
if (!_IsDirty())
return TRUE;
HRESULT hr = _Write();
if (SUCCEEDED(hr))
{
_SetDirty(FALSE);
return TRUE;
}
ReportError(::GetParent(m_hWnd),IDS_ERROR_WRITE_UPN_SUFFIXES, hr);
return FALSE;
}
void CUpnSuffixPropertyPage::OnEditChange()
{
GetDlgItemText(IDC_EDIT, m_szEditText);
m_szEditText.TrimRight();
m_szEditText.TrimLeft();
BOOL bEnable = !m_szEditText.IsEmpty();
CWnd* pWndFocus = CWnd::GetFocus();
CWnd* pAddBtnWnd = GetDlgItem(IDC_ADD_BTN);
if (!bEnable && (pAddBtnWnd == pWndFocus) )
{
GetDlgItem(IDC_EDIT)->SetFocus();
}
GetDlgItem(IDC_ADD_BTN)->EnableWindow(bEnable);
if (bEnable)
{
//
// Set the add button as the default button
//
::SendMessage(GetParent()->GetSafeHwnd(), DM_SETDEFID, (WPARAM)IDC_ADD_BTN, 0);
//
// Force the Add button to redraw itself
//
::SendDlgItemMessage(GetSafeHwnd(),
IDC_ADD_BTN,
BM_SETSTYLE,
BS_DEFPUSHBUTTON,
MAKELPARAM(TRUE, 0));
//
// Force the previous default button to redraw itself
//
::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
m_nPreviousDefaultButtonID,
BM_SETSTYLE,
BS_PUSHBUTTON,
MAKELPARAM(TRUE, 0));
}
else
{
//
// Set the previous button as the default button
//
::SendMessage(GetParent()->GetSafeHwnd(), DM_SETDEFID, (WPARAM)m_nPreviousDefaultButtonID, 0);
//
// Force the previous default button to redraw itself
//
::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
m_nPreviousDefaultButtonID,
BM_SETSTYLE,
BS_DEFPUSHBUTTON,
MAKELPARAM(TRUE, 0));
//
// Force the Add button to redraw itself
//
::SendDlgItemMessage(GetParent()->GetSafeHwnd(),
IDC_ADD_BTN,
BM_SETSTYLE,
BS_PUSHBUTTON,
MAKELPARAM(TRUE, 0));
}
}
void CUpnSuffixPropertyPage::OnAddButton()
{
// cannot add duplicated items
int nCount = m_listBox.GetCount();
CString szItem;
for (int i=0; i<nCount; i++)
{
m_listBox.GetItem(i, szItem);
if (_wcsicmp((LPCWSTR)szItem, (LPCWSTR)m_szEditText) == 0)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
AfxMessageBox(IDS_ERROR_ADD_UPN_NO_DUPLICATE, MB_OK|MB_ICONINFORMATION);
return;
}
}
m_listBox.AddItem(m_szEditText);
m_listBox.UpdateHorizontalExtent();
SetDlgItemText(IDC_EDIT, NULL);
if (1 == m_listBox.GetCount())
{
// we did not have any item in the list
// need to set the selection on the first one
VERIFY(m_listBox.SetSelection(0));
// need to enable buttons
GetDlgItem(IDC_DELETE_BTN)->EnableWindow(TRUE);
}
_SetDirty(TRUE);
}
void CUpnSuffixPropertyPage::OnDeleteButton()
{
int nCount = m_listBox.GetCount();
int nSel = m_listBox.GetSelection();
ASSERT(nCount > 0);
ASSERT((nSel >= 0) && (nSel < nCount));
// ask the user for confirmation
AFX_MANAGE_STATE(AfxGetStaticModuleState());
if (IDNO == AfxMessageBox(IDS_WARNING_DELETE_UPN_SUFFIX, MB_YESNO|MB_ICONQUESTION))
return;
// save the value and put it back in the edit control
CString szText;
m_listBox.GetItem(nSel, szText);
GetDlgItem(IDC_EDIT)->SetWindowText(szText);
// delete the item in the list
VERIFY(m_listBox.DeleteItem(nSel));
m_listBox.UpdateHorizontalExtent();
// handle UI changes
if (nCount == 1)
{
// removed the last one, lost the selection
CWnd* pWndFocus = CWnd::GetFocus();
CWnd* pDelBtnWnd = GetDlgItem(IDC_DELETE_BTN);
if (pDelBtnWnd == pWndFocus)
{
GetDlgItem(IDC_EDIT)->SetFocus();
}
GetDlgItem(IDC_DELETE_BTN)->EnableWindow(FALSE);
}
else
{
// need to select again: is it the last one or not
int nNewSel = (nSel == nCount-1) ? nSel-1 : nSel;
VERIFY(m_listBox.SetSelection(nNewSel));
ASSERT(m_listBox.GetSelection() == nNewSel);
}
_SetDirty(TRUE);
}
BOOL CUpnSuffixPropertyPage::OnHelpInfo(HELPINFO* pHelpInfo)
{
DialogContextHelp((DWORD*)&g_aHelpIDs_IDD_UPN_SUFFIX, pHelpInfo);
return TRUE;
}
//////////////////////////////////////////////////////////
// CUpnSuffixPropertyPage internal implementation methods
LPWSTR g_lpszRootDSE = L"LDAP://RootDSE";
LPWSTR g_lpszConfigurationNamingContext = L"configurationNamingContext";
LPWSTR g_lpszPartitionsFormat = L"LDAP://CN=Partitions,%s";
LPWSTR g_lpszPartitionsFormatWithServer = L"LDAP://%s/CN=Partitions,%s";
LPWSTR g_lpszUpnSuffixes = L"uPNSuffixes";
HRESULT CUpnSuffixPropertyPage::_GetPartitionsContainer()
{
if (m_pIADsPartitionsCont != NULL)
{
m_pIADsPartitionsCont->Release();
m_pIADsPartitionsCont = NULL;
}
// get the root of the enterprise
IADs* pADs;
HRESULT hr = ::ADsGetObject(g_lpszRootDSE,
IID_IADs, (void **)&pADs);
if (!(SUCCEEDED(hr)))
{
return hr;
}
//
// Get the server name so we can bind with ADS_SERVER_BIND
//
CString szServerName;
hr = GetADSIServerName(szServerName, pADs);
if (FAILED(hr))
{
szServerName.Empty();
}
// get the configuration naming context container
VARIANT configVar;
::VariantInit(&configVar);
hr = pADs->Get(g_lpszConfigurationNamingContext,
&configVar);
if (SUCCEEDED(hr))
{
// get the partitions container
DWORD dwFlags = ADS_SECURE_AUTHENTICATION;
CString szPartitionsPath;
if (szServerName.IsEmpty())
{
szPartitionsPath.Format(g_lpszPartitionsFormat, configVar.bstrVal);
}
else
{
szPartitionsPath.Format(g_lpszPartitionsFormatWithServer, szServerName, configVar.bstrVal);
dwFlags |= ADS_SERVER_BIND;
}
IADsContainer* pIADsContainer;
hr = ::ADsOpenObject((LPWSTR)(LPCWSTR)szPartitionsPath,
NULL, // username
NULL, // password
dwFlags,
IID_IDirectoryObject,
(void **)&m_pIADsPartitionsCont);
if (hr == E_INVALIDARG &&
(dwFlags & ADS_SERVER_BIND))
{
//
// Trying again without the ADS_SERVER_BIND flag
//
dwFlags &= ~ADS_SERVER_BIND;
hr = ::ADsOpenObject((LPWSTR)(LPCWSTR)szPartitionsPath,
NULL, // username
NULL, // password
dwFlags,
IID_IDirectoryObject,
(void **)&m_pIADsPartitionsCont);
}
}
::VariantClear(&configVar);
pADs->Release();
return hr;
}
void CUpnSuffixPropertyPage::_Read()
{
ASSERT(m_pIADsPartitionsCont != NULL);
PADS_ATTR_INFO pAttrs = NULL;
LPWSTR lpszArr[1];
DWORD cAttrs;
BOOL bHaveItems = FALSE;
HRESULT hr = m_pIADsPartitionsCont->GetObjectAttributes(
&g_lpszUpnSuffixes, 1, &pAttrs, &cAttrs);
if (SUCCEEDED(hr) && (pAttrs != NULL) && (cAttrs == 1) )
{
ASSERT(pAttrs->dwADsType == ADSTYPE_CASE_IGNORE_STRING);
ASSERT(cAttrs == 1);
for (DWORD i=0; i<pAttrs->dwNumValues; i++)
{
m_listBox.AddItem(pAttrs->pADsValues[i].CaseIgnoreString);
//TRACE(_T("i=%d, %s\n"), i, pAttrs->pADsValues[i].CaseIgnoreString);
}
bHaveItems = pAttrs->dwNumValues > 0;
}
if (bHaveItems)
{
m_listBox.UpdateHorizontalExtent();
VERIFY(m_listBox.SetSelection(0));
}
GetDlgItem(IDC_DELETE_BTN)->EnableWindow(bHaveItems);
if (pAttrs != NULL)
{
::FreeADsMem(pAttrs);
}
}
HRESULT CUpnSuffixPropertyPage::_Write()
{
ASSERT(m_pIADsPartitionsCont != NULL);
DWORD cModified;
CString* pStringArr = NULL;
ADSVALUE* pValues = NULL;
// set the update struct
ADS_ATTR_INFO info;
info.pszAttrName = g_lpszUpnSuffixes;
info.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
info.dwControlCode = ADS_ATTR_CLEAR;
info.pADsValues = NULL;
info.dwNumValues = 0;
int nCount = m_listBox.GetCount();
if (nCount > 0)
{
info.dwControlCode = ADS_ATTR_UPDATE;
info.dwNumValues = (DWORD)nCount;
pStringArr = new CString[nCount];
ADSVALUE* pValues = new ADSVALUE[nCount];
info.pADsValues = pValues;
for (int i=0; i<nCount; i++)
{
m_listBox.GetItem(i,pStringArr[i]);
pValues[i].dwType = ADSTYPE_CASE_IGNORE_STRING;
pValues[i].CaseIgnoreString = (LPWSTR)(LPCWSTR)pStringArr[i];
}
}
HRESULT hr = m_pIADsPartitionsCont->SetObjectAttributes(
&info, 1, &cModified);
if (pStringArr != NULL)
delete[] pStringArr;
if (pValues != NULL)
delete[] pValues;
return hr;
}