Skip to content

Commit c1b8c4f

Browse files
authored
[SHELL32] Correctly implement common desktop items PIDL (reactos#7730)
The current implementation is broken, if a file/folder exists in both places, you always get the user item. CORE-19861
1 parent 151ba9e commit c1b8c4f

File tree

4 files changed

+60
-50
lines changed

4 files changed

+60
-50
lines changed

dll/win32/shell32/folders/CDesktopFolder.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,17 @@ static BOOL IsSelf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
4949

5050
static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
5151
{
52-
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID) && pidl->mkid.abID[0] == PT_GUID)
52+
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID) && pidl->mkid.abID[0] == PT_DESKTOP_REGITEM)
5353
return (const CLSID*)(&pidl->mkid.abID[2]);
5454
return NULL;
5555
}
5656

57+
static inline void MarkAsCommonItem(LPITEMIDLIST pidl)
58+
{
59+
ASSERT(_ILGetFSType(pidl) & PT_FS);
60+
((PIDLDATA*)pidl->mkid.abID)->type |= PT_FS_COMMON_FLAG;
61+
}
62+
5763
STDMETHODIMP
5864
CDesktopFolder::ShellUrlParseDisplayName(
5965
HWND hwndOwner,
@@ -201,8 +207,19 @@ class CDesktopFolderEnum :
201207

202208
/* Enumerate the items in the two fs folders */
203209
AppendItemsFromEnumerator(pDesktopEnumerator);
210+
ENUMLIST *pCommon = this->mpLast;
204211
AppendItemsFromEnumerator(pCommonDesktopEnumerator);
205-
212+
if (pCommon != this->mpLast) // Any common items added?
213+
{
214+
ENUMLIST fake;
215+
if (!pCommon) // In the unlikely case that there are no RegItems nor user items
216+
{
217+
fake.pNext = this->mpFirst;
218+
pCommon = &fake;
219+
}
220+
while ((pCommon = pCommon->pNext) != NULL)
221+
MarkAsCommonItem(pCommon->pidl);
222+
}
206223
return S_OK;
207224
}
208225

@@ -281,22 +298,20 @@ HRESULT WINAPI CDesktopFolder::FinalConstruct()
281298

282299
HRESULT CDesktopFolder::_GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf)
283300
{
284-
WCHAR szFileName[MAX_PATH];
285-
286-
if (_ILIsSpecialFolder(pidl))
301+
if (IsRegItem(pidl))
287302
return m_regFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
288-
289-
lstrcpynW(szFileName, sPathTarget, MAX_PATH - 1);
290-
PathAddBackslashW(szFileName);
291-
int cLen = wcslen(szFileName);
292-
293-
if (!_ILSimpleGetTextW(pidl, szFileName + cLen, MAX_PATH - cLen))
294-
return E_FAIL;
295-
296-
if (GetFileAttributes(szFileName) == INVALID_FILE_ATTRIBUTES)
297-
return m_SharedDesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
303+
#if DBG
304+
if (_ILIsDesktop(pidl))
305+
{
306+
FIXME("Desktop is unexpected here!\n");
307+
}
298308
else
299-
return m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
309+
{
310+
ASSERT(!_ILIsSpecialFolder(pidl));
311+
}
312+
#endif
313+
IShellFolder *pSF = IsCommonItem(pidl) ? m_SharedDesktopFSFolder : m_DesktopFSFolder;
314+
return pSF->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
300315
}
301316

302317
HRESULT CDesktopFolder::_ParseDisplayNameByParent(
@@ -502,6 +517,8 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
502517
pchEaten,
503518
ppidl,
504519
pdwAttributes);
520+
if (SUCCEEDED(hr))
521+
MarkAsCommonItem(*ppidl);
505522
}
506523

507524
if (FAILED(hr) && bCreate && m_DesktopFSFolder)
@@ -604,7 +621,10 @@ HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl
604621
if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
605622
return m_regFolder->CompareIDs(lParam, pidl1, pidl2);
606623

607-
return m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
624+
HRESULT ret = m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
625+
if (ret == 0 && ((lParam & SHCIDS_COLUMNMASK) == SHFSF_COL_NAME || (lParam & (SHCIDS_ALLFIELDS | SHCIDS_CANONICALONLY))))
626+
ret = MAKE_COMPARE_HRESULT(IsCommonItem(pidl1) - IsCommonItem(pidl2));
627+
return ret;
608628
}
609629

610630
/**************************************************************************

dll/win32/shell32/folders/CDesktopFolder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class CDesktopFolder :
7575
~CDesktopFolder();
7676
HRESULT WINAPI FinalConstruct();
7777

78+
static inline BOOL IsCommonItem(LPCITEMIDLIST pidl) { return _ILGetFSType(pidl) & PT_FS_COMMON_FLAG; }
79+
7880
// *** IShellFolder methods ***
7981
STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
8082
STDMETHOD(EnumObjects)(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override;

dll/win32/shell32/wine/pidl.c

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,9 +2293,6 @@ static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl)
22932293
/*return (LPSTR)&(pdata->u.drive.szDriveName);*/
22942294
return NULL;
22952295

2296-
case PT_FOLDER:
2297-
case PT_FOLDER1:
2298-
case PT_VALUE:
22992296
case PT_IESPECIAL1:
23002297
case PT_IESPECIAL2:
23012298
/*return (LPSTR)&(pdata->u.file.szNames);*/
@@ -2327,27 +2324,25 @@ LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
23272324
{
23282325
/* TRACE(pidl,"(pidl%p)\n", pidl);*/
23292326

2327+
PIDLTYPE type;
23302328
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
2331-
23322329
if (!pdata)
23332330
return NULL;
23342331

2332+
type = _ILGetFSType(pidl);
2333+
if (type && !(type & PT_FS_UNICODE_FLAG))
2334+
return pdata->u.file.szNames;
2335+
2336+
if (_ILIsDrive(pidl))
2337+
return pdata->u.drive.szDriveName;
2338+
23352339
switch (pdata->type)
23362340
{
23372341
case PT_GUID:
23382342
case PT_SHELLEXT:
23392343
case PT_YAGUID:
23402344
return NULL;
23412345

2342-
case PT_DRIVE:
2343-
case PT_DRIVE1:
2344-
case PT_DRIVE2:
2345-
case PT_DRIVE3:
2346-
return pdata->u.drive.szDriveName;
2347-
2348-
case PT_FOLDER:
2349-
case PT_FOLDER1:
2350-
case PT_VALUE:
23512346
case PT_IESPECIAL1:
23522347
case PT_IESPECIAL2:
23532348
return pdata->u.file.szNames;
@@ -2370,15 +2365,18 @@ static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
23702365
{
23712366
/* TRACE(pidl,"(pidl%p)\n", pidl); */
23722367

2368+
PIDLTYPE type;
23732369
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
2374-
23752370
if (!pdata)
23762371
return NULL;
23772372

2378-
switch (pdata->type)
2373+
type = pdata->type;
2374+
if (_ILGetFSType(pidl) && !(type & PT_FS_UNICODE_FLAG))
2375+
type = PT_FS;
2376+
2377+
switch (type)
23792378
{
2380-
case PT_FOLDER:
2381-
case PT_VALUE:
2379+
case PT_FS:
23822380
case PT_IESPECIAL1:
23832381
case PT_IESPECIAL2:
23842382
return pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1;
@@ -2567,24 +2565,13 @@ BOOL _ILGetExtension(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
25672565
*/
25682566
DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
25692567
{
2570-
LPPIDLDATA pData = _ILGetDataPointer(pidl);
2571-
WORD wAttrib = 0;
2572-
int i;
2573-
2574-
if (!pData)
2575-
return 0;
2576-
2577-
switch(pData->type)
2578-
{
2579-
case PT_FOLDER:
2580-
case PT_VALUE:
2581-
wAttrib = pData->u.file.uFileAttribs;
2582-
break;
2583-
}
2568+
DWORD wAttrib = 0;
2569+
if (_ILGetFSType(pidl))
2570+
wAttrib = _ILGetDataPointer(pidl)->u.file.uFileAttribs;
25842571

2585-
if(uOutSize >= 6)
2572+
if (uOutSize >= 6)
25862573
{
2587-
i=0;
2574+
UINT i = 0;
25882575
if(wAttrib & FILE_ATTRIBUTE_READONLY)
25892576
pOut[i++] = L'R';
25902577
if(wAttrib & FILE_ATTRIBUTE_HIDDEN)

dll/win32/shell32/wine/pidl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ extern "C" {
112112
#define PT_FS_FOLDER_FLAG 0x01
113113
#define PT_FS_FILE_FLAG 0x02
114114
#define PT_FS_UNICODE_FLAG 0x04
115+
#define PT_FS_COMMON_FLAG 0x08
115116
// PT_NET_REGITEM 0x4? // => SHDID_NET_OTHER
116117
#define PT_CONTROLS_OLDREGITEM 0x70
117118
#define PT_CONTROLS_NEWREGITEM 0x71

0 commit comments

Comments
 (0)