mirror of
https://github.com/reactos/reactos.git
synced 2025-04-18 03:34:11 +00:00
[SHELL32] Correctly implement common desktop items PIDL (#7730)
The current implementation is broken, if a file/folder exists in both places, you always get the user item. CORE-19861
This commit is contained in:
parent
151ba9ee8f
commit
c1b8c4f96f
4 changed files with 60 additions and 50 deletions
|
@ -49,11 +49,17 @@ static BOOL IsSelf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
|||
|
||||
static const CLSID* IsRegItem(PCUITEMID_CHILD pidl)
|
||||
{
|
||||
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID) && pidl->mkid.abID[0] == PT_GUID)
|
||||
if (pidl && pidl->mkid.cb == 2 + 2 + sizeof(CLSID) && pidl->mkid.abID[0] == PT_DESKTOP_REGITEM)
|
||||
return (const CLSID*)(&pidl->mkid.abID[2]);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void MarkAsCommonItem(LPITEMIDLIST pidl)
|
||||
{
|
||||
ASSERT(_ILGetFSType(pidl) & PT_FS);
|
||||
((PIDLDATA*)pidl->mkid.abID)->type |= PT_FS_COMMON_FLAG;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
CDesktopFolder::ShellUrlParseDisplayName(
|
||||
HWND hwndOwner,
|
||||
|
@ -201,8 +207,19 @@ class CDesktopFolderEnum :
|
|||
|
||||
/* Enumerate the items in the two fs folders */
|
||||
AppendItemsFromEnumerator(pDesktopEnumerator);
|
||||
ENUMLIST *pCommon = this->mpLast;
|
||||
AppendItemsFromEnumerator(pCommonDesktopEnumerator);
|
||||
|
||||
if (pCommon != this->mpLast) // Any common items added?
|
||||
{
|
||||
ENUMLIST fake;
|
||||
if (!pCommon) // In the unlikely case that there are no RegItems nor user items
|
||||
{
|
||||
fake.pNext = this->mpFirst;
|
||||
pCommon = &fake;
|
||||
}
|
||||
while ((pCommon = pCommon->pNext) != NULL)
|
||||
MarkAsCommonItem(pCommon->pidl);
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -281,22 +298,20 @@ HRESULT WINAPI CDesktopFolder::FinalConstruct()
|
|||
|
||||
HRESULT CDesktopFolder::_GetSFFromPidl(LPCITEMIDLIST pidl, IShellFolder2** psf)
|
||||
{
|
||||
WCHAR szFileName[MAX_PATH];
|
||||
|
||||
if (_ILIsSpecialFolder(pidl))
|
||||
if (IsRegItem(pidl))
|
||||
return m_regFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
|
||||
|
||||
lstrcpynW(szFileName, sPathTarget, MAX_PATH - 1);
|
||||
PathAddBackslashW(szFileName);
|
||||
int cLen = wcslen(szFileName);
|
||||
|
||||
if (!_ILSimpleGetTextW(pidl, szFileName + cLen, MAX_PATH - cLen))
|
||||
return E_FAIL;
|
||||
|
||||
if (GetFileAttributes(szFileName) == INVALID_FILE_ATTRIBUTES)
|
||||
return m_SharedDesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
|
||||
#if DBG
|
||||
if (_ILIsDesktop(pidl))
|
||||
{
|
||||
FIXME("Desktop is unexpected here!\n");
|
||||
}
|
||||
else
|
||||
return m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
|
||||
{
|
||||
ASSERT(!_ILIsSpecialFolder(pidl));
|
||||
}
|
||||
#endif
|
||||
IShellFolder *pSF = IsCommonItem(pidl) ? m_SharedDesktopFSFolder : m_DesktopFSFolder;
|
||||
return pSF->QueryInterface(IID_PPV_ARG(IShellFolder2, psf));
|
||||
}
|
||||
|
||||
HRESULT CDesktopFolder::_ParseDisplayNameByParent(
|
||||
|
@ -502,6 +517,8 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
|
|||
pchEaten,
|
||||
ppidl,
|
||||
pdwAttributes);
|
||||
if (SUCCEEDED(hr))
|
||||
MarkAsCommonItem(*ppidl);
|
||||
}
|
||||
|
||||
if (FAILED(hr) && bCreate && m_DesktopFSFolder)
|
||||
|
@ -604,7 +621,10 @@ HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl
|
|||
if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
|
||||
return m_regFolder->CompareIDs(lParam, pidl1, pidl2);
|
||||
|
||||
return m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
|
||||
HRESULT ret = m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
|
||||
if (ret == 0 && ((lParam & SHCIDS_COLUMNMASK) == SHFSF_COL_NAME || (lParam & (SHCIDS_ALLFIELDS | SHCIDS_CANONICALONLY))))
|
||||
ret = MAKE_COMPARE_HRESULT(IsCommonItem(pidl1) - IsCommonItem(pidl2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
|
@ -75,6 +75,8 @@ class CDesktopFolder :
|
|||
~CDesktopFolder();
|
||||
HRESULT WINAPI FinalConstruct();
|
||||
|
||||
static inline BOOL IsCommonItem(LPCITEMIDLIST pidl) { return _ILGetFSType(pidl) & PT_FS_COMMON_FLAG; }
|
||||
|
||||
// *** IShellFolder methods ***
|
||||
STDMETHOD(ParseDisplayName)(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, DWORD *pchEaten, PIDLIST_RELATIVE *ppidl, DWORD *pdwAttributes) override;
|
||||
STDMETHOD(EnumObjects)(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList) override;
|
||||
|
|
|
@ -2293,9 +2293,6 @@ static LPWSTR _ILGetTextPointerW(LPCITEMIDLIST pidl)
|
|||
/*return (LPSTR)&(pdata->u.drive.szDriveName);*/
|
||||
return NULL;
|
||||
|
||||
case PT_FOLDER:
|
||||
case PT_FOLDER1:
|
||||
case PT_VALUE:
|
||||
case PT_IESPECIAL1:
|
||||
case PT_IESPECIAL2:
|
||||
/*return (LPSTR)&(pdata->u.file.szNames);*/
|
||||
|
@ -2327,11 +2324,18 @@ LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
|
|||
{
|
||||
/* TRACE(pidl,"(pidl%p)\n", pidl);*/
|
||||
|
||||
PIDLTYPE type;
|
||||
LPPIDLDATA pdata = _ILGetDataPointer(pidl);
|
||||
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
type = _ILGetFSType(pidl);
|
||||
if (type && !(type & PT_FS_UNICODE_FLAG))
|
||||
return pdata->u.file.szNames;
|
||||
|
||||
if (_ILIsDrive(pidl))
|
||||
return pdata->u.drive.szDriveName;
|
||||
|
||||
switch (pdata->type)
|
||||
{
|
||||
case PT_GUID:
|
||||
|
@ -2339,15 +2343,6 @@ LPSTR _ILGetTextPointer(LPCITEMIDLIST pidl)
|
|||
case PT_YAGUID:
|
||||
return NULL;
|
||||
|
||||
case PT_DRIVE:
|
||||
case PT_DRIVE1:
|
||||
case PT_DRIVE2:
|
||||
case PT_DRIVE3:
|
||||
return pdata->u.drive.szDriveName;
|
||||
|
||||
case PT_FOLDER:
|
||||
case PT_FOLDER1:
|
||||
case PT_VALUE:
|
||||
case PT_IESPECIAL1:
|
||||
case PT_IESPECIAL2:
|
||||
return pdata->u.file.szNames;
|
||||
|
@ -2370,15 +2365,18 @@ static LPSTR _ILGetSTextPointer(LPCITEMIDLIST pidl)
|
|||
{
|
||||
/* TRACE(pidl,"(pidl%p)\n", pidl); */
|
||||
|
||||
PIDLTYPE type;
|
||||
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
|
||||
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
switch (pdata->type)
|
||||
type = pdata->type;
|
||||
if (_ILGetFSType(pidl) && !(type & PT_FS_UNICODE_FLAG))
|
||||
type = PT_FS;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PT_FOLDER:
|
||||
case PT_VALUE:
|
||||
case PT_FS:
|
||||
case PT_IESPECIAL1:
|
||||
case PT_IESPECIAL2:
|
||||
return pdata->u.file.szNames + strlen (pdata->u.file.szNames) + 1;
|
||||
|
@ -2567,24 +2565,13 @@ BOOL _ILGetExtension(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
|
|||
*/
|
||||
DWORD _ILGetFileAttributes(LPCITEMIDLIST pidl, LPWSTR pOut, UINT uOutSize)
|
||||
{
|
||||
LPPIDLDATA pData = _ILGetDataPointer(pidl);
|
||||
WORD wAttrib = 0;
|
||||
int i;
|
||||
DWORD wAttrib = 0;
|
||||
if (_ILGetFSType(pidl))
|
||||
wAttrib = _ILGetDataPointer(pidl)->u.file.uFileAttribs;
|
||||
|
||||
if (!pData)
|
||||
return 0;
|
||||
|
||||
switch(pData->type)
|
||||
if (uOutSize >= 6)
|
||||
{
|
||||
case PT_FOLDER:
|
||||
case PT_VALUE:
|
||||
wAttrib = pData->u.file.uFileAttribs;
|
||||
break;
|
||||
}
|
||||
|
||||
if(uOutSize >= 6)
|
||||
{
|
||||
i=0;
|
||||
UINT i = 0;
|
||||
if(wAttrib & FILE_ATTRIBUTE_READONLY)
|
||||
pOut[i++] = L'R';
|
||||
if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
|
||||
|
|
|
@ -112,6 +112,7 @@ extern "C" {
|
|||
#define PT_FS_FOLDER_FLAG 0x01
|
||||
#define PT_FS_FILE_FLAG 0x02
|
||||
#define PT_FS_UNICODE_FLAG 0x04
|
||||
#define PT_FS_COMMON_FLAG 0x08
|
||||
// PT_NET_REGITEM 0x4? // => SHDID_NET_OTHER
|
||||
#define PT_CONTROLS_OLDREGITEM 0x70
|
||||
#define PT_CONTROLS_NEWREGITEM 0x71
|
||||
|
|
Loading…
Reference in a new issue