windows-nt/Source/XPSP1/NT/shell/ext/ftp/dialogs.cpp
2020-09-26 16:20:57 +08:00

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);
}