545 lines
16 KiB
C++
545 lines
16 KiB
C++
#include "local.h"
|
|
#include "../security.h"
|
|
#include "../favorite.h"
|
|
#include "resource.h"
|
|
#include "chcommon.h"
|
|
#include "cafolder.h"
|
|
|
|
#include <mluisupp.h>
|
|
|
|
#define DM_HSFOLDER 0
|
|
|
|
STDAPI AddToFavorites(HWND hwnd, LPCITEMIDLIST pidlCur, LPCTSTR pszTitle,
|
|
BOOL fDisplayUI, IOleCommandTarget *pCommandTarget, IHTMLDocument2 *pDoc);
|
|
|
|
#define MAX_ITEM_OPEN 10
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCacheItem Object
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CCacheItem::CCacheItem()
|
|
{
|
|
_dwDelCookie = DEL_COOKIE_WARN;
|
|
}
|
|
|
|
CCacheItem::~CCacheItem()
|
|
{
|
|
if (_pCFolder)
|
|
_pCFolder->Release(); // release the pointer to the sf
|
|
}
|
|
|
|
HRESULT CCacheItem::Initialize(CCacheFolder *pCFolder, HWND hwnd, UINT cidl, LPCITEMIDLIST *ppidl)
|
|
{
|
|
HRESULT hres = CBaseItem::Initialize(hwnd, cidl, ppidl);
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
_pCFolder = pCFolder;
|
|
_pCFolder->AddRef(); // we're going to hold onto this pointer, so
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CCacheItem_CreateInstance(CCacheFolder *pCFolder, HWND hwnd,
|
|
UINT cidl, LPCITEMIDLIST *ppidl, REFIID riid, void **ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*ppv = NULL; // null the out param
|
|
|
|
CCacheItem *pHCItem = new CCacheItem;
|
|
if (pHCItem)
|
|
{
|
|
hr = pHCItem->Initialize(pCFolder, hwnd, cidl, ppidl);
|
|
if (SUCCEEDED(hr))
|
|
hr = pHCItem->QueryInterface(riid, ppv);
|
|
pHCItem->Release();
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// IUnknown Methods...
|
|
//
|
|
HRESULT CCacheItem::QueryInterface(REFIID iid, void **ppv)
|
|
{
|
|
HRESULT hres = CBaseItem::QueryInterface(iid, ppv);
|
|
|
|
if (FAILED(hres) && iid == IID_ICache)
|
|
{
|
|
*ppv = (LPVOID)this; // for our friends
|
|
AddRef();
|
|
hres = S_OK;
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// IQueryInfo Methods
|
|
//
|
|
HRESULT CCacheItem::GetInfoTip(DWORD dwFlags, WCHAR **ppwszTip)
|
|
{
|
|
return _pCFolder->_GetInfoTip(_ppidl[0], dwFlags, ppwszTip);
|
|
}
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// IContextMenu Methods
|
|
//
|
|
HRESULT CCacheItem::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,UINT idCmdLast, UINT uFlags)
|
|
{
|
|
USHORT cItems;
|
|
|
|
TraceMsg(DM_HSFOLDER, "hci - cm - QueryContextMenu() called.");
|
|
|
|
if ((uFlags & CMF_VERBSONLY) || (uFlags & CMF_DVFILE))
|
|
{
|
|
cItems = MergePopupMenu(&hmenu, POPUP_CONTEXT_URL_VERBSONLY, 0, indexMenu,
|
|
idCmdFirst, idCmdLast);
|
|
|
|
}
|
|
else // (uFlags & CMF_NORMAL)
|
|
{
|
|
UINT idResource = POPUP_CACHECONTEXT_URL;
|
|
|
|
cItems = MergePopupMenu(&hmenu, idResource, 0, indexMenu, idCmdFirst, idCmdLast);
|
|
|
|
if (IsInetcplRestricted(L"History"))
|
|
{
|
|
DeleteMenu(hmenu, RSVIDM_DELCACHE + idCmdFirst, MF_BYCOMMAND);
|
|
_SHPrettyMenu(hmenu);
|
|
}
|
|
}
|
|
if (hmenu)
|
|
SetMenuDefaultItem(hmenu, indexMenu, MF_BYPOSITION);
|
|
|
|
return ResultFromShort(cItems); // number of menu items
|
|
}
|
|
|
|
static BOOL CachevuWarningDlg(LPCEIPIDL pcei, UINT uIDWarning, HWND hwnd)
|
|
{
|
|
TCHAR szFormat[MAX_PATH], szBuff[MAX_PATH], szTitle[MAX_PATH];
|
|
|
|
_GetCacheItemTitle(pcei, szTitle, ARRAYSIZE(szTitle));
|
|
MLLoadString(uIDWarning, szFormat, ARRAYSIZE(szFormat));
|
|
wnsprintf(szBuff, ARRAYSIZE(szFormat), szFormat);
|
|
|
|
return DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_HISTCACHE_WARNING),
|
|
hwnd, HistoryConfirmDeleteDlgProc, (LPARAM)szBuff) == IDYES;
|
|
}
|
|
|
|
STDMETHODIMP CCacheItem::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
|
|
{
|
|
UINT i;
|
|
int idCmd = _GetCmdID(pici->lpVerb);
|
|
HRESULT hres = S_OK;
|
|
DWORD dwAction;
|
|
BOOL fCancelCopyAndOpen = FALSE;
|
|
BOOL fZonesUI = FALSE;
|
|
BOOL fMustFlushNotify = FALSE;
|
|
BOOL fBulkDelete;
|
|
|
|
TraceMsg(DM_HSFOLDER, "hci - cm - InvokeCommand() called.");
|
|
|
|
// ZONES SECURITY CHECK.
|
|
//
|
|
// We need to cycle through each action and Zone Check the URLs.
|
|
// We pass NOUI when zone checking the URLs because we don't want info
|
|
// displayed to the user. We will stop when we find the first questionable
|
|
// URL. We will then
|
|
for (i = 0; (i < _cItems) && !fZonesUI; i++)
|
|
{
|
|
if (_ppidl[i])
|
|
{
|
|
switch (idCmd)
|
|
{
|
|
case RSVIDM_OPEN:
|
|
if ((i < MAX_ITEM_OPEN))
|
|
{
|
|
if (!_ZoneCheck(i, URLACTION_SHELL_VERB))
|
|
{
|
|
fZonesUI = TRUE;
|
|
dwAction = URLACTION_SHELL_VERB;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RSVIDM_COPY:
|
|
if (!_ZoneCheck(i, URLACTION_SHELL_MOVE_OR_COPY))
|
|
{
|
|
fZonesUI = TRUE;
|
|
dwAction = URLACTION_SHELL_MOVE_OR_COPY;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fZonesUI)
|
|
{
|
|
LPCTSTR pszUrl = _GetUrl(i-1); // Sub 1 because of for loop above.
|
|
if (S_OK != ZoneCheckUrl(pszUrl, dwAction, PUAF_DEFAULT|PUAF_WARN_IF_DENIED, NULL))
|
|
{
|
|
// The user cannot do this or does not want to do this.
|
|
fCancelCopyAndOpen = TRUE;
|
|
}
|
|
}
|
|
|
|
i = _cItems;
|
|
fBulkDelete = i > LOTS_OF_FILES;
|
|
|
|
// fCancelCopyAndOpen happens if the user cannot or chose not to proceed.
|
|
while (i && !fCancelCopyAndOpen)
|
|
{
|
|
i--;
|
|
if (_ppidl[i])
|
|
{
|
|
|
|
switch (idCmd)
|
|
{
|
|
case RSVIDM_OPEN:
|
|
if (i >= MAX_ITEM_OPEN)
|
|
{
|
|
hres = S_FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
if ((CEI_CACHEENTRYTYPE((LPCEIPIDL)_ppidl[i]) & COOKIE_CACHE_ENTRY))
|
|
{
|
|
ASSERT(PathFindExtension(CEI_LOCALFILENAME((LPCEIPIDL)_ppidl[i])) && \
|
|
!StrCmpI(PathFindExtension(CEI_LOCALFILENAME((LPCEIPIDL)_ppidl[i])),TEXT(".txt")));
|
|
hres = _LaunchApp(pici->hwnd, CEI_LOCALFILENAME((LPCEIPIDL)_ppidl[i]));
|
|
}
|
|
else
|
|
{
|
|
TCHAR szDecoded[MAX_URL_STRING];
|
|
LPCTSTR pszUrl = _GetUrl(i);
|
|
if (pszUrl)
|
|
{
|
|
ConditionallyDecodeUTF8(pszUrl, szDecoded, ARRAYSIZE(szDecoded));
|
|
hres = _LaunchApp(pici->hwnd, szDecoded);
|
|
}
|
|
else
|
|
{
|
|
hres = E_FAIL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case RSVIDM_ADDTOFAVORITES:
|
|
hres = _AddToFavorites(i);
|
|
goto Done;
|
|
case RSVIDM_OPEN_NEWWINDOW:
|
|
{
|
|
LPCTSTR pszUrl = _GetUrl(i);
|
|
if (pszUrl)
|
|
{
|
|
TCHAR szDecoded[MAX_URL_STRING];
|
|
ConditionallyDecodeUTF8(pszUrl, szDecoded, ARRAYSIZE(szDecoded));
|
|
LPWSTR pwszTarget;
|
|
|
|
if (SUCCEEDED((hres = SHStrDup(szDecoded, &pwszTarget)))) {
|
|
hres = NavToUrlUsingIEW(pwszTarget, TRUE);
|
|
CoTaskMemFree(pwszTarget);
|
|
}
|
|
}
|
|
else
|
|
hres = E_FAIL;
|
|
goto Done;
|
|
}
|
|
case RSVIDM_COPY:
|
|
OleSetClipboard((IDataObject *)this);
|
|
goto Done;
|
|
|
|
case RSVIDM_DELCACHE:
|
|
// pop warning msg for cookie only once
|
|
if ((CEI_CACHEENTRYTYPE((LPCEIPIDL)_ppidl[i]) & COOKIE_CACHE_ENTRY) &&
|
|
(_dwDelCookie == DEL_COOKIE_WARN ))
|
|
{
|
|
if(CachevuWarningDlg((LPCEIPIDL)_ppidl[i], IDS_WARN_DELETE_CACHE, pici->hwnd))
|
|
_dwDelCookie = DEL_COOKIE_YES;
|
|
else
|
|
_dwDelCookie = DEL_COOKIE_NO;
|
|
}
|
|
|
|
if ((CEI_CACHEENTRYTYPE((LPCEIPIDL)_ppidl[i]) & COOKIE_CACHE_ENTRY) &&
|
|
(_dwDelCookie == DEL_COOKIE_NO ))
|
|
continue;
|
|
|
|
if (DeleteUrlCacheEntry(CPidlToSourceUrl((LPCEIPIDL)_ppidl[i])))
|
|
{
|
|
if (!fBulkDelete)
|
|
{
|
|
_GenerateEvent(SHCNE_DELETE, _pCFolder->_pidl, _ppidl[i], NULL);
|
|
}
|
|
fMustFlushNotify = TRUE;
|
|
}
|
|
else
|
|
hres = E_FAIL;
|
|
break;
|
|
|
|
case RSVIDM_PROPERTIES:
|
|
// NOTE: We'll probably want to split this into two cases
|
|
// and call a function in each case
|
|
//
|
|
_CreatePropSheet(pici->hwnd, _ppidl[i], DLG_CACHEITEMPROP, _sPropDlgProc,
|
|
CEI_SOURCEURLNAME((LPCEIPIDL)_ppidl[i]));
|
|
goto Done;
|
|
|
|
default:
|
|
hres = E_FAIL;
|
|
break;
|
|
}
|
|
|
|
ASSERT(SUCCEEDED(hres));
|
|
if (FAILED(hres))
|
|
TraceMsg(DM_HSFOLDER, "Cachevu failed the command at: %s", CPidlToSourceUrl((LPCEIPIDL)_ppidl[i]));
|
|
}
|
|
}
|
|
Done:
|
|
if (fMustFlushNotify)
|
|
{
|
|
if (fBulkDelete)
|
|
{
|
|
_GenerateEvent(SHCNE_UPDATEDIR, _pCFolder->_pidl, NULL, NULL);
|
|
}
|
|
|
|
SHChangeNotifyHandleEvents();
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// IDataObject Methods...
|
|
//
|
|
|
|
HRESULT CCacheItem::GetData(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM)
|
|
{
|
|
HRESULT hres;
|
|
|
|
#ifdef DEBUG
|
|
TCHAR szName[64];
|
|
if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
|
|
wnsprintf(szName, ARRAYSIZE(szName), TEXT("#%d"), pFEIn->cfFormat);
|
|
|
|
TraceMsg(DM_HSFOLDER, "hci - do - GetData(%s)", szName);
|
|
#endif
|
|
|
|
pSTM->hGlobal = NULL;
|
|
pSTM->pUnkForRelease = NULL;
|
|
|
|
if (pFEIn->cfFormat == CF_HDROP && (pFEIn->tymed & TYMED_HGLOBAL))
|
|
hres = _CreateHDROP(pSTM);
|
|
|
|
else if ((pFEIn->cfFormat == g_cfPreferredEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
|
|
hres = _CreatePrefDropEffect(pSTM);
|
|
|
|
else
|
|
hres = DATA_E_FORMATETC;
|
|
|
|
return hres;
|
|
|
|
}
|
|
|
|
HRESULT CCacheItem::QueryGetData(LPFORMATETC pFEIn)
|
|
{
|
|
#ifdef DEBUG
|
|
TCHAR szName[64];
|
|
if (!GetClipboardFormatName(pFEIn->cfFormat, szName, sizeof(szName)))
|
|
wnsprintf(szName, ARRAYSIZE(szName), TEXT("#%d"), pFEIn->cfFormat);
|
|
|
|
TraceMsg(DM_HSFOLDER, "hci - do - QueryGetData(%s)", szName);
|
|
#endif
|
|
|
|
if (pFEIn->cfFormat == CF_HDROP ||
|
|
pFEIn->cfFormat == g_cfPreferredEffect)
|
|
{
|
|
TraceMsg(DM_HSFOLDER, " format supported.");
|
|
return NOERROR;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT CCacheItem::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC *ppEnum)
|
|
{
|
|
FORMATETC Cachefmte[] = {
|
|
{CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
|
|
{g_cfPreferredEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
|
|
};
|
|
return SHCreateStdEnumFmtEtc(ARRAYSIZE(Cachefmte), Cachefmte, ppEnum);
|
|
}
|
|
|
|
//////////////////////////////////
|
|
//
|
|
// IExtractIconA Methods...
|
|
//
|
|
HRESULT CCacheItem::GetIconLocation(UINT uFlags, LPSTR pszIconFile, UINT ucchMax, PINT pniIcon, PUINT puFlags)
|
|
{
|
|
if (ucchMax < 2)
|
|
return E_FAIL;
|
|
|
|
*puFlags = GIL_NOTFILENAME;
|
|
pszIconFile[0] = '*';
|
|
pszIconFile[1] = '\0';
|
|
|
|
// "*" as the file name means iIndex is already a system icon index.
|
|
return _pCFolder->GetIconOf(_ppidl[0], uFlags, pniIcon);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Helper Routines
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
UNALIGNED const TCHAR* CCacheItem::_GetURLTitle(LPCITEMIDLIST pidl)
|
|
{
|
|
return ::_GetURLTitle( (LPCEIPIDL) pidl);
|
|
}
|
|
|
|
LPCTSTR CCacheItem::_GetUrl(int nIndex)
|
|
{
|
|
LPCTSTR pszUrl = NULL;
|
|
pszUrl = CPidlToSourceUrl((LPCEIPIDL)_ppidl[nIndex]);
|
|
return pszUrl;
|
|
}
|
|
|
|
LPCTSTR CCacheItem::_PidlToSourceUrl(LPCITEMIDLIST pidl)
|
|
{
|
|
return CPidlToSourceUrl((LPCEIPIDL) pidl);
|
|
}
|
|
|
|
|
|
// Return value:
|
|
// TRUE - URL is Safe.
|
|
// FALSE - URL is questionable and needs to be re-zone checked w/o PUAF_NOUI.
|
|
BOOL CCacheItem::_ZoneCheck(int nIndex, DWORD dwUrlAction)
|
|
{
|
|
LPCTSTR pszUrl = _GetUrl(nIndex);
|
|
|
|
if (S_OK != ZoneCheckUrl(pszUrl, dwUrlAction, PUAF_NOUI, NULL))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT_PTR CALLBACK CCacheItem::_sPropDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE) GetWindowLongPtr(hDlg, DWLP_USER);
|
|
LPCEIPIDL pcei = lpPropSheet ? (LPCEIPIDL)lpPropSheet->lParam : NULL;
|
|
|
|
switch(message) {
|
|
|
|
case WM_INITDIALOG: {
|
|
SHFILEINFO sfi;
|
|
TCHAR szBuf[80];
|
|
|
|
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
|
|
pcei = (LPCEIPIDL)((LPPROPSHEETPAGE)lParam)->lParam;
|
|
|
|
// get the icon and file type strings
|
|
|
|
SHGetFileInfo(CEI_LOCALFILENAME(pcei), 0, &sfi, SIZEOF(sfi), SHGFI_ICON | SHGFI_TYPENAME);
|
|
|
|
SendDlgItemMessage(hDlg, IDD_ITEMICON, STM_SETICON, (WPARAM)sfi.hIcon, 0);
|
|
|
|
// set the info strings
|
|
SetDlgItemText(hDlg, IDD_HSFURL, CPidlToSourceUrl((LPCEIPIDL)pcei));
|
|
SetDlgItemText(hDlg, IDD_FILETYPE, sfi.szTypeName);
|
|
|
|
SetDlgItemText(hDlg, IDD_FILESIZE, StrFormatByteSize(pcei->cei.dwSizeLow, szBuf, ARRAYSIZE(szBuf)));
|
|
SetDlgItemText(hDlg, IDD_CACHE_NAME, PathFindFileName(CEI_LOCALFILENAME(pcei)));
|
|
FileTimeToDateTimeStringInternal(&pcei->cei.ExpireTime, szBuf, ARRAYSIZE(szBuf), FALSE);
|
|
SetDlgItemText(hDlg, IDD_EXPIRES, szBuf);
|
|
FileTimeToDateTimeStringInternal(&pcei->cei.LastModifiedTime, szBuf, ARRAYSIZE(szBuf), FALSE);
|
|
SetDlgItemText(hDlg, IDD_LAST_MODIFIED, szBuf);
|
|
FileTimeToDateTimeStringInternal(&pcei->cei.LastAccessTime, szBuf, ARRAYSIZE(szBuf), FALSE);
|
|
SetDlgItemText(hDlg, IDD_LAST_ACCESSED, szBuf);
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
HICON hIcon = (HICON)SendDlgItemMessage(hDlg, IDD_ITEMICON, STM_GETICON, 0, 0);
|
|
if (hIcon)
|
|
DestroyIcon(hIcon);
|
|
}
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
case WM_HELP:
|
|
case WM_CONTEXTMENU:
|
|
// user can't change anything, so we don't care about any messages
|
|
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
} // end of switch
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// use CEI_LOCALFILENAME to get the file name for the HDROP, but map that
|
|
// to the final file name (store in the file system) through the "FileNameMap"
|
|
// data which uses _GetURLTitle() as the final name of the file.
|
|
|
|
HRESULT CCacheItem::_CreateHDROP(STGMEDIUM *pmedium)
|
|
{
|
|
UINT i;
|
|
UINT cbAlloc = sizeof(DROPFILES) + sizeof(CHAR); // header + null terminator
|
|
|
|
for (i = 0; i < _cItems; i++)
|
|
{
|
|
char szAnsiUrl[MAX_URL_STRING];
|
|
|
|
SHTCharToAnsi(CEI_LOCALFILENAME((LPCEIPIDL)_ppidl[i]), szAnsiUrl, ARRAYSIZE(szAnsiUrl));
|
|
cbAlloc += sizeof(CHAR) * (lstrlenA(szAnsiUrl) + 1);
|
|
}
|
|
|
|
pmedium->tymed = TYMED_HGLOBAL;
|
|
pmedium->pUnkForRelease = NULL;
|
|
pmedium->hGlobal = GlobalAlloc(GPTR, cbAlloc);
|
|
if (pmedium->hGlobal)
|
|
{
|
|
LPDROPFILES pdf = (LPDROPFILES)pmedium->hGlobal;
|
|
LPSTR pszFiles = (LPSTR)(pdf + 1);
|
|
int cchFiles = (cbAlloc - sizeof(DROPFILES) - sizeof(CHAR));
|
|
pdf->pFiles = sizeof(DROPFILES);
|
|
pdf->fWide = FALSE;
|
|
|
|
for (i = 0; i < _cItems; i++)
|
|
{
|
|
LPTSTR pszPath = CEI_LOCALFILENAME((LPCEIPIDL)_ppidl[i]);
|
|
int cchPath = lstrlen(pszPath);
|
|
|
|
SHTCharToAnsi(pszPath, pszFiles, cchFiles);
|
|
|
|
pszFiles += cchPath + 1;
|
|
cchFiles -= cchPath + 1;
|
|
|
|
ASSERT((UINT)((LPBYTE)pszFiles - (LPBYTE)pdf) < cbAlloc);
|
|
}
|
|
ASSERT((LPSTR)pdf + cbAlloc - 1 == pszFiles);
|
|
ASSERT(*pszFiles == 0); // zero init alloc
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|