#define UNICODE 1 #include "shellprv.h" #pragma hdrstop const WCHAR szCommdlgHelp[] = L"commdlg_help"; UINT wBrowseHelp = WM_USER; /* Set to an unused value */ const CHAR szGetOpenFileName[] = "GetOpenFileNameW"; /* the defines below should be in windows.h */ /* Dialog window class */ #define WC_DIALOG (MAKEINTATOM(0x8002)) /* cbWndExtra bytes needed by dialog manager for dialog classes */ #define DLGWINDOWEXTRA 30 /* Get/SetWindowWord/Long offsets for use with WC_DIALOG windows */ #define DWL_MSGRESULT 0 #define DWL_DLGPROC 4 #define DWL_USER 8 /* For Long File Name support */ #define MAX_EXTENSION 64 typedef struct { LPWSTR lpszExe; LPWSTR lpszPath; LPWSTR lpszName; } FINDEXE_PARAMS, FAR *LPFINDEXE_PARAMS; typedef INT (APIENTRY *LPFNGETOPENFILENAME)(LPOPENFILENAME); VOID APIENTRY CheckEscapesW(LPWSTR szFile, DWORD cch) { LPWSTR szT; WCHAR *p, *pT; for (p = szFile; *p; p++) { switch (*p) { case WCHAR_SPACE: case WCHAR_COMMA: case WCHAR_SEMICOLON: case WCHAR_HAT: case WCHAR_QUOTE: { // this path contains an annoying character if (cch < (wcslen(szFile) + 2)) { return; } szT = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR)); if (!szT) { return; } wcscpy(szT,szFile); p = szFile; *p++ = WCHAR_QUOTE; for (pT = szT; *pT; ) { *p++ = *pT++; } *p++ = WCHAR_QUOTE; *p = WCHAR_NULL; LocalFree(szT); return; } } } } VOID APIENTRY CheckEscapesA(LPSTR lpFileA, DWORD cch) { if (lpFileA && *lpFileA) { LPWSTR lpFileW; lpFileW = (LPWSTR)LocalAlloc(LPTR, (cch * sizeof(WCHAR))); if (!lpFileW) { return; } SHAnsiToUnicode(lpFileA, lpFileW, cch); CheckEscapesW(lpFileW, cch); try { SHUnicodeToAnsi(lpFileW, lpFileA, cch); } except(EXCEPTION_EXECUTE_HANDLER) { LocalFree(lpFileW); return; } LocalFree(lpFileW); } return; } // Hooks into common dialog to allow size of selected files to be displayed. BOOL APIENTRY LocateHookProc( HWND hDlg, UINT uiMessage, WPARAM wParam, LONG lParam) { WCHAR szTemp[40]; WORD wID; switch (uiMessage) { case WM_INITDIALOG: PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L); break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case ctlLast+1: GetDlgItemText(hDlg, edt1, szTemp, ARRAYSIZE(szTemp)); if (SendDlgItemMessage(hDlg, lst1, LB_FINDSTRING, (WPARAM)-1, (LONG_PTR)(LPSTR)szTemp) >= 0) { wID = IDS_PROGFOUND; } else { wID = IDS_PROGNOTFOUND; } LoadString(HINST_THISDLL, wID, szTemp, ARRAYSIZE(szTemp)); SetDlgItemText(hDlg, ctlLast+2, szTemp); break; case lst2: if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_DBLCLK) PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L); break; case cmb2: switch (GET_WM_COMMAND_CMD(wParam, lParam)) { case CBN_SELCHANGE: PostMessage(hDlg, WM_COMMAND, ctlLast+1, 1L); break; case CBN_CLOSEUP: PostMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(cmb2, GetDlgItem(hDlg, cmb2), CBN_SELCHANGE)); break; } break; case IDOK: case IDCANCEL: case IDABORT: PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L); break; } break; } UNREFERENCED_PARAMETER(lParam); return(FALSE); // commdlg, do your thing } BOOL_PTR APIENTRY FindExeDlgProcW( HWND hDlg, register UINT wMsg, WPARAM wParam, LPARAM lParam) { /* Notice this is OK as a global, because it will be reloaded * when needed */ static HANDLE hCommDlg = NULL; WCHAR szPath[MAX_PATH]; /* This must be the same size as lpfind->lpszPath */ WCHAR szBuffer[MAX_PATH + 100]; LPFINDEXE_PARAMS lpfind; int temp; LPWSTR lpTemp; switch (wMsg) { case WM_INITDIALOG: wBrowseHelp = RegisterWindowMessage(szCommdlgHelp); lpfind = (LPFINDEXE_PARAMS)lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lpfind); 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); break; case WM_DESTROY: if (hCommDlg >= (HANDLE)32) { FreeLibrary(hCommDlg); hCommDlg = NULL; } break; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDD_BROWSE: { LPFNGETOPENFILENAME lpfnGetOpenFileName; WCHAR szExts[MAX_EXTENSION]; OPENFILENAME ofn; GetDlgItemText(hDlg, IDD_PATH, szBuffer, ARRAYSIZE(szBuffer)); lpfind = (LPFINDEXE_PARAMS)GetWindowLongPtr(hDlg, DWLP_USER); wcscpy(szPath, lpfind->lpszExe); SheRemoveQuotesW(szPath); /* Make up a file types string */ // BUG BUG this assumes extensions are of length 3. szExts[0] = WCHAR_CAP_A; szExts[1] = WCHAR_NULL; szExts[2] = WCHAR_STAR; szExts[3] = WCHAR_DOT; szExts[4] = WCHAR_NULL; if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_DOT))) StrCpyN(szExts+3, lpTemp, ((wcslen(lpTemp) < 60) ? wcslen(lpTemp) : 60)); szExts[3+wcslen(szExts+3)+1] = WCHAR_NULL; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.hInstance = HINST_THISDLL; ofn.lpstrFilter = L"A\0\?.?\0"; // a dummy filter ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = szPath; ofn.nMaxFile = sizeof(szPath); ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_ENABLETEMPLATE | OFN_SHOWHELP; ofn.lCustData = (LONG_PTR) hDlg; ofn.lpfnHook = NULL; // AddFileHookProc; ofn.lpTemplateName = MAKEINTRESOURCE(DLG_BROWSE); ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = NULL; ofn.lpstrFileTitle = NULL; if (hCommDlg < (HANDLE)32 && (hCommDlg = LoadLibrary(TEXT("comdlg32.dll"))) < (HANDLE)32) { CommDlgError: LoadString(HINST_THISDLL, IDS_NOCOMMDLG, szBuffer, ARRAYSIZE(szBuffer)); GetWindowText(hDlg, szPath, ARRAYSIZE(szPath)); MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK); break; } if (!(lpfnGetOpenFileName = (LPFNGETOPENFILENAME)GetProcAddress((HINSTANCE)hCommDlg, (LPSTR)szGetOpenFileName))) goto CommDlgError; temp = (*lpfnGetOpenFileName)(&ofn); if (temp) { LPWSTR lpTemp; lpTemp = StrRChrW(szPath, NULL, WCHAR_BSLASH); *lpTemp = WCHAR_NULL; SetDlgItemText(hDlg, IDD_PATH, szPath); } break; } case IDOK: { HANDLE hFile; lpfind = (LPFINDEXE_PARAMS)GetWindowLongPtr(hDlg, DWLP_USER); if (lpfind) { GetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath, MAX_PATH); switch (*CharPrev(lpfind->lpszPath, lpTemp=lpfind->lpszPath+lstrlen(lpfind->lpszPath))) { case WCHAR_BSLASH: case WCHAR_COLON: break; default: *lpTemp++ = WCHAR_BSLASH; break; } wcscpy(lpTemp, lpfind->lpszExe); hFile = CreateFile(lpfind->lpszPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { LoadString(HINST_THISDLL, IDS_STILLNOTFOUND, szPath, ARRAYSIZE(szPath)); wsprintf(szBuffer, szPath, lpfind->lpszPath); GetWindowText(hDlg, szPath, ARRAYSIZE(szPath)); MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK); break; } WriteProfileString(TEXT("programs"), lpfind->lpszExe, lpfind->lpszPath); } } // fall through case IDCANCEL: EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK); break; } break; default: return FALSE; } return TRUE; } // Returns -1 if we found the file (and it was not in an obvious place) // or an error code which will be returned to the app (see the error // returns for ShellExecute) HANDLE APIENTRY FindAssociatedExeW( HWND hwnd, LPWSTR lpCommand, LPWSTR lpName) { FINDEXE_PARAMS find; WCHAR szPath[MAX_PATH]; WCHAR szExe[MAX_PATH]; LPWSTR lpSpace, lpTemp; HANDLE hFile = NULL; BOOL fQuote = FALSE; // find the param list lpSpace = lpCommand; while (*lpSpace) { if ((*lpSpace == WCHAR_SPACE) && (!fQuote)) { break; } else if (*lpSpace == WCHAR_QUOTE) { fQuote = !fQuote; } lpSpace++; } if (*lpSpace == WCHAR_SPACE) { *lpSpace = 0; wcscpy(szPath, lpCommand); *lpSpace = WCHAR_SPACE; } else { lpSpace = TEXT(""); wcscpy(szPath, lpCommand); } SheRemoveQuotesW(szPath); /* Add ".exe" if there is no extension * Check if the file can be opened; if it can, then some DLL could not * be found during the WinExec, so return file not found */ if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH)) || NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) { ++lpTemp; } else { lpTemp = szPath; } hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); return((HANDLE)2); } // store the file name component wcscpy(szExe, lpTemp); // make sure there is an extension if (!StrChrW(szExe, WCHAR_DOT)) { wcscat(szExe, TEXT(".exe")); } // add back the quotes, if necessary CheckEscapesW(szExe, MAX_PATH); // look in win.ini GetProfileString(TEXT("programs"), szExe, TEXT(""), szPath, ARRAYSIZE(szPath)); if (szPath[0]) { hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); wcscat(szPath, lpSpace); // add the parameters wcscpy(lpCommand, szPath); // return the new path return((HANDLE)-1); } /* Strip off the file part */ if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH))) { if (*CharPrev(szPath, lpTemp) == WCHAR_COLON) { ++lpTemp; } *lpTemp = WCHAR_NULL; } else if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) { *(lpTemp+1) = WCHAR_NULL; } } else { /* Prompt with the disk that Windows is on */ GetWindowsDirectory(szPath, ARRAYSIZE(szPath)-1); szPath[3] = WCHAR_NULL; } find.lpszExe = szExe; find.lpszPath = szPath; find.lpszName = lpName; switch(DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FINDEXE), hwnd, FindExeDlgProcW, (LONG_PTR)(LPFINDEXE_PARAMS)&find)) { case IDOK: wcscat(szPath, lpSpace); // add the parameters wcscpy(lpCommand, szPath); // return the new path return ((HANDLE)-1); case IDCANCEL: return((HANDLE)15); // This is the user cancel return default: return((HANDLE)2); // stick with the file not found } }