Skip to content

Commit eae4bdb

Browse files
authored
[SHELL32] Translate PIDLs for change notification and ParseDisplayName (reactos#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.
1 parent 3885311 commit eae4bdb

6 files changed

Lines changed: 162 additions & 19 deletions

File tree

dll/win32/shell32/changenotify.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,41 @@ CreateNotificationParamAndSend(LONG wEventId, UINT uFlags, LPCITEMIDLIST pidl1,
334334
if (hTicket == NULL)
335335
return;
336336

337-
TRACE("hTicket: %p, 0x%lx\n", hTicket, pid);
337+
// Create alias PIDLs
338+
CComHeapPtr<ITEMIDLIST> pidl1Alias, pidl2Alias;
339+
if (pidl1)
340+
SHELL32_AliasTranslatePidl(pidl1, &pidl1Alias, ALIAS_ANY);
341+
if (pidl2)
342+
SHELL32_AliasTranslatePidl(pidl2, &pidl2Alias, ALIAS_ANY);
343+
344+
HANDLE hTicket2 = NULL;
345+
if ((pidl1Alias || pidl2Alias) &&
346+
(!ILIsEqual(pidl1, pidl1Alias) || !ILIsEqual(pidl2, pidl2Alias)))
347+
{
348+
hTicket2 = CreateNotificationParam(wEventId, uFlags, pidl1Alias, pidl2Alias,
349+
pid, dwTick);
350+
if (!hTicket2)
351+
{
352+
SHFreeShared(hTicket, pid);
353+
return;
354+
}
355+
}
356+
357+
TRACE("hTicket:%p, hTicket2:%p, pid:0x%lx\n", hTicket, hTicket2, pid);
338358

339359
// send the ticket by using CN_DELIVER_NOTIFICATION
340360
if (pid != GetCurrentProcessId() ||
341361
(uFlags & (SHCNF_FLUSH | SHCNF_FLUSHNOWAIT)) == SHCNF_FLUSH)
342362
{
343363
SendMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket, pid);
364+
if (hTicket2)
365+
SendMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket2, pid);
344366
}
345367
else
346368
{
347369
SendNotifyMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket, pid);
370+
if (hTicket2)
371+
SendNotifyMessageW(hwndServer, CN_DELIVER_NOTIFICATION, (WPARAM)hTicket2, pid);
348372
}
349373
}
350374

dll/win32/shell32/folders/CDesktopFolder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,9 @@ HRESULT WINAPI CDesktopFolder::ParseDisplayName(
475475
{
476476
if (BindCtx_ContainsObject(pbc, STR_PARSE_TRANSLATE_ALIASES))
477477
{
478+
// Use "alias" PIDL if possible
478479
CComHeapPtr<ITEMIDLIST> pidlAlias;
479-
if (SUCCEEDED(Shell_TranslateIDListAlias(*ppidl, NULL, &pidlAlias, 0xFFFF)))
480+
if (SUCCEEDED(SHELL32_AliasTranslatePidl(*ppidl, &pidlAlias, ALIAS_ANY)))
480481
{
481482
ILFree(*ppidl);
482483
*ppidl = pidlAlias.Detach();

dll/win32/shell32/precomp.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,13 +244,6 @@ class CStubWindow32 : public CWindowImpl<CStubWindow32>
244244

245245
void PostCabinetMessage(UINT Msg, WPARAM wParam, LPARAM lParam);
246246

247-
HRESULT
248-
Shell_TranslateIDListAlias(
249-
_In_ LPCITEMIDLIST pidl,
250-
_In_ HANDLE hToken,
251-
_Out_ LPITEMIDLIST *ppidlAlias,
252-
_In_ DWORD dwFlags);
253-
254247
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName);
255248
DWORD BindCtx_GetMode(_In_ IBindCtx *pbc, _In_ DWORD dwDefault);
256249
BOOL SHSkipJunctionBinding(_In_ IBindCtx *pbc, _In_ CLSID *pclsid);

dll/win32/shell32/utils.cpp

Lines changed: 110 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -257,16 +257,6 @@ OpenEffectiveToken(
257257
return ret;
258258
}
259259

260-
HRESULT
261-
Shell_TranslateIDListAlias(
262-
_In_ LPCITEMIDLIST pidl,
263-
_In_ HANDLE hToken,
264-
_Out_ LPITEMIDLIST *ppidlAlias,
265-
_In_ DWORD dwFlags)
266-
{
267-
return E_FAIL; //FIXME
268-
}
269-
270260
BOOL BindCtx_ContainsObject(_In_ IBindCtx *pBindCtx, _In_ LPCWSTR pszName)
271261
{
272262
CComPtr<IUnknown> punk;
@@ -2091,3 +2081,113 @@ SHGetComputerDisplayNameW(
20912081
// Build a string like "Description (SERVERNAME)"
20922082
return SHELL_BuildDisplayMachineName(pszName, cchNameMax, pszServerName, szDesc);
20932083
}
2084+
2085+
typedef struct tagALIAS_MAPPING
2086+
{
2087+
BYTE bFlagMask; // The combination of ALIAS_USER_FOLDER and/or ALIAS_DESKTOP
2088+
BYTE bCommonDesktop;
2089+
WORD nCsidlSrc; // CSIDL_... (source)
2090+
WORD nCsidlDest; // CSIDL_... (destination)
2091+
} ALIAS_MAPPING, *PALIAS_MAPPING;
2092+
2093+
//! PIDL alias table
2094+
static const ALIAS_MAPPING g_AliasTable[] =
2095+
{
2096+
{
2097+
ALIAS_USER_FOLDER,
2098+
FALSE,
2099+
CSIDL_PERSONAL | CSIDL_FLAG_NO_ALIAS,
2100+
CSIDL_PERSONAL
2101+
},
2102+
{
2103+
ALIAS_USER_FOLDER | ALIAS_DESKTOP,
2104+
FALSE,
2105+
CSIDL_COMMON_DOCUMENTS | CSIDL_FLAG_NO_ALIAS,
2106+
CSIDL_COMMON_DOCUMENTS
2107+
},
2108+
{
2109+
ALIAS_DESKTOP,
2110+
FALSE,
2111+
CSIDL_DESKTOPDIRECTORY,
2112+
CSIDL_DESKTOP
2113+
},
2114+
{
2115+
ALIAS_DESKTOP,
2116+
TRUE,
2117+
CSIDL_COMMON_DESKTOPDIRECTORY,
2118+
CSIDL_DESKTOP
2119+
}
2120+
};
2121+
2122+
//! Translate a PIDL to an "alias" PIDL.
2123+
EXTERN_C BOOL
2124+
SHELL32_ReparentAsAliasPidl(
2125+
_In_opt_ HWND hwnd,
2126+
_In_opt_ HANDLE hToken,
2127+
_In_ LPCITEMIDLIST pidlTarget,
2128+
_Out_ LPITEMIDLIST *ppidlNew,
2129+
_In_ DWORD dwFlags)
2130+
{
2131+
if (!pidlTarget || !ppidlNew)
2132+
return FALSE;
2133+
2134+
*ppidlNew = NULL;
2135+
2136+
for (SIZE_T iEntry = 0; iEntry < _countof(g_AliasTable); ++iEntry)
2137+
{
2138+
const ALIAS_MAPPING *pEntry = &g_AliasTable[iEntry];
2139+
2140+
if (!(dwFlags & pEntry->bFlagMask))
2141+
continue;
2142+
2143+
// Get the source root PIDL
2144+
LPITEMIDLIST pidlSrcRoot = NULL;
2145+
HRESULT hr = SHGetFolderLocation(hwnd, pEntry->nCsidlSrc, hToken, 0, &pidlSrcRoot);
2146+
if (FAILED(hr))
2147+
continue;
2148+
2149+
// Check whether the input pidlTarget is under the source folder.
2150+
// If it matches, ILFindChild returns the relative PIDL in the pidlTarget.
2151+
LPCITEMIDLIST pidlRelative = ILFindChild(pidlSrcRoot, pidlTarget);
2152+
if (!pidlRelative) // Not found?
2153+
{
2154+
ILFree(pidlSrcRoot);
2155+
continue;
2156+
}
2157+
2158+
// Found. Get the destination root PIDL
2159+
LPITEMIDLIST pidlDestRoot = NULL;
2160+
hr = SHGetFolderLocation(hwnd, pEntry->nCsidlDest, hToken, 0, &pidlDestRoot);
2161+
if (SUCCEEDED(hr))
2162+
{
2163+
// Create a new PIDL by combining the destination root PIDL and the relative PIDL
2164+
*ppidlNew = ILCombine(pidlDestRoot, pidlRelative);
2165+
if (*ppidlNew)
2166+
{
2167+
// Manipulate specific flags in the PIDL if necessary
2168+
if (pEntry->bCommonDesktop && (*ppidlNew)->mkid.cb)
2169+
{
2170+
UINT cbRoot = ILGetSize(pidlDestRoot);
2171+
PBYTE pAttr = (PBYTE)(*ppidlNew) + cbRoot - sizeof(USHORT);
2172+
*pAttr |= (PT_FS | PT_FS_COMMON_FLAG);
2173+
}
2174+
}
2175+
ILFree(pidlDestRoot);
2176+
}
2177+
2178+
ILFree(pidlSrcRoot);
2179+
break; // A match was found, so exit the loop
2180+
}
2181+
2182+
return (*ppidlNew != NULL);
2183+
}
2184+
2185+
//! Translate a PIDL to an "alias" PIDL.
2186+
EXTERN_C HRESULT
2187+
SHELL32_AliasTranslatePidl(
2188+
_In_ LPCITEMIDLIST pidl,
2189+
_Out_ LPITEMIDLIST *ppidlNew,
2190+
_In_ DWORD dwFlags)
2191+
{
2192+
return SHELL32_ReparentAsAliasPidl(NULL, NULL, pidl, ppidlNew, dwFlags) ? S_OK : E_FAIL;
2193+
}

dll/win32/shell32/wine/pidl.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,11 +911,17 @@ HRESULT WINAPI SHGetRealIDL(LPSHELLFOLDER lpsf, LPCITEMIDLIST pidlSimple, LPITEM
911911
*/
912912
LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
913913
{
914+
#ifdef __REACTOS__
915+
LPITEMIDLIST pidlNew = NULL;
916+
SHELL32_AliasTranslatePidl(pidl, &pidlNew, ALIAS_ANY);
917+
return pidlNew;
918+
#else
914919
FIXME("(pidl=%p)\n",pidl);
915920

916921
pdump(pidl);
917922

918923
return 0;
924+
#endif
919925
}
920926

921927
/*************************************************************************

dll/win32/shell32/wine/shell32_main.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,25 @@ PathProcessCommandW(
101101
_In_ INT cchDest,
102102
_In_ DWORD dwFlags);
103103

104+
HRESULT
105+
SHELL32_AliasTranslatePidl(
106+
_In_ LPCITEMIDLIST pidl,
107+
_Out_ LPITEMIDLIST *ppidlNew,
108+
_In_ DWORD dwFlags);
109+
110+
BOOL
111+
SHELL32_ReparentAsAliasPidl(
112+
_In_opt_ HWND hwnd,
113+
_In_opt_ HANDLE hToken,
114+
_In_ LPCITEMIDLIST pidlTarget,
115+
_Out_ LPITEMIDLIST *ppidlNew,
116+
_In_ DWORD dwFlags);
117+
118+
// Flags for SHELL32_AliasTranslatePidl and SHELL32_ReparentAsAliasPidl
119+
#define ALIAS_USER_FOLDER 0x1
120+
#define ALIAS_DESKTOP 0x2
121+
#define ALIAS_ANY 0xFFFF
122+
104123
/****************************************************************************
105124
* Class constructors
106125
*/

0 commit comments

Comments
 (0)