477 lines
14 KiB
C++
477 lines
14 KiB
C++
|
// ContainerSelectionDlg.cpp : implementation file
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "OuSelect.h"
|
||
|
#include "iads.h"
|
||
|
#include <DSCLIENT.H>
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CContainerSelectionDlg dialog
|
||
|
|
||
|
typedef int (CALLBACK * DSBROWSEFORCONTAINER)(PDSBROWSEINFOW dsInfo);
|
||
|
DSBROWSEFORCONTAINER DsBrowseForContainerX;
|
||
|
|
||
|
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 PadOUName(WCHAR * sPath)
|
||
|
{
|
||
|
WCHAR sTemp[255];
|
||
|
int off = 0;
|
||
|
WCHAR sSpecial[] = L"#+\"<>=\\;,/";
|
||
|
// Find the first = sign
|
||
|
wcscpy(sTemp, sPath);
|
||
|
for ( DWORD i = 0; i < wcslen(sTemp); i++ )
|
||
|
{
|
||
|
if ( wcschr(sSpecial, sTemp[i]) )
|
||
|
{
|
||
|
sPath[i + off] = L'\\';
|
||
|
off++;
|
||
|
}
|
||
|
sPath[i + off] = sTemp[i];
|
||
|
}
|
||
|
sPath[i+off] = L'\0';
|
||
|
}
|
||
|
|
||
|
void UnPadOUName(WCHAR * sPath)
|
||
|
{
|
||
|
WCHAR sTemp[255];
|
||
|
int off = 0;
|
||
|
DWORD i = 0;
|
||
|
// Copy everything after the first = sign (if one exists)
|
||
|
WCHAR * pTemp = wcschr(sPath, L'=');
|
||
|
if ( pTemp )
|
||
|
{
|
||
|
wcscpy(sTemp, ++pTemp);
|
||
|
off = wcslen(pTemp) - wcslen(sPath);
|
||
|
}
|
||
|
else
|
||
|
wcscpy(sTemp, sPath);
|
||
|
|
||
|
for ( ; i < wcslen(sTemp); i++ )
|
||
|
{
|
||
|
if ( sTemp[i] == L'\\' )
|
||
|
{
|
||
|
i++;
|
||
|
off++;
|
||
|
}
|
||
|
sPath[i - off] = sTemp[i];
|
||
|
}
|
||
|
sPath[i-off] = L'\0';
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
domain = _bstr_t(m_strDomain);
|
||
|
ExpandCompletely(root, L"");
|
||
|
::SysFreeString(domain);
|
||
|
FindContainer();
|
||
|
*/
|
||
|
HMODULE hMod = NULL;
|
||
|
hMod = LoadLibrary(L"dsuiext.dll");
|
||
|
if ( hMod )
|
||
|
{
|
||
|
WCHAR sDomPath[255];
|
||
|
wsprintf(sDomPath, L"LDAP://%s", (WCHAR*) m_strDomain);
|
||
|
DsBrowseForContainerX = (DSBROWSEFORCONTAINER)GetProcAddress(hMod, "DsBrowseForContainerW");
|
||
|
WCHAR * sContPath, * sContName;
|
||
|
BrowseForContainer(m_hWnd, sDomPath, &sContPath, &sContName);
|
||
|
m_strCont = sContPath;
|
||
|
CoTaskMemFree(sContPath);
|
||
|
CoTaskMemFree(sContName);
|
||
|
UpdateData(FALSE);
|
||
|
}
|
||
|
OnOK();
|
||
|
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_t 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;
|
||
|
SAFEARRAY * psaVals;
|
||
|
_bstr_t sValName;
|
||
|
_bstr_t sType;
|
||
|
_variant_t * pDataVar;
|
||
|
_variant_t varVal;
|
||
|
WCHAR sTempName[255];
|
||
|
WCHAR sPath[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) )
|
||
|
{
|
||
|
//
|
||
|
wcscpy(sPath, (WCHAR*) sValName);
|
||
|
PadOUName(sPath);
|
||
|
if ( wcsicmp(sType, L"organizationalUnit") == 0 )
|
||
|
{
|
||
|
wsprintf(sTempName, L"OU=%s", sPath);
|
||
|
img = 4;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wsprintf(sTempName, L"CN=%s", sPath);
|
||
|
img = 2;
|
||
|
}
|
||
|
if ( wcsicmp(sTempName, L"CN=System") != 0 )
|
||
|
m_trOUTree.InsertItem(sTempName, img, img+1, tvItemParent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Clean up
|
||
|
if ( pEnum ) pEnum->Release();
|
||
|
VariantInit(&var);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CContainerSelectionDlg::ExpandCompletely(HTREEITEM tvItem, _bstr_t 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()
|
||
|
{
|
||
|
AFX_MANAGE_STATE(AfxGetStaticModuleState())
|
||
|
// 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;
|
||
|
WCHAR sTemp[255];
|
||
|
|
||
|
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.
|
||
|
wcscpy(sTemp,strCont);
|
||
|
UnPadOUName(sTemp);
|
||
|
strCont = CString(sTemp);
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
HRESULT CContainerSelectionDlg::BrowseForContainer(HWND hWnd,//Handle to window that should own the browse dialog.
|
||
|
LPOLESTR szRootPath, //Root of the browse tree. NULL for entire forest.
|
||
|
LPOLESTR *ppContainerADsPath, //Return the ADsPath of the selected container.
|
||
|
LPOLESTR *ppContainerClass //Return the ldapDisplayName of the container's class.
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
DSBROWSEINFO dsbi;
|
||
|
OLECHAR szPath[1000];
|
||
|
OLECHAR szClass[MAX_PATH];
|
||
|
DWORD result;
|
||
|
|
||
|
if (!ppContainerADsPath)
|
||
|
return E_POINTER;
|
||
|
|
||
|
::ZeroMemory( &dsbi, sizeof(dsbi) );
|
||
|
dsbi.hwndOwner = hWnd;
|
||
|
dsbi.cbStruct = sizeof (DSBROWSEINFO);
|
||
|
dsbi.pszCaption = L"Browse for Container"; // The caption (titlebar text)
|
||
|
dsbi.pszTitle = L"Select a target container."; //Text for the dialog.
|
||
|
dsbi.pszRoot = szRootPath; //ADsPath for the root of the tree to display in the browser.
|
||
|
//Specify NULL with DSBI_ENTIREDIRECTORY flag for entire forest.
|
||
|
//NULL without DSBI_ENTIREDIRECTORY flag displays current domain rooted at LDAP.
|
||
|
dsbi.pszPath = szPath; //Pointer to a unicode string buffer.
|
||
|
dsbi.cchPath = sizeof(szPath)/sizeof(OLECHAR);//count of characters for buffer.
|
||
|
dsbi.dwFlags = DSBI_RETURN_FORMAT | //Return the path to object in format specified in dwReturnFormat
|
||
|
DSBI_RETURNOBJECTCLASS; //Return the object class
|
||
|
dsbi.pfnCallback = NULL;
|
||
|
dsbi.lParam = 0;
|
||
|
dsbi.dwReturnFormat = ADS_FORMAT_X500; //Specify the format.
|
||
|
//This one returns an ADsPath. See ADS_FORMAT enum in IADS.H
|
||
|
dsbi.pszObjectClass = szClass; //Pointer to a unicode string buffer.
|
||
|
dsbi.cchObjectClass = sizeof(szClass)/sizeof(OLECHAR);//count of characters for buffer.
|
||
|
|
||
|
//if root path is NULL, make the forest the root.
|
||
|
if (!szRootPath)
|
||
|
dsbi.dwFlags |= DSBI_ENTIREDIRECTORY;
|
||
|
|
||
|
|
||
|
|
||
|
//Display browse dialog box.
|
||
|
result = DsBrowseForContainerX( &dsbi ); // returns -1, 0, IDOK or IDCANCEL
|
||
|
if (result == IDOK)
|
||
|
{
|
||
|
//Allocate memory for string
|
||
|
*ppContainerADsPath = (OLECHAR *)CoTaskMemAlloc (sizeof(OLECHAR)*(wcslen(szPath)+1));
|
||
|
if (*ppContainerADsPath)
|
||
|
{
|
||
|
wcscpy(*ppContainerADsPath, szPath);
|
||
|
//Caller must free using CoTaskMemFree
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr=E_FAIL;
|
||
|
if (ppContainerClass)
|
||
|
{
|
||
|
//Allocate memory for string
|
||
|
*ppContainerClass = (OLECHAR *)CoTaskMemAlloc (sizeof(OLECHAR)*(wcslen(szClass)+1));
|
||
|
if (*ppContainerClass)
|
||
|
{
|
||
|
wcscpy(*ppContainerClass, szClass);
|
||
|
//Call must free using CoTaskMemFree
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
else
|
||
|
hr=E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
hr = E_FAIL;
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|