//+-------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1994 - 1996. // // File: selprog.cxx // // Contents: Task wizard program selection property page implementation. // // Classes: CSelectProgramPage // // History: 4-28-1997 DavidMun Created // //--------------------------------------------------------------------------- #include "..\pch\headers.hxx" #pragma hdrstop #include "myheaders.hxx" #include "commdlg.h" #include "..\schedui\rc.h" #include "..\inc\resource.h" #include "..\folderui\jobicons.hxx" #include "walklib.h" // // Types // // COLUMNS - indexes to the columns in the listview displaying the results // of walking the start menu // enum COLUMNS { COL_APP, COL_VERSION, NUM_COLUMNS }; // // Forward references // INT InsertSmallIcon( HIMAGELIST hSmallImageList, LPCTSTR tszExeName); // // Externals // extern HICON GetDefaultAppIcon(UINT nIconSize); //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::CSelectProgramPage // // Synopsis: ctor // // Arguments: [ptszFolderPath] - full path to tasks folder with dummy // filename appended // [phPSP] - filled with prop page handle // // History: 4-28-1997 DavidMun Created // //--------------------------------------------------------------------------- CSelectProgramPage::CSelectProgramPage( CTaskWizard *pParent, LPTSTR ptszFolderPath, HPROPSHEETPAGE *phPSP): CWizPage(MAKEINTRESOURCE(IDD_SELECT_PROGRAM), ptszFolderPath) { TRACE_CONSTRUCTOR(CSelectProgramPage); _hwndLV = NULL; _pSelectedLinkInfo = NULL; _idxSelectedIcon = 0; _fUseBrowseSelection = FALSE; _tszExePath[0] = TEXT('\0'); _tszExeName[0] = TEXT('\0'); _CreatePage(IDS_SELPROG_HDR1, IDS_SELPROG_HDR2, phPSP); } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::~CSelectProgramPage // // Synopsis: dtor // // History: 4-28-1997 DavidMun Created // //--------------------------------------------------------------------------- CSelectProgramPage::~CSelectProgramPage() { TRACE_DESTRUCTOR(CSelectProgramPage); } //=========================================================================== // // CPropPage overrides // //=========================================================================== //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_OnCommand // // Synopsis: Handle the browse button being clicked, ignore all else. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- LRESULT CSelectProgramPage::_OnCommand( int id, HWND hwndCtl, UINT codeNotify) { TRACE_METHOD(CSelectProgramPage, _OnCommand); LRESULT lr = 0; if (codeNotify == BN_CLICKED && id == selprogs_browse_pb) { _OnBrowse(); } else { lr = 1; // not handled } return lr; } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_OnInitDialog // // Synopsis: Perform initialization that should only occur once. // // Arguments: [lParam] - LPPROPSHEETPAGE used to create this page // // Returns: TRUE (let windows set focus) // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- LRESULT CSelectProgramPage::_OnInitDialog( LPARAM lParam) { TRACE_METHOD(CSelectProgramPage, _OnInitDialog); HRESULT hr = S_OK; // Policy dictates whether we have a browse button or not // true means don't allow us to browse if (RegReadPolicyKey(TS_KEYPOLICY_DENY_BROWSE)) { DEBUG_OUT((DEB_ITRACE, "Policy DENY_BROWSE active - removing browse btn\n")); EnableWindow(_hCtrl(selprogs_browse_pb), FALSE); ShowWindow(_hCtrl(selprogs_browse_pb), SW_HIDE); ShowWindow(_hCtrl(selprogs_static_text_browse), SW_HIDE); } // Next not enabled till user picks app _SetWizButtons(PSWIZB_BACK); _hwndLV = _hCtrl(selprog_programs_lv); hr = _InitListView(); if (SUCCEEDED(hr)) { _PopulateListView(); } return (HRESULT) TRUE; // wm_initdialog wants BOOL for setfocus info } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_OnPSNSetActive // // Synopsis: Enable the Next button if an item has been selected in the // listview. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- LRESULT CSelectProgramPage::_OnPSNSetActive( LPARAM lParam) { _fUseBrowseSelection = FALSE; if (_pSelectedLinkInfo) { _SetWizButtons(PSWIZB_BACK | PSWIZB_NEXT); } else { _SetWizButtons(PSWIZB_BACK); } return CPropPage::_OnPSNSetActive(lParam); } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_OnDestroy // // Synopsis: Free all the linkinfos stored as user data in the listview. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- LRESULT CSelectProgramPage::_OnDestroy() { DEBUG_ASSERT(IsWindow(_hwndLV)); ULONG cItems = ListView_GetItemCount(_hwndLV); ULONG i; LV_ITEM lvi; SecureZeroMemory(&lvi, sizeof lvi); lvi.mask = LVIF_PARAM; for (i = 0; i < cItems; i++) { lvi.iItem = i; lvi.lParam = 0; BOOL fOk = ListView_GetItem(_hwndLV, &lvi); if (fOk) { delete (LINKINFO *) lvi.lParam; } else { DEBUG_OUT_LASTERROR; } } return 0; } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_ProcessListViewNotifications // // Synopsis: If the user makes a selection in the listview, remember the // associated linkinfo and enable the next button. // // Returns: FALSE // // History: 5-20-1997 DavidMun Created // // Notes: Ignores all other notifications. // //--------------------------------------------------------------------------- BOOL CSelectProgramPage::_ProcessListViewNotifications( UINT uMsg, WPARAM wParam, LPARAM lParam) { UINT code = ((LPNMHDR)lParam)->code; if (((LPNMHDR)lParam)->idFrom != selprog_programs_lv) { return FALSE; } DEBUG_ASSERT(code != LVN_GETDISPINFO); // not using callbacks DEBUG_ASSERT(code != LVN_SETDISPINFO); // items are r/o if (code == LVN_ITEMCHANGED) { NM_LISTVIEW *pnmLV = (NM_LISTVIEW *) lParam; if ((pnmLV->uChanged & LVIF_STATE) && (pnmLV->uNewState & LVIS_SELECTED)) { // translate the index into a LinkInfo pointer LV_ITEM lvi; lvi.iItem = pnmLV->iItem; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM | LVIF_IMAGE; if (!ListView_GetItem(_hwndLV, &lvi)) { DEBUG_OUT_LASTERROR; return FALSE; } _pSelectedLinkInfo = (LINKINFO *) lvi.lParam; _idxSelectedIcon = lvi.iImage; _SetWizButtons(PSWIZB_BACK | PSWIZB_NEXT); } } return FALSE; } //=========================================================================== // // CSelectProgramPage members // //=========================================================================== //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::GetDefaultDisplayName // // Synopsis: Fill [tszDisplayName] with the string to offer the user // as the new task object name. // // Arguments: [tszDisplayName] - buffer to receive string // [cchDisplayName] - size, in chars, of buffer // // Modifies: *[tszDisplayName] // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- VOID CSelectProgramPage::GetDefaultDisplayName( LPTSTR tszDisplayName, ULONG cchDisplayName) { LPTSTR ptszToCopy; if (_fUseBrowseSelection) { ptszToCopy = _tszExeName; } else if (*_pSelectedLinkInfo->szLnkName) { ptszToCopy = _pSelectedLinkInfo->szLnkName; } else { ptszToCopy = _pSelectedLinkInfo->szExeName; } lstrcpyn(tszDisplayName, ptszToCopy, cchDisplayName); // // Truncate at the file extension // LPTSTR ptszExt = PathFindExtension(tszDisplayName); if (ptszExt) { *ptszExt = TEXT('\0'); } } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::GetSelectedAppIcon // // Synopsis: Retrieve the icon associated with the selected appliation. // // Returns: The selected app's small icon, or NULL if no small icon is // available. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- HICON CSelectProgramPage::GetSelectedAppIcon() { if (_fUseBrowseSelection) { HICON hicon = NULL; TCHAR tszFullPath[MAX_PATH]; GetExeFullPath(tszFullPath, ARRAYLEN(tszFullPath)); TS_ExtractIconEx(tszFullPath, 0, &hicon, 1, GetSystemMetrics(SM_CXSMICON)); return hicon; } if (_idxSelectedIcon == -1) { return NULL; } HIMAGELIST hSmallImageList = ListView_GetImageList(_hwndLV, LVSIL_SMALL); if (!hSmallImageList) { return NULL; } return ImageList_ExtractIcon(0, hSmallImageList, _idxSelectedIcon); } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_InitListView // // Synopsis: Initialize the listview's columns and image lists. // // Returns: HRESULT // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- HRESULT CSelectProgramPage::_InitListView() { HRESULT hr = S_OK; HIMAGELIST himlSmall = NULL; INT cxSmall = GetSystemMetrics(SM_CXSMICON); INT cySmall = GetSystemMetrics(SM_CYSMICON); DWORD dwFlag = ILC_MASK | ILC_COLOR32; do { if (!_hwndLV || !cxSmall || !cySmall) { hr = E_UNEXPECTED; DEBUG_OUT_HRESULT(hr); break; } // // Create the listview image list. Only the small image list is // required, since this listview will be restricted to report // mode. // if (GetWindowLongPtr(_hwndLV, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) { dwFlag |= ILC_MIRROR; } himlSmall = ImageList_Create(cxSmall, cySmall, dwFlag, 1, 1); if (!himlSmall) { hr = HRESULT_FROM_LASTERROR; DEBUG_OUT_LASTERROR; break; } // Add the generic icon HICON hiconGeneric = GetDefaultAppIcon(GetSystemMetrics(SM_CXSMICON)); DEBUG_ASSERT(hiconGeneric); INT index = ImageList_AddIcon(himlSmall, hiconGeneric); DEBUG_ASSERT(index != -1); // Assign the image list to the listview if (!ListView_SetImageList(_hwndLV, himlSmall, LVSIL_SMALL)) { himlSmall = NULL; } else { hr = HRESULT_FROM_LASTERROR; DEBUG_OUT_LASTERROR; break; } // // Create 2 listview columns. If more are added, the column // width calculation needs to change. // DEBUG_ASSERT(NUM_COLUMNS == 2); LV_COLUMN lvc; RECT rcLV; TCHAR tszColumnLabel[MAX_LVIEW_HEADER_CCH]; VERIFY(GetClientRect(_hwndLV, &rcLV)); rcLV.right -= GetSystemMetrics(SM_CXVSCROLL); SecureZeroMemory(&lvc, sizeof lvc); lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.cx = (2 * rcLV.right) / 3; lvc.pszText = tszColumnLabel; int iCol; for (iCol = 0; iCol < NUM_COLUMNS; iCol++) { lvc.iSubItem = iCol; LoadStr(IDS_FIRSTCOLUMN + iCol, tszColumnLabel, ARRAYLEN(tszColumnLabel)); // // Once the first column has been inserted, allocate the // remaining width to the second column. // if (iCol) { lvc.cx = rcLV.right - lvc.cx; } if (ListView_InsertColumn(_hwndLV, iCol, &lvc) == -1) { hr = HRESULT_FROM_LASTERROR; DEBUG_OUT_LASTERROR; break; } } BREAK_ON_FAIL_HRESULT(hr); } while (0); if (FAILED(hr)) { if (himlSmall) { VERIFY(ImageList_Destroy(himlSmall)); } if (_hwndLV) { EnableWindow(_hwndLV, FALSE); } } return hr; } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_PopulateListView // // Synopsis: Fill the listview from the shortcuts found under the start // menu directory. // // Returns: HRESULT // // History: 5-20-1997 DavidMun Created // // Notes: Searches both under the current user and the all users // start menu directories. Note the walk link code ignores // links to certain programs, e.g. notepad.exe. These would // generally not make interesting tasks. // //--------------------------------------------------------------------------- HRESULT CSelectProgramPage::_PopulateListView() { TRACE_METHOD(CSelectProgramPage, _PopulateListView); HRESULT hr = S_OK; LPLINKINFO pLinkInfo = new LINKINFO; HWALK hWalk = NULL; ERR errWalk; LV_ITEM lvi; HIMAGELIST hSmallImageList = ListView_GetImageList(_hwndLV, LVSIL_SMALL); SecureZeroMemory(&lvi, sizeof lvi); lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; if (hSmallImageList) { lvi.mask |= LVIF_IMAGE; } CWaitCursor HourGlass; do { if (!pLinkInfo) { hr = E_OUTOFMEMORY; DEBUG_OUT_HRESULT(hr); break; } TCHAR tszAllUsersStartMenuPath[MAX_PATH]; TCHAR tszAllUsersStartMenuPathExpanded[MAX_PATH]; // // This CSIDL is valid on NT only // hr = SHGetFolderPath(NULL, CSIDL_COMMON_STARTMENU, NULL, 0, tszAllUsersStartMenuPath); if (FAILED(hr)) { DEBUG_OUT_HRESULT(hr); break; } VERIFY(ExpandEnvironmentStrings(tszAllUsersStartMenuPath, tszAllUsersStartMenuPathExpanded, MAX_PATH)); hWalk = GetFirstFileLnkInfo(pLinkInfo, INPTYPE_STARTMENU | INPTYPE_ANYFOLDER | INPFLAG_SKIPFILES, tszAllUsersStartMenuPathExpanded, &errWalk); if (!hWalk || FAILED(errWalk)) { DEBUG_OUT((DEB_ERROR, "_PopulateListView: GetFirstFileLnkInfo %dL\n", errWalk)); hr = E_FAIL; break; // no links in start menu (!) or error } hr = _AddAppToListView(&lvi, hSmallImageList, pLinkInfo); BREAK_ON_FAIL_HRESULT(hr); } while (0); // // If the first link was found, continue until no more are found // or an error occurs. // while (SUCCEEDED(hr)) { pLinkInfo = new LINKINFO; if (!pLinkInfo) { hr = E_OUTOFMEMORY; DEBUG_OUT_HRESULT(hr); break; } if (GetNextFileLnkInfo(hWalk, pLinkInfo) > 0) { if (!_AppAlreadyInListView(pLinkInfo)) { hr = _AddAppToListView(&lvi, hSmallImageList, pLinkInfo); BREAK_ON_FAIL_HRESULT(hr); } else { DEBUG_OUT((DEB_TRACE, "Discarding duplicate link %S %S\n", pLinkInfo->szLnkName, pLinkInfo->szExeVersionInfo)); delete pLinkInfo; } } else { break; // no more links or error } } delete pLinkInfo; CloseWalk(hWalk); // no-op on null // // If anything was added to the listview, make the first item focused // (but not selected). // if (ListView_GetItemCount(_hwndLV)) { ListView_SetItemState(_hwndLV, 0, LVIS_FOCUSED, LVIS_FOCUSED); } return hr; } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_AppAlreadyInListView // // Synopsis: Return TRUE if a link with the same name and version info // as [pLinkInfo] has already been inserted in the listview. // // Arguments: [pLinkInfo] - contains link name to check // // Returns: TRUE - same link name found // FALSE - same link not found, or error // // History: 5-20-1997 DavidMun Created // // Notes: This eliminates links that have the same name, even if they // point to different programs, or have different arguments. // //--------------------------------------------------------------------------- BOOL CSelectProgramPage::_AppAlreadyInListView( LPLINKINFO pLinkInfo) { LV_FINDINFO lvfi; lvfi.flags = LVFI_STRING; lvfi.psz = pLinkInfo->szLnkName; INT iItem = ListView_FindItem(_hwndLV, -1, &lvfi); if (iItem == -1) { return FALSE; } LV_ITEM lvi; lvi.mask = LVIF_PARAM; lvi.iItem = iItem; lvi.iSubItem = 0; BOOL fOk = ListView_GetItem(_hwndLV, &lvi); if (!fOk) { DEBUG_OUT_LASTERROR; return FALSE; } LPLINKINFO pliInserted = (LPLINKINFO) lvi.lParam; DEBUG_ASSERT(pliInserted); return !lstrcmpi(pLinkInfo->szExeVersionInfo, pliInserted->szExeVersionInfo); } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_AddAppToListView // // Synopsis: Add an entry to the listview and its image list for the // application specified by [pLinkInfo]. // // Arguments: [plvi] - all fields valid except pszText, lParam, // and iImage. // [hSmallImageList] - listview's small icon imagelist // [pLinkInfo] - describes app to insert info on // // Returns: HRESULT // // Modifies: pszText, lparam, and iImage fields of [plvi]; contents of // [hSmallImageList]. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- HRESULT CSelectProgramPage::_AddAppToListView( LV_ITEM *plvi, HIMAGELIST hSmallImageList, LPLINKINFO pLinkInfo) { HRESULT hr = S_OK; plvi->pszText = pLinkInfo->szLnkName; plvi->lParam = (LPARAM) pLinkInfo; if (hSmallImageList) { TCHAR tszExeFullPath[MAX_PATH +1]; StringCchPrintf(tszExeFullPath, MAX_PATH +1, TEXT("%s\\%s"), pLinkInfo->szExePath, pLinkInfo->szExeName); plvi->iImage = InsertSmallIcon(hSmallImageList, tszExeFullPath); if (plvi->iImage == -1) { plvi->iImage = 0; } } INT iIndex = ListView_InsertItem(_hwndLV, plvi); if (iIndex == -1) { hr = E_FAIL; DEBUG_OUT_LASTERROR; return hr; } ListView_SetItemText(_hwndLV, iIndex, COL_VERSION, pLinkInfo->szExeVersionInfo); plvi->iItem++; return hr; } //+-------------------------------------------------------------------------- // // Function: InsertSmallIcon // // Synopsis: Extract the small icon from [tszExeName] and add it to // [hSmallImageList]. // // Arguments: [hSmallImageList] - handle to small icon imagelist // [tszExeName] - full path to executable // // Returns: Index of new entry or -1 if [tszExeName] doesn't have a // small icon or an error occurred. // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- INT InsertSmallIcon( HIMAGELIST hSmallImageList, LPCTSTR tszExeName) { HICON hSmallIcon = NULL; UINT uiResult; uiResult = TS_ExtractIconEx(tszExeName, 0, &hSmallIcon, 1, GetSystemMetrics(SM_CXSMICON)); if (!hSmallIcon) { DEBUG_OUT((DEB_IWARN, "Can't find icon for app '%s'\n", tszExeName)); } if (uiResult) { INT retVal; DEBUG_ASSERT(hSmallIcon); retVal = ImageList_AddIcon(hSmallImageList, hSmallIcon); if( hSmallIcon && !DestroyIcon( hSmallIcon ) ) { CHECK_LASTERROR(GetLastError()); } return retVal; } CHECK_LASTERROR(GetLastError()); return -1; } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::GetExeName // // Synopsis: Fill [tszBuf] with the name of the executable selected by // the user. // // Arguments: [tszBuf] - buffer to receive name // [cchBuf] - size, in characters, of buffer // // Modifies: *[tszBuf] // // History: 10-28-1997 DavidMun Created // //--------------------------------------------------------------------------- VOID CSelectProgramPage::GetExeName( LPTSTR tszBuf, ULONG cchBuf) { LPTSTR ptszExeName; if (_fUseBrowseSelection) { ptszExeName = _tszExeName; } else { ptszExeName = _pSelectedLinkInfo->szExeName; } lstrcpyn(tszBuf, ptszExeName, cchBuf); } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::GetExeFullPath // // Synopsis: Fill [tszBuf] with the full path to the executable selected // by the user. // // Arguments: [tszBuf] - buffer to receive path // [cchBuf] - size, in characters, of buffer // // Modifies: *[tszBuf] // // History: 5-20-1997 DavidMun Created // //--------------------------------------------------------------------------- VOID CSelectProgramPage::GetExeFullPath( LPTSTR tszBuf, ULONG cchBuf) { LPTSTR ptszExePath; LPTSTR ptszExeName; if (_fUseBrowseSelection) { ptszExePath = _tszExePath; ptszExeName = _tszExeName; } else { ptszExePath = _pSelectedLinkInfo->szExePath; ptszExeName = _pSelectedLinkInfo->szExeName; } ULONG cchRequired = lstrlen(ptszExePath) + 1 + // backslash lstrlen(ptszExeName) + 1; // terminating null // if there's not enough room in the buffer for the whole path // just copy the executable name if (cchRequired > cchBuf) { lstrcpyn(tszBuf, ptszExeName, cchBuf); } else { StringCchCopy(tszBuf, cchBuf, ptszExePath); StringCchCat(tszBuf, cchBuf, TEXT("\\")); StringCchCat(tszBuf, cchBuf, ptszExeName); } } //+-------------------------------------------------------------------------- // // Function: FixupRemoteLink // // Synopsis: determine whether a link came from another computer // If so, append server name // // History: 5-24-2002 hhance Created // // Notes: assumes that exePath is MAX_PATH long // //--------------------------------------------------------------------------- void FixupRemoteLink(LPCWSTR linkPath, LPWSTR exePath) { // step one - if the exePath is already a UNC name, do nothing if ((exePath[0] == L'\\') && (exePath[1] == L'\\')) return; WCHAR drive[4]; StringCchCopyN(drive, 4, linkPath, 3); if ((drive[1] == L':') && (drive[2] == L'\\') && (GetDriveType(drive) == DRIVE_REMOTE)) { // now we only want the drive letter drive[2] = L'\0'; // we know the link file exists on a remote drive // therefore, the path is based on ANOTHER machine somewhere. WCHAR serverName[MAX_PATH]; DWORD dLength = MAX_PATH; if (0 == WNetGetConnection(drive, serverName, &dLength) && ((wcslen(serverName) + wcslen(exePath) +1) <= MAX_PATH)) { // server name will be of the form \\machine\c$ // but all we need is "\\machine\" WCHAR* pChar = wcsrchr(serverName, L'\\'); if (pChar) { *(pChar +1) = L'\0'; WCHAR copyBuf[MAX_PATH +1]; StringCchCopy(copyBuf, MAX_PATH +1, exePath); StringCchCopy(exePath, MAX_PATH +1, serverName); StringCchCat(exePath, MAX_PATH +1, copyBuf); // and make it C$ rather than C: ... WCHAR* pChar = wcschr(exePath, L':'); if (pChar) *pChar = L'$'; } } } // maybe they've keyed in a UNC name all by their little lonesomes // we're expecting \\servername\somepath at this point else if ((linkPath[0] == L'\\') && (linkPath[1] == L'\\')) { WCHAR copyBuf[MAX_PATH +1]; StringCchCopy(copyBuf, MAX_PATH +1, linkPath); WCHAR* pChar = wcschr(©Buf[2], L'\\'); // Shouldn't be able to get here otherwise // if we did - we'll let them get what they've asked for. if (!pChar) return; // append exepath right behind the backwhack StringCchCopy(pChar +1, MAX_PATH +1 - (pChar - copyBuf), exePath); // make it C$ rather than C: ... pChar = wcschr(copyBuf, L':'); if (pChar) *pChar = L'$'; // and copy it into the output buffer StringCchCopy(exePath, MAX_PATH +1, copyBuf); } } //+-------------------------------------------------------------------------- // // Member: CSelectProgramPage::_OnBrowse // // Synopsis: Allow the user to set the task's application via a common // file open dialog. // // History: 5-20-1997 DavidMun Created // // Notes: If successful, advances to the next page. // //--------------------------------------------------------------------------- VOID CSelectProgramPage::_OnBrowse() { TRACE_METHOD(CSelectProgramPage, _OnBrowse); TCHAR tszDefExt[5]; TCHAR tszFilter[MAX_PATH]; TCHAR tszTitle[100]; DWORD dwFlags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_NONETWORKBUTTON | OFN_PATHMUSTEXIST; LoadStr(IDS_EXE, tszDefExt, ARRAYLEN(tszDefExt)); LoadStr(IDS_WIZARD_BROWSE_CAPTION, tszTitle, ARRAYLEN(tszTitle)); SecureZeroMemory(tszFilter, sizeof tszFilter); LoadStr(IDS_WIZARD_FILTER, tszFilter, ARRAYLEN(tszFilter)); OPENFILENAME ofn; SecureZeroMemory(&ofn, sizeof(ofn)); _tszExeName[0] = TEXT('\0'); _tszExePath[0] = TEXT('\0'); // Set up info for common file open dialog. ofn.lStructSize = CDSIZEOF_STRUCT(OPENFILENAME, lpTemplateName); ofn.hwndOwner = Hwnd(); ofn.lpstrFilter = tszFilter; ofn.nFilterIndex = 1; ofn.lpstrFile = _tszExePath; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = _tszExeName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrInitialDir = TEXT("\\"); ofn.lpstrTitle = tszTitle; ofn.Flags = dwFlags; ofn.lpstrDefExt = tszDefExt; // // Invoke the dialog. If the user makes a selection and hits OK, record // the name selected and go on to the trigger selection page. // if (GetOpenFileName(&ofn)) { PathRemoveFileSpec(_tszExePath); LPTSTR ptszLastSlash = _tcsrchr(_tszExePath, TEXT('\\')); if (ptszLastSlash && lstrlen(ptszLastSlash) == 1) { *ptszLastSlash = TEXT('\0'); } _fUseBrowseSelection = TRUE; // if the user chose a link, resolve the link TCHAR tszFullPath[MAX_PATH +1]; GetExeFullPath(tszFullPath, ARRAYLEN(tszFullPath)); if (*tszFullPath != TEXT('\0')) { LPTSTR ptszExt = PathFindExtension(tszFullPath); if (ptszExt && !_tcsicmp(ptszExt, TEXT(".LNK"))) { TCHAR szLnkPath[MAX_PATH +1] = {TEXT('\0')}; TCHAR szArguments[MAX_PATH] = {TEXT('\0')}; WIN32_FIND_DATA wfdExeData; if (ResolveLnk(tszFullPath, szLnkPath, &wfdExeData, szArguments) == 0) { ptszLastSlash = _tcsrchr(szLnkPath, TEXT('\\')); if (ptszLastSlash) { lstrcpyn(_tszExeName, ptszLastSlash + 1, MAX_PATH); *ptszLastSlash = TEXT('\0'); lstrcpyn(_tszExePath, szLnkPath, MAX_PATH); // got this far. Now need to see whether this is a remote link FixupRemoteLink(tszFullPath, _tszExePath); } } } } PropSheet_PressButton(GetParent(Hwnd()), PSBTN_NEXT); } else { // user hit cancel or an error occurred if (CommDlgExtendedError()) { DEBUG_OUT((DEB_ERROR, "GetOpenFileName failed<0x%x>\n", CommDlgExtendedError())); } } }