Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

328 lines
9.4 KiB

// ContainerSelectionDlg.cpp : implementation file
//
#include "stdafx.h"
#include "OUPicker.h"
#include "ContainerSelectionDlg.h"
#include "iads.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CContainerSelectionDlg dialog
const BSTR sQuery = L"(|(objectClass=organizationalUnit) (objectClass=container))";
HTREEITEM root;
CContainerSelectionDlg::CContainerSelectionDlg(CWnd* pParent /*=NULL*/)
: CDialog(CContainerSelectionDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CContainerSelectionDlg)
m_strCont = _T("");
//}}AFX_DATA_INIT
}
void CContainerSelectionDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CContainerSelectionDlg)
DDX_Control(pDX, IDOK, m_btnOK);
DDX_Control(pDX, IDC_TREE1, m_trOUTree);
DDX_Text(pDX, IDC_EDIT1, m_strCont);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CContainerSelectionDlg, CDialog)
//{{AFX_MSG_MAP(CContainerSelectionDlg)
ON_BN_CLICKED(IDOK, OnOk)
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, OnSelchangedTree1)
ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CContainerSelectionDlg message handlers
void CContainerSelectionDlg::OnOk()
{
CDialog::OnOK();
}
BOOL CContainerSelectionDlg::OnInitDialog()
{
CWaitCursor wait;
CDialog::OnInitDialog();
if ( m_strDomain.IsEmpty() )
return TRUE;
LoadImageList();
root = m_trOUTree.InsertItem(m_strDomain, 0, 1);
ExpandCompletely(root, L"");
FindContainer();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
HRESULT CContainerSelectionDlg::PopulateContainer(
HTREEITEM tvItemParent, //in- Item to expand
BSTR sContName, //in- Name of the container.
INetObjEnumeratorPtr pQuery //in- Query Object
)
{
HRESULT hr = E_FAIL;
IEnumVARIANT * pEnum = NULL;
SAFEARRAY * psaCols = NULL;
SAFEARRAYBOUND bd = { 2, 0 };
LPWSTR pCols[] = { L"name", L"objectClass" };
BSTR HUGEP * pData;
_variant_t var;
DWORD dwFetch = 0;
BSTR domain = m_strDomain.AllocSysString();
SAFEARRAY * psaVals;
_bstr_t sValName;
_bstr_t sType;
_variant_t * pDataVar;
_variant_t varVal;
WCHAR sTempName[255];
int img = 0;
psaCols = SafeArrayCreate(VT_BSTR, 1, &bd);
if ( psaCols )
{
hr = SafeArrayAccessData(psaCols, (void HUGEP **)&pData);
if ( SUCCEEDED(hr) )
{
pData[0] = SysAllocString(pCols[0]);
pData[1] = SysAllocString(pCols[1]);
}
SafeArrayUnaccessData(psaCols);
}
if ( SUCCEEDED(hr))
hr = pQuery->raw_SetQuery(sContName, domain, sQuery, ADS_SCOPE_ONELEVEL, FALSE);
if ( SUCCEEDED(hr) )
hr = pQuery->raw_SetColumns(psaCols);
if ( SUCCEEDED(hr))
hr = pQuery->raw_Execute(&pEnum);
if ( pEnum )
{
while ( pEnum->Next(1, &var, &dwFetch) == S_OK )
{
psaVals = V_ARRAY(&var);
hr = SafeArrayAccessData(psaVals, (void**)&pDataVar);
if ( SUCCEEDED(hr) )
{
varVal = pDataVar[0];
if ( varVal.vt == VT_BSTR ) sValName = V_BSTR(&varVal);
varVal = pDataVar[1];
if ( varVal.vt == VT_BSTR ) sType = V_BSTR(&varVal);
SafeArrayUnaccessData(psaVals);
}
if ( SUCCEEDED(hr) )
{
//
if ( wcsicmp(sType, L"organizationalUnit") == 0 )
{
wsprintf(sTempName, L"OU=%s", (WCHAR*)sValName);
img = 4;
}
else
{
wsprintf(sTempName, L"CN=%s", (WCHAR*)sValName);
img = 2;
}
if ( wcsicmp(sTempName, L"CN=System") != 0 )
m_trOUTree.InsertItem(sTempName, img, img+1, tvItemParent);
}
}
}
// Clean up
::SysFreeString(domain);
if ( pEnum ) pEnum->Release();
VariantInit(&var);
return hr;
}
HRESULT CContainerSelectionDlg::ExpandCompletely(HTREEITEM tvItem, BSTR parentCont)
{
HTREEITEM tvChild;
WCHAR currCont[255];
CString sContName;
HRESULT hr = S_OK;
INetObjEnumeratorPtr pQuery(__uuidof(NetObjEnumerator));
// First populate this container
hr = PopulateContainer( tvItem, parentCont, pQuery);
// Check if it has children. If it does then for each child call this function recursively
if ( m_trOUTree.ItemHasChildren(tvItem) )
{
tvChild = m_trOUTree.GetChildItem(tvItem);
while ( tvChild )
{
// Get the name of the
sContName = m_trOUTree.GetItemText(tvChild);
if ( wcslen(parentCont) > 0 )
wsprintf(currCont, L"%s,%s", sContName, (WCHAR*)parentCont);
else
wcscpy(currCont, sContName);
ExpandCompletely(tvChild, currCont);
tvChild = m_trOUTree.GetNextSiblingItem(tvChild);
}
}
return hr;
}
BOOL CContainerSelectionDlg::LoadImageList()
{
// set up icon list for list box
// use bitmaps
CBitmap cont;
CBitmap ou;
CBitmap openCont;
CBitmap openOU;
CBitmap dir;
CBitmap dirOpen;
COLORREF cr = 0x000000;
if (
dir.LoadBitmap(IDB_DIR)
&& dirOpen.LoadBitmap(IDB_OPEN_DIR)
&& cont.LoadBitmap(IDB_CONT)
&& ou.LoadBitmap(IDB_OU)
&& openCont.LoadBitmap(IDB_OPEN_CONT)
&& openOU.LoadBitmap(IDB_OPEN_OU)
)
{
cr = GetFirstBitmapPixel(this,IDB_CONT);
ilist.Create(IDB_DIR, 16, 16, cr);
ilist.Add(&dirOpen, cr);
ilist.Add(&cont,cr);
ilist.Add(&openCont,cr);
ilist.Add(&ou,cr);
ilist.Add(&openOU,cr);
m_trOUTree.SetImageList(&ilist,TVSIL_NORMAL);
}
return TRUE;
}
COLORREF CContainerSelectionDlg::GetFirstBitmapPixel(CWnd * window,UINT idbBitmap)
{
CBitmap bmp;
COLORREF color = 0x00ffffff;
if ( bmp.LoadBitmap(idbBitmap) )
{
// Get Device context
CDC * windowDC = window->GetDC();
HDC hdcImage = ::CreateCompatibleDC(windowDC->m_hDC);
CBitmap * tempBmp = (CBitmap *)::SelectObject(hdcImage,(HBITMAP)bmp);
// now get the pixel
if ( windowDC && hdcImage && tempBmp )
{
color = GetPixel(hdcImage,0, 0);
}
if ( tempBmp )
::SelectObject(hdcImage,tempBmp);
if ( hdcImage )
::DeleteObject(hdcImage);
}
return color;
}
void CContainerSelectionDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
m_strCont = L"";
HTREEITEM tvSelected, tvParent;
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
tvSelected = m_trOUTree.GetSelectedItem();
if ( tvSelected )
{
// We dont want to process the domain name in the Container name so go upto
// the point where we have a parent. i.e. Child of the domain node.
while( tvParent = m_trOUTree.GetParentItem(tvSelected) )
{
// Build the container list by walking up the tree.
if ( m_strCont.IsEmpty() )
m_strCont = m_trOUTree.GetItemText(tvSelected);
else
m_strCont = m_strCont + CString(L",") + m_trOUTree.GetItemText(tvSelected);
tvSelected = tvParent;
}
}
m_btnOK.EnableWindow(!m_strCont.IsEmpty());
UpdateData(FALSE);
*pResult = 0;
}
void CContainerSelectionDlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
UpdateData();
if ( !m_strCont.IsEmpty() )
OnOk();
*pResult = 0;
}
HRESULT CContainerSelectionDlg::FindContainer()
{
CString strName;
int ndx = 0, oldNdx = -1;
// We can find the container iff there is one specified.
if (!m_strCont.IsEmpty())
{
OpenContainer(m_strCont, root);
}
return S_OK;
}
HTREEITEM CContainerSelectionDlg::OpenContainer(CString strCont, HTREEITEM rootSub)
{
int ndx = -1;
CString strLeft, strRight;
HTREEITEM tvItem = NULL;
if ( !strCont.IsEmpty() && rootSub )
{
ndx = strCont.Find(L",", 0);
if ( ndx > -1 )
{
// Get the right side of the comma string and Call this again to open the parent container.
strLeft = strCont.Left(ndx);
strRight = strCont.Mid(ndx + 1);
tvItem = OpenContainer(strRight, rootSub);
tvItem = OpenContainer(strLeft, tvItem);
}
else
{
// We have a container name so lets find it below rootSub node.
tvItem = m_trOUTree.GetChildItem(rootSub);
while (tvItem)
{
if ( m_trOUTree.GetItemText(tvItem) == strCont )
{
//m_trOUTree.Expand(tvItem, 0);
m_trOUTree.Select(tvItem, TVGN_CARET);
break;
}
tvItem = m_trOUTree.GetNextSiblingItem(tvItem);
}
}
}
return tvItem;
}