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.
 
 
 
 
 
 

2170 lines
60 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: delegwiz.cpp
//
//--------------------------------------------------------------------------
#include "pch.h"
#include "wizbase.h"
#include "util.h"
#include <initguid.h>
#include <cmnquery.h> // ICommonQuery
#include <dsquery.h>
#include <dsclient.h>
#include "resource.h"
#include "dsuiwiz.h"
#include "delegWiz.h"
#define GET_OU_WIZARD() ((CDelegWiz*)GetWizard())
/////////////////////////////////////////////////////////////////////////////
void InitBigBoldFont(HWND hWnd, HFONT& hFont)
{
ASSERT(::IsWindow(hWnd));
NONCLIENTMETRICS ncm;
memset(&ncm, 0, sizeof(ncm));
ncm.cbSize = sizeof(ncm);
::SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
LOGFONT boldLogFont = ncm.lfMessageFont;
boldLogFont.lfWeight = FW_BOLD;
// load big font definition from resources
WCHAR szFontName[LF_FACESIZE];
if (0 == ::LoadString(_Module.GetResourceInstance(), IDS_BIG_BOLD_FONT_NAME,
boldLogFont.lfFaceName, LF_FACESIZE))
{
// set to default of failed to load
wcscpy(boldLogFont.lfFaceName, L"Verdana Bold"); // LF_FACESIZE == 32
}
WCHAR szFontSize[128];
int nFontSize = 0;
if (0 != ::LoadString(_Module.GetResourceInstance(), IDS_BIG_BOLD_FONT_SIZE,
szFontSize, sizeof(szFontSize)/sizeof(WCHAR)))
{
nFontSize = _wtoi(szFontSize);
}
if (nFontSize == 0)
nFontSize = 12; // default
HDC hdc = ::GetDC(hWnd);
//Bug fix 447884
if( hdc )
{
boldLogFont.lfHeight =
0 - (::GetDeviceCaps(hdc, LOGPIXELSY) * nFontSize / 72);
hFont = ::CreateFontIndirect((const LOGFONT*)(&boldLogFont));
::ReleaseDC(hWnd, hdc);
}
}
void SetLargeFont(HWND hWndDialog, int nControlID)
{
ASSERT(::IsWindow(hWndDialog));
ASSERT(nControlID);
static HFONT boldLogFont = 0;
if (boldLogFont == 0)
{
InitBigBoldFont(hWndDialog, boldLogFont);
}
HWND hWndControl = ::GetDlgItem(hWndDialog, nControlID);
if (hWndControl)
{
::SendMessage(hWndControl, WM_SETFONT, (WPARAM)boldLogFont, MAKELPARAM(TRUE, 0));
}
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_StartPage
BOOL CDelegWiz_StartPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
pWizard->SetWizardButtonsFirst(TRUE);
return TRUE;
}
BOOL CALLBACK CDelegWiz_StartPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
SetLargeFont(m_hWnd, IDC_STATIC_WELCOME);
return TRUE;
}
#ifdef _SKIP_NAME_PAGE
LRESULT CDelegWiz_StartPage::OnWizardNext()
{
BOOL bSuccess = TRUE;
HRESULT hr = S_OK;
CDelegWiz* pWiz = GET_OU_WIZARD();
// if we do not have an object, we will browse from the next page
if (!pWiz->CanChangeName() && !m_bBindOK)
{
// make sure it exists and it is of the right type
{
// scope to restore cursor
CWaitCursor wait;
hr = pWiz->GetObjectInfo();
}
if (FAILED(hr))
{
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_OBJ_NAME, szFmt, 256);
WCHAR szMsg[512];
if(SUCCEEDED(StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(WCHAR),szFmt, pWiz->GetCanonicalName())))
{
pWiz->WizReportHRESULTError(szMsg, hr);
}
goto error;
}
{
// scope to restore cursor
CWaitCursor wait;
hr = pWiz->GetClassInfoFromSchema();
}
if (FAILED(hr))
{
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_OBJ_INFO, szFmt, 256);
WCHAR szMsg[512];
if(SUCCEEDED(StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(WCHAR),szFmt, pWiz->GetCanonicalName())))
{
pWiz->WizReportHRESULTError(szMsg, hr);
}
goto error;
}
// all fine, we do not need to do it anymore
m_bBindOK = TRUE;
}
OnWizardNextHelper();
return 0; // all fine, go to next page
error:
pWiz->SetWizardButtonsFirst(FALSE);
return -1; // do not advance
}
#endif
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_NamePage
BOOL CALLBACK CDelegWiz_NamePage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
BOOL bRes = TRUE;
CDelegWiz* pWiz = GET_OU_WIZARD();
m_hwndNameEdit = GetDlgItem(IDC_OBJ_NAME_EDIT);
if (!pWiz->CanChangeName()) // called on a given object
{
// hide static text that gives instructions
HWND hwndNameStatic = GetDlgItem(IDC_OBJ_NAME_STATIC);
::ShowWindow(hwndNameStatic, FALSE);
// change text to the editbox
HWND hwndNameEditStatic = GetDlgItem(IDC_OBJ_NAME_EDIT_STATIC);
CWString szLabel;
szLabel.LoadFromResource(IDS_OBJ_NAME_EDIT_STATIC);
::SendMessage(hwndNameEditStatic, WM_SETTEXT,0 , (LPARAM)(LPCWSTR)szLabel);
// remove the tabstop flag from the Edit Box
LONG style = ::GetWindowLong(m_hwndNameEdit, GWL_STYLE);
style &= ~WS_TABSTOP;
::SetWindowLong(m_hwndNameEdit, GWL_STYLE, style);
// make the Edit Box Read Only
::SendMessage(m_hwndNameEdit, EM_SETREADONLY, TRUE, 0L);
// disable and hide the Browse Button
HWND hWndBrowseButton = GetDlgItem(IDC_BROWSE_BUTTON);
::EnableWindow(hWndBrowseButton, FALSE);
::ShowWindow(hWndBrowseButton, FALSE);
bRes = FALSE;
}
return bRes;
}
LRESULT CDelegWiz_NamePage::OnBrowse(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
// load resources to customize dialog
TCHAR szCaption[256];
LoadStringHelper(IDS_DELEGWIZ_BROWSE_CONTAINER_CAPTION, szCaption, ARRAYSIZE(szCaption));
TCHAR szTitle[256];
LoadStringHelper(IDS_DELEGWIZ_BROWSE_CONTAINER_TITLE, szTitle, ARRAYSIZE(szTitle));
// set dialog struct
TCHAR szPath[MAX_PATH+1];
szPath[0] = NULL;
DSBROWSEINFO dsbi;
::ZeroMemory( &dsbi, sizeof(dsbi) );
dsbi.cbStruct = sizeof(DSBROWSEINFO);
dsbi.hwndOwner = m_hWnd;
dsbi.pszCaption = szCaption;
dsbi.pszTitle = szTitle;
dsbi.pszRoot = NULL; // ADS path to root (NULL == root of DS namespace)
dsbi.pszPath = szPath;
dsbi.cchPath = (sizeof(szPath) / sizeof(TCHAR));
dsbi.dwFlags = DSBI_ENTIREDIRECTORY;
// REVIEW_MARCOC: need to determine how to show/hide hidden folders
dsbi.dwFlags |= DSBI_INCLUDEHIDDEN; //m_fBrowseHiddenFolders ? DSBI_INCLUDEHIDDEN : 0;
dsbi.pfnCallback = NULL;
dsbi.lParam = 0;
// make the call to the dialog
int iRet = ::DsBrowseForContainer( &dsbi );
if ( IDOK == iRet )
{ // returns -1, 0, IDOK or IDCANCEL
// get path from BROWSEINFO struct, put in text edit field
//TRACE(_T("returned from DS Browse successfully with:\n %s\n"),
// dsbi.pszPath);
::SetWindowText(m_hwndNameEdit, szPath);
}
return 1;
}
BOOL CDelegWiz_NamePage::OnSetActive()
{
CDelegWiz* pWiz = GET_OU_WIZARD();
#ifdef _SKIP_NAME_PAGE
if (!pWiz->CanChangeName())
{
// just cause the page to fail, so that we skip it
return FALSE;
}
#endif
HRESULT hr = S_OK;
if (pWiz->m_bFwd && !pWiz->CanChangeName()) // called on a given object
{
// need to bind now to get the needed data
hr = pWiz->GetObjectInfo();
if (SUCCEEDED(hr))
{
// set the name of the object in the Edit Box
::SendMessage(m_hwndNameEdit, WM_SETTEXT, 0, (LPARAM)pWiz->GetCanonicalName());
}
else
{
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_OBJ_NAME, szFmt, 256);
WCHAR szMsg[512];
if(SUCCEEDED(StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(WCHAR),szFmt, pWiz->GetCanonicalName())))
{
pWiz->WizReportHRESULTError(szMsg, hr);
}
}
}
pWiz->SetWizardButtonsMiddle(SUCCEEDED(hr));
return TRUE;
}
LRESULT CDelegWiz_NamePage::OnWizardNext()
{
BOOL bSuccess = TRUE;
HRESULT hr = S_OK;
CDelegWiz* pWiz = GET_OU_WIZARD();
if (pWiz->CanChangeName())
{
// retrieve name from the edit control
int nEditTextLen = ::SendMessage(m_hwndNameEdit, WM_GETTEXTLENGTH,0,0) + 1;// count NULL
TCHAR* lpszName = (TCHAR*)alloca(sizeof(TCHAR)*(nEditTextLen));
::SendMessage(m_hwndNameEdit, WM_GETTEXT, (WPARAM)nEditTextLen, (LPARAM)lpszName);
// this will get the equivalent LDAP path
pWiz->SetName(lpszName);
// make sure it exists and it is of the right type
{
// scope to restore cursor
CWaitCursor wait;
hr = pWiz->GetObjectInfo();
}
if (FAILED(hr))
{
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_OBJ_NAME, szFmt, 256);
WCHAR szMsg[512];
if(SUCCEEDED(StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(WCHAR),szFmt, pWiz->GetCanonicalName())))
{
pWiz->WizReportHRESULTError(szMsg, hr);
}
goto error;
}
} // if can change name
{
// scope to restore cursor
CWaitCursor wait;
hr = pWiz->GetClassInfoFromSchema();
}
if (FAILED(hr))
{
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_OBJ_INFO, szFmt, 256);
WCHAR szMsg[512];
if(SUCCEEDED(StringCchPrintf(szMsg, sizeof(szMsg)/sizeof(WCHAR),szFmt, pWiz->GetCanonicalName())))
{
pWiz->WizReportHRESULTError(szMsg, hr);
}
goto error;
}
OnWizardNextHelper();
return 0; // all fine, go to next page
error:
pWiz->SetWizardButtonsMiddle(FALSE);
return -1; // do not advance
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_DelegationTemplateSelectionPage
BOOL CALLBACK CDelegWiz_DelegationTemplateSelectionPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
m_delegationTemplatesListView.Initialize(IDC_DELEGATE_TEMPLATE_LIST, m_hWnd);
// set the correct value for radiobuttons text
m_hwndDelegateTemplateRadio = GetDlgItem(IDC_DELEGATE_TEMPLATE_RADIO);
_ASSERTE(m_hwndDelegateTemplateRadio != NULL);
m_hwndDelegateCustomRadio = GetDlgItem(IDC_DELEGATE_CUSTOM_RADIO);
_ASSERTE(m_hwndDelegateCustomRadio != NULL);
// set default setting
::SendMessage(m_hwndDelegateTemplateRadio, BM_SETCHECK, BST_CHECKED, 0);
return TRUE;
}
LRESULT CDelegWiz_DelegationTemplateSelectionPage::OnDelegateTypeRadioChange(WORD wNotifyCode, WORD wID,
HWND hWndCtl, BOOL& bHandled)
{
SyncControlsHelper(IDC_DELEGATE_CUSTOM_RADIO == wID);
return 1;
}
LRESULT CDelegWiz_DelegationTemplateSelectionPage::OnListViewItemChanged(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
if (CCheckListViewHelper::CheckChanged(pNMListView))
{
int nSelCount = m_delegationTemplatesListView.GetCheckCount();
GET_OU_WIZARD()->SetWizardButtonsMiddle(nSelCount > 0);
}
return 1;
}
BOOL CDelegWiz_DelegationTemplateSelectionPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
BOOL bRetVal = TRUE;
BOOL bDelegateCustom =
(BST_CHECKED == ::SendMessage(m_hwndDelegateCustomRadio, BM_GETCHECK,0,0));
if (pWizard->m_bFwd)
{
// need to fill in with data
BOOL bHaveTemplates =
pWizard->m_templateAccessPermissionsHolderManager.FillTemplatesListView(
&m_delegationTemplatesListView, pWizard->GetClass())> 0;
if (!bDelegateCustom && !bHaveTemplates)
{
::SendMessage(m_hwndDelegateCustomRadio, BM_SETCHECK,BST_CHECKED,0);
::SendMessage(m_hwndDelegateTemplateRadio, BM_SETCHECK,BST_UNCHECKED,0);
bDelegateCustom = TRUE;
}
SyncControlsHelper(bDelegateCustom);
}
else
{
// data already in, just coming back from next page
if (bDelegateCustom)
{
pWizard->SetWizardButtonsMiddle(TRUE);
}
else
{
int nSelCount = m_delegationTemplatesListView.GetCheckCount();
pWizard->SetWizardButtonsMiddle(nSelCount > 0);
}
}
return TRUE;
}
LRESULT CDelegWiz_DelegationTemplateSelectionPage::OnWizardNext()
{
HRESULT hr = S_OK;
int nSelCount = -1;
int* nSelArray = NULL;
BOOL bCanAdvance = FALSE;
CDelegWiz* pWiz = GET_OU_WIZARD();
// check if the delegation is on all objects
BOOL bCustom = TRUE;
UINT nNextPageID = 0;
if (BST_CHECKED == ::SendMessage(m_hwndDelegateCustomRadio, BM_GETCHECK,0,0))
{
nSelCount = 0;
nSelArray = NULL;
bCanAdvance = TRUE;
}
else
{
ASSERT(BST_CHECKED == ::SendMessage(m_hwndDelegateTemplateRadio, BM_GETCHECK,0,0));
bCustom = FALSE;
nSelCount = 0;
int nCount = m_delegationTemplatesListView.GetItemCount();
for (int k=0; k<nCount; k++)
{
CTemplate* pTempl = (CTemplate*)m_delegationTemplatesListView.GetItemData(k);
pTempl->m_bSelected = m_delegationTemplatesListView.IsItemChecked(k);
if (pTempl->m_bSelected)
nSelCount++;
}
bCanAdvance = (nSelCount > 0);
}
if (!bCanAdvance)
goto error;
// set branching info
if (bCustom)
{
// just move to the next custom page
nNextPageID = CDelegWiz_ObjectTypeSelectionPage::IDD;
pWiz->m_objectTypeSelectionPage.m_nPrevPageID = IDD;
pWiz->m_finishPage.m_nPrevPageID = CDelegWiz_DelegatedRightsPage::IDD;
pWiz->m_finishPage.SetCustom();
}
else
{
// need to gather info for the selected templates
{
// scope to restore cursor
CWaitCursor wait;
if (!pWiz->InitPermissionHoldersFromSelectedTemplates())
{
// REVIEW_MARCOC: need to give a message to the user
pWiz->WizMessageBox(IDS_DELEGWIZ_ERR_TEMPL_APPLY);
goto error;
}
}
// got info, can proceed
nNextPageID = CDelegWiz_FinishPage::IDD;
pWiz->m_finishPage.m_nPrevPageID = IDD;
pWiz->m_finishPage.SetTemplate();
}
OnWizardNextHelper();
return nNextPageID; // advance next
error:
// do not advance, error
pWiz->SetWizardButtonsMiddle(FALSE);
return -1;
}
void CDelegWiz_DelegationTemplateSelectionPage::SyncControlsHelper(BOOL bDelegateCustom)
{
CDelegWiz* pWiz = GET_OU_WIZARD();
// uncheck all items in the listview if delegating custom
if (bDelegateCustom)
{
m_delegationTemplatesListView.SetCheckAll(FALSE);
pWiz->m_templateAccessPermissionsHolderManager.DeselectAll(); // in the list templates
}
// disable listbox if "delegate custom"
m_delegationTemplatesListView.EnableWindow(!bDelegateCustom);
// enable "Wizard Next"
BOOL bEnableNext = bDelegateCustom ?
TRUE : (m_delegationTemplatesListView.GetCheckCount() > 0);
pWiz->SetWizardButtonsMiddle(bEnableNext);
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_ObjectTypeSelectionPage
BOOL CALLBACK CDelegWiz_ObjectTypeSelectionPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
m_objectTypeListView.Initialize(IDC_OBJ_TYPE_LIST, m_hWnd);
// set the correct value for radiobuttons text
m_hwndDelegateAllRadio = GetDlgItem(IDC_DELEGATE_ALL_RADIO);
ASSERT(m_hwndDelegateAllRadio != NULL);
m_hwndDelegateFollowingRadio = GetDlgItem(IDC_DELEGATE_FOLLOWING_RADIO);
ASSERT(m_hwndDelegateFollowingRadio != NULL);
m_hwndDelegateCreateChild = GetDlgItem(IDC_DELEGATE_CREATE_CHILD);
ASSERT(m_hwndDelegateCreateChild != NULL);
m_hwndDelegateDeleteChild = GetDlgItem(IDC_DELEGATE_DELETE_CHILD);
ASSERT(m_hwndDelegateDeleteChild != NULL);
// set default setting
::SendMessage(m_hwndDelegateAllRadio, BM_SETCHECK, BST_CHECKED, 0);
::SendMessage(m_hwndDelegateCreateChild, BM_SETCHECK, BST_UNCHECKED, 0);
::SendMessage(m_hwndDelegateCreateChild, BM_SETCHECK, BST_UNCHECKED, 0);
return TRUE;
}
LRESULT CDelegWiz_ObjectTypeSelectionPage::OnObjectRadioChange(WORD wNotifyCode, WORD wID,
HWND hWndCtl, BOOL& bHandled)
{
SyncControlsHelper(IDC_DELEGATE_ALL_RADIO == wID);
return 1;
}
LRESULT CDelegWiz_ObjectTypeSelectionPage::OnCreateDelCheckBoxChanage(WORD wNotifyCode, WORD wID,
HWND hWndCtl, BOOL& bHandled)
{
CDelegWiz* pWiz = GET_OU_WIZARD();
if( IDC_DELEGATE_CREATE_CHILD == wID )
{
if( ::SendMessage( hWndCtl, BM_GETCHECK,0,0 ) )
pWiz->m_fCreateDelChild |= ACTRL_DS_CREATE_CHILD;
else
pWiz->m_fCreateDelChild &= ~ACTRL_DS_CREATE_CHILD;
}
if( IDC_DELEGATE_DELETE_CHILD == wID )
{
if( ::SendMessage( hWndCtl, BM_GETCHECK,0,0 ) )
pWiz->m_fCreateDelChild |= ACTRL_DS_DELETE_CHILD;
else
pWiz->m_fCreateDelChild &= ~ACTRL_DS_DELETE_CHILD;
}
return 1;
}
LRESULT CDelegWiz_ObjectTypeSelectionPage::OnListViewItemChanged(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
if (CCheckListViewHelper::CheckChanged(pNMListView))
{
int nSelCount = m_objectTypeListView.GetCheckCount();
GET_OU_WIZARD()->SetWizardButtonsMiddle(nSelCount > 0);
}
return 1;
}
void CDelegWiz_ObjectTypeSelectionPage::SyncControlsHelper(BOOL bDelegateAll)
{
CDelegWiz* pWiz = GET_OU_WIZARD();
if (bDelegateAll)
{
// uncheck all items in the listview if delegating all
m_objectTypeListView.SetCheckAll(FALSE); // in the listview
pWiz->DeselectSchemaClassesSelectionCustom(); // in the list of schama classes
//Uncheck delete/create check boxes
::SendMessage(m_hwndDelegateCreateChild,BM_SETCHECK,0,0);
::SendMessage(m_hwndDelegateDeleteChild,BM_SETCHECK,0,0);
pWiz->m_fCreateDelChild = 0;
}
// enable "Wizard Next" of "delegate all"
pWiz->SetWizardButtonsMiddle(bDelegateAll);
// disable listbox if "delegate all"
m_objectTypeListView.EnableWindow(!bDelegateAll);
::EnableWindow( m_hwndDelegateCreateChild, !bDelegateAll);
::EnableWindow( m_hwndDelegateDeleteChild, !bDelegateAll);
}
void CDelegWiz_ObjectTypeSelectionPage::SetRadioControlText(HWND hwndCtrl, LPCWSTR lpszFmtText, LPCWSTR lpszText)
{
// format new text
int nTextLen = lstrlen(lpszText)+1; // count NULL
int nFmtTextLen = lstrlen(lpszFmtText)+1; // count NULL
WCHAR* lpszNewText = (WCHAR*)alloca(sizeof(WCHAR)*(nFmtTextLen+nTextLen));
wsprintf(lpszNewText, lpszFmtText, lpszText);
// set back
::SendMessage(hwndCtrl, WM_SETTEXT, 0, (WPARAM)lpszNewText);
}
BOOL CDelegWiz_ObjectTypeSelectionPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
BOOL bRetVal = TRUE;
BOOL bDelegateAll =
(BST_CHECKED == ::SendMessage(m_hwndDelegateAllRadio, BM_GETCHECK,0,0));
if (pWizard->m_bFwd)
{
// need to fill in with data
BOOL bFilter = TRUE;
BOOL bHaveChildClasses = pWizard->FillCustomSchemaClassesListView(&m_objectTypeListView, bFilter) > 0;
if (!bHaveChildClasses)
{
::SendMessage(m_hwndDelegateAllRadio, BM_SETCHECK,BST_CHECKED,0);
::SendMessage(m_hwndDelegateFollowingRadio, BM_SETCHECK,BST_UNCHECKED,0);
::EnableWindow(m_hwndDelegateFollowingRadio, FALSE);
bDelegateAll = TRUE;
}
SyncControlsHelper(bDelegateAll);
}
else
{
// data already in, just coming back from next page
if (bDelegateAll)
{
pWizard->SetWizardButtonsMiddle(TRUE);
}
else
{
int nSelCount = m_objectTypeListView.GetCheckCount();
pWizard->SetWizardButtonsMiddle(nSelCount > 0);
}
}
return TRUE;
}
LRESULT CDelegWiz_ObjectTypeSelectionPage::OnWizardNext()
{
HRESULT hr = S_OK;
BOOL bCanAdvance = FALSE;
CDelegWiz* pWiz = GET_OU_WIZARD();
pWiz->m_bAuxClass = false;
// check if the delegation is on all objects
if (BST_CHECKED == ::SendMessage(m_hwndDelegateAllRadio, BM_GETCHECK,0,0))
{
bCanAdvance = TRUE;
}
else
{
ASSERT(BST_CHECKED == ::SendMessage(m_hwndDelegateFollowingRadio, BM_GETCHECK,0,0));
int nSelCount = 0;
int nCount = m_objectTypeListView.GetItemCount();
CSchemaClassInfo* pAuxClassInfo = NULL;
for (int k=0; k<nCount; k++)
{
CSchemaClassInfo* pChildClassInfo = (CSchemaClassInfo*)m_objectTypeListView.GetItemData(k);
pChildClassInfo->m_bSelected = m_objectTypeListView.IsItemChecked(k);
if (pChildClassInfo->m_bSelected)
{
nSelCount++;
if(pChildClassInfo->IsAux())
{
pWiz->m_bAuxClass = true;
if(!pAuxClassInfo)
pAuxClassInfo = pChildClassInfo;
}
}
}
bCanAdvance = (nSelCount > 0);
if(nSelCount > 1 && pWiz->m_bAuxClass)
{
LPWSTR pszMessage = NULL;
FormatStringID(&pszMessage, IDS_DELEGWIZ_ONE_AUX_CLASS,pAuxClassInfo->GetDisplayName());
pWiz->WizMessageBox(pszMessage);
LocalFree(pszMessage);
bCanAdvance = FALSE;
}
}
if (!bCanAdvance)
goto error;
{
// scope to restore cursor
CWaitCursor wait;
bCanAdvance = pWiz->SetSchemaClassesSelectionCustom();
}
if (!bCanAdvance)
goto error;
// for the selected child class(es), get the access permissions
// to display in the next page
{
// scope to restore cursor
CWaitCursor wait;
bCanAdvance = pWiz->GetCustomAccessPermissions();
}
if (!bCanAdvance)
goto error;
OnWizardNextHelper();
return 0; // advance next
error:
// do not advance, error
pWiz->SetWizardButtonsMiddle(FALSE);
return -1;
}
///////////////////////////////////////////////////////////////////////
// CPrincipalListViewHelper
BOOL CPrincipalListViewHelper::Initialize(UINT nID, HWND hParent)
{
m_hWnd = GetDlgItem(hParent, nID);
if (m_hWnd == NULL)
return FALSE;
if (!m_imageList.Create(m_hWnd))
return FALSE;
SetImageList();
RECT r;
::GetClientRect(m_hWnd, &r);
int scroll = ::GetSystemMetrics(SM_CXVSCROLL);
LV_COLUMN col;
ZeroMemory(&col, sizeof(LV_COLUMN));
col.mask = LVCF_WIDTH;
col.cx = (r.right - r.left) - scroll;
m_defaultColWidth = col.cx;
return (0 == ListView_InsertColumn(m_hWnd,0,&col));
}
int CPrincipalListViewHelper::InsertItem(int iItem, CPrincipal* pPrincipal)
{
// need to get the icon index
int nIconIndex = m_imageList.GetIconIndex(pPrincipal->GetClass());
if (nIconIndex == -1)
{
nIconIndex = m_imageList.AddIcon(pPrincipal->GetClass(),
pPrincipal->GetClassIcon());
if (nIconIndex != -1)
SetImageList();
}
LV_ITEM item;
ZeroMemory(&item, sizeof(LV_ITEM));
item.mask = LVIF_TEXT | LVIF_PARAM;
item.pszText = (LPWSTR)(LPCWSTR)(pPrincipal->GetDisplayName());
item.lParam = (LPARAM)pPrincipal;
item.iItem = iItem;
if (nIconIndex != -1)
{
item.iImage = nIconIndex;
item.mask |= LVIF_IMAGE;
}
int iRes = ListView_InsertItem(m_hWnd, &item);
return iRes;
}
BOOL CPrincipalListViewHelper::SelectItem(int iItem)
{
LV_ITEM item;
ZeroMemory(&item, sizeof(LV_ITEM));
item.mask = LVIF_STATE;
item.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
item.state = LVIS_FOCUSED | LVIS_SELECTED;
return ListView_SetItem(m_hWnd, &item);
}
CPrincipal* CPrincipalListViewHelper::GetItemData(int iItem)
{
LV_ITEM item;
ZeroMemory(&item, sizeof(LV_ITEM));
item.mask = LVIF_PARAM;
item.iItem = iItem;
ListView_GetItem(m_hWnd, &item);
return (CPrincipal*)item.lParam;
}
void CPrincipalListViewHelper::DeleteSelectedItems(CGrowableArr<CPrincipal>* pDeletedArr)
{
int nItemIndex;
while ( (nItemIndex = ListView_GetNextItem(m_hWnd, -1, LVNI_SELECTED)) != -1)
{
CPrincipal* pPrincipal = GetItemData(nItemIndex);
if (ListView_DeleteItem(m_hWnd, nItemIndex))
{
pDeletedArr->Add(pPrincipal);
}
} // if
// restore selection to first item
if (GetItemCount() > 0)
SelectItem(0);
}
void CPrincipalListViewHelper::UpdateWidth(int cxNew)
{
int cx = GetWidth(); // get current col width from the control
if (cxNew < m_defaultColWidth)
cxNew = m_defaultColWidth;
if (cxNew != cx)
SetWidth(cx);
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_PrincipalSelectionPage
BOOL CALLBACK CDelegWiz_PrincipalSelectionPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
// initialize the list of principals
m_principalListView.Initialize(IDC_SELECTED_PRINCIPALS_LIST, m_hWnd);
// cache handle for the remove button
m_hwndRemoveButton = GetDlgItem(IDC_REMOVE_BUTTON);
return TRUE;
}
LRESULT CDelegWiz_PrincipalSelectionPage::OnAdd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
GET_OU_WIZARD()->AddPrincipals(&m_principalListView);
SyncButtons();
return 1;
}
LRESULT CDelegWiz_PrincipalSelectionPage::OnRemove(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
GET_OU_WIZARD()->DeletePrincipals(&m_principalListView);
SyncButtons();
return 1;
}
LRESULT CDelegWiz_PrincipalSelectionPage::OnListViewSelChange(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
SyncButtons();
return 1;
}
BOOL CDelegWiz_PrincipalSelectionPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
SyncButtons();
return TRUE;
}
LRESULT CDelegWiz_PrincipalSelectionPage::OnWizardNext()
{
CDelegWiz* pWiz = GET_OU_WIZARD();
// set branching info
UINT nNextPageID = 0;
if (pWiz->m_templateAccessPermissionsHolderManager.HasTemplates(pWiz->GetClass()))
{
nNextPageID = CDelegWiz_DelegationTemplateSelectionPage::IDD;
}
else
{
nNextPageID = CDelegWiz_ObjectTypeSelectionPage::IDD;
pWiz->m_objectTypeSelectionPage.m_nPrevPageID = IDD;
}
OnWizardNextHelper();
return nNextPageID;
}
void CDelegWiz_PrincipalSelectionPage::SyncButtons()
{
BOOL bEnable = FALSE;
int nItemCount = m_principalListView.GetItemCount();
if (nItemCount > 0)
{
bEnable = m_principalListView.GetSelCount() > 0;
}
::EnableWindow(m_hwndRemoveButton, bEnable);
CDelegWiz* pWiz = GET_OU_WIZARD();
pWiz->SetWizardButtonsMiddle(nItemCount > 0);
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_DelegatedRightsPage
BOOL CALLBACK CDelegWiz_DelegatedRightsPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
// initialize check list view
m_delegatedRigthsListView.Initialize(IDC_DELEG_RIGHTS_LIST, m_hWnd);
// get HWND's of controls
m_hwndGeneralRigthsCheck = GetDlgItem(IDC_SHOW_GENERAL_CHECK);
_ASSERTE(m_hwndGeneralRigthsCheck);
m_hwndPropertyRightsCheck = GetDlgItem(IDC_SHOW_PROPERTY_CHECK);
_ASSERTE(m_hwndPropertyRightsCheck);
m_hwndSubobjectRightsCheck = GetDlgItem(IDC_SHOW_SUBOBJ_CHECK);
_ASSERTE(m_hwndSubobjectRightsCheck);
return TRUE;
}
BOOL CDelegWiz_DelegatedRightsPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
if (pWizard->m_bFwd)
{
if(pWizard->m_bAuxClass)
SetFilterOptions(FILTER_EXP_GEN_DISABLED|FILTER_EXP_PROP);
else
SetFilterOptions(FILTER_EXP_GEN);
ResetCheckList(); // will set wizard button
}
else
{
//coming back from next page, just set the wizard button
pWizard->SetWizardButtonsMiddle(pWizard->HasPermissionSelectedCustom());
}
return TRUE;
}
LRESULT CDelegWiz_DelegatedRightsPage::OnWizardNext()
{
CDelegWiz* pWiz = GET_OU_WIZARD();
// must at least one check > 0
if (pWiz->HasPermissionSelectedCustom())
{
OnWizardNextHelper();
return 0;
}
pWiz->SetWizardButtonsMiddle(FALSE);
return -1;
}
LRESULT CDelegWiz_DelegatedRightsPage::OnFilterChange(WORD wNotifyCode, WORD wID,
HWND hWndCtl, BOOL& bHandled)
{
ResetCheckList();
return 1;
}
LRESULT CDelegWiz_DelegatedRightsPage::OnListViewItemChanged(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
{
if (m_bUIUpdateInProgress)
return 1;
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pnmh;
if (CCheckListViewHelper::CheckChanged(pNMListView))
{
CRigthsListViewItem* pItem = (CRigthsListViewItem*)pNMListView->lParam; // item data
CDelegWiz* pWizard = GET_OU_WIZARD();
ULONG nCurrFilterOptions = GetFilterOptions();
ULONG nNewFilterOptions = 0;
pWizard->OnCustomAccessRightsCheckListClick(
pItem, CCheckListViewHelper::IsChecked(pNMListView),
&nNewFilterOptions);
nNewFilterOptions |= nCurrFilterOptions;
m_bUIUpdateInProgress = TRUE;
// this call will cause a series of notifications:
// we have to disable them to avoid reentrancy
if (nNewFilterOptions == nCurrFilterOptions)
{
// no need to change filter selection, just update the checkboxes
pWizard->UpdateAccessRightsListViewSelection(&m_delegatedRigthsListView, nNewFilterOptions);
}
else
{
// filter selection must be changed,
// so we have to update the check boxes and to refill the checklist
SetFilterOptions(nNewFilterOptions);
ResetCheckList();
}
m_bUIUpdateInProgress = FALSE;
BOOL bSel = pWizard->HasPermissionSelectedCustom();
pWizard->SetWizardButtonsMiddle(bSel);
}
return 1;
}
void CDelegWiz_DelegatedRightsPage::ResetCheckList()
{
// get a new filtered list of rights in the list view
CDelegWiz* pWizard = GET_OU_WIZARD();
// this call will cause a series of notifications:
// we have to disable them to avoid reentrancy
m_bUIUpdateInProgress = TRUE;
pWizard->FillCustomAccessRightsListView(&m_delegatedRigthsListView, GetFilterOptions());
m_bUIUpdateInProgress = FALSE;
pWizard->SetWizardButtonsMiddle(pWizard->HasPermissionSelectedCustom());
}
ULONG CDelegWiz_DelegatedRightsPage::GetFilterOptions()
{
ULONG nFilterState = 0;
// read the filtering options from checkboxes
if (BST_CHECKED == ::SendMessage(m_hwndGeneralRigthsCheck, BM_GETCHECK, 0, 0))
nFilterState |= FILTER_EXP_GEN;
if (BST_CHECKED == ::SendMessage(m_hwndPropertyRightsCheck, BM_GETCHECK, 0, 0))
nFilterState |= FILTER_EXP_PROP;
if (BST_CHECKED == ::SendMessage(m_hwndSubobjectRightsCheck, BM_GETCHECK, 0, 0))
nFilterState |= FILTER_EXP_SUBOBJ;
return nFilterState;
}
inline WPARAM _Checked(ULONG f) { return f ? BST_CHECKED : BST_UNCHECKED;}
void CDelegWiz_DelegatedRightsPage::SetFilterOptions(ULONG nFilterOptions)
{
::EnableWindow(m_hwndGeneralRigthsCheck,!(nFilterOptions & FILTER_EXP_GEN_DISABLED));
::SendMessage(m_hwndGeneralRigthsCheck, BM_SETCHECK, _Checked(nFilterOptions & FILTER_EXP_GEN), 0);
::SendMessage(m_hwndPropertyRightsCheck, BM_SETCHECK, _Checked(nFilterOptions & FILTER_EXP_PROP), 0);
::SendMessage(m_hwndSubobjectRightsCheck, BM_SETCHECK, _Checked(nFilterOptions & FILTER_EXP_SUBOBJ), 0);
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz_FinishPage
BOOL CALLBACK CDelegWiz_FinishPage::OnInitDialog(UINT uMsg, WPARAM wParam,
LPARAM lParam, BOOL& bHandled)
{
SetLargeFont(m_hWnd, IDC_STATIC_COMPLETION);
return TRUE;
}
LRESULT CDelegWiz_FinishPage::OnSetFocusSummaryEdit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
ASSERT(hWndCtl == GetDlgItem(IDC_EDIT_SUMMARY));
::SendMessage(hWndCtl, EM_SETSEL, (WPARAM)-1, (LPARAM)0);
if (m_bNeedSetFocus)
{
m_bNeedSetFocus = FALSE;
TRACE(_T("Resetting Focus\n"));
HWND hwndSheet = ::GetParent(m_hWnd);
ASSERT(::IsWindow(hwndSheet));
HWND hWndFinishCtrl =::GetDlgItem(hwndSheet, 0x3025);
ASSERT(::IsWindow(hWndFinishCtrl));
::SetFocus(hWndFinishCtrl);
}
return 1;
}
BOOL CDelegWiz_FinishPage::OnSetActive()
{
CDelegWiz* pWizard = GET_OU_WIZARD();
pWizard->SetWizardButtonsLast(TRUE);
CWString szSummary;
if (m_bCustom)
pWizard->WriteSummaryInfoCustom(szSummary, g_lpszSummaryIdent, g_lpszSummaryNewLine);
else
pWizard->WriteSummaryInfoTemplate(szSummary, g_lpszSummaryIdent, g_lpszSummaryNewLine);
HWND hWndSummary = GetDlgItem(IDC_EDIT_SUMMARY);
::SetWindowText(hWndSummary, (LPCWSTR)szSummary);
m_bNeedSetFocus = TRUE;
return TRUE;
}
BOOL CDelegWiz_FinishPage::OnWizardFinish()
{
CWaitCursor wait;
BOOL bRes;
CDelegWiz* pWizard = GET_OU_WIZARD();
if (m_bCustom)
bRes = GET_OU_WIZARD()->FinishCustom();
else
bRes = GET_OU_WIZARD()->FinishTemplate();
return bRes;
}
////////////////////////////////////////////////////////////////////////////
// CDelegWiz
const long CDelegWiz::nSchemaClassesSelAll = -2;
const long CDelegWiz::nSchemaClassesSelMultiple = -1;
// REVIEW_MARCOC: should probably nuke, not used
BOOL Is256ColorSupported()
{
BOOL bRetval = FALSE;
HDC hdc = GetDC(NULL);
if( hdc )
{
if( GetDeviceCaps( hdc, BITSPIXEL ) >= 8 )
{
bRetval = TRUE;
}
ReleaseDC(NULL, hdc);
}
return bRetval;
}
CDelegWiz::CDelegWiz() :
CWizardBase(IDB_DELEG_WATER, IDB_DELEG_HD, IDS_DELEGWIZ_WIZ_TITLE),
m_startPage(this),
m_namePage(this),
m_templateSelectionPage(this),
m_userOrGroupSelectionPage(this),
m_objectTypeSelectionPage(this),
m_delegatedRightsPage(this),
m_finishPage(this),
m_bAuxClass(FALSE)
{
m_lpszLDAPPath = NULL;
m_nSchemaClassesSel = nSchemaClassesSelAll;
m_fCreateDelChild = 0;
// Add the property pages
m_startPage.InitWiz97(TRUE);
AddPage(m_startPage);
m_namePage.InitWiz97(FALSE,
IDS_DELEGWIZ_NAME_TITLE,
IDS_DELEGWIZ_NAME_SUBTITLE);
AddPage(m_namePage);
m_userOrGroupSelectionPage.InitWiz97(FALSE,
IDS_DELEGWIZ_PRINCIPALS_SEL_TITLE,
IDS_DELEGWIZ_PRINCIPALS_SEL_SUBTITLE);
AddPage(m_userOrGroupSelectionPage);
// branching page
m_templateSelectionPage.InitWiz97(FALSE,
IDS_DELEGWIZ_TEMPLATE_SEL_TITLE,
IDS_DELEGWIZ_TEMPLATE_SEL_SUBTITLE);
AddPage(m_templateSelectionPage);
m_objectTypeSelectionPage.InitWiz97(FALSE,
IDS_DELEGWIZ_OBJ_TYPE_SEL_TITLE,
IDS_DELEGWIZ_OBJ_TYPE_SEL_SUBTITLE);
AddPage(m_objectTypeSelectionPage);
m_delegatedRightsPage.InitWiz97(FALSE,
IDS_DELEGWIZ_DELEG_RIGHTS_TITLE,
IDS_DELEGWIZ_DELEG_RIGHTS_SUBTITLE);
AddPage(m_delegatedRightsPage);
m_finishPage.InitWiz97(TRUE);
AddPage(m_finishPage);
m_templateAccessPermissionsHolderManager.LoadTemplates();
};
CDelegWiz::~CDelegWiz()
{
}
HRESULT CDelegWiz::AddPrincipalsFromBrowseResults(CPrincipalListViewHelper* pListViewHelper,
PDS_SELECTION_LIST pDsSelectionList)
{
TRACE(L"CDelegWiz::AddPrincipalsFromBrowseResults()\n");
HRESULT hr = S_OK;
if ( (pDsSelectionList == NULL) || (pDsSelectionList->cItems == 0))
{
TRACE(L"CDelegWiz::AddPrincipalsFromBrowseResults(), no items!!!\n");
return E_INVALIDARG;
}
int nListInsertPosition = pListViewHelper->GetItemCount();
for (int i = 0; i < pDsSelectionList->cItems; i++)
{
TRACE(L"For loop, pDsSelectionList->cItems = %d\n", pDsSelectionList->cItems);
// add to list of principals
CPrincipal* pPrincipal = new CPrincipal;
if (pPrincipal != NULL)
{
HICON hClassIcon = m_adsiObject.GetClassIcon(pDsSelectionList->aDsSelection[i].pwzClass);
HRESULT hrInit = pPrincipal->Initialize(&(pDsSelectionList->aDsSelection[i]), hClassIcon);
if (FAILED(hrInit))
{
LPCWSTR lpszName = pDsSelectionList->aDsSelection[i].pwzName;
WCHAR szFmt[256];
LoadStringHelper(IDS_DELEGWIZ_ERR_INVALID_PRINCIPAL, szFmt, 256);
int nNameLen = lstrlen(lpszName) + 1;
WCHAR* lpszMsg = (WCHAR*)alloca(sizeof(WCHAR)*(nNameLen+256));
wsprintf(lpszMsg, szFmt, lpszName);
WizReportHRESULTError(lpszMsg, hrInit);
delete pPrincipal;
continue;
}
// add to list of principals (if not already there)
if (m_principalList.AddIfNotPresent(pPrincipal))
{
// add to listbox (assume not sorted)
pListViewHelper->InsertItem(nListInsertPosition, pPrincipal);
nListInsertPosition++;
}
} // if pPrincipal not NULL
} // for
// make sure there is a selection
if ( (pListViewHelper->GetItemCount() > 0) &&
(pListViewHelper->GetSelCount() == 0) )
{
// if we have items, but none is selected, make sure we set the selection
// to the first one.
pListViewHelper->SelectItem(0);
}
// update width
//pListViewHelper->UpdateWidth(m_principalList.GetMaxListboxExtent());
return hr;
}
/*
typedef struct _DSOP_FILTER_FLAGS
{
DSOP_UPLEVEL_FILTER_FLAGS Uplevel;
ULONG flDownlevel;
} DSOP_FILTER_FLAGS;
typedef struct _DSOP_SCOPE_INIT_INFO
{
ULONG cbSize;
ULONG flType;
ULONG flScope;
DSOP_FILTER_FLAGS FilterFlags;
PCWSTR pwzDcName; // OPTIONAL
PCWSTR pwzADsPath; // OPTIONAL
HRESULT hr;
} DSOP_SCOPE_INIT_INFO, *PDSOP_SCOPE_INIT_INFO;
*/
DSOP_SCOPE_INIT_INFO g_aDSOPScopes[] =
{
#if 0
{
cbSize,
flType,
flScope,
{
{ flBothModes, flMixedModeOnly, flNativeModeOnly },
flDownlevel,
},
pwzDcName,
pwzADsPath,
hr // OUT
},
#endif
// The Global Catalog
{
sizeof(DSOP_SCOPE_INIT_INFO),
DSOP_SCOPE_TYPE_GLOBAL_CATALOG,
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS,
{
{ DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS |
DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE |
DSOP_FILTER_COMPUTERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS, 0, 0 },
0,
},
NULL,
NULL,
S_OK
},
// The domain to which the target computer is joined.
{
sizeof(DSOP_SCOPE_INIT_INFO),
DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN,
DSOP_SCOPE_FLAG_STARTING_SCOPE |
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS,
{
// joined domain is always NT5 for DS ACLs Editor
{ 0,
//mixed: users, well known SIDs, local groups, builtin groups, global groups, computers
DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS | DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_BUILTIN_GROUPS | DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_COMPUTERS ,
//native users, well known SIDs, local groups, builtin groups, global groups, universal groups, computers
DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_WELL_KNOWN_PRINCIPALS |
DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_BUILTIN_GROUPS |
DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_COMPUTERS
},
0, // zero for downlevel joined domain, should be DS-aware
},
NULL,
NULL,
S_OK
},
// The domains in the same forest (enterprise) as the domain to which
// the target machine is joined. Note these can only be DS-aware
{
sizeof(DSOP_SCOPE_INIT_INFO),
DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN,
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS,
{
{ DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_COMPUTERS, 0, 0},
0,
},
NULL,
NULL,
S_OK
},
// Domains external to the enterprise but trusted directly by the
// domain to which the target machine is joined.
{
sizeof(DSOP_SCOPE_INIT_INFO),
DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN,
DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_GROUPS|
DSOP_SCOPE_FLAG_DEFAULT_FILTER_USERS,
{
{ DSOP_FILTER_INCLUDE_ADVANCED_VIEW | DSOP_FILTER_USERS | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_COMPUTERS, 0, 0},
DSOP_DOWNLEVEL_FILTER_USERS | DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS,
},
NULL,
NULL,
S_OK
},
};
//
// Attributes that we want the Object Picker to retrieve
//
static const LPCTSTR g_aszOPAttributes[] =
{
TEXT("ObjectSid"),
TEXT("userAccountControl"),
};
HRESULT CDelegWiz::AddPrincipals(CPrincipalListViewHelper* pListViewHelper)
{
TRACE(L"CDelegWiz::AddPrincipals()\n");
// create object picker COM object
CComPtr<IDsObjectPicker> spDsObjectPicker;
HRESULT hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER,
IID_IDsObjectPicker, (void**)&spDsObjectPicker);
if (FAILED(hr))
{
TRACE(L"CoCreateInstance(CLSID_DsObjectPicker) failed, hr = 0x%x\n");
return hr;
}
// set init info
DSOP_INIT_INFO InitInfo;
ZeroMemory(&InitInfo, sizeof(InitInfo));
InitInfo.cbSize = sizeof(DSOP_INIT_INFO);
InitInfo.pwzTargetComputer = m_adsiObject.GetServerName();
InitInfo.cDsScopeInfos = sizeof(g_aDSOPScopes)/sizeof(DSOP_SCOPE_INIT_INFO);
InitInfo.aDsScopeInfos = g_aDSOPScopes;
InitInfo.flOptions = DSOP_FLAG_MULTISELECT;
InitInfo.cAttributesToFetch = 2;
InitInfo.apwzAttributeNames = (LPCTSTR*)g_aszOPAttributes;;
TRACE(L"InitInfo.cbSize = %d\n", InitInfo.cbSize);
TRACE(L"InitInfo.pwzTargetComputer = %s\n", InitInfo.pwzTargetComputer);
TRACE(L"InitInfo.cDsScopeInfos = %d\n", InitInfo.cDsScopeInfos);
TRACE(L"InitInfo.aDsScopeInfos = 0x%x\n", InitInfo.aDsScopeInfos);
TRACE(L"InitInfo.flOptions = 0x%x\n", InitInfo.flOptions);
TRACE(L"InitInfo.cAttributesToFetch = %d\n", InitInfo.cAttributesToFetch);
TRACE(L"InitInfo.apwzAttributeNames[0]= %s\n", InitInfo.apwzAttributeNames[0]);
// initialize object picker
hr = spDsObjectPicker->Initialize(&InitInfo);
if (FAILED(hr))
{
TRACE(L"spDsObjectPicker->Initialize(...) failed, hr = 0x%x\n");
return hr;
}
// invoke the dialog
CComPtr<IDataObject> spdoSelections;
hr = spDsObjectPicker->InvokeDialog(m_hWnd, &spdoSelections);
if (hr == S_FALSE || !spdoSelections)
{
return S_FALSE;
}
// retrieve data from data object
FORMATETC fmte = {(CLIPFORMAT)_Module.GetCfDsopSelectionList(), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
STGMEDIUM medium = {TYMED_NULL, NULL, NULL};
PDS_SELECTION_LIST pDsSelList = NULL;
hr = spdoSelections->GetData(&fmte, &medium);
if (FAILED(hr))
{
TRACE(L"spdoSelections->GetData(...) failed, hr = 0x%x\n");
return hr;
}
pDsSelList = (PDS_SELECTION_LIST)GlobalLock(medium.hGlobal);
if(!DoDisabledCheck(*this,pDsSelList))
{
return S_FALSE;
}
hr = AddPrincipalsFromBrowseResults(pListViewHelper, pDsSelList);
GlobalUnlock(medium.hGlobal);
ReleaseStgMedium(&medium);
return hr;
}
BOOL CDelegWiz::DeletePrincipals(CPrincipalListViewHelper* pListViewHelper)
{
CGrowableArr<CPrincipal> deletedArr(FALSE); // do not own memory
// remove from listview
pListViewHelper->DeleteSelectedItems(&deletedArr);
// remove from list of items
int nDeletedCount = deletedArr.GetCount();
for (int k=0; k<nDeletedCount; k++)
{
m_principalList.Remove(deletedArr[k]);
}
//pListViewHelper->UpdateWidth(m_principalList.GetMaxListboxExtent());
return TRUE;
}
int CDelegWiz::FillCustomSchemaClassesListView(CCheckListViewHelper* pListViewHelper, BOOL bFilter)
{
// clear old entries
pListViewHelper->DeleteAllItems();
int nCount = m_schemaClassInfoArray.GetCount();
if (nCount == 0)
return 0; // no insertions, nothing else to do
// figure out the max len of items to get a big enough buffer
int nMaxLen = 0;
int nCurrLen = 0;
for (long index = 0; index < nCount; index++)
{
nCurrLen = lstrlen(m_schemaClassInfoArray[index]->GetDisplayName());
if (nCurrLen > nMaxLen)
nMaxLen = nCurrLen;
}
CWString szFormat;
szFormat.LoadFromResource(IDS_DELEGWIZ_CHILD_CLASS_FMT);
WCHAR* pwszNewText = (WCHAR*)alloca(sizeof(WCHAR)*(szFormat.size()+nMaxLen+1));
// add formatted entries, assume listbox not sorted
long iListBoxItem = 0;
for (index = 0; index < nCount; index++)
{
CSchemaClassInfo* pChildClassInfo = m_schemaClassInfoArray[index];
pChildClassInfo->m_bSelected = FALSE;
if (bFilter && pChildClassInfo->IsFiltered())
continue;
wsprintf(pwszNewText, (LPCWSTR)szFormat, pChildClassInfo->GetDisplayName());
pListViewHelper->InsertItem(iListBoxItem, pwszNewText, (LPARAM)pChildClassInfo, FALSE);
iListBoxItem++;
}
return iListBoxItem; // return the # of items inserted
}
BOOL CDelegWiz::SetSchemaClassesSelectionCustom()
{
int nSelCount = 0;
int nCount = m_schemaClassInfoArray.GetCount();
CComPtr<IADsClass> spSchemaObjectClass;
m_bChildClass = FALSE;
// get the selection count
int nSingleSel = -1;
for (int k=0; k < nCount; k++)
{
if (m_schemaClassInfoArray[k]->m_bSelected)
{
if( m_schemaClassInfoArray[k]->m_dwChildClass == CHILD_CLASS_NOT_CALCULATED )
{
if (m_schemaClassInfoArray[k]->GetName() != NULL)
{
int nServerNameLen = lstrlen(m_adsiObject.GetServerName());
int nClassNameLen = lstrlen(m_schemaClassInfoArray[k]->GetName());
int nFormatStringLen = lstrlen(g_wzLDAPAbstractSchemaFormat);
VARIANT var = {0};
// build the LDAP path for the schema class
WCHAR* pwszSchemaObjectPath =
(WCHAR*)alloca(sizeof(WCHAR)*(nServerNameLen+nClassNameLen+nFormatStringLen+1));
wsprintf(pwszSchemaObjectPath, g_wzLDAPAbstractSchemaFormat, m_adsiObject.GetServerName(), m_schemaClassInfoArray[k]->GetName());
// get the schema class ADSI object
HRESULT hr = ::ADsOpenObjectHelper(pwszSchemaObjectPath,
IID_IADsClass,
0,
(void**)&spSchemaObjectClass);
if (FAILED(hr))
//NTRAID#NTBUG9-530206-2002/06/18-ronmart-PREFAST: Casting HRESULT to BOOL
//return hr;
return FALSE;
spSchemaObjectClass->get_Containment(&var);
if (V_VT(&var) == (VT_ARRAY | VT_VARIANT))
{
LPSAFEARRAY psa = V_ARRAY(&var);
ASSERT(psa && psa->cDims == 1);
if (psa->rgsabound[0].cElements > 0)
{
m_schemaClassInfoArray[k]->m_dwChildClass = CHILD_CLASS_EXIST;
}
else
m_schemaClassInfoArray[k]->m_dwChildClass = CHILD_CLASS_NOT_EXIST;
}
else if (V_VT(&var) == VT_BSTR) // single entry
{
m_schemaClassInfoArray[k]->m_dwChildClass = CHILD_CLASS_EXIST;
}
else
m_schemaClassInfoArray[k]->m_dwChildClass = CHILD_CLASS_NOT_EXIST;
VariantClear(&var);
}
}
if( m_schemaClassInfoArray[k]->m_dwChildClass != CHILD_CLASS_NOT_EXIST )
m_bChildClass = TRUE;
if (nSingleSel == -1)
nSingleSel = k;
nSelCount++;
}
}
if (nSelCount == 0)
{
m_nSchemaClassesSel = nSchemaClassesSelAll;
m_bChildClass = TRUE;
return TRUE; // delegate control to all types
}
// keep track if it is a single selection
if (nSelCount == 1)
{
ASSERT(nSingleSel != -1);
m_nSchemaClassesSel = nSingleSel;
return TRUE;
}
// multiple selection
m_nSchemaClassesSel = nSchemaClassesSelMultiple;
return TRUE;
}
void CDelegWiz::DeselectSchemaClassesSelectionCustom()
{
int nCount = m_schemaClassInfoArray.GetCount();
for (int k=0; k < nCount; k++)
{
m_schemaClassInfoArray[k]->m_bSelected = FALSE;
}
}
BOOL CDelegWiz::GetCustomAccessPermissions()
{
// remove all the old entries
m_permissionHolder.Clear();
// retrieve the string for the child class object type (single selection)
// for multiple selection, it will be NULL
CSchemaClassInfo* pClassInfo = NULL;
switch (m_nSchemaClassesSel)
{
case nSchemaClassesSelMultiple:
{
// for multiple selection, it will be NULL
pClassInfo = NULL;
}
break;
case nSchemaClassesSelAll:
{
// just get the class name of the object we want to delegate rights on
// need to find matching class in the schema info array
for (int k=0; k < m_schemaClassInfoArray.GetCount(); k++)
{
if (_wcsicmp(m_schemaClassInfoArray[k]->GetName(), m_adsiObject.GetClass()) == 0)
{
pClassInfo = m_schemaClassInfoArray[k];
break;
}
} // for k
ASSERT(pClassInfo != NULL);
}
break;
default:
{
// single selection
ASSERT( (m_nSchemaClassesSel >= 0) &&
(m_nSchemaClassesSel < m_schemaClassInfoArray.GetCount()) );
pClassInfo = m_schemaClassInfoArray[m_nSchemaClassesSel];
}
} // switch
// get the permissions from the DS
LPCWSTR lpszClassName = NULL;
const GUID* pSchemaIDGUID = NULL;
if (pClassInfo != NULL)
{
lpszClassName = pClassInfo->GetName();
pSchemaIDGUID = pClassInfo->GetSchemaGUID();
}
HRESULT hr = m_permissionHolder.ReadDataFromDS(&m_adsiObject,
m_adsiObject.GetNamingContext(),
lpszClassName,
pSchemaIDGUID,
m_bChildClass,
HideListObjectAccess());
if (FAILED(hr))
{
WizReportHRESULTError(IDS_DELEGWIZ_ERR_PERMISSIONS, hr);
return FALSE;
}
return TRUE;
}
void CDelegWiz::FillCustomAccessRightsListView(CCheckListViewHelper* pListViewHelper,
ULONG nFilterState)
{
// clear check list
pListViewHelper->DeleteAllItems();
m_permissionHolder.FillAccessRightsListView(pListViewHelper, nFilterState);
}
void CDelegWiz::UpdateAccessRightsListViewSelection(
CCheckListViewHelper* pListViewHelper,
ULONG nFilterState)
{
m_permissionHolder.UpdateAccessRightsListViewSelection(
pListViewHelper, nFilterState);
}
BOOL CDelegWiz::HasPermissionSelectedCustom()
{
return m_permissionHolder.HasPermissionSelected();
}
void CDelegWiz::OnCustomAccessRightsCheckListClick(
CRigthsListViewItem* pItem,
BOOL bSelected,
ULONG* pnNewFilterState)
{
m_permissionHolder.Select(pItem, bSelected, pnNewFilterState);
}
void CDelegWiz::WriteSummaryInfoCustom(CWString& szSummary, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
{
// write object name and principals
WriteSummaryInfoHelper(szSummary, lpszIdent, lpszNewLine);
// write the list of rights
m_permissionHolder.WriteSummary(szSummary, lpszIdent, lpszNewLine);
// write the list of child classes (if applicable)
if (m_nSchemaClassesSel != nSchemaClassesSelAll)
{
WriteSummaryTitleLine(szSummary, IDS_DELEGWIZ_FINISH_OBJECT, lpszNewLine);
for (int k=0; k < m_schemaClassInfoArray.GetCount(); k++)
{
if (m_schemaClassInfoArray[k]->m_bSelected)
{
WriteSummaryLine(szSummary, m_schemaClassInfoArray[k]->GetDisplayName(), lpszIdent, lpszNewLine);
}
}
szSummary += lpszNewLine;
} // if
}
BOOL CDelegWiz::InitPermissionHoldersFromSelectedTemplates()
{
if (!m_templateAccessPermissionsHolderManager.InitPermissionHoldersFromSelectedTemplates(
&m_schemaClassInfoArray, &m_adsiObject))
{
// error: no valid and applicable data has been retrieved from the selected
// templates
return FALSE;
}
return TRUE;
}
void CDelegWiz::WriteSummaryInfoTemplate(CWString& szSummary, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
{
// write object name and principals
WriteSummaryInfoHelper(szSummary,lpszIdent, lpszNewLine);
// write the list of templates
m_templateAccessPermissionsHolderManager.WriteSummary(szSummary, lpszIdent, lpszNewLine);
}
void CDelegWiz::WriteSummaryInfoHelper(CWString& szSummary, LPCWSTR lpszIdent, LPCWSTR lpszNewLine)
{
// set the canonical name
WriteSummaryTitleLine(szSummary, IDS_DELEGWIZ_FINISH_FOLDER, lpszNewLine);
WriteSummaryLine(szSummary, GetCanonicalName(), lpszIdent, lpszNewLine);
szSummary += lpszNewLine;
// write the list of principals
m_principalList.WriteSummaryInfo(szSummary, lpszIdent, lpszNewLine);
}
/*
typedef struct _ACTRL_ACCESS_ENTRYW
{
TRUSTEE_W Trustee;
ULONG fAccessFlags;
ACCESS_RIGHTS Access;
ACCESS_RIGHTS ProvSpecificAccess;
INHERIT_FLAGS Inheritance;
LPWSTR lpInheritProperty;
} ACTRL_ACCESS_ENTRYW, *PACTRL_ACCESS_ENTRYW;
*/
DWORD CDelegWiz::UpdateAccessList(CPrincipal* pPrincipal,
CSchemaClassInfo* pClassInfo,
PACL *ppAcl)
{
return m_permissionHolder.UpdateAccessList(
pPrincipal, pClassInfo,
m_adsiObject.GetServerName(),
m_adsiObject.GetPhysicalSchemaNamingContext(),
ppAcl);
}
DWORD CDelegWiz::BuildNewAccessListCustom(PACL *ppNewAcl)
{
DWORD dwErr = 0;
TRACE(L"BuildNewAccessListCustom()\n");
// loop thru all the principals and classes
CPrincipalList::iterator i;
for (i = m_principalList.begin(); i != m_principalList.end(); ++i)
{
CPrincipal* pCurrPrincipal = *i;
if (m_nSchemaClassesSel == nSchemaClassesSelAll)
{
// delegate on all objects
dwErr = UpdateAccessList(
pCurrPrincipal,
NULL, // all classes
ppNewAcl);
if (dwErr != ERROR_SUCCESS)
return dwErr;
}
else if (m_nSchemaClassesSel == nSchemaClassesSelMultiple)
{
// delegate on multiple objects
// multiple selection, loop thru each class to
// add rights for each
for (int k=0; k < m_schemaClassInfoArray.GetCount(); k++)
{
if (m_schemaClassInfoArray[k]->m_bSelected)
{
dwErr = UpdateAccessList(
pCurrPrincipal,
m_schemaClassInfoArray[k],
ppNewAcl);
if (dwErr != ERROR_SUCCESS)
return dwErr;
if( m_fCreateDelChild != 0 )
{
dwErr = ::AddObjectRightInAcl( pCurrPrincipal->GetSid(),
m_fCreateDelChild,
m_schemaClassInfoArray[k]->GetSchemaGUID(),
NULL,
ppNewAcl);
if (dwErr != ERROR_SUCCESS)
return dwErr;
}
}
} // for k
}
else
{
// single selection on child classes
dwErr = UpdateAccessList(
pCurrPrincipal,
m_schemaClassInfoArray[m_nSchemaClassesSel],
ppNewAcl);
if (dwErr != ERROR_SUCCESS)
return dwErr;
if( m_fCreateDelChild != 0 )
{
dwErr = ::AddObjectRightInAcl( pCurrPrincipal->GetSid(),
m_fCreateDelChild,
m_schemaClassInfoArray[m_nSchemaClassesSel]->GetSchemaGUID(),
NULL,
ppNewAcl);
if (dwErr != ERROR_SUCCESS)
return dwErr;
}
}
} // for pCurrPrincipal
return dwErr;
}
DWORD CDelegWiz::BuildNewAccessListTemplate(PACL *ppNewAcl)
{
DWORD dwErr = 0;
TRACE(L"BuildNewAccessListTemplate()\n");
// loop thru all the principals and classes
CPrincipalList::iterator i;
for (i = m_principalList.begin(); i != m_principalList.end(); ++i)
{
CPrincipal* pCurrPrincipal = *i;
dwErr = m_templateAccessPermissionsHolderManager.UpdateAccessList(
pCurrPrincipal,
m_adsiObject.GetServerName(),
m_adsiObject.GetPhysicalSchemaNamingContext(),
ppNewAcl);
if (dwErr != 0)
break;
} // for pCurrPrincipal
return dwErr;
}
BOOL CDelegWiz::FinishHelper(BOOL bCustom)
{
BOOL bRetVal = FALSE;
DWORD dwErr = 0;
PACL pDacl = NULL;
PACL pOldAcl = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
LPCWSTR lpszObjectLdapPath = m_adsiObject.GetLdapPath();
// get the security info
TRACE(L"calling GetSDForDsObjectPath(%s, ...)\n", lpszObjectLdapPath);
HRESULT hr = ::GetSDForDsObjectPath(IN const_cast<LPWSTR>(lpszObjectLdapPath),
&pDacl,
&pSD);
if (FAILED(hr))
{
TRACE(L"failed on GetSDForDsObjectPath(): hr = 0x%x\n", hr);
WCHAR szMsg[512];
LoadStringHelper(IDS_DELEGWIZ_ERR_GET_SEC_INFO, szMsg, 512);
WizReportHRESULTError(szMsg, hr);
goto exit;
}
//pOldAcl is passed to functions which free it. pDacl cannot be
//passed as pSD should be freed , not pDacl. Instead of changing code
//to pass pSD, i am changing it to make a copy of pDacl which can
//be correctly freed.
if(pDacl)
{
pOldAcl = (PACL)LocalAlloc(LPTR, pDacl->AclSize);
if(!pOldAcl)
return FALSE;
memcpy(pOldAcl, pDacl,pDacl->AclSize);
}
LocalFree(pSD);
pSD = NULL;
pDacl = NULL;
// build the new Access List
if (bCustom)
{
dwErr = BuildNewAccessListCustom(&pOldAcl); // in/out parameter
}
else
{
dwErr = BuildNewAccessListTemplate(&pOldAcl); // in/out parameter
}
if (dwErr != ERROR_SUCCESS)
{
TRACE(_T("failed on BuildNewAccessListXXX()\n"));
WCHAR szMsg[512];
LoadStringHelper(IDS_DELEGWIZ_ERR_EDIT_SEC_INFO, szMsg, 512);
WizReportWin32Error(szMsg, dwErr);
goto exit;
}
// commit changes
TRACE(L"calling SetDaclForDsObjectPath(%s, ...)\n", lpszObjectLdapPath);
hr = ::SetDaclForDsObjectPath(IN const_cast<LPWSTR>(lpszObjectLdapPath),pOldAcl);
if(FAILED(hr))
{
TRACE(L"failed on SetDaclForDsObjectPath(): hr = 0x%x\n", hr);
WCHAR szMsg[512];
if(dwErr == ERROR_ACCESS_DENIED)
LoadStringHelper(IDS_DELEGWIZ_ERR_ACCESS_DENIED, szMsg, 512);
else
LoadStringHelper(IDS_DELEGWIZ_ERR_SET_SEC_INFO, szMsg, 512);
WizReportHRESULTError(szMsg, hr);
goto exit;
}
bRetVal = TRUE;
exit:
// cleanup memory
if (pOldAcl != NULL)
::LocalFree(pOldAcl);
return bRetVal;
}
//+----------------------------------------------------------------------------
// Function:DoDisabledCheck
// Synopsis:Check if any of the object in pDsSelList is disabled. if yes,
// function displays a dialog box to user.
// Returns: TRUE if to add objects in list to acl else no.
//-----------------------------------------------------------------------------
BOOL
DoDisabledCheck(IN CDelegWiz& refWiz,
IN PDS_SELECTION_LIST pDsSelList)
{
if(!pDsSelList)
{
return FALSE;
}
HRESULT hr = S_OK;
int cNames = pDsSelList->cItems;
BOOL bDisabled = FALSE;
//
//Check if account of any of the object in the list is disbled
//
for (int i = 0; i < cNames; i++)
{
//Second element in the array is pointer to UserAccountControl
LPVARIANT pvarUAC = pDsSelList->aDsSelection[i].pvarFetchedAttributes + 1;
if (NULL == pvarUAC || (VT_I4 != V_VT(pvarUAC)))
{
continue;
}
if(bDisabled = V_I4(pvarUAC) & UF_ACCOUNTDISABLE)
break;
}
BOOL bReturn = TRUE;
if(bDisabled)
{
if(IDCANCEL == refWiz.WizMessageBox(IDS_DISABLED_USER,
MB_OKCANCEL | MB_ICONWARNING | MB_APPLMODAL ))
{
bReturn = FALSE;
}
}
return bReturn;
}