Skip to content

Commit 28399a2

Browse files
authored
[SHELL32] Use FS compatible PIDL format for Recycle Bin items (reactos#7532)
* [SHELL32] Use FS compatible PIDL format for Recycle Bin items This allows SHChangeNotify to handle these items and DefView will correctly update the recycle folder. CORE-18005 CORE-19239 CORE-13950 CORE-18435 CORE-18436 CORE-18437
1 parent a184242 commit 28399a2

27 files changed

+1141
-941
lines changed

dll/win32/shell32/CCopyAsPathMenu.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ CCopyAsPathMenu::DoCopyAsPath(IDataObject *pdto)
103103
return hr;
104104
}
105105

106+
static const CMVERBMAP g_VerbMap[] =
107+
{
108+
{ "copyaspath", IDC_COPYASPATH },
109+
{ NULL }
110+
};
111+
106112
STDMETHODIMP
107113
CCopyAsPathMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
108114
{
@@ -133,7 +139,8 @@ CCopyAsPathMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
133139
{
134140
TRACE("CCopyAsPathMenu::InvokeCommand(%p %p)\n", this, lpcmi);
135141

136-
if (IS_INTRESOURCE(lpcmi->lpVerb) && LOWORD(lpcmi->lpVerb) == IDC_COPYASPATH)
142+
int CmdId = SHELL_MapContextMenuVerbToCmdId(lpcmi, g_VerbMap);
143+
if (CmdId == IDC_COPYASPATH)
137144
return DoCopyAsPath(m_pDataObject);
138145

139146
return E_FAIL;
@@ -142,10 +149,9 @@ CCopyAsPathMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
142149
STDMETHODIMP
143150
CCopyAsPathMenu::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
144151
{
145-
FIXME("CCopyAsPathMenu::GetCommandString(%p %lu %u %p %p %u)\n", this,
152+
TRACE("CCopyAsPathMenu::GetCommandString(%p %lu %u %p %p %u)\n", this,
146153
idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
147-
148-
return E_NOTIMPL;
154+
return SHELL_GetCommandStringImpl(idCommand, uFlags, lpszName, uMaxNameLen, g_VerbMap);
149155
}
150156

151157
STDMETHODIMP

dll/win32/shell32/CDefView.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,7 @@ int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
13181318
{
13191319
for (i = 0; i < cItems; i++)
13201320
{
1321+
//FIXME: ILIsEqual needs absolute pidls!
13211322
currentpidl = _PidlByItem(i);
13221323
if (ILIsEqual(pidl, currentpidl))
13231324
return i;
@@ -2848,29 +2849,35 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &
28482849
TRACE("(%p)(%p,%p,%p)\n", this, Pidls[0], Pidls[1], lParam);
28492850

28502851
if (_DoFolderViewCB(SFVM_FSNOTIFY, (WPARAM)Pidls, lEvent) == S_FALSE)
2852+
{
2853+
SHChangeNotification_Unlock(hLock);
28512854
return FALSE;
2855+
}
28522856

28532857
// Translate child IDLs.
28542858
// SHSimpleIDListFromPathW creates fake PIDLs (lacking some attributes)
2859+
lEvent &= ~SHCNE_INTERRUPT;
28552860
HRESULT hr;
28562861
PITEMID_CHILD child0 = NULL, child1 = NULL;
28572862
CComHeapPtr<ITEMIDLIST_RELATIVE> pidl0Temp, pidl1Temp;
2858-
if (_ILIsSpecialFolder(Pidls[0]) || ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]))
2863+
if (lEvent != SHCNE_UPDATEIMAGE && lEvent < SHCNE_EXTENDED_EVENT)
28592864
{
2860-
child0 = ILFindLastID(Pidls[0]);
2861-
hr = SHGetRealIDL(m_pSFParent, child0, &pidl0Temp);
2862-
if (SUCCEEDED(hr))
2863-
child0 = pidl0Temp;
2864-
}
2865-
if (_ILIsSpecialFolder(Pidls[1]) || ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]))
2866-
{
2867-
child1 = ILFindLastID(Pidls[1]);
2868-
hr = SHGetRealIDL(m_pSFParent, child1, &pidl1Temp);
2869-
if (SUCCEEDED(hr))
2870-
child1 = pidl1Temp;
2865+
if (_ILIsSpecialFolder(Pidls[0]) || ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]))
2866+
{
2867+
child0 = ILFindLastID(Pidls[0]);
2868+
hr = SHGetRealIDL(m_pSFParent, child0, &pidl0Temp);
2869+
if (SUCCEEDED(hr))
2870+
child0 = pidl0Temp;
2871+
}
2872+
if (_ILIsSpecialFolder(Pidls[1]) || ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]))
2873+
{
2874+
child1 = ILFindLastID(Pidls[1]);
2875+
hr = SHGetRealIDL(m_pSFParent, child1, &pidl1Temp);
2876+
if (SUCCEEDED(hr))
2877+
child1 = pidl1Temp;
2878+
}
28712879
}
28722880

2873-
lEvent &= ~SHCNE_INTERRUPT;
28742881
switch (lEvent)
28752882
{
28762883
case SHCNE_MKDIR:

dll/win32/shell32/CDefaultContextMenu.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,25 @@ UINT MapVerbToDfmCmd(_In_ LPCSTR verba)
8484
return 0;
8585
}
8686

87+
static HRESULT
88+
MapVerbToCmdId(PVOID Verb, BOOL IsUnicode, IContextMenu *pCM, UINT idFirst, UINT idLast)
89+
{
90+
const UINT gcs = IsUnicode ? GCS_VERBW : GCS_VERBA;
91+
for (UINT id = idFirst; id <= idLast; ++id)
92+
{
93+
WCHAR buf[MAX_PATH];
94+
*buf = UNICODE_NULL;
95+
HRESULT hr = pCM->GetCommandString(id, gcs, NULL, (LPSTR)buf, _countof(buf));
96+
if (FAILED(hr) || !*buf)
97+
continue;
98+
else if (IsUnicode && !_wcsicmp((LPWSTR)Verb, buf))
99+
return id;
100+
else if (!IsUnicode && !lstrcmpiA((LPSTR)Verb, (LPSTR)buf))
101+
return id;
102+
}
103+
return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
104+
}
105+
87106
static inline bool IsVerbListSeparator(WCHAR Ch)
88107
{
89108
return Ch == L' ' || Ch == L','; // learn.microsoft.com/en-us/windows/win32/shell/context-menu-handlers
@@ -738,7 +757,7 @@ CDefaultContextMenu::AddStaticContextMenusToMenu(
738757
return cIds;
739758
}
740759

741-
void WINAPI _InsertMenuItemW(
760+
BOOL WINAPI _InsertMenuItemW(
742761
HMENU hMenu,
743762
UINT indexMenu,
744763
BOOL fByPosition,
@@ -764,7 +783,7 @@ void WINAPI _InsertMenuItemW(
764783
else
765784
{
766785
ERR("failed to load string %p\n", dwTypeData);
767-
return;
786+
return FALSE;
768787
}
769788
}
770789
else
@@ -774,7 +793,7 @@ void WINAPI _InsertMenuItemW(
774793

775794
mii.wID = wID;
776795
mii.fType = fType;
777-
InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
796+
return InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
778797
}
779798

780799
void
@@ -1212,6 +1231,18 @@ CDefaultContextMenu::MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode)
12121231
}
12131232
}
12141233

1234+
for (POSITION it = m_DynamicEntries.GetHeadPosition(); it != NULL;)
1235+
{
1236+
DynamicShellEntry& entry = m_DynamicEntries.GetNext(it);
1237+
if (!entry.NumIds)
1238+
continue;
1239+
HRESULT hr = ::MapVerbToCmdId(Verb, IsUnicode, entry.pCM, 0, entry.NumIds - 1);
1240+
if (SUCCEEDED(hr))
1241+
{
1242+
*idCmd = m_iIdSHEFirst + entry.iIdCmdFirst + hr;
1243+
return TRUE;
1244+
}
1245+
}
12151246
return FALSE;
12161247
}
12171248

dll/win32/shell32/CFolderItemVerbs.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,7 @@ CFolderItemVerbs::~CFolderItemVerbs()
9191

9292
HRESULT CFolderItemVerbs::Init(LPITEMIDLIST idlist)
9393
{
94-
CComPtr<IShellFolder> folder;
95-
LPCITEMIDLIST child;
96-
HRESULT hr = SHBindToParent(idlist, IID_PPV_ARG(IShellFolder, &folder), &child);
97-
if (FAILED_UNEXPECTEDLY(hr))
98-
return hr;
99-
100-
hr = folder->GetUIObjectOf(NULL, 1, &child, IID_IContextMenu, NULL, (PVOID*)&m_contextmenu);
94+
HRESULT hr = SHELL_GetUIObjectOfAbsoluteItem(NULL, idlist, IID_PPV_ARG(IContextMenu, &m_contextmenu));
10195
if (FAILED_UNEXPECTEDLY(hr))
10296
return hr;
10397

dll/win32/shell32/COpenWithMenu.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,11 @@ VOID COpenWithMenu::AddApp(PVOID pApp)
12501250
m_idCmdLast++;
12511251
}
12521252

1253+
static const CMVERBMAP g_VerbMap[] = {
1254+
{ "openas", 0 },
1255+
{ NULL }
1256+
};
1257+
12531258
HRESULT WINAPI COpenWithMenu::QueryContextMenu(
12541259
HMENU hMenu,
12551260
UINT indexMenu,
@@ -1328,14 +1333,19 @@ HRESULT WINAPI COpenWithMenu::QueryContextMenu(
13281333
HRESULT WINAPI
13291334
COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
13301335
{
1336+
const SIZE_T idChooseApp = m_idCmdLast;
13311337
HRESULT hr = E_FAIL;
13321338

13331339
TRACE("This %p idFirst %u idLast %u idCmd %u\n", this, m_idCmdFirst, m_idCmdLast, m_idCmdFirst + LOWORD(lpici->lpVerb));
13341340

1335-
if (HIWORD(lpici->lpVerb) == 0 && m_idCmdFirst + LOWORD(lpici->lpVerb) <= m_idCmdLast)
1341+
if (!IS_INTRESOURCE(lpici->lpVerb) && SHELL_MapContextMenuVerbToCmdId(lpici, g_VerbMap) == 0)
1342+
goto DoChooseApp;
1343+
1344+
if (IS_INTRESOURCE(lpici->lpVerb) && m_idCmdFirst + LOWORD(lpici->lpVerb) <= m_idCmdLast)
13361345
{
1337-
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == m_idCmdLast)
1346+
if (m_idCmdFirst + LOWORD(lpici->lpVerb) == idChooseApp)
13381347
{
1348+
DoChooseApp:
13391349
OPENASINFO info;
13401350
LPCWSTR pwszExt = PathFindExtensionW(m_wszPath);
13411351

@@ -1371,9 +1381,13 @@ HRESULT WINAPI
13711381
COpenWithMenu::GetCommandString(UINT_PTR idCmd, UINT uType,
13721382
UINT* pwReserved, LPSTR pszName, UINT cchMax )
13731383
{
1374-
FIXME("%p %lu %u %p %p %u\n", this,
1384+
TRACE("%p %lu %u %p %p %u\n", this,
13751385
idCmd, uType, pwReserved, pszName, cchMax );
13761386

1387+
const SIZE_T idChooseApp = m_idCmdLast;
1388+
if (m_idCmdFirst + idCmd == idChooseApp)
1389+
return SHELL_GetCommandStringImpl(0, uType, pszName, cchMax, g_VerbMap);
1390+
13771391
return E_NOTIMPL;
13781392
}
13791393

dll/win32/shell32/CSendToMenu.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,7 @@ HRESULT CSendToMenu::GetUIObjectFromPidl(HWND hwnd, PIDLIST_ABSOLUTE pidl,
130130
REFIID riid, LPVOID *ppvOut)
131131
{
132132
*ppvOut = NULL;
133-
134-
PCITEMID_CHILD pidlLast;
135-
CComPtr<IShellFolder> pFolder;
136-
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &pFolder), &pidlLast);
137-
if (FAILED_UNEXPECTEDLY(hr))
138-
return hr;
139-
140-
hr = pFolder->GetUIObjectOf(hwnd, 1, &pidlLast, riid, NULL, ppvOut);
133+
HRESULT hr = SHELL_GetUIObjectOfAbsoluteItem(hwnd, pidl, riid, ppvOut);
141134
if (FAILED_UNEXPECTEDLY(hr))
142135
return hr;
143136

dll/win32/shell32/CShellLink.cpp

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,18 +1729,10 @@ HRESULT STDMETHODCALLTYPE CShellLink::GetIconLocation(LPWSTR pszIconPath, INT cc
17291729
static HRESULT SHELL_PidlGetIconLocationW(PCIDLIST_ABSOLUTE pidl,
17301730
UINT uFlags, PWSTR pszIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
17311731
{
1732-
LPCITEMIDLIST pidlLast;
1733-
CComPtr<IShellFolder> psf;
1734-
1735-
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
1736-
if (FAILED_UNEXPECTEDLY(hr))
1737-
return hr;
1738-
17391732
CComPtr<IExtractIconW> pei;
1740-
hr = psf->GetUIObjectOf(0, 1, &pidlLast, IID_NULL_PPV_ARG(IExtractIconW, &pei));
1733+
HRESULT hr = SHELL_GetUIObjectOfAbsoluteItem(NULL, pidl, IID_PPV_ARG(IExtractIconW, &pei));
17411734
if (FAILED_UNEXPECTEDLY(hr))
17421735
return hr;
1743-
17441736
hr = pei->GetIconLocation(uFlags, pszIconFile, cchMax, piIndex, pwFlags);
17451737
if (FAILED_UNEXPECTEDLY(hr))
17461738
return hr;
@@ -3142,20 +3134,9 @@ HRESULT STDMETHODCALLTYPE CShellLink::DragEnter(IDataObject *pDataObject,
31423134
if (*pdwEffect == DROPEFFECT_NONE)
31433135
return S_OK;
31443136

3145-
LPCITEMIDLIST pidlLast;
3146-
CComPtr<IShellFolder> psf;
3147-
3148-
HRESULT hr = SHBindToParent(m_pPidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
3149-
3137+
HRESULT hr = SHELL_GetUIObjectOfAbsoluteItem(NULL, m_pPidl, IID_PPV_ARG(IDropTarget, &m_DropTarget));
31503138
if (SUCCEEDED(hr))
3151-
{
3152-
hr = psf->GetUIObjectOf(0, 1, &pidlLast, IID_NULL_PPV_ARG(IDropTarget, &m_DropTarget));
3153-
3154-
if (SUCCEEDED(hr))
3155-
hr = m_DropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect);
3156-
else
3157-
*pdwEffect = DROPEFFECT_NONE;
3158-
}
3139+
hr = m_DropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect);
31593140
else
31603141
*pdwEffect = DROPEFFECT_NONE;
31613142

0 commit comments

Comments
 (0)