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.

1885 lines
48 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. HRESULT* 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. HRESULT* 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 && FAILED(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. //
  497. // Get the error message
  498. //
  499. PWSTR pszErrMessage;
  500. int iChar = cchLoadHrMsg(m_pErrorArray[nIdx], &pszErrMessage, TRUE);
  501. if (pszErrMessage != NULL && iChar > 0)
  502. {
  503. ListView_SetItemText(hList, NewIndex, IDX_ERR_COL, pszErrMessage);
  504. LocalFree(pszErrMessage);
  505. }
  506. }
  507. }
  508. }
  509. }
  510. else if (m_pPathArray != NULL) // if the node list is NULL then use the string list
  511. {
  512. ASSERT(m_pErrorArray != NULL && m_pPathArray != NULL);
  513. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  514. {
  515. if (nIdx < m_nErrorCount && FAILED(m_pErrorArray[nIdx]))
  516. {
  517. //
  518. // Use the path cracker to retrieve the name of the object
  519. //
  520. PCWSTR pszPath = m_pPathArray[nIdx];
  521. CPathCracker pathCracker;
  522. VERIFY(SUCCEEDED(pathCracker.Set((BSTR)(PWSTR)pszPath, ADS_SETTYPE_DN)));
  523. VERIFY(SUCCEEDED(pathCracker.put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX)));
  524. VERIFY(SUCCEEDED(pathCracker.SetDisplayType(ADS_DISPLAY_VALUE_ONLY)));
  525. CComBSTR bstrName;
  526. VERIFY(SUCCEEDED(pathCracker.GetElement(0, &bstrName)));
  527. //
  528. // Create the list view item
  529. //
  530. LV_ITEM lvi = {0};
  531. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  532. lvi.iSubItem = IDX_NAME_COL;
  533. //
  534. // Make the LPARAM be the path to the object
  535. // Not used at this time but may be useful in
  536. // the future for bringing up property pages or
  537. // other special features.
  538. //
  539. lvi.lParam = (LPARAM)m_pPathArray[nIdx];
  540. lvi.pszText = (PWSTR)bstrName;
  541. lvi.iItem = nIdx;
  542. if (m_hImageList != NULL)
  543. {
  544. //
  545. // REVIEW_JEFFJON : this will add multiple icons of the same class
  546. // need to provide a better means for managing the icons
  547. //
  548. ASSERT(m_pClassArray[nIdx] != NULL);
  549. HICON icon = m_pComponentData->GetBasePathsInfo()->GetIcon(
  550. // someone really blew it with const correctness...
  551. const_cast<LPTSTR>(m_pClassArray[nIdx]),
  552. DSGIF_ISNORMAL | DSGIF_GETDEFAULTICON,
  553. 16,
  554. 16);
  555. int i = ::ImageList_AddIcon(m_hImageList, icon);
  556. ASSERT(i != -1);
  557. if (i != -1)
  558. {
  559. lvi.mask |= LVIF_IMAGE;
  560. lvi.iImage = i;
  561. }
  562. }
  563. //
  564. // Insert the new item
  565. //
  566. int NewIndex = ListView_InsertItem(hList, &lvi);
  567. ASSERT(NewIndex != -1);
  568. if (NewIndex == -1)
  569. {
  570. continue;
  571. }
  572. //
  573. // Get the error message
  574. //
  575. PWSTR pszErrMessage;
  576. int iChar = cchLoadHrMsg(m_pErrorArray[nIdx], &pszErrMessage, TRUE);
  577. if (pszErrMessage != NULL && iChar > 0)
  578. {
  579. //
  580. // REVIEW_JEFFJON : this is a hack to get rid of two extra characters
  581. // at the end of the error message
  582. //
  583. size_t iLen = wcslen(pszErrMessage);
  584. pszErrMessage[iLen - 2] = L'\0';
  585. ListView_SetItemText(hList, NewIndex, IDX_ERR_COL, pszErrMessage);
  586. LocalFree(pszErrMessage);
  587. }
  588. }
  589. }
  590. }
  591. UpdateListboxHorizontalExtent();
  592. return TRUE;
  593. }
  594. void CMultiselectErrorDialog::UpdateListboxHorizontalExtent()
  595. {
  596. CListCtrl* pListView = reinterpret_cast<CListCtrl*>(GetDlgItem(IDC_ERROR_LIST));
  597. pListView->SetColumnWidth(IDX_ERR_COL, LVSCW_AUTOSIZE);
  598. }
  599. /////////////////////////////////////////////////////////////////////
  600. // MFC Utilities
  601. //
  602. // CDialogEx
  603. //
  604. CDialogEx::CDialogEx(UINT nIDTemplate, CWnd * pParentWnd) : CDialog(nIDTemplate, pParentWnd)
  605. {
  606. }
  607. HWND CDialogEx::HGetDlgItem(INT nIdDlgItem)
  608. {
  609. return ::HGetDlgItem(m_hWnd, nIdDlgItem);
  610. }
  611. void CDialogEx::SetDlgItemFocus(INT nIdDlgItem)
  612. {
  613. ::SetDlgItemFocus(m_hWnd, nIdDlgItem);
  614. }
  615. void CDialogEx::EnableDlgItem(INT nIdDlgItem, BOOL fEnable)
  616. {
  617. ::EnableDlgItem(m_hWnd, nIdDlgItem, fEnable);
  618. }
  619. void CDialogEx::HideDlgItem(INT nIdDlgItem, BOOL fHideItem)
  620. {
  621. ::HideDlgItem(m_hWnd, nIdDlgItem, fHideItem);
  622. }
  623. /////////////////////////////////////////////////////////////////////////////////////
  624. // CPropertyPageEx_Mine
  625. //
  626. CPropertyPageEx_Mine::CPropertyPageEx_Mine(UINT nIDTemplate) : CPropertyPage(nIDTemplate)
  627. {
  628. }
  629. HWND CPropertyPageEx_Mine::HGetDlgItem(INT nIdDlgItem)
  630. {
  631. return ::HGetDlgItem(m_hWnd, nIdDlgItem);
  632. }
  633. void CPropertyPageEx_Mine::SetDlgItemFocus(INT nIdDlgItem)
  634. {
  635. ::SetDlgItemFocus(m_hWnd, nIdDlgItem);
  636. }
  637. void CPropertyPageEx_Mine::EnableDlgItem(INT nIdDlgItem, BOOL fEnable)
  638. {
  639. ::EnableDlgItem(m_hWnd, nIdDlgItem, fEnable);
  640. }
  641. void CPropertyPageEx_Mine::HideDlgItem(INT nIdDlgItem, BOOL fHideItem)
  642. {
  643. ::HideDlgItem(m_hWnd, nIdDlgItem, fHideItem);
  644. }
  645. /////////////////////////////////////////////////////////////////////////////
  646. // CProgressDialogBase
  647. UINT CProgressDialogBase::s_nNextStepMessage = WM_USER + 100;
  648. CProgressDialogBase::CProgressDialogBase(HWND hParentWnd)
  649. : CDialog(IDD_PROGRESS, CWnd::FromHandle(hParentWnd))
  650. {
  651. m_nSteps = 0;
  652. m_nCurrStep = 0;
  653. m_nTitleStringID = 0;
  654. }
  655. BEGIN_MESSAGE_MAP(CProgressDialogBase, CDialog)
  656. ON_WM_SHOWWINDOW()
  657. ON_WM_CLOSE()
  658. ON_MESSAGE(CProgressDialogBase::s_nNextStepMessage, OnNextStepMessage )
  659. END_MESSAGE_MAP()
  660. BOOL CProgressDialogBase::OnInitDialog()
  661. {
  662. CDialog::OnInitDialog();
  663. m_progressCtrl.SubclassDlgItem(IDC_PROG_BAR, this);
  664. if (m_nTitleStringID >0)
  665. {
  666. CString szTitle;
  667. if (szTitle.LoadString(m_nTitleStringID))
  668. SetWindowText(szTitle);
  669. }
  670. GetDlgItemText(IDC_PROG_STATIC, m_szProgressFormat);
  671. SetDlgItemText(IDC_PROG_STATIC, NULL);
  672. OnStart();
  673. ASSERT(m_nSteps > 0);
  674. if (m_nSteps == 0)
  675. PostMessage(WM_CLOSE);
  676. #if _MFC_VER >= 0x0600
  677. m_progressCtrl.SetRange32(0, m_nSteps);
  678. #else
  679. m_progressCtrl.SetRange(0, m_nSteps);
  680. #endif
  681. //
  682. // We want to walk backwards through the list for UI performance reasons
  683. //
  684. m_nCurrStep = m_nSteps - 1;
  685. return TRUE; // return TRUE unless you set the focus to a control
  686. // EXCEPTION: OCX Property Pages should return FALSE
  687. }
  688. void CProgressDialogBase::OnShowWindow(BOOL bShow, UINT nStatus)
  689. {
  690. CDialog::OnShowWindow(bShow, nStatus);
  691. // kick the process
  692. if (bShow && (m_nSteps > 0) && (m_nCurrStep == m_nSteps - 1))
  693. {
  694. m_bDone = FALSE;
  695. PostMessage(s_nNextStepMessage);
  696. }
  697. }
  698. void CProgressDialogBase::OnClose()
  699. {
  700. OnEnd();
  701. CDialog::OnClose();
  702. }
  703. afx_msg LONG CProgressDialogBase::OnNextStepMessage( WPARAM, LPARAM)
  704. {
  705. ASSERT(!m_bDone);
  706. BOOL bExit = FALSE;
  707. if (m_nCurrStep > 0)
  708. {
  709. m_progressCtrl.OffsetPos(1);
  710. _SetProgressText();
  711. if (!OnStep(m_nCurrStep--))
  712. bExit = TRUE; // aborted by user
  713. }
  714. else if (m_nCurrStep == 0)
  715. {
  716. m_progressCtrl.OffsetPos(1);
  717. _SetProgressText();
  718. OnStep(m_nCurrStep--);
  719. bExit = TRUE;
  720. m_bDone = TRUE;
  721. }
  722. else
  723. {
  724. bExit = TRUE;
  725. m_bDone = TRUE;
  726. }
  727. if (bExit)
  728. {
  729. PostMessage(WM_CLOSE);
  730. }
  731. else
  732. {
  733. MSG tempMSG;
  734. while(::PeekMessage(&tempMSG,NULL, 0, 0, PM_REMOVE))
  735. {
  736. DispatchMessage(&tempMSG);
  737. }
  738. PostMessage(s_nNextStepMessage);
  739. }
  740. return 0;
  741. }
  742. void CProgressDialogBase::_SetProgressText()
  743. {
  744. CString szMessage;
  745. WCHAR szCurrStep[128], szMaxSteps[128];
  746. wsprintf(szCurrStep, L"%d",(m_nSteps - m_nCurrStep));
  747. wsprintf(szMaxSteps, L"%d",m_nSteps);
  748. szMessage.FormatMessage(m_szProgressFormat, szCurrStep, szMaxSteps);
  749. SetDlgItemText(IDC_PROG_STATIC, szMessage);
  750. }
  751. ////////////////////////////////////////////////////////////////////////////
  752. // CMultipleProgressDialogBase
  753. //
  754. CMultipleProgressDialogBase::~CMultipleProgressDialogBase()
  755. {
  756. //
  757. // Delete the error reporting structures
  758. //
  759. if (m_phrArray != NULL)
  760. {
  761. delete[] m_phrArray;
  762. }
  763. if (m_pPathArray != NULL)
  764. {
  765. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  766. {
  767. if (m_pPathArray[nIdx] != NULL)
  768. {
  769. delete[] m_pPathArray[nIdx];
  770. }
  771. }
  772. delete[] m_pPathArray;
  773. m_pPathArray = NULL;
  774. }
  775. if (m_pClassArray != NULL)
  776. {
  777. for (UINT nIdx = 0; nIdx < m_nErrorCount; nIdx++)
  778. {
  779. if (m_pClassArray[nIdx] != NULL)
  780. {
  781. delete[] m_pClassArray[nIdx];
  782. }
  783. }
  784. delete[] m_pClassArray;
  785. m_pClassArray = NULL;
  786. }
  787. }
  788. HRESULT CMultipleProgressDialogBase::AddError(HRESULT hr,
  789. PCWSTR pszPath,
  790. PCWSTR pszClass)
  791. {
  792. //
  793. // Prepare the multiselect error handling structures if necessary
  794. //
  795. if (m_phrArray == NULL)
  796. {
  797. m_phrArray = new HRESULT[GetStepCount()];
  798. }
  799. if (m_pPathArray == NULL)
  800. {
  801. m_pPathArray = new PWSTR[GetStepCount()];
  802. }
  803. if (m_pClassArray == NULL)
  804. {
  805. m_pClassArray = new PWSTR[GetStepCount()];
  806. }
  807. if (m_phrArray == NULL ||
  808. m_pPathArray == NULL ||
  809. m_pClassArray == NULL)
  810. {
  811. return E_OUTOFMEMORY;
  812. }
  813. m_phrArray[m_nErrorCount] = hr;
  814. m_pPathArray[m_nErrorCount] = new WCHAR[wcslen(pszPath) + 1];
  815. if (m_pPathArray[m_nErrorCount] == NULL)
  816. {
  817. return E_OUTOFMEMORY;
  818. }
  819. wcscpy(m_pPathArray[m_nErrorCount], pszPath);
  820. m_pClassArray[m_nErrorCount] = new WCHAR[wcslen(pszClass) + 1];
  821. if (m_pClassArray[m_nErrorCount] == NULL)
  822. {
  823. return E_OUTOFMEMORY;
  824. }
  825. wcscpy(m_pClassArray[m_nErrorCount], pszClass);
  826. m_nErrorCount++;
  827. return S_OK;
  828. }
  829. void CMultipleProgressDialogBase::OnEnd()
  830. {
  831. if (m_nErrorCount > 0)
  832. {
  833. if (m_pComponentData != NULL)
  834. {
  835. ASSERT(m_pPathArray != NULL);
  836. ASSERT(m_pClassArray != NULL);
  837. ASSERT(m_phrArray != NULL);
  838. CString szTitle;
  839. if (m_pComponentData->QuerySnapinType() == SNAPINTYPE_SITE)
  840. {
  841. VERIFY(szTitle.LoadString(IDS_SITESNAPINNAME));
  842. }
  843. else
  844. {
  845. VERIFY(szTitle.LoadString(IDS_DSSNAPINNAME));
  846. }
  847. CString szHeader;
  848. VERIFY(szHeader.LoadString(IDS_COLUMN_NAME));
  849. CString szCaption;
  850. GetCaptionString(szCaption);
  851. //
  852. // Initialize and show the multiselect error dialog
  853. //
  854. CMultiselectErrorDialog errorDlg(m_pComponentData);
  855. HRESULT hr = errorDlg.Initialize(m_pPathArray,
  856. m_pClassArray,
  857. m_phrArray,
  858. m_nErrorCount,
  859. szTitle,
  860. szCaption,
  861. szHeader);
  862. ASSERT(SUCCEEDED(hr));
  863. errorDlg.DoModal();
  864. }
  865. else
  866. {
  867. ASSERT(m_pComponentData != NULL);
  868. }
  869. }
  870. else
  871. {
  872. m_pComponentData->InvalidateSavedQueriesContainingObjects(m_szObjPathList);
  873. }
  874. }
  875. ////////////////////////////////////////////////////////////////////////////
  876. // CMultipleDeleteProgressDialog
  877. //
  878. void CMultipleDeleteProgressDialog::OnStart()
  879. {
  880. SetStepCount(m_pDeleteHandler->GetItemCount());
  881. m_hWndOld = m_pDeleteHandler->GetParentHwnd();
  882. m_pDeleteHandler->SetParentHwnd(GetSafeHwnd());
  883. m_pDeleteHandler->m_confirmationUI.SetWindow(GetSafeHwnd());
  884. }
  885. BOOL CMultipleDeleteProgressDialog::OnStep(UINT i)
  886. {
  887. BOOL bContinue = TRUE;
  888. CString szPath;
  889. CString szClass;
  890. HRESULT hr = m_pDeleteHandler->OnDeleteStep(i,
  891. &bContinue,
  892. szPath,
  893. szClass,
  894. TRUE /*silent*/);
  895. if (FAILED(hr) && hr != E_FAIL)
  896. {
  897. AddError(hr, szPath, szClass);
  898. }
  899. m_szObjPathList.AddTail(szPath);
  900. return bContinue;
  901. }
  902. void CMultipleDeleteProgressDialog::OnEnd()
  903. {
  904. CMultipleProgressDialogBase::OnEnd();
  905. m_pDeleteHandler->GetTransaction()->End();
  906. m_pDeleteHandler->SetParentHwnd(m_hWndOld);
  907. m_pDeleteHandler->m_confirmationUI.SetWindow(m_hWndOld);
  908. }
  909. /////////////////////////////////////////////////////////////////////////////
  910. // CMultipleMoveProgressDialog
  911. //
  912. void CMultipleMoveProgressDialog::OnStart()
  913. {
  914. SetStepCount(m_pMoveHandler->GetItemCount());
  915. m_hWndOld = m_pMoveHandler->GetParentHwnd();
  916. m_pMoveHandler->SetParentHwnd(GetSafeHwnd());
  917. }
  918. BOOL CMultipleMoveProgressDialog::OnStep(UINT i)
  919. {
  920. BOOL bContinue = TRUE;
  921. CString szPath;
  922. CString szClass;
  923. HRESULT hr = m_pMoveHandler->_OnMoveStep(i,
  924. &bContinue,
  925. szPath,
  926. szClass);
  927. if (FAILED(hr) && hr != E_FAIL && hr != E_POINTER)
  928. {
  929. AddError(hr, szPath, szClass);
  930. }
  931. m_szObjPathList.AddTail(szPath);
  932. return bContinue;
  933. }
  934. void CMultipleMoveProgressDialog::OnEnd()
  935. {
  936. CMultipleProgressDialogBase::OnEnd();
  937. m_pMoveHandler->GetTransaction()->End();
  938. m_pMoveHandler->SetParentHwnd(m_hWndOld);
  939. }
  940. /////////////////////////////////////////////////////////////////////////////
  941. // CConfirmOperationDialog
  942. //
  943. void CConfirmOperationDialog::OnYes()
  944. {
  945. m_pTransaction->ReadFromCheckListBox(&m_extensionsList);
  946. EndDialog(IDYES);
  947. }
  948. /////////////////////////////////////////////////////////////////////////////
  949. // CConfirmOperationDialog
  950. //
  951. CConfirmOperationDialog::CConfirmOperationDialog(HWND hParentWnd,
  952. CDSNotifyHandlerTransaction* pTransaction)
  953. : CDialog(IDD_CONFIRM_OPERATION_EXT, CWnd::FromHandle(hParentWnd))
  954. {
  955. ASSERT(pTransaction != NULL);
  956. m_pTransaction = pTransaction;
  957. m_nTitleStringID = IDS_ERRMSG_TITLE;
  958. }
  959. BEGIN_MESSAGE_MAP(CConfirmOperationDialog, CDialog)
  960. ON_BN_CLICKED(IDYES, OnYes)
  961. ON_BN_CLICKED(IDNO, OnNo)
  962. END_MESSAGE_MAP()
  963. BOOL CConfirmOperationDialog::OnInitDialog()
  964. {
  965. CDialog::OnInitDialog();
  966. m_extensionsList.SubclassDlgItem(IDC_EXTENS_LIST, this);
  967. m_extensionsList.SetCheckStyle(BS_AUTOCHECKBOX);
  968. m_pTransaction->SetCheckListBox(&m_extensionsList);
  969. UpdateListBoxHorizontalExtent();
  970. if (m_nTitleStringID > 0)
  971. {
  972. CString szTitle;
  973. if (szTitle.LoadString(m_nTitleStringID))
  974. SetWindowText(szTitle);
  975. }
  976. SetDlgItemText(IDC_STATIC_OPERATION, m_lpszOperation);
  977. SetDlgItemText(IDC_STATIC_ASSOC_DATA, m_lpszAssocData);
  978. GetDlgItem(IDNO)->SetFocus();
  979. return FALSE; // we set focus
  980. }
  981. void CConfirmOperationDialog::UpdateListBoxHorizontalExtent()
  982. {
  983. int nHorzExtent = 0;
  984. CClientDC dc(&m_extensionsList);
  985. int nItems = m_extensionsList.GetCount();
  986. for (int i=0; i < nItems; i++)
  987. {
  988. TEXTMETRIC tm;
  989. VERIFY(dc.GetTextMetrics(&tm));
  990. CString szBuffer;
  991. m_extensionsList.GetText(i, szBuffer);
  992. CSize ext = dc.GetTextExtent(szBuffer,szBuffer.GetLength());
  993. nHorzExtent = max(ext.cx ,nHorzExtent);
  994. }
  995. m_extensionsList.SetHorizontalExtent(nHorzExtent);
  996. }
  997. ////////////////////////////////////////////////////////////////////////////////
  998. // Message reporting and message boxes
  999. //
  1000. //+----------------------------------------------------------------------------
  1001. //
  1002. // Function: ReportError
  1003. //
  1004. // Sysnopsis: Attempts to get a user-friendly error message from the system.
  1005. //
  1006. // CODEWORK: If called with hr == 0 (hrFallback case), this will generate
  1007. // ptzSysMsg unnecessarily.
  1008. //
  1009. //-----------------------------------------------------------------------------
  1010. void ReportError(HRESULT hr, int nStr, HWND hWnd)
  1011. {
  1012. TCHAR tzSysMsgBuf[255];
  1013. TRACE (_T("*+*+* ReportError called with hr = %lx, nStr = %lx"), hr, nStr);
  1014. if (S_OK == hr && 0 == nStr)
  1015. {
  1016. nStr = IDS_ERRMSG_DEFAULT_TEXT;
  1017. }
  1018. PTSTR ptzSysMsg = NULL;
  1019. BOOL fDelSysMsg = TRUE;
  1020. int cch = cchLoadHrMsg( hr, &ptzSysMsg, FALSE );
  1021. if (!cch)
  1022. {
  1023. PTSTR ptzFallbackSysMsgFormat = NULL;
  1024. BOOL fDelFallbackSysMsgFormat = TRUE;
  1025. LoadStringToTchar(IDS_ERRMSG_FALLBACK_TEXT, &ptzFallbackSysMsgFormat);
  1026. if (NULL == ptzFallbackSysMsgFormat)
  1027. {
  1028. ptzFallbackSysMsgFormat = TEXT("Active Directory failure with code '0x%08x'!");
  1029. fDelFallbackSysMsgFormat = FALSE;
  1030. }
  1031. ptzSysMsg = (PTSTR)LocalAlloc(LPTR, (lstrlen(ptzFallbackSysMsgFormat)+10)*sizeof(TCHAR));
  1032. if (NULL == ptzSysMsg)
  1033. {
  1034. ptzSysMsg = tzSysMsgBuf;
  1035. fDelSysMsg = FALSE;
  1036. }
  1037. wsprintf(ptzSysMsg, ptzFallbackSysMsgFormat, hr);
  1038. if (fDelFallbackSysMsgFormat)
  1039. {
  1040. delete ptzFallbackSysMsgFormat;
  1041. }
  1042. }
  1043. PTSTR ptzMsg = ptzSysMsg;
  1044. BOOL fDelMsg = FALSE;
  1045. PTSTR ptzFormat = NULL;
  1046. if (nStr)
  1047. {
  1048. LoadStringToTchar(nStr, &ptzFormat);
  1049. }
  1050. if (ptzFormat)
  1051. {
  1052. ptzMsg = new TCHAR[lstrlen(ptzFormat) + lstrlen(ptzSysMsg) + 1];
  1053. if (ptzMsg)
  1054. {
  1055. wsprintf(ptzMsg, ptzFormat, ptzSysMsg);
  1056. fDelMsg = TRUE;
  1057. }
  1058. }
  1059. PTSTR ptzTitle = NULL;
  1060. BOOL fDelTitle = TRUE;
  1061. if (!LoadStringToTchar(IDS_ERRMSG_TITLE, &ptzTitle))
  1062. {
  1063. ptzTitle = TEXT("Active Directory");
  1064. fDelTitle = FALSE;
  1065. }
  1066. if (ptzMsg)
  1067. {
  1068. MessageBox((hWnd)?hWnd:GetDesktopWindow(), ptzMsg, ptzTitle, MB_OK | MB_ICONINFORMATION);
  1069. }
  1070. if (fDelSysMsg && ptzSysMsg != NULL)
  1071. {
  1072. LocalFree(ptzSysMsg);
  1073. }
  1074. if (fDelTitle && ptzTitle != NULL)
  1075. {
  1076. delete ptzTitle;
  1077. }
  1078. if (fDelMsg && ptzMsg != NULL)
  1079. {
  1080. delete ptzMsg;
  1081. }
  1082. if (ptzFormat != NULL)
  1083. {
  1084. delete ptzFormat;
  1085. }
  1086. }
  1087. int ReportMessageWorker(HWND hWnd,
  1088. DWORD dwMessageId,
  1089. UINT fuStyle,
  1090. PVOID* lpArguments,
  1091. int nArguments,
  1092. DWORD dwTitleId,
  1093. HRESULT hrFallback,
  1094. LPCTSTR pszHelpTopic = NULL,
  1095. MSGBOXCALLBACK lpfnMsgBoxCallback = NULL );
  1096. // Don't bother with LoadLibrary, MMC is hardlinked with HtmlHelp anyway
  1097. VOID CALLBACK MsgBoxStdCallback(LPHELPINFO pHelpInfo)
  1098. {
  1099. ASSERT( NULL != pHelpInfo && NULL != pHelpInfo->dwContextId );
  1100. TRACE(_T("MsgBoxStdCallback: CtrlId = %d, ContextId = \"%s\"\n"),
  1101. pHelpInfo->iCtrlId, pHelpInfo->dwContextId);
  1102. HtmlHelp( (HWND)pHelpInfo->hItemHandle,
  1103. DSADMIN_LINKED_HELP_FILE,
  1104. HH_DISPLAY_TOPIC,
  1105. pHelpInfo->dwContextId );
  1106. }
  1107. int ReportMessageWorker(HWND hWnd,
  1108. DWORD dwMessageId,
  1109. UINT fuStyle,
  1110. PVOID* lpArguments,
  1111. int,
  1112. DWORD dwTitleId,
  1113. HRESULT hrFallback,
  1114. LPCTSTR pszHelpTopic,
  1115. MSGBOXCALLBACK lpfnMsgBoxCallback )
  1116. {
  1117. ASSERT( !pszHelpTopic || !lpfnMsgBoxCallback );
  1118. LPTSTR ptzFormat = NULL;
  1119. LPTSTR ptzMessage = NULL;
  1120. LPTSTR ptzTitle = NULL;
  1121. int retval = MB_OK;
  1122. do
  1123. {
  1124. // load message format
  1125. if (!LoadStringToTchar(dwMessageId, &ptzFormat))
  1126. {
  1127. ASSERT(FALSE);
  1128. break;
  1129. }
  1130. // generate actual message
  1131. int cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  1132. | FORMAT_MESSAGE_FROM_STRING
  1133. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1134. ptzFormat,
  1135. NULL,
  1136. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1137. (PTSTR)&ptzMessage, 0, (va_list*)lpArguments);
  1138. if (!cch)
  1139. {
  1140. ASSERT(FALSE);
  1141. ReportError( hrFallback, 0, hWnd );
  1142. break;
  1143. }
  1144. // load title string
  1145. if (0 == dwTitleId)
  1146. {
  1147. dwTitleId = IDS_ERRMSG_TITLE;
  1148. }
  1149. if (!LoadStringToTchar(dwTitleId, &ptzTitle))
  1150. {
  1151. ptzTitle = NULL;
  1152. }
  1153. // display actual message
  1154. if ((fuStyle & S_MB_YES_TO_ALL) == S_MB_YES_TO_ALL) //use special message box
  1155. {
  1156. if (fuStyle & MB_HELP)
  1157. {
  1158. ASSERT(FALSE); // not supported
  1159. fuStyle &= ~MB_HELP;
  1160. }
  1161. retval = SpecialMessageBox(hWnd,
  1162. ptzMessage,
  1163. (NULL != ptzTitle) ? ptzTitle : TEXT("Active Directory"),
  1164. fuStyle );
  1165. }
  1166. else
  1167. {
  1168. MSGBOXPARAMS mbp;
  1169. ::ZeroMemory( &mbp, sizeof(mbp) );
  1170. mbp.cbSize = sizeof(mbp);
  1171. mbp.hwndOwner = hWnd;
  1172. mbp.lpszText = ptzMessage;
  1173. mbp.lpszCaption = (NULL != ptzTitle) ? ptzTitle : TEXT("Active Directory");
  1174. mbp.dwStyle = fuStyle;
  1175. mbp.dwContextHelpId = (DWORD_PTR)pszHelpTopic;
  1176. mbp.lpfnMsgBoxCallback = (NULL == pszHelpTopic)
  1177. ? lpfnMsgBoxCallback
  1178. : MsgBoxStdCallback;
  1179. //
  1180. // Display the actual message box
  1181. //
  1182. retval = MessageBoxIndirect( &mbp );
  1183. }
  1184. } while (FALSE); // false loop
  1185. //
  1186. // cleanup
  1187. //
  1188. if (NULL != ptzFormat)
  1189. {
  1190. delete ptzFormat;
  1191. }
  1192. if (NULL != ptzMessage)
  1193. {
  1194. LocalFree(ptzMessage);
  1195. }
  1196. if (NULL != ptzTitle)
  1197. {
  1198. delete ptzTitle;
  1199. }
  1200. return retval;
  1201. }
  1202. int ReportMessageEx(HWND hWnd,
  1203. DWORD dwMessageId,
  1204. UINT fuStyle,
  1205. PVOID* lpArguments,
  1206. int nArguments,
  1207. DWORD dwTitleId,
  1208. LPCTSTR pszHelpTopic,
  1209. MSGBOXCALLBACK lpfnMsgBoxCallback )
  1210. {
  1211. return ReportMessageWorker(
  1212. hWnd,
  1213. dwMessageId,
  1214. fuStyle,
  1215. lpArguments,
  1216. nArguments,
  1217. dwTitleId,
  1218. 0,
  1219. pszHelpTopic,
  1220. lpfnMsgBoxCallback );
  1221. }
  1222. int ReportErrorEx(HWND hWnd,
  1223. DWORD dwMessageId,
  1224. HRESULT hr,
  1225. UINT fuStyle,
  1226. PVOID* lpArguments,
  1227. int nArguments,
  1228. DWORD dwTitleId,
  1229. BOOL TryADsIErrors)
  1230. {
  1231. LPTSTR ptzSysMsg = NULL;
  1232. int retval = MB_OK;
  1233. do
  1234. { // false loop
  1235. // load message for this HRESULT
  1236. int cch = cchLoadHrMsg( hr, &ptzSysMsg, TryADsIErrors );
  1237. if (!cch)
  1238. {
  1239. //
  1240. // JonN 5/10/01 375461 fallback message cleanup
  1241. //
  1242. // load message format
  1243. LPTSTR ptzFormat = NULL;
  1244. if (!LoadStringToTchar(IDS_ERRMSG_UNKNOWN_HR, &ptzFormat) || !ptzFormat)
  1245. {
  1246. ASSERT(FALSE);
  1247. ReportError( hr, 0, hWnd );
  1248. break;
  1249. }
  1250. // format in HRESULT
  1251. cch = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
  1252. | FORMAT_MESSAGE_FROM_STRING
  1253. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  1254. ptzFormat,
  1255. NULL,
  1256. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1257. (PTSTR)&ptzSysMsg,
  1258. 1, (va_list*)&hr);
  1259. delete ptzFormat;
  1260. if (!cch)
  1261. {
  1262. ReportError( hr, 0, hWnd );
  1263. break;
  1264. }
  1265. }
  1266. // prepare argument array
  1267. PVOID* ppvArguments = (PVOID*)new BYTE[(nArguments+1)*sizeof(PVOID)];
  1268. if (!ppvArguments)
  1269. {
  1270. ASSERT(ppvArguments );
  1271. ReportError( hr, 0, hWnd);
  1272. break;
  1273. }
  1274. ppvArguments[0] = ptzSysMsg;
  1275. if (0 != nArguments)
  1276. {
  1277. ::CopyMemory( ppvArguments+1, lpArguments, nArguments*sizeof(PVOID) );
  1278. }
  1279. retval = ReportMessageWorker(hWnd,
  1280. dwMessageId,
  1281. fuStyle,
  1282. ppvArguments,
  1283. nArguments+1,
  1284. dwTitleId,
  1285. hr );
  1286. delete[] ppvArguments;
  1287. ppvArguments = 0;
  1288. } while (FALSE); // false loop
  1289. //
  1290. // cleanup
  1291. //
  1292. if (NULL != ptzSysMsg)
  1293. {
  1294. LocalFree(ptzSysMsg);
  1295. }
  1296. return retval;
  1297. }
  1298. int SpecialMessageBox (HWND,
  1299. LPWSTR pwszMessage,
  1300. LPWSTR pwszTitle,
  1301. DWORD)
  1302. {
  1303. CSpecialMessageBox MBDlg;
  1304. MBDlg.m_title = pwszTitle;
  1305. MBDlg.m_message = pwszMessage;
  1306. int answer = (int)MBDlg.DoModal();
  1307. return answer;
  1308. }
  1309. ///////////////////////////////////////////////////////////////////////////
  1310. // CNameFormatterBase
  1311. HRESULT CNameFormatterBase::Initialize(IN MyBasePathsInfo* pBasePathInfo,
  1312. IN LPCWSTR lpszClassName, IN UINT nStringID)
  1313. {
  1314. CString szFormatString;
  1315. HRESULT hr = _ReadFromDS(pBasePathInfo, lpszClassName, szFormatString);
  1316. if (FAILED(hr))
  1317. {
  1318. // nothing in the display specifiers, load from resource
  1319. if (!szFormatString.LoadString(nStringID))
  1320. {
  1321. // if failed for some reason, use this default
  1322. szFormatString = L"%<givenName> %<initials>. %<sn>";
  1323. }
  1324. }
  1325. Initialize(szFormatString);
  1326. return S_OK;
  1327. }
  1328. HRESULT CNameFormatterBase::_ReadFromDS(IN MyBasePathsInfo* pBasePathInfo,
  1329. IN LPCWSTR lpszClassName,
  1330. OUT CString& szFormatString)
  1331. {
  1332. static LPCWSTR lpszObjectClass = L"displaySpecifier";
  1333. static LPCWSTR lpszSettingsObjectFmt = L"cn=%s-Display";
  1334. static LPCWSTR lpszFormatProperty = L"createDialog";
  1335. szFormatString.Empty();
  1336. if ( (pBasePathInfo == NULL) ||
  1337. (lpszClassName == NULL) || (lpszClassName[0] == NULL) )
  1338. {
  1339. return E_INVALIDARG;
  1340. }
  1341. // get the display specifiers locale container (e.g. 409)
  1342. CComPtr<IADsContainer> spLocaleContainer;
  1343. HRESULT hr = pBasePathInfo->GetDisplaySpecifier(NULL, IID_IADsContainer, (void**)&spLocaleContainer);
  1344. if (FAILED(hr))
  1345. return hr;
  1346. // bind to the settings object
  1347. CString szSettingsObject;
  1348. szSettingsObject.Format(lpszSettingsObjectFmt, lpszClassName);
  1349. CComPtr<IDispatch> spIDispatchObject;
  1350. hr = spLocaleContainer->GetObject((LPWSTR)lpszObjectClass,
  1351. (LPWSTR)(LPCWSTR)szSettingsObject,
  1352. &spIDispatchObject);
  1353. if (FAILED(hr))
  1354. return hr;
  1355. CComPtr<IADs> spSettingsObject;
  1356. hr = spIDispatchObject->QueryInterface(IID_IADs, (void**)&spSettingsObject);
  1357. if (FAILED(hr))
  1358. return hr;
  1359. // get single valued property in string list form
  1360. CComVariant var;
  1361. hr = spSettingsObject->Get((LPWSTR)lpszFormatProperty, &var);
  1362. if (FAILED(hr))
  1363. return hr;
  1364. if (var.vt != VT_BSTR)
  1365. return E_UNEXPECTED;
  1366. szFormatString = var.bstrVal;
  1367. return S_OK;
  1368. }
  1369. BOOL CNameFormatterBase::Initialize(IN LPCWSTR lpszFormattingString)
  1370. {
  1371. TRACE(L"CNameFormatterBase::Initialize(%s)\n", lpszFormattingString);
  1372. _Clear();
  1373. if (lpszFormattingString == NULL)
  1374. {
  1375. return FALSE;
  1376. }
  1377. // copy the formatting string (it will be modified)
  1378. m_lpszFormattingString = new WCHAR[lstrlen(lpszFormattingString)+1];
  1379. wcscpy(m_lpszFormattingString, lpszFormattingString);
  1380. // allocate memory for the arrays
  1381. _AllocateMemory(lpszFormattingString);
  1382. // loop thugh the string and extract tokens
  1383. // Establish string and get the first token
  1384. WCHAR szSeparators[] = L"%>";
  1385. WCHAR* lpszToken = wcstok(m_lpszFormattingString, szSeparators);
  1386. while (lpszToken != NULL)
  1387. {
  1388. // While there are tokens in "string"
  1389. //TRACE( L" %s\n", token );
  1390. if ( (lpszToken[0] == L'<') &&
  1391. !((lpszFormattingString[0] == L'<') && (m_tokenArrCount == 0)) )
  1392. {
  1393. // parameter
  1394. m_tokenArray[m_tokenArrCount].m_bIsParam = TRUE;
  1395. m_tokenArray[m_tokenArrCount].m_nIndex = m_paramArrCount;
  1396. m_lpszParamArr[m_paramArrCount++] = (lpszToken+1);
  1397. }
  1398. else
  1399. {
  1400. // constant
  1401. m_tokenArray[m_tokenArrCount].m_bIsParam = FALSE;
  1402. m_tokenArray[m_tokenArrCount].m_nIndex = m_constArrCount;
  1403. m_lpszConstArr[m_constArrCount++] = lpszToken;
  1404. }
  1405. m_tokenArrCount++;
  1406. /* Get next token: */
  1407. lpszToken = wcstok(NULL, szSeparators);
  1408. } // while
  1409. return TRUE;
  1410. }
  1411. void CNameFormatterBase::SetMapping(IN LPCWSTR* lpszArgMapping, IN int nArgCount)
  1412. {
  1413. if (m_mapArr != NULL)
  1414. {
  1415. delete[] m_mapArr;
  1416. }
  1417. // do the mapping
  1418. m_mapArr = new int[m_paramArrCount];
  1419. for (int kk=0; kk<m_paramArrCount;kk++)
  1420. {
  1421. m_mapArr[kk] = -1; // clear
  1422. for (int jj=0; jj<nArgCount;jj++)
  1423. {
  1424. if (wcscmp(m_lpszParamArr[kk], lpszArgMapping[jj]) == 0)
  1425. {
  1426. m_mapArr[kk] = jj;
  1427. }
  1428. }
  1429. }
  1430. }
  1431. void CNameFormatterBase::Format(OUT CString& szBuffer, IN LPCWSTR* lpszArgArr)
  1432. {
  1433. szBuffer.Empty();
  1434. //TRACE(L"\nResult:#");
  1435. BOOL bLastParamNull = FALSE;
  1436. for (int k=0; k<m_tokenArrCount; k++)
  1437. {
  1438. if (m_tokenArray[k].m_bIsParam)
  1439. {
  1440. if (m_mapArr[m_tokenArray[k].m_nIndex] >= 0)
  1441. {
  1442. LPCWSTR lpszVal = lpszArgArr[m_mapArr[m_tokenArray[k].m_nIndex]];
  1443. if (lpszVal != NULL)
  1444. {
  1445. //TRACE(L"%s", lpszVal);
  1446. szBuffer += lpszVal;
  1447. bLastParamNull = FALSE;
  1448. }
  1449. else
  1450. {
  1451. bLastParamNull = TRUE;
  1452. }
  1453. }
  1454. }
  1455. else
  1456. {
  1457. if (!bLastParamNull)
  1458. {
  1459. //TRACE(L"%s", m_lpszConstArr[m_tokenArray[k].m_nIndex]);
  1460. szBuffer += m_lpszConstArr[m_tokenArray[k].m_nIndex];
  1461. }
  1462. }
  1463. }
  1464. szBuffer.TrimRight(); // in case we got a trailing space.
  1465. //TRACE(L"#\n");
  1466. }
  1467. void CNameFormatterBase::_AllocateMemory(LPCWSTR lpszFormattingString)
  1468. {
  1469. int nFieldCount = 1; // conservative, have at least one
  1470. for (WCHAR* pChar = (WCHAR*)lpszFormattingString; *pChar != NULL; pChar++)
  1471. {
  1472. if (*pChar == L'%')
  1473. {
  1474. nFieldCount++;
  1475. }
  1476. }
  1477. // conservative estimates on array sizes
  1478. m_tokenArray = new CToken[2*nFieldCount];
  1479. m_lpszConstArr = new LPCWSTR[nFieldCount];
  1480. m_lpszParamArr = new LPCWSTR[nFieldCount];
  1481. }
  1482. /////////////////////////////////////////////////////////////////////////////
  1483. // CHelpDialog
  1484. CHelpDialog::CHelpDialog(UINT uIDD, CWnd* pParentWnd) :
  1485. CDialog(uIDD, pParentWnd),
  1486. m_hWndWhatsThis (0)
  1487. {
  1488. }
  1489. CHelpDialog::CHelpDialog(UINT uIDD) :
  1490. CDialog(uIDD),
  1491. m_hWndWhatsThis (0)
  1492. {
  1493. }
  1494. CHelpDialog::~CHelpDialog()
  1495. {
  1496. }
  1497. BEGIN_MESSAGE_MAP(CHelpDialog, CDialog)
  1498. ON_WM_CONTEXTMENU()
  1499. ON_MESSAGE(WM_HELP, OnHelp)
  1500. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1501. END_MESSAGE_MAP()
  1502. /////////////////////////////////////////////////////////////////////////////
  1503. // CHelpDialog message handlers
  1504. void CHelpDialog::OnWhatsThis()
  1505. {
  1506. //
  1507. // Display context help for a control
  1508. //
  1509. if ( m_hWndWhatsThis )
  1510. {
  1511. DoContextHelp (m_hWndWhatsThis);
  1512. }
  1513. }
  1514. BOOL CHelpDialog::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1515. {
  1516. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1517. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1518. {
  1519. //
  1520. // Display context help for a control
  1521. //
  1522. DoContextHelp ((HWND) pHelpInfo->hItemHandle);
  1523. }
  1524. return TRUE;
  1525. }
  1526. void CHelpDialog::DoContextHelp (HWND /*hWndControl*/)
  1527. {
  1528. }
  1529. void CHelpDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1530. {
  1531. //
  1532. // point is in screen coordinates
  1533. //
  1534. CMenu bar;
  1535. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1536. {
  1537. CMenu& popup = *bar.GetSubMenu (0);
  1538. ASSERT(popup.m_hMenu);
  1539. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1540. point.x, // in screen coordinates
  1541. point.y, // in screen coordinates
  1542. this) ) // route commands through main window
  1543. {
  1544. m_hWndWhatsThis = 0;
  1545. ScreenToClient (&point);
  1546. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1547. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1548. if ( pChild )
  1549. {
  1550. m_hWndWhatsThis = pChild->m_hWnd;
  1551. }
  1552. }
  1553. }
  1554. }
  1555. /////////////////////////////////////////////////////////////////////////////
  1556. // CHelpPropertyPage
  1557. CHelpPropertyPage::CHelpPropertyPage(UINT uIDD) :
  1558. CPropertyPage(uIDD),
  1559. m_hWndWhatsThis (0)
  1560. {
  1561. }
  1562. CHelpPropertyPage::~CHelpPropertyPage()
  1563. {
  1564. }
  1565. BEGIN_MESSAGE_MAP(CHelpPropertyPage, CPropertyPage)
  1566. ON_WM_CONTEXTMENU()
  1567. ON_MESSAGE(WM_HELP, OnHelp)
  1568. ON_COMMAND(IDM_WHATS_THIS, OnWhatsThis)
  1569. END_MESSAGE_MAP()
  1570. /////////////////////////////////////////////////////////////////////////////
  1571. // CHelpPropertyPage message handlers
  1572. void CHelpPropertyPage::OnWhatsThis()
  1573. {
  1574. //
  1575. // Display context help for a control
  1576. //
  1577. if ( m_hWndWhatsThis )
  1578. {
  1579. DoContextHelp (m_hWndWhatsThis);
  1580. }
  1581. }
  1582. BOOL CHelpPropertyPage::OnHelp(WPARAM /*wParam*/, LPARAM lParam)
  1583. {
  1584. const LPHELPINFO pHelpInfo = (LPHELPINFO)lParam;
  1585. if (pHelpInfo && pHelpInfo->iContextType == HELPINFO_WINDOW)
  1586. {
  1587. //
  1588. // Display context help for a control
  1589. //
  1590. DoContextHelp ((HWND) pHelpInfo->hItemHandle);
  1591. }
  1592. return TRUE;
  1593. }
  1594. void CHelpPropertyPage::DoContextHelp (HWND /*hWndControl*/)
  1595. {
  1596. }
  1597. void CHelpPropertyPage::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
  1598. {
  1599. //
  1600. // point is in screen coordinates
  1601. //
  1602. CMenu bar;
  1603. if ( bar.LoadMenu(IDR_WHATS_THIS_CONTEXT_MENU1) )
  1604. {
  1605. CMenu& popup = *bar.GetSubMenu (0);
  1606. ASSERT(popup.m_hMenu);
  1607. if ( popup.TrackPopupMenu (TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
  1608. point.x, // in screen coordinates
  1609. point.y, // in screen coordinates
  1610. this) ) // route commands through main window
  1611. {
  1612. m_hWndWhatsThis = 0;
  1613. ScreenToClient (&point);
  1614. CWnd* pChild = ChildWindowFromPoint (point, // in client coordinates
  1615. CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
  1616. if ( pChild )
  1617. {
  1618. m_hWndWhatsThis = pChild->m_hWnd;
  1619. }
  1620. }
  1621. }
  1622. }
  1623. //////////////////////////////////////////////////////////////////
  1624. // CMoreInfoMessageBox
  1625. //
  1626. BEGIN_MESSAGE_MAP(CMoreInfoMessageBox, CDialog)
  1627. ON_BN_CLICKED(ID_BUTTON_MORE_INFO, OnMoreInfo)
  1628. END_MESSAGE_MAP()