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.

1314 lines
38 KiB

  1. // cmndlgs.cpp - Common Dialogs
  2. #include "stdafx.h"
  3. #include <adext.h>
  4. #include <windowsx.h>
  5. #include <algorithm>
  6. #include "cmndlgs.h"
  7. #include "query.h"
  8. #include "rowitem.h"
  9. #include "scopenode.h"
  10. #include "namemap.h"
  11. #include "menuCmd.h"
  12. #include "util.h"
  13. //////////////////////////////////////////////////////////////////////////////////
  14. // CAddColumnDlg
  15. LRESULT CAddColumnDlg::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  16. {
  17. ASSERT(!m_strClassName.empty());
  18. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_strClassName.c_str());
  19. if (pNameMap == NULL)
  20. return TRUE;
  21. SetDlgItemText( IDC_OBJCLASS, pNameMap->GetClassDisplayName() );
  22. pNameMap->GetFriendlyNames(&m_vstrAllColumns);
  23. HWND hwndList = GetDlgItem(IDC_COLUMNLIST);
  24. if( hwndList && ::IsWindow(hwndList) )
  25. {
  26. ConfigSingleColumnListView(hwndList);
  27. if (!m_vstrAllColumns.empty())
  28. {
  29. LV_ITEM lvi;
  30. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  31. lvi.iItem = 0;
  32. lvi.iSubItem = 0;
  33. string_vector::iterator itStr;
  34. for (itStr = m_vstrAllColumns.begin(); itStr != m_vstrAllColumns.end(); itStr++)
  35. {
  36. lvi.pszText = const_cast<LPWSTR>(pNameMap->GetAttributeDisplayName(itStr->c_str()));
  37. lvi.lParam = (LPARAM)itStr->c_str();
  38. int iPos = ListView_InsertItem(hwndList, &lvi);
  39. ASSERT(iPos >= 0);
  40. }
  41. }
  42. }
  43. EnableDlgItem( m_hWnd, IDOK, FALSE );
  44. return TRUE;
  45. }
  46. LRESULT CAddColumnDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  47. {
  48. if (wID == IDOK)
  49. {
  50. HWND hwndList = GetDlgItem(IDC_COLUMNLIST);
  51. ASSERT(hwndList != NULL);
  52. m_vstrColumns.clear();
  53. // copy LDAP names of selected items to vector
  54. int iIndex = -1;
  55. while ((iIndex = ListView_GetNextItem(hwndList, iIndex, LVNI_SELECTED)) != -1)
  56. {
  57. LVITEM lvi;
  58. lvi.mask = LVIF_PARAM;
  59. lvi.iItem = iIndex;
  60. lvi.iSubItem = 0;
  61. BOOL bStat = ListView_GetItem(hwndList, &lvi);
  62. ASSERT(bStat);
  63. m_vstrColumns.push_back(reinterpret_cast<LPWSTR>(lvi.lParam));
  64. }
  65. }
  66. EndDialog(wID);
  67. return 0;
  68. }
  69. LRESULT CAddColumnDlg::OnColumnChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  70. {
  71. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  72. if( !pnmv ) return 0;
  73. // if selection change, update OK button
  74. if ((pnmv->uChanged & LVIF_STATE))
  75. {
  76. EnableDlgItem( m_hWnd, IDOK, (ListView_GetSelectedCount(GetDlgItem(idCtrl)) > 0) );
  77. }
  78. return 0;
  79. }
  80. LRESULT CAddColumnDlg::OnColumnActivate(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  81. {
  82. SendDlgItemMessage( IDOK, BM_CLICK, (WPARAM)0, (LPARAM)0 );
  83. return 0;
  84. }
  85. //////////////////////////////////////////////////////////////////////////////////
  86. // CAddMenuDlg
  87. CAddMenuDlg::~CAddMenuDlg()
  88. {
  89. m_MenuTypeCB.Detach();
  90. DeleteObject(m_hbmArrow);
  91. }
  92. LRESULT CAddMenuDlg::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  93. {
  94. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_ClassInfo.Name());
  95. if (pNameMap == NULL)
  96. return TRUE;
  97. SetDlgItemText( IDC_OBJCLASS, pNameMap->GetClassDisplayName() );
  98. HWND hwndMenuType = GetDlgItem(IDC_COMMANDTYPE);
  99. if( hwndMenuType && ::IsWindow(hwndMenuType) )
  100. {
  101. m_MenuTypeCB.Attach( hwndMenuType );
  102. }
  103. // Set menu arrow bitmap in param menu button
  104. m_hbmArrow = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
  105. if( m_hbmArrow )
  106. {
  107. SendDlgItemMessage( IDC_PARAMS_MENU, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)m_hbmArrow );
  108. }
  109. COMBOBOXEXITEM cbi;
  110. cbi.mask = CBEIF_TEXT|CBEIF_LPARAM;
  111. cbi.iItem = -1;
  112. tstring strMenuType = StrLoadString(IDS_ACTDIRCMD);
  113. cbi.pszText = const_cast<LPWSTR>(strMenuType.c_str());
  114. cbi.lParam = MENUTYPE_ACTDIR;
  115. m_MenuTypeCB.InsertItem(&cbi);
  116. strMenuType = StrLoadString(IDS_SHELLCMD);
  117. cbi.pszText = const_cast<LPWSTR>(strMenuType.c_str());
  118. cbi.lParam = MENUTYPE_SHELL;
  119. m_MenuTypeCB.InsertItem(&cbi);
  120. Edit_LimitText(GetDlgItem(IDC_NAME), 255);
  121. Edit_LimitText(GetDlgItem(IDC_COMMAND), 255);
  122. Edit_LimitText(GetDlgItem(IDC_STARTIN), 500);
  123. LoadClassMenuCmds();
  124. // If editing an existing menu
  125. if (m_pMenuCmd != NULL)
  126. {
  127. // Set name modified so that it won't be changed to default
  128. m_bUserModifiedName = TRUE;
  129. // Display info for selected menu
  130. LoadMenuInfo(m_pMenuCmd);
  131. }
  132. else
  133. {
  134. m_MenuTypeCB.SetCurSel(0);
  135. SetMenuType(MENUTYPE_ACTDIR);
  136. }
  137. m_bCommandChg = FALSE;
  138. m_bStartDirChg = FALSE;
  139. EnableOKButton();
  140. return TRUE;
  141. }
  142. void CAddMenuDlg::LoadMenuInfo(CMenuCmd* pMenuCmd)
  143. {
  144. if( !pMenuCmd ) return;
  145. SetDlgItemText( IDC_NAME, pMenuCmd->Name() );
  146. Button_SetCheck(GetDlgItem(IDC_REFRESH), pMenuCmd->IsAutoRefresh() ? BST_CHECKED : BST_UNCHECKED);
  147. switch (pMenuCmd->MenuType())
  148. {
  149. case MENUTYPE_SHELL:
  150. {
  151. CShellMenuCmd* pShellCmd = static_cast<CShellMenuCmd*>(pMenuCmd);
  152. SetDlgItemText( IDC_COMMAND, pShellCmd->m_strProgPath.c_str() );
  153. SetDlgItemText( IDC_STARTIN, pShellCmd->m_strStartDir.c_str() );
  154. // Convert parameters from LDAP names to display names
  155. tstring strParams = pShellCmd->m_strCmdLine;
  156. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_ClassInfo.Name());
  157. if (pNameMap != NULL)
  158. {
  159. // Create function object to do parameter translation
  160. CLookupDisplayName lookup(m_ClassInfo.Columns(), pNameMap);
  161. ReplaceParameters(strParams, lookup, TRUE);
  162. }
  163. SetDlgItemText( IDC_PARAMS, strParams.c_str() );
  164. m_MenuTypeCB.SetCurSel(1);
  165. SetMenuType(MENUTYPE_SHELL);
  166. }
  167. break;
  168. case MENUTYPE_ACTDIR:
  169. {
  170. CActDirMenuCmd* pADCmd = static_cast<CActDirMenuCmd*>(pMenuCmd);
  171. LVFINDINFO lvfi;
  172. lvfi.flags = LVFI_STRING;
  173. lvfi.psz = pADCmd->m_strADName.c_str();
  174. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  175. int iItem = ListView_FindItem(hwndLV, -1, &lvfi);
  176. if( iItem == -1 )
  177. {
  178. // Couldn't find the language dependant string, try the language independant string
  179. int nItems = ListView_GetItemCount(hwndLV);
  180. for( int i = 0; i < nItems; i++ )
  181. {
  182. LVITEM lvi;
  183. ZeroMemory( &lvi, sizeof(lvi) );
  184. lvi.mask = LVIF_PARAM;
  185. lvi.iItem = i;
  186. ListView_GetItem( hwndLV, &lvi );
  187. if( lvi.lParam )
  188. {
  189. LPCWSTR pszMenuNoLoc = pADCmd->ADNoLocName();
  190. // Compare the stored string with the menu string
  191. if( pszMenuNoLoc && (wcscmp( (LPCWSTR)(lvi.lParam), pszMenuNoLoc ) == 0) )
  192. {
  193. iItem = i;
  194. break;
  195. }
  196. }
  197. }
  198. }
  199. // If we found the string, default the value
  200. if (iItem != -1)
  201. ListView_SetItemState(hwndLV, iItem, LVIS_SELECTED, LVIS_SELECTED);
  202. m_MenuTypeCB.SetCurSel(0);
  203. SetMenuType(MENUTYPE_ACTDIR);
  204. }
  205. break;
  206. default:
  207. ASSERT(FALSE);
  208. }
  209. }
  210. void CAddMenuDlg::LoadClassMenuCmds()
  211. {
  212. // Use a directory extension proxy to query for menu items
  213. // because this dialog may run on a secondary thread and some
  214. // directory extensions (dsadmin.dll!!) can only run on the main thread.
  215. CActDirExtProxy adext;
  216. // Initialize it with selected class name
  217. HRESULT hr = adext.Initialize(m_ClassInfo.Name());
  218. if (FAILED(hr))
  219. return;
  220. // Get menu commands for the selected class
  221. menu_vector vMenuNames;
  222. hr = adext.GetMenuItems(vMenuNames);
  223. if (FAILED(hr))
  224. return;
  225. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  226. ASSERT(::IsWindow(hwndLV));
  227. ConfigSingleColumnListView(hwndLV);
  228. LV_ITEM lvi;
  229. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  230. lvi.iItem = 0;
  231. lvi.iSubItem = 0;
  232. menu_vector::iterator itstr;
  233. for (itstr = vMenuNames.begin(); itstr < vMenuNames.end(); ++itstr)
  234. {
  235. TCHAR* szNoLoc = new TCHAR[itstr->strNoLoc.length() + 1];
  236. if( szNoLoc )
  237. {
  238. _tcscpy(szNoLoc, itstr->strNoLoc.c_str());
  239. }
  240. lvi.pszText = const_cast<LPWSTR>(itstr->strPlain.c_str());
  241. lvi.lParam = reinterpret_cast<LPARAM>(szNoLoc);
  242. int iPos = ListView_InsertItem(hwndLV, &lvi);
  243. ASSERT(iPos >= 0);
  244. if( iPos == -1 )
  245. {
  246. // Error, need to clean up here
  247. delete [] szNoLoc;
  248. continue;
  249. }
  250. // After adding the first item, default the selection to the first item
  251. if( iPos == 0 )
  252. {
  253. ListView_SetItemState(hwndLV, 0, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED);
  254. }
  255. lvi.iItem++;
  256. }
  257. }
  258. LRESULT CAddMenuDlg::OnTypeSelect( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  259. {
  260. int iItem = m_MenuTypeCB.GetCurSel();
  261. ASSERT(iItem >= 0);
  262. if( iItem >= 0 )
  263. {
  264. MENUTYPE type = static_cast<MENUTYPE>(m_MenuTypeCB.GetItemData(iItem));
  265. SetMenuType(type);
  266. }
  267. return 0;
  268. }
  269. LRESULT CAddMenuDlg::OnBrowseForCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  270. {
  271. tstring strCommand;
  272. GetItemText( GetDlgItem(IDC_COMMAND), strCommand );
  273. tstring strFilter = StrLoadString(IDS_EXEFILTER);
  274. /*
  275. * The file dialog expects embedded \0's in the string, but those
  276. * don't load well. The string in the resource file has \\ where
  277. * the \0 should be, so let's make the substitution now.
  278. */
  279. LPTSTR pchTemp = (LPTSTR)strFilter.data();
  280. for( LPTSTR pch = pchTemp; *pch != _T('\0'); pch = pchTemp )
  281. {
  282. pchTemp = CharNext(pch);
  283. if (*pch == _T('\\'))
  284. *pch = _T('\0');
  285. }
  286. // don't call ReleaseBuffer, since the string now contains \0 chars
  287. CFileDialog dlg (true, NULL, strCommand.c_str(), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, strFilter.c_str(), m_hWnd);
  288. if (dlg.DoModal() == IDOK)
  289. {
  290. SetDlgItemText (IDC_COMMAND, dlg.m_szFileName);
  291. }
  292. return (0);
  293. }
  294. // Define private CFolderDialog to handle the OnInitialized callback
  295. class CFolderDialogPriv : public CFolderDialogImpl<CFolderDialogPriv>
  296. {
  297. public:
  298. CFolderDialogPriv(HWND hWndParent, LPCWSTR pszTitle, UINT uFlags, LPCWSTR pszCurFolder )
  299. : CFolderDialogImpl<CFolderDialogPriv>(hWndParent, pszTitle, uFlags), m_pszCurFolder(pszCurFolder) {}
  300. void OnInitialized() { if (m_pszCurFolder) SetSelection(m_pszCurFolder); }
  301. LPCWSTR m_pszCurFolder;
  302. };
  303. LRESULT CAddMenuDlg::OnBrowseForStartIn( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  304. {
  305. tstring strCaption = StrLoadString(IDS_SELECT_STARTDIR);
  306. tstring strDir;
  307. GetItemText( GetDlgItem(IDC_STARTIN), strDir );
  308. CFolderDialogPriv dlg( m_hWnd, strCaption.c_str(), BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE, strDir.c_str() );
  309. if (dlg.DoModal() == IDOK)
  310. SetDlgItemText (IDC_STARTIN, dlg.GetFolderPath());
  311. return (0);
  312. }
  313. LRESULT CAddMenuDlg::OnNameChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  314. {
  315. m_bUserModifiedName = TRUE;
  316. EnableOKButton();
  317. return 0;
  318. }
  319. LRESULT CAddMenuDlg::OnCommandChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  320. {
  321. EnableOKButton();
  322. m_bCommandChg = TRUE;
  323. return 0;
  324. }
  325. LRESULT CAddMenuDlg::OnStartDirChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  326. {
  327. m_bStartDirChg = TRUE;
  328. return 0;
  329. }
  330. LRESULT CAddMenuDlg::OnMenuChanged(int idCtrl, LPNMHDR pNMHDR, BOOL& bHandled)
  331. {
  332. LPNMLISTVIEW pnmv = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
  333. if( !pnmv ) return 0;
  334. // if new item selected user hasn't entered a name, default name to the menu
  335. if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED))
  336. {
  337. // If user hasn't modified the name or the name is empty, default to the menu name
  338. if (!m_bUserModifiedName || ::Edit_GetTextLength(GetDlgItem(IDC_NAME)) == 0)
  339. {
  340. WCHAR szName[256];
  341. ListView_GetItemText(GetDlgItem(IDC_MENULIST), pnmv->iItem, 0, szName, lengthof(szName));
  342. ::Edit_SetText(GetDlgItem(IDC_NAME), szName);
  343. // reset user modified flag becuase it will be set by the Edit_SetText call
  344. m_bUserModifiedName = FALSE;
  345. }
  346. }
  347. EnableOKButton();
  348. return 0;
  349. }
  350. void CAddMenuDlg::EnableOKButton()
  351. {
  352. BOOL bEnable = TRUE;
  353. if (::Edit_GetTextLength(GetDlgItem(IDC_NAME)) == 0)
  354. {
  355. bEnable = FALSE;
  356. }
  357. else
  358. {
  359. if (m_menutype == MENUTYPE_SHELL)
  360. {
  361. if (::Edit_GetTextLength(GetDlgItem(IDC_COMMAND)) == 0)
  362. bEnable = FALSE;
  363. }
  364. else
  365. {
  366. if (ListView_GetSelectedCount(GetDlgItem(IDC_MENULIST)) == 0)
  367. bEnable = FALSE;
  368. }
  369. }
  370. EnableDlgItem( m_hWnd, IDOK, bEnable );
  371. }
  372. void CAddMenuDlg::SetMenuType(MENUTYPE type)
  373. {
  374. static int aiActDirItems[] = {IDC_OBJCLASS_LBL, IDC_OBJCLASS, IDC_MENULIST_LBL, IDC_MENULIST, 0};
  375. static int aiShellItems[] = {IDC_COMMAND_LBL, IDC_COMMAND, IDC_COMMAND_BROWSE, IDC_PARAMS_LBL,
  376. IDC_PARAMS, IDC_STARTIN_LBL, IDC_STARTIN, IDC_STARTIN_BROWSE,
  377. IDC_PARAMS_MENU, 0};
  378. int* piItem = (type == MENUTYPE_SHELL) ? aiActDirItems : aiShellItems;
  379. while (*piItem)
  380. {
  381. EnableDlgItem( m_hWnd, *piItem, FALSE );
  382. ::ShowWindow(GetDlgItem(*piItem), SW_HIDE);
  383. piItem++;
  384. }
  385. piItem = (type == MENUTYPE_SHELL) ? aiShellItems : aiActDirItems;
  386. while (*piItem)
  387. {
  388. ::ShowWindow(GetDlgItem(*piItem), SW_SHOW);
  389. EnableDlgItem( m_hWnd, *piItem, TRUE );
  390. piItem++;
  391. }
  392. m_menutype = type;
  393. EnableOKButton();
  394. }
  395. LRESULT CAddMenuDlg::OnParameterMenu(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  396. {
  397. // Construct parameter menu
  398. CMenu menu;
  399. menu.CreatePopupMenu();
  400. // Add standard parameters first
  401. UINT uID = 1;
  402. for( int i = 0; i < lengthof(MenuParamTable); i++ )
  403. {
  404. if (MenuParamTable[i].ID == 0)
  405. {
  406. menu.AppendMenu(MF_SEPARATOR);
  407. }
  408. else
  409. {
  410. CString str;
  411. str.LoadString(MenuParamTable[i].rsrcID);
  412. menu.AppendMenu(MF_STRING, uID++, str);
  413. }
  414. }
  415. // Then add class attributes
  416. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_ClassInfo.Name());
  417. if (pNameMap != NULL)
  418. {
  419. string_vector& vColumns = m_ClassInfo.Columns();
  420. string_vector::iterator itCol;
  421. for (itCol = vColumns.begin(); itCol != vColumns.end(); itCol++)
  422. {
  423. menu.AppendMenu(MF_STRING, uID++, pNameMap->GetAttributeDisplayName(itCol->c_str()));
  424. }
  425. }
  426. // Pop-up menu at menu button
  427. RECT rc;
  428. ::GetWindowRect(GetDlgItem(IDC_PARAMS_MENU), &rc);
  429. long cx = (rc.right + rc.left) / 2;
  430. long cy = (rc.top + rc.bottom) / 2;
  431. UINT uCmd = menu.TrackPopupMenu(TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RETURNCMD|TPM_LEFTBUTTON,
  432. cx, cy, m_hWnd);
  433. if (uCmd != 0)
  434. {
  435. WCHAR szBuf[128] = {0};
  436. // Convert menu name to parameter format: $<name>
  437. wcscpy(szBuf, L"$<");
  438. // BUGBUG - Don't depend on count returned by GetMenuString. For some locales
  439. // it returns a byte count rather than a character count.
  440. int iLen = menu.GetMenuString(uCmd, szBuf+2, lengthof(szBuf)-5, MF_BYCOMMAND);
  441. ASSERT(iLen != 0);
  442. // Add closing '>' and one trailing space so user can add multiple parameters
  443. // without manually entering separating spaces
  444. wcscat(szBuf, L"> ");
  445. Edit_ReplaceSel(GetDlgItem(IDC_PARAMS), szBuf);
  446. ::SetFocus(GetDlgItem(IDC_PARAMS));
  447. }
  448. return 0;
  449. }
  450. LRESULT CAddMenuDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  451. {
  452. if (wID == IDOK)
  453. {
  454. CMenuCmd* pMenu = NULL;
  455. // Get menu name
  456. tstring strName;
  457. GetItemText( GetDlgItem(IDC_NAME), strName );
  458. // Name without the hotkey
  459. tstring strPlainName = strName;
  460. // Validate hotkey selection
  461. int posKey = strName.find(L"&", 0);
  462. if (posKey != tstring::npos)
  463. {
  464. WCHAR chKey = posKey < strName.length() - 1 ? strName[posKey+1] : 0;
  465. if (!( (chKey >= L'A' && chKey <= L'Z') ||
  466. (chKey >= L'a' && chKey <= L'z') ||
  467. (chKey >= L'0' && chKey <= L'9') ))
  468. {
  469. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_BADACCESSKEY);
  470. return 0;
  471. }
  472. if (strName.find(L"&", posKey+1) != tstring::npos)
  473. {
  474. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_MULTIACCESSKEY);
  475. return 0;
  476. }
  477. // remove '&'
  478. strPlainName.erase(posKey, 1);
  479. }
  480. // Check for duplicated name
  481. menucmd_vector::iterator itMenu;
  482. for (itMenu = m_ClassInfo.Menus().begin(); itMenu != m_ClassInfo.Menus().end(); ++itMenu)
  483. {
  484. // if editing a an existing menu, don't compare to itself
  485. if (*itMenu == m_pMenuCmd)
  486. continue;
  487. // Compare names, skipping '&'s
  488. LPCWSTR pszName = (*itMenu)->Name();
  489. LPCWSTR pszNewName = strPlainName.c_str();
  490. if( pszName && pszNewName )
  491. {
  492. while (*pszName && *pszNewName)
  493. {
  494. if (*pszName == L'&')
  495. ++pszName;
  496. if (*pszName != *pszNewName)
  497. break;
  498. ++pszName;
  499. ++pszNewName;
  500. }
  501. // if duplicate name
  502. if (*pszName == *pszNewName)
  503. {
  504. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_DUPMENUNAME, MB_OK|MB_ICONEXCLAMATION, strPlainName.c_str());
  505. return 0;
  506. }
  507. }
  508. }
  509. switch (m_menutype)
  510. {
  511. case MENUTYPE_SHELL:
  512. {
  513. CShellMenuCmd* pShellMenu = new CShellMenuCmd();
  514. if (pShellMenu != NULL)
  515. {
  516. GetItemText( GetDlgItem(IDC_COMMAND), pShellMenu->m_strProgPath );
  517. if (m_bCommandChg && ValidateFile(pShellMenu->m_strProgPath) != S_OK)
  518. {
  519. int iRet = DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUCMD, IDS_ERROR_MENUCMD,
  520. MB_ICONINFORMATION | MB_YESNO, pShellMenu->m_strProgPath.c_str());
  521. if (iRet != IDYES)
  522. {
  523. delete pShellMenu;
  524. return 0;
  525. }
  526. }
  527. GetItemText( GetDlgItem(IDC_STARTIN), pShellMenu->m_strStartDir );
  528. if (m_bStartDirChg && !pShellMenu->m_strStartDir.empty() &&
  529. ValidateDirectory(pShellMenu->m_strStartDir) != S_OK)
  530. {
  531. int iRet = DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_STARTDIR, IDS_ERROR_STARTDIR,
  532. MB_ICONINFORMATION | MB_YESNO, pShellMenu->m_strStartDir.c_str());
  533. if (iRet != IDYES)
  534. {
  535. delete pShellMenu;
  536. return 0;
  537. }
  538. }
  539. tstring strParams;
  540. GetItemText( GetDlgItem(IDC_PARAMS), strParams );
  541. // Convert parameters from display names to LDAP names
  542. DisplayNameMap* pNameMap = DisplayNames::GetMap(m_ClassInfo.Name());
  543. if (pNameMap != NULL)
  544. {
  545. // Create function object to do parameter translation
  546. CLookupLDAPName lookup(m_ClassInfo.Columns(), pNameMap);
  547. ReplaceParameters(strParams, lookup, TRUE);
  548. }
  549. pShellMenu->m_strCmdLine.erase();
  550. pShellMenu->m_strCmdLine = strParams;
  551. pMenu = pShellMenu;
  552. }
  553. }
  554. break;
  555. case MENUTYPE_ACTDIR:
  556. {
  557. CActDirMenuCmd* pADMenu = new CActDirMenuCmd();
  558. if (pADMenu != NULL)
  559. {
  560. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  561. int iItem = ListView_GetNextItem(hwndLV, -1, LVNI_SELECTED);
  562. ASSERT(iItem != -1);
  563. LV_ITEM lvi;
  564. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  565. lvi.iItem = iItem;
  566. lvi.iSubItem = 0;
  567. WCHAR szBuf[MAX_PATH];
  568. szBuf[0] = 0;
  569. lvi.pszText = szBuf;
  570. lvi.cchTextMax = MAX_PATH;
  571. ListView_GetItem(hwndLV, &lvi);
  572. pADMenu->m_strADName = szBuf;
  573. pADMenu->m_strADNoLocName = (TCHAR*)lvi.lParam;
  574. pMenu = pADMenu;
  575. }
  576. }
  577. break;
  578. default:
  579. ASSERT(FALSE);
  580. }
  581. if (pMenu != NULL)
  582. {
  583. pMenu->m_strName = strName;
  584. m_pMenuCmd = pMenu;
  585. pMenu->SetAutoRefresh(Button_GetCheck(GetDlgItem(IDC_REFRESH)) == BST_CHECKED);
  586. }
  587. }
  588. //Iterate through list and delete lParams
  589. HWND hwndLV = GetDlgItem(IDC_MENULIST);
  590. int nItems = ListView_GetItemCount(hwndLV);
  591. for( int i = 0; i < nItems; i++ )
  592. {
  593. LVITEM lvi;
  594. ZeroMemory( &lvi, sizeof(lvi) );
  595. lvi.mask = LVIF_PARAM;
  596. lvi.iItem = i;
  597. ListView_GetItem( hwndLV, &lvi );
  598. if( lvi.lParam )
  599. {
  600. delete [] (TCHAR*)lvi.lParam;
  601. lvi.lParam = NULL;
  602. ListView_SetItem( hwndLV, &lvi );
  603. }
  604. }
  605. EndDialog(wID);
  606. return 0;
  607. }
  608. //////////////////////////////////////////////////////////////////////////////////
  609. // CAddQNMenuDlg
  610. LRESULT CAddQNMenuDlg::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  611. {
  612. // If editing an existing menu
  613. if (m_pMenuCmd != NULL)
  614. {
  615. // Set name modified so that it won't be changed to default
  616. m_bUserModifiedName = TRUE;
  617. // Display info for selected menu
  618. LoadMenuInfo(m_pMenuCmd);
  619. }
  620. m_bCommandChg = FALSE;
  621. m_bStartDirChg = FALSE;
  622. EnableOKButton();
  623. return TRUE;
  624. }
  625. void CAddQNMenuDlg::LoadMenuInfo(CMenuCmd* pMenuCmd)
  626. {
  627. SetDlgItemText( IDC_NAME, pMenuCmd->Name() );
  628. Button_SetCheck(GetDlgItem(IDC_REFRESH), pMenuCmd->IsAutoRefresh() ? BST_CHECKED : BST_UNCHECKED);
  629. CShellMenuCmd* pShellCmd = static_cast<CShellMenuCmd*>(pMenuCmd);
  630. SetDlgItemText( IDC_COMMAND, pShellCmd->m_strProgPath.c_str() );
  631. SetDlgItemText( IDC_STARTIN, pShellCmd->m_strStartDir.c_str() );
  632. SetDlgItemText( IDC_PARAMS, pShellCmd->m_strCmdLine.c_str() );
  633. SetMenuType(MENUTYPE_SHELL);
  634. }
  635. LRESULT CAddQNMenuDlg::OnBrowseForCommand( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  636. {
  637. tstring strCommand;
  638. GetItemText( GetDlgItem(IDC_COMMAND), strCommand );
  639. tstring strFilter = StrLoadString(IDS_EXEFILTER);
  640. /*
  641. * The file dialog expects embedded \0's in the string, but those
  642. * don't load well. The string in the resource file has \\ where
  643. * the \0 should be, so let's make the substitution now.
  644. */
  645. LPTSTR pchTemp = (LPTSTR)strFilter.data();
  646. for (LPTSTR pch = pchTemp; *pch != _T('\0'); pch = pchTemp )
  647. {
  648. pchTemp = CharNext(pch);
  649. if (*pch == _T('\\'))
  650. *pch = _T('\0');
  651. }
  652. // don't call ReleaseBuffer, since the string now contains \0 chars
  653. CFileDialog dlg (true, NULL, strCommand.c_str(), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, strFilter.c_str(), m_hWnd);
  654. if (dlg.DoModal() == IDOK)
  655. {
  656. SetDlgItemText (IDC_COMMAND, dlg.m_szFileName);
  657. }
  658. return (0);
  659. }
  660. LRESULT CAddQNMenuDlg::OnBrowseForStartIn( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  661. {
  662. tstring strCaption = StrLoadString(IDS_SELECT_STARTDIR);
  663. tstring strDir;
  664. GetItemText( GetDlgItem(IDC_STARTIN), strDir );
  665. CFolderDialogPriv dlg( m_hWnd, strCaption.c_str(), BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE, strDir.c_str() );
  666. if (dlg.DoModal() == IDOK)
  667. {
  668. SetDlgItemText (IDC_STARTIN, dlg.GetFolderPath());
  669. }
  670. return (0);
  671. }
  672. LRESULT CAddQNMenuDlg::OnNameChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  673. {
  674. m_bUserModifiedName = TRUE;
  675. EnableOKButton();
  676. return 0;
  677. }
  678. LRESULT CAddQNMenuDlg::OnCommandChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  679. {
  680. EnableOKButton();
  681. m_bCommandChg = TRUE;
  682. return 0;
  683. }
  684. LRESULT CAddQNMenuDlg::OnStartDirChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  685. {
  686. m_bStartDirChg = TRUE;
  687. return 0;
  688. }
  689. void CAddQNMenuDlg::EnableOKButton()
  690. {
  691. BOOL bEnable = TRUE;
  692. if (::Edit_GetTextLength(GetDlgItem(IDC_NAME)) == 0)
  693. {
  694. bEnable = FALSE;
  695. }
  696. else
  697. {
  698. if (::Edit_GetTextLength(GetDlgItem(IDC_COMMAND)) == 0)
  699. bEnable = FALSE;
  700. }
  701. EnableDlgItem( m_hWnd, IDOK, bEnable );
  702. }
  703. void CAddQNMenuDlg::SetMenuType(MENUTYPE type)
  704. {
  705. m_menutype = type;
  706. EnableOKButton();
  707. }
  708. LRESULT CAddQNMenuDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  709. {
  710. if (wID == IDOK)
  711. {
  712. CMenuCmd* pMenu = NULL;
  713. // Get menu name
  714. tstring strName;
  715. GetItemText( GetDlgItem(IDC_NAME), strName );
  716. // Name without the hotkey
  717. tstring strPlainName = strName;
  718. // Validate hotkey selection
  719. int posKey = strName.find(L"&", 0);
  720. if (posKey != tstring::npos)
  721. {
  722. WCHAR chKey = posKey < strName.size() - 1 ? strName[posKey+1] : 0;
  723. if (!( (chKey >= L'A' && chKey <= L'Z') ||
  724. (chKey >= L'a' && chKey <= L'z') ||
  725. (chKey >= L'0' && chKey <= L'9') ))
  726. {
  727. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_BADACCESSKEY);
  728. return 0;
  729. }
  730. if (strName.find(L"&", posKey+1) != tstring::npos)
  731. {
  732. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_MULTIACCESSKEY);
  733. return 0;
  734. }
  735. // remove '&'
  736. strPlainName.erase(posKey, 1);
  737. }
  738. // Check for duplicated name
  739. menucmd_vector::iterator itMenu;
  740. for (itMenu = m_EditObject.Menus().begin(); itMenu != m_EditObject.Menus().end(); ++itMenu)
  741. {
  742. // if editing a an existing menu, don't compare to itself
  743. if (*itMenu == m_pMenuCmd)
  744. continue;
  745. // Compare names, skipping '&'s
  746. LPCWSTR pszName = (*itMenu)->Name();
  747. LPCWSTR pszNewName = strPlainName.c_str();
  748. while (*pszName && *pszNewName)
  749. {
  750. if (*pszName == L'&')
  751. ++pszName;
  752. if (*pszName != *pszNewName)
  753. break;
  754. ++pszName;
  755. ++pszNewName;
  756. }
  757. // if duplicate name
  758. if (*pszName == *pszNewName)
  759. {
  760. DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUNAME, IDS_ERROR_DUPMENUNAME, MB_OK|MB_ICONEXCLAMATION, strPlainName.c_str());
  761. return 0;
  762. }
  763. }
  764. CShellMenuCmd* pShellMenu = new CShellMenuCmd();
  765. if (pShellMenu != NULL)
  766. {
  767. GetItemText( GetDlgItem(IDC_COMMAND), pShellMenu->m_strProgPath );
  768. if (m_bCommandChg && ValidateFile(pShellMenu->m_strProgPath) != S_OK)
  769. {
  770. int iRet = DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_MENUCMD, IDS_ERROR_MENUCMD,
  771. MB_ICONINFORMATION | MB_YESNO, pShellMenu->m_strProgPath.c_str());
  772. if (iRet != IDYES)
  773. {
  774. delete pShellMenu;
  775. return 0;
  776. }
  777. }
  778. GetItemText( GetDlgItem(IDC_STARTIN), pShellMenu->m_strStartDir );
  779. if (m_bStartDirChg && !pShellMenu->m_strStartDir.empty() &&
  780. ValidateDirectory(pShellMenu->m_strStartDir) != S_OK)
  781. {
  782. int iRet = DisplayMessageBox(m_hWnd, IDS_ERRORTITLE_STARTDIR, IDS_ERROR_STARTDIR,
  783. MB_ICONINFORMATION | MB_YESNO, pShellMenu->m_strStartDir.c_str());
  784. if (iRet != IDYES)
  785. {
  786. delete pShellMenu;
  787. return 0;
  788. }
  789. }
  790. tstring strParams;
  791. GetItemText( GetDlgItem(IDC_PARAMS), strParams );
  792. pShellMenu->m_strCmdLine.erase();
  793. pShellMenu->m_strCmdLine = strParams;
  794. pMenu = pShellMenu;
  795. }
  796. if (pMenu != NULL)
  797. {
  798. pMenu->m_strName = strName;
  799. m_pMenuCmd = pMenu;
  800. pMenu->SetAutoRefresh(Button_GetCheck(GetDlgItem(IDC_REFRESH)) == BST_CHECKED);
  801. }
  802. }
  803. EndDialog(wID);
  804. return 0;
  805. }
  806. //////////////////////////////////////////////////////////////////////////////////////////////
  807. // Add Group Node Dialog
  808. LRESULT CAddGroupNodeDlg::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  809. {
  810. EnableDlgItem( m_hWnd, IDC_SCOPE_LBL, FALSE );
  811. EnableDlgItem( m_hWnd, IDC_SCOPE, FALSE );
  812. EnableDlgItem( m_hWnd, IDC_SCOPE_BROWSE, FALSE );
  813. EnableDlgItem( m_hWnd, IDC_FILTER_LBL, FALSE );
  814. EnableDlgItem( m_hWnd, IDC_FILTER, FALSE );
  815. EnableDlgItem( m_hWnd, IDOK, FALSE );
  816. SendDlgItemMessage( IDC_NAME, EM_LIMITTEXT, 255, 0);
  817. return TRUE;
  818. }
  819. LRESULT CAddGroupNodeDlg::OnApplyScopeClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  820. {
  821. BOOL bEnable = Button_GetCheck(GetDlgItem(IDC_APPLYSCOPE)) == BST_CHECKED;
  822. EnableDlgItem( m_hWnd, IDC_SCOPE_LBL, bEnable );
  823. EnableDlgItem( m_hWnd, IDC_SCOPE, bEnable );
  824. EnableDlgItem( m_hWnd, IDC_SCOPE_BROWSE, bEnable );
  825. EnableOKButton();
  826. return 0;
  827. }
  828. LRESULT CAddGroupNodeDlg::OnApplyFilterClicked(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  829. {
  830. BOOL bEnable = Button_GetCheck(GetDlgItem(IDC_APPLYFILTER)) == BST_CHECKED;
  831. EnableDlgItem( m_hWnd, IDC_FILTER_LBL, bEnable );
  832. EnableDlgItem( m_hWnd, IDC_FILTER, bEnable );
  833. EnableOKButton();
  834. return 0;
  835. }
  836. LRESULT CAddGroupNodeDlg::OnScopeBrowse(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  837. {
  838. HRESULT hr = GetQueryScope(m_hWnd, m_strScope);
  839. if (hr == S_OK)
  840. {
  841. tstring strDisplay;
  842. GetScopeDisplayString(m_strScope, strDisplay);
  843. SetDlgItemText( IDC_SCOPE, strDisplay.c_str() );
  844. }
  845. EnableOKButton();
  846. return 0;
  847. }
  848. LRESULT CAddGroupNodeDlg::OnEditChange( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  849. {
  850. EnableOKButton();
  851. return 0;
  852. }
  853. void CAddGroupNodeDlg::EnableOKButton()
  854. {
  855. BOOL bEnable;
  856. if ( (::Edit_GetTextLength(GetDlgItem(IDC_NAME)) == 0) ||
  857. (Button_GetCheck(GetDlgItem(IDC_APPLYFILTER)) == BST_CHECKED &&
  858. ::Edit_GetTextLength(GetDlgItem(IDC_FILTER)) == 0) ||
  859. (Button_GetCheck(GetDlgItem(IDC_APPLYSCOPE)) == BST_CHECKED &&
  860. m_strScope.size() == 0) )
  861. {
  862. bEnable = FALSE;
  863. }
  864. else
  865. {
  866. bEnable = TRUE;
  867. }
  868. EnableDlgItem( m_hWnd, IDOK, bEnable );
  869. }
  870. LRESULT CAddGroupNodeDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  871. {
  872. if (wID == IDOK)
  873. {
  874. if( !m_pnode ) return 0;
  875. bool bScope = Button_GetCheck(GetDlgItem(IDC_APPLYSCOPE)) == BST_CHECKED;
  876. m_pnode->SetApplyScope(bScope);
  877. m_pnode->SetScope(m_strScope.c_str());
  878. bool bFilter = Button_GetCheck(GetDlgItem(IDC_APPLYFILTER)) == BST_CHECKED;
  879. m_pnode->SetApplyFilter(bFilter);
  880. tstring strFilter;
  881. GetItemText( GetDlgItem(IDC_FILTER), strFilter );
  882. m_pnode->SetFilter(strFilter.c_str());
  883. GetItemText( GetDlgItem(IDC_NAME), m_strName );
  884. }
  885. EndDialog(wID);
  886. return 0;
  887. }
  888. //////////////////////////////////////////////////////////////////////////////////
  889. // CMoveQueryDlg
  890. LRESULT CMoveQueryDlg::OnInitDialog( UINT mMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled )
  891. {
  892. if( !m_pnodeCurFolder ) return 0;
  893. CRootNode* pRootNode = m_pnodeCurFolder->GetRootNode();
  894. if( !pRootNode ) return 0;
  895. HWND hwndTree = GetDlgItem(IDC_FOLDERTREE);
  896. // Create a node image list and assign to folder tree
  897. CImageList images;
  898. if (images.Create(IDB_QUERY16, 16, 100, RGB(255,0,255)))
  899. TreeView_SetImageList(hwndTree, images.Detach(), TVSIL_NORMAL);
  900. // Set snap-in root node as root of tree
  901. TV_INSERTSTRUCT tvi;
  902. tvi.hParent = TVI_ROOT;
  903. tvi.hInsertAfter = TVI_ROOT;
  904. tvi.item.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
  905. tvi.item.pszText = const_cast<LPWSTR>(pRootNode->GetName());
  906. tvi.item.iImage = pRootNode->GetImage();
  907. tvi.item.iSelectedImage = tvi.item.iImage;
  908. tvi.item.lParam = reinterpret_cast<LPARAM>(pRootNode);
  909. HTREEITEM hti = TreeView_InsertItem(hwndTree, &tvi);
  910. if( !hti ) return 0;
  911. // Insert all group nodes as children of root
  912. tvi.hParent = hti;
  913. tvi.hInsertAfter = TVI_LAST;
  914. CScopeNode* pnode = pRootNode->FirstChild();
  915. while (pnode != NULL)
  916. {
  917. if (pnode->NodeType() == GROUP_NODETYPE)
  918. {
  919. tvi.item.pszText = const_cast<LPWSTR>(pnode->GetName());
  920. tvi.item.iImage = pnode->GetImage();
  921. tvi.item.iSelectedImage = tvi.item.iImage;
  922. tvi.item.lParam = reinterpret_cast<LPARAM>(pnode);
  923. HTREEITEM hti2 = TreeView_InsertItem(hwndTree, &tvi);
  924. ASSERT(hti2 != NULL);
  925. }
  926. pnode = pnode->Next();
  927. }
  928. // Show the group nodes
  929. TreeView_Expand(hwndTree, hti, TVE_EXPAND);
  930. return TRUE;
  931. }
  932. LRESULT CMoveQueryDlg::OnClose( WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled )
  933. {
  934. if( (wID == IDOK) && m_ppnodeDestFolder )
  935. {
  936. HWND hwndTree = GetDlgItem(IDC_FOLDERTREE);
  937. // Get the node pointer (lparam) of the selected tree item
  938. HTREEITEM hti = TreeView_GetSelection(hwndTree);
  939. if( !hti ) return 0;
  940. TVITEM tvi;
  941. tvi.hItem = hti;
  942. tvi.mask = TVIF_PARAM;
  943. tvi.lParam = NULL;
  944. BOOL bStat = TreeView_GetItem(hwndTree, &tvi);
  945. ASSERT(bStat && tvi.lParam != NULL);
  946. *m_ppnodeDestFolder = reinterpret_cast<CScopeNode*>(tvi.lParam);
  947. }
  948. EndDialog(wID);
  949. return 0;
  950. }
  951. ////////////////////////////////////////////////////////////////////////////////////
  952. // Parameter translation classes
  953. //
  954. // LDAP to Display translator
  955. BOOL CLookupDisplayName::operator() (tstring& strParam, tstring& strValue)
  956. {
  957. // Check for special parameter ID value
  958. if (strParam.size() == 1 && strParam[0] <= MENU_PARAM_LAST)
  959. {
  960. // Find entry in param table and return display string
  961. for (int i = 0; i<lengthof(MenuParamTable); i++)
  962. {
  963. if (MenuParamTable[i].ID == strParam[0])
  964. {
  965. CString str;
  966. str.LoadString(MenuParamTable[i].rsrcID);
  967. strValue = str;
  968. return TRUE;
  969. }
  970. }
  971. }
  972. // check for class attribute name
  973. string_vector::iterator itstr = std::find(m_vstrParam.begin(), m_vstrParam.end(), strParam);
  974. if (itstr == m_vstrParam.end())
  975. return FALSE;
  976. strValue = m_pNameMap->GetAttributeDisplayName(itstr->c_str());
  977. return TRUE;
  978. }
  979. // Display to LDAP translator
  980. BOOL CLookupLDAPName::operator() (tstring& strParam, tstring& strValue)
  981. {
  982. // Check for standard parameter name
  983. for (int i=0; i<lengthof(MenuParamTable); i++)
  984. {
  985. CString str;
  986. str.LoadString(MenuParamTable[i].rsrcID);
  987. // if match, return single wchar equal to param ID
  988. if (_wcsicmp(strParam.c_str(), str) == 0)
  989. {
  990. strValue = (WCHAR)MenuParamTable[i].ID;
  991. return TRUE;
  992. }
  993. }
  994. // Check for class attribute display name
  995. string_vector::iterator itstr;
  996. for (itstr = m_vstrParam.begin(); itstr != m_vstrParam.end(); ++itstr)
  997. {
  998. if (_wcsicmp(strParam.c_str(), m_pNameMap->GetAttributeDisplayName(itstr->c_str())) == 0)
  999. {
  1000. strValue = (*itstr);
  1001. return TRUE;
  1002. }
  1003. }
  1004. return FALSE;
  1005. }