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.

1106 lines
26 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1996.
  5. //
  6. // File: selprog.cxx
  7. //
  8. // Contents: Task wizard program selection property page implementation.
  9. //
  10. // Classes: CSelectProgramPage
  11. //
  12. // History: 4-28-1997 DavidMun Created
  13. //
  14. //---------------------------------------------------------------------------
  15. #include "..\pch\headers.hxx"
  16. #pragma hdrstop
  17. #include "myheaders.hxx"
  18. #include "commdlg.h"
  19. #include "..\schedui\rc.h"
  20. #include "..\inc\resource.h"
  21. //
  22. // Types
  23. //
  24. // COLUMNS - indexes to the columns in the listview displaying the results
  25. // of walking the start menu
  26. //
  27. enum COLUMNS
  28. {
  29. COL_APP,
  30. COL_VERSION,
  31. NUM_COLUMNS
  32. };
  33. //
  34. // Forward references
  35. //
  36. INT
  37. InsertSmallIcon(
  38. HIMAGELIST hSmallImageList,
  39. LPCTSTR tszExeName);
  40. //
  41. // Externals
  42. //
  43. extern HICON
  44. GetDefaultAppIcon(
  45. BOOL fLarge);
  46. //+--------------------------------------------------------------------------
  47. //
  48. // Member: CSelectProgramPage::CSelectProgramPage
  49. //
  50. // Synopsis: ctor
  51. //
  52. // Arguments: [ptszFolderPath] - full path to tasks folder with dummy
  53. // filename appended
  54. // [phPSP] - filled with prop page handle
  55. //
  56. // History: 4-28-1997 DavidMun Created
  57. //
  58. //---------------------------------------------------------------------------
  59. CSelectProgramPage::CSelectProgramPage(
  60. CTaskWizard *pParent,
  61. LPTSTR ptszFolderPath,
  62. HPROPSHEETPAGE *phPSP):
  63. CWizPage(MAKEINTRESOURCE(IDD_SELECT_PROGRAM), ptszFolderPath)
  64. {
  65. TRACE_CONSTRUCTOR(CSelectProgramPage);
  66. _hwndLV = NULL;
  67. _pSelectedLinkInfo = NULL;
  68. _idxSelectedIcon = 0;
  69. _fUseBrowseSelection = FALSE;
  70. _tszExePath[0] = TEXT('\0');
  71. _tszExeName[0] = TEXT('\0');
  72. _CreatePage(IDS_SELPROG_HDR1, IDS_SELPROG_HDR2, phPSP);
  73. }
  74. //+--------------------------------------------------------------------------
  75. //
  76. // Member: CSelectProgramPage::~CSelectProgramPage
  77. //
  78. // Synopsis: dtor
  79. //
  80. // History: 4-28-1997 DavidMun Created
  81. //
  82. //---------------------------------------------------------------------------
  83. CSelectProgramPage::~CSelectProgramPage()
  84. {
  85. TRACE_DESTRUCTOR(CSelectProgramPage);
  86. }
  87. //===========================================================================
  88. //
  89. // CPropPage overrides
  90. //
  91. //===========================================================================
  92. //+--------------------------------------------------------------------------
  93. //
  94. // Member: CSelectProgramPage::_OnCommand
  95. //
  96. // Synopsis: Handle the browse button being clicked, ignore all else.
  97. //
  98. // History: 5-20-1997 DavidMun Created
  99. //
  100. //---------------------------------------------------------------------------
  101. LRESULT
  102. CSelectProgramPage::_OnCommand(
  103. int id,
  104. HWND hwndCtl,
  105. UINT codeNotify)
  106. {
  107. TRACE_METHOD(CSelectProgramPage, _OnCommand);
  108. LRESULT lr = 0;
  109. if (codeNotify == BN_CLICKED && id == selprogs_browse_pb)
  110. {
  111. _OnBrowse();
  112. }
  113. else
  114. {
  115. lr = 1; // not handled
  116. }
  117. return lr;
  118. }
  119. //+--------------------------------------------------------------------------
  120. //
  121. // Member: CSelectProgramPage::_OnInitDialog
  122. //
  123. // Synopsis: Perform initialization that should only occur once.
  124. //
  125. // Arguments: [lParam] - LPPROPSHEETPAGE used to create this page
  126. //
  127. // Returns: TRUE (let windows set focus)
  128. //
  129. // History: 5-20-1997 DavidMun Created
  130. //
  131. //---------------------------------------------------------------------------
  132. LRESULT
  133. CSelectProgramPage::_OnInitDialog(
  134. LPARAM lParam)
  135. {
  136. TRACE_METHOD(CSelectProgramPage, _OnInitDialog);
  137. HRESULT hr = S_OK;
  138. // Policy dictates whether we have a browse button or not
  139. // true means don't allow us to browse
  140. if (RegReadPolicyKey(TS_KEYPOLICY_DENY_BROWSE))
  141. {
  142. DEBUG_OUT((DEB_ITRACE, "Policy DENY_BROWSE active - removing browse btn\n"));
  143. EnableWindow(_hCtrl(selprogs_browse_pb), FALSE);
  144. ShowWindow(_hCtrl(selprogs_browse_pb), SW_HIDE);
  145. ShowWindow(_hCtrl(selprogs_static_text_browse), SW_HIDE);
  146. }
  147. // Next not enabled till user picks app
  148. _SetWizButtons(PSWIZB_BACK);
  149. _hwndLV = _hCtrl(selprog_programs_lv);
  150. hr = _InitListView();
  151. if (SUCCEEDED(hr))
  152. {
  153. _PopulateListView();
  154. }
  155. return (HRESULT) TRUE; // wm_initdialog wants BOOL for setfocus info
  156. }
  157. //+--------------------------------------------------------------------------
  158. //
  159. // Member: CSelectProgramPage::_OnPSNSetActive
  160. //
  161. // Synopsis: Enable the Next button if an item has been selected in the
  162. // listview.
  163. //
  164. // History: 5-20-1997 DavidMun Created
  165. //
  166. //---------------------------------------------------------------------------
  167. LRESULT
  168. CSelectProgramPage::_OnPSNSetActive(
  169. LPARAM lParam)
  170. {
  171. _fUseBrowseSelection = FALSE;
  172. if (_pSelectedLinkInfo)
  173. {
  174. _SetWizButtons(PSWIZB_BACK | PSWIZB_NEXT);
  175. }
  176. else
  177. {
  178. _SetWizButtons(PSWIZB_BACK);
  179. }
  180. return CPropPage::_OnPSNSetActive(lParam);
  181. }
  182. //+--------------------------------------------------------------------------
  183. //
  184. // Member: CSelectProgramPage::_OnDestroy
  185. //
  186. // Synopsis: Free all the linkinfos stored as user data in the listview.
  187. //
  188. // History: 5-20-1997 DavidMun Created
  189. //
  190. //---------------------------------------------------------------------------
  191. LRESULT
  192. CSelectProgramPage::_OnDestroy()
  193. {
  194. DEBUG_ASSERT(IsWindow(_hwndLV));
  195. ULONG cItems = ListView_GetItemCount(_hwndLV);
  196. ULONG i;
  197. LV_ITEM lvi;
  198. ZeroMemory(&lvi, sizeof lvi);
  199. lvi.mask = LVIF_PARAM;
  200. for (i = 0; i < cItems; i++)
  201. {
  202. lvi.iItem = i;
  203. lvi.lParam = 0;
  204. BOOL fOk = ListView_GetItem(_hwndLV, &lvi);
  205. if (fOk)
  206. {
  207. delete (LINKINFO *) lvi.lParam;
  208. }
  209. else
  210. {
  211. DEBUG_OUT_LASTERROR;
  212. }
  213. }
  214. return 0;
  215. }
  216. //+--------------------------------------------------------------------------
  217. //
  218. // Member: CSelectProgramPage::_ProcessListViewNotifications
  219. //
  220. // Synopsis: If the user makes a selection in the listview, remember the
  221. // associated linkinfo and enable the next button.
  222. //
  223. // Returns: FALSE
  224. //
  225. // History: 5-20-1997 DavidMun Created
  226. //
  227. // Notes: Ignores all other notifications.
  228. //
  229. //---------------------------------------------------------------------------
  230. BOOL
  231. CSelectProgramPage::_ProcessListViewNotifications(
  232. UINT uMsg,
  233. WPARAM wParam,
  234. LPARAM lParam)
  235. {
  236. UINT code = ((LPNMHDR)lParam)->code;
  237. if (((LPNMHDR)lParam)->idFrom != selprog_programs_lv)
  238. {
  239. return FALSE;
  240. }
  241. DEBUG_ASSERT(code != LVN_GETDISPINFO); // not using callbacks
  242. DEBUG_ASSERT(code != LVN_SETDISPINFO); // items are r/o
  243. if (code == LVN_ITEMCHANGED)
  244. {
  245. NM_LISTVIEW *pnmLV = (NM_LISTVIEW *) lParam;
  246. if ((pnmLV->uChanged & LVIF_STATE) &&
  247. (pnmLV->uNewState & LVIS_SELECTED))
  248. {
  249. // translate the index into a LinkInfo pointer
  250. LV_ITEM lvi;
  251. lvi.iItem = pnmLV->iItem;
  252. lvi.iSubItem = 0;
  253. lvi.mask = LVIF_PARAM | LVIF_IMAGE;
  254. if (!ListView_GetItem(_hwndLV, &lvi))
  255. {
  256. DEBUG_OUT_LASTERROR;
  257. return FALSE;
  258. }
  259. _pSelectedLinkInfo = (LINKINFO *) lvi.lParam;
  260. _idxSelectedIcon = lvi.iImage;
  261. _SetWizButtons(PSWIZB_BACK | PSWIZB_NEXT);
  262. }
  263. }
  264. return FALSE;
  265. }
  266. //===========================================================================
  267. //
  268. // CSelectProgramPage members
  269. //
  270. //===========================================================================
  271. //+--------------------------------------------------------------------------
  272. //
  273. // Member: CSelectProgramPage::GetDefaultDisplayName
  274. //
  275. // Synopsis: Fill [tszDisplayName] with the string to offer the user
  276. // as the new task object name.
  277. //
  278. // Arguments: [tszDisplayName] - buffer to receive string
  279. // [cchDisplayName] - size, in chars, of buffer
  280. //
  281. // Modifies: *[tszDisplayName]
  282. //
  283. // History: 5-20-1997 DavidMun Created
  284. //
  285. //---------------------------------------------------------------------------
  286. VOID
  287. CSelectProgramPage::GetDefaultDisplayName(
  288. LPTSTR tszDisplayName,
  289. ULONG cchDisplayName)
  290. {
  291. LPTSTR ptszToCopy;
  292. if (_fUseBrowseSelection)
  293. {
  294. ptszToCopy = _tszExeName;
  295. }
  296. else if (*_pSelectedLinkInfo->szLnkName)
  297. {
  298. ptszToCopy = _pSelectedLinkInfo->szLnkName;
  299. }
  300. else
  301. {
  302. ptszToCopy = _pSelectedLinkInfo->szExeName;
  303. }
  304. lstrcpyn(tszDisplayName, ptszToCopy, cchDisplayName);
  305. //
  306. // Truncate at the file extension
  307. //
  308. LPTSTR ptszExt = PathFindExtension(tszDisplayName);
  309. if (ptszExt)
  310. {
  311. *ptszExt = TEXT('\0');
  312. }
  313. }
  314. //+--------------------------------------------------------------------------
  315. //
  316. // Member: CSelectProgramPage::GetSelectedAppIcon
  317. //
  318. // Synopsis: Retrieve the icon associated with the selected appliation.
  319. //
  320. // Returns: The selected app's small icon, or NULL if no small icon is
  321. // available.
  322. //
  323. // History: 5-20-1997 DavidMun Created
  324. //
  325. //---------------------------------------------------------------------------
  326. HICON
  327. CSelectProgramPage::GetSelectedAppIcon()
  328. {
  329. if (_fUseBrowseSelection)
  330. {
  331. HICON hicon = NULL;
  332. TCHAR tszFullPath[MAX_PATH];
  333. GetExeFullPath(tszFullPath, ARRAYLEN(tszFullPath));
  334. ExtractIconEx(tszFullPath, 0, NULL, &hicon, 1);
  335. return hicon;
  336. }
  337. if (_idxSelectedIcon == -1)
  338. {
  339. return NULL;
  340. }
  341. HIMAGELIST hSmallImageList = ListView_GetImageList(_hwndLV, LVSIL_SMALL);
  342. if (!hSmallImageList)
  343. {
  344. return NULL;
  345. }
  346. return ImageList_ExtractIcon(0, hSmallImageList, _idxSelectedIcon);
  347. }
  348. //+--------------------------------------------------------------------------
  349. //
  350. // Member: CSelectProgramPage::_InitListView
  351. //
  352. // Synopsis: Initialize the listview's columns and image lists.
  353. //
  354. // Returns: HRESULT
  355. //
  356. // History: 5-20-1997 DavidMun Created
  357. //
  358. //---------------------------------------------------------------------------
  359. HRESULT
  360. CSelectProgramPage::_InitListView()
  361. {
  362. HRESULT hr = S_OK;
  363. HIMAGELIST himlSmall = NULL;
  364. INT cxSmall = GetSystemMetrics(SM_CXSMICON);
  365. INT cySmall = GetSystemMetrics(SM_CYSMICON);
  366. DWORD dwFlag = ILC_MASK;
  367. do
  368. {
  369. if (!_hwndLV || !cxSmall || !cySmall)
  370. {
  371. hr = E_UNEXPECTED;
  372. DEBUG_OUT_HRESULT(hr);
  373. break;
  374. }
  375. //
  376. // Create the listview image list. Only the small image list is
  377. // required, since this listview will be restricted to report
  378. // mode.
  379. //
  380. #ifdef UNICODE
  381. if (GetWindowLongPtr(_hwndLV, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) {
  382. dwFlag |= ILC_MIRROR;
  383. }
  384. #endif
  385. himlSmall = ImageList_Create(cxSmall, cySmall, dwFlag, 1, 1);
  386. if (!himlSmall)
  387. {
  388. hr = HRESULT_FROM_LASTERROR;
  389. DEBUG_OUT_LASTERROR;
  390. break;
  391. }
  392. // Add the generic icon
  393. HICON hiconGeneric = GetDefaultAppIcon(FALSE);
  394. DEBUG_ASSERT(hiconGeneric);
  395. INT index = ImageList_AddIcon(himlSmall, hiconGeneric);
  396. DEBUG_ASSERT(index != -1);
  397. // Assign the image list to the listview
  398. if (!ListView_SetImageList(_hwndLV, himlSmall, LVSIL_SMALL))
  399. {
  400. himlSmall = NULL;
  401. }
  402. else
  403. {
  404. hr = HRESULT_FROM_LASTERROR;
  405. DEBUG_OUT_LASTERROR;
  406. break;
  407. }
  408. //
  409. // Create 2 listview columns. If more are added, the column
  410. // width calculation needs to change.
  411. //
  412. DEBUG_ASSERT(NUM_COLUMNS == 2);
  413. LV_COLUMN lvc;
  414. RECT rcLV;
  415. TCHAR tszColumnLabel[MAX_LVIEW_HEADER_CCH];
  416. VERIFY(GetClientRect(_hwndLV, &rcLV));
  417. rcLV.right -= GetSystemMetrics(SM_CXVSCROLL);
  418. ZeroMemory(&lvc, sizeof lvc);
  419. lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  420. lvc.fmt = LVCFMT_LEFT;
  421. lvc.cx = (2 * rcLV.right) / 3;
  422. lvc.pszText = tszColumnLabel;
  423. int iCol;
  424. for (iCol = 0; iCol < NUM_COLUMNS; iCol++)
  425. {
  426. lvc.iSubItem = iCol;
  427. LoadStr(IDS_FIRSTCOLUMN + iCol,
  428. tszColumnLabel,
  429. ARRAYLEN(tszColumnLabel));
  430. //
  431. // Once the first column has been inserted, allocate the
  432. // remaining width to the second column.
  433. //
  434. if (iCol)
  435. {
  436. lvc.cx = rcLV.right - lvc.cx;
  437. }
  438. if (ListView_InsertColumn(_hwndLV, iCol, &lvc) == -1)
  439. {
  440. hr = HRESULT_FROM_LASTERROR;
  441. DEBUG_OUT_LASTERROR;
  442. break;
  443. }
  444. }
  445. BREAK_ON_FAIL_HRESULT(hr);
  446. } while (0);
  447. if (FAILED(hr))
  448. {
  449. if (himlSmall)
  450. {
  451. VERIFY(ImageList_Destroy(himlSmall));
  452. }
  453. if (_hwndLV)
  454. {
  455. EnableWindow(_hwndLV, FALSE);
  456. }
  457. }
  458. return hr;
  459. }
  460. //+--------------------------------------------------------------------------
  461. //
  462. // Member: CSelectProgramPage::_PopulateListView
  463. //
  464. // Synopsis: Fill the listview from the shortcuts found under the start
  465. // menu directory.
  466. //
  467. // Returns: HRESULT
  468. //
  469. // History: 5-20-1997 DavidMun Created
  470. //
  471. // Notes: Searches both under the current user and the all users
  472. // start menu directories. Note the walk link code ignores
  473. // links to certain programs, e.g. notepad.exe. These would
  474. // generally not make interesting tasks.
  475. //
  476. //---------------------------------------------------------------------------
  477. HRESULT
  478. CSelectProgramPage::_PopulateListView()
  479. {
  480. TRACE_METHOD(CSelectProgramPage, _PopulateListView);
  481. HRESULT hr = S_OK;
  482. LPLINKINFO pLinkInfo = new LINKINFO;
  483. HWALK hWalk = NULL;
  484. ERR errWalk;
  485. LV_ITEM lvi;
  486. HIMAGELIST hSmallImageList = ListView_GetImageList(_hwndLV, LVSIL_SMALL);
  487. ZeroMemory(&lvi, sizeof lvi);
  488. lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  489. if (hSmallImageList)
  490. {
  491. lvi.mask |= LVIF_IMAGE;
  492. }
  493. CWaitCursor HourGlass;
  494. do
  495. {
  496. if (!pLinkInfo)
  497. {
  498. hr = E_OUTOFMEMORY;
  499. DEBUG_OUT_HRESULT(hr);
  500. break;
  501. }
  502. TCHAR tszAllUsersStartMenuPath[MAX_PATH];
  503. TCHAR tszAllUsersStartMenuPathExpanded[MAX_PATH];
  504. #if !defined(_CHICAGO_)
  505. //
  506. // This CSIDL is valid on NT only
  507. //
  508. hr = SHGetFolderPath(NULL,
  509. CSIDL_COMMON_STARTMENU,
  510. NULL,
  511. 0,
  512. tszAllUsersStartMenuPath);
  513. if (FAILED(hr))
  514. {
  515. DEBUG_OUT_HRESULT(hr);
  516. break;
  517. }
  518. #else
  519. LoadStr(IDS_ALLUSERS_PATH,
  520. tszAllUsersStartMenuPath,
  521. ARRAYLEN(tszAllUsersStartMenuPath));
  522. #endif // !defined(_CHICAGO_)
  523. VERIFY(ExpandEnvironmentStrings(tszAllUsersStartMenuPath,
  524. tszAllUsersStartMenuPathExpanded,
  525. MAX_PATH));
  526. hWalk = GetFirstFileLnkInfo(pLinkInfo,
  527. INPTYPE_STARTMENU |
  528. INPTYPE_ANYFOLDER |
  529. INPFLAG_SKIPFILES,
  530. tszAllUsersStartMenuPathExpanded,
  531. &errWalk);
  532. if (!hWalk || FAILED(errWalk))
  533. {
  534. DEBUG_OUT((DEB_ERROR,
  535. "_PopulateListView: GetFirstFileLnkInfo %dL\n",
  536. errWalk));
  537. hr = E_FAIL;
  538. break; // no links in start menu (!) or error
  539. }
  540. hr = _AddAppToListView(&lvi, hSmallImageList, pLinkInfo);
  541. BREAK_ON_FAIL_HRESULT(hr);
  542. } while (0);
  543. //
  544. // If the first link was found, continue until no more are found
  545. // or an error occurs.
  546. //
  547. while (SUCCEEDED(hr))
  548. {
  549. pLinkInfo = new LINKINFO;
  550. if (!pLinkInfo)
  551. {
  552. hr = E_OUTOFMEMORY;
  553. DEBUG_OUT_HRESULT(hr);
  554. break;
  555. }
  556. if (GetNextFileLnkInfo(hWalk, pLinkInfo) > 0)
  557. {
  558. if (!_AppAlreadyInListView(pLinkInfo))
  559. {
  560. hr = _AddAppToListView(&lvi, hSmallImageList, pLinkInfo);
  561. BREAK_ON_FAIL_HRESULT(hr);
  562. }
  563. else
  564. {
  565. DEBUG_OUT((DEB_TRACE,
  566. "Discarding duplicate link %S %S\n",
  567. pLinkInfo->szLnkName,
  568. pLinkInfo->szExeVersionInfo));
  569. delete pLinkInfo;
  570. }
  571. }
  572. else
  573. {
  574. break; // no more links or error
  575. }
  576. }
  577. delete pLinkInfo;
  578. CloseWalk(hWalk); // no-op on null
  579. //
  580. // If anything was added to the listview, make the first item focused
  581. // (but not selected).
  582. //
  583. if (ListView_GetItemCount(_hwndLV))
  584. {
  585. ListView_SetItemState(_hwndLV, 0, LVIS_FOCUSED, LVIS_FOCUSED);
  586. }
  587. return hr;
  588. }
  589. //+--------------------------------------------------------------------------
  590. //
  591. // Member: CSelectProgramPage::_AppAlreadyInListView
  592. //
  593. // Synopsis: Return TRUE if a link with the same name and version info
  594. // as [pLinkInfo] has already been inserted in the listview.
  595. //
  596. // Arguments: [pLinkInfo] - contains link name to check
  597. //
  598. // Returns: TRUE - same link name found
  599. // FALSE - same link not found, or error
  600. //
  601. // History: 5-20-1997 DavidMun Created
  602. //
  603. // Notes: This eliminates links that have the same name, even if they
  604. // point to different programs, or have different arguments.
  605. //
  606. //---------------------------------------------------------------------------
  607. BOOL
  608. CSelectProgramPage::_AppAlreadyInListView(
  609. LPLINKINFO pLinkInfo)
  610. {
  611. LV_FINDINFO lvfi;
  612. lvfi.flags = LVFI_STRING;
  613. lvfi.psz = pLinkInfo->szLnkName;
  614. INT iItem = ListView_FindItem(_hwndLV, -1, &lvfi);
  615. if (iItem == -1)
  616. {
  617. return FALSE;
  618. }
  619. LV_ITEM lvi;
  620. lvi.mask = LVIF_PARAM;
  621. lvi.iItem = iItem;
  622. lvi.iSubItem = 0;
  623. BOOL fOk = ListView_GetItem(_hwndLV, &lvi);
  624. if (!fOk)
  625. {
  626. DEBUG_OUT_LASTERROR;
  627. return FALSE;
  628. }
  629. LPLINKINFO pliInserted = (LPLINKINFO) lvi.lParam;
  630. DEBUG_ASSERT(pliInserted);
  631. return !lstrcmpi(pLinkInfo->szExeVersionInfo,
  632. pliInserted->szExeVersionInfo);
  633. }
  634. //+--------------------------------------------------------------------------
  635. //
  636. // Member: CSelectProgramPage::_AddAppToListView
  637. //
  638. // Synopsis: Add an entry to the listview and its image list for the
  639. // application specified by [pLinkInfo].
  640. //
  641. // Arguments: [plvi] - all fields valid except pszText, lParam,
  642. // and iImage.
  643. // [hSmallImageList] - listview's small icon imagelist
  644. // [pLinkInfo] - describes app to insert info on
  645. //
  646. // Returns: HRESULT
  647. //
  648. // Modifies: pszText, lparam, and iImage fields of [plvi]; contents of
  649. // [hSmallImageList].
  650. //
  651. // History: 5-20-1997 DavidMun Created
  652. //
  653. //---------------------------------------------------------------------------
  654. HRESULT
  655. CSelectProgramPage::_AddAppToListView(
  656. LV_ITEM *plvi,
  657. HIMAGELIST hSmallImageList,
  658. LPLINKINFO pLinkInfo)
  659. {
  660. HRESULT hr = S_OK;
  661. plvi->pszText = pLinkInfo->szLnkName;
  662. plvi->lParam = (LPARAM) pLinkInfo;
  663. if (hSmallImageList)
  664. {
  665. TCHAR tszExeFullPath[MAX_PATH];
  666. wsprintf(tszExeFullPath,
  667. TEXT("%s\\%s"),
  668. pLinkInfo->szExePath,
  669. pLinkInfo->szExeName);
  670. plvi->iImage = InsertSmallIcon(hSmallImageList, tszExeFullPath);
  671. if (plvi->iImage == -1)
  672. {
  673. plvi->iImage = 0;
  674. }
  675. }
  676. INT iIndex = ListView_InsertItem(_hwndLV, plvi);
  677. if (iIndex == -1)
  678. {
  679. hr = E_FAIL;
  680. DEBUG_OUT_LASTERROR;
  681. return hr;
  682. }
  683. ListView_SetItemText(_hwndLV,
  684. iIndex,
  685. COL_VERSION,
  686. pLinkInfo->szExeVersionInfo);
  687. plvi->iItem++;
  688. return hr;
  689. }
  690. //+--------------------------------------------------------------------------
  691. //
  692. // Function: InsertSmallIcon
  693. //
  694. // Synopsis: Extract the small icon from [tszExeName] and add it to
  695. // [hSmallImageList].
  696. //
  697. // Arguments: [hSmallImageList] - handle to small icon imagelist
  698. // [tszExeName] - full path to executable
  699. //
  700. // Returns: Index of new entry or -1 if [tszExeName] doesn't have a
  701. // small icon or an error occurred.
  702. //
  703. // History: 5-20-1997 DavidMun Created
  704. //
  705. //---------------------------------------------------------------------------
  706. INT
  707. InsertSmallIcon(
  708. HIMAGELIST hSmallImageList,
  709. LPCTSTR tszExeName)
  710. {
  711. HICON hSmallIcon = NULL;
  712. UINT uiResult;
  713. uiResult = ExtractIconEx(tszExeName, 0, NULL, &hSmallIcon, 1);
  714. if (!hSmallIcon)
  715. {
  716. DEBUG_OUT((DEB_IWARN, "Can't find icon for app '%s'\n", tszExeName));
  717. }
  718. if (uiResult)
  719. {
  720. INT retVal;
  721. DEBUG_ASSERT(hSmallIcon);
  722. retVal = ImageList_AddIcon(hSmallImageList, hSmallIcon);
  723. if( hSmallIcon && !DestroyIcon( hSmallIcon ) )
  724. {
  725. CHECK_LASTERROR(GetLastError());
  726. }
  727. return retVal;
  728. }
  729. CHECK_LASTERROR(GetLastError());
  730. return -1;
  731. }
  732. //+--------------------------------------------------------------------------
  733. //
  734. // Member: CSelectProgramPage::GetExeName
  735. //
  736. // Synopsis: Fill [tszBuf] with the name of the executable selected by
  737. // the user.
  738. //
  739. // Arguments: [tszBuf] - buffer to receive name
  740. // [cchBuf] - size, in characters, of buffer
  741. //
  742. // Modifies: *[tszBuf]
  743. //
  744. // History: 10-28-1997 DavidMun Created
  745. //
  746. //---------------------------------------------------------------------------
  747. VOID
  748. CSelectProgramPage::GetExeName(
  749. LPTSTR tszBuf,
  750. ULONG cchBuf)
  751. {
  752. LPTSTR ptszExeName;
  753. if (_fUseBrowseSelection)
  754. {
  755. ptszExeName = _tszExeName;
  756. }
  757. else
  758. {
  759. ptszExeName = _pSelectedLinkInfo->szExeName;
  760. }
  761. lstrcpyn(tszBuf, ptszExeName, cchBuf);
  762. }
  763. //+--------------------------------------------------------------------------
  764. //
  765. // Member: CSelectProgramPage::GetExeFullPath
  766. //
  767. // Synopsis: Fill [tszBuf] with the full path to the executable selected
  768. // by the user.
  769. //
  770. // Arguments: [tszBuf] - buffer to receive path
  771. // [cchBuf] - size, in characters, of buffer
  772. //
  773. // Modifies: *[tszBuf]
  774. //
  775. // History: 5-20-1997 DavidMun Created
  776. //
  777. //---------------------------------------------------------------------------
  778. VOID
  779. CSelectProgramPage::GetExeFullPath(
  780. LPTSTR tszBuf,
  781. ULONG cchBuf)
  782. {
  783. LPTSTR ptszExePath;
  784. LPTSTR ptszExeName;
  785. if (_fUseBrowseSelection)
  786. {
  787. ptszExePath = _tszExePath;
  788. ptszExeName = _tszExeName;
  789. }
  790. else
  791. {
  792. ptszExePath = _pSelectedLinkInfo->szExePath;
  793. ptszExeName = _pSelectedLinkInfo->szExeName;
  794. }
  795. ULONG cchRequired = lstrlen(ptszExePath) +
  796. 1 + // backslash
  797. lstrlen(ptszExeName) +
  798. 1; // terminating null
  799. if (cchRequired > cchBuf)
  800. {
  801. lstrcpyn(tszBuf, ptszExeName, cchBuf);
  802. }
  803. else
  804. {
  805. lstrcpy(tszBuf, ptszExePath);
  806. lstrcat(tszBuf, TEXT("\\"));
  807. lstrcat(tszBuf, ptszExeName);
  808. }
  809. }
  810. //+--------------------------------------------------------------------------
  811. //
  812. // Member: CSelectProgramPage::_OnBrowse
  813. //
  814. // Synopsis: Allow the user to set the task's application via a common
  815. // file open dialog.
  816. //
  817. // History: 5-20-1997 DavidMun Created
  818. //
  819. // Notes: If successful, advances to the next page.
  820. //
  821. //---------------------------------------------------------------------------
  822. VOID
  823. CSelectProgramPage::_OnBrowse()
  824. {
  825. TRACE_METHOD(CSelectProgramPage, _OnBrowse);
  826. TCHAR tszDefExt[5];
  827. TCHAR tszFilter[MAX_PATH];
  828. TCHAR tszTitle[100];
  829. DWORD dwFlags = OFN_HIDEREADONLY |
  830. OFN_FILEMUSTEXIST |
  831. OFN_NOCHANGEDIR |
  832. OFN_NONETWORKBUTTON |
  833. OFN_PATHMUSTEXIST;
  834. LoadStr(IDS_EXE, tszDefExt, ARRAYLEN(tszDefExt));
  835. LoadStr(IDS_WIZARD_BROWSE_CAPTION, tszTitle, ARRAYLEN(tszTitle));
  836. ZeroMemory(tszFilter, ARRAYLEN(tszFilter));
  837. LoadStr(IDS_WIZARD_FILTER, tszFilter, ARRAYLEN(tszFilter));
  838. OPENFILENAME ofn;
  839. ZeroMemory(&ofn, sizeof(ofn));
  840. _tszExeName[0] = TEXT('\0');
  841. _tszExePath[0] = TEXT('\0');
  842. // Set up info for common file open dialog.
  843. ofn.lStructSize = CDSIZEOF_STRUCT(OPENFILENAME, lpTemplateName);
  844. ofn.hwndOwner = Hwnd();
  845. ofn.lpstrFilter = tszFilter;
  846. ofn.nFilterIndex = 1;
  847. ofn.lpstrFile = _tszExePath;
  848. ofn.nMaxFile = MAX_PATH;
  849. ofn.lpstrFileTitle = _tszExeName;
  850. ofn.nMaxFileTitle = MAX_PATH;
  851. ofn.lpstrInitialDir = TEXT("\\");
  852. ofn.lpstrTitle = tszTitle;
  853. ofn.Flags = dwFlags;
  854. ofn.lpstrDefExt = tszDefExt;
  855. //
  856. // Invoke the dialog. If the user makes a selection and hits OK, record
  857. // the name selected and go on to the trigger selection page.
  858. //
  859. if (GetOpenFileName(&ofn))
  860. {
  861. PathRemoveFileSpec(_tszExePath);
  862. LPTSTR ptszLastSlash = _tcsrchr(_tszExePath, TEXT('\\'));
  863. if (ptszLastSlash && lstrlen(ptszLastSlash) == 1)
  864. {
  865. *ptszLastSlash = TEXT('\0');
  866. }
  867. _fUseBrowseSelection = TRUE;
  868. PropSheet_PressButton(GetParent(Hwnd()), PSBTN_NEXT);
  869. }
  870. else
  871. {
  872. // user hit cancel or an error occurred
  873. if (CommDlgExtendedError())
  874. {
  875. DEBUG_OUT((DEB_ERROR,
  876. "GetOpenFileName failed<0x%x>\n",
  877. CommDlgExtendedError()));
  878. }
  879. }
  880. }