mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 00:40:26 +08:00
[SHELL32] Translate PIDLs for change notification and ParseDisplayName (#8569)
Change notification on a folder on Desktop was failing due to mismatching PIDLs. We translate PIDLs to match the alias PIDLs. JIRA issue: CORE-19630 JIRA issue: CORE-19820 JIRA issue: CORE-16941 - Add SHELL32_ReparentAsAliasPidl and SHELL32_AliasTranslatePidl helper functions. They translate a PIDL to an "alias" PIDL. - Implement SHLogILFromFSIL function. - Use SHELL32_AliasTranslatePidl in CDesktopFolder::ParseDisplayName instread of Shell_TranslateIDListAlias. - Use SHELL32_AliasTranslatePidl in CreateNotificationParam.
This commit is contained in:
committed by
GitHub
parent
3885311c85
commit
eae4bdb95e
@@ -334,17 +334,41 @@ CreateNotificationParamAndSend(LONG wEventId, UINT uFlags, LPCITEMIDLIST pidl1,
|
||||
if (hTicket == NULL)
|
||||
return;
|
||||
|
||||
TRACE("hTicket: %p, 0x%lx\n", hTicket, pid);
|
||||
// Create alias PIDLs
|
||||
CComHeapPtr<ITEMIDLIST> pidl1Alias, pidl2Alias;
|
||||
if (pidl1)
|
||||
SHELL32_AliasTranslatePidl(pidl1, &pidl1Alias, ALIAS_ANY);
|
||||
if (pidl2)
|
||||
SHELL32_AliasTranslatePidl(pidl2, &pidl2Alias, ALIAS_ANY);
|
||||
|
||||
HANDLE hTicket2 = NULL;
|
||||
if ((pidl1Alias || pidl2Alias) &&
|
||||
(!ILIsEqual(pidl1, pidl1Alias) || !ILIsEqual(pidl2, pidl2Alias)))
|
||||
{
|
||||
hTicket2 = CreateNotificationParam(wEventId, uFlags, pidl1Alias, pidl2Alias,
|
||||
pid, dwTick);
|
||||
if (!hTicket2)
|
||||
{
|
||||
SHFreeShared(hTicket, pid);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("hTicket:%p, hTicket2:%p, pid:0x%lx\n", hTicket, hTicket2, pid);
|
||||
|
||||
// send the ticket by using CN_DELIVER_NOTIFICATION
|
||||
if (pid != GetCurrentProcessId() ||
|
||||
(uFlags & (SHCNF_FLUSH | SHCNF_FLUSHNOWAIT)) == SHCNF_FLUSH)
|
||||
{
|
||||
SendMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket, pid);
|
||||
if (hTicket2)
|
||||
SendMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket2, pid);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendNotifyMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket, pid);
|
||||
if (hTicket2)
|
||||
SendNotifyMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket2, pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -475,8 +475,9 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
|
||||
{
|
||||
if (BindCtx_ContainsObject(pbc, STR_PARSE_TRANSLATE_ALIASES))
|
||||
{
|
||||
// Use "alias" PIDL if possible
|
||||
CComHeapPtr<ITEMIDLIST> pidlAlias;
|
||||
if (SUCCEEDED(Shell_TranslateIDListAlias(*ppidl, NULL, &pidlAlias, 0xFFFF)))
|
||||
if (SUCCEEDED(SHELL32_AliasTranslatePidl(*ppidl, &pidlAlias, ALIAS_ANY)))
|
||||
{
|
||||
ILFree(*ppidl);
|
||||
*ppidl = pidlAlias.Detach();
|
||||
|
||||
@@ -244,13 +244,6 @@ public:
|
||||
|
||||
void PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
HRESULT
|
||||
Shell_TranslateIDListAlias(
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_In_ HANDLE hToken,
|
||||
_Out_ LPITEMIDLIST *ppidlAlias,
|
||||
_In_ DWORD dwFlags);
|
||||
|
||||
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName);
|
||||
DWORD BindCtx_GetMode(_In_ IBindCtx *pbc, _In_ DWORD dwDefault);
|
||||
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid);
|
||||
|
||||
@@ -257,16 +257,6 @@ OpenEffectiveToken(
|
||||
return ret;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Shell_TranslateIDListAlias(
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_In_ HANDLE hToken,
|
||||
_Out_ LPITEMIDLIST *ppidlAlias,
|
||||
_In_ DWORD dwFlags)
|
||||
{
|
||||
return E_FAIL; //FIXME
|
||||
}
|
||||
|
||||
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName)
|
||||
{
|
||||
CComPtr<IUnknown> punk;
|
||||
@@ -2091,3 +2081,113 @@ SHGetComputerDisplayNameW(
|
||||
// Build a string like "Description (SERVERNAME)"
|
||||
return SHELL_BuildDisplayMachineName(pszName, cchNameMax, pszServerName, szDesc);
|
||||
}
|
||||
|
||||
typedef struct tagALIAS_MAPPING
|
||||
{
|
||||
BYTE bFlagMask; // The combination of ALIAS_USER_FOLDER and/or ALIAS_DESKTOP
|
||||
BYTE bCommonDesktop;
|
||||
WORD nCsidlSrc; // CSIDL_... (source)
|
||||
WORD nCsidlDest; // CSIDL_... (destination)
|
||||
} ALIAS_MAPPING, *PALIAS_MAPPING;
|
||||
|
||||
//! PIDL alias table
|
||||
static const ALIAS_MAPPING g_AliasTable[] =
|
||||
{
|
||||
{
|
||||
ALIAS_USER_FOLDER,
|
||||
FALSE,
|
||||
CSIDL_PERSONAL | CSIDL_FLAG_NO_ALIAS,
|
||||
CSIDL_PERSONAL
|
||||
},
|
||||
{
|
||||
ALIAS_USER_FOLDER | ALIAS_DESKTOP,
|
||||
FALSE,
|
||||
CSIDL_COMMON_DOCUMENTS | CSIDL_FLAG_NO_ALIAS,
|
||||
CSIDL_COMMON_DOCUMENTS
|
||||
},
|
||||
{
|
||||
ALIAS_DESKTOP,
|
||||
FALSE,
|
||||
CSIDL_DESKTOPDIRECTORY,
|
||||
CSIDL_DESKTOP
|
||||
},
|
||||
{
|
||||
ALIAS_DESKTOP,
|
||||
TRUE,
|
||||
CSIDL_COMMON_DESKTOPDIRECTORY,
|
||||
CSIDL_DESKTOP
|
||||
}
|
||||
};
|
||||
|
||||
//! Translate a PIDL to an "alias" PIDL.
|
||||
EXTERN_C BOOL
|
||||
SHELL32_ReparentAsAliasPidl(
|
||||
_In_opt_ HWND hwnd,
|
||||
_In_opt_ HANDLE hToken,
|
||||
_In_ LPCITEMIDLIST pidlTarget,
|
||||
_Out_ LPITEMIDLIST *ppidlNew,
|
||||
_In_ DWORD dwFlags)
|
||||
{
|
||||
if (!pidlTarget || !ppidlNew)
|
||||
return FALSE;
|
||||
|
||||
*ppidlNew = NULL;
|
||||
|
||||
for (SIZE_T iEntry = 0; iEntry < _countof(g_AliasTable); ++iEntry)
|
||||
{
|
||||
const ALIAS_MAPPING *pEntry = &g_AliasTable[iEntry];
|
||||
|
||||
if (!(dwFlags & pEntry->bFlagMask))
|
||||
continue;
|
||||
|
||||
// Get the source root PIDL
|
||||
LPITEMIDLIST pidlSrcRoot = NULL;
|
||||
HRESULT hr = SHGetFolderLocation(hwnd, pEntry->nCsidlSrc, hToken, 0, &pidlSrcRoot);
|
||||
if (FAILED(hr))
|
||||
continue;
|
||||
|
||||
// Check whether the input pidlTarget is under the source folder.
|
||||
// If it matches, ILFindChild returns the relative PIDL in the pidlTarget.
|
||||
LPCITEMIDLIST pidlRelative = ILFindChild(pidlSrcRoot, pidlTarget);
|
||||
if (!pidlRelative) // Not found?
|
||||
{
|
||||
ILFree(pidlSrcRoot);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Found. Get the destination root PIDL
|
||||
LPITEMIDLIST pidlDestRoot = NULL;
|
||||
hr = SHGetFolderLocation(hwnd, pEntry->nCsidlDest, hToken, 0, &pidlDestRoot);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Create a new PIDL by combining the destination root PIDL and the relative PIDL
|
||||
*ppidlNew = ILCombine(pidlDestRoot, pidlRelative);
|
||||
if (*ppidlNew)
|
||||
{
|
||||
// Manipulate specific flags in the PIDL if necessary
|
||||
if (pEntry->bCommonDesktop && (*ppidlNew)->mkid.cb)
|
||||
{
|
||||
UINT cbRoot = ILGetSize(pidlDestRoot);
|
||||
PBYTE pAttr = (PBYTE)(*ppidlNew) + cbRoot - sizeof(USHORT);
|
||||
*pAttr |= (PT_FS | PT_FS_COMMON_FLAG);
|
||||
}
|
||||
}
|
||||
ILFree(pidlDestRoot);
|
||||
}
|
||||
|
||||
ILFree(pidlSrcRoot);
|
||||
break; // A match was found, so exit the loop
|
||||
}
|
||||
|
||||
return (*ppidlNew != NULL);
|
||||
}
|
||||
|
||||
//! Translate a PIDL to an "alias" PIDL.
|
||||
EXTERN_C HRESULT
|
||||
SHELL32_AliasTranslatePidl(
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_Out_ LPITEMIDLIST *ppidlNew,
|
||||
_In_ DWORD dwFlags)
|
||||
{
|
||||
return SHELL32_ReparentAsAliasPidl(NULL, NULL, pidl, ppidlNew, dwFlags) ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
@@ -911,11 +911,17 @@ HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEM
|
||||
*/
|
||||
LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
|
||||
{
|
||||
#ifdef __REACTOS__
|
||||
LPITEMIDLIST pidlNew = NULL;
|
||||
SHELL32_AliasTranslatePidl(pidl, &pidlNew, ALIAS_ANY);
|
||||
return pidlNew;
|
||||
#else
|
||||
FIXME("(pidl=%p)\n",pidl);
|
||||
|
||||
pdump(pidl);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
@@ -101,6 +101,25 @@ PathProcessCommandW(
|
||||
_In_ INT cchDest,
|
||||
_In_ DWORD dwFlags);
|
||||
|
||||
HRESULT
|
||||
SHELL32_AliasTranslatePidl(
|
||||
_In_ LPCITEMIDLIST pidl,
|
||||
_Out_ LPITEMIDLIST *ppidlNew,
|
||||
_In_ DWORD dwFlags);
|
||||
|
||||
BOOL
|
||||
SHELL32_ReparentAsAliasPidl(
|
||||
_In_opt_ HWND hwnd,
|
||||
_In_opt_ HANDLE hToken,
|
||||
_In_ LPCITEMIDLIST pidlTarget,
|
||||
_Out_ LPITEMIDLIST *ppidlNew,
|
||||
_In_ DWORD dwFlags);
|
||||
|
||||
// Flags for SHELL32_AliasTranslatePidl and SHELL32_ReparentAsAliasPidl
|
||||
#define ALIAS_USER_FOLDER 0x1
|
||||
#define ALIAS_DESKTOP 0x2
|
||||
#define ALIAS_ANY 0xFFFF
|
||||
|
||||
/****************************************************************************
|
||||
* Class constructors
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user