698 lines
20 KiB
C++
698 lines
20 KiB
C++
#include "priv.h"
|
|
#include "browmenu.h"
|
|
#include "resource.h"
|
|
#include "uemapp.h"
|
|
#include "mluisupp.h"
|
|
#include <varutil.h>
|
|
#include "legacy.h"
|
|
|
|
#define UEM_NEWITEMCOUNT 2
|
|
// Exported by shdocvw
|
|
STDAPI GetLinkInfo(IShellFolder* psf, LPCITEMIDLIST pidlItem, BOOL* pfAvailable, BOOL* pfSticky);
|
|
|
|
#define REG_STR_MAIN TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main")
|
|
|
|
BOOL AreIntelliMenusEnbaled()
|
|
{
|
|
// This is only garenteed to work on version 5 shell because the session
|
|
// incrementer is located in the tray
|
|
if (GetUIVersion() >= 5)
|
|
{
|
|
DWORD dwRest = SHRestricted(REST_INTELLIMENUS);
|
|
if (dwRest != RESTOPT_INTELLIMENUS_USER)
|
|
return (dwRest == RESTOPT_INTELLIMENUS_ENABLED);
|
|
|
|
return SHRegGetBoolUSValue(REG_STR_MAIN, TEXT("FavIntelliMenus"),
|
|
FALSE, FALSE); // Don't ignore HKCU, Disable Menus by default
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
CFavoritesCallback::CFavoritesCallback() : _cRef(1)
|
|
{
|
|
_fOffline = BOOLIFY(SHIsGlobalOffline());
|
|
}
|
|
|
|
CFavoritesCallback::~CFavoritesCallback()
|
|
{
|
|
ASSERT(_punkSite == NULL);
|
|
|
|
ASSERT(_psmFavCache == NULL);
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: IUnknown::QueryInterface method
|
|
|
|
*/
|
|
STDMETHODIMP CFavoritesCallback::QueryInterface (REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
static const QITAB qit[] =
|
|
{
|
|
QITABENT(CFavoritesCallback, IShellMenuCallback),
|
|
QITABENT(CFavoritesCallback, IObjectWithSite),
|
|
{ 0 },
|
|
};
|
|
|
|
return QISearch(this, qit, riid, ppvObj);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: IUnknown::AddRef method
|
|
|
|
*/
|
|
STDMETHODIMP_(ULONG) CFavoritesCallback::AddRef ()
|
|
{
|
|
return ++_cRef;
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: IUnknown::Release method
|
|
|
|
*/
|
|
STDMETHODIMP_(ULONG) CFavoritesCallback::Release()
|
|
{
|
|
ASSERT(_cRef > 0);
|
|
_cRef--;
|
|
|
|
if( _cRef > 0)
|
|
return _cRef;
|
|
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: IObjectWithSite::SetSite method
|
|
|
|
*/
|
|
STDMETHODIMP CFavoritesCallback::SetSite(IUnknown* punk)
|
|
{
|
|
ATOMICRELEASE(_punkSite);
|
|
_punkSite = punk;
|
|
if (_punkSite)
|
|
{
|
|
_punkSite->AddRef();
|
|
}
|
|
else if (_psmFavCache)
|
|
{
|
|
// Since the top level menu is being destroyed, they are removing
|
|
// our site. We should cleanup.
|
|
DWORD dwFlags;
|
|
UINT uId;
|
|
UINT uIdA;
|
|
|
|
_psmFavCache->GetMenuInfo(NULL, &uId, &uIdA, &dwFlags);
|
|
|
|
// Tell menuband we're no longer caching it. We need to do this so ClowseDW
|
|
// cleans up the menus.
|
|
dwFlags &= ~SMINIT_CACHED;
|
|
_psmFavCache->Initialize(NULL, uId, uIdA, dwFlags);
|
|
|
|
IDeskBand* pdesk;
|
|
if (SUCCEEDED(_psmFavCache->QueryInterface(IID_IDeskBand, (LPVOID*)&pdesk)))
|
|
{
|
|
pdesk->CloseDW(0);
|
|
pdesk->Release();
|
|
}
|
|
|
|
ATOMICRELEASE(_psmFavCache);
|
|
}
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: IShellMenuCallback::CallbackSM method
|
|
|
|
*/
|
|
STDMETHODIMP CFavoritesCallback::CallbackSM(LPSMDATA psmd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
switch (uMsg)
|
|
{
|
|
case SMC_INITMENU:
|
|
hres = _Init(psmd->hmenu, psmd->uIdParent, psmd->punk);
|
|
break;
|
|
|
|
case SMC_EXITMENU:
|
|
hres = _Exit();
|
|
break;
|
|
|
|
case SMC_CREATE:
|
|
if (psmd->uIdParent == FCIDM_MENU_FAVORITES)
|
|
_fExpandoMenus = AreIntelliMenusEnbaled();
|
|
break;
|
|
|
|
case SMC_DEMOTE:
|
|
hres = _Demote(psmd);
|
|
break;
|
|
|
|
case SMC_PROMOTE:
|
|
hres = _Promote(psmd);
|
|
break;
|
|
|
|
case SMC_NEWITEM:
|
|
hres = _HandleNew(psmd);
|
|
break;
|
|
|
|
case SMC_SFEXEC:
|
|
hres = SHNavigateToFavorite(psmd->psf, psmd->pidlItem, _punkSite, SBSP_DEFBROWSER | SBSP_DEFMODE);
|
|
break;
|
|
|
|
case SMC_GETINFO:
|
|
hres = _GetHmenuInfo(psmd->hmenu, psmd->uId, (SMINFO*)lParam);
|
|
break;
|
|
|
|
case SMC_SFSELECTITEM:
|
|
hres = _SelectItem(psmd->pidlFolder, psmd->pidlItem);
|
|
break;
|
|
|
|
case SMC_GETOBJECT:
|
|
hres = _GetObject(psmd, (GUID)*((GUID*)wParam), (void**)lParam);
|
|
break;
|
|
|
|
case SMC_DEFAULTICON:
|
|
hres = _GetDefaultIcon((LPTSTR)wParam, (int*)lParam);
|
|
break;
|
|
|
|
case SMC_GETSFINFO:
|
|
hres = _GetSFInfo(psmd, (SMINFO*)lParam);
|
|
break;
|
|
|
|
case SMC_SHCHANGENOTIFY:
|
|
{
|
|
PSMCSHCHANGENOTIFYSTRUCT pshf = (PSMCSHCHANGENOTIFYSTRUCT)lParam;
|
|
hres = _ProcessChangeNotify(psmd, pshf->lEvent, pshf->pidl1, pshf->pidl2);
|
|
}
|
|
break;
|
|
|
|
case SMC_REFRESH:
|
|
_fExpandoMenus = AreIntelliMenusEnbaled();
|
|
break;
|
|
|
|
case SMC_CHEVRONGETTIP:
|
|
hres = _GetTip((LPTSTR)wParam, (LPTSTR)lParam);
|
|
break;
|
|
|
|
case SMC_CHEVRONEXPAND:
|
|
{
|
|
if (_fShowingTip)
|
|
{
|
|
LPTSTR pszExpanded = TEXT("NO");
|
|
|
|
SHRegSetUSValue(REG_STR_MAIN, TEXT("FavChevron"),
|
|
REG_SZ, pszExpanded, lstrlen(pszExpanded) * sizeof(TCHAR), SHREGSET_FORCE_HKCU);
|
|
}
|
|
|
|
_fShowingTip = FALSE;
|
|
|
|
hres = S_OK;
|
|
}
|
|
break;
|
|
|
|
case SMC_DISPLAYCHEVRONTIP:
|
|
|
|
// Should we show the tip?
|
|
_fShowingTip = SHRegGetBoolUSValue(REG_STR_MAIN, TEXT("FavChevron"), FALSE, TRUE); // Default to YES.
|
|
|
|
if (_fShowingTip)
|
|
{
|
|
hres = S_OK;
|
|
}
|
|
break;
|
|
|
|
case SMC_SFDDRESTRICTED:
|
|
hres = _AllowDrop((IDataObject*)wParam, (HWND)lParam) ? S_FALSE : S_OK;
|
|
break;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT CFavoritesCallback::_Init(HMENU hMenu, UINT uIdParent, IUnknown* punk)
|
|
{
|
|
#ifdef DEBUG
|
|
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
|
{
|
|
UEMFireEvent(&UEMIID_BROWSER, UEME_CTLSESSION, UEMF_XEVENT, TRUE, -1);
|
|
}
|
|
#endif
|
|
|
|
HRESULT hres = S_FALSE;
|
|
|
|
if (SUCCEEDED(IUnknown_QueryServiceExec(_punkSite, SID_STopLevelBrowser, &CGID_MenuBand, MBANDCID_ENTERMENU, 0, NULL, NULL)))
|
|
hres = S_OK;
|
|
|
|
// Only do this for the favorites dropdown. This was causing
|
|
// the chevron menu to be invalidated before it was created. This caused some
|
|
// resize problems because the metrics were unavailable.
|
|
if (uIdParent == FCIDM_MENU_FAVORITES)
|
|
{
|
|
// If we switched between online and offline, we need to re-init the menu
|
|
BOOL fOffline = BOOLIFY(SHIsGlobalOffline());
|
|
if (fOffline ^ _fOffline || _fRefresh)
|
|
{
|
|
_fOffline = fOffline;
|
|
IShellMenu* psm;
|
|
if (SUCCEEDED(punk->QueryInterface(IID_IShellMenu, (void**)&psm)))
|
|
{
|
|
psm->InvalidateItem(NULL, SMINV_REFRESH);
|
|
psm->Release();
|
|
}
|
|
_fRefresh = FALSE;
|
|
}
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
|
|
HRESULT CFavoritesCallback::_Exit()
|
|
{
|
|
HRESULT hr = IUnknown_QueryServiceExec(_punkSite, SID_STopLevelBrowser, &CGID_MenuBand, MBANDCID_EXITMENU, 0, NULL, NULL);
|
|
|
|
return SUCCEEDED(hr) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_GetHmenuInfo(HMENU hMenu, UINT uId, SMINFO* psminfo)
|
|
{
|
|
if (uId == FCIDM_MENU_FAVORITES)
|
|
{
|
|
if (psminfo->dwMask & SMIM_FLAGS)
|
|
psminfo->dwFlags |= SMIF_DROPCASCADE;
|
|
}
|
|
else
|
|
{
|
|
if (psminfo->dwMask & SMIM_FLAGS)
|
|
psminfo->dwFlags |= SMIF_TRACKPOPUP;
|
|
}
|
|
|
|
// No item has icons
|
|
if (psminfo->dwMask & SMIM_ICON)
|
|
psminfo->iIcon = -1;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CFavoritesCallback::_GetSFInfo(SMDATA* psmd, SMINFO* psminfo)
|
|
{
|
|
BOOL fAvailable;
|
|
|
|
//
|
|
// If we are offline and the item is not available, we set the
|
|
// SMIF_ALTSTATE so that the menu item is greyed
|
|
//
|
|
if (psminfo->dwMask & SMIM_FLAGS)
|
|
{
|
|
if (_fOffline &&
|
|
SUCCEEDED(GetLinkInfo(psmd->psf, psmd->pidlItem, &fAvailable, NULL)) &&
|
|
fAvailable == FALSE)
|
|
{
|
|
// Not available, so grey the item
|
|
psminfo->dwFlags |= SMIF_ALTSTATE;
|
|
}
|
|
|
|
if (_fExpandoMenus)
|
|
psminfo->dwFlags |= _GetDemote(psmd);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_SelectItem(LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidl)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
LPITEMIDLIST pidlFull = ILCombine(pidlFolder, pidl);
|
|
if (pidlFull)
|
|
{
|
|
VARIANTARG vargIn;
|
|
hres = InitVariantFromIDList(&vargIn, pidlFull);
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
hres = IUnknown_QueryServiceExec(_punkSite, SID_SMenuBandHandler,
|
|
&CGID_MenuBandHandler, MBHANDCID_PIDLSELECT, 0, &vargIn, NULL);
|
|
VariantClearLazy(&vargIn);
|
|
}
|
|
ILFree(pidlFull);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
void CFavoritesCallback::_RefreshItem(HMENU hmenu, int idCmd, IShellMenu* psm)
|
|
{
|
|
SMDATA smd;
|
|
smd.dwMask = SMDM_HMENU;
|
|
smd.hmenu = hmenu;
|
|
smd.uId = idCmd;
|
|
|
|
psm->InvalidateItem(&smd, SMINV_ID | SMINV_REFRESH);
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_GetObject(LPSMDATA psmd, REFIID riid, void** ppvOut)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
*ppvOut = NULL;
|
|
|
|
if (IsEqualIID(IID_IShellMenu, riid))
|
|
{
|
|
if (psmd->uId == FCIDM_MENU_FAVORITES)
|
|
{
|
|
// Do we have a cached Favorites menu?
|
|
if (_psmFavCache)
|
|
{
|
|
// Yes we do, return it
|
|
_psmFavCache->AddRef();
|
|
*ppvOut = (LPVOID)_psmFavCache;
|
|
hres = S_OK;
|
|
}
|
|
else
|
|
{
|
|
// Nope; We need to create one...
|
|
hres = CoCreateInstance(CLSID_MenuBand, NULL, CLSCTX_INPROC,
|
|
IID_IShellMenu, (void**)&_psmFavCache);
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
HMENU hmenu = NULL;
|
|
HWND hwnd;
|
|
|
|
_psmFavCache->Initialize(this, FCIDM_MENU_FAVORITES, ANCESTORDEFAULT,
|
|
SMINIT_CACHED | SMINIT_VERTICAL);
|
|
|
|
// We need to grab the Top HMENU portion of the Favorites menu from the current band
|
|
IShellMenu* psm;
|
|
if (SUCCEEDED(psmd->punk->QueryInterface(IID_IShellMenu, (LPVOID*)&psm)))
|
|
{
|
|
psm->GetMenu(&hmenu, &hwnd, NULL);
|
|
|
|
hmenu = GetSubMenu(hmenu, GetMenuPosFromID(hmenu, FCIDM_MENU_FAVORITES));
|
|
|
|
// Delete the placeholder item (there to keep the separator from getting
|
|
// lost during shbrowse menu merging, which deletes trailing separators).
|
|
int iPos = GetMenuPosFromID(hmenu, FCIDM_FAVPLACEHOLDER);
|
|
if (iPos >= 0)
|
|
DeleteMenu(hmenu, iPos, MF_BYPOSITION);
|
|
|
|
psm->Release();
|
|
}
|
|
|
|
if (hmenu)
|
|
{
|
|
hres = _psmFavCache->SetMenu(hmenu, hwnd, SMSET_TOP | SMSET_DONTOWN);
|
|
}
|
|
|
|
LPITEMIDLIST pidlFav;
|
|
if (SUCCEEDED(hres) &&
|
|
SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFav)))
|
|
{
|
|
IShellFolder* psf;
|
|
if (SUCCEEDED(IEBindToObject(pidlFav, &psf)))
|
|
{
|
|
HKEY hMenuKey;
|
|
DWORD dwDisp;
|
|
|
|
RegCreateKeyEx(HKEY_CURRENT_USER, STRREG_FAVORITES, NULL, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
|
|
NULL, &hMenuKey, &dwDisp);
|
|
|
|
hres = _psmFavCache->SetShellFolder(psf, pidlFav, hMenuKey,
|
|
SMSET_BOTTOM | SMSET_USEBKICONEXTRACTION | SMSET_HASEXPANDABLEFOLDERS);
|
|
psf->Release();
|
|
}
|
|
ILFree(pidlFav);
|
|
}
|
|
|
|
if (SUCCEEDED(hres))
|
|
{
|
|
_psmFavCache->AddRef(); // We're caching this.
|
|
*ppvOut = _psmFavCache;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (IsEqualIID(IID_IShellMenuCallback, riid))
|
|
{
|
|
IShellMenuCallback* psmcb = (IShellMenuCallback*) new CFavoritesCallback;
|
|
|
|
if (psmcb)
|
|
{
|
|
*ppvOut = (LPVOID)psmcb;
|
|
hres = S_OK;
|
|
}
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
// Short circuit the looking up of a default icon. We're going to assume that all of them
|
|
// are URLs, even folders, for the sake of speed. It gives the user feedback directly, then
|
|
// we asyncronously render the real icons.
|
|
HRESULT CFavoritesCallback::_GetDefaultIcon(TCHAR* psz, int* piIndex)
|
|
{
|
|
HRESULT hr;
|
|
DWORD cchSize = MAX_PATH;
|
|
|
|
if (SUCCEEDED(hr = AssocQueryString(0, ASSOCSTR_DEFAULTICON, TEXT("InternetShortcut"), NULL, psz, &cchSize)))
|
|
*piIndex = PathParseIconLocation(psz);
|
|
|
|
return hr;
|
|
}
|
|
|
|
DWORD CFavoritesCallback::_GetDemote(SMDATA* psmd)
|
|
{
|
|
UEMINFO uei;
|
|
DWORD dwFlags = 0;
|
|
if (_fExpandoMenus)
|
|
{
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT;
|
|
if (SUCCEEDED(UEMQueryEvent(&UEMIID_BROWSER, UEME_RUNPIDL, (WPARAM)psmd->psf, (LPARAM)psmd->pidlItem, &uei)))
|
|
{
|
|
if (uei.cHit == 0)
|
|
{
|
|
dwFlags |= SMIF_DEMOTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwFlags;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_Demote(LPSMDATA psmd)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
|
|
if (_fExpandoMenus)
|
|
{
|
|
UEMINFO uei;
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT;
|
|
uei.cHit = 0;
|
|
hres = UEMSetEvent(&UEMIID_BROWSER, UEME_RUNPIDL, (WPARAM)psmd->psf, (LPARAM)psmd->pidlItem, &uei);
|
|
}
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_Promote(LPSMDATA psmd)
|
|
{
|
|
if (_fExpandoMenus)
|
|
{
|
|
UEMFireEvent(&UEMIID_BROWSER, UEME_RUNPIDL, UEMF_XEVENT, (WPARAM)psmd->psf, (LPARAM)psmd->pidlItem);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_HandleNew(LPSMDATA psmd)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
if (_fExpandoMenus)
|
|
{
|
|
UEMINFO uei;
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT;
|
|
uei.cHit = UEM_NEWITEMCOUNT;
|
|
hres = UEMSetEvent(&UEMIID_BROWSER, UEME_RUNPIDL, (WPARAM)psmd->psf, (LPARAM)psmd->pidlItem, &uei);
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_GetTip(LPTSTR pstrTitle, LPTSTR pstrTip)
|
|
{
|
|
MLLoadString(IDS_CHEVRONTIPTITLE, pstrTitle, MAX_PATH);
|
|
MLLoadString(IDS_CHEVRONTIP, pstrTip, MAX_PATH);
|
|
|
|
// Why would this fail?
|
|
if (EVAL(pstrTitle[0] != TEXT('\0') && pstrTip[0] != TEXT('\0')))
|
|
return S_OK;
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
// There is a duplicate of this helper in shell32\unicpp\startmnu.cpp
|
|
// When modifying this, rev that one as well.
|
|
void UEMRenamePidl(const GUID *pguidGrp1, IShellFolder* psf1, LPCITEMIDLIST pidl1,
|
|
const GUID *pguidGrp2, IShellFolder* psf2, LPCITEMIDLIST pidl2)
|
|
{
|
|
UEMINFO uei;
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT | UEIM_FILETIME;
|
|
if (SUCCEEDED(UEMQueryEvent(pguidGrp1,
|
|
UEME_RUNPIDL, (WPARAM)psf1,
|
|
(LPARAM)pidl1, &uei)) &&
|
|
uei.cHit > 0)
|
|
{
|
|
UEMSetEvent(pguidGrp2,
|
|
UEME_RUNPIDL, (WPARAM)psf2, (LPARAM)pidl2, &uei);
|
|
|
|
uei.cHit = 0;
|
|
UEMSetEvent(pguidGrp1,
|
|
UEME_RUNPIDL, (WPARAM)psf1, (LPARAM)pidl1, &uei);
|
|
}
|
|
}
|
|
|
|
// There is a duplicate of this helper in shell32\unicpp\startmnu.cpp
|
|
// When modifying this, rev that one as well.
|
|
void UEMDeletePidl(const GUID *pguidGrp, IShellFolder* psf, LPCITEMIDLIST pidl)
|
|
{
|
|
UEMINFO uei;
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT;
|
|
uei.cHit = 0;
|
|
UEMSetEvent(pguidGrp, UEME_RUNPIDL, (WPARAM)psf, (LPARAM)pidl, &uei);
|
|
}
|
|
|
|
HRESULT CFavoritesCallback::_ProcessChangeNotify(SMDATA* psmd, LONG lEvent,
|
|
LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
|
|
{
|
|
switch (lEvent)
|
|
{
|
|
case SHCNE_RENAMEFOLDER:
|
|
case SHCNE_RENAMEITEM:
|
|
{
|
|
LPITEMIDLIST pidlFavorites;
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidlFavorites)))
|
|
{
|
|
if (ILIsParent(pidlFavorites, pidl1, FALSE))
|
|
{
|
|
IShellFolder* psfFrom;
|
|
LPCITEMIDLIST pidlFrom;
|
|
if (SUCCEEDED(IEBindToParentFolder(pidl1, &psfFrom, &pidlFrom)))
|
|
{
|
|
if (ILIsParent(pidlFavorites, pidl2, FALSE))
|
|
{
|
|
IShellFolder* psfTo;
|
|
LPCITEMIDLIST pidlTo;
|
|
|
|
if (SUCCEEDED(IEBindToParentFolder(pidl2, &psfTo, &pidlTo)))
|
|
{
|
|
// Then we need to rename it
|
|
UEMRenamePidl(&UEMIID_BROWSER, psfFrom, pidlFrom,
|
|
&UEMIID_BROWSER, psfTo, pidlTo);
|
|
psfTo->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Otherwise, we delete it.
|
|
UEMDeletePidl(&UEMIID_BROWSER, psfFrom, pidlFrom);
|
|
}
|
|
|
|
psfFrom->Release();
|
|
}
|
|
}
|
|
|
|
ILFree(pidlFavorites);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SHCNE_DELETE:
|
|
case SHCNE_RMDIR:
|
|
{
|
|
IShellFolder* psf;
|
|
LPCITEMIDLIST pidl;
|
|
|
|
if (SUCCEEDED(IEBindToParentFolder(pidl1, &psf, &pidl)))
|
|
{
|
|
UEMDeletePidl(&UEMIID_BROWSER, psf, pidl);
|
|
psf->Release();
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case SHCNE_CREATE:
|
|
case SHCNE_MKDIR:
|
|
{
|
|
IShellFolder* psf;
|
|
LPCITEMIDLIST pidl;
|
|
|
|
if (SUCCEEDED(IEBindToParentFolder(pidl1, &psf, &pidl)))
|
|
{
|
|
UEMINFO uei;
|
|
uei.cbSize = SIZEOF(uei);
|
|
uei.dwMask = UEIM_HIT;
|
|
uei.cHit = UEM_NEWITEMCOUNT;
|
|
UEMSetEvent(&UEMIID_BROWSER,
|
|
UEME_RUNPIDL, (WPARAM)psf, (LPARAM)pidl, &uei);
|
|
}
|
|
|
|
}
|
|
break;
|
|
case SHCNE_EXTENDED_EVENT:
|
|
{
|
|
// We get this event when we are offline and the cache was changed.
|
|
// We need to refresh the favorites menu when we next show it so the
|
|
// correct items are greyed.
|
|
|
|
SHChangeDWORDAsIDList UNALIGNED * pdwidl = (SHChangeDWORDAsIDList UNALIGNED *)pidl1;
|
|
|
|
int iEvent = pdwidl->dwItem1;
|
|
|
|
if (iEvent == SHCNEE_WININETCHANGED &&
|
|
(pdwidl->dwItem2 & (CACHE_NOTIFY_ADD_URL |
|
|
CACHE_NOTIFY_DELETE_URL |
|
|
CACHE_NOTIFY_DELETE_ALL |
|
|
CACHE_NOTIFY_URL_SET_STICKY |
|
|
CACHE_NOTIFY_URL_UNSET_STICKY)))
|
|
{
|
|
_fRefresh = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
//
|
|
// _Disallow drop returns S_OK if the drop shold not be allowed. S_FALSE if
|
|
// the drop should be allowed.
|
|
//
|
|
BOOL CFavoritesCallback::_AllowDrop(IDataObject* pIDataObject, HWND hwnd)
|
|
{
|
|
ASSERT(NULL == hwnd || IsWindow(hwnd));
|
|
|
|
BOOL fRet = True; // Allow drop.
|
|
|
|
if (hwnd && pIDataObject)
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
|
|
if (SUCCEEDED(SHPidlFromDataObject(pIDataObject, &pidl, NULL, 0)))
|
|
{
|
|
fRet = IEIsLinkSafe(hwnd, pidl, ILS_ADDTOFAV);
|
|
ILFree(pidl);
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|