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.

1948 lines
51 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: Util.cpp
  7. //
  8. // Contents: Utility functions
  9. //
  10. // History: 08-Nov-99 JeffJon Created
  11. //
  12. //
  13. //--------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. #include "util.h"
  16. #include "uiutil.h"
  17. #include "dsutil.h"
  18. #include "dsdlgs.h"
  19. #include "helpids.h"
  20. /////////////////////////////////////////////////////////////////////
  21. // Combo box Utilities
  22. //
  23. int ComboBox_AddString(HWND hwndCombobox, UINT uStringId)
  24. {
  25. ASSERT(IsWindow(hwndCombobox));
  26. CString str;
  27. VERIFY( str.LoadString(uStringId) );
  28. LRESULT i = SendMessage(hwndCombobox, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)str);
  29. Report(i >= 0);
  30. SendMessage(hwndCombobox, CB_SETITEMDATA, (WPARAM)i, uStringId);
  31. return (int)i;
  32. }
  33. void ComboBox_AddStrings(HWND hwndCombobox, const UINT rgzuStringId[])
  34. {
  35. ASSERT(IsWindow(hwndCombobox));
  36. ASSERT(rgzuStringId != NULL);
  37. CString str;
  38. for (const UINT * puStringId = rgzuStringId; *puStringId != 0; puStringId++)
  39. {
  40. VERIFY( str.LoadString(*puStringId) );
  41. LRESULT i = SendMessage(hwndCombobox, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)str);
  42. Report(i >= 0);
  43. SendMessage(hwndCombobox, CB_SETITEMDATA, (WPARAM)i, *puStringId);
  44. }
  45. }
  46. int ComboBox_FindItemByLParam(HWND hwndCombobox, LPARAM lParam)
  47. {
  48. ASSERT(IsWindow(hwndCombobox));
  49. Report(lParam != CB_ERR && "Ambiguous parameter.");
  50. LRESULT iItem = SendMessage(hwndCombobox, CB_GETCOUNT, 0, 0);
  51. ASSERT(iItem >= 0);
  52. while (iItem-- > 0)
  53. {
  54. LRESULT l = SendMessage(hwndCombobox, CB_GETITEMDATA, (WPARAM)iItem, 0);
  55. Report(l != CB_ERR);
  56. if (l == lParam)
  57. {
  58. return ((int)iItem);
  59. }
  60. }
  61. return -1;
  62. }
  63. int ComboBox_SelectItemByLParam(HWND hwndCombobox, LPARAM lParam)
  64. {
  65. ASSERT(IsWindow(hwndCombobox));
  66. int iItem = ComboBox_FindItemByLParam(hwndCombobox, lParam);
  67. if (iItem >= 0)
  68. {
  69. SendMessage(hwndCombobox, CB_SETCURSEL, iItem, 0);
  70. }
  71. return iItem;
  72. }
  73. LPARAM ComboBox_GetSelectedItemLParam(HWND hwndCombobox)
  74. {
  75. LRESULT iItem = SendMessage(hwndCombobox, CB_GETCURSEL, 0, 0);
  76. if (iItem < 0)
  77. {
  78. // No item selected
  79. return NULL;
  80. }
  81. LRESULT lParam = SendMessage(hwndCombobox, CB_GETITEMDATA, (WPARAM)iItem, 0);
  82. if (lParam == CB_ERR)
  83. {
  84. Report(FALSE && "Ambiguous return value.");
  85. return NULL;
  86. }
  87. return (LPARAM)lParam;
  88. }
  89. /////////////////////////////////////////////////////////////////////
  90. // Dialog Utilities
  91. //
  92. HWND HGetDlgItem(HWND hdlg, INT nIdDlgItem)
  93. {
  94. ASSERT(IsWindow(hdlg));
  95. ASSERT(IsWindow(GetDlgItem(hdlg, nIdDlgItem)));
  96. return GetDlgItem(hdlg, nIdDlgItem);
  97. } // HGetDlgItem()
  98. void SetDlgItemFocus(HWND hdlg, INT nIdDlgItem)
  99. {
  100. SetFocus(HGetDlgItem(hdlg, nIdDlgItem));
  101. }
  102. void EnableDlgItem(HWND hdlg, INT nIdDlgItem, BOOL fEnable)
  103. {
  104. EnableWindow(HGetDlgItem(hdlg, nIdDlgItem), fEnable);
  105. }
  106. void HideDlgItem(HWND hdlg, INT nIdDlgItem, BOOL fHideItem)
  107. {
  108. HWND hwndCtl = HGetDlgItem(hdlg, nIdDlgItem);
  109. ShowWindow(hwndCtl, fHideItem ? SW_HIDE : SW_SHOW);
  110. EnableWindow(hwndCtl, !fHideItem);
  111. }
  112. void EnableDlgItemGroup(HWND hdlg, // IN: Parent dialog of the controls
  113. const UINT rgzidCtl[], // IN: Group (array) of control Ids to be enabled (or disabled)
  114. BOOL fEnableAll) // IN: TRUE => We want to enable the controls; FALSE => We want to disable the controls
  115. {
  116. ASSERT(IsWindow(hdlg));
  117. ASSERT(rgzidCtl != NULL);
  118. for (const UINT * pidCtl = rgzidCtl; *pidCtl != 0; pidCtl++)
  119. {
  120. EnableWindow(HGetDlgItem(hdlg, *pidCtl), fEnableAll);
  121. }
  122. } // EnableDlgItemGroup()
  123. void HideDlgItemGroup(HWND hdlg, // IN: Parent dialog of the controls
  124. const UINT rgzidCtl[], // IN: Group (array) of control Ids to be shown (or hidden)
  125. BOOL fHideAll) // IN: TRUE => We want to hide all the controls; FALSE => We want to show all the controls
  126. {
  127. ASSERT(IsWindow(hdlg));
  128. ASSERT(rgzidCtl != NULL);
  129. for (const UINT * pidCtl = rgzidCtl; *pidCtl != 0; pidCtl++)
  130. {
  131. HideDlgItem(hdlg, *pidCtl, fHideAll);
  132. }
  133. } // HideDlgItemGroup()
  134. /////////////////////////////////////////////////////////////////////
  135. // List View Utilities
  136. //
  137. void ListView_AddColumnHeaders(HWND hwndListview, // IN: Handle of the listview we want to add columns
  138. const TColumnHeaderItem rgzColumnHeader[]) // IN: Array of column header items
  139. {
  140. RECT rcClient;
  141. INT cxTotalWidth; // Total width of the listview control
  142. LV_COLUMN lvColumn;
  143. INT cxColumn; // Width of the individual column
  144. CString str;
  145. ASSERT(IsWindow(hwndListview));
  146. ASSERT(rgzColumnHeader != NULL);
  147. GetClientRect(hwndListview, OUT &rcClient);
  148. cxTotalWidth = rcClient.right;
  149. for (INT i = 0; rgzColumnHeader[i].uStringId != 0; i++)
  150. {
  151. if (!str.LoadString(rgzColumnHeader[i].uStringId))
  152. {
  153. TRACE(L"Unable to load string Id=%d\n", rgzColumnHeader[i].uStringId);
  154. ASSERT(FALSE && "String not found");
  155. continue;
  156. }
  157. lvColumn.mask = LVCF_TEXT;
  158. lvColumn.pszText = (LPTSTR)(LPCTSTR)str;
  159. cxColumn = rgzColumnHeader[i].nColWidth;
  160. if (cxColumn > 0)
  161. {
  162. ASSERT(cxColumn <= 100);
  163. cxColumn = (cxTotalWidth * cxColumn) / 100;
  164. lvColumn.mask |= LVCF_WIDTH;
  165. lvColumn.cx = cxColumn;
  166. }
  167. int iColRet = ListView_InsertColumn(hwndListview, i, IN &lvColumn);
  168. Report(iColRet == i);
  169. } // for
  170. } // ListView_AddColumnHeaders()
  171. int ListView_AddString(HWND hwndListview,
  172. const LPCTSTR psz, // IN: String to insert
  173. LPARAM lParam) // IN: User-defined parameter
  174. {
  175. ASSERT(IsWindow(hwndListview));
  176. ASSERT(psz != NULL);
  177. LV_ITEM lvItem;
  178. int iItem;
  179. GarbageInit(&lvItem, sizeof(lvItem));
  180. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  181. lvItem.lParam = lParam;
  182. lvItem.iSubItem = 0;
  183. lvItem.pszText = const_cast<LPTSTR>(psz);
  184. iItem = ListView_InsertItem(hwndListview, IN &lvItem);
  185. Report(iItem >= 0);
  186. return iItem;
  187. } // ListView_AddString()
  188. int ListView_AddStrings(HWND hwndListview,
  189. const LPCTSTR rgzpsz[], // IN: Array of strings
  190. LPARAM lParam) // IN: User-defined parameter
  191. {
  192. ASSERT(IsWindow(hwndListview));
  193. ASSERT(rgzpsz != NULL);
  194. LV_ITEM lvItem;
  195. int iItem;
  196. GarbageInit(&lvItem, sizeof(lvItem));
  197. lvItem.mask = LVIF_TEXT | LVIF_PARAM;
  198. lvItem.lParam = lParam;
  199. lvItem.iSubItem = 0;
  200. lvItem.pszText = const_cast<LPTSTR>(rgzpsz[0]);
  201. iItem = ListView_InsertItem(hwndListview, IN &lvItem);
  202. Report(iItem >= 0);
  203. if (rgzpsz[0] == NULL)
  204. {
  205. return iItem;
  206. }
  207. lvItem.iItem = iItem;
  208. lvItem.mask = LVIF_TEXT;
  209. for (lvItem.iSubItem = 1 ; rgzpsz[lvItem.iSubItem] != NULL; lvItem.iSubItem++)
  210. {
  211. lvItem.pszText = const_cast<LPTSTR>(rgzpsz[lvItem.iSubItem]);
  212. VERIFY( ListView_SetItem(hwndListview, IN &lvItem) );
  213. }
  214. return iItem;
  215. } // ListView_AddStrings()
  216. void ListView_SelectItem(HWND hwndListview,
  217. int iItem)
  218. {
  219. ASSERT(IsWindow(hwndListview));
  220. ASSERT(iItem >= 0);
  221. ListView_SetItemState(hwndListview, iItem, LVIS_SELECTED, LVIS_SELECTED);
  222. } // ListView_SelectItem()
  223. int ListView_GetSelectedItem(HWND hwndListview)
  224. {
  225. ASSERT(IsWindow(hwndListview));
  226. return ListView_GetNextItem(hwndListview, -1, LVNI_SELECTED);
  227. }
  228. void ListView_SetItemString(HWND hwndListview,
  229. int iItem,
  230. int iSubItem,
  231. IN const CString& rstrText)
  232. {
  233. ASSERT(IsWindow(hwndListview));
  234. ASSERT(iItem >= 0);
  235. ASSERT(iSubItem >= 0);
  236. ListView_SetItemText(hwndListview, iItem, iSubItem,
  237. const_cast<LPTSTR>((LPCTSTR)rstrText));
  238. } // ListView_SetItemString()
  239. int ListView_GetItemString(HWND hwndListview,
  240. int iItem,
  241. int iSubItem,
  242. OUT CString& rstrText)
  243. {
  244. ASSERT(IsWindow(hwndListview));
  245. if (iItem == -1)
  246. {
  247. // Find out the selected item
  248. iItem = ListView_GetSelectedItem(hwndListview);
  249. if (iItem == -1)
  250. {
  251. // No item selected
  252. rstrText.Empty();
  253. return -1;
  254. }
  255. }
  256. ASSERT(iItem >= 0);
  257. const int cchBuffer = 1024; // Initial buffer
  258. TCHAR * psz = rstrText.GetBuffer(cchBuffer);
  259. ASSERT(psz != NULL);
  260. *psz = '\0';
  261. ListView_GetItemText(hwndListview, iItem, iSubItem, OUT psz, cchBuffer-1);
  262. rstrText.ReleaseBuffer();
  263. Report((rstrText.GetLength() < cchBuffer - 16) && "Buffer too small to hold entire string");
  264. rstrText.FreeExtra();
  265. return iItem;
  266. } // ListView_GetItemString()
  267. LPARAM ListView_GetItemLParam(HWND hwndListview,
  268. int iItem,
  269. int * piItem) // OUT: OPTIONAL: Pointer to the index of the listview item
  270. {
  271. ASSERT(IsWindow(hwndListview));
  272. Endorse(piItem == NULL); // TRUE => Don't care about the index
  273. if (iItem == -1)
  274. {
  275. // Find out the selected item
  276. iItem = ListView_GetSelectedItem(hwndListview);
  277. if (iItem == -1)
  278. {
  279. // No item selected
  280. if (piItem != NULL)
  281. {
  282. *piItem = -1;
  283. }
  284. return NULL;
  285. }
  286. }
  287. ASSERT(iItem >= 0);
  288. if (piItem != NULL)
  289. {
  290. *piItem = iItem;
  291. }
  292. LV_ITEM lvItem;
  293. GarbageInit(&lvItem, sizeof(lvItem));
  294. lvItem.mask = LVIF_PARAM;
  295. lvItem.iItem = iItem;
  296. lvItem.iSubItem = 0;
  297. lvItem.lParam = 0; // Just in case
  298. VERIFY(ListView_GetItem(hwndListview, OUT &lvItem));
  299. return lvItem.lParam;
  300. } // ListView_GetItemLParam()
  301. int ListView_FindString(HWND hwndListview,
  302. LPCTSTR pszTextSearch)
  303. {
  304. ASSERT(IsWindow(hwndListview));
  305. ASSERT(pszTextSearch != NULL);
  306. LV_FINDINFO lvFindInfo;
  307. GarbageInit(&lvFindInfo, sizeof(lvFindInfo));
  308. lvFindInfo.flags = LVFI_STRING;
  309. lvFindInfo.psz = pszTextSearch;
  310. return ListView_FindItem(hwndListview, -1, &lvFindInfo);
  311. } // ListView_FindString()
  312. int ListView_FindLParam(HWND hwndListview,
  313. LPARAM lParam)
  314. {
  315. ASSERT(IsWindow(hwndListview));
  316. LV_FINDINFO lvFindInfo;
  317. GarbageInit(&lvFindInfo, sizeof(lvFindInfo));
  318. lvFindInfo.flags = LVFI_PARAM;
  319. lvFindInfo.lParam = lParam;
  320. return ListView_FindItem(hwndListview, -1, &lvFindInfo);
  321. } // ListView_FindLParam()
  322. int ListView_SelectLParam(HWND hwndListview,
  323. LPARAM lParam)
  324. {
  325. int iItem = ListView_FindLParam(hwndListview, lParam);
  326. if (iItem >= 0)
  327. {
  328. ListView_SelectItem(hwndListview, iItem);
  329. }
  330. else
  331. {
  332. TRACE2("ListView_SelectLParam() - Unable to find lParam=%x (%d).\n",
  333. lParam, lParam);
  334. }
  335. return iItem;
  336. } // ListView_SelectLParam()
  337. ////////////////////////////////////////////////////////////////////////////
  338. // CMultiselectErrorDialog
  339. BEGIN_MESSAGE_MAP(CMultiselectErrorDialog, CDialog)
  340. END_MESSAGE_MAP()
  341. HRESULT CMultiselectErrorDialog::Initialize(CUINode** ppNodeArray,
  342. PWSTR* pErrorArray,
  343. UINT nErrorCount,
  344. PCWSTR pszTitle,
  345. PCWSTR pszCaption,
  346. PCWSTR pszColumnHeader)
  347. {
  348. ASSERT(ppNodeArray != NULL);
  349. ASSERT(pErrorArray != NULL);
  350. ASSERT(pszTitle != NULL);
  351. ASSERT(pszCaption != NULL);
  352. ASSERT(pszColumnHeader != NULL);
  353. if (ppNodeArray == NULL ||
  354. pErrorArray == NULL ||
  355. pszTitle == NULL ||
  356. pszCaption == NULL ||
  357. pszColumnHeader == NULL)
  358. {
  359. return E_POINTER;
  360. }
  361. m_ppNodeList = ppNodeArray;
  362. m_pErrorArray = pErrorArray;
  363. m_nErrorCount = nErrorCount;
  364. m_szTitle = pszTitle;
  365. m_szCaption = pszCaption;
  366. m_szColumnHeader = pszColumnHeader;
  367. return S_OK;
  368. }
  369. HRESULT CMultiselectErrorDialog::Initialize(PWSTR* pPathArray,
  370. PWSTR* pClassArray,
  371. PWSTR* pErrorArray,
  372. UINT nErrorCount,
  373. PCWSTR pszTitle,
  374. PCWSTR pszCaption,
  375. PCWSTR pszColumnHeader)
  376. {
  377. ASSERT(pPathArray != NULL);
  378. ASSERT(pClassArray != NULL);
  379. ASSERT(pErrorArray != NULL);
  380. ASSERT(pszTitle != NULL);
  381. ASSERT(pszCaption != NULL);
  382. ASSERT(pszColumnHeader != NULL);
  383. if (pPathArray == NULL ||
  384. pClassArray == NULL ||
  385. pErrorArray == NULL ||
  386. pszTitle == NULL ||
  387. pszCaption == NULL ||
  388. pszColumnHeader == NULL)
  389. {
  390. return E_POINTER;
  391. }
  392. m_pPathArray = pPathArray;
  393. m_pClassArray = pClassArray;
  394. m_pErrorArray = pErrorArray;
  395. m_nErrorCount = nErrorCount;
  396. m_szTitle = pszTitle;
  397. m_szCaption = pszCaption;
  398. m_szColumnHeader = pszColumnHeader;
  399. return S_OK;
  400. }
  401. const int OBJ_LIST_NAME_COL_WIDTH = 100;
  402. const int IDX_NAME_COL = 0;
  403. const int IDX_ERR_COL = 1;
  404. BOOL CMultiselectErrorDialog::OnInitDialog()
  405. {
  406. CDialog::OnInitDialog();
  407. SetWindowText(m_szTitle);
  408. SetDlgItemText(IDC_STATIC_MESSAGE, m_szCaption);
  409. HWND hList = GetDlgItem(IDC_ERROR_LIST)->GetSafeHwnd();
  410. ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT);
  411. //
  412. // Create the image list
  413. //
  414. m_hImageList = ImageList_Create(16, 16, ILC_COLOR | ILC_MASK, 1, 1);
  415. ASSERT(m_hImageList != NULL);
  416. if (m_hImageList != NULL)
  417. {
  418. ListView_SetImageList(hList, m_hImageList, LVSIL_SMALL);
  419. }
  420. //
  421. // Set the column headings.
  422. //
  423. RECT rect;
  424. ::GetClientRect(hList, &rect);
  425. LV_COLUMN lvc = {0};
  426. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  427. lvc.fmt = LVCFMT_LEFT;
  428. lvc.cx = OBJ_LIST_NAME_COL_WIDTH;
  429. lvc.pszText = (PWSTR)(PCWSTR)m_szColumnHeader;
  430. lvc.iSubItem = IDX_NAME_COL;
  431. ListView_InsertColumn(hList, IDX_NAME_COL, &lvc);
  432. CString szError;
  433. VERIFY(szError.LoadString(IDS_ERROR));
  434. lvc.cx = rect.right - OBJ_LIST_NAME_COL_WIDTH;
  435. lvc.pszText = (PWSTR)(PCWSTR)szError;
  436. lvc.iSubItem = IDX_ERR_COL;
  437. ListView_InsertColumn(hList, IDX_ERR_COL, &lvc);
  438. //
  439. // Insert the errors
  440. //
  441. //
  442. // Use the node list if its not NULL
  443. //
  444. if (m_ppNodeList != NULL)
  445. {
  446. ASSERT(m_pErrorArray != NULL && m_ppNodeList != NULL);
  447. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  448. {
  449. CUINode* pNode = m_ppNodeList[nIdx];
  450. if (pNode != NULL)
  451. {
  452. if (nIdx < m_nErrorCount && m_pErrorArray[nIdx])
  453. {
  454. //
  455. // Create the list view item
  456. //
  457. LV_ITEM lvi = {0};
  458. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  459. lvi.iSubItem = IDX_NAME_COL;
  460. lvi.lParam = (LPARAM)pNode->GetName();
  461. lvi.pszText = (PWSTR)pNode->GetName();
  462. lvi.iItem = nIdx;
  463. if (m_hImageList != NULL)
  464. {
  465. //
  466. // REVIEW_JEFFJON : this will add multiple icons of the same class
  467. // need to provide a better means for managing the icons
  468. //
  469. CDSCookie* pCookie = GetDSCookieFromUINode(pNode);
  470. if (pCookie != NULL)
  471. {
  472. HICON icon = m_pComponentData->GetBasePathsInfo()->GetIcon(
  473. // someone really blew it with const correctness...
  474. const_cast<LPTSTR>(pCookie->GetClass()),
  475. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON,
  476. 16,
  477. 16);
  478. int i = ::ImageList_AddIcon(m_hImageList, icon);
  479. ASSERT(i != -1);
  480. if (i != -1)
  481. {
  482. lvi.mask |= LVIF_IMAGE;
  483. lvi.iImage = i;
  484. }
  485. }
  486. }
  487. //
  488. // Insert the new item
  489. //
  490. int NewIndex = ListView_InsertItem(hList, &lvi);
  491. ASSERT(NewIndex != -1);
  492. if (NewIndex == -1)
  493. {
  494. continue;
  495. }
  496. // Add the error message
  497. ListView_SetItemText(hList, NewIndex, IDX_ERR_COL, m_pErrorArray[nIdx]);
  498. }
  499. }
  500. }
  501. }
  502. else if (m_pPathArray != NULL) // if the node list is NULL then use the string list
  503. {
  504. ASSERT(m_pErrorArray != NULL && m_pPathArray != NULL);
  505. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  506. {
  507. if (nIdx < m_nErrorCount && m_pErrorArray[nIdx])
  508. {
  509. //
  510. // Use the path cracker to retrieve the name of the object
  511. //
  512. PCWSTR pszPath = m_pPathArray[nIdx];
  513. CPathCracker pathCracker;
  514. VERIFY(SUCCEEDED(pathCracker.Set(CComBSTR(pszPath), ADS_SETTYPE_DN)));
  515. VERIFY(SUCCEEDED(pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX)));
  516. VERIFY(SUCCEEDED(pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY)));
  517. CComBSTR bstrName;
  518. VERIFY(SUCCEEDED(pathCracker.GetElement(0, &bstrName)));
  519. //
  520. // Create the list view item
  521. //
  522. LV_ITEM lvi = {0};
  523. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  524. lvi.iSubItem = IDX_NAME_COL;
  525. //
  526. // Make the LPARAM be the path to the object
  527. // Not used at this time but may be useful in
  528. // the future for bringing up property pages or
  529. // other special features.
  530. //
  531. lvi.lParam = (LPARAM)m_pPathArray[nIdx];
  532. lvi.pszText = (PWSTR)bstrName;
  533. lvi.iItem = nIdx;
  534. if (m_hImageList != NULL)
  535. {
  536. //
  537. // REVIEW_JEFFJON : this will add multiple icons of the same class
  538. // need to provide a better means for managing the icons
  539. //
  540. ASSERT(m_pClassArray[nIdx] != NULL);
  541. HICON icon = m_pComponentData->GetBasePathsInfo()->GetIcon(
  542. // someone really blew it with const correctness...
  543. const_cast<LPTSTR>(m_pClassArray[nIdx]),
  544. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON,
  545. 16,
  546. 16);
  547. int i = ::ImageList_AddIcon(m_hImageList, icon);
  548. ASSERT(i != -1);
  549. if (i != -1)
  550. {
  551. lvi.mask |= LVIF_IMAGE;
  552. lvi.iImage = i;
  553. }
  554. }
  555. //
  556. // Insert the new item
  557. //
  558. int NewIndex = ListView_InsertItem(hList, &lvi);
  559. ASSERT(NewIndex != -1);
  560. if (NewIndex == -1)
  561. {
  562. continue;
  563. }
  564. //
  565. // Set the error message
  566. //
  567. ListView_SetItemText(hList, NewIndex, IDX_ERR_COL, m_pErrorArray[nIdx]);
  568. }
  569. }
  570. }
  571. UpdateListboxHorizontalExtent();
  572. return TRUE;
  573. }
  574. void CMultiselectErrorDialog::UpdateListboxHorizontalExtent()
  575. {
  576. CListCtrl* pListView = reinterpret_cast<CListCtrl*>(GetDlgItem(IDC_ERROR_LIST));
  577. pListView->SetColumnWidth(IDX_ERR_COL, LVSCW_AUTOSIZE);
  578. }
  579. /////////////////////////////////////////////////////////////////////
  580. // MFC Utilities
  581. //
  582. // CDialogEx
  583. //
  584. CDialogEx::CDialogEx(UINT nIDTemplate, CWnd * pParentWnd) : CDialog(nIDTemplate, pParentWnd)
  585. {
  586. }
  587. HWND CDialogEx::HGetDlgItem(INT nIdDlgItem)
  588. {
  589. return ::HGetDlgItem(m_hWnd, nIdDlgItem);
  590. }
  591. void CDialogEx::SetDlgItemFocus(INT nIdDlgItem)
  592. {
  593. ::SetDlgItemFocus(m_hWnd, nIdDlgItem);
  594. }
  595. void CDialogEx::EnableDlgItem(INT nIdDlgItem, BOOL fEnable)
  596. {
  597. ::EnableDlgItem(m_hWnd, nIdDlgItem, fEnable);
  598. }
  599. void CDialogEx::HideDlgItem(INT nIdDlgItem, BOOL fHideItem)
  600. {
  601. ::HideDlgItem(m_hWnd, nIdDlgItem, fHideItem);
  602. }
  603. /////////////////////////////////////////////////////////////////////////////////////
  604. // CPropertyPageEx_Mine
  605. //
  606. CPropertyPageEx_Mine::CPropertyPageEx_Mine(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
  607. {
  608. }
  609. HWND CPropertyPageEx_Mine::HGetDlgItem(INT nIdDlgItem)
  610. {
  611. return ::HGetDlgItem(m_hWnd, nIdDlgItem);
  612. }
  613. void CPropertyPageEx_Mine::SetDlgItemFocus(INT nIdDlgItem)
  614. {
  615. ::SetDlgItemFocus(m_hWnd, nIdDlgItem);
  616. }
  617. void CPropertyPageEx_Mine::EnableDlgItem(INT nIdDlgItem, BOOL fEnable)
  618. {
  619. ::EnableDlgItem(m_hWnd, nIdDlgItem, fEnable);
  620. }
  621. void CPropertyPageEx_Mine::HideDlgItem(INT nIdDlgItem, BOOL fHideItem)
  622. {
  623. ::HideDlgItem(m_hWnd, nIdDlgItem, fHideItem);
  624. }
  625. /////////////////////////////////////////////////////////////////////////////
  626. // CProgressDialogBase
  627. UINT CProgressDialogBase::s_nNextStepMessage = WM_USER + 100;
  628. CProgressDialogBase::CProgressDialogBase(HWND hParentWnd)
  629. : CDialog(IDD_PROGRESS, CWnd::FromHandle(hParentWnd))
  630. {
  631. m_nSteps = 0;
  632. m_nCurrStep = 0;
  633. m_nTitleStringID = 0;
  634. }
  635. BEGIN_MESSAGE_MAP(CProgressDialogBase, CDialog)
  636. ON_WM_SHOWWINDOW()
  637. ON_WM_CLOSE()
  638. ON_MESSAGE(CProgressDialogBase::s_nNextStepMessage, OnNextStepMessage )
  639. END_MESSAGE_MAP()
  640. BOOL CProgressDialogBase::OnInitDialog()
  641. {
  642. CDialog::OnInitDialog();
  643. m_progressCtrl.SubclassDlgItem(IDC_PROG_BAR, this);
  644. if (m_nTitleStringID >0)
  645. {
  646. CString szTitle;
  647. if (szTitle.LoadString(m_nTitleStringID))
  648. SetWindowText(szTitle);
  649. }
  650. GetDlgItemText(IDC_PROG_STATIC, m_szProgressFormat);
  651. SetDlgItemText(IDC_PROG_STATIC, NULL);
  652. OnStart();
  653. ASSERT(m_nSteps > 0);
  654. if (m_nSteps == 0)
  655. PostMessage(WM_CLOSE);
  656. #if _MFC_VER >= 0x0600
  657. m_progressCtrl.SetRange32(0, m_nSteps);
  658. #else
  659. m_progressCtrl.SetRange(0, m_nSteps);
  660. #endif
  661. //
  662. // We want to walk backwards through the list for UI performance reasons
  663. //
  664. m_nCurrStep = m_nSteps - 1;
  665. return TRUE; // return TRUE unless you set the focus to a control
  666. // EXCEPTION: OCX Property Pages should return FALSE
  667. }
  668. void CProgressDialogBase::OnShowWindow(BOOL bShow, UINT nStatus)
  669. {
  670. CDialog::OnShowWindow(bShow, nStatus);
  671. // kick the process
  672. if (bShow && (m_nSteps > 0) && (m_nCurrStep == m_nSteps - 1))
  673. {
  674. m_bDone = FALSE;
  675. PostMessage(s_nNextStepMessage);
  676. }
  677. }
  678. void CProgressDialogBase::OnClose()
  679. {
  680. OnEnd();
  681. CDialog::OnClose();
  682. }
  683. afx_msg LONG CProgressDialogBase::OnNextStepMessage( WPARAM, LPARAM)
  684. {
  685. ASSERT(!m_bDone);
  686. BOOL bExit = FALSE;
  687. if (m_nCurrStep > 0)
  688. {
  689. m_progressCtrl.OffsetPos(1);
  690. _SetProgressText();
  691. if (!OnStep(m_nCurrStep--))
  692. bExit = TRUE; // aborted by user
  693. }
  694. else if (m_nCurrStep == 0)
  695. {
  696. m_progressCtrl.OffsetPos(1);
  697. _SetProgressText();
  698. OnStep(m_nCurrStep--);
  699. bExit = TRUE;
  700. m_bDone = TRUE;
  701. }
  702. else
  703. {
  704. bExit = TRUE;
  705. m_bDone = TRUE;
  706. }
  707. if (bExit)
  708. {
  709. PostMessage(WM_CLOSE);
  710. }
  711. else
  712. {
  713. MSG tempMSG;
  714. while(::PeekMessage(&tempMSG,NULL, 0, 0, PM_REMOVE))
  715. {
  716. DispatchMessage(&tempMSG);
  717. }
  718. PostMessage(s_nNextStepMessage);
  719. }
  720. return 0;
  721. }
  722. void CProgressDialogBase::_SetProgressText()
  723. {
  724. CString szMessage;
  725. WCHAR szCurrStep[128], szMaxSteps[128];
  726. wsprintf(szCurrStep, L"%d",(m_nSteps - m_nCurrStep));
  727. wsprintf(szMaxSteps, L"%d",m_nSteps);
  728. //NTRAID#NTBUG9-571997-2002/03/10-jmessec szMessage.FormatString may throw an exception, which isn't being caught...
  729. // might be appropriate behavior if caller is aware; possible memory leak with szMessage?
  730. szMessage.FormatMessage(m_szProgressFormat, szCurrStep, szMaxSteps);
  731. SetDlgItemText(IDC_PROG_STATIC, szMessage);
  732. }
  733. ////////////////////////////////////////////////////////////////////////////
  734. // CMultipleProgressDialogBase
  735. //
  736. CMultipleProgressDialogBase::~CMultipleProgressDialogBase()
  737. {
  738. //
  739. // Delete the error reporting structures
  740. //
  741. if (m_pErrorArray != NULL)
  742. {
  743. for (UINT nIdx = 0; nIdx < m_nErrorCount; ++nIdx)
  744. {
  745. if (m_pErrorArray[nIdx])
  746. {
  747. delete[] m_pErrorArray[nIdx];
  748. }
  749. }
  750. delete[] m_pErrorArray;
  751. m_pErrorArray = 0;
  752. }
  753. if (m_pPathArray != NULL)
  754. {
  755. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  756. {
  757. if (m_pPathArray[nIdx] != NULL)
  758. {
  759. delete[] m_pPathArray[nIdx];
  760. }
  761. }
  762. delete[] m_pPathArray;
  763. m_pPathArray = NULL;
  764. }
  765. if (m_pClassArray != NULL)
  766. {
  767. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  768. {
  769. if (m_pClassArray[nIdx] != NULL)
  770. {
  771. delete[] m_pClassArray[nIdx];
  772. }
  773. }
  774. delete[] m_pClassArray;
  775. m_pClassArray = NULL;
  776. }
  777. }
  778. HRESULT CMultipleProgressDialogBase::AddError(PCWSTR pszError,
  779. PCWSTR pszPath,
  780. PCWSTR pszClass)
  781. {
  782. //
  783. // Prepare the multiselect error handling structures if necessary
  784. //
  785. if (m_pErrorArray == NULL)
  786. {
  787. m_pErrorArray = new PWSTR[GetStepCount()];
  788. if (m_pErrorArray)
  789. {
  790. ZeroMemory(m_pErrorArray, sizeof(PWSTR) * GetStepCount());
  791. }
  792. }
  793. if (m_pPathArray == NULL)
  794. {
  795. m_pPathArray = new PWSTR[GetStepCount()];
  796. if (m_pPathArray)
  797. {
  798. ZeroMemory(m_pPathArray, sizeof(PWSTR) * GetStepCount());
  799. }
  800. }
  801. if (m_pClassArray == NULL)
  802. {
  803. m_pClassArray = new PWSTR[GetStepCount()];
  804. if (m_pClassArray)
  805. {
  806. ZeroMemory(m_pClassArray, sizeof(PWSTR) * GetStepCount());
  807. }
  808. }
  809. if (m_pErrorArray == NULL ||
  810. m_pPathArray == NULL ||
  811. m_pClassArray == NULL)
  812. {
  813. return E_OUTOFMEMORY;
  814. }
  815. m_pErrorArray[m_nErrorCount] = new WCHAR[wcslen(pszError) + 1];
  816. if (m_pErrorArray[m_nErrorCount] == NULL)
  817. {
  818. return E_OUTOFMEMORY;
  819. }
  820. wcscpy(m_pErrorArray[m_nErrorCount], pszError);
  821. m_pPathArray[m_nErrorCount] = new WCHAR[wcslen(pszPath) + 1];
  822. if (m_pPathArray[m_nErrorCount] == NULL)
  823. {
  824. return E_OUTOFMEMORY;
  825. }
  826. wcscpy(m_pPathArray[m_nErrorCount], pszPath);
  827. m_pClassArray[m_nErrorCount] = new WCHAR[wcslen(pszClass) + 1];
  828. if (m_pClassArray[m_nErrorCount] == NULL)
  829. {
  830. return E_OUTOFMEMORY;
  831. }
  832. wcscpy(m_pClassArray[m_nErrorCount], pszClass);
  833. m_nErrorCount++;
  834. return S_OK;
  835. }
  836. void CMultipleProgressDialogBase::OnEnd()
  837. {
  838. if (m_nErrorCount > 0)
  839. {
  840. if (m_pComponentData != NULL)
  841. {
  842. ASSERT(m_pPathArray != NULL);
  843. ASSERT(m_pClassArray != NULL);
  844. ASSERT(m_pErrorArray != NULL);
  845. CString szTitle;
  846. if (m_pComponentData->QuerySnapinType() == SNAPINTYPE_SITE)
  847. {
  848. VERIFY(szTitle.LoadString(IDS_SITESNAPINNAME));
  849. }
  850. else
  851. {
  852. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  853. }
  854. CString szHeader;
  855. VERIFY(szHeader.LoadString(IDS_COLUMN_NAME));
  856. CString szCaption;
  857. GetCaptionString(szCaption);
  858. //
  859. // Initialize and show the multiselect error dialog
  860. //
  861. CThemeContextActivator activator;
  862. CMultiselectErrorDialog errorDlg(m_pComponentData);
  863. HRESULT hr = errorDlg.Initialize(m_pPathArray,
  864. m_pClassArray,
  865. m_pErrorArray,
  866. m_nErrorCount,
  867. szTitle,
  868. szCaption,
  869. szHeader);
  870. ASSERT(SUCCEEDED(hr));
  871. errorDlg.DoModal();
  872. }
  873. else
  874. {
  875. ASSERT(m_pComponentData != NULL);
  876. }
  877. }
  878. else
  879. {
  880. m_pComponentData->InvalidateSavedQueriesContainingObjects(m_szObjPathList);
  881. }
  882. }
  883. ////////////////////////////////////////////////////////////////////////////
  884. // CMultipleDeleteProgressDialog
  885. //
  886. void CMultipleDeleteProgressDialog::OnStart()
  887. {
  888. SetStepCount(m_pDeleteHandler->GetItemCount());
  889. m_hWndOld = m_pDeleteHandler->GetParentHwnd();
  890. m_pDeleteHandler->SetParentHwnd(GetSafeHwnd());
  891. m_pDeleteHandler->m_confirmationUI.SetWindow(GetSafeHwnd());
  892. }
  893. BOOL CMultipleDeleteProgressDialog::OnStep(UINT i)
  894. {
  895. BOOL bContinue = TRUE;
  896. CString szPath;
  897. CString szClass;
  898. HRESULT hr = m_pDeleteHandler->OnDeleteStep(i,
  899. &bContinue,
  900. szPath,
  901. szClass,
  902. TRUE /*silent*/);
  903. if (FAILED(hr) && hr != E_FAIL)
  904. {
  905. PWSTR pszErrMessage = 0;
  906. int iChar = cchLoadHrMsg(hr, &pszErrMessage, TRUE);
  907. if (pszErrMessage != NULL && iChar > 0)
  908. {
  909. //
  910. // this is a hack to get rid of two extra characters
  911. // at the end of the error message
  912. //
  913. size_t iLen = wcslen(pszErrMessage);
  914. pszErrMessage[iLen - 2] = L'\0';
  915. AddError(pszErrMessage, szPath, szClass);
  916. LocalFree(pszErrMessage);
  917. }
  918. }
  919. m_szObjPathList.AddTail(szPath);
  920. return bContinue;
  921. }
  922. void CMultipleDeleteProgressDialog::OnEnd()
  923. {
  924. CMultipleProgressDialogBase::OnEnd();
  925. m_pDeleteHandler->GetTransaction()->End();
  926. m_pDeleteHandler->SetParentHwnd(m_hWndOld);
  927. m_pDeleteHandler->m_confirmationUI.SetWindow(m_hWndOld);
  928. }
  929. /////////////////////////////////////////////////////////////////////////////
  930. // CMultipleMoveProgressDialog
  931. //
  932. void CMultipleMoveProgressDialog::OnStart()
  933. {
  934. SetStepCount(m_pMoveHandler->GetItemCount());
  935. m_hWndOld = m_pMoveHandler->GetParentHwnd();
  936. m_pMoveHandler->SetParentHwnd(GetSafeHwnd());
  937. }
  938. BOOL CMultipleMoveProgressDialog::OnStep(UINT i)
  939. {
  940. BOOL bContinue = TRUE;
  941. CString szPath;
  942. CString szClass;
  943. HRESULT hr = m_pMoveHandler->_OnMoveStep(i,
  944. &bContinue,
  945. szPath,
  946. szClass);
  947. if (FAILED(hr) && hr != E_FAIL && hr != E_POINTER)
  948. {
  949. PWSTR pszErrMessage = 0;
  950. int iChar = cchLoadHrMsg(hr, &pszErrMessage, TRUE);
  951. if (pszErrMessage != NULL && iChar > 0)
  952. {
  953. //
  954. // this is a hack to get rid of two extra characters
  955. // at the end of the error message
  956. //
  957. size_t iLen = wcslen(pszErrMessage);
  958. pszErrMessage[iLen - 2] = L'\0';
  959. AddError(pszErrMessage, szPath, szClass);
  960. LocalFree(pszErrMessage);
  961. }
  962. }
  963. m_szObjPathList.AddTail(szPath);
  964. return bContinue;
  965. }
  966. void CMultipleMoveProgressDialog::OnEnd()
  967. {
  968. CMultipleProgressDialogBase::OnEnd();
  969. m_pMoveHandler->GetTransaction()->End();
  970. m_pMoveHandler->SetParentHwnd(m_hWndOld);
  971. }
  972. /////////////////////////////////////////////////////////////////////////////
  973. // CConfirmOperationDialog
  974. //
  975. void CConfirmOperationDialog::OnYes()
  976. {
  977. m_pTransaction->ReadFromCheckListBox(&m_extensionsList);
  978. EndDialog(IDYES);
  979. }
  980. /////////////////////////////////////////////////////////////////////////////
  981. // CConfirmOperationDialog
  982. //
  983. CConfirmOperationDialog::CConfirmOperationDialog(HWND hParentWnd,
  984. CDSNotifyHandlerTransaction* pTransaction)
  985. : CDialog(IDD_CONFIRM_OPERATION_EXT, CWnd::FromHandle(hParentWnd))
  986. {
  987. ASSERT(pTransaction != NULL);
  988. m_pTransaction = pTransaction;
  989. m_nTitleStringID = IDS_ERRMSG_TITLE;
  990. }
  991. BEGIN_MESSAGE_MAP(CConfirmOperationDialog, CDialog)
  992. ON_BN_CLICKED(IDYES, OnYes)
  993. ON_BN_CLICKED(IDNO, OnNo)
  994. END_MESSAGE_MAP()
  995. BOOL CConfirmOperationDialog::OnInitDialog()
  996. {
  997. CDialog::OnInitDialog();
  998. m_extensionsList.SubclassDlgItem(IDC_EXTENS_LIST, this);
  999. m_extensionsList.SetCheckStyle(BS_AUTOCHECKBOX);
  1000. m_pTransaction->SetCheckListBox(&m_extensionsList);
  1001. UpdateListBoxHorizontalExtent();
  1002. if (m_nTitleStringID > 0)
  1003. {
  1004. CString szTitle;
  1005. if (szTitle.LoadString(m_nTitleStringID))
  1006. SetWindowText(szTitle);
  1007. }
  1008. SetDlgItemText(IDC_STATIC_OPERATION, m_lpszOperation);
  1009. SetDlgItemText(IDC_STATIC_ASSOC_DATA, m_lpszAssocData);
  1010. GetDlgItem(IDNO)->SetFocus();
  1011. return FALSE; // we set focus
  1012. }
  1013. void CConfirmOperationDialog::UpdateListBoxHorizontalExtent()
  1014. {
  1015. int nHorzExtent = 0;
  1016. CClientDC dc(&m_extensionsList);
  1017. int nItems = m_extensionsList.GetCount();
  1018. for (int i=0; i < nItems; i++)
  1019. {
  1020. TEXTMETRIC tm;
  1021. VERIFY(dc.GetTextMetrics(&tm));
  1022. CString szBuffer;
  1023. m_extensionsList.GetText(i, szBuffer);
  1024. CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength());
  1025. nHorzExtent = max(ext.cx ,nHorzExtent);
  1026. }
  1027. m_extensionsList.SetHorizontalExtent(nHorzExtent);
  1028. }
  1029. ////////////////////////////////////////////////////////////////////////////////
  1030. // Message reporting and message boxes
  1031. //
  1032. //+----------------------------------------------------------------------------
  1033. //
  1034. // Function: ReportError
  1035. //
  1036. // Sysnopsis: Attempts to get a user-friendly error message from the system.
  1037. //
  1038. // CODEWORK: If called with hr == 0 (hrFallback case), this will generate
  1039. // ptzSysMsg unnecessarily.
  1040. //
  1041. //-----------------------------------------------------------------------------
  1042. void ReportError(HRESULT hr, int nStr, HWND hWnd)
  1043. {
  1044. CThemeContextActivator activator;
  1045. TCHAR tzSysMsgBuf[255];
  1046. TRACE (_T("*+*+* ReportError called with hr = %lx, nStr = %lx"), hr, nStr);
  1047. if (S_OK == hr && 0 == nStr)
  1048. {
  1049. nStr = IDS_ERRMSG_DEFAULT_TEXT;
  1050. }
  1051. PTSTR ptzSysMsg = NULL;
  1052. BOOL fDelSysMsg = TRUE;
  1053. int cch = cchLoadHrMsg( hr, &ptzSysMsg, FALSE );
  1054. if (!cch)
  1055. {
  1056. PTSTR ptzFallbackSysMsgFormat = NULL;
  1057. BOOL fDelFallbackSysMsgFormat = TRUE;
  1058. LoadStringToTchar(IDS_ERRMSG_FALLBACK_TEXT, &ptzFallbackSysMsgFormat);
  1059. if (NULL == ptzFallbackSysMsgFormat)
  1060. {
  1061. ptzFallbackSysMsgFormat = TEXT("Active Directory failure with code '0x%08x'!");
  1062. fDelFallbackSysMsgFormat = FALSE;
  1063. }
  1064. //#_#BUGBUG: this should be commented on why there is a magic 10...highly dependent on format message,
  1065. // cause of potential buffer overrun (just from resources, though)
  1066. ptzSysMsg = (PTSTR)LocalAlloc(LPTR, (lstrlen(ptzFallbackSysMsgFormat)+10)*sizeof(TCHAR));
  1067. if (NULL == ptzSysMsg)
  1068. {
  1069. ptzSysMsg = tzSysMsgBuf;
  1070. fDelSysMsg = FALSE;
  1071. }
  1072. //#_#BUGBUG: coming from resource, so probably not a security bug, but potential AV:
  1073. // if LocalAlloc above fails, falls back to stack buffer of length 255
  1074. wsprintf(ptzSysMsg, ptzFallbackSysMsgFormat, hr);
  1075. if (fDelFallbackSysMsgFormat)
  1076. {
  1077. delete ptzFallbackSysMsgFormat;
  1078. }
  1079. }
  1080. PTSTR ptzMsg = ptzSysMsg;
  1081. BOOL fDelMsg = FALSE;
  1082. PTSTR ptzFormat = NULL;
  1083. if (nStr)
  1084. {
  1085. LoadStringToTchar(nStr, &ptzFormat);
  1086. }
  1087. if (ptzFormat)
  1088. {
  1089. //NTRAID#NTBUG9-571996-2002/03/10-jmessec the following length calculation can't determine buffer length;
  1090. // for instance format string %s%s would cause an overrun
  1091. ptzMsg = new TCHAR[lstrlen(ptzFormat) + lstrlen(ptzSysMsg) + 1];
  1092. if (ptzMsg)
  1093. {
  1094. wsprintf(ptzMsg, ptzFormat, ptzSysMsg);
  1095. fDelMsg = TRUE;
  1096. }
  1097. }
  1098. PTSTR ptzTitle = NULL;
  1099. BOOL fDelTitle = TRUE;
  1100. if (!LoadStringToTchar(IDS_ERRMSG_TITLE, &ptzTitle))
  1101. {
  1102. ptzTitle = TEXT("Active Directory");
  1103. fDelTitle = FALSE;
  1104. }
  1105. if (ptzMsg)
  1106. {
  1107. MessageBox((hWnd)?hWnd:GetDesktopWindow(), ptzMsg, ptzTitle, MB_OK | MB_ICONINFORMATION);
  1108. }
  1109. if (fDelSysMsg && ptzSysMsg != NULL)
  1110. {
  1111. LocalFree(ptzSysMsg);
  1112. }
  1113. if (fDelTitle && ptzTitle != NULL)
  1114. {
  1115. delete ptzTitle;
  1116. }
  1117. if (fDelMsg && ptzMsg != NULL)
  1118. {
  1119. delete[] ptzMsg;
  1120. }
  1121. if (ptzFormat != NULL)
  1122. {
  1123. delete ptzFormat;
  1124. }
  1125. }
  1126. int ReportMessageWorker(HWND hWnd,
  1127. DWORD dwMessageId,
  1128. UINT fuStyle,
  1129. PVOID* lpArguments,
  1130. int nArguments,
  1131. DWORD dwTitleId,
  1132. HRESULT hrFallback,
  1133. LPCTSTR pszHelpTopic = NULL,
  1134. MSGBOXCALLBACK lpfnMsgBoxCallback = NULL );
  1135. // Don't bother with LoadLibrary, MMC is hardlinked with HtmlHelp anyway
  1136. VOID CALLBACK MsgBoxStdCallback(LPHELPINFO pHelpInfo)
  1137. {
  1138. ASSERT( NULL != pHelpInfo && NULL != pHelpInfo->dwContextId );
  1139. TRACE(_T("MsgBoxStdCallback: CtrlId = %d, ContextId = \"%s\"\n"),
  1140. pHelpInfo->iCtrlId, pHelpInfo->dwContextId);
  1141. HtmlHelp( (HWND)pHelpInfo->hItemHandle,
  1142. DSADMIN_LINKED_HELP_FILE,
  1143. HH_DISPLAY_TOPIC,
  1144. pHelpInfo->dwContextId );
  1145. }
  1146. int ReportMessageWorker(HWND hWnd,
  1147. DWORD dwMessageId,
  1148. UINT fuStyle,
  1149. PVOID* lpArguments,
  1150. int,
  1151. DWORD dwTitleId,
  1152. HRESULT hrFallback,
  1153. LPCTSTR pszHelpTopic,
  1154. MSGBOXCALLBACK lpfnMsgBoxCallback )
  1155. {
  1156. CThemeContextActivator activator;
  1157. ASSERT( !pszHelpTopic || !lpfnMsgBoxCallback );
  1158. LPTSTR ptzFormat = NULL;
  1159. LPTSTR ptzMessage = NULL;
  1160. LPTSTR ptzTitle = NULL;
  1161. int retval = MB_OK;
  1162. do
  1163. {
  1164. // load message format
  1165. if (!LoadStringToTchar(dwMessageId, &ptzFormat))
  1166. {
  1167. ASSERT(FALSE);
  1168. break;
  1169. }
  1170. // generate actual message
  1171. int cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  1172. | FORMAT_MESSAGE_FROM_STRING
  1173. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1174. ptzFormat,
  1175. NULL,
  1176. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1177. (PTSTR)&ptzMessage, 0, (va_list*)lpArguments);
  1178. if (!cch)
  1179. {
  1180. ASSERT(FALSE);
  1181. ReportError( hrFallback, 0, hWnd );
  1182. break;
  1183. }
  1184. // load title string
  1185. if (0 == dwTitleId)
  1186. {
  1187. dwTitleId = IDS_ERRMSG_TITLE;
  1188. }
  1189. if (!LoadStringToTchar(dwTitleId, &ptzTitle))
  1190. {
  1191. ptzTitle = NULL;
  1192. }
  1193. // display actual message
  1194. if ((fuStyle & S_MB_YES_TO_ALL) == S_MB_YES_TO_ALL) //use special message box
  1195. {
  1196. if (fuStyle & MB_HELP)
  1197. {
  1198. ASSERT(FALSE); // not supported
  1199. fuStyle &= ~MB_HELP;
  1200. }
  1201. retval = SpecialMessageBox(hWnd,
  1202. ptzMessage,
  1203. (NULL != ptzTitle) ? ptzTitle : TEXT("Active Directory"),
  1204. fuStyle );
  1205. }
  1206. else
  1207. {
  1208. MSGBOXPARAMS mbp;
  1209. ::ZeroMemory( &mbp, sizeof(mbp) );
  1210. mbp.cbSize = sizeof(mbp);
  1211. mbp.hwndOwner = hWnd;
  1212. mbp.lpszText = ptzMessage;
  1213. mbp.lpszCaption = (NULL != ptzTitle) ? ptzTitle : TEXT("Active Directory");
  1214. mbp.dwStyle = fuStyle;
  1215. mbp.dwContextHelpId = (DWORD_PTR)pszHelpTopic;
  1216. mbp.lpfnMsgBoxCallback = (NULL == pszHelpTopic)
  1217. ? lpfnMsgBoxCallback
  1218. : MsgBoxStdCallback;
  1219. //
  1220. // Display the actual message box
  1221. //
  1222. retval = MessageBoxIndirect( &mbp );
  1223. }
  1224. } while (FALSE); // false loop
  1225. //
  1226. // cleanup
  1227. //
  1228. if (NULL != ptzFormat)
  1229. {
  1230. delete ptzFormat;
  1231. }
  1232. if (NULL != ptzMessage)
  1233. {
  1234. LocalFree(ptzMessage);
  1235. }
  1236. if (NULL != ptzTitle)
  1237. {
  1238. delete ptzTitle;
  1239. }
  1240. return retval;
  1241. }
  1242. int ReportMessageEx(HWND hWnd,
  1243. DWORD dwMessageId,
  1244. UINT fuStyle,
  1245. PVOID* lpArguments,
  1246. int nArguments,
  1247. DWORD dwTitleId,
  1248. LPCTSTR pszHelpTopic,
  1249. MSGBOXCALLBACK lpfnMsgBoxCallback )
  1250. {
  1251. return ReportMessageWorker(
  1252. hWnd,
  1253. dwMessageId,
  1254. fuStyle,
  1255. lpArguments,
  1256. nArguments,
  1257. dwTitleId,
  1258. 0,
  1259. pszHelpTopic,
  1260. lpfnMsgBoxCallback );
  1261. }
  1262. int ReportErrorEx(HWND hWnd,
  1263. DWORD dwMessageId,
  1264. HRESULT hr,
  1265. UINT fuStyle,
  1266. PVOID* lpArguments,
  1267. int nArguments,
  1268. DWORD dwTitleId,
  1269. BOOL TryADsIErrors)
  1270. {
  1271. LPTSTR ptzSysMsg = NULL;
  1272. int retval = MB_OK;
  1273. do
  1274. { // false loop
  1275. // load message for this HRESULT
  1276. int cch = cchLoadHrMsg( hr, &ptzSysMsg, TryADsIErrors );
  1277. if (!cch)
  1278. {
  1279. //
  1280. // JonN 5/10/01 375461 fallback message cleanup
  1281. //
  1282. // load message format
  1283. LPTSTR ptzFormat = NULL;
  1284. if (!LoadStringToTchar(IDS_ERRMSG_UNKNOWN_HR, &ptzFormat) || !ptzFormat)
  1285. {
  1286. ASSERT(FALSE);
  1287. ReportError( hr, 0, hWnd );
  1288. break;
  1289. }
  1290. // format in HRESULT
  1291. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  1292. | FORMAT_MESSAGE_FROM_STRING
  1293. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1294. ptzFormat,
  1295. NULL,
  1296. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1297. (PTSTR)&ptzSysMsg,
  1298. 1, (va_list*)&hr);
  1299. delete ptzFormat;
  1300. if (!cch)
  1301. {
  1302. ReportError( hr, 0, hWnd );
  1303. break;
  1304. }
  1305. }
  1306. // prepare argument array
  1307. PVOID* ppvArguments = (PVOID*)new BYTE[(nArguments+1)*sizeof(PVOID)];
  1308. if (!ppvArguments)
  1309. {
  1310. ASSERT(ppvArguments );
  1311. ReportError( hr, 0, hWnd);
  1312. break;
  1313. }
  1314. ppvArguments[0] = ptzSysMsg;
  1315. if (0 != nArguments)
  1316. {
  1317. ::CopyMemory( ppvArguments+1, lpArguments, nArguments*sizeof(PVOID) );
  1318. }
  1319. retval = ReportMessageWorker(hWnd,
  1320. dwMessageId,
  1321. fuStyle,
  1322. ppvArguments,
  1323. nArguments+1,
  1324. dwTitleId,
  1325. hr );
  1326. delete[] ppvArguments;
  1327. ppvArguments = 0;
  1328. } while (FALSE); // false loop
  1329. //
  1330. // cleanup
  1331. //
  1332. if (NULL != ptzSysMsg)
  1333. {
  1334. LocalFree(ptzSysMsg);
  1335. }
  1336. return retval;
  1337. }
  1338. int SpecialMessageBox (HWND,
  1339. LPWSTR pwszMessage,
  1340. LPWSTR pwszTitle,
  1341. DWORD)
  1342. {
  1343. CThemeContextActivator activator;
  1344. CSpecialMessageBox MBDlg;
  1345. MBDlg.m_title = pwszTitle;
  1346. MBDlg.m_message = pwszMessage;
  1347. int answer = (int)MBDlg.DoModal();
  1348. return answer;
  1349. }
  1350. ///////////////////////////////////////////////////////////////////////////
  1351. // CNameFormatterBase
  1352. HRESULT CNameFormatterBase::Initialize(IN MyBasePathsInfo* pBasePathInfo,
  1353. IN LPCWSTR lpszClassName, IN UINT nStringID)
  1354. {
  1355. CString szFormatString;
  1356. HRESULT hr = _ReadFromDS(pBasePathInfo, lpszClassName, szFormatString);
  1357. if (FAILED(hr))
  1358. {
  1359. // nothing in the display specifiers, load from resource
  1360. if (!szFormatString.LoadString(nStringID))
  1361. {
  1362. // if failed for some reason, use this default
  1363. szFormatString = L"%<givenName> %<initials>. %<sn>";
  1364. }
  1365. }
  1366. Initialize(szFormatString);
  1367. return S_OK;
  1368. }
  1369. HRESULT CNameFormatterBase::_ReadFromDS(IN MyBasePathsInfo* pBasePathInfo,
  1370. IN LPCWSTR lpszClassName,
  1371. OUT CString& szFormatString)
  1372. {
  1373. static LPCWSTR lpszObjectClass = L"displaySpecifier";
  1374. static LPCWSTR lpszSettingsObjectFmt = L"cn=%s-Display";
  1375. static LPCWSTR lpszFormatProperty = L"createDialog";
  1376. szFormatString.Empty();
  1377. if ( (pBasePathInfo == NULL) ||
  1378. (lpszClassName == NULL) || (lpszClassName[0] == NULL) )
  1379. {
  1380. return E_INVALIDARG;
  1381. }
  1382. // get the display specifiers locale container (e.g. 409)
  1383. CComPtr<IADsContainer> spLocaleContainer;
  1384. HRESULT hr = pBasePathInfo->GetDisplaySpecifier(NULL, IID_IADsContainer, (void**)&spLocaleContainer);
  1385. if (FAILED(hr))
  1386. return hr;
  1387. // bind to the settings object
  1388. CString szSettingsObject;
  1389. szSettingsObject.Format(lpszSettingsObjectFmt, lpszClassName);
  1390. CComPtr<IDispatch> spIDispatchObject;
  1391. hr = spLocaleContainer->GetObject(CComBSTR(lpszObjectClass),
  1392. CComBSTR(szSettingsObject),
  1393. &spIDispatchObject);
  1394. if (FAILED(hr))
  1395. return hr;
  1396. CComPtr<IADs> spSettingsObject;
  1397. hr = spIDispatchObject->QueryInterface(IID_IADs, (void**)&spSettingsObject);
  1398. if (FAILED(hr))
  1399. return hr;
  1400. // get single valued property in string list form
  1401. CComVariant var;
  1402. hr = spSettingsObject->Get(CComBSTR(lpszFormatProperty), &var);
  1403. if (FAILED(hr))
  1404. return hr;
  1405. if (var.vt != VT_BSTR)
  1406. return E_UNEXPECTED;
  1407. szFormatString = var.bstrVal;
  1408. return S_OK;
  1409. }
  1410. BOOL CNameFormatterBase::Initialize(IN LPCWSTR lpszFormattingString)
  1411. {
  1412. TRACE(L"CNameFormatterBase::Initialize(%s)\n", lpszFormattingString);
  1413. _Clear();
  1414. if (lpszFormattingString == NULL)
  1415. {
  1416. return FALSE;
  1417. }
  1418. // copy the formatting string (it will be modified)
  1419. m_lpszFormattingString = new WCHAR[lstrlen(lpszFormattingString)+1];
  1420. wcscpy(m_lpszFormattingString, lpszFormattingString);
  1421. // allocate memory for the arrays
  1422. _AllocateMemory(lpszFormattingString);
  1423. // loop thugh the string and extract tokens
  1424. // Establish string and get the first token
  1425. WCHAR szSeparators[] = L"%>";
  1426. WCHAR* lpszToken = wcstok(m_lpszFormattingString, szSeparators);
  1427. while (lpszToken != NULL)
  1428. {
  1429. // While there are tokens in "string"
  1430. //TRACE( L" %s\n", token );
  1431. if ( (lpszToken[0] == L'<') &&
  1432. !((lpszFormattingString[0] == L'<') && (m_tokenArrCount == 0)) )
  1433. {
  1434. // parameter
  1435. m_tokenArray[m_tokenArrCount].m_bIsParam = TRUE;
  1436. m_tokenArray[m_tokenArrCount].m_nIndex = m_paramArrCount;
  1437. m_lpszParamArr[m_paramArrCount++] = (lpszToken+1);
  1438. }
  1439. else
  1440. {
  1441. // constant
  1442. m_tokenArray[m_tokenArrCount].m_bIsParam = FALSE;
  1443. m_tokenArray[m_tokenArrCount].m_nIndex = m_constArrCount;
  1444. m_lpszConstArr[m_constArrCount++] = lpszToken;
  1445. }
  1446. m_tokenArrCount++;
  1447. /* Get next token: */
  1448. lpszToken = wcstok(NULL, szSeparators);
  1449. } // while
  1450. return TRUE;
  1451. }
  1452. void CNameFormatterBase::SetMapping(IN LPCWSTR* lpszArgMapping, IN int nArgCount)
  1453. {
  1454. if (m_mapArr != NULL)
  1455. {
  1456. delete[] m_mapArr;
  1457. }
  1458. // do the mapping
  1459. m_mapArr = new int[m_paramArrCount];
  1460. for (int kk=0; kk<m_paramArrCount;kk++)
  1461. {
  1462. m_mapArr[kk] = -1; // clear
  1463. for (int jj=0; jj<nArgCount;jj++)
  1464. {
  1465. if (wcscmp(m_lpszParamArr[kk], lpszArgMapping[jj]) == 0)
  1466. {
  1467. m_mapArr[kk] = jj;
  1468. }
  1469. }
  1470. }
  1471. }
  1472. void CNameFormatterBase::Format(OUT CString& szBuffer, IN LPCWSTR* lpszArgArr)
  1473. {
  1474. szBuffer.Empty();
  1475. //TRACE(L"\nResult:#");
  1476. BOOL bLastParamNull = FALSE;
  1477. for (int k=0; k<m_tokenArrCount; k++)
  1478. {
  1479. if (m_tokenArray[k].m_bIsParam)
  1480. {
  1481. if (m_mapArr[m_tokenArray[k].m_nIndex] >= 0)
  1482. {
  1483. LPCWSTR lpszVal = lpszArgArr[m_mapArr[m_tokenArray[k].m_nIndex]];
  1484. if (lpszVal != NULL)
  1485. {
  1486. //TRACE(L"%s", lpszVal);
  1487. szBuffer += lpszVal;
  1488. bLastParamNull = FALSE;
  1489. }
  1490. else
  1491. {
  1492. bLastParamNull = TRUE;
  1493. }
  1494. }
  1495. }
  1496. else
  1497. {
  1498. if (!bLastParamNull)
  1499. {
  1500. //TRACE(L"%s", m_lpszConstArr[m_tokenArray[k].m_nIndex]);
  1501. szBuffer += m_lpszConstArr[m_tokenArray[k].m_nIndex];
  1502. }
  1503. }
  1504. }
  1505. szBuffer.TrimRight(); // in case we got a trailing space.
  1506. //TRACE(L"#\n");
  1507. }
  1508. void CNameFormatterBase::_AllocateMemory(LPCWSTR lpszFormattingString)
  1509. {
  1510. int nFieldCount = 1; // conservative, have at least one
  1511. for (WCHAR* pChar = (WCHAR*)lpszFormattingString; *pChar != NULL; pChar++)
  1512. {
  1513. if (*pChar == L'%')
  1514. {
  1515. nFieldCount++;
  1516. }
  1517. }
  1518. // conservative estimates on array sizes
  1519. m_tokenArray = new CToken[2*nFieldCount];
  1520. m_lpszConstArr = new LPCWSTR[nFieldCount];
  1521. m_lpszParamArr = new LPCWSTR[nFieldCount];
  1522. }
  1523. /////////////////////////////////////////////////////////////////////////////
  1524. // CHelpDialog
  1525. CHelpDialog::CHelpDialog(UINT uIDD, CWnd* pParentWnd) :
  1526. CDialog(uIDD, pParentWnd),
  1527. m_hWndWhatsThis (0)
  1528. {
  1529. }
  1530. CHelpDialog::CHelpDialog(UINT uIDD) :
  1531. CDialog(uIDD),
  1532. m_hWndWhatsThis (0)
  1533. {
  1534. }
  1535. CHelpDialog::~CHelpDialog()
  1536. {
  1537. }
  1538. BEGIN_MESSAGE_MAP(CHelpDialog, CDialog)
  1539. ON_WM_CONTEXTMENU()
  1540. ON_MESSAGE(WM_HELP, OnHelp)
  1541. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1542. END_MESSAGE_MAP()
  1543. /////////////////////////////////////////////////////////////////////////////
  1544. // CHelpDialog message handlers
  1545. void CHelpDialog::OnWhatsThis()
  1546. {
  1547. //
  1548. // Display context help for a control
  1549. //
  1550. if ( m_hWndWhatsThis )
  1551. {
  1552. DoContextHelp (m_hWndWhatsThis);
  1553. }
  1554. }
  1555. BOOL CHelpDialog::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1556. {
  1557. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1558. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1559. {
  1560. //
  1561. // Display context help for a control
  1562. //
  1563. DoContextHelp ((HWND) pHelpInfo->hItemHandle);
  1564. }
  1565. return TRUE;
  1566. }
  1567. void CHelpDialog::DoContextHelp (HWND /*hWndControl*/)
  1568. {
  1569. }
  1570. void CHelpDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1571. {
  1572. //
  1573. // point is in screen coordinates
  1574. //
  1575. CMenu bar;
  1576. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1577. {
  1578. CMenu& popup = *bar.GetSubMenu (0);
  1579. ASSERT(popup.m_hMenu);
  1580. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1581. point.x, // in screen coordinates
  1582. point.y, // in screen coordinates
  1583. this) ) // route commands through main window
  1584. {
  1585. m_hWndWhatsThis = 0;
  1586. ScreenToClient (&point);
  1587. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1588. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1589. if ( pChild )
  1590. {
  1591. m_hWndWhatsThis = pChild->m_hWnd;
  1592. }
  1593. }
  1594. }
  1595. }
  1596. /////////////////////////////////////////////////////////////////////////////
  1597. // CHelpPropertyPage
  1598. CHelpPropertyPage::CHelpPropertyPage(UINT uIDD) :
  1599. CPropertyPage(uIDD),
  1600. m_hWndWhatsThis (0)
  1601. {
  1602. }
  1603. CHelpPropertyPage::~CHelpPropertyPage()
  1604. {
  1605. }
  1606. BEGIN_MESSAGE_MAP(CHelpPropertyPage, CPropertyPage)
  1607. ON_WM_CONTEXTMENU()
  1608. ON_MESSAGE(WM_HELP, OnHelp)
  1609. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1610. END_MESSAGE_MAP()
  1611. /////////////////////////////////////////////////////////////////////////////
  1612. // CHelpPropertyPage message handlers
  1613. void CHelpPropertyPage::OnWhatsThis()
  1614. {
  1615. //
  1616. // Display context help for a control
  1617. //
  1618. if ( m_hWndWhatsThis )
  1619. {
  1620. DoContextHelp (m_hWndWhatsThis);
  1621. }
  1622. }
  1623. BOOL CHelpPropertyPage::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1624. {
  1625. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1626. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1627. {
  1628. //
  1629. // Display context help for a control
  1630. //
  1631. DoContextHelp ((HWND) pHelpInfo->hItemHandle);
  1632. }
  1633. return TRUE;
  1634. }
  1635. void CHelpPropertyPage::DoContextHelp (HWND /*hWndControl*/)
  1636. {
  1637. }
  1638. void CHelpPropertyPage::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1639. {
  1640. //
  1641. // point is in screen coordinates
  1642. //
  1643. CMenu bar;
  1644. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1645. {
  1646. CMenu& popup = *bar.GetSubMenu (0);
  1647. ASSERT(popup.m_hMenu);
  1648. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1649. point.x, // in screen coordinates
  1650. point.y, // in screen coordinates
  1651. this) ) // route commands through main window
  1652. {
  1653. m_hWndWhatsThis = 0;
  1654. ScreenToClient (&point);
  1655. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1656. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1657. if ( pChild )
  1658. {
  1659. m_hWndWhatsThis = pChild->m_hWnd;
  1660. }
  1661. }
  1662. }
  1663. }
  1664. //////////////////////////////////////////////////////////////////
  1665. // CMoreInfoMessageBox
  1666. //
  1667. BEGIN_MESSAGE_MAP(CMoreInfoMessageBox, CDialog)
  1668. ON_BN_CLICKED(ID_BUTTON_MORE_INFO, OnMoreInfo)
  1669. ON_BN_CLICKED(IDYES, OnOK)
  1670. ON_BN_CLICKED(IDNO, OnCancel)
  1671. END_MESSAGE_MAP()
  1672. //////////////////////////////////////////////////////////////////
  1673. // Theming support
  1674. HPROPSHEETPAGE MyCreatePropertySheetPage(AFX_OLDPROPSHEETPAGE* psp)
  1675. {
  1676. PROPSHEETPAGE_V3 sp_v3 = {0};
  1677. CopyMemory (&sp_v3, psp, psp->dwSize);
  1678. sp_v3.dwSize = sizeof(sp_v3);
  1679. return (::CreatePropertySheetPage(&sp_v3));
  1680. }