|
|
#include "shellprv.h"
#pragma hdrstop
#include "fstreex.h"
typedef struct { HWND hDlg; // input output
LPTSTR lpszExe; // base file name (to search for)
LPTSTR lpszPath; // starting location for search
LPCTSTR lpszName; // doc type name "Winword Document"
} FINDEXE_PARAMS, *LPFINDEXE_PARAMS;
int CALLBACK LocateCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { TCHAR szPath[MAX_PATH + 80]; int id; LPFINDEXE_PARAMS lpfind = (LPFINDEXE_PARAMS)lpData;
switch(uMsg) { case BFFM_SELCHANGED: SHGetPathFromIDList((LPITEMIDLIST)lParam, szPath); if ((lstrlen(szPath) + lstrlen(lpfind->lpszExe)) < MAX_PATH) { PathAppend(szPath, lpfind->lpszExe); if (PathFileExistsAndAttributes(szPath, NULL)) { id = IDS_FILEFOUND; } else { id = IDS_FILENOTFOUND; } } else { id = IDS_FILENOTFOUND; } SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, id); break;
case BFFM_INITIALIZED: SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, IDS_FILENOTFOUND); break; } return 0; }
void _GetBrowseTitle(LPFINDEXE_PARAMS lpfind, LPTSTR lpszBuffer, UINT cchBuffer) { TCHAR szTemplate[100]; LoadString(HINST_THISDLL, IDS_FINDASSEXEBROWSETITLE, szTemplate, ARRAYSIZE(szTemplate)); wnsprintf(lpszBuffer, cchBuffer, szTemplate, lpfind->lpszExe); }
void DoBrowseForFile(LPFINDEXE_PARAMS lpfind) { TCHAR szFilePath[MAX_PATH] = { 0 }; // buffer for file name
TCHAR szInitialDir[MAX_PATH] = { 0 }; // buffer for file name
// initial directory to Program Files
SHGetSpecialFolderPath(NULL, szInitialDir, CSIDL_PROGRAM_FILES, TRUE);
if (GetFileNameFromBrowse(lpfind->hDlg, szFilePath, ARRAYSIZE(szFilePath), szInitialDir, MAKEINTRESOURCE(IDS_EXE), MAKEINTRESOURCE(IDS_PROGRAMSFILTER), MAKEINTRESOURCE(IDS_BROWSE))) { SetDlgItemText(lpfind->hDlg, IDD_PATH, szFilePath); lstrcpy((LPTSTR)lpfind->lpszPath, szFilePath); } }
void InitFindDlg(HWND hDlg, LPFINDEXE_PARAMS lpfind) { TCHAR szPath[MAX_PATH]; /* This must be the same size as lpfind->lpszPath */ TCHAR szBuffer[MAX_PATH + 100];
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lpfind); lpfind->hDlg = hDlg;
GetDlgItemText(hDlg, IDD_TEXT1, szPath, ARRAYSIZE(szPath)); wsprintf(szBuffer, szPath, lpfind->lpszExe, lpfind->lpszName); SetDlgItemText(hDlg, IDD_TEXT1, szBuffer);
GetDlgItemText(hDlg, IDD_TEXT2, szPath, ARRAYSIZE(szPath)); wsprintf(szBuffer, szPath, lpfind->lpszExe); SetDlgItemText(hDlg, IDD_TEXT2, szBuffer);
SetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath);
SHAutoComplete(GetDlgItem(hDlg, IDD_PATH), (SHACF_FILESYSTEM | SHACF_URLALL | SHACF_FILESYS_ONLY)); }
BOOL FindOk(LPFINDEXE_PARAMS lpfind) { GetDlgItemText(lpfind->hDlg, IDD_PATH, lpfind->lpszPath, MAX_PATH);
// If they entered a directory, then append the EXE name to it
// The dialog is confusing - it asks for the "location". Does that
// mean I should enter the directory or the filename?
// Allow both to work.
if (PathIsDirectory(lpfind->lpszPath)) { PathAppend(lpfind->lpszPath, lpfind->lpszExe); }
if (!PathFileExistsAndAttributes(lpfind->lpszPath, NULL)) { ShellMessageBox(HINST_THISDLL, lpfind->hDlg, MAKEINTRESOURCE(IDS_STILLNOTFOUND), NULL, MB_ICONHAND | MB_OK, (LPTSTR)lpfind->lpszPath); return FALSE; }
// HACKHACK we should use the registry but it's too late now;
// Win95 shipped with this code so it's gonna be in win.ini forever...
WriteProfileString(TEXT("programs"), lpfind->lpszExe, lpfind->lpszPath); return TRUE; }
//----------------------------------------------------------------------------
// FindExeDlgProc was mistakenly exported in the original NT SHELL32.DLL when
// it didn't need to be (dlgproc's, like wndproc's don't need to be exported
// in the 32-bit world). In order to maintain loadability of some app
// which might have linked to it, we stub it here. If some app ended up really
// using it, then we'll look into a specific fix for that app.
//
// -BobDay
//
BOOL_PTR WINAPI FindExeDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LONG lParam ) { return FALSE; }
BOOL_PTR CALLBACK FindExeDlgProcA(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { LPFINDEXE_PARAMS lpfind = (LPFINDEXE_PARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
switch (wMsg) { case WM_INITDIALOG: InitFindDlg(hDlg, (LPFINDEXE_PARAMS)lParam); break;
case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDD_BROWSE: DoBrowseForFile(lpfind); break;
case IDOK: if (!FindOk(lpfind)) break;
// fall through
case IDCANCEL: EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam)); break;
}
break;
default: return FALSE; }
return TRUE; }
//
// Give a command line, change the exe (leaving the args). For example,
// PathReplaceExe(C:\Old\foo.exe -silent, C:\NewDirectory\foo.exe)
// yields C:\NewDirectory\foo.exe -silent.
//
void PathReplaceExe(LPTSTR lpCommand, UINT cchCommand, LPCTSTR pszExe) { LPTSTR lpArgs;
lpArgs = PathGetArgs(lpCommand); if (*lpArgs) { // Must save the original args before copying pszExe because it
// might overwrite lpCommand. I could be clever with hmemcpy and
// avoid allocating memory but this function is called so rarely
// it isn't worth it.
UINT cchArgs = lstrlen(lpArgs); LPTSTR lpArgsCopy = (LPTSTR)_alloca((cchArgs + 1) * sizeof(TCHAR)); lstrcpy(lpArgsCopy, lpArgs);
lstrcpyn(lpCommand, pszExe, cchCommand); PathQuoteSpaces(lpCommand); // lpArgs is no good after this point
lstrcatn(lpCommand, c_szSpace, cchCommand); lstrcatn(lpCommand, lpArgsCopy, cchCommand); } else { lstrcpyn(lpCommand, pszExe, cchCommand); PathQuoteSpaces(lpCommand); } }
//
// put up cool ui to find the exe responsible for performing
// a ShellExecute()
// "excel.exe foo.xls" -> "c:\excel\excel.exe foo.xls"
//
// in:
// hwnd to post UI on
// lpCommand command line to try to repair [in/out]
// cchCommand size of lpCommand buffer
// hkeyProgID program ID
//
// out:
// lpCommand change cmd line if we returned -1
//
// returns:
// -1 we found a new location lpCommand, use it
// or other win exec error codes, notably...
// 2 we really didn't find it
// 15 user cancel, fail the exec quietly
//
int FindAssociatedExe(HWND hwnd, LPTSTR lpCommand, UINT cchCommand, LPCTSTR pszDocument, HKEY hkeyProgID) { FINDEXE_PARAMS find; TCHAR szPath[MAX_PATH]; TCHAR szExe[MAX_PATH]; TCHAR szType[MAX_PATH];
// strip down to just the EXE name
lstrcpyn(szPath, lpCommand, ARRAYSIZE(szPath)); PathRemoveArgs(szPath); PathUnquoteSpaces(szPath);
// check to see if the file does exist. if it does then
// the original exec must have failed because some
// dependant DLL is missing. so we return file not
// found, even though we really found the file
PathAddExtension(szPath, NULL); if (PathFileExists(szPath)) return SE_ERR_FNF; // file exists, but some dll must not
// store the file name component
lstrcpyn(szExe, PathFindFileName(szPath), ARRAYSIZE(szExe));
// HACKHACK we should use the registry but it's too late now;
// Win95 shipped with this code so it's gonna be in win.ini forever...
GetProfileString(TEXT("programs"), szExe, szNULL, szPath, ARRAYSIZE(szPath)); if (szPath[0]) { if (PathFileExists(szPath)) { PathReplaceExe(lpCommand, cchCommand, szPath); // return the new path
return -1; // this means to try again
}
PathRemoveFileSpec(szPath); } else { /* Prompt with the disk that Windows is on */ GetWindowsDirectory(szPath, ARRAYSIZE(szPath)); szPath[3] = TEXT('\0'); }
SHGetTypeName(pszDocument, hkeyProgID, FALSE, szType, ARRAYSIZE(szType));
find.lpszExe = szExe; // base file name (to search for)
find.lpszPath = szPath; // starting location for search
find.lpszName = szType; // file type we are looking for
switch (DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FINDEXE), hwnd, FindExeDlgProcA, (LPARAM)(LPFINDEXE_PARAMS)&find)) { case IDOK: PathReplaceExe(lpCommand, cchCommand, szPath); // return the new path
return -1; // file found and lpCommand fixed up
case IDCANCEL: return ERROR_INVALID_FUNCTION; // This is the user cancel return
default: return SE_ERR_FNF; // stick with the file not found
} }
|