[SHELL32]

- Correctly handle recursive change notifications in CDefView
- Remove desktop folder hack from SHChangeNotify and move it to CDefView until we have ITranslateShellChangeNotify
Fixes phantom files/folders on desktop. Based on a patch by Huw Campbell.
CORE-8844

svn path=/trunk/; revision=66901
This commit is contained in:
Thomas Faber 2015-03-26 12:05:54 +00:00
parent 8114dd9fe0
commit 508a03733a
2 changed files with 54 additions and 31 deletions

View file

@ -93,6 +93,7 @@ class CDefView :
UINT m_uState;
UINT m_cidl;
PCUITEMID_CHILD_ARRAY m_apidl;
PIDLIST_ABSOLUTE m_pidlParent;
LISTVIEW_SORT_INFO m_sortInfo;
ULONG m_hNotify; /* change notification handle */
HACCEL m_hAccel;
@ -354,6 +355,7 @@ CDefView::CDefView() :
m_uState(0),
m_cidl(0),
m_apidl(NULL),
m_pidlParent(NULL),
m_hNotify(0),
m_hAccel(NULL),
m_dwAspects(0),
@ -943,6 +945,7 @@ LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
DestroyMenu(m_hMenu);
RevokeDragDrop(m_hWnd);
SHChangeNotifyDeregister(m_hNotify);
SHFree(m_pidlParent);
bHandled = FALSE;
return 0;
}
@ -1000,12 +1003,10 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
if (ppf2)
{
PIDLIST_ABSOLUTE pidlParent;
ppf2->GetCurFolder(&pidlParent);
ppf2->GetCurFolder(&m_pidlParent);
ntreg.fRecursive = TRUE;
ntreg.pidl = pidlParent;
m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
SHFree(pidlParent);
ntreg.pidl = m_pidlParent;
m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
}
m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
@ -1848,12 +1849,48 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
return 0;
}
/*
* This is just a quick hack to make the desktop work correctly.
* ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
* a folder should know if it should update upon a change notification.
* It is exported by merged folders at a minimum.
*/
static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
{
if (!pidl1 || !pidl2)
return FALSE;
if (ILIsParent(pidl1, pidl2, TRUE))
return TRUE;
if (_ILIsDesktop(pidl1))
{
PIDLIST_ABSOLUTE deskpidl;
SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
if (ILIsParent(deskpidl, pidl2, TRUE))
{
ILFree(deskpidl);
return TRUE;
}
ILFree(deskpidl);
SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
if (ILIsParent(deskpidl, pidl2, TRUE))
{
ILFree(deskpidl);
return TRUE;
}
ILFree(deskpidl);
}
return FALSE;
}
/**********************************************************
* ShellView_OnChange()
*/
LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
@ -1861,20 +1898,28 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &
{
case SHCNE_MKDIR:
case SHCNE_CREATE:
if (bParent0)
LV_AddItem(ILFindLastID(Pidls[0]));
break;
case SHCNE_RMDIR:
case SHCNE_DELETE:
if (bParent0)
LV_DeleteItem(ILFindLastID(Pidls[0]));
break;
case SHCNE_RENAMEFOLDER:
case SHCNE_RENAMEITEM:
if (bParent0 && bParent1)
LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
else if (bParent0)
LV_DeleteItem(ILFindLastID(Pidls[0]));
else if (bParent1)
LV_AddItem(ILFindLastID(Pidls[0]));
break;
case SHCNE_UPDATEITEM:
if (bParent0)
LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
break;

View file

@ -255,28 +255,6 @@ static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL su
return TRUE;
if( sub && ILIsParent( watched, changed, FALSE ) )
return TRUE;
#ifdef __REACTOS__
if (sub && _ILIsDesktop(watched)) {
LPITEMIDLIST deskpidl;
WCHAR wszPath[MAX_PATH];
SHGetSpecialFolderPathW(0, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE);
deskpidl = SHSimpleIDListFromPathW(wszPath);
if (ILIsParent(deskpidl, changed, TRUE))
{
ILFree(deskpidl);
return TRUE;
}
ILFree(deskpidl);
SHGetSpecialFolderPathW(0, wszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
deskpidl = SHSimpleIDListFromPathW(wszPath);
if (ILIsParent(deskpidl, changed, TRUE))
{
ILFree(deskpidl);
return TRUE;
}
ILFree(deskpidl);
}
#endif
return FALSE;
}