/*****************************************************************************\ FILE: Dialogs.cpp DESCRIPTION: This file exists to display dialogs needed during FTP operations. \*****************************************************************************/ #include "priv.h" #include #include "dialogs.h" #ifdef ADD_ABOUTBOX /*****************************************************************************\ FUNCTION: DisplayAboutBox DESCRIPTION: The about box is now an HTML dialog. It is sent a ~ (tilde) delimited BSTR that has, in this order, version number, person software is licensed to, company software is licensed to, and whether 40, 56, or 128 bit ie is installed. \*****************************************************************************/ HRESULT DisplayAboutBox(HWND hWnd) { TCHAR szInfo[512]; szInfo[0] = 0; SHAboutInfo(szInfo, ARRAYSIZE(szInfo)); // from shlwapi BSTR bstrVal = TCharSysAllocString(szInfo); if (bstrVal) { VARIANT var = {0}; // variant containing version and user info var.vt = VT_BSTR; var.bstrVal = bstrVal; IMoniker *pmk; if (SUCCEEDED(CreateURLMoniker(NULL, L"res://msieftp.dll/about.htm", &pmk))) { ShowHTMLDialog(hWnd, pmk, &var, NULL, NULL); pmk->Release(); } SysFreeString(bstrVal); } return S_OK; } #endif // ADD_ABOUTBOX // This function exists to see if the FTP version of the Copy To Folder // feature's target is valid. The shell has "Copy To Folder" in the toolbar // that accomplishes the copy by using Drag and Drop. FTP has it's own // version of this feature in the context menu and file menu that doesn't // use drag and drop. This exists because the type of drag and drop // that we need (CFSTR_FILECONTENTS) isn't correctly implemented on // old shells and our implmentation is 3 times faster!!! However, // we only support file system targets so let's see if this is one // of those. BOOL IsValidFTPCopyToFolderTarget(LPCITEMIDLIST pidl) { BOOL fAllowed = FALSE; if (pidl) { TCHAR szPath[MAX_PATH]; if (SHGetPathFromIDList((LPITEMIDLIST)pidl, szPath)) { fAllowed = TRUE; } } return fAllowed; } int BrowseCallback(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData) { int nResult = 0; switch (msg) { case BFFM_INITIALIZED: if (lpData) // Documentation says it will be NULL but other code does this. { // we passed ppidl as lpData so pass on just pidl // Notice I pass BFFM_SETSELECTIONA which would normally indicate ANSI. // I do this because Win95 requires it, but it doesn't matter because I'm // only passing a pidl SendMessage(hwnd, BFFM_SETSELECTIONA, FALSE, (LPARAM)((LPITEMIDLIST)lpData)); } break; // NT #282886: Need to verify if the path is supported. (A:\ with floppy inserted w/o cancel) // I verified this works shortly after Win2k but we need to test for it in the future. case BFFM_SELCHANGED: // We need to make sure that the selected item is valid for us to // accept. This is because the tree will contain items that don't // pass the filter (file sys only) because they have non-filtered // children. We need to disable the OK button when this happens // to prevent getting SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM)IsValidFTPCopyToFolderTarget((LPCITEMIDLIST) lParam)); break; case BFFM_VALIDATEFAILEDA: AssertMsg(0, TEXT("How can we get this? That's not the structure I sent them.")); break; case BFFM_VALIDATEFAILEDW: // If we return zero, then we are saying it's OK. We only want to do this with // file paths. nResult = !PathIsRoot((LPCWSTR) lParam); // Is this invalid? if (nResult) { TCHAR szErrorTitle[MAX_PATH]; TCHAR szErrorMsg[MAX_PATH]; // Yes, so we need to inform the user so they know why the dialog doesn't // close. EVAL(LoadString(HINST_THISDLL, IDS_HELP_MSIEFTPTITLE, szErrorTitle, ARRAYSIZE(szErrorTitle))); EVAL(LoadString(HINST_THISDLL, IDS_FTPERR_BAD_DL_TARGET, szErrorMsg, ARRAYSIZE(szErrorMsg))); MessageBox(hwnd, szErrorMsg, szErrorTitle, (MB_OK | MB_ICONERROR)); } break; } return nResult; } /*****************************************************************************\ FUNCTION: BrowseForDir DESCRIPTION: Let the user browser for a directory on the local file system in order to chose a destination for the FTP transfer. S_FALSE will be returned if the user cancelled the action. \*****************************************************************************/ HRESULT BrowseForDir(HWND hwndParent, LPCTSTR pszTitle, LPCITEMIDLIST pidlDefaultSelect, LPITEMIDLIST * ppidlSelected) { HRESULT hr = S_OK; if (ppidlSelected) { ASSERT(hwndParent); BROWSEINFO bi = {0}; bi.hwndOwner = hwndParent; bi.lpszTitle = pszTitle; bi.lpfn = BrowseCallback; bi.lParam = (LPARAM) pidlDefaultSelect; bi.ulFlags = (BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS | BIF_EDITBOX | BIF_USENEWUI | BIF_VALIDATE); *ppidlSelected = SHBrowseForFolder(&bi); if (!*ppidlSelected) hr = S_FALSE; } return hr; } /****************************************************\ FUNCTION: ShowDialog DESCRIPTION: \****************************************************/ HRESULT CDownloadDialog::ShowDialog(HWND hwndOwner, LPTSTR pszDir, DWORD cchSize, DWORD * pdwDownloadType) { HRESULT hr = S_OK; if (DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(IDD_DOWNLOADDIALOG), hwndOwner, DownloadDialogProc, (LPARAM)this)) { StrCpyN(pszDir, HANDLE_NULLSTR(m_pszDir), cchSize); *pdwDownloadType = m_dwDownloadType; hr = S_OK; } else hr = S_FALSE; return hr; } /****************************************************\ FUNCTION: DownloadDialogProc DESCRIPTION: \****************************************************/ INT_PTR CALLBACK CDownloadDialog::DownloadDialogProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { CDownloadDialog * ppd = (CDownloadDialog *)GetWindowLongPtr(hDlg, GWLP_USERDATA); if (WM_INITDIALOG == wMsg) { SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam); ppd = (CDownloadDialog *)lParam; } if (ppd) return ppd->_DownloadDialogProc(hDlg, wMsg, wParam, lParam); return TRUE; } /****************************************************\ FUNCTION: _DownloadDialogProc DESCRIPTION: \****************************************************/ BOOL CDownloadDialog::_DownloadDialogProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch (wMsg) { case WM_INITDIALOG: return _InitDialog(hDlg); case WM_COMMAND: return _OnCommand(hDlg, wParam, lParam); } return FALSE; } /****************************************************\ FUNCTION: _OnCommand DESCRIPTION: \****************************************************/ BOOL CDownloadDialog::_OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) { UINT idc = GET_WM_COMMAND_ID(wParam, lParam); switch (idc) { case IDC_DOWNLOAD_BUTTON: if (SUCCEEDED(_DownloadButton(hDlg))) EndDialog(hDlg, TRUE); break; case IDCANCEL: EndDialog(hDlg, FALSE); break; case IDC_BROWSE_BUTTON: _BrowseButton(hDlg); break; default: return FALSE; } return TRUE; } /****************************************************\ FUNCTION: _InitDialog DESCRIPTION: \****************************************************/ BOOL CDownloadDialog::_InitDialog(HWND hDlg) { HRESULT hr; TCHAR szDir[MAX_PATH] = TEXT("C:\\"); // If all else fails. DWORD cbSize = sizeof(szDir); // Set the Directory if ((ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_EXPLORER, SZ_REGVALUE_DOWNLOAD_DIR, NULL, szDir, &cbSize)) || (!PathFileExists(szDir))) { LPITEMIDLIST pidlMyDocuments; // Create the default dir, which should be "My Documents" hr = SHGetSpecialFolderLocation(hDlg, CSIDL_PERSONAL, &pidlMyDocuments); if (SUCCEEDED(hr) && pidlMyDocuments) { SHGetPathFromIDList(pidlMyDocuments, szDir); ILFree(pidlMyDocuments); } } SetWindowText(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR), szDir); // Set the Download Type cbSize = sizeof(m_dwDownloadType); m_dwDownloadType = FTP_TRANSFER_TYPE_UNKNOWN; // Default. SHGetValue(HKEY_CURRENT_USER, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_DOWNLOAD_TYPE, NULL, &m_dwDownloadType, &cbSize); for (UINT idDownloadType = IDS_DL_TYPE_AUTOMATIC; idDownloadType <= IDS_DL_TYPE_BINARY; idDownloadType++) { LoadString(HINST_THISDLL, idDownloadType, szDir, ARRAYSIZE(szDir)); SendMessage(GetDlgItem(hDlg, IDC_DOWNLOAD_AS_LIST), CB_ADDSTRING, NULL, (LPARAM) szDir); } SendMessage(GetDlgItem(hDlg, IDC_DOWNLOAD_AS_LIST), CB_SETCURSEL, (WPARAM) m_dwDownloadType, 0); hr = AutoCompleteFileSysInEditbox(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR)); ASSERT(SUCCEEDED(hr)); return FALSE; } /****************************************************\ FUNCTION: _DownloadButton DESCRIPTION: \****************************************************/ HRESULT CDownloadDialog::_DownloadButton(HWND hDlg) { HRESULT hr = S_OK; TCHAR szDirOriginal[MAX_PATH]; // If all else fails. TCHAR szDir[MAX_PATH]; // If all else fails. // Get the Directory GetWindowText(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR), szDirOriginal, ARRAYSIZE(szDirOriginal)); EVAL(ExpandEnvironmentStrings(szDirOriginal, szDir, ARRAYSIZE(szDir))); Str_SetPtr(&m_pszDir, szDir); SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_INTERNET_EXPLORER, SZ_REGVALUE_DOWNLOAD_DIR, REG_SZ, szDir, ARRAYSIZE(szDir)); // Get the Download Type m_dwDownloadType = (DWORD)SendMessage(GetDlgItem(hDlg, IDC_DOWNLOAD_AS_LIST), CB_GETCURSEL, 0, 0); SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_FTPFOLDER, SZ_REGVALUE_DOWNLOAD_TYPE, REG_DWORD, &m_dwDownloadType, sizeof(m_dwDownloadType)); // Make sure this path is usable ASSERT(hDlg); if (S_OK == SHPathPrepareForWriteWrapW(hDlg, NULL, szDir, FO_COPY, SHPPFW_DEFAULT)) { if (!PathIsRoot(szDir) && !PathFileExists(szDir)) { TCHAR szErrorTitle[MAX_PATH]; TCHAR szErrorMsg[MAX_PATH]; TCHAR szErrorTemplate[MAX_PATH]; hr = E_FAIL; // Until we get a valid directory, we can't do the download. EVAL(LoadString(HINST_THISDLL, IDS_HELP_MSIEFTPTITLE, szErrorTitle, ARRAYSIZE(szErrorTitle))); EVAL(LoadString(HINST_THISDLL, IDS_FTPERR_CREATEDIRPROMPT, szErrorTemplate, ARRAYSIZE(szErrorTemplate))); wnsprintf(szErrorMsg, ARRAYSIZE(szErrorMsg), szErrorTemplate, szDir); if (IDYES == MessageBox(hDlg, szErrorMsg, szErrorTitle, (MB_YESNO | MB_ICONQUESTION))) { if (CreateDirectory(szDir, NULL)) hr = S_OK; else { EVAL(LoadString(HINST_THISDLL, IDS_FTPERR_CREATEFAILED, szErrorMsg, ARRAYSIZE(szErrorMsg))); MessageBox(hDlg, szErrorMsg, szErrorTitle, (MB_OK | MB_ICONERROR)); } } } } return hr; } /****************************************************\ FUNCTION: _BrowseButton DESCRIPTION: \****************************************************/ void CDownloadDialog::_BrowseButton(HWND hDlg) { TCHAR szDefaultDir[MAX_PATH]; TCHAR szTitle[MAX_PATH]; GetWindowText(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR), szDefaultDir, ARRAYSIZE(szDefaultDir)); EVAL(LoadString(HINST_THISDLL, IDS_DLG_DOWNLOAD_TITLE, szTitle, ARRAYSIZE(szTitle))); if (S_OK == BrowseForDir(hDlg, szTitle, NULL, NULL)) SetWindowText(GetDlgItem(hDlg, IDC_DOWNLOAD_DIR), szDefaultDir); } /****************************************************\ Constructor \****************************************************/ CDownloadDialog::CDownloadDialog() { // NOTE: This can go on the stack so it may not be zero inited. m_pszDir = NULL; m_hwnd = NULL; } /****************************************************\ Destructor \****************************************************/ CDownloadDialog::~CDownloadDialog() { Str_SetPtr(&m_pszDir, NULL); }