402 lines
12 KiB
C++
402 lines
12 KiB
C++
|
/*****************************************************************************\
|
||
|
FILE: Dialogs.cpp
|
||
|
|
||
|
DESCRIPTION:
|
||
|
This file exists to display dialogs needed during FTP operations.
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
#include "priv.h"
|
||
|
#include <mshtmhst.h>
|
||
|
#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);
|
||
|
}
|
||
|
|
||
|
|