|
|
#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)); StringCchPrintf(szBuff, ARRAYSIZE(szBuff), 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; }
|