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.

327 lines
9.4 KiB

  1. // ContainerSelectionDlg.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "OUPicker.h"
  5. #include "ContainerSelectionDlg.h"
  6. #include "iads.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CContainerSelectionDlg dialog
  14. const BSTR sQuery = L"(|(objectClass=organizationalUnit) (objectClass=container))";
  15. HTREEITEM root;
  16. CContainerSelectionDlg::CContainerSelectionDlg(CWnd* pParent /*=NULL*/)
  17. : CDialog(CContainerSelectionDlg::IDD, pParent)
  18. {
  19. //{{AFX_DATA_INIT(CContainerSelectionDlg)
  20. m_strCont = _T("");
  21. //}}AFX_DATA_INIT
  22. }
  23. void CContainerSelectionDlg::DoDataExchange(CDataExchange* pDX)
  24. {
  25. CDialog::DoDataExchange(pDX);
  26. //{{AFX_DATA_MAP(CContainerSelectionDlg)
  27. DDX_Control(pDX, IDOK, m_btnOK);
  28. DDX_Control(pDX, IDC_TREE1, m_trOUTree);
  29. DDX_Text(pDX, IDC_EDIT1, m_strCont);
  30. //}}AFX_DATA_MAP
  31. }
  32. BEGIN_MESSAGE_MAP(CContainerSelectionDlg, CDialog)
  33. //{{AFX_MSG_MAP(CContainerSelectionDlg)
  34. ON_BN_CLICKED(IDOK, OnOk)
  35. ON_NOTIFY(TVN_SELCHANGED, IDC_TREE1, OnSelchangedTree1)
  36. ON_NOTIFY(NM_DBLCLK, IDC_TREE1, OnDblclkTree1)
  37. //}}AFX_MSG_MAP
  38. END_MESSAGE_MAP()
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CContainerSelectionDlg message handlers
  41. void CContainerSelectionDlg::OnOk()
  42. {
  43. CDialog::OnOK();
  44. }
  45. BOOL CContainerSelectionDlg::OnInitDialog()
  46. {
  47. CWaitCursor wait;
  48. CDialog::OnInitDialog();
  49. if ( m_strDomain.IsEmpty() )
  50. return TRUE;
  51. LoadImageList();
  52. root = m_trOUTree.InsertItem(m_strDomain, 0, 1);
  53. ExpandCompletely(root, L"");
  54. FindContainer();
  55. return TRUE; // return TRUE unless you set the focus to a control
  56. // EXCEPTION: OCX Property Pages should return FALSE
  57. }
  58. HRESULT CContainerSelectionDlg::PopulateContainer(
  59. HTREEITEM tvItemParent, //in- Item to expand
  60. BSTR sContName, //in- Name of the container.
  61. INetObjEnumeratorPtr pQuery //in- Query Object
  62. )
  63. {
  64. HRESULT hr = E_FAIL;
  65. IEnumVARIANT * pEnum = NULL;
  66. SAFEARRAY * psaCols = NULL;
  67. SAFEARRAYBOUND bd = { 2, 0 };
  68. BSTR pCols[] = { L"name", L"objectClass" };
  69. BSTR HUGEP * pData;
  70. _variant_t var;
  71. DWORD dwFetch = 0;
  72. BSTR domain = m_strDomain.AllocSysString();
  73. SAFEARRAY * psaVals;
  74. _bstr_t sValName;
  75. _bstr_t sType;
  76. _variant_t * pDataVar;
  77. _variant_t varVal;
  78. WCHAR sTempName[255];
  79. int img = 0;
  80. psaCols = SafeArrayCreate(VT_BSTR, 1, &bd);
  81. if ( psaCols )
  82. {
  83. hr = SafeArrayAccessData(psaCols, (void HUGEP **)&pData);
  84. if ( SUCCEEDED(hr) )
  85. {
  86. pData[0] = pCols[0];
  87. pData[1] = pCols[1];
  88. }
  89. SafeArrayUnaccessData(psaCols);
  90. }
  91. if ( SUCCEEDED(hr))
  92. hr = pQuery->raw_SetQuery(sContName, domain, sQuery, ADS_SCOPE_ONELEVEL, FALSE);
  93. if ( SUCCEEDED(hr) )
  94. hr = pQuery->raw_SetColumns(psaCols);
  95. if ( SUCCEEDED(hr))
  96. hr = pQuery->raw_Execute(&pEnum);
  97. if ( pEnum )
  98. {
  99. while ( pEnum->Next(1, &var, &dwFetch) == S_OK )
  100. {
  101. psaVals = V_ARRAY(&var);
  102. hr = SafeArrayAccessData(psaVals, (void**)&pDataVar);
  103. if ( SUCCEEDED(hr) )
  104. {
  105. varVal = pDataVar[0];
  106. if ( varVal.vt == VT_BSTR ) sValName = V_BSTR(&varVal);
  107. varVal = pDataVar[1];
  108. if ( varVal.vt == VT_BSTR ) sType = V_BSTR(&varVal);
  109. SafeArrayUnaccessData(psaVals);
  110. }
  111. if ( SUCCEEDED(hr) )
  112. {
  113. //
  114. if ( wcsicmp(sType, L"organizationalUnit") == 0 )
  115. {
  116. wsprintf(sTempName, L"OU=%s", (WCHAR*)sValName);
  117. img = 4;
  118. }
  119. else
  120. {
  121. wsprintf(sTempName, L"CN=%s", (WCHAR*)sValName);
  122. img = 2;
  123. }
  124. if ( wcsicmp(sTempName, L"CN=System") != 0 )
  125. m_trOUTree.InsertItem(sTempName, img, img+1, tvItemParent);
  126. }
  127. }
  128. }
  129. // Clean up
  130. ::SysFreeString(domain);
  131. if ( pEnum ) pEnum->Release();
  132. VariantInit(&var);
  133. return hr;
  134. }
  135. HRESULT CContainerSelectionDlg::ExpandCompletely(HTREEITEM tvItem, BSTR parentCont)
  136. {
  137. HTREEITEM tvChild;
  138. WCHAR currCont[255];
  139. CString sContName;
  140. HRESULT hr = S_OK;
  141. INetObjEnumeratorPtr pQuery(__uuidof(NetObjEnumerator));
  142. // First populate this container
  143. hr = PopulateContainer( tvItem, parentCont, pQuery);
  144. // Check if it has children. If it does then for each child call this function recursively
  145. if ( m_trOUTree.ItemHasChildren(tvItem) )
  146. {
  147. tvChild = m_trOUTree.GetChildItem(tvItem);
  148. while ( tvChild )
  149. {
  150. // Get the name of the
  151. sContName = m_trOUTree.GetItemText(tvChild);
  152. if ( wcslen(parentCont) > 0 )
  153. wsprintf(currCont, L"%s,%s", sContName, (WCHAR*)parentCont);
  154. else
  155. wcscpy(currCont, sContName.AllocSysString());
  156. ExpandCompletely(tvChild, currCont);
  157. tvChild = m_trOUTree.GetNextSiblingItem(tvChild);
  158. }
  159. }
  160. return hr;
  161. }
  162. BOOL CContainerSelectionDlg::LoadImageList()
  163. {
  164. // set up icon list for list box
  165. // use bitmaps
  166. CBitmap cont;
  167. CBitmap ou;
  168. CBitmap openCont;
  169. CBitmap openOU;
  170. CBitmap dir;
  171. CBitmap dirOpen;
  172. COLORREF cr = 0x000000;
  173. if (
  174. dir.LoadBitmap(IDB_DIR)
  175. && dirOpen.LoadBitmap(IDB_OPEN_DIR)
  176. && cont.LoadBitmap(IDB_CONT)
  177. && ou.LoadBitmap(IDB_OU)
  178. && openCont.LoadBitmap(IDB_OPEN_CONT)
  179. && openOU.LoadBitmap(IDB_OPEN_OU)
  180. )
  181. {
  182. cr = GetFirstBitmapPixel(this,IDB_CONT);
  183. ilist.Create(IDB_DIR, 16, 16, cr);
  184. ilist.Add(&dirOpen, cr);
  185. ilist.Add(&cont,cr);
  186. ilist.Add(&openCont,cr);
  187. ilist.Add(&ou,cr);
  188. ilist.Add(&openOU,cr);
  189. m_trOUTree.SetImageList(&ilist,TVSIL_NORMAL);
  190. }
  191. return TRUE;
  192. }
  193. COLORREF CContainerSelectionDlg::GetFirstBitmapPixel(CWnd * window,UINT idbBitmap)
  194. {
  195. CBitmap bmp;
  196. COLORREF color = 0x00ffffff;
  197. if ( bmp.LoadBitmap(idbBitmap) )
  198. {
  199. // Get Device context
  200. CDC * windowDC = window->GetDC();
  201. HDC hdcImage = ::CreateCompatibleDC(windowDC->m_hDC);
  202. CBitmap * tempBmp = (CBitmap *)::SelectObject(hdcImage,(HBITMAP)bmp);
  203. // now get the pixel
  204. if ( windowDC && hdcImage && tempBmp )
  205. {
  206. color = GetPixel(hdcImage,0, 0);
  207. }
  208. if ( tempBmp )
  209. ::SelectObject(hdcImage,tempBmp);
  210. if ( hdcImage )
  211. ::DeleteObject(hdcImage);
  212. }
  213. return color;
  214. }
  215. void CContainerSelectionDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
  216. {
  217. m_strCont = L"";
  218. HTREEITEM tvSelected, tvParent;
  219. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  220. tvSelected = m_trOUTree.GetSelectedItem();
  221. if ( tvSelected )
  222. {
  223. // We dont want to process the domain name in the Container name so go upto
  224. // the point where we have a parent. i.e. Child of the domain node.
  225. while( tvParent = m_trOUTree.GetParentItem(tvSelected) )
  226. {
  227. // Build the container list by walking up the tree.
  228. if ( m_strCont.IsEmpty() )
  229. m_strCont = m_trOUTree.GetItemText(tvSelected);
  230. else
  231. m_strCont = m_strCont + CString(L",") + m_trOUTree.GetItemText(tvSelected);
  232. tvSelected = tvParent;
  233. }
  234. }
  235. m_btnOK.EnableWindow(!m_strCont.IsEmpty());
  236. UpdateData(FALSE);
  237. *pResult = 0;
  238. }
  239. void CContainerSelectionDlg::OnDblclkTree1(NMHDR* pNMHDR, LRESULT* pResult)
  240. {
  241. UpdateData();
  242. if ( !m_strCont.IsEmpty() )
  243. OnOk();
  244. *pResult = 0;
  245. }
  246. HRESULT CContainerSelectionDlg::FindContainer()
  247. {
  248. CString strName;
  249. int ndx = 0, oldNdx = -1;
  250. // We can find the container iff there is one specified.
  251. if (!m_strCont.IsEmpty())
  252. {
  253. OpenContainer(m_strCont, root);
  254. }
  255. return S_OK;
  256. }
  257. HTREEITEM CContainerSelectionDlg::OpenContainer(CString strCont, HTREEITEM rootSub)
  258. {
  259. int ndx = -1;
  260. CString strLeft, strRight;
  261. HTREEITEM tvItem = NULL;
  262. if ( !strCont.IsEmpty() && rootSub )
  263. {
  264. ndx = strCont.Find(L",", 0);
  265. if ( ndx > -1 )
  266. {
  267. // Get the right side of the comma string and Call this again to open the parent container.
  268. strLeft = strCont.Left(ndx);
  269. strRight = strCont.Mid(ndx + 1);
  270. tvItem = OpenContainer(strRight, rootSub);
  271. tvItem = OpenContainer(strLeft, tvItem);
  272. }
  273. else
  274. {
  275. // We have a container name so lets find it below rootSub node.
  276. tvItem = m_trOUTree.GetChildItem(rootSub);
  277. while (tvItem)
  278. {
  279. if ( m_trOUTree.GetItemText(tvItem) == strCont )
  280. {
  281. //m_trOUTree.Expand(tvItem, 0);
  282. m_trOUTree.Select(tvItem, TVGN_CARET);
  283. break;
  284. }
  285. tvItem = m_trOUTree.GetNextSiblingItem(tvItem);
  286. }
  287. }
  288. }
  289. return tvItem;
  290. }